[globalisel][tablegen] Fuse the generated tables together.
authorDaniel Sanders <daniel_l_sanders@apple.com>
Wed, 26 Jul 2017 10:20:56 +0000 (10:20 +0000)
committerDaniel Sanders <daniel_l_sanders@apple.com>
Wed, 26 Jul 2017 10:20:56 +0000 (10:20 +0000)
Summary:
Now that we have control flow in place, fuse the per-rule tables into a
single table. This is a compile-time saving at this point. However, this will
also enable the optimization of a table so that similar instructions can be
tested together, reducing the time spent on the matching the code.

This is NFC in terms of externally visible behaviour but some internals have
changed slightly. State.MIs is no longer reset between each rule that is
attempted because it's not necessary to do so. As a consequence of this the
restriction on the order that instructions are added to State.MIs has been
relaxed to only affect recorded instructions that require new elements to be
added to the vector. GIM_RecordInsn can now write to any element from 1 to
State.MIs.size() instead of just State.MIs.size().

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

Reviewed By: rovka

Subscribers: kristof.beyls, igorb, llvm-commits

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

llvm-svn: 309094

llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
llvm/test/TableGen/GlobalISelEmitter.td
llvm/utils/TableGen/GlobalISelEmitter.cpp

index b3d7942..1aef544 100644 (file)
@@ -58,7 +58,6 @@ bool InstructionSelector::executeMatchTable(
       // As an optimisation we require that MIs[0] is always the root. Refuse
       // any attempt to modify it.
       assert(NewInsnID != 0 && "Refusing to modify MIs[0]");
-      (void)NewInsnID;
 
       MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
       if (!MO.isReg()) {
@@ -74,9 +73,14 @@ bool InstructionSelector::executeMatchTable(
         break;
       }
 
-      assert((size_t)NewInsnID == State.MIs.size() &&
-             "Expected to store MIs in order");
-      State.MIs.push_back(MRI.getVRegDef(MO.getReg()));
+      MachineInstr *NewMI = MRI.getVRegDef(MO.getReg());
+      if ((size_t)NewInsnID < State.MIs.size())
+        State.MIs[NewInsnID] = NewMI;
+      else {
+        assert((size_t)NewInsnID == State.MIs.size() &&
+               "Expected to store MIs in order");
+        State.MIs.push_back(NewMI);
+      }
       DEBUG(dbgs() << CurrentIdx << ": MIs[" << NewInsnID
                    << "] = GIM_RecordInsn(" << InsnID << ", " << OpIdx
                    << ")\n");
@@ -213,7 +217,8 @@ bool InstructionSelector::executeMatchTable(
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
       MachineOperand &OM = State.MIs[InsnID]->getOperand(OpIdx);
       if (!OM.isIntrinsicID() || OM.getIntrinsicID() != Value)
-        return false;
+        if (handleReject() == RejectAndGiveUp)
+          return false;
       break;
     }
     case GIM_CheckIsMBB: {
index fa9db02..8c32615 100644 (file)
@@ -96,7 +96,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
 //
 
 // CHECK-LABEL: MatchTable0[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
 // CHECK-NEXT:    // MIs[0] dst
@@ -121,14 +121,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable0\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable0, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 0: @[[LABEL]]
 
 def INSN3 : I<(outs GPR32:$dst),
               (ins GPR32Op:$src1, complex:$src2, GPR32:$src3, complex:$src4, complex:$src5), []>;
@@ -138,8 +131,7 @@ def : Pat<(select GPR32:$src1, complex:$src2, (select GPR32:$src3, complex:$src4
 //===- Test a pattern with multiple ComplexPattern operands. --------------===//
 //
 
-// CHECK-LABEL: MatchTable1[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 1*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
 // CHECK-NEXT:    GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/3, // MIs[1]
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/1, /*Expected*/4,
@@ -180,14 +172,7 @@ def : Pat<(select GPR32:$src1, complex:$src2, (select GPR32:$src3, complex:$src4
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable1\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable1, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 1: @[[LABEL]]
 
 def : GINodeEquiv<G_SELECT, select>;
 def INSN2 : I<(outs GPR32:$dst), (ins GPR32Op:$src1, complex:$src2, complex:$src3), []>;
@@ -196,8 +181,7 @@ def : Pat<(select GPR32:$src1, complex:$src2, complex:$src3),
 
 //===- Test a simple pattern with regclass operands. ----------------------===//
 
-// CHECK-LABEL: MatchTable2[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 2*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_ADD,
 // CHECK-NEXT:    // MIs[0] dst
@@ -213,14 +197,7 @@ def : Pat<(select GPR32:$src1, complex:$src2, complex:$src3),
 // CHECK-NEXT:    GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::ADD,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable2\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable2, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 2: @[[LABEL]]
 
 def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
             [(set GPR32:$dst, (add GPR32:$src1, GPR32:$src2))]>;
@@ -228,8 +205,7 @@ def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
 //===- Test a simple pattern with an intrinsic. ---------------------------===//
 //
 
-// CHECK-LABEL: MatchTable3[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 3*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_INTRINSIC,
 // CHECK-NEXT:    // MIs[0] dst
@@ -249,22 +225,14 @@ def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable3\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable3, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 3: @[[LABEL]]
 
 def MOV : I<(outs GPR32:$dst), (ins GPR32:$src1),
             [(set GPR32:$dst, (int_mytarget_nop GPR32:$src1))]>;
 
 //===- Test a nested instruction match. -----------------------------------===//
 
-// CHECK-LABEL: MatchTable4[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 4*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckFeatures, GIFBS_HasA,
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
@@ -298,18 +266,10 @@ def MOV : I<(outs GPR32:$dst), (ins GPR32:$src1),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable4\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable4, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 4: @[[LABEL]]
 
 // We also get a second rule by commutativity.
-// CHECK-LABEL: MatchTable5[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 5*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckFeatures, GIFBS_HasA,
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/2,
@@ -343,14 +303,7 @@ def MOV : I<(outs GPR32:$dst), (ins GPR32:$src1),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable5\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable5, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 5: @[[LABEL]]
 
 def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
                [(set GPR32:$dst,
@@ -359,8 +312,7 @@ def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
 
 //===- Test another simple pattern with regclass operands. ----------------===//
 
-// CHECK-LABEL: MatchTable6[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 6*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckFeatures, GIFBS_HasA_HasB_HasC,
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_MUL,
@@ -382,14 +334,7 @@ def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable6\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable6, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 6: @[[LABEL]]
 
 def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
              [(set GPR32:$dst, (mul GPR32:$src1, GPR32:$src2))]>,
@@ -397,8 +342,7 @@ def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
 
 //===- Test a more complex multi-instruction match. -----------------------===//
 
-// CHECK-LABEL: MatchTable7[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 7*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckFeatures, GIFBS_HasA,
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
@@ -444,14 +388,7 @@ def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable7\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable7, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 7: @[[LABEL]]
 
 def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
                  [(set GPR32:$dst,
@@ -461,8 +398,7 @@ def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, G
 //===- Test a pattern with ComplexPattern operands. -----------------------===//
 //
 
-// CHECK-LABEL: MatchTable8[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 8*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SUB,
 // CHECK-NEXT:    // MIs[0] dst
@@ -483,14 +419,7 @@ def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, G
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable8\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable8, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 8: @[[LABEL]]
 
 def INSN1 : I<(outs GPR32:$dst), (ins GPR32:$src1, complex:$src2), []>;
 def : Pat<(sub GPR32:$src1, complex:$src2), (INSN1 GPR32:$src1, complex:$src2)>;
@@ -498,8 +427,7 @@ def : Pat<(sub GPR32:$src1, complex:$src2), (INSN1 GPR32:$src1, complex:$src2)>;
 //===- Test a simple pattern with a default operand. ----------------------===//
 //
 
-// CHECK-LABEL: MatchTable9[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 9*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
 // CHECK-NEXT:    // MIs[0] dst
@@ -520,14 +448,7 @@ def : Pat<(sub GPR32:$src1, complex:$src2), (INSN1 GPR32:$src1, complex:$src2)>;
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable9\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable9, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 9: @[[LABEL]]
 
 // The -2 is just to distinguish it from the 'not' case below.
 def XORI : I<(outs GPR32:$dst), (ins m1:$src2, GPR32:$src1),
@@ -536,8 +457,7 @@ def XORI : I<(outs GPR32:$dst), (ins m1:$src2, GPR32:$src1),
 //===- Test a simple pattern with a default register operand. -------------===//
 //
 
-// CHECK-LABEL: MatchTable10[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 10*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
 // CHECK-NEXT:    // MIs[0] dst
@@ -558,14 +478,7 @@ def XORI : I<(outs GPR32:$dst), (ins m1:$src2, GPR32:$src1),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable10\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable10, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 10: @[[LABEL]]
 
 // The -3 is just to distinguish it from the 'not' case below and the other default op case above.
 def XOR : I<(outs GPR32:$dst), (ins Z:$src2, GPR32:$src1),
@@ -574,8 +487,7 @@ def XOR : I<(outs GPR32:$dst), (ins Z:$src2, GPR32:$src1),
 //===- Test a simple pattern with a multiple default operands. ------------===//
 //
 
-// CHECK-LABEL: MatchTable11[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 11*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
 // CHECK-NEXT:    // MIs[0] dst
@@ -597,14 +509,7 @@ def XOR : I<(outs GPR32:$dst), (ins Z:$src2, GPR32:$src1),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable11\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable11, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 11: @[[LABEL]]
 
 // The -4 is just to distinguish it from the other 'not' cases.
 def XORlike : I<(outs GPR32:$dst), (ins m1Z:$src2, GPR32:$src1),
@@ -613,8 +518,7 @@ def XORlike : I<(outs GPR32:$dst), (ins m1Z:$src2, GPR32:$src1),
 //===- Test a simple pattern with multiple operands with defaults. --------===//
 //
 
-// CHECK-LABEL: MatchTable12[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 12*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
 // CHECK-NEXT:    // MIs[0] dst
@@ -637,14 +541,7 @@ def XORlike : I<(outs GPR32:$dst), (ins m1Z:$src2, GPR32:$src1),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable12\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable12, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 12: @[[LABEL]]
 
 // The -5 is just to distinguish it from the other cases.
 def XORManyDefaults : I<(outs GPR32:$dst), (ins m1Z:$src3, Z:$src2, GPR32:$src1),
@@ -655,8 +552,7 @@ def XORManyDefaults : I<(outs GPR32:$dst), (ins m1Z:$src3, Z:$src2, GPR32:$src1)
 // This must precede the 3-register variants because constant immediates have
 // priority over register banks.
 
-// CHECK-LABEL: MatchTable13[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 13*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
 // CHECK-NEXT:    // MIs[0] dst
@@ -677,14 +573,7 @@ def XORManyDefaults : I<(outs GPR32:$dst), (ins m1Z:$src3, Z:$src2, GPR32:$src1)
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable13\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable13, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 13: @[[LABEL]]
 
 def ORN : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2), []>;
 def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>;
@@ -692,8 +581,7 @@ def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>;
 //===- Test a COPY_TO_REGCLASS --------------------------------------------===//
 //
 
-// CHECK-LABEL: MatchTable14[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 14*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BITCAST,
 // CHECK-NEXT:    // MIs[0] dst
@@ -706,22 +594,14 @@ def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>;
 // 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:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable14\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable14, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 14: @[[LABEL]]
 
 def : Pat<(i32 (bitconvert FPR32:$src1)),
           (COPY_TO_REGCLASS FPR32:$src1, GPR32)>;
 
 //===- Test a simple pattern with just a leaf immediate. ------------------===//
 
-// CHECK-LABEL: MatchTable15[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 15*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
 // CHECK-NEXT:    // MIs[0] dst
@@ -736,21 +616,13 @@ def : Pat<(i32 (bitconvert FPR32:$src1)),
 // CHECK-NEXT:    GIR_EraseFromParent, /*InsnID*/0,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
-// CHECK-NEXT:    GIM_Reject,
-// CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable15\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable15, TII, MRI, TRI, RBI, AvailableFeatures)) {
-// CHECK-NEXT:    return true;
-// CHECK-NEXT:  }
+// CHECK-NEXT:  // Label 15: @[[LABEL]]
 
 def MOV1 : I<(outs GPR32:$dst), (ins), [(set GPR32:$dst, 1)]>;
 
 //===- Test a pattern with an MBB operand. --------------------------------===//
 
-// CHECK-LABEL: MatchTable16[] = {
-// CHECK-NEXT:    GIM_Try, /*On fail goto*//*Label 0*/ [[LABEL:[0-9]+]],
+// CHECK-NEXT:  GIM_Try, /*On fail goto*//*Label 16*/ [[LABEL:[0-9]+]],
 // CHECK-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/1,
 // CHECK-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BR,
 // CHECK-NEXT:    // MIs[0] target
@@ -759,12 +631,10 @@ def MOV1 : I<(outs GPR32:$dst), (ins), [(set GPR32:$dst, 1)]>;
 // CHECK-NEXT:    GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::BR,
 // CHECK-NEXT:    GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
 // CHECK-NEXT:    GIR_Done,
-// CHECK-NEXT:    // Label 0: @[[LABEL]]
+// CHECK-NEXT:  // Label 16: @[[LABEL]]
 // CHECK-NEXT:    GIM_Reject,
 // CHECK-NEXT:  };
-// CHECK-NEXT:  MIs.resize(1);
-// CHECK-NEXT:  DEBUG(dbgs() << "Processing MatchTable16\n");
-// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable16, TII, MRI, TRI, RBI, AvailableFeatures)) {
+// CHECK-NEXT:  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable0, TII, MRI, TRI, RBI, AvailableFeatures)) {
 // CHECK-NEXT:    return true;
 // CHECK-NEXT:  }
 
index 2cfcadd..47f974a 100644 (file)
@@ -53,8 +53,6 @@ STATISTIC(NumPatternTotal, "Total number of patterns");
 STATISTIC(NumPatternImported, "Number of patterns imported from SelectionDAG");
 STATISTIC(NumPatternImportsSkipped, "Number of SelectionDAG imports skipped");
 STATISTIC(NumPatternEmitted, "Number of patterns emitted");
-/// A unique identifier for a MatchTable.
-static unsigned CurrentMatchTableID = 0;
 
 cl::OptionCategory GlobalISelEmitterCat("Options for -gen-global-isel");
 
@@ -303,6 +301,9 @@ class MatchTable {
   /// Tracks the sum of MatchTableRecord::NumElements as the table is built.
   unsigned CurrentSize;
 
+  /// A unique identifier for a MatchTable label.
+  static unsigned CurrentLabelID;
+
 public:
   static MatchTableRecord LineBreak;
   static MatchTableRecord Comment(StringRef Comment) {
@@ -338,7 +339,7 @@ public:
                                 MatchTableRecord::MTRF_LineBreakFollows);
   }
   static MatchTableRecord JumpTarget(unsigned LabelID) {
-    return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 0,
+    return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 1,
                             MatchTableRecord::MTRF_JumpTarget |
                                 MatchTableRecord::MTRF_Comment |
                                 MatchTableRecord::MTRF_CommaFollows);
@@ -353,8 +354,10 @@ public:
     CurrentSize += Value.size();
   }
 
+  unsigned allocateLabelID() const { return CurrentLabelID++; }
+
   void defineLabel(unsigned LabelID) {
-    LabelMap.insert(std::make_pair(LabelID, CurrentSize + 1));
+    LabelMap.insert(std::make_pair(LabelID, CurrentSize));
   }
 
   unsigned getLabelIndex(unsigned LabelID) const {
@@ -363,7 +366,9 @@ public:
     return I->second;
   }
 
-  void emit(raw_ostream &OS) const {
+  void emitUse(raw_ostream &OS) const { OS << "MatchTable" << ID; }
+
+  void emitDeclaration(raw_ostream &OS) const {
     unsigned Indentation = 4;
     OS << "  const static int64_t MatchTable" << ID << "[] = {";
     LineBreak.emit(OS, true, *this);
@@ -394,6 +399,8 @@ public:
   }
 };
 
+unsigned MatchTable::CurrentLabelID = 0;
+
 MatchTableRecord MatchTable::LineBreak = {
     None, "" /* Emit String */, 0 /* Elements */,
     MatchTableRecord::MTRF_LineBreakFollows};
@@ -436,11 +443,6 @@ MatchTable &operator<<(MatchTable &Table, const MatchTableRecord &Value) {
   return Table;
 }
 
-raw_ostream &operator<<(raw_ostream &OS, const MatchTable &Table) {
-  Table.emit(OS);
-  return OS;
-}
-
 //===- Matchers -----------------------------------------------------------===//
 
 class OperandMatcher;
@@ -489,7 +491,7 @@ public:
 
   void emitCaptureOpcodes(MatchTable &Table);
 
-  void emit(raw_ostream &OS);
+  void emit(MatchTable &Table);
 
   /// Compare the priority of this object and B.
   ///
@@ -1548,7 +1550,7 @@ void RuleMatcher::emitCaptureOpcodes(MatchTable &Table) {
   Matchers.front()->emitCaptureOpcodes(Table, *this, InsnVarID);
 }
 
-void RuleMatcher::emit(raw_ostream &OS) {
+void RuleMatcher::emit(MatchTable &Table) {
   if (Matchers.empty())
     llvm_unreachable("Unexpected empty matcher!");
 
@@ -1563,9 +1565,9 @@ void RuleMatcher::emit(raw_ostream &OS) {
   // on some targets but we don't need to make use of that yet.
   assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet");
 
-  MatchTable Table(CurrentMatchTableID);
+  unsigned LabelID = Table.allocateLabelID();
   Table << MatchTable::Opcode("GIM_Try", +1)
-        << MatchTable::Comment("On fail goto") << MatchTable::JumpTarget(0)
+        << MatchTable::Comment("On fail goto") << MatchTable::JumpTarget(LabelID)
         << MatchTable::LineBreak;
 
   if (!RequiredFeatures.empty()) {
@@ -1639,16 +1641,7 @@ void RuleMatcher::emit(raw_ostream &OS) {
   for (const auto &MA : Actions)
     MA->emitActionOpcodes(Table, *this, 0);
   Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak
-        << MatchTable::Label(0) << MatchTable::Opcode("GIM_Reject")
-        << MatchTable::LineBreak;
-  OS << Table
-     << "  State.MIs.resize(1);\n"
-     << "  DEBUG(dbgs() << \"Processing MatchTable" << CurrentMatchTableID
-     << "\\n\");\n"
-     << "  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable"
-     << CurrentMatchTableID << ", TII, MRI, TRI, RBI, AvailableFeatures)) {\n"
-     << "    return true;\n"
-     << "  }\n\n";
+        << MatchTable::Label(LabelID);
 }
 
 bool RuleMatcher::isHigherPriorityThan(const RuleMatcher &B) const {
@@ -2498,13 +2491,18 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
      << "  State.MIs.clear();\n"
      << "  State.MIs.push_back(&I);\n\n";
 
+  MatchTable Table(0);
   for (auto &Rule : Rules) {
-    Rule.emit(OS);
-    ++CurrentMatchTableID;
+    Rule.emit(Table);
     ++NumPatternEmitted;
-    assert(CurrentMatchTableID == NumPatternEmitted &&
-           "Statistic deviates from number of emitted tables");
   }
+  Table << MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak;
+  Table.emitDeclaration(OS);
+  OS << "  if (executeMatchTable(*this, OutMIs, State, MatcherInfo, ";
+  Table.emitUse(OS);
+  OS << ", TII, MRI, TRI, RBI, AvailableFeatures)) {\n"
+     << "    return true;\n"
+     << "  }\n\n";
 
   OS << "  return false;\n"
      << "}\n"