|
@@ -91,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) {
|
|
@@ -256,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 {
|
|
@@ -361,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.
|
|
@@ -391,10 +348,6 @@ protected:
|
|
|
const OperandMatcher &Operand;
|
|
|
const Record &TheDef;
|
|
|
|
|
|
- unsigned getNumOperands() const {
|
|
|
- return TheDef.getValueAsDag("Operands")->getNumArgs();
|
|
|
- }
|
|
|
-
|
|
|
unsigned getAllocatedTemporariesBaseID() const;
|
|
|
|
|
|
public:
|
|
@@ -409,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;
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -488,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:
|
|
@@ -569,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();
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -623,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.
|
|
@@ -780,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();
|
|
|
});
|
|
|
}
|
|
|
};
|
|
@@ -845,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 };
|
|
@@ -942,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";
|
|
|
}
|
|
|
};
|
|
|
|
|
@@ -1249,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();
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -1452,9 +1391,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();
|
|
|
}
|
|
|
|
|
@@ -1519,13 +1458,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();
|
|
|
}
|
|
|
|
|
@@ -1745,7 +1681,7 @@ 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()
|
|
@@ -1756,12 +1692,12 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
|
|
|
|
|
|
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";
|