]> granicus.if.org Git - llvm/commitdiff
[globalisel][tablegen] Revise API for ComplexPattern operands to improve flexibility.
authorDaniel Sanders <daniel_l_sanders@apple.com>
Sat, 22 Apr 2017 15:11:04 +0000 (15:11 +0000)
committerDaniel Sanders <daniel_l_sanders@apple.com>
Sat, 22 Apr 2017 15:11:04 +0000 (15:11 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301079 91177308-0d34-0410-b5e6-96231b3b80d8

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

index c6394e20efeeaae67d59681c83b66195bbaf4055..899563acc330b734c7ed0fe90aa3386555e4f6e8 100644 (file)
 #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
index 81b43126adeba7899e61c19d3f99af1e65ede466..e1635408829684334a24ddd5f1da1ab9492a3c51 100644 (file)
@@ -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:
index fa1a424b589542e8a090a0c6eca0bae51fca7004..fd2ebca86d607356c10eebd2ed3384baaacf5e92 100644 (file)
@@ -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)
index 6da174a536666ca3da43270d32743f1f0cf61838..b6624b88fe231aeba61f47aa8ed8aa7446287bf0 100644 (file)
@@ -925,9 +925,6 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI,
        << CmpInst::getPredicateName(Pred) << ')';
     break;
   }
-  case MachineOperand::MO_Placeholder:
-    OS << "<placeholder>";
-    break;
   }
 }
 
index 4bd5fbfe38e6e1d173a604c2e5528e91a1bd4d95..1faf6292a9c1a64bad322bc8905d117a6f143476 100644 (file)
@@ -287,8 +287,6 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) 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 MachineOperand &MO) {
     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 &OS, ModuleSlotTracker &MST,
        << CmpInst::getPredicateName(Pred) << '>';
     break;
   }
-  case MachineOperand::MO_Placeholder:
-    OS << "<placeholder>";
-    break;
   }
   if (unsigned TF = getTargetFlags())
     OS << "[TF=" << TF << ']';
index 16be4432b160707e4bbfb8fa74572cbd32488ca9..c44daf306ea937ddd0cf992f5872328e42f668e9 100644 (file)
@@ -693,11 +693,11 @@ def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
 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>
index d20438237626ab5511e6756fc07f70a6e147ab01..b0e0e3eb4ba7dd27277b38bf9c9b92d21df9fee0 100644 (file)
@@ -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(MachineInstr &I) const {
 /// 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::selectArithImmed(
   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::selectArithImmed(
     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 {
index e0aecff2633b4fddf1111e1f8fea508a7e22ab8b..78a9144bd321407764cf682592c54324e2f99f99 100644 (file)
@@ -661,7 +661,6 @@ static bool IsAnAddressOperand(const MachineOperand &MO) {
     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");
index 375af14e8762d145acbbed929a7654b298092d28..c3ce530d431edcf4eb1c369f7ffbed138f1e9c37 100644 (file)
@@ -22,7 +22,7 @@ def complex : Operand<i32>, ComplexPattern<i32, 2, "SelectComplexPattern", []> {
   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 GPR32:$src2, GPR32:$src1),
 // 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);
index 488bf8d312bcf29cbbfb902f85286cec46387a81..b637114a2e03b79b38119d6779a3557004340211 100644 (file)
@@ -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";