[llvm] r301079 - [globalisel][tablegen] Revise API for ComplexPattern operands to improve flexibility.

Daniel Sanders via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 22 08:11:04 PDT 2017


Author: dsanders
Date: Sat Apr 22 10:11:04 2017
New Revision: 301079

URL: http://llvm.org/viewvc/llvm-project?rev=301079&view=rev
Log:
[globalisel][tablegen] Revise API for ComplexPattern operands to improve flexibility.

Summary:
Some targets need to be able to do more complex rendering than just adding an
operand or two to an instruction. For example, it may need to insert an
instruction to extract a subreg first, or it may need to perform an operation
on the operand.

In SelectionDAG, targets would create SDNode's to achieve the desired effect
during the complex pattern predicate. This worked because SelectionDAG had a
form of garbage collection that would take care of SDNode's that were created
but not used due to a later predicate rejecting a match. This doesn't translate
well to GlobalISel and the churn was wasteful.

The API changes in this patch enable GlobalISel to accomplish the same thing
without the waste. The API is now:
	InstructionSelector::OptionalComplexRendererFn selectArithImmed(MachineOperand &Root) const;
where Root is the root of the match. The return value can be omitted to
indicate that the predicate failed to match, or a function with the signature
ComplexRendererFn can be returned. For example:
	return OptionalComplexRendererFn(
	       [=](MachineInstrBuilder &MIB) { MIB.addImm(Immed).addImm(ShVal); });
adds two immediate operands to the rendered instruction. Immed and ShVal are
captured from the predicate function.

As an added bonus, this also reduces the amount of information we need to
provide to GIComplexOperandMatcher.

Depends on D31418

Reviewers: aditya_nandakumar, t.p.northover, qcolombet, rovka, ab, javed.absar

Reviewed By: ab

Subscribers: dberris, kristof.beyls, igorb, llvm-commits

Differential Revision: https://reviews.llvm.org/D31761

Modified:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
    llvm/trunk/include/llvm/CodeGen/MachineOperand.h
    llvm/trunk/include/llvm/Target/GlobalISel/Target.td
    llvm/trunk/lib/CodeGen/MIRPrinter.cpp
    llvm/trunk/lib/CodeGen/MachineInstr.cpp
    llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td
    llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
    llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp
    llvm/trunk/test/TableGen/GlobalISelEmitter.td
    llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h Sat Apr 22 10:11:04 2017
@@ -19,9 +19,11 @@
 #include "llvm/ADT/Optional.h"
 #include <cstdint>
 #include <bitset>
+#include <functional>
 
 namespace llvm {
 class MachineInstr;
+class MachineInstrBuilder;
 class MachineFunction;
 class MachineOperand;
 class MachineRegisterInfo;
@@ -76,6 +78,8 @@ public:
   virtual bool select(MachineInstr &I) const = 0;
 
 protected:
+  typedef std::function<void(MachineInstrBuilder &)> ComplexRendererFn;
+
   InstructionSelector();
 
   /// Mutate the newly-selected instruction \p I to constrain its (possibly

Modified: llvm/trunk/include/llvm/CodeGen/MachineOperand.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineOperand.h?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineOperand.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineOperand.h Sat Apr 22 10:11:04 2017
@@ -65,7 +65,6 @@ public:
     MO_CFIIndex,          ///< MCCFIInstruction index.
     MO_IntrinsicID,       ///< Intrinsic ID for ISel
     MO_Predicate,         ///< Generic predicate for ISel
-    MO_Placeholder,       ///< Placeholder for GlobalISel ComplexPattern result.
   };
 
 private:
@@ -768,11 +767,6 @@ public:
     return Op;
   }
 
-  static MachineOperand CreatePlaceholder() {
-    MachineOperand Op(MachineOperand::MO_Placeholder);
-    return Op;
-  }
-
   friend class MachineInstr;
   friend class MachineRegisterInfo;
 private:

Modified: llvm/trunk/include/llvm/Target/GlobalISel/Target.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/GlobalISel/Target.td?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/GlobalISel/Target.td (original)
+++ llvm/trunk/include/llvm/Target/GlobalISel/Target.td Sat Apr 22 10:11:04 2017
@@ -30,21 +30,13 @@ def s64 : LLT;
 // Definitions that inherit from this may also inherit from
 // GIComplexPatternEquiv to enable the import of SelectionDAG patterns involving
 // those ComplexPatterns.
-class GIComplexOperandMatcher<LLT type, dag operands, string matcherfn> {
+class GIComplexOperandMatcher<LLT type, string matcherfn> {
   // The expected type of the root of the match.
   //
   // TODO: We should probably support, any-type, any-scalar, and multiple types
   //       in the future.
   LLT Type = type;
 
-  // The operands that result from a successful match
-  // Should be of the form '(ops ty1, ty2, ...)' where ty1/ty2 are definitions
-  // that inherit from Operand.
-  //
-  // FIXME: Which definition is used for ty1/ty2 doesn't actually matter at the
-  //        moment. Only the number of operands is used.
-  dag Operands = operands;
-
   // The function that determines whether the operand matches. It should be of
   // the form:
   //   bool select(const MatchOperand &Root, MatchOperand &Result1)

Modified: llvm/trunk/lib/CodeGen/MIRPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MIRPrinter.cpp?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MIRPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/MIRPrinter.cpp Sat Apr 22 10:11:04 2017
@@ -925,9 +925,6 @@ void MIPrinter::print(const MachineOpera
        << CmpInst::getPredicateName(Pred) << ')';
     break;
   }
-  case MachineOperand::MO_Placeholder:
-    OS << "<placeholder>";
-    break;
   }
 }
 

Modified: llvm/trunk/lib/CodeGen/MachineInstr.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineInstr.cpp?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineInstr.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineInstr.cpp Sat Apr 22 10:11:04 2017
@@ -287,8 +287,6 @@ bool MachineOperand::isIdenticalTo(const
     return getIntrinsicID() == Other.getIntrinsicID();
   case MachineOperand::MO_Predicate:
     return getPredicate() == Other.getPredicate();
-  case MachineOperand::MO_Placeholder:
-    return true;
   }
   llvm_unreachable("Invalid machine operand type");
 }
@@ -337,8 +335,6 @@ hash_code llvm::hash_value(const Machine
     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID());
   case MachineOperand::MO_Predicate:
     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate());
-  case MachineOperand::MO_Placeholder:
-    return hash_combine();
   }
   llvm_unreachable("Invalid machine operand type");
 }
@@ -515,9 +511,6 @@ void MachineOperand::print(raw_ostream &
        << CmpInst::getPredicateName(Pred) << '>';
     break;
   }
-  case MachineOperand::MO_Placeholder:
-    OS << "<placeholder>";
-    break;
   }
   if (unsigned TF = getTargetFlags())
     OS << "[TF=" << TF << ']';

Modified: llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstrFormats.td Sat Apr 22 10:11:04 2017
@@ -693,11 +693,11 @@ def addsub_shifted_imm32_neg : addsub_sh
 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
 
 def gi_addsub_shifted_imm32 :
-    GIComplexOperandMatcher<s32, (ops i32imm, i32imm), "selectArithImmed">,
+    GIComplexOperandMatcher<s32, "selectArithImmed">,
     GIComplexPatternEquiv<addsub_shifted_imm32>;
 
 def gi_addsub_shifted_imm64 :
-    GIComplexOperandMatcher<s64, (ops i32imm, i32imm), "selectArithImmed">,
+    GIComplexOperandMatcher<s64, "selectArithImmed">,
     GIComplexPatternEquiv<addsub_shifted_imm64>;
 
 class neg_addsub_shifted_imm<ValueType Ty>

Modified: llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp Sat Apr 22 10:11:04 2017
@@ -67,8 +67,7 @@ private:
   bool selectCompareBranch(MachineInstr &I, MachineFunction &MF,
                            MachineRegisterInfo &MRI) const;
 
-  bool selectArithImmed(MachineOperand &Root, MachineOperand &Result1,
-                        MachineOperand &Result2) const;
+  ComplexRendererFn selectArithImmed(MachineOperand &Root) const;
 
   const AArch64TargetMachine &TM;
   const AArch64Subtarget &STI;
@@ -1329,9 +1328,8 @@ bool AArch64InstructionSelector::select(
 /// SelectArithImmed - Select an immediate value that can be represented as
 /// a 12-bit value shifted left by either 0 or 12.  If so, return true with
 /// Val set to the 12-bit value and Shift set to the shifter operand.
-bool AArch64InstructionSelector::selectArithImmed(
-    MachineOperand &Root, MachineOperand &Result1,
-    MachineOperand &Result2) const {
+InstructionSelector::ComplexRendererFn
+AArch64InstructionSelector::selectArithImmed(MachineOperand &Root) const {
   MachineInstr &MI = *Root.getParent();
   MachineBasicBlock &MBB = *MI.getParent();
   MachineFunction &MF = *MBB.getParent();
@@ -1350,13 +1348,13 @@ bool AArch64InstructionSelector::selectA
   else if (Root.isReg()) {
     MachineInstr *Def = MRI.getVRegDef(Root.getReg());
     if (Def->getOpcode() != TargetOpcode::G_CONSTANT)
-      return false;
+      return nullptr;
     MachineOperand &Op1 = Def->getOperand(1);
     if (!Op1.isCImm() || Op1.getCImm()->getBitWidth() > 64)
-      return false;
+      return nullptr;
     Immed = Op1.getCImm()->getZExtValue();
   } else
-    return false;
+    return nullptr;
 
   unsigned ShiftAmt;
 
@@ -1366,14 +1364,10 @@ bool AArch64InstructionSelector::selectA
     ShiftAmt = 12;
     Immed = Immed >> 12;
   } else
-    return false;
+    return nullptr;
 
   unsigned ShVal = AArch64_AM::getShifterImm(AArch64_AM::LSL, ShiftAmt);
-  Result1.ChangeToImmediate(Immed);
-  Result1.clearParent();
-  Result2.ChangeToImmediate(ShVal);
-  Result2.clearParent();
-  return true;
+  return [=](MachineInstrBuilder &MIB) { MIB.addImm(Immed).addImm(ShVal); };
 }
 
 namespace llvm {

Modified: llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp Sat Apr 22 10:11:04 2017
@@ -661,7 +661,6 @@ static bool IsAnAddressOperand(const Mac
     return false;
   case MachineOperand::MO_IntrinsicID:
   case MachineOperand::MO_Predicate:
-  case MachineOperand::MO_Placeholder:
     llvm_unreachable("should not exist post-isel");
   }
   llvm_unreachable("unhandled machine operand type");

Modified: llvm/trunk/test/TableGen/GlobalISelEmitter.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/GlobalISelEmitter.td?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/GlobalISelEmitter.td (original)
+++ llvm/trunk/test/TableGen/GlobalISelEmitter.td Sat Apr 22 10:11:04 2017
@@ -22,7 +22,7 @@ def complex : Operand<i32>, ComplexPatte
   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))>;
@@ -72,17 +72,15 @@ def HasB : Predicate<"Subtarget->hasB()"
 // 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);
@@ -263,13 +261,12 @@ def MUL : I<(outs GPR32:$dst), (ins GPR3
 // 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);

Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=301079&r1=301078&r2=301079&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Sat Apr 22 10:11:04 2017
@@ -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(c
   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::importChildMatc
         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::importExplicitU
         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
 
   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 << "#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";




More information about the llvm-commits mailing list