let MIOperandInfo = (ops i32imm, i32imm);
}
def gi_complex :
- GIComplexOperandMatcher<s32, (ops i32imm, i32imm), "selectComplexPattern">,
+ GIComplexOperandMatcher<s32, "selectComplexPattern">,
GIComplexPatternEquiv<complex>;
def m1 : OperandWithDefaultOps <i32, (ops (i32 -1))>;
// CHECK-NEXT: ((/* src1 */ (MRI.getType(MI0.getOperand(1).getReg()) == (LLT::scalar(32))) &&
// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(MI0.getOperand(1).getReg(), MRI, TRI))))) &&
// CHECK-NEXT: ((/* src2 */ (MRI.getType(MI0.getOperand(2).getReg()) == (LLT::scalar(32))) &&
-// CHECK-NEXT: (selectComplexPattern(MI0.getOperand(2), TempOp0, TempOp1)))) &&
+// CHECK-NEXT: ((Renderer0 = selectComplexPattern(MI0.getOperand(2)))))) &&
// CHECK-NEXT: ((/* src3 */ (MRI.getType(MI0.getOperand(3).getReg()) == (LLT::scalar(32))) &&
-// CHECK-NEXT: (selectComplexPattern(MI0.getOperand(3), TempOp2, TempOp3))))) {
+// CHECK-NEXT: ((Renderer1 = selectComplexPattern(MI0.getOperand(3))))))) {
// CHECK-NEXT: // (select:i32 GPR32:i32:$src1, complex:i32:$src2, complex:i32:$src3) => (INSN2:i32 GPR32:i32:$src1, complex:i32:$src3, complex:i32:$src2)
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::INSN2));
// CHECK-NEXT: MIB.add(MI0.getOperand(0)/*dst*/);
// CHECK-NEXT: MIB.add(MI0.getOperand(1)/*src1*/);
-// CHECK-NEXT: MIB.add(TempOp2);
-// CHECK-NEXT: MIB.add(TempOp3);
-// CHECK-NEXT: MIB.add(TempOp0);
-// CHECK-NEXT: MIB.add(TempOp1);
+// CHECK-NEXT: Renderer1(MIB);
+// CHECK-NEXT: Renderer0(MIB);
// CHECK-NEXT: for (const auto *FromMI : {&MI0, })
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
// CHECK-NEXT: MIB.addMemOperand(MMO);
// CHECK-NEXT: ((/* src1 */ (MRI.getType(MI0.getOperand(1).getReg()) == (LLT::scalar(32))) &&
// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(MI0.getOperand(1).getReg(), MRI, TRI))))) &&
// CHECK-NEXT: ((/* src2 */ (MRI.getType(MI0.getOperand(2).getReg()) == (LLT::scalar(32))) &&
-// CHECK-NEXT: (selectComplexPattern(MI0.getOperand(2), TempOp0, TempOp1))))) {
+// CHECK-NEXT: ((Renderer0 = selectComplexPattern(MI0.getOperand(2))))))) {
// CHECK-NEXT: // (sub:i32 GPR32:i32:$src1, complex:i32:$src2) => (INSN1:i32 GPR32:i32:$src1, complex:i32:$src2)
// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::INSN1));
// CHECK-NEXT: MIB.add(MI0.getOperand(0)/*dst*/);
// CHECK-NEXT: MIB.add(MI0.getOperand(1)/*src1*/);
-// CHECK-NEXT: MIB.add(TempOp0);
-// CHECK-NEXT: MIB.add(TempOp1);
+// CHECK-NEXT: Renderer0(MIB);
// CHECK-NEXT: for (const auto *FromMI : {&MI0, })
// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
// CHECK-NEXT: MIB.addMemOperand(MMO);
};
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) {
/// 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 {
/// 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.
const OperandMatcher &Operand;
const Record &TheDef;
- unsigned getNumOperands() const {
- return TheDef.getValueAsDag("Operands")->getNumArgs();
- }
-
unsigned getAllocatedTemporariesBaseID() const;
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;
}
};
/// 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:
/// 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();
});
}
/// 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.
/// 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();
});
}
};
};
//===- 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 };
}
};
+/// 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";
}
};
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();
});
}
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();
}
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();
}
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()
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";