llvm.org GIT mirror llvm / 97c5e76
Revert r310919 - [globalisel][tablegen] Support zero-instruction emission. As expected, this failed on the windows bots but the instrumentation showed something interesting. The ADD8ri and INC8r rules are never directly compared on the windows machines. That implies that the issue lies in transitivity of the Compare predicate. I believe I've already verified that but maybe I missed something. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310922 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Sanders 2 years ago
4 changed file(s) with 66 addition(s) and 175 deletion(s). Raw diff Collapse all Expand all
11621162
11631163
11641164 case TargetOpcode::G_INTTOPTR:
1165 // The importer is currently unable to import pointer types since they
1166 // didn't exist in SelectionDAG.
1165 case TargetOpcode::G_BITCAST:
11671166 return selectCopy(I, TII, MRI, TRI, RBI);
1168
1169 case TargetOpcode::G_BITCAST:
1170 // Imported SelectionDAG rules can handle every bitcast except those that
1171 // bitcast from a type to the same type. Ideally, these shouldn't occur
1172 // but we might not run an optimizer that deletes them.
1173 if (MRI.getType(I.getOperand(0).getReg()) ==
1174 MRI.getType(I.getOperand(1).getReg()))
1175 return selectCopy(I, TII, MRI, TRI, RBI);
1176 return false;
11771167
11781168 case TargetOpcode::G_FPEXT: {
11791169 if (MRI.getType(I.getOperand(0).getReg()) != LLT::scalar(64)) {
1010 define void @bitcast_s64_fpr() { ret void }
1111 define void @bitcast_s64_gpr_fpr() { ret void }
1212 define void @bitcast_s64_fpr_gpr() { ret void }
13 define void @bitcast_s64_v2f32_fpr() { ret void }
14 define void @bitcast_s64_v8i8_fpr() { ret void }
1513 ...
1614
1715 ---
211209 %1(s64) = G_BITCAST %0
212210 %x0 = COPY %1(s64)
213211 ...
214
215 ---
216 # CHECK-LABEL: name: bitcast_s64_v2f32_fpr
217 name: bitcast_s64_v2f32_fpr
218 legalized: true
219 regBankSelected: true
220
221 # CHECK: registers:
222 # CHECK-NEXT: - { id: 0, class: fpr64, preferred-register: '' }
223 # CHECK-NEXT: - { id: 1, class: fpr64, preferred-register: '' }
224 registers:
225 - { id: 0, class: fpr }
226 - { id: 1, class: fpr }
227
228 # CHECK: body:
229 # CHECK: %0 = COPY %d0
230 # CHECK: %1 = COPY %0
231 body: |
232 bb.0:
233 liveins: %d0
234
235 %0(s64) = COPY %d0
236 %1(<2 x s32>) = G_BITCAST %0
237 %x0 = COPY %1(<2 x s32>)
238 ...
239
240 ---
241 # CHECK-LABEL: name: bitcast_s64_v8i8_fpr
242 name: bitcast_s64_v8i8_fpr
243 legalized: true
244 regBankSelected: true
245
246 # CHECK: registers:
247 # CHECK-NEXT: - { id: 0, class: fpr64, preferred-register: '' }
248 # CHECK-NEXT: - { id: 1, class: fpr64, preferred-register: '' }
249 registers:
250 - { id: 0, class: fpr }
251 - { id: 1, class: fpr }
252
253 # CHECK: body:
254 # CHECK: %0 = COPY %d0
255 # CHECK: %1 = COPY %0
256 body: |
257 bb.0:
258 liveins: %d0
259
260 %0(s64) = COPY %d0
261 %1(<8 x s8>) = G_BITCAST %0
262 %x0 = COPY %1(<8 x s8>)
263 ...
8181 // CHECK-NEXT: Features[Feature_HasCBit] = 1;
8282 // CHECK-NEXT: return Features;
8383 // CHECK-NEXT: }
84
85 // CHECK-LABEL: enum {
86 // CHECK-NEXT: GILLT_s32,
87 // CHECK-NEXT: }
88 // CHECK-NEXT: const static LLT TypeObjects[] = {
89 // CHECK-NEXT: LLT::scalar(32),
90 // CHECK-NEXT: };
9184
9285 // CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I) const {
9386 // CHECK-NEXT: MachineFunction &MF = *I.getParent()->getParent();
109109 const LLT &get() const { return Ty; }
110110
111111 /// This ordering is used for std::unique() and std::sort(). There's no
112 /// particular logic behind the order but either A < B or B < A must be
113 /// true if A != B.
112 /// particular logic behind the order.
114113 bool operator<(const LLTCodeGen &Other) const {
115 if (Ty.isValid() != Other.Ty.isValid())
116 return Ty.isValid() < Other.Ty.isValid();
117114 if (!Ty.isValid())
115 return Other.Ty.isValid();
116 if (Ty.isScalar()) {
117 if (!Other.Ty.isValid())
118 return false;
119 if (Other.Ty.isScalar())
120 return Ty.getSizeInBits() < Other.Ty.getSizeInBits();
118121 return false;
119
120 if (Ty.isVector() != Other.Ty.isVector())
121 return Ty.isVector() < Other.Ty.isVector();
122 if (Ty.isScalar() != Other.Ty.isScalar())
123 return Ty.isScalar() < Other.Ty.isScalar();
124 if (Ty.isPointer() != Other.Ty.isPointer())
125 return Ty.isPointer() < Other.Ty.isPointer();
126
127 if (Ty.isPointer() && Ty.getAddressSpace() != Other.Ty.getAddressSpace())
128 return Ty.getAddressSpace() < Other.Ty.getAddressSpace();
129
130 if (Ty.isVector() && Ty.getNumElements() != Other.Ty.getNumElements())
131 return Ty.getNumElements() < Other.Ty.getNumElements();
132
133 return Ty.getSizeInBits() < Other.Ty.getSizeInBits();
122 }
123 if (Ty.isVector()) {
124 if (!Other.Ty.isValid() || Other.Ty.isScalar())
125 return false;
126 if (Other.Ty.isVector()) {
127 if (Ty.getNumElements() < Other.Ty.getNumElements())
128 return true;
129 if (Ty.getNumElements() > Other.Ty.getNumElements())
130 return false;
131 return Ty.getSizeInBits() < Other.Ty.getSizeInBits();
132 }
133 return false;
134 }
135 llvm_unreachable("Unhandled LLT");
134136 }
135137 };
136138
179181 static Error isTrivialOperatorNode(const TreePatternNode *N) {
180182 std::string Explanation = "";
181183 std::string Separator = "";
184 if (N->isLeaf()) {
185 if (isa(N->getLeafValue()))
186 return Error::success();
187
188 Explanation = "Is a leaf";
189 Separator = ", ";
190 }
191
182192 if (N->hasAnyPredicate()) {
183193 Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")";
184194 Separator = ", ";
189199 Separator = ", ";
190200 }
191201
192 if (!N->hasAnyPredicate() && !N->getTransformFn())
202 if (!N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn())
193203 return Error::success();
194204
195205 return failedImport(Explanation);
447457
448458 /// A list of actions that need to be taken when all predicates in this rule
449459 /// have succeeded.
450 public:
451460 std::vector> Actions;
452 protected:
453461
454462 typedef std::map
455463 DefinedInsnVariablesMap;
625633 LLTCodeGen Ty;
626634
627635 public:
628 static std::set KnownTypes;
629
630636 LLTOperandMatcher(const LLTCodeGen &Ty)
631 : OperandPredicateMatcher(OPM_LLT), Ty(Ty) {
632 KnownTypes.insert(Ty);
633 }
637 : OperandPredicateMatcher(OPM_LLT), Ty(Ty) {}
634638
635639 static bool classof(const OperandPredicateMatcher *P) {
636640 return P->getKind() == OPM_LLT;
645649 << MatchTable::LineBreak;
646650 }
647651 };
648
649 std::set LLTOperandMatcher::KnownTypes;
650652
651653 /// Generates code to check that an operand is a particular target constant.
652654 class ComplexPatternOperandMatcher : public OperandPredicateMatcher {
14331435 class BuildMIAction : public MatchAction {
14341436 private:
14351437 unsigned InsnID;
1436 public:
14371438 const CodeGenInstruction *I;
1438 private:
14391439 const InstructionMatcher &Matched;
14401440 std::vector> OperandRenderers;
14411441
22862286 return failedImport("Src pattern root isn't a trivial operator (" +
22872287 toString(std::move(Err)) + ")");
22882288
2289 if (Dst->isLeaf())
2290 return failedImport("Dst pattern root isn't a known leaf");
2291
2292 // Start with the defined operands (i.e., the results of the root operator).
2293 Record *DstOp = Dst->getOperator();
2294 if (!DstOp->isSubClassOf("Instruction"))
2295 return failedImport("Pattern operator isn't an instruction");
2296
2297 auto &DstI = Target.getInstruction(DstOp);
2298 if (DstI.Operands.NumDefs != Src->getExtTypes().size())
2299 return failedImport("Src pattern results and dst MI defs are different (" +
2300 to_string(Src->getExtTypes().size()) + " def(s) vs " +
2301 to_string(DstI.Operands.NumDefs) + " def(s))");
2302
22892303 InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src->getName());
22902304 unsigned TempOpIdx = 0;
22912305 auto InsnMatcherOrError =
22932307 if (auto Error = InsnMatcherOrError.takeError())
22942308 return std::move(Error);
22952309 InstructionMatcher &InsnMatcher = InsnMatcherOrError.get();
2296
2297 if (Dst->isLeaf()) {
2298 Record *RCDef = getInitValueAsRegClass(Dst->getLeafValue());
2299
2300 const CodeGenRegisterClass &RC = Target.getRegisterClass(RCDef);
2301 if (RCDef) {
2302 // We need to replace the def and all its uses with the specified
2303 // operand. However, we must also insert COPY's wherever needed.
2304 // For now, emit a copy and let the register allocator clean up.
2305 auto &DstI = Target.getInstruction(RK.getDef("COPY"));
2306 const auto &DstIOperand = DstI.Operands[0];
2307
2308 OperandMatcher &OM0 = InsnMatcher.getOperand(0);
2309 OM0.setSymbolicName(DstIOperand.Name);
2310 OM0.addPredicate(RC);
2311
2312 auto &DstMIBuilder = M.addAction(0, &DstI, InsnMatcher);
2313 DstMIBuilder.addRenderer(0, InsnMatcher, DstIOperand.Name);
2314 DstMIBuilder.addRenderer(0, InsnMatcher, Dst->getName());
2315 M.addAction(0, 0, RC);
2316
2317 // We're done with this pattern! It's eligible for GISel emission; return
2318 // it.
2319 ++NumPatternImported;
2320 return std::move(M);
2321 }
2322
2323 return failedImport("Dst pattern root isn't a known leaf");
2324 }
2325
2326 // Start with the defined operands (i.e., the results of the root operator).
2327 Record *DstOp = Dst->getOperator();
2328 if (!DstOp->isSubClassOf("Instruction"))
2329 return failedImport("Pattern operator isn't an instruction");
2330
2331 auto &DstI = Target.getInstruction(DstOp);
2332 if (DstI.Operands.NumDefs != Src->getExtTypes().size())
2333 return failedImport("Src pattern results and dst MI defs are different (" +
2334 to_string(Src->getExtTypes().size()) + " def(s) vs " +
2335 to_string(DstI.Operands.NumDefs) + " def(s))");
23362310
23372311 // The root of the match also has constraints on the register bank so that it
23382312 // matches the result instruction.
24812455 Rules.push_back(std::move(MatcherOrErr.get()));
24822456 }
24832457
2484 const auto &IsRuleEmittingOpcode = [](const RuleMatcher &A, StringRef I) -> bool {
2485 const BuildMIAction &BMI = (const BuildMIAction &)*A.Actions[1];
2486 if (BMI.I->TheDef->getName() == I)
2487 return true;
2488 return false;
2489 };
2490
2491 std::stable_sort(Rules.begin(), Rules.end(), [&](const RuleMatcher &A,
2492 const RuleMatcher &B) {
2493 bool EmitResult = false;
2494 bool AIsADD8ri = false;
2495 if (IsRuleEmittingOpcode(A, "ADD8ri") && IsRuleEmittingOpcode(B, "INC8r")) {
2496 EmitResult = true;
2497 AIsADD8ri = true;
2498 }
2499 if (IsRuleEmittingOpcode(B, "ADD8ri") && IsRuleEmittingOpcode(A, "INC8r"))
2500 EmitResult = true;
2501
2502 if (EmitResult)
2503 errs() << "A=" << (AIsADD8ri ? "ADD8ri" : "INC8r") << ", B=" << (!AIsADD8ri ? "ADD8ri" : "INC8r") << "\n";
2504 if (A.isHigherPriorityThan(B)) {
2505 if (EmitResult)
2506 errs() << "A higher priority than B\n";
2507 assert(!B.isHigherPriorityThan(A) && "Cannot be more important "
2508 "and less important at "
2509 "the same time");
2510 return true;
2511 } else if (EmitResult)
2512 errs() << "A lower priority than B\n";
2513 return false;
2514 });
2458 std::stable_sort(Rules.begin(), Rules.end(),
2459 [&](const RuleMatcher &A, const RuleMatcher &B) {
2460 if (A.isHigherPriorityThan(B)) {
2461 assert(!B.isHigherPriorityThan(A) && "Cannot be more important "
2462 "and less important at "
2463 "the same time");
2464 return true;
2465 }
2466 return false;
2467 });
25152468
25162469 std::vector ComplexPredicates =
25172470 RK.getAllDerivedDefinitions("GIComplexOperandMatcher");
25812534
25822535 // Emit a table containing the LLT objects needed by the matcher and an enum
25832536 // for the matcher to reference them with.
2584 std::vector TypeObjects;
2585 for (const auto &Ty : LLTOperandMatcher::KnownTypes)
2586 TypeObjects.push_back(Ty);
2537 std::vector TypeObjects = {
2538 LLT::scalar(8), LLT::scalar(16), LLT::scalar(32),
2539 LLT::scalar(64), LLT::scalar(80), LLT::vector(8, 1),
2540 LLT::vector(16, 1), LLT::vector(32, 1), LLT::vector(64, 1),
2541 LLT::vector(8, 8), LLT::vector(16, 8), LLT::vector(32, 8),
2542 LLT::vector(64, 8), LLT::vector(4, 16), LLT::vector(8, 16),
2543 LLT::vector(16, 16), LLT::vector(32, 16), LLT::vector(2, 32),
2544 LLT::vector(4, 32), LLT::vector(8, 32), LLT::vector(16, 32),
2545 LLT::vector(2, 64), LLT::vector(4, 64), LLT::vector(8, 64),
2546 };
25872547 std::sort(TypeObjects.begin(), TypeObjects.end());
25882548 OS << "enum {\n";
25892549 for (const auto &TypeObject : TypeObjects) {