[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

llvm-svn: 307133
diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
index f137379..1faebc2 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
@@ -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::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,