diff options
author | Daniel Sanders <daniel_l_sanders@apple.com> | 2017-04-21 15:59:56 +0000 |
---|---|---|
committer | Daniel Sanders <daniel_l_sanders@apple.com> | 2017-04-21 15:59:56 +0000 |
commit | e7b0d660808ef8a68a90da4c1b1234568f133219 (patch) | |
tree | f4509077e0deecb74bab70f011d11d5b3b58457e /llvm/utils | |
parent | 7af078847cd287256213b2db061a4e14eae6bb5d (diff) | |
download | bcm5719-llvm-e7b0d660808ef8a68a90da4c1b1234568f133219.tar.gz bcm5719-llvm-e7b0d660808ef8a68a90da4c1b1234568f133219.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: 300993
Diffstat (limited to 'llvm/utils')
-rw-r--r-- | llvm/utils/TableGen/AsmMatcherEmitter.cpp | 2 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeEmitterGen.cpp | 2 | ||||
-rw-r--r-- | llvm/utils/TableGen/GlobalISelEmitter.cpp | 91 | ||||
-rw-r--r-- | llvm/utils/TableGen/SubtargetFeatureInfo.cpp | 32 | ||||
-rw-r--r-- | llvm/utils/TableGen/SubtargetFeatureInfo.h | 40 | ||||
-rw-r--r-- | llvm/utils/TableGen/Types.cpp | 1 |
6 files changed, 141 insertions, 27 deletions
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp index 3947d0220ed..a5c2ea6c7ac 100644 --- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -2861,7 +2861,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { emitValidateOperandClass(Info, OS); // Emit the available features compute function. - SubtargetFeatureInfo::emitComputeAvailableFeatures( + SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( Info.Target.getName(), ClassName, "ComputeAvailableFeatures", Info.SubtargetFeatures, OS); diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index f34c0ded0a3..565235d8214 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -336,7 +336,7 @@ void CodeEmitterGen::run(raw_ostream &o) { o << "#endif // NDEBUG\n"; // Emit the available features compute function. - SubtargetFeatureInfo::emitComputeAvailableFeatures( + SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( Target.getName(), "MCCodeEmitter", "computeAvailableFeatures", SubtargetFeatures, o); diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 7acc65e349e..0c77167d4cc 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 = " + "llvm::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 //===----------------------------------------------------------------------===// diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp index 72a556182b1..96418dc77d5 100644 --- a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp +++ b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp @@ -59,6 +59,20 @@ void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( OS << "};\n\n"; } +void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration( + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, + raw_ostream &OS) { + OS << "// Bits for subtarget features that participate in " + << "instruction matching.\n"; + OS << "enum SubtargetFeatureBits : " + << getMinimalTypeForRange(SubtargetFeatures.size()) << " {\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " " << SFI.getEnumBitName() << " = " << SFI.Index << ",\n"; + } + OS << "};\n\n"; +} + void SubtargetFeatureInfo::emitNameTable( std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, raw_ostream &OS) { @@ -90,6 +104,24 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures( StringRef TargetName, StringRef ClassName, StringRef FuncName, std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, raw_ostream &OS) { + OS << "PredicateBitset " << TargetName << ClassName << "::\n" + << FuncName << "(const MachineFunction *MF, const " << TargetName + << "Subtarget *Subtarget) const {\n"; + OS << " PredicateBitset Features;\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + + OS << " if (" << SFI.TheDef->getValueAsString("CondString") << ")\n"; + OS << " Features[" << SFI.getEnumBitName() << "] = 1;\n"; + } + OS << " return Features;\n"; + OS << "}\n\n"; +} + +void SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( + StringRef TargetName, StringRef ClassName, StringRef FuncName, + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, + raw_ostream &OS) { OS << "uint64_t " << TargetName << ClassName << "::\n" << FuncName << "(const FeatureBitset& FB) const {\n"; OS << " uint64_t Features = 0;\n"; diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.h b/llvm/utils/TableGen/SubtargetFeatureInfo.h index 99f380f2a1d..bbaf4525960 100644 --- a/llvm/utils/TableGen/SubtargetFeatureInfo.h +++ b/llvm/utils/TableGen/SubtargetFeatureInfo.h @@ -37,16 +37,34 @@ struct SubtargetFeatureInfo { return "Feature_" + TheDef->getName().str(); } + /// \brief The name of the enumerated constant identifying the bitnumber for + /// this feature. + std::string getEnumBitName() const { + return "Feature_" + TheDef->getName().str() + "Bit"; + } + void dump() const; static std::vector<std::pair<Record *, SubtargetFeatureInfo>> getAll(const RecordKeeper &Records); /// Emit the subtarget feature flag definitions. + /// + /// This version emits the bit value for the feature and is therefore limited + /// to 64 feature bits. static void emitSubtargetFeatureFlagEnumeration( std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, raw_ostream &OS); + /// Emit the subtarget feature flag definitions. + /// + /// This version emits the bit index for the feature and can therefore support + /// more than 64 feature bits. + static void emitSubtargetFeatureBitEnumeration( + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> + &SubtargetFeatures, + raw_ostream &OS); + static void emitNameTable(std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, raw_ostream &OS); @@ -54,6 +72,9 @@ struct SubtargetFeatureInfo { /// Emit the function to compute the list of available features given a /// subtarget. /// + /// This version is used for subtarget features defined using Predicate<> + /// and supports more than 64 feature bits. + /// /// \param TargetName The name of the target as used in class prefixes (e.g. /// <TargetName>Subtarget) /// \param ClassName The name of the class (without the <Target> prefix) @@ -66,6 +87,25 @@ struct SubtargetFeatureInfo { std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures, raw_ostream &OS); + + /// Emit the function to compute the list of available features given a + /// subtarget. + /// + /// This version is used for subtarget features defined using + /// AssemblerPredicate<> and supports up to 64 feature bits. + /// + /// \param TargetName The name of the target as used in class prefixes (e.g. + /// <TargetName>Subtarget) + /// \param ClassName The name of the class (without the <Target> prefix) + /// that will contain the generated functions. + /// \param FuncName The name of the function to emit. + /// \param SubtargetFeatures A map of TableGen records to the + /// SubtargetFeatureInfo equivalent. + static void emitComputeAssemblerAvailableFeatures( + StringRef TargetName, StringRef ClassName, StringRef FuncName, + std::map<Record *, SubtargetFeatureInfo, LessRecordByID> + &SubtargetFeatures, + raw_ostream &OS); }; } // end namespace llvm diff --git a/llvm/utils/TableGen/Types.cpp b/llvm/utils/TableGen/Types.cpp index 35458296f8f..04d9e40f674 100644 --- a/llvm/utils/TableGen/Types.cpp +++ b/llvm/utils/TableGen/Types.cpp @@ -40,5 +40,6 @@ const char *llvm::getMinimalTypeForEnumBitfield(uint64_t Size) { uint64_t MaxIndex = Size; if (MaxIndex > 0) MaxIndex--; + assert(MaxIndex <= 64 && "Too many bits"); return getMinimalTypeForRange(1ULL << MaxIndex); } |