llvm.org GIT mirror llvm / 395b777
[ARM GlobalISel] Fix assertion in RegBankSelect We get an assertion in RegBankSelect for code along the lines of my_32_bit_int = my_64_bit_int, which tends to translate into a 64-bit load, followed by a G_TRUNC, followed by a 32-bit store. This appears in a couple of places in the test-suite. At the moment, the legalizer doesn't distinguish between integer and floating point scalars, so a 64-bit load will be marked as legal for targets with VFP, and so will the rest of the sequence, leading to a slightly bizarre G_TRUNC reaching RegBankSelect. Since the current support for 64-bit integers is rather immature, this patch works around the issue by explicitly handling this case in RegBankSelect and InstructionSelect. In the future, we may want to revisit this decision and make sure 64-bit integer loads are narrowed before reaching RegBankSelect. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@321165 91177308-0d34-0410-b5e6-96231b3b80d8 Diana Picus 2 years ago
4 changed file(s) with 98 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
740740 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
741741 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
742742
743 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
744 // This should only happen in the obscure case where we have put a 64-bit
745 // integer into a D register. Get it out of there and keep only the
746 // interesting part.
747 assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
748 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
749 "Unsupported combination of register banks");
750 assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
751 assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
752
753 unsigned IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
754 auto InsertBefore = std::next(I.getIterator());
755 auto MovI =
756 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
757 .addDef(DstReg)
758 .addDef(IgnoredBits)
759 .addUse(SrcReg)
760 .add(predOps(ARMCC::AL));
761 if (!constrainSelectedInstRegOperands(*MovI, TII, TRI, RBI))
762 return false;
763
764 MIB->eraseFromParent();
765 return true;
766 }
767
743768 if (SrcRegBank.getID() != DstRegBank.getID()) {
744769 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
745770 return false;
225225 case G_SEXT:
226226 case G_ZEXT:
227227 case G_ANYEXT:
228 case G_TRUNC:
229228 case G_GEP:
230229 // FIXME: We're abusing the fact that everything lives in a GPR for now; in
231230 // the real world we would use different mappings.
232231 OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
233232 break;
233 case G_TRUNC: {
234 // In some cases we may end up with a G_TRUNC from a 64-bit value to a
235 // 32-bit value. This isn't a real floating point trunc (that would be a
236 // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
237 // because the legalizer doesn't distinguish between integer and floating
238 // point values so it may leave some 64-bit integers un-narrowed. Until we
239 // have a more principled solution that doesn't let such things sneak all
240 // the way to this point, just map the source to a DPR and the destination
241 // to a GPR.
242 LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
243 OperandsMapping =
244 LargeTy.getSizeInBits() <= 32
245 ? &ARM::ValueMappings[ARM::GPR3OpsIdx]
246 : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
247 &ARM::ValueMappings[ARM::DPR3OpsIdx]});
248 break;
249 }
234250 case G_LOAD:
235251 case G_STORE: {
236252 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
55 define void @test_trunc_and_zext_s16() { ret void }
66 define void @test_trunc_and_anyext_s8() { ret void }
77 define void @test_trunc_and_anyext_s16() { ret void }
8 define void @test_trunc_s64() #0 { ret void }
89
910 define void @test_add_s32() { ret void }
1011 define void @test_add_fold_imm_s32() { ret void }
238239
239240 BX_RET 14, %noreg, implicit %r0
240241 ; CHECK: BX_RET 14, %noreg, implicit %r0
242 ...
243 ---
244 name: test_trunc_s64
245 # CHECK-LABEL: name: test_trunc_s64
246 legalized: true
247 regBankSelected: true
248 selected: false
249 # CHECK: selected: true
250 registers:
251 - { id: 0, class: fprb }
252 - { id: 1, class: gprb }
253 - { id: 2, class: gprb }
254 body: |
255 bb.0:
256 liveins: %r0, %d0
257
258 %0(s64) = COPY %d0
259 ; CHECK: [[VREG:%[0-9]+]]:dpr = COPY %d0
260
261 %2(p0) = COPY %r0
262 ; CHECK: [[PTR:%[0-9]+]]:gpr = COPY %r0
263
264 %1(s32) = G_TRUNC %0(s64)
265 ; CHECK: [[VREGTRUNC:%[0-9]+]]:gpr, [[UNINTERESTING:%[0-9]+]]:gpr = VMOVRRD [[VREG]]
266
267 G_STORE %1(s32), %2 :: (store 4)
268 ; CHECK: STRi12 [[VREGTRUNC]], [[PTR]], 0, 14, %noreg
269
270 BX_RET 14, %noreg
271 ; CHECK: BX_RET 14, %noreg
241272 ...
242273 ---
243274 name: test_add_s32
3030 define void @test_anyext_s16_32() { ret void }
3131
3232 define void @test_trunc_s32_16() { ret void }
33 define void @test_trunc_s64_32() #0 { ret void }
3334
3435 define void @test_icmp_eq_s32() { ret void }
3536 define void @test_fcmp_one_s32() #0 { ret void }
583584 BX_RET 14, %noreg
584585 ...
585586 ---
587 name: test_trunc_s64_32
588 # CHECK-LABEL: name: test_trunc_s64_32
589 legalized: true
590 regBankSelected: false
591 selected: false
592 # CHECK: registers:
593 # CHECK: - { id: 0, class: fprb, preferred-register: '' }
594 # CHECK: - { id: 1, class: gprb, preferred-register: '' }
595 # CHECK: - { id: 2, class: gprb, preferred-register: '' }
596 registers:
597 - { id: 0, class: _ }
598 - { id: 1, class: _ }
599 - { id: 2, class: _ }
600 body: |
601 bb.0:
602 liveins: %r0, %d0
603
604 %0(s64) = COPY %d0
605 %2(p0) = COPY %r0
606 %1(s32) = G_TRUNC %0(s64)
607 G_STORE %1(s32), %2 :: (store 4)
608 BX_RET 14, %noreg
609 ...
610 ---
586611 name: test_icmp_eq_s32
587612 # CHECK-LABEL: name: test_icmp_eq_s32
588613 legalized: true