llvm.org GIT mirror llvm / ca71b34
[ARM][GISel] PR35965 Constrain RegClasses of nested instructions built from Dst Pattern Summary: Apparently, we missed on constraining register classes of VReg-operands of all the instructions built from a destination pattern but the root (top-level) one. The issue exposed itself while selecting G_FPTOSI for armv7: the corresponding pattern generates VTOSIZS wrapped into COPY_TO_REGCLASS, so top-level COPY_TO_REGCLASS gets properly constrained, while nested VTOSIZS (or rather its destination virtual register to be exact) does not. Fixing this by issuing GIR_ConstrainSelectedInstOperands for every nested GIR_BuildMI. https://bugs.llvm.org/show_bug.cgi?id=35965 rdar://problem/36886530 Patch by Roman Tereshin Reviewers: dsanders, qcolombet, rovka, bogner, aditya_nandakumar, volkan Reviewed By: dsanders, qcolombet, rovka Subscribers: aemerson, javed.absar, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D42565 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@323692 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Sanders 2 years ago
5 changed file(s) with 63 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
5252 "PhysReg not implemented");
5353
5454 const TargetRegisterClass *RegClass = TII.getRegClass(II, OpIdx, &TRI, MF);
55 // Some of the target independent instructions, like COPY, may not impose any
56 // register class constraints on some of their operands:
57 if (!RegClass) {
58 assert(!isTargetSpecificOpcode(II.getOpcode()) &&
59 "Only target independent instructions are allowed to have operands "
60 "with no register class constraints");
61 // FIXME: Just bailing out like this here could be not enough, unless we
62 // expect the users of this function to do the right thing for PHIs and
63 // COPY:
64 // v1 = COPY v0
65 // v2 = COPY v1
66 // v1 here may end up not being constrained at all. Please notice that to
67 // reproduce the issue we likely need a destination pattern of a selection
68 // rule producing such extra copies, not just an input GMIR with them as
69 // every existing target using selectImpl handles copies before calling it
70 // and they never reach this function.
71 return Reg;
72 }
5573 return constrainRegToClass(MRI, TII, RBI, InsertPt, Reg, *RegClass);
5674 }
5775
5977 const TargetInstrInfo &TII,
6078 const TargetRegisterInfo &TRI,
6179 const RegisterBankInfo &RBI) {
80 assert(!isPreISelGenericOpcode(I.getOpcode()) &&
81 "A selected instruction is expected");
6282 MachineBasicBlock &MBB = *I.getParent();
6383 MachineFunction &MF = *MBB.getParent();
6484 MachineRegisterInfo &MRI = MF.getRegInfo();
132132
133133 setAction({G_PTRTOINT, s32}, Legal);
134134 setAction({G_PTRTOINT, 1, p0}, Legal);
135
136 setAction({G_FPTOSI, s32}, Legal);
137 setAction({G_FPTOSI, 1, s32}, Legal);
135138
136139 for (unsigned Op : {G_ASHR, G_LSHR, G_SHL})
137140 setAction({Op, s32}, Legal);
0 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
1 # RUN: llc -mtriple armv7-gnueabihf -run-pass instruction-select \
2 # RUN: -verify-machineinstrs -o - %s | FileCheck %s
3 ---
4 # Test that we constrain register classes of temporary virtual registers
5 # defined by nested instructions built from a Dst Pattern
6 #
7 # G_FPTOSI selects to a (COPY_TO_REGCLASS (VTOSIZS SPR:$a), GPR), where
8 # COPY_TO_REGCLASS doesn't constrain its source register class. It exposes the
9 # bug as we create a tmp reg for VTOSIZS' result and don't constrain its
10 # register class as COPY_TO_REGCLASS' source (which is fine) nor as VTOSIZS'
11 # destination (which is not).
12 #
13 # https://bugs.llvm.org/show_bug.cgi?id=35965
14 name: test_fptosi
15 legalized: true
16 regBankSelected: true
17 body: |
18 bb.1:
19 ; CHECK-LABEL: name: test_fptosi
20 ; CHECK: [[COPY:%[0-9]+]]:spr = COPY %s0
21 ; CHECK: [[VTOSIZS:%[0-9]+]]:spr = VTOSIZS [[COPY]], 14, %noreg
22 ; CHECK: [[COPY1:%[0-9]+]]:gpr = COPY [[VTOSIZS]]
23 ; CHECK: %r0 = COPY [[COPY1]]
24 ; CHECK: MOVPCLR 14, %noreg, implicit %r0
25 %0:fprb(s32) = COPY %s0
26 %1:gprb(s32) = G_FPTOSI %0(s32)
27 %r0 = COPY %1(s32)
28 MOVPCLR 14, %noreg, implicit %r0
29 ...
307307 // CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/1, /*RendererID*/1,
308308 // CHECK-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/1, /*RendererID*/2, /*SubOperand*/0, // src5a
309309 // CHECK-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/1, /*RendererID*/2, /*SubOperand*/1, // src5b
310 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/1,
310311 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN3,
311312 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
312313 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
609609 /// Generates code to check that a match rule matches.
610610 class RuleMatcher : public Matcher {
611611 public:
612 using ActionVec = std::vector>;
613 using action_iterator = ActionVec::iterator;
612 using ActionList = std::list>;
613 using action_iterator = ActionList::iterator;
614614
615615 protected:
616616 /// A list of matchers that all need to succeed for the current rule to match.
621621
622622 /// A list of actions that need to be taken when all predicates in this rule
623623 /// have succeeded.
624 ActionVec Actions;
624 ActionList Actions;
625625
626626 using DefinedInsnVariablesMap =
627627 std::map;
21242124 BuildMIAction(unsigned InsnID, const CodeGenInstruction *I)
21252125 : InsnID(InsnID), I(I), Matched(nullptr) {}
21262126
2127 unsigned getInsnID() const { return InsnID; }
21272128 const CodeGenInstruction *getCGI() const { return I; }
21282129
21292130 void chooseInsnToMutate(RuleMatcher &Rule) {
31983199
31993200 Expected
32003201 GlobalISelEmitter::createAndImportSubInstructionRenderer(
3201 action_iterator InsertPt, RuleMatcher &M, const TreePatternNode *Dst,
3202 const action_iterator InsertPt, RuleMatcher &M, const TreePatternNode *Dst,
32023203 unsigned TempRegID) {
32033204 auto InsertPtOrError = createInstructionRenderer(InsertPt, M, Dst);
32043205
32063207
32073208 if (auto Error = InsertPtOrError.takeError())
32083209 return std::move(Error);
3209 InsertPt = InsertPtOrError.get();
32103210
32113211 BuildMIAction &DstMIBuilder =
32123212 *static_cast(InsertPtOrError.get()->get());
32143214 // Assign the result to TempReg.
32153215 DstMIBuilder.addRenderer(TempRegID, true);
32163216
3217 InsertPtOrError = importExplicitUseRenderers(InsertPt, M, DstMIBuilder, Dst);
3217 InsertPtOrError =
3218 importExplicitUseRenderers(InsertPtOrError.get(), M, DstMIBuilder, Dst);
32183219 if (auto Error = InsertPtOrError.takeError())
32193220 return std::move(Error);
32203221
3222 M.insertAction(InsertPt,
3223 DstMIBuilder.getInsnID());
32213224 return InsertPtOrError.get();
32223225 }
32233226