diff options
author | Daniel Sanders <daniel_l_sanders@apple.com> | 2017-04-21 10:27:20 +0000 |
---|---|---|
committer | Daniel Sanders <daniel_l_sanders@apple.com> | 2017-04-21 10:27:20 +0000 |
commit | 279d03527e59bb6bcfaa04417e4d3210fb9f853b (patch) | |
tree | 1fb95db9704cb3ec3b1bd4e245f8e5d9fd3d695d /llvm/utils/TableGen/GlobalISelEmitter.cpp | |
parent | 41b4333066b1b37ad51dc751630aa8c983cfb003 (diff) | |
download | bcm5719-llvm-279d03527e59bb6bcfaa04417e4d3210fb9f853b.tar.gz bcm5719-llvm-279d03527e59bb6bcfaa04417e4d3210fb9f853b.zip |
[globalisel][tablegen] Import SelectionDAG's rule predicates and support the equivalent in GIRule.
Summary:
The SelectionDAG importer now imports rules with Predicate's attached via
Requires, PredicateControl, etc. These predicates are implemented as
bitset's to allow multiple predicates to be tested together. However,
unlike the MC layer subtarget features, each target only pays for it's own
predicates (e.g. AArch64 doesn't have 192 feature bits just because X86
needs a lot).
Both AArch64 and X86 derive at least one predicate from the MachineFunction
or Function so they must re-initialize AvailableFeatures before each
function. They also declare locals in <Target>InstructionSelector so that
computeAvailableFeatures() can use the code from SelectionDAG without
modification.
Reviewers: rovka, qcolombet, aditya_nandakumar, t.p.northover, ab
Reviewed By: rovka
Subscribers: aemerson, rengolin, dberris, kristof.beyls, llvm-commits, igorb
Differential Revision: https://reviews.llvm.org/D31418
llvm-svn: 300964
Diffstat (limited to 'llvm/utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r-- | llvm/utils/TableGen/GlobalISelEmitter.cpp | 91 |
1 files changed, 66 insertions, 25 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 7acc65e349e..312b3a69c71 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -31,6 +31,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenDAGPatterns.h" +#include "SubtargetFeatureInfo.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" @@ -161,20 +162,6 @@ static std::string explainPredicates(const TreePatternNode *N) { return Explanation; } -static std::string explainRulePredicates(const ArrayRef<Init *> Predicates) { - std::string Explanation = ""; - StringRef Separator = ""; - for (const auto *P : Predicates) { - Explanation += Separator; - - if (const DefInit *PDef = dyn_cast<DefInit>(P)) { - Explanation += PDef->getDef()->getName(); - } else - Explanation += "<unknown>"; - } - return Explanation; -} - std::string explainOperator(Record *Operator) { if (Operator->isSubClassOf("SDNode")) return " (" + Operator->getValueAsString("Opcode") + ")"; @@ -238,6 +225,8 @@ class RuleMatcher { /// ID for the next instruction variable defined with defineInsnVar() unsigned NextInsnVarID; + std::vector<Record *> RequiredFeatures; + public: RuleMatcher() : Matchers(), Actions(), InsnVariableNames(), NextInsnVarID(0) {} @@ -245,6 +234,7 @@ public: RuleMatcher &operator=(RuleMatcher &&Other) = default; InstructionMatcher &addInstructionMatcher(); + void addRequiredFeature(Record *Feature); template <class Kind, class... Args> Kind &addAction(Args &&... args); @@ -255,7 +245,9 @@ public: void emitCxxCapturedInsnList(raw_ostream &OS); void emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr); - void emit(raw_ostream &OS); + void emit(raw_ostream &OS, + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> + SubtargetFeatures); /// Compare the priority of this object and B. /// @@ -1092,6 +1084,10 @@ InstructionMatcher &RuleMatcher::addInstructionMatcher() { return *Matchers.back(); } +void RuleMatcher::addRequiredFeature(Record *Feature) { + RequiredFeatures.push_back(Feature); +} + template <class Kind, class... Args> Kind &RuleMatcher::addAction(Args &&... args) { Actions.emplace_back(llvm::make_unique<Kind>(std::forward<Args>(args)...)); @@ -1135,7 +1131,9 @@ void RuleMatcher::emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr) { Matchers.front()->emitCxxCaptureStmts(OS, *this, InsnVarName); } -void RuleMatcher::emit(raw_ostream &OS) { +void RuleMatcher::emit(raw_ostream &OS, + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> + SubtargetFeatures) { if (Matchers.empty()) llvm_unreachable("Unexpected empty matcher!"); @@ -1149,7 +1147,22 @@ void RuleMatcher::emit(raw_ostream &OS) { // %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr // on some targets but we don't need to make use of that yet. assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet"); - OS << "if ([&]() {\n"; + + OS << "if ("; + OS << "[&]() {\n"; + if (!RequiredFeatures.empty()) { + OS << " PredicateBitset ExpectedFeatures = {"; + StringRef Separator = ""; + for (const auto &Predicate : RequiredFeatures) { + const auto &I = SubtargetFeatures.find(Predicate); + assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); + OS << Separator << I->second.getEnumBitName(); + Separator = ", "; + } + OS << "};\n"; + OS << "if ((AvailableFeatures & ExpectedFeatures) != ExpectedFeatures)\n" + << " return false;\n"; + } emitCxxCaptureStmts(OS, "I"); @@ -1264,10 +1277,13 @@ private: /// GIComplexPatternEquiv. DenseMap<const Record *, const Record *> ComplexPatternEquivs; + // Map of predicates to their subtarget features. + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures; + void gatherNodeEquivs(); const CodeGenInstruction *findNodeEquiv(Record *N) const; - Error importRulePredicates(RuleMatcher &M, ArrayRef<Init *> Predicates) const; + Error importRulePredicates(RuleMatcher &M, ArrayRef<Init *> Predicates); Expected<InstructionMatcher &> createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher, const TreePatternNode *Src) const; @@ -1287,6 +1303,8 @@ private: /// Analyze pattern \p P, returning a matcher for it if possible. /// Otherwise, return an Error explaining why we don't support it. Expected<RuleMatcher> runOnPattern(const PatternToMatch &P); + + void declareSubtargetFeature(Record *Predicate); }; void GlobalISelEmitter::gatherNodeEquivs() { @@ -1315,10 +1333,13 @@ GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK) Error GlobalISelEmitter::importRulePredicates(RuleMatcher &M, - ArrayRef<Init *> Predicates) const { - if (!Predicates.empty()) - return failedImport("Pattern has a rule predicate (" + - explainRulePredicates(Predicates) + ")"); + ArrayRef<Init *> Predicates) { + for (const Init *Predicate : Predicates) { + const DefInit *PredicateDef = static_cast<const DefInit *>(Predicate); + declareSubtargetFeature(PredicateDef->getDef()); + M.addRequiredFeature(PredicateDef->getDef()); + } + return Error::success(); } @@ -1725,6 +1746,13 @@ void GlobalISelEmitter::run(raw_ostream &OS) { for (const auto &Rule : Rules) MaxTemporaries = std::max(MaxTemporaries, Rule.countTemporaryOperands()); + OS << "#ifdef GET_GLOBALISEL_PREDICATE_BITSET\n" + << "const unsigned MAX_SUBTARGET_PREDICATES = " << SubtargetFeatures.size() + << ";\n" + << "using PredicateBitset = " + "PredicateBitsetImpl<MAX_SUBTARGET_PREDICATES>;\n" + << "#endif // ifdef GET_GLOBALISEL_PREDICATE_BITSET\n\n"; + OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_DECL\n"; for (unsigned I = 0; I < MaxTemporaries; ++I) OS << " mutable MachineOperand TempOp" << I << ";\n"; @@ -1735,14 +1763,21 @@ void GlobalISelEmitter::run(raw_ostream &OS) { OS << ", TempOp" << I << "(MachineOperand::CreatePlaceholder())\n"; OS << "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n\n"; - OS << "#ifdef GET_GLOBALISEL_IMPL\n" - << "bool " << Target.getName() + OS << "#ifdef GET_GLOBALISEL_IMPL\n"; + SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, + OS); + SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, OS); + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Target.getName(), "InstructionSelector", "computeAvailableFeatures", + SubtargetFeatures, OS); + + OS << "bool " << Target.getName() << "InstructionSelector::selectImpl(MachineInstr &I) const {\n" << " MachineFunction &MF = *I.getParent()->getParent();\n" << " const MachineRegisterInfo &MRI = MF.getRegInfo();\n"; for (auto &Rule : Rules) { - Rule.emit(OS); + Rule.emit(OS, SubtargetFeatures); ++NumPatternEmitted; } @@ -1751,6 +1786,12 @@ void GlobalISelEmitter::run(raw_ostream &OS) { << "#endif // ifdef GET_GLOBALISEL_IMPL\n"; } +void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) { + if (SubtargetFeatures.count(Predicate) == 0) + SubtargetFeatures.emplace( + Predicate, SubtargetFeatureInfo(Predicate, SubtargetFeatures.size())); +} + } // end anonymous namespace //===----------------------------------------------------------------------===// |