summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen/GlobalISelEmitter.cpp
diff options
context:
space:
mode:
authorDaniel Sanders <daniel_l_sanders@apple.com>2017-04-21 10:27:20 +0000
committerDaniel Sanders <daniel_l_sanders@apple.com>2017-04-21 10:27:20 +0000
commit279d03527e59bb6bcfaa04417e4d3210fb9f853b (patch)
tree1fb95db9704cb3ec3b1bd4e245f8e5d9fd3d695d /llvm/utils/TableGen/GlobalISelEmitter.cpp
parent41b4333066b1b37ad51dc751630aa8c983cfb003 (diff)
downloadbcm5719-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.cpp91
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
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud