[llvm] r307133 - [globalisel][tablegen] Added instruction emission to the state-machine-based matcher.

Daniel Sanders via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 5 02:39:34 PDT 2017


Author: dsanders
Date: Wed Jul  5 02:39:33 2017
New Revision: 307133

URL: http://llvm.org/viewvc/llvm-project?rev=307133&view=rev
Log:
[globalisel][tablegen] Added instruction emission to the state-machine-based matcher.

Summary:
This further improves the compile-time regressions that will be caused by a
re-commit of r303259.

Also added included preliminary work in preparation for the multi-insn emitter
since I needed to change the relevant part of the API for this patch anyway.

Depends on D33758

Reviewers: rovka, vitalybuka, ab, t.p.northover, qcolombet, aditya_nandakumar

Reviewed By: ab

Subscribers: kristof.beyls, igorb, llvm-commits

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

Modified:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
    llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
    llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.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=307133&r1=307132&r2=307133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h Wed Jul  5 02:39:33 2017
@@ -116,6 +116,69 @@ enum {
   GIM_Accept,
 };
 
+enum {
+  /// Mutate an instruction
+  /// - NewInsnID - Instruction ID to define
+  /// - OldInsnID - Instruction ID to mutate
+  /// - NewOpcode - The new opcode to use
+  GIR_MutateOpcode,
+  /// Build a new instruction
+  /// - InsnID - Instruction ID to define
+  /// - Opcode - The new opcode to use
+  GIR_BuildMI,
+
+  /// Copy an operand to the specified instruction
+  /// - NewInsnID - Instruction ID to modify
+  /// - OldInsnID - Instruction ID to copy from
+  /// - OpIdx - The operand to copy
+  GIR_Copy,
+  /// Copy an operand to the specified instruction
+  /// - NewInsnID - Instruction ID to modify
+  /// - OldInsnID - Instruction ID to copy from
+  /// - OpIdx - The operand to copy
+  /// - SubRegIdx - The subregister to copy
+  GIR_CopySubReg,
+  /// Add an implicit register def to the specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - RegNum - The register to add
+  GIR_AddImplicitDef,
+  /// Add an implicit register use to the specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - RegNum - The register to add
+  GIR_AddImplicitUse,
+  /// Add an register to the specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - RegNum - The register to add
+  GIR_AddRegister,
+  /// Add an immediate to the specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - Imm - The immediate to add
+  GIR_AddImm,
+  /// Render complex operands to the specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - RendererID - The renderer to call
+  GIR_ComplexRenderer,
+
+  /// Constrain an instruction operand to a register class.
+  /// - InsnID - Instruction ID to modify
+  /// - OpIdx - Operand index
+  /// - RCEnum - Register class enumeration value
+  GIR_ConstrainOperandRC,
+  /// Constrain an instructions operands according to the instruction
+  /// description.
+  /// - InsnID - Instruction ID to modify
+  GIR_ConstrainSelectedInstOperands,
+  /// Merge all memory operands into instruction.
+  /// - InsnID - Instruction ID to modify
+  GIR_MergeMemOperands,
+  /// Erase from parent.
+  /// - InsnID - Instruction ID to erase
+  GIR_EraseFromParent,
+
+  /// A successful emission
+  GIR_Done,
+};
+
 /// Provides the logic to select generic machine instructions.
 class InstructionSelector {
 public:
@@ -137,6 +200,7 @@ public:
 protected:
   using ComplexRendererFn = std::function<void(MachineInstrBuilder &)>;
   using RecordedMIVector = SmallVector<MachineInstr *, 4>;
+  using NewMIVector = SmallVector<MachineInstrBuilder, 4>;
 
   struct MatcherState {
     std::vector<ComplexRendererFn> Renderers;
@@ -166,6 +230,10 @@ protected:
       const int64_t *MatchTable, MachineRegisterInfo &MRI,
       const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI,
       const PredicateBitset &AvailableFeatures) const;
+  void executeEmitTable(NewMIVector &OutMIs, MatcherState &State,
+                        const int64_t *EmitTable, const TargetInstrInfo &TII,
+                        const TargetRegisterInfo &TRI,
+                        const RegisterBankInfo &RBI) const;
 
   /// Constrain a register operand of an instruction \p I to a specified
   /// register class. This could involve inserting COPYs before (for uses) or

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h?rev=307133&r1=307132&r2=307133&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h Wed Jul  5 02:39:33 2017
@@ -161,13 +161,14 @@ bool InstructionSelector::executeMatchTa
     }
 
     case GIM_Accept:
-      DEBUG(dbgs() << "GIM_Accept");
+      DEBUG(dbgs() << "GIM_Accept\n");
       return true;
     default:
       llvm_unreachable("Unexpected command");
     }
   }
 }
+
 } // end namespace llvm
 
 #endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H

Modified: llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp?rev=307133&r1=307132&r2=307133&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/InstructionSelector.cpp Wed Jul  5 02:39:33 2017
@@ -16,7 +16,11 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstr.h"
 #include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/MC/MCInstrDesc.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetRegisterInfo.h"
@@ -31,6 +35,155 @@ InstructionSelector::MatcherState::Match
 
 InstructionSelector::InstructionSelector() = default;
 
+void InstructionSelector::executeEmitTable(NewMIVector &OutMIs,
+                                           MatcherState &State,
+                                           const int64_t *EmitTable,
+                                           const TargetInstrInfo &TII,
+                                           const TargetRegisterInfo &TRI,
+                                           const RegisterBankInfo &RBI) const {
+  const int64_t *Command = EmitTable;
+  while (true) {
+    switch (*Command++) {
+    case GIR_MutateOpcode: {
+      int64_t OldInsnID = *Command++;
+      int64_t NewInsnID = *Command++;
+      int64_t NewOpcode = *Command++;
+      assert((size_t)NewInsnID == OutMIs.size() &&
+             "Expected to store MIs in order");
+      OutMIs.push_back(
+          MachineInstrBuilder(*State.MIs[OldInsnID]->getParent()->getParent(),
+                              State.MIs[OldInsnID]));
+      OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
+      DEBUG(dbgs() << "GIR_MutateOpcode(OutMIs[" << NewInsnID << "], MIs["
+                   << OldInsnID << "], " << NewOpcode << ")\n");
+      break;
+    }
+    case GIR_BuildMI: {
+      int64_t InsnID = *Command++;
+      int64_t Opcode = *Command++;
+      assert((size_t)InsnID == OutMIs.size() &&
+             "Expected to store MIs in order");
+      OutMIs.push_back(BuildMI(*State.MIs[0]->getParent(), State.MIs[0],
+                               State.MIs[0]->getDebugLoc(), TII.get(Opcode)));
+      DEBUG(dbgs() << "GIR_BuildMI(OutMIs[" << InsnID << "], " << Opcode
+                   << ")\n");
+      break;
+    }
+
+    case GIR_Copy: {
+      int64_t NewInsnID = *Command++;
+      int64_t OldInsnID = *Command++;
+      int64_t OpIdx = *Command++;
+      assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
+      OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
+      DEBUG(dbgs() << "GIR_Copy(OutMIs[" << NewInsnID << "], MIs[" << OldInsnID
+                   << "], " << OpIdx << ")\n");
+      break;
+    }
+    case GIR_CopySubReg: {
+      int64_t NewInsnID = *Command++;
+      int64_t OldInsnID = *Command++;
+      int64_t OpIdx = *Command++;
+      int64_t SubRegIdx = *Command++;
+      assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
+      OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
+                               0, SubRegIdx);
+      DEBUG(dbgs() << "GIR_CopySubReg(OutMIs[" << NewInsnID << "], MIs["
+                   << OldInsnID << "], " << OpIdx << ", " << SubRegIdx
+                   << ")\n");
+      break;
+    }
+    case GIR_AddImplicitDef: {
+      int64_t InsnID = *Command++;
+      int64_t RegNum = *Command++;
+      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+      OutMIs[InsnID].addDef(RegNum, RegState::Implicit);
+      DEBUG(dbgs() << "GIR_AddImplicitDef(OutMIs[" << InsnID << "], " << RegNum
+                   << ")\n");
+      break;
+    }
+    case GIR_AddImplicitUse: {
+      int64_t InsnID = *Command++;
+      int64_t RegNum = *Command++;
+      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+      OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
+      DEBUG(dbgs() << "GIR_AddImplicitUse(OutMIs[" << InsnID << "], " << RegNum
+                   << ")\n");
+      break;
+    }
+    case GIR_AddRegister: {
+      int64_t InsnID = *Command++;
+      int64_t RegNum = *Command++;
+      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+      OutMIs[InsnID].addReg(RegNum);
+      DEBUG(dbgs() << "GIR_AddRegister(OutMIs[" << InsnID << "], " << RegNum
+                   << ")\n");
+      break;
+    }
+    case GIR_AddImm: {
+      int64_t InsnID = *Command++;
+      int64_t Imm = *Command++;
+      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+      OutMIs[InsnID].addImm(Imm);
+      DEBUG(dbgs() << "GIR_AddImm(OutMIs[" << InsnID << "], " << Imm << ")\n");
+      break;
+    }
+    case GIR_ComplexRenderer: {
+      int64_t InsnID = *Command++;
+      int64_t RendererID = *Command++;
+      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+      State.Renderers[RendererID](OutMIs[InsnID]);
+      DEBUG(dbgs() << "GIR_ComplexRenderer(OutMIs[" << InsnID << "], "
+                   << RendererID << ")\n");
+      break;
+    }
+
+    case GIR_ConstrainOperandRC: {
+      int64_t InsnID = *Command++;
+      int64_t OpIdx = *Command++;
+      int64_t RCEnum = *Command++;
+      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+      constrainOperandRegToRegClass(*OutMIs[InsnID].getInstr(), OpIdx,
+                                    *TRI.getRegClass(RCEnum), TII, TRI, RBI);
+      DEBUG(dbgs() << "GIR_ConstrainOperandRC(OutMIs[" << InsnID << "], "
+                   << OpIdx << ", " << RCEnum << ")\n");
+      break;
+    }
+    case GIR_ConstrainSelectedInstOperands: {
+      int64_t InsnID = *Command++;
+      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+      constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
+                                       RBI);
+      DEBUG(dbgs() << "GIR_ConstrainSelectedInstOperands(OutMIs[" << InsnID
+                   << "])\n");
+      break;
+    }
+    case GIR_MergeMemOperands: {
+      int64_t InsnID = *Command++;
+      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
+      for (const auto *FromMI : State.MIs)
+        for (const auto &MMO : FromMI->memoperands())
+          OutMIs[InsnID].addMemOperand(MMO);
+      DEBUG(dbgs() << "GIR_MergeMemOperands(OutMIs[" << InsnID << "])\n");
+      break;
+    }
+    case GIR_EraseFromParent: {
+      int64_t InsnID = *Command++;
+      assert(State.MIs[InsnID] && "Attempted to erase an undefined instruction");
+      State.MIs[InsnID]->eraseFromParent();
+      DEBUG(dbgs() << "GIR_EraseFromParent(MIs[" << InsnID << "])\n");
+      break;
+    }
+
+    case GIR_Done:
+      DEBUG(dbgs() << "GIR_Done");
+      return;
+    default:
+      llvm_unreachable("Unexpected command");
+    }
+  }
+}
+
 bool InstructionSelector::constrainOperandRegToRegClass(
     MachineInstr &I, unsigned OpIdx, const TargetRegisterClass &RC,
     const TargetInstrInfo &TII, const TargetRegisterInfo &TRI,

Modified: llvm/trunk/test/TableGen/GlobalISelEmitter.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/GlobalISelEmitter.td?rev=307133&r1=307132&r2=307133&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/GlobalISelEmitter.td (original)
+++ llvm/trunk/test/TableGen/GlobalISelEmitter.td Wed Jul  5 02:39:33 2017
@@ -107,19 +107,23 @@ def HasC : Predicate<"Subtarget->hasC()"
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable0\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable0, MRI, TRI, RBI, AvailableFeatures)) {
-// 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(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
-// CHECK-NEXT:    Renderers[1](MIB);
-// CHECK-NEXT:    Renderers[0](MIB);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable0[] = {
+// 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:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN2,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/1,
+// CHECK-NEXT:      GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable0\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable0, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -146,11 +150,17 @@ def : Pat<(select GPR32:$src1, complex:$
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable1\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable1, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    // (add:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (ADD:i32 GPR32:i32:$src1, GPR32:i32:$src2)
-// CHECK-NEXT:    I.setDesc(TII.get(MyTarget::ADD));
-// CHECK-NEXT:    MachineInstr &NewI = I;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable1[] = {
+// CHECK-NEXT:      // (add:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (ADD:i32 GPR32:i32:$src1, GPR32:i32:$src2)
+// CHECK-NEXT:      GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/ 0, /*Opcode*/MyTarget::ADD,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable1\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable1, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -186,21 +196,25 @@ def ADD : I<(outs GPR32:$dst), (ins GPR3
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable2\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable2, MRI, TRI, RBI, AvailableFeatures)) {
 // CHECK-NEXT:    if (!isObviouslySafeToFold(*State.MIs[1]))
 // CHECK-NEXT:      return false;
-// CHECK-NEXT:    // (mul:i32 (add:i32 GPR32:i32:$src1, GPR32:i32:$src2), GPR32:i32:$src3)  =>  (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
-// CHECK-NEXT:    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MULADD));
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.add(State.MIs[1]->getOperand(1)/*src1*/);
-// CHECK-NEXT:    MIB.add(State.MIs[1]->getOperand(2)/*src2*/);
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(2)/*src3*/);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], State.MIs[1], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable2[] = {
+// CHECK-NEXT:      // (mul:i32 (add:i32 GPR32:i32:$src1, GPR32:i32:$src2), GPR32:i32:$src3)  =>  (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src3
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable2\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable2, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -232,23 +246,27 @@ def ADD : I<(outs GPR32:$dst), (ins GPR3
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable3\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable3, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:     if (!isObviouslySafeToFold(*State.MIs[1]))
-// CHECK-NEXT:       return false;
-// CHECK-NEXT:     // (mul:i32 GPR32:i32:$src3, (add:i32 GPR32:i32:$src1, GPR32:i32:$src2))  =>  (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
-// CHECK-NEXT:     MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MULADD));
-// CHECK-NEXT:     MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:     MIB.add(State.MIs[1]->getOperand(1)/*src1*/);
-// CHECK-NEXT:     MIB.add(State.MIs[1]->getOperand(2)/*src2*/);
-// CHECK-NEXT:     MIB.add(State.MIs[0]->getOperand(1)/*src3*/);
-// CHECK-NEXT:     for (const auto *FromMI : {State.MIs[0], State.MIs[1], })
-// CHECK-NEXT:       for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:         MIB.addMemOperand(MMO);
-// CHECK-NEXT:     I.eraseFromParent();
-// CHECK-NEXT:     MachineInstr &NewI = *MIB;
-// CHECK-NEXT:     constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
-// CHECK-NEXT:     return true;
-// CHECK-NEXT:   }
+// CHECK-NEXT:    if (!isObviouslySafeToFold(*State.MIs[1]))
+// CHECK-NEXT:      return false;
+// CHECK-NEXT:    const static int64_t EmitTable3[] = {
+// CHECK-NEXT:      // (mul:i32 GPR32:i32:$src3, (add:i32 GPR32:i32:$src1, GPR32:i32:$src2))  =>  (MULADD:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src3
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable3\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable3, TII, TRI, RBI);
+// CHECK-NEXT:    return true;
+// CHECK-NEXT:  }
 
 def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
                [(set GPR32:$dst,
@@ -274,18 +292,22 @@ def MULADD : I<(outs GPR32:$dst), (ins G
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable4\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable4, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:   // (mul:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (MUL:i32 GPR32:i32:$src2, GPR32:i32:$src1)
-// CHECK-NEXT:   MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MUL));
-// CHECK-NEXT:   MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:   MIB.add(State.MIs[0]->getOperand(2)/*src2*/);
-// CHECK-NEXT:   MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
-// CHECK-NEXT:   for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:     for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:       MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable4[] = {
+// CHECK-NEXT:      // (mul:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (MUL:i32 GPR32:i32:$src2, GPR32:i32:$src1)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MUL,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src2
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable4\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable4, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -332,24 +354,28 @@ def MUL : I<(outs GPR32:$dst), (ins GPR3
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable5\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable5, MRI, TRI, RBI, AvailableFeatures)) {
 // CHECK-NEXT:    if (!isObviouslySafeToFold(*State.MIs[1]))
 // CHECK-NEXT:      return false;
 // CHECK-NEXT:    if (!isObviouslySafeToFold(*State.MIs[2]))
 // CHECK-NEXT:      return false;
-// CHECK-NEXT:    // (sub:i32 (sub:i32 GPR32:i32:$src1, GPR32:i32:$src2), (sub:i32 GPR32:i32:$src3, GPR32:i32:$src4)) => (INSNBOB:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3, GPR32:i32:$src4)
-// CHECK-NEXT:    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::INSNBOB));
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.add(State.MIs[1]->getOperand(1)/*src1*/);
-// CHECK-NEXT:    MIB.add(State.MIs[1]->getOperand(2)/*src2*/);
-// CHECK-NEXT:    MIB.add(State.MIs[2]->getOperand(1)/*src3*/);
-// CHECK-NEXT:    MIB.add(State.MIs[2]->getOperand(2)/*src4*/);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], State.MIs[1], State.MIs[2], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable5[] = {
+// CHECK-NEXT:      // (sub:i32 (sub:i32 GPR32:i32:$src1, GPR32:i32:$src2), (sub:i32 GPR32:i32:$src3, GPR32:i32:$src4)) => (INSNBOB:i32 GPR32:i32:$src1, GPR32:i32:$src2, GPR32:i32:$src3, GPR32:i32:$src4)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSNBOB,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/1, // src3
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/2, // src4
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable5\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable5, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -377,18 +403,22 @@ def INSNBOB : I<(outs GPR32:$dst), (ins
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable6\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable6, MRI, TRI, RBI, AvailableFeatures)) {
-// 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(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
-// CHECK-NEXT:    Renderers[0](MIB);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable6[] = {
+// CHECK-NEXT:      // (sub:i32 GPR32:i32:$src1, complex:i32:$src2) => (INSN1:i32 GPR32:i32:$src1, complex:i32:$src2)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN1,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable6\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable6, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -414,18 +444,22 @@ def : Pat<(sub GPR32:$src1, complex:$src
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable7\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable7, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    // (xor:i32 GPR32:i32:$src1, -2:i32) => (XORI:i32 GPR32:i32:$src1)
-// CHECK-NEXT:    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XORI));
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.addImm(-1);
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable7[] = {
+// CHECK-NEXT:      // (xor:i32 GPR32:i32:$src1, -2:i32) => (XORI:i32 GPR32:i32:$src1)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORI,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable7\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable7, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -452,18 +486,22 @@ def XORI : I<(outs GPR32:$dst), (ins m1:
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable8\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable8, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    // (xor:i32 GPR32:i32:$src1, -3:i32) => (XOR:i32 GPR32:i32:$src1)
-// CHECK-NEXT:    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XOR));
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.addReg(MyTarget::R0);
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable8[] = {
+// CHECK-NEXT:      // (xor:i32 GPR32:i32:$src1, -3:i32) => (XOR:i32 GPR32:i32:$src1)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XOR,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable8\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable8, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -490,19 +528,23 @@ def XOR : I<(outs GPR32:$dst), (ins Z:$s
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable9\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable9, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    // (xor:i32 GPR32:i32:$src1, -4:i32) => (XORlike:i32 GPR32:i32:$src1)
-// CHECK-NEXT:    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XORlike));
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.addImm(-1);
-// CHECK-NEXT:    MIB.addReg(MyTarget::R0);
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable9[] = {
+// CHECK-NEXT:      // (xor:i32 GPR32:i32:$src1, -4:i32) => (XORlike:i32 GPR32:i32:$src1)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORlike,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
+// CHECK-NEXT:      GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable9\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable9, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -529,20 +571,24 @@ def XORlike : I<(outs GPR32:$dst), (ins
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable10\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable10, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    // (xor:i32 GPR32:i32:$src1, -5:i32) => (XORManyDefaults:i32 GPR32:i32:$src1)
-// CHECK-NEXT:    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XORManyDefaults));
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.addImm(-1);
-// CHECK-NEXT:    MIB.addReg(MyTarget::R0);
-// CHECK-NEXT:    MIB.addReg(MyTarget::R0);
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(1)/*src1*/);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable10[] = {
+// CHECK-NEXT:      // (xor:i32 GPR32:i32:$src1, -5:i32) => (XORManyDefaults:i32 GPR32:i32:$src1)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORManyDefaults,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
+// CHECK-NEXT:      GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
+// CHECK-NEXT:      GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable10\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable10, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -571,18 +617,22 @@ def XORManyDefaults : I<(outs GPR32:$dst
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable11\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable11, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    // (xor:i32 GPR32:i32:$Wm, -1:i32) => (ORN:i32 R0:i32, GPR32:i32:$Wm)
-// CHECK-NEXT:    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::ORN));
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    MIB.addReg(MyTarget::R0);
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(1)/*Wm*/);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable11[] = {
+// CHECK-NEXT:      // (xor:i32 GPR32:i32:$Wm, -1:i32) => (ORN:i32 R0:i32, GPR32:i32:$Wm)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::ORN,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // Wm
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable11\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable11, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -605,11 +655,17 @@ def : Pat<(not GPR32:$Wm), (ORN R0, GPR3
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable12\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable12, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    // (bitconvert:i32 FPR32:f32:$src1) => (COPY_TO_REGCLASS:i32 FPR32:f32:$src1, GPR32:i32)
-// CHECK-NEXT:    I.setDesc(TII.get(TargetOpcode::COPY));
-// CHECK-NEXT:    MachineInstr &NewI = I;
-// CHECK-NEXT:    constrainOperandRegToRegClass(NewI, 0, MyTarget::GPR32RegClass, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable12[] = {
+// CHECK-NEXT:      // (bitconvert:i32 FPR32:f32:$src1) => (COPY_TO_REGCLASS:i32 FPR32:f32:$src1, GPR32:i32)
+// CHECK-NEXT:      GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/ 0, /*Opcode*/TargetOpcode::COPY,
+// CHECK-NEXT:      GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC GPR32*/ 1,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable12\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable12, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -630,16 +686,20 @@ def : Pat<(i32 (bitconvert FPR32:$src1))
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable13\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable13, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    // 1:i32 => (MOV1:i32)
-// CHECK-NEXT:    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MOV1));
-// CHECK-NEXT:    MIB.add(State.MIs[0]->getOperand(0)/*dst*/);
-// CHECK-NEXT:    for (const auto *FromMI : {State.MIs[0], })
-// CHECK-NEXT:      for (const auto &MMO : FromMI->memoperands())
-// CHECK-NEXT:        MIB.addMemOperand(MMO);
-// CHECK-NEXT:    I.eraseFromParent();
-// CHECK-NEXT:    MachineInstr &NewI = *MIB;
-// CHECK-NEXT:    constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
+// CHECK-NEXT:    const static int64_t EmitTable13[] = {
+// CHECK-NEXT:      // 1:i32  =>  (MOV1:i32)
+// CHECK-NEXT:      GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV1,
+// CHECK-NEXT:      GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
+// CHECK-NEXT:      GIR_MergeMemOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_EraseFromParent, /*InsnID*/0,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable13\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable13, TII, TRI, RBI);
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
@@ -656,12 +716,18 @@ def MOV1 : I<(outs GPR32:$dst), (ins), [
 // CHECK-NEXT:  };
 // CHECK-NEXT:  MIs.clear();
 // CHECK-NEXT:  MIs.push_back(&I);
+// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable14\n");
 // CHECK-NEXT:  if (executeMatchTable(*this, State, MatcherInfo, MatchTable14, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:     // (br (bb:Other):$target) => (BR (bb:Other):$target)
-// CHECK-NEXT:     I.setDesc(TII.get(MyTarget::BR));
-// CHECK-NEXT:     MachineInstr &NewI = I;
-// CHECK-NEXT:     constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
-// CHECK-NEXT:     return true;
+// CHECK-NEXT:    const static int64_t EmitTable14[] = {
+// CHECK-NEXT:      // (br (bb:Other):$target) => (BR (bb:Other):$target)
+// CHECK-NEXT:      GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/ 0, /*Opcode*/MyTarget::BR,
+// CHECK-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
+// CHECK-NEXT:      GIR_Done,
+// CHECK-NEXT:    };
+// CHECK-NEXT:    NewMIVector OutMIs;
+// CHECK-NEXT:    DEBUG(dbgs() << "Processing EmitTable14\n");
+// CHECK-NEXT:    executeEmitTable(OutMIs, State, EmitTable14, TII, TRI, RBI);
+// CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
 def BR : I<(outs), (ins unknown:$target),

Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=307133&r1=307132&r2=307133&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Wed Jul  5 02:39:33 2017
@@ -263,7 +263,6 @@ public:
                          unsigned InsnVarID, unsigned OpIdx);
   unsigned getInsnVarID(const InstructionMatcher &InsnMatcher) const;
 
-  void emitCxxCapturedInsnList(raw_ostream &OS);
   void emitCxxCaptureStmts(raw_ostream &OS);
 
   void emit(raw_ostream &OS);
@@ -906,6 +905,7 @@ public:
 /// instruction to the one being built.
 class CopyRenderer : public OperandRenderer {
 protected:
+  unsigned NewInsnID;
   /// The matcher for the instruction that this operand is copied from.
   /// This provides the facility for looking up an a operand by it's name so
   /// that it can be used as a source for the instruction being built.
@@ -914,9 +914,10 @@ protected:
   const StringRef SymbolicName;
 
 public:
-  CopyRenderer(const InstructionMatcher &Matched, StringRef SymbolicName)
-      : OperandRenderer(OR_Copy), Matched(Matched), SymbolicName(SymbolicName) {
-  }
+  CopyRenderer(unsigned NewInsnID, const InstructionMatcher &Matched,
+               StringRef SymbolicName)
+      : OperandRenderer(OR_Copy), NewInsnID(NewInsnID), Matched(Matched),
+        SymbolicName(SymbolicName) {}
 
   static bool classof(const OperandRenderer *R) {
     return R->getKind() == OR_Copy;
@@ -926,10 +927,10 @@ public:
 
   void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
     const OperandMatcher &Operand = Matched.getOperand(SymbolicName);
-    unsigned InsnVarID =
-        Rule.getInsnVarID(Operand.getInstructionMatcher());
-    std::string OperandExpr = Operand.getOperandExpr(InsnVarID);
-    OS << "    MIB.add(" << OperandExpr << "/*" << SymbolicName << "*/);\n";
+    unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
+    OS << "      GIR_Copy, /*NewInsnID*/" << NewInsnID << ", /*OldInsnID*/"
+       << OldInsnVarID << ", /*OpIdx*/" << Operand.getOperandIndex() << ", // "
+       << SymbolicName << "\n";
   }
 };
 
@@ -938,6 +939,7 @@ public:
 /// subregister should be copied.
 class CopySubRegRenderer : public OperandRenderer {
 protected:
+  unsigned NewInsnID;
   /// The matcher for the instruction that this operand is copied from.
   /// This provides the facility for looking up an a operand by it's name so
   /// that it can be used as a source for the instruction being built.
@@ -948,9 +950,9 @@ protected:
   const CodeGenSubRegIndex *SubReg;
 
 public:
-  CopySubRegRenderer(const InstructionMatcher &Matched, StringRef SymbolicName,
-                     const CodeGenSubRegIndex *SubReg)
-      : OperandRenderer(OR_CopySubReg), Matched(Matched),
+  CopySubRegRenderer(unsigned NewInsnID, const InstructionMatcher &Matched,
+                     StringRef SymbolicName, const CodeGenSubRegIndex *SubReg)
+      : OperandRenderer(OR_CopySubReg), NewInsnID(NewInsnID), Matched(Matched),
         SymbolicName(SymbolicName), SubReg(SubReg) {}
 
   static bool classof(const OperandRenderer *R) {
@@ -961,10 +963,11 @@ public:
 
   void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
     const OperandMatcher &Operand = Matched.getOperand(SymbolicName);
-    unsigned InsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
-    std::string OperandExpr = Operand.getOperandExpr(InsnVarID);
-    OS << "    MIB.addReg(" << OperandExpr << ".getReg() /*" << SymbolicName
-       << "*/, 0, " << SubReg->EnumValue << ");\n";
+    unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
+    OS << "      GIR_CopySubReg, /*NewInsnID*/" << NewInsnID
+       << ", /*OldInsnID*/" << OldInsnVarID << ", /*OpIdx*/"
+       << Operand.getOperandIndex() << ", /*SubRegIdx*/" << SubReg->EnumValue
+       << ", // " << SymbolicName << "\n";
   }
 };
 
@@ -972,39 +975,44 @@ public:
 /// This is typically useful for WZR/XZR on AArch64.
 class AddRegisterRenderer : public OperandRenderer {
 protected:
+  unsigned InsnID;
   const Record *RegisterDef;
 
 public:
-  AddRegisterRenderer(const Record *RegisterDef)
-      : OperandRenderer(OR_Register), RegisterDef(RegisterDef) {}
+  AddRegisterRenderer(unsigned InsnID, const Record *RegisterDef)
+      : OperandRenderer(OR_Register), InsnID(InsnID), RegisterDef(RegisterDef) {
+  }
 
   static bool classof(const OperandRenderer *R) {
     return R->getKind() == OR_Register;
   }
 
   void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
-    OS << "    MIB.addReg(" << (RegisterDef->getValue("Namespace")
-                                    ? RegisterDef->getValueAsString("Namespace")
-                                    : "")
-       << "::" << RegisterDef->getName() << ");\n";
+    OS << "      GIR_AddRegister, /*InsnID*/" << InsnID << ", "
+       << (RegisterDef->getValue("Namespace")
+               ? RegisterDef->getValueAsString("Namespace")
+               : "")
+       << "::" << RegisterDef->getName() << ",\n";
   }
 };
 
 /// Adds a specific immediate to the instruction being built.
 class ImmRenderer : public OperandRenderer {
 protected:
+  unsigned InsnID;
   int64_t Imm;
 
 public:
-  ImmRenderer(int64_t Imm)
-      : OperandRenderer(OR_Imm), Imm(Imm) {}
+  ImmRenderer(unsigned InsnID, int64_t Imm)
+      : OperandRenderer(OR_Imm), InsnID(InsnID), Imm(Imm) {}
 
   static bool classof(const OperandRenderer *R) {
     return R->getKind() == OR_Imm;
   }
 
   void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
-    OS << "    MIB.addImm(" << Imm << ");\n";
+    OS << "      GIR_AddImm, /*InsnID*/" << InsnID << ", /*Imm*/" << Imm
+       << ",\n";
   }
 };
 
@@ -1012,6 +1020,7 @@ public:
 /// matcher function.
 class RenderComplexPatternOperand : public OperandRenderer {
 private:
+  unsigned InsnID;
   const Record &TheDef;
   /// The name of the operand.
   const StringRef SymbolicName;
@@ -1024,9 +1033,9 @@ private:
   }
 
 public:
-  RenderComplexPatternOperand(const Record &TheDef, StringRef SymbolicName,
-                              unsigned RendererID)
-      : OperandRenderer(OR_ComplexPattern), TheDef(TheDef),
+  RenderComplexPatternOperand(unsigned InsnID, const Record &TheDef,
+                              StringRef SymbolicName, unsigned RendererID)
+      : OperandRenderer(OR_ComplexPattern), InsnID(InsnID), TheDef(TheDef),
         SymbolicName(SymbolicName), RendererID(RendererID) {}
 
   static bool classof(const OperandRenderer *R) {
@@ -1034,7 +1043,8 @@ public:
   }
 
   void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
-    OS << "    State.Renderers[" << RendererID << "](MIB);\n";
+    OS << "      GIR_ComplexRenderer, /*InsnID*/" << InsnID
+       << ", /*RendererID*/" << RendererID << ",\n";
   }
 };
 
@@ -1049,11 +1059,11 @@ public:
 
   /// Emit the C++ statements to implement the action.
   ///
-  /// \param RecycleVarName If given, it's an instruction to recycle. The
-  ///                       requirements on the instruction vary from action to
-  ///                       action.
+  /// \param RecycleInsnID If given, it's an instruction to recycle. The
+  ///                      requirements on the instruction vary from action to
+  ///                      action.
   virtual void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
-                                  StringRef RecycleVarName) const = 0;
+                                  unsigned RecycleInsnID) const = 0;
 };
 
 /// Generates a comment describing the matched rule being acted upon.
@@ -1065,8 +1075,9 @@ public:
   DebugCommentAction(const PatternToMatch &P) : P(P) {}
 
   void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
-                          StringRef RecycleVarName) const override {
-    OS << "    // " << *P.getSrcPattern() << "  =>  " << *P.getDstPattern() << "\n";
+                          unsigned RecycleInsnID) const override {
+    OS << "      // " << *P.getSrcPattern() << "  =>  " << *P.getDstPattern()
+       << "\n";
   }
 };
 
@@ -1074,7 +1085,7 @@ public:
 /// into the desired instruction when this is possible.
 class BuildMIAction : public MatchAction {
 private:
-  std::string Name;
+  unsigned InsnID;
   const CodeGenInstruction *I;
   const InstructionMatcher &Matched;
   std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers;
@@ -1098,9 +1109,9 @@ private:
   }
 
 public:
-  BuildMIAction(const StringRef Name, const CodeGenInstruction *I,
+  BuildMIAction(unsigned InsnID, const CodeGenInstruction *I,
                 const InstructionMatcher &Matched)
-      : Name(Name), I(I), Matched(Matched) {}
+      : InsnID(InsnID), I(I), Matched(Matched) {}
 
   template <class Kind, class... Args>
   Kind &addRenderer(Args&&... args) {
@@ -1110,84 +1121,74 @@ public:
   }
 
   void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
-                          StringRef RecycleVarName) const override {
+                          unsigned RecycleInsnID) const override {
     if (canMutate()) {
-      OS << "    " << RecycleVarName << ".setDesc(TII.get(" << I->Namespace
-         << "::" << I->TheDef->getName() << "));\n";
+      OS << "      GIR_MutateOpcode, /*InsnID*/" << InsnID
+         << ", /*RecycleInsnID*/ " << RecycleInsnID << ", /*Opcode*/"
+         << I->Namespace << "::" << I->TheDef->getName() << ",\n";
 
       if (!I->ImplicitDefs.empty() || !I->ImplicitUses.empty()) {
-        OS << "    auto MIB = MachineInstrBuilder(MF, &" << RecycleVarName
-           << ");\n";
-
         for (auto Def : I->ImplicitDefs) {
           auto Namespace = Def->getValue("Namespace")
                                ? Def->getValueAsString("Namespace")
                                : "";
-          OS << "    MIB.addDef(" << Namespace << "::" << Def->getName()
-             << ", RegState::Implicit);\n";
+          OS << "      GIR_AddImplicitDef, " << InsnID << ", " << Namespace
+             << "::" << Def->getName() << ",\n";
         }
         for (auto Use : I->ImplicitUses) {
           auto Namespace = Use->getValue("Namespace")
                                ? Use->getValueAsString("Namespace")
                                : "";
-          OS << "    MIB.addUse(" << Namespace << "::" << Use->getName()
-             << ", RegState::Implicit);\n";
+          OS << "      GIR_AddImplicitUse, " << InsnID << ", " << Namespace
+             << "::" << Use->getName() << ",\n";
         }
       }
-
-      OS << "    MachineInstr &" << Name << " = " << RecycleVarName << ";\n";
       return;
     }
 
     // TODO: Simple permutation looks like it could be almost as common as
     //       mutation due to commutative operations.
 
-    OS << "    MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, "
-          "I.getDebugLoc(), TII.get("
-       << I->Namespace << "::" << I->TheDef->getName() << "));\n";
+    OS << "      GIR_BuildMI, /*InsnID*/" << InsnID << ", /*Opcode*/"
+       << I->Namespace << "::" << I->TheDef->getName() << ",\n";
     for (const auto &Renderer : OperandRenderers)
       Renderer->emitCxxRenderStmts(OS, Rule);
-    OS << "    for (const auto *FromMI : ";
-    Rule.emitCxxCapturedInsnList(OS);
-    OS << ")\n";
-    OS << "      for (const auto &MMO : FromMI->memoperands())\n";
-    OS << "        MIB.addMemOperand(MMO);\n";
-    OS << "    " << RecycleVarName << ".eraseFromParent();\n";
-    OS << "    MachineInstr &" << Name << " = *MIB;\n";
+
+    OS << "      GIR_MergeMemOperands, /*InsnID*/" << InsnID << ",\n"
+       << "      GIR_EraseFromParent, /*InsnID*/" << RecycleInsnID << ",\n";
   }
 };
 
 /// Generates code to constrain the operands of an output instruction to the
 /// register classes specified by the definition of that instruction.
 class ConstrainOperandsToDefinitionAction : public MatchAction {
-  std::string Name;
+  unsigned InsnID;
 
 public:
-  ConstrainOperandsToDefinitionAction(const StringRef Name) : Name(Name) {}
+  ConstrainOperandsToDefinitionAction(unsigned InsnID) : InsnID(InsnID) {}
 
   void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
-                          StringRef RecycleVarName) const override {
-    OS << "      constrainSelectedInstRegOperands(" << Name
-       << ", TII, TRI, RBI);\n";
+                          unsigned RecycleInsnID) const override {
+    OS << "      GIR_ConstrainSelectedInstOperands, /*InsnID*/" << InsnID << ",\n";
   }
 };
 
 /// Generates code to constrain the specified operand of an output instruction
 /// to the specified register class.
 class ConstrainOperandToRegClassAction : public MatchAction {
-  std::string Name;
+  unsigned InsnID;
   unsigned OpIdx;
   const CodeGenRegisterClass &RC;
 
 public:
-  ConstrainOperandToRegClassAction(const StringRef Name, unsigned OpIdx,
+  ConstrainOperandToRegClassAction(unsigned InsnID, unsigned OpIdx,
                                    const CodeGenRegisterClass &RC)
-      : Name(Name), OpIdx(OpIdx), RC(RC) {}
+      : InsnID(InsnID), OpIdx(OpIdx), RC(RC) {}
 
   void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
-                          StringRef RecycleVarName) const override {
-    OS << "      constrainOperandRegToRegClass(" << Name << ", " << OpIdx
-       << ", " << RC.getQualifiedName() << "RegClass, TII, TRI, RBI);\n";
+                          unsigned RecycleInsnID) const override {
+    OS << "      GIR_ConstrainOperandRC, /*InsnID*/" << InsnID << ", /*Op*/"
+       << OpIdx << ", /*RC " << RC.getName() << "*/ " << RC.EnumValue << ",\n";
   }
 };
 
@@ -1234,20 +1235,6 @@ unsigned RuleMatcher::getInsnVarID(const
   llvm_unreachable("Matched Insn was not captured in a local variable");
 }
 
-/// Emit a C++ initializer_list containing references to every matched
-/// instruction.
-void RuleMatcher::emitCxxCapturedInsnList(raw_ostream &OS) {
-  SmallVector<unsigned, 2> IDs;
-  for (const auto &Pair : InsnVariableIDs)
-    IDs.push_back(Pair.second);
-  std::sort(IDs.begin(), IDs.end());
-
-  OS << "{";
-  for (const auto &ID : IDs)
-    OS << "State.MIs[" << ID << "], ";
-  OS << "}";
-}
-
 /// Emit C++ statements to check the shape of the match and capture
 /// instructions into local variables.
 void RuleMatcher::emitCxxCaptureStmts(raw_ostream &OS) {
@@ -1287,6 +1274,8 @@ void RuleMatcher::emit(raw_ostream &OS)
      << "  };\n"
      << "  State.MIs.clear();\n"
      << "  State.MIs.push_back(&I);\n"
+     << "  DEBUG(dbgs() << \"Processing MatchTable" << NumPatternEmitted
+     << "\\n\");\n"
      << "  if (executeMatchTable(*this, State, MatcherInfo, MatchTable"
      << CurrentMatchTableID << ", MRI, TRI, RBI, AvailableFeatures)) {\n";
 
@@ -1346,9 +1335,16 @@ void RuleMatcher::emit(raw_ostream &OS)
     }
   }
 
-  for (const auto &MA : Actions) {
-    MA->emitCxxActionStmts(OS, *this, "I");
-  }
+  OS << "    const static int64_t EmitTable" << NumPatternEmitted << "[] = {\n";
+  for (const auto &MA : Actions)
+    MA->emitCxxActionStmts(OS, *this, 0);
+  OS << "      GIR_Done,\n"
+     << "    };\n"
+     << "    NewMIVector OutMIs;\n"
+     << "    DEBUG(dbgs() << \"Processing EmitTable" << NumPatternEmitted
+     << "\\n\");\n"
+     << "    executeEmitTable(OutMIs, State, EmitTable" << NumPatternEmitted
+     << ", TII, TRI, RBI);\n";
 
   OS << "    return true;\n";
   OS << "  }\n\n";
@@ -1625,7 +1621,7 @@ Error GlobalISelEmitter::importExplicitU
     if (DstChild->getOperator()->isSubClassOf("SDNode")) {
       auto &ChildSDNI = CGP.getSDNodeInfo(DstChild->getOperator());
       if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
-        DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher,
+        DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher,
                                                DstChild->getName());
         return Error::success();
       }
@@ -1650,13 +1646,14 @@ Error GlobalISelEmitter::importExplicitU
       return failedImport("Dst operand has an unsupported type");
 
     if (ChildRec->isSubClassOf("Register")) {
-      DstMIBuilder.addRenderer<AddRegisterRenderer>(ChildRec);
+      DstMIBuilder.addRenderer<AddRegisterRenderer>(0, ChildRec);
       return Error::success();
     }
 
     if (ChildRec->isSubClassOf("RegisterClass") ||
         ChildRec->isSubClassOf("RegisterOperand")) {
-      DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstChild->getName());
+      DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher,
+                                             DstChild->getName());
       return Error::success();
     }
 
@@ -1668,7 +1665,7 @@ Error GlobalISelEmitter::importExplicitU
 
       const OperandMatcher &OM = InsnMatcher.getOperand(DstChild->getName());
       DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
-          *ComplexPattern->second, DstChild->getName(),
+          0, *ComplexPattern->second, DstChild->getName(),
           OM.getAllocatedTemporariesBaseID());
       return Error::success();
     }
@@ -1711,12 +1708,12 @@ Expected<BuildMIAction &> GlobalISelEmit
     IsExtractSubReg = true;
   }
 
-  auto &DstMIBuilder = M.addAction<BuildMIAction>("NewI", DstI, InsnMatcher);
+  auto &DstMIBuilder = M.addAction<BuildMIAction>(0, DstI, InsnMatcher);
 
   // Render the explicit defs.
   for (unsigned I = 0; I < DstI->Operands.NumDefs; ++I) {
     const CGIOperandList::OperandInfo &DstIOperand = DstI->Operands[I];
-    DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstIOperand.Name);
+    DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher, DstIOperand.Name);
   }
 
   // EXTRACT_SUBREG needs to use a subregister COPY.
@@ -1739,7 +1736,7 @@ Expected<BuildMIAction &> GlobalISelEmit
       }
 
       DstMIBuilder.addRenderer<CopySubRegRenderer>(
-          InsnMatcher, Dst->getChild(0)->getName(), SubIdx);
+          0, InsnMatcher, Dst->getChild(0)->getName(), SubIdx);
       return DstMIBuilder;
     }
 
@@ -1795,12 +1792,12 @@ Error GlobalISelEmitter::importDefaultOp
     }
 
     if (const DefInit *DefaultDefOp = dyn_cast<DefInit>(DefaultOp)) {
-      DstMIBuilder.addRenderer<AddRegisterRenderer>(DefaultDefOp->getDef());
+      DstMIBuilder.addRenderer<AddRegisterRenderer>(0, DefaultDefOp->getDef());
       continue;
     }
 
     if (const IntInit *DefaultIntOp = dyn_cast<IntInit>(DefaultOp)) {
-      DstMIBuilder.addRenderer<ImmRenderer>(DefaultIntOp->getValue());
+      DstMIBuilder.addRenderer<ImmRenderer>(0, DefaultIntOp->getValue());
       continue;
     }
 
@@ -1919,7 +1916,7 @@ Expected<RuleMatcher> GlobalISelEmitter:
       return failedImport("COPY_TO_REGCLASS operand #1 isn't a register class");
 
     M.addAction<ConstrainOperandToRegClassAction>(
-        "NewI", 0, Target.getRegisterClass(DstIOpRec));
+        0, 0, Target.getRegisterClass(DstIOpRec));
 
     // We're done with this pattern!  It's eligible for GISel emission; return
     // it.
@@ -1947,8 +1944,7 @@ Expected<RuleMatcher> GlobalISelEmitter:
       return failedImport("EXTRACT_SUBREG operand #1 isn't a register class");
 
     CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
-    CodeGenRegisterClass *SrcRC = CGRegs.getRegClass(
-        getInitValueAsRegClass(Dst->getChild(0)->getLeafValue()));
+    CodeGenRegisterClass *SrcRC = CGRegs.getRegClass(DstIOpRec);
 
     // It would be nice to leave this constraint implicit but we're required
     // to pick a register class so constrain the result to a register class
@@ -1962,12 +1958,16 @@ Expected<RuleMatcher> GlobalISelEmitter:
     const auto &SrcRCDstRCPair =
         SrcRC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
     assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
-    M.addAction<ConstrainOperandToRegClassAction>("NewI", 0,
-                                                  *SrcRCDstRCPair->second);
-    M.addAction<ConstrainOperandToRegClassAction>("NewI", 1,
-                                                  *SrcRCDstRCPair->first);
-  } else
-    M.addAction<ConstrainOperandsToDefinitionAction>("NewI");
+    M.addAction<ConstrainOperandToRegClassAction>(0, 0, *SrcRCDstRCPair->second);
+    M.addAction<ConstrainOperandToRegClassAction>(0, 1, *SrcRCDstRCPair->first);
+
+    // We're done with this pattern!  It's eligible for GISel emission; return
+    // it.
+    ++NumPatternImported;
+    return std::move(M);
+  }
+
+  M.addAction<ConstrainOperandsToDefinitionAction>(0);
 
   // We're done with this pattern!  It's eligible for GISel emission; return it.
   ++NumPatternImported;




More information about the llvm-commits mailing list