summaryrefslogtreecommitdiff
path: root/utils/TableGen/GlobalISelEmitter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-26 19:45:00 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-26 19:45:00 +0000
commit12f3ca4cdb95b193af905a00e722a4dcb40b3de3 (patch)
treeae1a7fcfc24a8d4b23206c57121c3f361d4b7f84 /utils/TableGen/GlobalISelEmitter.cpp
parentd99dafe2e4a385dd2a6c76da6d8258deb100657b (diff)
Diffstat (limited to 'utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r--utils/TableGen/GlobalISelEmitter.cpp251
1 files changed, 119 insertions, 132 deletions
diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp
index 7acc65e349ea6..dcf10ab511da7 100644
--- a/utils/TableGen/GlobalISelEmitter.cpp
+++ b/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"
@@ -79,7 +80,7 @@ public:
return;
}
if (Ty.isVector()) {
- OS << "LLT::vector(" << Ty.getNumElements() << ", " << Ty.getSizeInBits()
+ OS << "LLT::vector(" << Ty.getNumElements() << ", " << Ty.getScalarSizeInBits()
<< ")";
return;
}
@@ -90,52 +91,6 @@ public:
};
class InstructionMatcher;
-class OperandPlaceholder {
-private:
- enum PlaceholderKind {
- OP_MatchReference,
- OP_Temporary,
- } Kind;
-
- struct MatchReferenceData {
- InstructionMatcher *InsnMatcher;
- StringRef InsnVarName;
- StringRef SymbolicName;
- };
-
- struct TemporaryData {
- unsigned OpIdx;
- };
-
- union {
- struct MatchReferenceData MatchReference;
- struct TemporaryData Temporary;
- };
-
- OperandPlaceholder(PlaceholderKind Kind) : Kind(Kind) {}
-
-public:
- ~OperandPlaceholder() {}
-
- static OperandPlaceholder
- CreateMatchReference(InstructionMatcher *InsnMatcher,
- StringRef InsnVarName, StringRef SymbolicName) {
- OperandPlaceholder Result(OP_MatchReference);
- Result.MatchReference.InsnMatcher = InsnMatcher;
- Result.MatchReference.InsnVarName = InsnVarName;
- Result.MatchReference.SymbolicName = SymbolicName;
- return Result;
- }
-
- static OperandPlaceholder CreateTemporary(unsigned OpIdx) {
- OperandPlaceholder Result(OP_Temporary);
- Result.Temporary.OpIdx = OpIdx;
- return Result;
- }
-
- void emitCxxValueExpr(raw_ostream &OS) const;
-};
-
/// Convert an MVT to an equivalent LLT if possible, or the invalid LLT() for
/// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...).
static Optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
@@ -161,20 +116,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 +179,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 +188,7 @@ public:
RuleMatcher &operator=(RuleMatcher &&Other) = default;
InstructionMatcher &addInstructionMatcher();
+ void addRequiredFeature(Record *Feature);
template <class Kind, class... Args> Kind &addAction(Args &&... args);
@@ -255,7 +199,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.
///
@@ -264,7 +210,10 @@ public:
/// Report the maximum number of temporary operands needed by the rule
/// matcher.
- unsigned countTemporaryOperands() const;
+ unsigned countRendererFns() const;
+
+ // FIXME: Remove this as soon as possible
+ InstructionMatcher &insnmatcher_front() const { return *Matchers.front(); }
};
template <class PredicateTy> class PredicateListMatcher {
@@ -369,7 +318,7 @@ public:
/// Report the maximum number of temporary operands needed by the predicate
/// matcher.
- virtual unsigned countTemporaryOperands() const { return 0; }
+ virtual unsigned countRendererFns() const { return 0; }
};
/// Generates code to check that an operand is a particular LLT.
@@ -399,10 +348,6 @@ protected:
const OperandMatcher &Operand;
const Record &TheDef;
- unsigned getNumOperands() const {
- return TheDef.getValueAsDag("Operands")->getNumArgs();
- }
-
unsigned getAllocatedTemporariesBaseID() const;
public:
@@ -417,17 +362,13 @@ public:
void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
StringRef OperandExpr) const override {
- OS << TheDef.getValueAsString("MatcherFn") << "(" << OperandExpr;
- for (unsigned I = 0; I < getNumOperands(); ++I) {
- OS << ", ";
- OperandPlaceholder::CreateTemporary(getAllocatedTemporariesBaseID() + I)
- .emitCxxValueExpr(OS);
- }
- OS << ")";
+ unsigned ID = getAllocatedTemporariesBaseID();
+ OS << "(Renderer" << ID << " = " << TheDef.getValueAsString("MatcherFn")
+ << "(" << OperandExpr << "))";
}
- unsigned countTemporaryOperands() const override {
- return getNumOperands();
+ unsigned countRendererFns() const override {
+ return 1;
}
};
@@ -496,7 +437,7 @@ protected:
/// The index of the first temporary variable allocated to this operand. The
/// number of allocated temporaries can be found with
- /// countTemporaryOperands().
+ /// countRendererFns().
unsigned AllocatedTemporariesBaseID;
public:
@@ -577,12 +518,12 @@ public:
/// Report the maximum number of temporary operands needed by the operand
/// matcher.
- unsigned countTemporaryOperands() const {
+ unsigned countRendererFns() const {
return std::accumulate(
predicates().begin(), predicates().end(), 0,
[](unsigned A,
const std::unique_ptr<OperandPredicateMatcher> &Predicate) {
- return A + Predicate->countTemporaryOperands();
+ return A + Predicate->countRendererFns();
});
}
@@ -631,7 +572,7 @@ public:
/// Report the maximum number of temporary operands needed by the predicate
/// matcher.
- virtual unsigned countTemporaryOperands() const { return 0; }
+ virtual unsigned countRendererFns() const { return 0; }
};
/// Generates code to check the opcode of an instruction.
@@ -788,17 +729,17 @@ public:
/// Report the maximum number of temporary operands needed by the instruction
/// matcher.
- unsigned countTemporaryOperands() const {
+ unsigned countRendererFns() const {
return std::accumulate(predicates().begin(), predicates().end(), 0,
[](unsigned A,
const std::unique_ptr<InstructionPredicateMatcher>
&Predicate) {
- return A + Predicate->countTemporaryOperands();
+ return A + Predicate->countRendererFns();
}) +
std::accumulate(
Operands.begin(), Operands.end(), 0,
[](unsigned A, const std::unique_ptr<OperandMatcher> &Operand) {
- return A + Operand->countTemporaryOperands();
+ return A + Operand->countRendererFns();
});
}
};
@@ -853,18 +794,6 @@ public:
};
//===- Actions ------------------------------------------------------------===//
-void OperandPlaceholder::emitCxxValueExpr(raw_ostream &OS) const {
- switch (Kind) {
- case OP_MatchReference:
- OS << MatchReference.InsnMatcher->getOperand(MatchReference.SymbolicName)
- .getOperandExpr(MatchReference.InsnVarName);
- break;
- case OP_Temporary:
- OS << "TempOp" << Temporary.OpIdx;
- break;
- }
-}
-
class OperandRenderer {
public:
enum RendererKind { OR_Copy, OR_Imm, OR_Register, OR_ComplexPattern };
@@ -950,31 +879,33 @@ public:
}
};
+/// Adds operands by calling a renderer function supplied by the ComplexPattern
+/// matcher function.
class RenderComplexPatternOperand : public OperandRenderer {
private:
const Record &TheDef;
- std::vector<OperandPlaceholder> Sources;
+ /// The name of the operand.
+ const StringRef SymbolicName;
+ /// The renderer number. This must be unique within a rule since it's used to
+ /// identify a temporary variable to hold the renderer function.
+ unsigned RendererID;
unsigned getNumOperands() const {
return TheDef.getValueAsDag("Operands")->getNumArgs();
}
public:
- RenderComplexPatternOperand(const Record &TheDef,
- const ArrayRef<OperandPlaceholder> Sources)
- : OperandRenderer(OR_ComplexPattern), TheDef(TheDef), Sources(Sources) {}
+ RenderComplexPatternOperand(const Record &TheDef, StringRef SymbolicName,
+ unsigned RendererID)
+ : OperandRenderer(OR_ComplexPattern), TheDef(TheDef),
+ SymbolicName(SymbolicName), RendererID(RendererID) {}
static bool classof(const OperandRenderer *R) {
return R->getKind() == OR_ComplexPattern;
}
void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
- assert(Sources.size() == getNumOperands() && "Inconsistent number of operands");
- for (const auto &Source : Sources) {
- OS << "MIB.add(";
- Source.emitCxxValueExpr(OS);
- OS << ");\n";
- }
+ OS << "Renderer" << RendererID << "(MIB);\n";
}
};
@@ -1022,8 +953,9 @@ private:
bool canMutate() const {
for (const auto &Renderer : enumerate(OperandRenderers)) {
if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.value())) {
- if (Matched.getOperand(Copy->getSymbolicName()).getOperandIndex() !=
- Renderer.index())
+ const OperandMatcher &OM = Matched.getOperand(Copy->getSymbolicName());
+ if (&Matched != &OM.getInstructionMatcher() ||
+ OM.getOperandIndex() != Renderer.index())
return false;
} else
return false;
@@ -1092,6 +1024,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 +1071,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 +1087,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");
@@ -1235,11 +1188,11 @@ bool RuleMatcher::isHigherPriorityThan(const RuleMatcher &B) const {
return false;
}
-unsigned RuleMatcher::countTemporaryOperands() const {
+unsigned RuleMatcher::countRendererFns() const {
return std::accumulate(
Matchers.begin(), Matchers.end(), 0,
[](unsigned A, const std::unique_ptr<InstructionMatcher> &Matcher) {
- return A + Matcher->countTemporaryOperands();
+ return A + Matcher->countRendererFns();
});
}
@@ -1264,10 +1217,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 +1243,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 +1273,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();
}
@@ -1423,6 +1384,12 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher,
return Error::success();
}
+ if (ChildRec->isSubClassOf("RegisterOperand")) {
+ OM.addPredicate<RegisterBankOperandMatcher>(
+ Target.getRegisterClass(ChildRec->getValueAsDef("RegClass")));
+ return Error::success();
+ }
+
// Check for ComplexPattern's.
if (ChildRec->isSubClassOf("ComplexPattern")) {
const auto &ComplexPattern = ComplexPatternEquivs.find(ChildRec);
@@ -1430,9 +1397,9 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher,
return failedImport("SelectionDAG ComplexPattern (" +
ChildRec->getName() + ") not mapped to GlobalISel");
- const auto &Predicate = OM.addPredicate<ComplexPatternOperandMatcher>(
- OM, *ComplexPattern->second);
- TempOpIdx += Predicate.countTemporaryOperands();
+ OM.addPredicate<ComplexPatternOperandMatcher>(OM,
+ *ComplexPattern->second);
+ TempOpIdx++;
return Error::success();
}
@@ -1486,7 +1453,8 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
return Error::success();
}
- if (ChildRec->isSubClassOf("RegisterClass")) {
+ if (ChildRec->isSubClassOf("RegisterClass") ||
+ ChildRec->isSubClassOf("RegisterOperand")) {
DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstChild->getName());
return Error::success();
}
@@ -1497,13 +1465,10 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
return failedImport(
"SelectionDAG ComplexPattern not mapped to GlobalISel");
- SmallVector<OperandPlaceholder, 2> RenderedOperands;
const OperandMatcher &OM = InsnMatcher.getOperand(DstChild->getName());
- for (unsigned I = 0; I < OM.countTemporaryOperands(); ++I)
- RenderedOperands.push_back(OperandPlaceholder::CreateTemporary(
- OM.getAllocatedTemporariesBaseID() + I));
DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
- *ComplexPattern->second, RenderedOperands);
+ *ComplexPattern->second, DstChild->getName(),
+ OM.getAllocatedTemporariesBaseID());
return Error::success();
}
@@ -1656,6 +1621,8 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
const auto &DstIOperand = DstI.Operands[OpIdx];
Record *DstIOpRec = DstIOperand.Rec;
+ if (DstIOpRec->isSubClassOf("RegisterOperand"))
+ DstIOpRec = DstIOpRec->getValueAsDef("RegClass");
if (!DstIOpRec->isSubClassOf("RegisterClass"))
return failedImport("Dst MI def isn't a register class");
@@ -1723,26 +1690,40 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
unsigned MaxTemporaries = 0;
for (const auto &Rule : Rules)
- MaxTemporaries = std::max(MaxTemporaries, Rule.countTemporaryOperands());
+ MaxTemporaries = std::max(MaxTemporaries, Rule.countRendererFns());
+
+ 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";
+ OS << " mutable ComplexRendererFn Renderer" << I << ";\n";
OS << "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL\n\n";
OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n";
for (unsigned I = 0; I < MaxTemporaries; ++I)
- OS << ", TempOp" << I << "(MachineOperand::CreatePlaceholder())\n";
+ OS << ", Renderer" << I << "(nullptr)\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 +1732,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
//===----------------------------------------------------------------------===//