1 //===- GlobalCombinerEmitter.cpp - Generate a combiner --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file Generate a combiner implementation for GlobalISel from a declarative 10 /// syntax 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ADT/SmallSet.h" 15 #include "llvm/ADT/Statistic.h" 16 #include "llvm/ADT/StringSet.h" 17 #include "llvm/Support/CommandLine.h" 18 #include "llvm/Support/Debug.h" 19 #include "llvm/Support/ScopedPrinter.h" 20 #include "llvm/Support/Timer.h" 21 #include "llvm/TableGen/Error.h" 22 #include "llvm/TableGen/StringMatcher.h" 23 #include "llvm/TableGen/TableGenBackend.h" 24 #include "CodeGenTarget.h" 25 #include "GlobalISel/CodeExpander.h" 26 #include "GlobalISel/CodeExpansions.h" 27 #include "GlobalISel/GIMatchDag.h" 28 #include "GlobalISel/GIMatchTree.h" 29 #include <cstdint> 30 31 using namespace llvm; 32 33 #define DEBUG_TYPE "gicombiner-emitter" 34 35 // FIXME: Use ALWAYS_ENABLED_STATISTIC once it's available. 36 unsigned NumPatternTotal = 0; 37 STATISTIC(NumPatternTotalStatistic, "Total number of patterns"); 38 39 cl::OptionCategory 40 GICombinerEmitterCat("Options for -gen-global-isel-combiner"); 41 static cl::list<std::string> 42 SelectedCombiners("combiners", cl::desc("Emit the specified combiners"), 43 cl::cat(GICombinerEmitterCat), cl::CommaSeparated); 44 static cl::opt<bool> ShowExpansions( 45 "gicombiner-show-expansions", 46 cl::desc("Use C++ comments to indicate occurence of code expansion"), 47 cl::cat(GICombinerEmitterCat)); 48 static cl::opt<bool> StopAfterParse( 49 "gicombiner-stop-after-parse", 50 cl::desc("Stop processing after parsing rules and dump state"), 51 cl::cat(GICombinerEmitterCat)); 52 static cl::opt<bool> StopAfterBuild( 53 "gicombiner-stop-after-build", 54 cl::desc("Stop processing after building the match tree"), 55 cl::cat(GICombinerEmitterCat)); 56 57 namespace { 58 typedef uint64_t RuleID; 59 60 // We're going to be referencing the same small strings quite a lot for operand 61 // names and the like. Make their lifetime management simple with a global 62 // string table. 63 StringSet<> StrTab; 64 65 StringRef insertStrTab(StringRef S) { 66 if (S.empty()) 67 return S; 68 return StrTab.insert(S).first->first(); 69 } 70 71 class format_partition_name { 72 const GIMatchTree &Tree; 73 unsigned Idx; 74 75 public: 76 format_partition_name(const GIMatchTree &Tree, unsigned Idx) 77 : Tree(Tree), Idx(Idx) {} 78 void print(raw_ostream &OS) const { 79 Tree.getPartitioner()->emitPartitionName(OS, Idx); 80 } 81 }; 82 raw_ostream &operator<<(raw_ostream &OS, const format_partition_name &Fmt) { 83 Fmt.print(OS); 84 return OS; 85 } 86 87 /// Declares data that is passed from the match stage to the apply stage. 88 class MatchDataInfo { 89 /// The symbol used in the tablegen patterns 90 StringRef PatternSymbol; 91 /// The data type for the variable 92 StringRef Type; 93 /// The name of the variable as declared in the generated matcher. 94 std::string VariableName; 95 96 public: 97 MatchDataInfo(StringRef PatternSymbol, StringRef Type, StringRef VariableName) 98 : PatternSymbol(PatternSymbol), Type(Type), VariableName(VariableName) {} 99 100 StringRef getPatternSymbol() const { return PatternSymbol; }; 101 StringRef getType() const { return Type; }; 102 StringRef getVariableName() const { return VariableName; }; 103 }; 104 105 class RootInfo { 106 StringRef PatternSymbol; 107 108 public: 109 RootInfo(StringRef PatternSymbol) : PatternSymbol(PatternSymbol) {} 110 111 StringRef getPatternSymbol() const { return PatternSymbol; } 112 }; 113 114 class CombineRule { 115 public: 116 117 using const_matchdata_iterator = std::vector<MatchDataInfo>::const_iterator; 118 119 struct VarInfo { 120 const GIMatchDagInstr *N; 121 const GIMatchDagOperand *Op; 122 const DagInit *Matcher; 123 124 public: 125 VarInfo(const GIMatchDagInstr *N, const GIMatchDagOperand *Op, 126 const DagInit *Matcher) 127 : N(N), Op(Op), Matcher(Matcher) {} 128 }; 129 130 protected: 131 /// A unique ID for this rule 132 /// ID's are used for debugging and run-time disabling of rules among other 133 /// things. 134 RuleID ID; 135 136 /// A unique ID that can be used for anonymous objects belonging to this rule. 137 /// Used to create unique names in makeNameForAnon*() without making tests 138 /// overly fragile. 139 unsigned UID = 0; 140 141 /// The record defining this rule. 142 const Record &TheDef; 143 144 /// The roots of a match. These are the leaves of the DAG that are closest to 145 /// the end of the function. I.e. the nodes that are encountered without 146 /// following any edges of the DAG described by the pattern as we work our way 147 /// from the bottom of the function to the top. 148 std::vector<RootInfo> Roots; 149 150 GIMatchDag MatchDag; 151 152 /// A block of arbitrary C++ to finish testing the match. 153 /// FIXME: This is a temporary measure until we have actual pattern matching 154 const StringInit *MatchingFixupCode = nullptr; 155 156 /// The MatchData defined by the match stage and required by the apply stage. 157 /// This allows the plumbing of arbitrary data from C++ predicates between the 158 /// stages. 159 /// 160 /// For example, suppose you have: 161 /// %A = <some-constant-expr> 162 /// %0 = G_ADD %1, %A 163 /// you could define a GIMatchPredicate that walks %A, constant folds as much 164 /// as possible and returns an APInt containing the discovered constant. You 165 /// could then declare: 166 /// def apint : GIDefMatchData<"APInt">; 167 /// add it to the rule with: 168 /// (defs root:$root, apint:$constant) 169 /// evaluate it in the pattern with a C++ function that takes a 170 /// MachineOperand& and an APInt& with: 171 /// (match [{MIR %root = G_ADD %0, %A }], 172 /// (constantfold operand:$A, apint:$constant)) 173 /// and finally use it in the apply stage with: 174 /// (apply (create_operand 175 /// [{ MachineOperand::CreateImm(${constant}.getZExtValue()); 176 /// ]}, apint:$constant), 177 /// [{MIR %root = FOO %0, %constant }]) 178 std::vector<MatchDataInfo> MatchDataDecls; 179 180 void declareMatchData(StringRef PatternSymbol, StringRef Type, 181 StringRef VarName); 182 183 bool parseInstructionMatcher(const CodeGenTarget &Target, StringInit *ArgName, 184 const Init &Arg, 185 StringMap<std::vector<VarInfo>> &NamedEdgeDefs, 186 StringMap<std::vector<VarInfo>> &NamedEdgeUses); 187 bool parseWipMatchOpcodeMatcher(const CodeGenTarget &Target, 188 StringInit *ArgName, const Init &Arg); 189 190 public: 191 CombineRule(const CodeGenTarget &Target, GIMatchDagContext &Ctx, RuleID ID, 192 const Record &R) 193 : ID(ID), TheDef(R), MatchDag(Ctx) {} 194 CombineRule(const CombineRule &) = delete; 195 196 bool parseDefs(); 197 bool parseMatcher(const CodeGenTarget &Target); 198 199 RuleID getID() const { return ID; } 200 unsigned allocUID() { return UID++; } 201 StringRef getName() const { return TheDef.getName(); } 202 const Record &getDef() const { return TheDef; } 203 const StringInit *getMatchingFixupCode() const { return MatchingFixupCode; } 204 size_t getNumRoots() const { return Roots.size(); } 205 206 GIMatchDag &getMatchDag() { return MatchDag; } 207 const GIMatchDag &getMatchDag() const { return MatchDag; } 208 209 using const_root_iterator = std::vector<RootInfo>::const_iterator; 210 const_root_iterator roots_begin() const { return Roots.begin(); } 211 const_root_iterator roots_end() const { return Roots.end(); } 212 iterator_range<const_root_iterator> roots() const { 213 return llvm::make_range(Roots.begin(), Roots.end()); 214 } 215 216 iterator_range<const_matchdata_iterator> matchdata_decls() const { 217 return make_range(MatchDataDecls.begin(), MatchDataDecls.end()); 218 } 219 220 /// Export expansions for this rule 221 void declareExpansions(CodeExpansions &Expansions) const { 222 for (const auto &I : matchdata_decls()) 223 Expansions.declare(I.getPatternSymbol(), I.getVariableName()); 224 } 225 226 /// The matcher will begin from the roots and will perform the match by 227 /// traversing the edges to cover the whole DAG. This function reverses DAG 228 /// edges such that everything is reachable from a root. This is part of the 229 /// preparation work for flattening the DAG into a tree. 230 void reorientToRoots() { 231 SmallSet<const GIMatchDagInstr *, 5> Roots; 232 SmallSet<const GIMatchDagInstr *, 5> Visited; 233 SmallSet<GIMatchDagEdge *, 20> EdgesRemaining; 234 235 for (auto &I : MatchDag.roots()) { 236 Roots.insert(I); 237 Visited.insert(I); 238 } 239 for (auto &I : MatchDag.edges()) 240 EdgesRemaining.insert(I); 241 242 bool Progressed = false; 243 SmallSet<GIMatchDagEdge *, 20> EdgesToRemove; 244 while (!EdgesRemaining.empty()) { 245 for (auto *EI : EdgesRemaining) { 246 if (Visited.count(EI->getFromMI())) { 247 if (Roots.count(EI->getToMI())) 248 PrintError(TheDef.getLoc(), "One or more roots are unnecessary"); 249 Visited.insert(EI->getToMI()); 250 EdgesToRemove.insert(EI); 251 Progressed = true; 252 } 253 } 254 for (GIMatchDagEdge *ToRemove : EdgesToRemove) 255 EdgesRemaining.erase(ToRemove); 256 EdgesToRemove.clear(); 257 258 for (auto EI = EdgesRemaining.begin(), EE = EdgesRemaining.end(); 259 EI != EE; ++EI) { 260 if (Visited.count((*EI)->getToMI())) { 261 (*EI)->reverse(); 262 Visited.insert((*EI)->getToMI()); 263 EdgesToRemove.insert(*EI); 264 Progressed = true; 265 } 266 for (GIMatchDagEdge *ToRemove : EdgesToRemove) 267 EdgesRemaining.erase(ToRemove); 268 EdgesToRemove.clear(); 269 } 270 271 if (!Progressed) { 272 LLVM_DEBUG(dbgs() << "No progress\n"); 273 return; 274 } 275 Progressed = false; 276 } 277 } 278 }; 279 280 /// A convenience function to check that an Init refers to a specific def. This 281 /// is primarily useful for testing for defs and similar in DagInit's since 282 /// DagInit's support any type inside them. 283 static bool isSpecificDef(const Init &N, StringRef Def) { 284 if (const DefInit *OpI = dyn_cast<DefInit>(&N)) 285 if (OpI->getDef()->getName() == Def) 286 return true; 287 return false; 288 } 289 290 /// A convenience function to check that an Init refers to a def that is a 291 /// subclass of the given class and coerce it to a def if it is. This is 292 /// primarily useful for testing for subclasses of GIMatchKind and similar in 293 /// DagInit's since DagInit's support any type inside them. 294 static Record *getDefOfSubClass(const Init &N, StringRef Cls) { 295 if (const DefInit *OpI = dyn_cast<DefInit>(&N)) 296 if (OpI->getDef()->isSubClassOf(Cls)) 297 return OpI->getDef(); 298 return nullptr; 299 } 300 301 /// A convenience function to check that an Init refers to a dag whose operator 302 /// is a specific def and coerce it to a dag if it is. This is primarily useful 303 /// for testing for subclasses of GIMatchKind and similar in DagInit's since 304 /// DagInit's support any type inside them. 305 static const DagInit *getDagWithSpecificOperator(const Init &N, 306 StringRef Name) { 307 if (const DagInit *I = dyn_cast<DagInit>(&N)) 308 if (I->getNumArgs() > 0) 309 if (const DefInit *OpI = dyn_cast<DefInit>(I->getOperator())) 310 if (OpI->getDef()->getName() == Name) 311 return I; 312 return nullptr; 313 } 314 315 /// A convenience function to check that an Init refers to a dag whose operator 316 /// is a def that is a subclass of the given class and coerce it to a dag if it 317 /// is. This is primarily useful for testing for subclasses of GIMatchKind and 318 /// similar in DagInit's since DagInit's support any type inside them. 319 static const DagInit *getDagWithOperatorOfSubClass(const Init &N, 320 StringRef Cls) { 321 if (const DagInit *I = dyn_cast<DagInit>(&N)) 322 if (I->getNumArgs() > 0) 323 if (const DefInit *OpI = dyn_cast<DefInit>(I->getOperator())) 324 if (OpI->getDef()->isSubClassOf(Cls)) 325 return I; 326 return nullptr; 327 } 328 329 StringRef makeNameForAnonInstr(CombineRule &Rule) { 330 return insertStrTab(to_string( 331 format("__anon%" PRIu64 "_%u", Rule.getID(), Rule.allocUID()))); 332 } 333 334 StringRef makeDebugName(CombineRule &Rule, StringRef Name) { 335 return insertStrTab(Name.empty() ? makeNameForAnonInstr(Rule) : StringRef(Name)); 336 } 337 338 StringRef makeNameForAnonPredicate(CombineRule &Rule) { 339 return insertStrTab(to_string( 340 format("__anonpred%" PRIu64 "_%u", Rule.getID(), Rule.allocUID()))); 341 } 342 343 void CombineRule::declareMatchData(StringRef PatternSymbol, StringRef Type, 344 StringRef VarName) { 345 MatchDataDecls.emplace_back(PatternSymbol, Type, VarName); 346 } 347 348 bool CombineRule::parseDefs() { 349 DagInit *Defs = TheDef.getValueAsDag("Defs"); 350 351 if (Defs->getOperatorAsDef(TheDef.getLoc())->getName() != "defs") { 352 PrintError(TheDef.getLoc(), "Expected defs operator"); 353 return false; 354 } 355 356 for (unsigned I = 0, E = Defs->getNumArgs(); I < E; ++I) { 357 // Roots should be collected into Roots 358 if (isSpecificDef(*Defs->getArg(I), "root")) { 359 Roots.emplace_back(Defs->getArgNameStr(I)); 360 continue; 361 } 362 363 // Subclasses of GIDefMatchData should declare that this rule needs to pass 364 // data from the match stage to the apply stage, and ensure that the 365 // generated matcher has a suitable variable for it to do so. 366 if (Record *MatchDataRec = 367 getDefOfSubClass(*Defs->getArg(I), "GIDefMatchData")) { 368 declareMatchData(Defs->getArgNameStr(I), 369 MatchDataRec->getValueAsString("Type"), 370 llvm::to_string(llvm::format("MatchData%" PRIu64, ID))); 371 continue; 372 } 373 374 // Otherwise emit an appropriate error message. 375 if (getDefOfSubClass(*Defs->getArg(I), "GIDefKind")) 376 PrintError(TheDef.getLoc(), 377 "This GIDefKind not implemented in tablegen"); 378 else if (getDefOfSubClass(*Defs->getArg(I), "GIDefKindWithArgs")) 379 PrintError(TheDef.getLoc(), 380 "This GIDefKindWithArgs not implemented in tablegen"); 381 else 382 PrintError(TheDef.getLoc(), 383 "Expected a subclass of GIDefKind or a sub-dag whose " 384 "operator is of type GIDefKindWithArgs"); 385 return false; 386 } 387 388 if (Roots.empty()) { 389 PrintError(TheDef.getLoc(), "Combine rules must have at least one root"); 390 return false; 391 } 392 return true; 393 } 394 395 // Parse an (Instruction $a:Arg1, $b:Arg2, ...) matcher. Edges are formed 396 // between matching operand names between different matchers. 397 bool CombineRule::parseInstructionMatcher( 398 const CodeGenTarget &Target, StringInit *ArgName, const Init &Arg, 399 StringMap<std::vector<VarInfo>> &NamedEdgeDefs, 400 StringMap<std::vector<VarInfo>> &NamedEdgeUses) { 401 if (const DagInit *Matcher = 402 getDagWithOperatorOfSubClass(Arg, "Instruction")) { 403 auto &Instr = 404 Target.getInstruction(Matcher->getOperatorAsDef(TheDef.getLoc())); 405 406 StringRef Name = ArgName ? ArgName->getValue() : ""; 407 408 GIMatchDagInstr *N = 409 MatchDag.addInstrNode(makeDebugName(*this, Name), insertStrTab(Name), 410 MatchDag.getContext().makeOperandList(Instr)); 411 412 N->setOpcodeAnnotation(&Instr); 413 const auto &P = MatchDag.addPredicateNode<GIMatchDagOpcodePredicate>( 414 makeNameForAnonPredicate(*this), Instr); 415 MatchDag.addPredicateDependency(N, nullptr, P, &P->getOperandInfo()["mi"]); 416 unsigned OpIdx = 0; 417 for (const auto &NameInit : Matcher->getArgNames()) { 418 StringRef Name = insertStrTab(NameInit->getAsUnquotedString()); 419 if (Name.empty()) 420 continue; 421 N->assignNameToOperand(OpIdx, Name); 422 423 // Record the endpoints of any named edges. We'll add the cartesian 424 // product of edges later. 425 const auto &InstrOperand = N->getOperandInfo()[OpIdx]; 426 if (InstrOperand.isDef()) { 427 NamedEdgeDefs.try_emplace(Name); 428 NamedEdgeDefs[Name].emplace_back(N, &InstrOperand, Matcher); 429 } else { 430 NamedEdgeUses.try_emplace(Name); 431 NamedEdgeUses[Name].emplace_back(N, &InstrOperand, Matcher); 432 } 433 434 if (InstrOperand.isDef()) { 435 if (any_of(Roots, [&](const RootInfo &X) { 436 return X.getPatternSymbol() == Name; 437 })) { 438 N->setMatchRoot(); 439 } 440 } 441 442 OpIdx++; 443 } 444 445 return true; 446 } 447 return false; 448 } 449 450 // Parse the wip_match_opcode placeholder that's temporarily present in lieu of 451 // implementing macros or choices between two matchers. 452 bool CombineRule::parseWipMatchOpcodeMatcher(const CodeGenTarget &Target, 453 StringInit *ArgName, 454 const Init &Arg) { 455 if (const DagInit *Matcher = 456 getDagWithSpecificOperator(Arg, "wip_match_opcode")) { 457 StringRef Name = ArgName ? ArgName->getValue() : ""; 458 459 GIMatchDagInstr *N = 460 MatchDag.addInstrNode(makeDebugName(*this, Name), insertStrTab(Name), 461 MatchDag.getContext().makeEmptyOperandList()); 462 463 if (any_of(Roots, [&](const RootInfo &X) { 464 return ArgName && X.getPatternSymbol() == ArgName->getValue(); 465 })) { 466 N->setMatchRoot(); 467 } 468 469 const auto &P = MatchDag.addPredicateNode<GIMatchDagOneOfOpcodesPredicate>( 470 makeNameForAnonPredicate(*this)); 471 MatchDag.addPredicateDependency(N, nullptr, P, &P->getOperandInfo()["mi"]); 472 // Each argument is an opcode that will pass this predicate. Add them all to 473 // the predicate implementation 474 for (const auto &Arg : Matcher->getArgs()) { 475 Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction"); 476 if (OpcodeDef) { 477 P->addOpcode(&Target.getInstruction(OpcodeDef)); 478 continue; 479 } 480 PrintError(TheDef.getLoc(), 481 "Arguments to wip_match_opcode must be instructions"); 482 return false; 483 } 484 return true; 485 } 486 return false; 487 } 488 bool CombineRule::parseMatcher(const CodeGenTarget &Target) { 489 StringMap<std::vector<VarInfo>> NamedEdgeDefs; 490 StringMap<std::vector<VarInfo>> NamedEdgeUses; 491 DagInit *Matchers = TheDef.getValueAsDag("Match"); 492 493 if (Matchers->getOperatorAsDef(TheDef.getLoc())->getName() != "match") { 494 PrintError(TheDef.getLoc(), "Expected match operator"); 495 return false; 496 } 497 498 if (Matchers->getNumArgs() == 0) { 499 PrintError(TheDef.getLoc(), "Matcher is empty"); 500 return false; 501 } 502 503 // The match section consists of a list of matchers and predicates. Parse each 504 // one and add the equivalent GIMatchDag nodes, predicates, and edges. 505 for (unsigned I = 0; I < Matchers->getNumArgs(); ++I) { 506 if (parseInstructionMatcher(Target, Matchers->getArgName(I), 507 *Matchers->getArg(I), NamedEdgeDefs, 508 NamedEdgeUses)) 509 continue; 510 511 if (parseWipMatchOpcodeMatcher(Target, Matchers->getArgName(I), 512 *Matchers->getArg(I))) 513 continue; 514 515 516 // Parse arbitrary C++ code we have in lieu of supporting MIR matching 517 if (const StringInit *StringI = dyn_cast<StringInit>(Matchers->getArg(I))) { 518 assert(!MatchingFixupCode && 519 "Only one block of arbitrary code is currently permitted"); 520 MatchingFixupCode = StringI; 521 MatchDag.setHasPostMatchPredicate(true); 522 continue; 523 } 524 525 PrintError(TheDef.getLoc(), 526 "Expected a subclass of GIMatchKind or a sub-dag whose " 527 "operator is either of a GIMatchKindWithArgs or Instruction"); 528 PrintNote("Pattern was `" + Matchers->getArg(I)->getAsString() + "'"); 529 return false; 530 } 531 532 // Add the cartesian product of use -> def edges. 533 bool FailedToAddEdges = false; 534 for (const auto &NameAndDefs : NamedEdgeDefs) { 535 if (NameAndDefs.getValue().size() > 1) { 536 PrintError(TheDef.getLoc(), 537 "Two different MachineInstrs cannot def the same vreg"); 538 for (const auto &NameAndDefOp : NameAndDefs.getValue()) 539 PrintNote("in " + to_string(*NameAndDefOp.N) + " created from " + 540 to_string(*NameAndDefOp.Matcher) + ""); 541 FailedToAddEdges = true; 542 } 543 const auto &Uses = NamedEdgeUses[NameAndDefs.getKey()]; 544 for (const VarInfo &DefVar : NameAndDefs.getValue()) { 545 for (const VarInfo &UseVar : Uses) { 546 MatchDag.addEdge(insertStrTab(NameAndDefs.getKey()), UseVar.N, UseVar.Op, 547 DefVar.N, DefVar.Op); 548 } 549 } 550 } 551 if (FailedToAddEdges) 552 return false; 553 554 // If a variable is referenced in multiple use contexts then we need a 555 // predicate to confirm they are the same operand. We can elide this if it's 556 // also referenced in a def context and we're traversing the def-use chain 557 // from the def to the uses but we can't know which direction we're going 558 // until after reorientToRoots(). 559 for (const auto &NameAndUses : NamedEdgeUses) { 560 const auto &Uses = NameAndUses.getValue(); 561 if (Uses.size() > 1) { 562 const auto &LeadingVar = Uses.front(); 563 for (const auto &Var : ArrayRef<VarInfo>(Uses).drop_front()) { 564 // Add a predicate for each pair until we've covered the whole 565 // equivalence set. We could test the whole set in a single predicate 566 // but that means we can't test any equivalence until all the MO's are 567 // available which can lead to wasted work matching the DAG when this 568 // predicate can already be seen to have failed. 569 // 570 // We have a similar problem due to the need to wait for a particular MO 571 // before being able to test any of them. However, that is mitigated by 572 // the order in which we build the DAG. We build from the roots outwards 573 // so by using the first recorded use in all the predicates, we are 574 // making the dependency on one of the earliest visited references in 575 // the DAG. It's not guaranteed once the generated matcher is optimized 576 // (because the factoring the common portions of rules might change the 577 // visit order) but this should mean that these predicates depend on the 578 // first MO to become available. 579 const auto &P = MatchDag.addPredicateNode<GIMatchDagSameMOPredicate>( 580 makeNameForAnonPredicate(*this)); 581 MatchDag.addPredicateDependency(LeadingVar.N, LeadingVar.Op, P, 582 &P->getOperandInfo()["mi0"]); 583 MatchDag.addPredicateDependency(Var.N, Var.Op, P, 584 &P->getOperandInfo()["mi1"]); 585 } 586 } 587 } 588 return true; 589 } 590 591 class GICombinerEmitter { 592 RecordKeeper &Records; 593 StringRef Name; 594 const CodeGenTarget &Target; 595 Record *Combiner; 596 std::vector<std::unique_ptr<CombineRule>> Rules; 597 GIMatchDagContext MatchDagCtx; 598 599 std::unique_ptr<CombineRule> makeCombineRule(const Record &R); 600 601 void gatherRules(std::vector<std::unique_ptr<CombineRule>> &ActiveRules, 602 const std::vector<Record *> &&RulesAndGroups); 603 604 public: 605 explicit GICombinerEmitter(RecordKeeper &RK, const CodeGenTarget &Target, 606 StringRef Name, Record *Combiner); 607 ~GICombinerEmitter() {} 608 609 StringRef getClassName() const { 610 return Combiner->getValueAsString("Classname"); 611 } 612 void run(raw_ostream &OS); 613 614 /// Emit the name matcher (guarded by #ifndef NDEBUG) used to disable rules in 615 /// response to the generated cl::opt. 616 void emitNameMatcher(raw_ostream &OS) const; 617 618 void generateCodeForTree(raw_ostream &OS, const GIMatchTree &Tree, 619 StringRef Indent) const; 620 }; 621 622 GICombinerEmitter::GICombinerEmitter(RecordKeeper &RK, 623 const CodeGenTarget &Target, 624 StringRef Name, Record *Combiner) 625 : Records(RK), Name(Name), Target(Target), Combiner(Combiner) {} 626 627 void GICombinerEmitter::emitNameMatcher(raw_ostream &OS) const { 628 std::vector<std::pair<std::string, std::string>> Cases; 629 Cases.reserve(Rules.size()); 630 631 for (const CombineRule &EnumeratedRule : make_pointee_range(Rules)) { 632 std::string Code; 633 raw_string_ostream SS(Code); 634 SS << "return " << EnumeratedRule.getID() << ";\n"; 635 Cases.push_back( 636 std::make_pair(std::string(EnumeratedRule.getName()), Code)); 637 } 638 639 OS << "static Optional<uint64_t> getRuleIdxForIdentifier(StringRef " 640 "RuleIdentifier) {\n" 641 << " uint64_t I;\n" 642 << " // getAtInteger(...) returns false on success\n" 643 << " bool Parsed = !RuleIdentifier.getAsInteger(0, I);\n" 644 << " if (Parsed)\n" 645 << " return I;\n\n" 646 << "#ifndef NDEBUG\n"; 647 StringMatcher Matcher("RuleIdentifier", Cases, OS); 648 Matcher.Emit(); 649 OS << "#endif // ifndef NDEBUG\n\n" 650 << " return None;\n" 651 << "}\n"; 652 } 653 654 std::unique_ptr<CombineRule> 655 GICombinerEmitter::makeCombineRule(const Record &TheDef) { 656 std::unique_ptr<CombineRule> Rule = 657 std::make_unique<CombineRule>(Target, MatchDagCtx, NumPatternTotal, TheDef); 658 659 if (!Rule->parseDefs()) 660 return nullptr; 661 if (!Rule->parseMatcher(Target)) 662 return nullptr; 663 664 Rule->reorientToRoots(); 665 666 LLVM_DEBUG({ 667 dbgs() << "Parsed rule defs/match for '" << Rule->getName() << "'\n"; 668 Rule->getMatchDag().dump(); 669 Rule->getMatchDag().writeDOTGraph(dbgs(), Rule->getName()); 670 }); 671 if (StopAfterParse) 672 return Rule; 673 674 // For now, don't support traversing from def to use. We'll come back to 675 // this later once we have the algorithm changes to support it. 676 bool EmittedDefToUseError = false; 677 for (const auto &E : Rule->getMatchDag().edges()) { 678 if (E->isDefToUse()) { 679 if (!EmittedDefToUseError) { 680 PrintError( 681 TheDef.getLoc(), 682 "Generated state machine cannot lookup uses from a def (yet)"); 683 EmittedDefToUseError = true; 684 } 685 PrintNote("Node " + to_string(*E->getFromMI())); 686 PrintNote("Node " + to_string(*E->getToMI())); 687 PrintNote("Edge " + to_string(*E)); 688 } 689 } 690 if (EmittedDefToUseError) 691 return nullptr; 692 693 // For now, don't support multi-root rules. We'll come back to this later 694 // once we have the algorithm changes to support it. 695 if (Rule->getNumRoots() > 1) { 696 PrintError(TheDef.getLoc(), "Multi-root matches are not supported (yet)"); 697 return nullptr; 698 } 699 return Rule; 700 } 701 702 /// Recurse into GICombineGroup's and flatten the ruleset into a simple list. 703 void GICombinerEmitter::gatherRules( 704 std::vector<std::unique_ptr<CombineRule>> &ActiveRules, 705 const std::vector<Record *> &&RulesAndGroups) { 706 for (Record *R : RulesAndGroups) { 707 if (R->isValueUnset("Rules")) { 708 std::unique_ptr<CombineRule> Rule = makeCombineRule(*R); 709 if (Rule == nullptr) { 710 PrintError(R->getLoc(), "Failed to parse rule"); 711 continue; 712 } 713 ActiveRules.emplace_back(std::move(Rule)); 714 ++NumPatternTotal; 715 } else 716 gatherRules(ActiveRules, R->getValueAsListOfDefs("Rules")); 717 } 718 } 719 720 void GICombinerEmitter::generateCodeForTree(raw_ostream &OS, 721 const GIMatchTree &Tree, 722 StringRef Indent) const { 723 if (Tree.getPartitioner() != nullptr) { 724 Tree.getPartitioner()->generatePartitionSelectorCode(OS, Indent); 725 for (const auto &EnumChildren : enumerate(Tree.children())) { 726 OS << Indent << "if (Partition == " << EnumChildren.index() << " /* " 727 << format_partition_name(Tree, EnumChildren.index()) << " */) {\n"; 728 generateCodeForTree(OS, EnumChildren.value(), (Indent + " ").str()); 729 OS << Indent << "}\n"; 730 } 731 return; 732 } 733 734 bool AnyFullyTested = false; 735 for (const auto &Leaf : Tree.possible_leaves()) { 736 OS << Indent << "// Leaf name: " << Leaf.getName() << "\n"; 737 738 const CombineRule *Rule = Leaf.getTargetData<CombineRule>(); 739 const Record &RuleDef = Rule->getDef(); 740 741 OS << Indent << "// Rule: " << RuleDef.getName() << "\n" 742 << Indent << "if (!RuleConfig->isRuleDisabled(" << Rule->getID() 743 << ")) {\n"; 744 745 CodeExpansions Expansions; 746 for (const auto &VarBinding : Leaf.var_bindings()) { 747 if (VarBinding.isInstr()) 748 Expansions.declare(VarBinding.getName(), 749 "MIs[" + to_string(VarBinding.getInstrID()) + "]"); 750 else 751 Expansions.declare(VarBinding.getName(), 752 "MIs[" + to_string(VarBinding.getInstrID()) + 753 "]->getOperand(" + 754 to_string(VarBinding.getOpIdx()) + ")"); 755 } 756 Rule->declareExpansions(Expansions); 757 758 DagInit *Applyer = RuleDef.getValueAsDag("Apply"); 759 if (Applyer->getOperatorAsDef(RuleDef.getLoc())->getName() != 760 "apply") { 761 PrintError(RuleDef.getLoc(), "Expected 'apply' operator in Apply DAG"); 762 return; 763 } 764 765 OS << Indent << " if (1\n"; 766 767 // Attempt to emit code for any untested predicates left over. Note that 768 // isFullyTested() will remain false even if we succeed here and therefore 769 // combine rule elision will not be performed. This is because we do not 770 // know if there's any connection between the predicates for each leaf and 771 // therefore can't tell if one makes another unreachable. Ideally, the 772 // partitioner(s) would be sufficiently complete to prevent us from having 773 // untested predicates left over. 774 for (const GIMatchDagPredicate *Predicate : Leaf.untested_predicates()) { 775 if (Predicate->generateCheckCode(OS, (Indent + " ").str(), 776 Expansions)) 777 continue; 778 PrintError(RuleDef.getLoc(), 779 "Unable to test predicate used in rule"); 780 PrintNote(SMLoc(), 781 "This indicates an incomplete implementation in tablegen"); 782 Predicate->print(errs()); 783 errs() << "\n"; 784 OS << Indent 785 << "llvm_unreachable(\"TableGen did not emit complete code for this " 786 "path\");\n"; 787 break; 788 } 789 790 if (Rule->getMatchingFixupCode() && 791 !Rule->getMatchingFixupCode()->getValue().empty()) { 792 // FIXME: Single-use lambda's like this are a serious compile-time 793 // performance and memory issue. It's convenient for this early stage to 794 // defer some work to successive patches but we need to eliminate this 795 // before the ruleset grows to small-moderate size. Last time, it became 796 // a big problem for low-mem systems around the 500 rule mark but by the 797 // time we grow that large we should have merged the ISel match table 798 // mechanism with the Combiner. 799 OS << Indent << " && [&]() {\n" 800 << Indent << " " 801 << CodeExpander(Rule->getMatchingFixupCode()->getValue(), Expansions, 802 RuleDef.getLoc(), ShowExpansions) 803 << "\n" 804 << Indent << " return true;\n" 805 << Indent << " }()"; 806 } 807 OS << ") {\n" << Indent << " "; 808 809 if (const StringInit *Code = dyn_cast<StringInit>(Applyer->getArg(0))) { 810 OS << CodeExpander(Code->getAsUnquotedString(), Expansions, 811 RuleDef.getLoc(), ShowExpansions) 812 << "\n" 813 << Indent << " return true;\n" 814 << Indent << " }\n"; 815 } else { 816 PrintError(RuleDef.getLoc(), "Expected apply code block"); 817 return; 818 } 819 820 OS << Indent << "}\n"; 821 822 assert(Leaf.isFullyTraversed()); 823 824 // If we didn't have any predicates left over and we're not using the 825 // trap-door we have to support arbitrary C++ code while we're migrating to 826 // the declarative style then we know that subsequent leaves are 827 // unreachable. 828 if (Leaf.isFullyTested() && 829 (!Rule->getMatchingFixupCode() || 830 Rule->getMatchingFixupCode()->getValue().empty())) { 831 AnyFullyTested = true; 832 OS << Indent 833 << "llvm_unreachable(\"Combine rule elision was incorrect\");\n" 834 << Indent << "return false;\n"; 835 } 836 } 837 if (!AnyFullyTested) 838 OS << Indent << "return false;\n"; 839 } 840 841 static void emitAdditionalHelperMethodArguments(raw_ostream &OS, 842 Record *Combiner) { 843 for (Record *Arg : Combiner->getValueAsListOfDefs("AdditionalArguments")) 844 OS << ",\n " << Arg->getValueAsString("Type") 845 << Arg->getValueAsString("Name"); 846 } 847 848 void GICombinerEmitter::run(raw_ostream &OS) { 849 Records.startTimer("Gather rules"); 850 gatherRules(Rules, Combiner->getValueAsListOfDefs("Rules")); 851 if (StopAfterParse) { 852 MatchDagCtx.print(errs()); 853 PrintNote(Combiner->getLoc(), 854 "Terminating due to -gicombiner-stop-after-parse"); 855 return; 856 } 857 if (ErrorsPrinted) 858 PrintFatalError(Combiner->getLoc(), "Failed to parse one or more rules"); 859 LLVM_DEBUG(dbgs() << "Optimizing tree for " << Rules.size() << " rules\n"); 860 std::unique_ptr<GIMatchTree> Tree; 861 Records.startTimer("Optimize combiner"); 862 { 863 GIMatchTreeBuilder TreeBuilder(0); 864 for (const auto &Rule : Rules) { 865 bool HadARoot = false; 866 for (const auto &Root : enumerate(Rule->getMatchDag().roots())) { 867 TreeBuilder.addLeaf(Rule->getName(), Root.index(), Rule->getMatchDag(), 868 Rule.get()); 869 HadARoot = true; 870 } 871 if (!HadARoot) 872 PrintFatalError(Rule->getDef().getLoc(), "All rules must have a root"); 873 } 874 875 Tree = TreeBuilder.run(); 876 } 877 if (StopAfterBuild) { 878 Tree->writeDOTGraph(outs()); 879 PrintNote(Combiner->getLoc(), 880 "Terminating due to -gicombiner-stop-after-build"); 881 return; 882 } 883 884 Records.startTimer("Emit combiner"); 885 OS << "#ifdef " << Name.upper() << "_GENCOMBINERHELPER_DEPS\n" 886 << "#include \"llvm/ADT/SparseBitVector.h\"\n" 887 << "namespace llvm {\n" 888 << "extern cl::OptionCategory GICombinerOptionCategory;\n" 889 << "} // end namespace llvm\n" 890 << "#endif // ifdef " << Name.upper() << "_GENCOMBINERHELPER_DEPS\n\n"; 891 892 OS << "#ifdef " << Name.upper() << "_GENCOMBINERHELPER_H\n" 893 << "class " << getClassName() << "RuleConfig {\n" 894 << " SparseBitVector<> DisabledRules;\n" 895 << "\n" 896 << "public:\n" 897 << " bool parseCommandLineOption();\n" 898 << " bool isRuleDisabled(unsigned ID) const;\n" 899 << " bool setRuleEnabled(StringRef RuleIdentifier);\n" 900 << " bool setRuleDisabled(StringRef RuleIdentifier);\n" 901 << "};\n" 902 << "\n" 903 << "class " << getClassName(); 904 StringRef StateClass = Combiner->getValueAsString("StateClass"); 905 if (!StateClass.empty()) 906 OS << " : public " << StateClass; 907 OS << " {\n" 908 << " const " << getClassName() << "RuleConfig *RuleConfig;\n" 909 << "\n" 910 << "public:\n" 911 << " template <typename... Args>" << getClassName() << "(const " 912 << getClassName() << "RuleConfig &RuleConfig, Args &&... args) : "; 913 if (!StateClass.empty()) 914 OS << StateClass << "(std::forward<Args>(args)...), "; 915 OS << "RuleConfig(&RuleConfig) {}\n" 916 << "\n" 917 << " bool tryCombineAll(\n" 918 << " GISelChangeObserver &Observer,\n" 919 << " MachineInstr &MI,\n" 920 << " MachineIRBuilder &B"; 921 emitAdditionalHelperMethodArguments(OS, Combiner); 922 OS << ") const;\n"; 923 OS << "};\n\n"; 924 925 emitNameMatcher(OS); 926 927 OS << "static Optional<std::pair<uint64_t, uint64_t>> " 928 "getRuleRangeForIdentifier(StringRef RuleIdentifier) {\n" 929 << " std::pair<StringRef, StringRef> RangePair = " 930 "RuleIdentifier.split('-');\n" 931 << " if (!RangePair.second.empty()) {\n" 932 << " const auto First = " 933 "getRuleIdxForIdentifier(RangePair.first);\n" 934 << " const auto Last = " 935 "getRuleIdxForIdentifier(RangePair.second);\n" 936 << " if (!First.hasValue() || !Last.hasValue())\n" 937 << " return None;\n" 938 << " if (First >= Last)\n" 939 << " report_fatal_error(\"Beginning of range should be before " 940 "end of range\");\n" 941 << " return {{*First, *Last + 1}};\n" 942 << " } else if (RangePair.first == \"*\") {\n" 943 << " return {{0, " << Rules.size() << "}};\n" 944 << " } else {\n" 945 << " const auto I = getRuleIdxForIdentifier(RangePair.first);\n" 946 << " if (!I.hasValue())\n" 947 << " return None;\n" 948 << " return {{*I, *I + 1}};\n" 949 << " }\n" 950 << " return None;\n" 951 << "}\n\n"; 952 953 for (bool Enabled : {true, false}) { 954 OS << "bool " << getClassName() << "RuleConfig::setRule" 955 << (Enabled ? "Enabled" : "Disabled") << "(StringRef RuleIdentifier) {\n" 956 << " auto MaybeRange = getRuleRangeForIdentifier(RuleIdentifier);\n" 957 << " if (!MaybeRange.hasValue())\n" 958 << " return false;\n" 959 << " for (auto I = MaybeRange->first; I < MaybeRange->second; ++I)\n" 960 << " DisabledRules." << (Enabled ? "reset" : "set") << "(I);\n" 961 << " return true;\n" 962 << "}\n\n"; 963 } 964 965 OS << "bool " << getClassName() 966 << "RuleConfig::isRuleDisabled(unsigned RuleID) const {\n" 967 << " return DisabledRules.test(RuleID);\n" 968 << "}\n"; 969 OS << "#endif // ifdef " << Name.upper() << "_GENCOMBINERHELPER_H\n\n"; 970 971 OS << "#ifdef " << Name.upper() << "_GENCOMBINERHELPER_CPP\n" 972 << "\n" 973 << "std::vector<std::string> " << Name << "Option;\n" 974 << "cl::list<std::string> " << Name << "DisableOption(\n" 975 << " \"" << Name.lower() << "-disable-rule\",\n" 976 << " cl::desc(\"Disable one or more combiner rules temporarily in " 977 << "the " << Name << " pass\"),\n" 978 << " cl::CommaSeparated,\n" 979 << " cl::Hidden,\n" 980 << " cl::cat(GICombinerOptionCategory),\n" 981 << " cl::callback([](const std::string &Str) {\n" 982 << " " << Name << "Option.push_back(Str);\n" 983 << " }));\n" 984 << "cl::list<std::string> " << Name << "OnlyEnableOption(\n" 985 << " \"" << Name.lower() << "-only-enable-rule\",\n" 986 << " cl::desc(\"Disable all rules in the " << Name 987 << " pass then re-enable the specified ones\"),\n" 988 << " cl::Hidden,\n" 989 << " cl::cat(GICombinerOptionCategory),\n" 990 << " cl::callback([](const std::string &CommaSeparatedArg) {\n" 991 << " StringRef Str = CommaSeparatedArg;\n" 992 << " " << Name << "Option.push_back(\"*\");\n" 993 << " do {\n" 994 << " auto X = Str.split(\",\");\n" 995 << " " << Name << "Option.push_back((\"!\" + X.first).str());\n" 996 << " Str = X.second;\n" 997 << " } while (!Str.empty());\n" 998 << " }));\n" 999 << "\n" 1000 << "bool " << getClassName() << "RuleConfig::parseCommandLineOption() {\n" 1001 << " for (StringRef Identifier : " << Name << "Option) {\n" 1002 << " bool Enabled = Identifier.consume_front(\"!\");\n" 1003 << " if (Enabled && !setRuleEnabled(Identifier))\n" 1004 << " return false;\n" 1005 << " if (!Enabled && !setRuleDisabled(Identifier))\n" 1006 << " return false;\n" 1007 << " }\n" 1008 << " return true;\n" 1009 << "}\n\n"; 1010 1011 OS << "bool " << getClassName() << "::tryCombineAll(\n" 1012 << " GISelChangeObserver &Observer,\n" 1013 << " MachineInstr &MI,\n" 1014 << " MachineIRBuilder &B"; 1015 emitAdditionalHelperMethodArguments(OS, Combiner); 1016 OS << ") const {\n" 1017 << " MachineBasicBlock *MBB = MI.getParent();\n" 1018 << " MachineFunction *MF = MBB->getParent();\n" 1019 << " MachineRegisterInfo &MRI = MF->getRegInfo();\n" 1020 << " SmallVector<MachineInstr *, 8> MIs = {&MI};\n\n" 1021 << " (void)MBB; (void)MF; (void)MRI; (void)RuleConfig;\n\n"; 1022 1023 OS << " // Match data\n"; 1024 for (const auto &Rule : Rules) 1025 for (const auto &I : Rule->matchdata_decls()) 1026 OS << " " << I.getType() << " " << I.getVariableName() << ";\n"; 1027 OS << "\n"; 1028 1029 OS << " int Partition = -1;\n"; 1030 generateCodeForTree(OS, *Tree, " "); 1031 OS << "\n return false;\n" 1032 << "}\n" 1033 << "#endif // ifdef " << Name.upper() << "_GENCOMBINERHELPER_CPP\n"; 1034 } 1035 1036 } // end anonymous namespace 1037 1038 //===----------------------------------------------------------------------===// 1039 1040 namespace llvm { 1041 void EmitGICombiner(RecordKeeper &RK, raw_ostream &OS) { 1042 CodeGenTarget Target(RK); 1043 emitSourceFileHeader("Global Combiner", OS); 1044 1045 if (SelectedCombiners.empty()) 1046 PrintFatalError("No combiners selected with -combiners"); 1047 for (const auto &Combiner : SelectedCombiners) { 1048 Record *CombinerDef = RK.getDef(Combiner); 1049 if (!CombinerDef) 1050 PrintFatalError("Could not find " + Combiner); 1051 GICombinerEmitter(RK, Target, Combiner, CombinerDef).run(OS); 1052 } 1053 NumPatternTotalStatistic = NumPatternTotal; 1054 } 1055 1056 } // namespace llvm 1057