[llvm] 1fe7d9c - [GlobalISel] Generalize `InstructionSelector` Match Tables

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 11 00:42:46 PDT 2023


Author: pvanhout
Date: 2023-07-11T09:42:30+02:00
New Revision: 1fe7d9c79967d1e1456778e5008b8f68bc16d41f

URL: https://github.com/llvm/llvm-project/commit/1fe7d9c79967d1e1456778e5008b8f68bc16d41f
DIFF: https://github.com/llvm/llvm-project/commit/1fe7d9c79967d1e1456778e5008b8f68bc16d41f.diff

LOG: [GlobalISel] Generalize `InstructionSelector` Match Tables

Makes `InstructionSelector.h`/`InstructionSelectorImpl.h` generic so the match tables can also be used for the combiner.

Some notes:
 - Coverage was made an optional parameter of `executeMatchTable`, combines won't use it for now.
 - `GIPFP_` -> `GICXXPred_` so it's more generic. Those are just C++ predicates and aren't PatFrag-specific.
 - Pass the MatcherState directly to testMIPredicate_MI, the combiner will need it.

Reviewed By: arsenm

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

Added: 
    llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
    llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
    llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp

Modified: 
    llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
    llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
    llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
    llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
    llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
    llvm/lib/Target/ARM/ARMInstructionSelector.cpp
    llvm/lib/Target/M68k/GISel/M68kInstructionSelector.cpp
    llvm/lib/Target/Mips/MipsInstructionSelector.cpp
    llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
    llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
    llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
    llvm/lib/Target/X86/X86InstructionSelector.cpp
    llvm/test/TableGen/ContextlessPredicates.td
    llvm/test/TableGen/GlobalISelEmitter-PR39045.td
    llvm/test/TableGen/GlobalISelEmitter.td
    llvm/test/TableGen/GlobalISelEmitterCustomPredicate.td
    llvm/test/TableGen/GlobalISelEmitterOverloadedPtr.td
    llvm/test/TableGen/immarg-predicated.td
    llvm/test/TableGen/predicate-patfags.td
    llvm/utils/TableGen/GlobalISelEmitter.cpp
    llvm/utils/TableGen/GlobalISelMatchTable.cpp
    llvm/utils/TableGen/GlobalISelMatchTable.h

Removed: 
    llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
new file mode 100644
index 00000000000000..a1e0c889dc10eb
--- /dev/null
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h
@@ -0,0 +1,583 @@
+//===- llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file declares the GIMatchTableExecutor API, the opcodes supported
+/// by the match table, and some associated data structures used by the
+/// executor's implementation (see `GIMatchTableExecutorImpl.h`).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTOR_H
+#define LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTOR_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
+#include "llvm/CodeGen/LowLevelType.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/IR/Function.h"
+#include <bitset>
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <initializer_list>
+#include <optional>
+#include <vector>
+
+namespace llvm {
+
+class BlockFrequencyInfo;
+class CodeGenCoverage;
+class MachineBasicBlock;
+class ProfileSummaryInfo;
+class APInt;
+class APFloat;
+class GISelKnownBits;
+class MachineInstr;
+class MachineInstrBuilder;
+class MachineFunction;
+class MachineOperand;
+class MachineRegisterInfo;
+class RegisterBankInfo;
+class TargetInstrInfo;
+class TargetRegisterInfo;
+
+/// Container class for CodeGen predicate results.
+/// This is convenient because std::bitset does not have a constructor
+/// with an initializer list of set bits.
+///
+/// Each GIMatchTableExecutor subclass should define a PredicateBitset class
+/// with:
+///   const unsigned MAX_SUBTARGET_PREDICATES = 192;
+///   using PredicateBitset = PredicateBitsetImpl<MAX_SUBTARGET_PREDICATES>;
+/// and updating the constant to suit the target. Tablegen provides a suitable
+/// definition for the predicates in use in <Target>GenGlobalISel.inc when
+/// GET_GLOBALISEL_PREDICATE_BITSET is defined.
+template <std::size_t MaxPredicates>
+class PredicateBitsetImpl : public std::bitset<MaxPredicates> {
+public:
+  // Cannot inherit constructors because it's not supported by VC++..
+  PredicateBitsetImpl() = default;
+
+  PredicateBitsetImpl(const std::bitset<MaxPredicates> &B)
+      : std::bitset<MaxPredicates>(B) {}
+
+  PredicateBitsetImpl(std::initializer_list<unsigned> Init) {
+    for (auto I : Init)
+      std::bitset<MaxPredicates>::set(I);
+  }
+};
+
+enum {
+  GICXXPred_I64_Invalid = 0,
+  GICXXPred_APInt_Invalid = 0,
+  GICXXPred_APFloat_Invalid = 0,
+  GICXXPred_MI_Invalid = 0,
+};
+
+enum {
+  /// Begin a try-block to attempt a match and jump to OnFail if it is
+  /// unsuccessful.
+  /// - OnFail - The MatchTable entry at which to resume if the match fails.
+  ///
+  /// FIXME: This ought to take an argument indicating the number of try-blocks
+  ///        to exit on failure. It's usually one but the last match attempt of
+  ///        a block will need more. The (implemented) alternative is to tack a
+  ///        GIM_Reject on the end of each try-block which is simpler but
+  ///        requires an extra opcode and iteration in the interpreter on each
+  ///        failed match.
+  GIM_Try,
+
+  /// Switch over the opcode on the specified instruction
+  /// - InsnID - Instruction ID
+  /// - LowerBound - numerically minimum opcode supported
+  /// - UpperBound - numerically maximum + 1 opcode supported
+  /// - Default - failure jump target
+  /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets
+  GIM_SwitchOpcode,
+
+  /// Switch over the LLT on the specified instruction operand
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - LowerBound - numerically minimum Type ID supported
+  /// - UpperBound - numerically maximum + 1 Type ID supported
+  /// - Default - failure jump target
+  /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets
+  GIM_SwitchType,
+
+  /// Record the specified instruction.
+  /// The IgnoreCopies variant ignores COPY instructions.
+  /// - NewInsnID - Instruction ID to define
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  GIM_RecordInsn,
+  GIM_RecordInsnIgnoreCopies,
+
+  /// Check the feature bits
+  /// - Expected features
+  GIM_CheckFeatures,
+
+  /// Check the opcode on the specified instruction
+  /// - InsnID - Instruction ID
+  /// - Expected opcode
+  GIM_CheckOpcode,
+
+  /// Check the opcode on the specified instruction, checking 2 acceptable
+  /// alternatives.
+  /// - InsnID - Instruction ID
+  /// - Expected opcode
+  /// - Alternative expected opcode
+  GIM_CheckOpcodeIsEither,
+
+  /// Check the instruction has the right number of operands
+  /// - InsnID - Instruction ID
+  /// - Expected number of operands
+  GIM_CheckNumOperands,
+  /// Check an immediate predicate on the specified instruction
+  /// - InsnID - Instruction ID
+  /// - The predicate to test
+  GIM_CheckI64ImmPredicate,
+  /// Check an immediate predicate on the specified instruction via an APInt.
+  /// - InsnID - Instruction ID
+  /// - The predicate to test
+  GIM_CheckAPIntImmPredicate,
+  /// Check a floating point immediate predicate on the specified instruction.
+  /// - InsnID - Instruction ID
+  /// - The predicate to test
+  GIM_CheckAPFloatImmPredicate,
+  /// Check an immediate predicate on the specified instruction
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - The predicate to test
+  GIM_CheckImmOperandPredicate,
+  /// Check a memory operation has the specified atomic ordering.
+  /// - InsnID - Instruction ID
+  /// - Ordering - The AtomicOrdering value
+  GIM_CheckAtomicOrdering,
+  GIM_CheckAtomicOrderingOrStrongerThan,
+  GIM_CheckAtomicOrderingWeakerThan,
+  /// Check the size of the memory access for the given machine memory operand.
+  /// - InsnID - Instruction ID
+  /// - MMOIdx - MMO index
+  /// - Size - The size in bytes of the memory access
+  GIM_CheckMemorySizeEqualTo,
+
+  /// Check the address space of the memory access for the given machine memory
+  /// operand.
+  /// - InsnID - Instruction ID
+  /// - MMOIdx - MMO index
+  /// - NumAddrSpace - Number of valid address spaces
+  /// - AddrSpaceN - An allowed space of the memory access
+  /// - AddrSpaceN+1 ...
+  GIM_CheckMemoryAddressSpace,
+
+  /// Check the minimum alignment of the memory access for the given machine
+  /// memory operand.
+  /// - InsnID - Instruction ID
+  /// - MMOIdx - MMO index
+  /// - MinAlign - Minimum acceptable alignment
+  GIM_CheckMemoryAlignment,
+
+  /// Check the size of the memory access for the given machine memory operand
+  /// against the size of an operand.
+  /// - InsnID - Instruction ID
+  /// - MMOIdx - MMO index
+  /// - OpIdx - The operand index to compare the MMO against
+  GIM_CheckMemorySizeEqualToLLT,
+  GIM_CheckMemorySizeLessThanLLT,
+  GIM_CheckMemorySizeGreaterThanLLT,
+
+  /// Check if this is a vector that can be treated as a vector splat
+  /// constant. This is valid for both G_BUILD_VECTOR as well as
+  /// G_BUILD_VECTOR_TRUNC. For AllOnes refers to individual bits, so a -1
+  /// element.
+  /// - InsnID - Instruction ID
+  GIM_CheckIsBuildVectorAllOnes,
+  GIM_CheckIsBuildVectorAllZeros,
+
+  /// Check a generic C++ instruction predicate
+  /// - InsnID - Instruction ID
+  /// - PredicateID - The ID of the predicate function to call
+  GIM_CheckCxxInsnPredicate,
+
+  /// Check if there's no use of the first result.
+  /// - InsnID - Instruction ID
+  GIM_CheckHasNoUse,
+
+  /// Check the type for the specified operand
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - Expected type
+  GIM_CheckType,
+  /// Check the type of a pointer to any address space.
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - SizeInBits - The size of the pointer value in bits.
+  GIM_CheckPointerToAny,
+  /// Check the register bank for the specified operand
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - Expected register bank (specified as a register class)
+  GIM_CheckRegBankForClass,
+
+  /// Check the operand matches a complex predicate
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - RendererID - The renderer to hold the result
+  /// - Complex predicate ID
+  GIM_CheckComplexPattern,
+
+  /// Check the operand is a specific integer
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - Expected integer
+  GIM_CheckConstantInt,
+  /// Check the operand is a specific literal integer (i.e. MO.isImm() or
+  /// MO.isCImm() is true).
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - Expected integer
+  GIM_CheckLiteralInt,
+  /// Check the operand is a specific intrinsic ID
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - Expected Intrinsic ID
+  GIM_CheckIntrinsicID,
+
+  /// Check the operand is a specific predicate
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - Expected predicate
+  GIM_CheckCmpPredicate,
+
+  /// Check the specified operand is an MBB
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  GIM_CheckIsMBB,
+
+  /// Check the specified operand is an Imm
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  GIM_CheckIsImm,
+
+  /// Check if the specified operand is safe to fold into the current
+  /// instruction.
+  /// - InsnID - Instruction ID
+  GIM_CheckIsSafeToFold,
+
+  /// Check the specified operands are identical.
+  /// The IgnoreCopies variant looks through COPY instructions before
+  /// comparing the operands.
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - OtherInsnID - Other instruction ID
+  /// - OtherOpIdx - Other operand index
+  GIM_CheckIsSameOperand,
+  GIM_CheckIsSameOperandIgnoreCopies,
+
+  /// Predicates with 'let PredicateCodeUsesOperands = 1' need to examine some
+  /// named operands that will be recorded in RecordedOperands. Names of these
+  /// operands are referenced in predicate argument list. Emitter determines
+  /// StoreIdx(corresponds to the order in which names appear in argument list).
+  /// - InsnID - Instruction ID
+  /// - OpIdx - Operand index
+  /// - StoreIdx - Store location in RecordedOperands.
+  GIM_RecordNamedOperand,
+
+  /// Fail the current try-block, or completely fail to match if there is no
+  /// current try-block.
+  GIM_Reject,
+
+  //=== Renderers ===
+
+  /// 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 or add a zero register if the
+  /// operand is a zero immediate.
+  /// - NewInsnID - Instruction ID to modify
+  /// - OldInsnID - Instruction ID to copy from
+  /// - OpIdx - The operand to copy
+  /// - ZeroReg - The zero register to use
+  GIR_CopyOrAddZeroReg,
+  /// 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 a temporary register to the specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - TempRegID - The temporary register ID to add
+  /// - TempRegFlags - The register flags to set
+  GIR_AddTempRegister,
+
+  /// Add a temporary register to the specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - TempRegID - The temporary register ID to add
+  /// - TempRegFlags - The register flags to set
+  /// - SubRegIndex - The subregister index to set
+  GIR_AddTempSubRegister,
+
+  /// 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,
+  /// Render sub-operands of complex operands to the specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - RendererID - The renderer to call
+  /// - RenderOpID - The suboperand to render.
+  GIR_ComplexSubOperandRenderer,
+  /// Render subregisters of suboperands of complex operands to the
+  /// specified instruction
+  /// - InsnID - Instruction ID to modify
+  /// - RendererID - The renderer to call
+  /// - RenderOpID - The suboperand to render
+  /// - SubRegIdx - The subregister to extract
+  GIR_ComplexSubOperandSubRegRenderer,
+
+  /// Render operands to the specified instruction using a custom function
+  /// - InsnID - Instruction ID to modify
+  /// - OldInsnID - Instruction ID to get the matched operand from
+  /// - RendererFnID - Custom renderer function to call
+  GIR_CustomRenderer,
+
+  /// Render operands to the specified instruction using a custom function,
+  /// reading from a specific operand.
+  /// - InsnID - Instruction ID to modify
+  /// - OldInsnID - Instruction ID to get the matched operand from
+  /// - OpIdx - Operand index in OldInsnID the render function should read
+  /// from..
+  /// - RendererFnID - Custom renderer function to call
+  GIR_CustomOperandRenderer,
+
+  /// Render a G_CONSTANT operator as a sign-extended immediate.
+  /// - NewInsnID - Instruction ID to modify
+  /// - OldInsnID - Instruction ID to copy from
+  /// The operand index is implicitly 1.
+  GIR_CopyConstantAsSImm,
+
+  /// Render a G_FCONSTANT operator as a sign-extended immediate.
+  /// - NewInsnID - Instruction ID to modify
+  /// - OldInsnID - Instruction ID to copy from
+  /// The operand index is implicitly 1.
+  GIR_CopyFConstantAsFPImm,
+
+  /// 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
+  /// - MergeInsnID... - One or more Instruction ID to merge into the result.
+  /// - GIU_MergeMemOperands_EndOfList - Terminates the list of instructions to
+  ///                                    merge.
+  GIR_MergeMemOperands,
+
+  /// Erase from parent.
+  /// - InsnID - Instruction ID to erase
+  GIR_EraseFromParent,
+
+  /// Create a new temporary register that's not constrained.
+  /// - TempRegID - The temporary register ID to initialize.
+  /// - Expected type
+  GIR_MakeTempReg,
+
+  /// A successful emission
+  GIR_Done,
+
+  /// Increment the rule coverage counter.
+  /// - RuleID - The ID of the rule that was covered.
+  GIR_Coverage,
+
+  /// Keeping track of the number of the GI opcodes. Must be the last entry.
+  GIU_NumOpcodes,
+};
+
+enum {
+  /// Indicates the end of the variable-length MergeInsnID list in a
+  /// GIR_MergeMemOperands opcode.
+  GIU_MergeMemOperands_EndOfList = -1,
+};
+
+/// Provides the logic to execute GlobalISel match tables, which are used by the
+/// instruction selector and instruction combiners as their engine to match and
+/// apply MIR patterns.
+class GIMatchTableExecutor {
+public:
+  virtual ~GIMatchTableExecutor() = default;
+
+  CodeGenCoverage *CoverageInfo = nullptr;
+  GISelKnownBits *KnownBits = nullptr;
+  MachineFunction *MF = nullptr;
+  ProfileSummaryInfo *PSI = nullptr;
+  BlockFrequencyInfo *BFI = nullptr;
+  // For some predicates, we need to track the current MBB.
+  MachineBasicBlock *CurMBB = nullptr;
+
+  virtual void setupGeneratedPerFunctionState(MachineFunction &MF) {
+    llvm_unreachable("TableGen should have emitted implementation");
+  }
+
+  /// Setup per-MF executor state.
+  virtual void setupMF(MachineFunction &mf, GISelKnownBits *KB,
+                       CodeGenCoverage &covinfo, ProfileSummaryInfo *psi,
+                       BlockFrequencyInfo *bfi) {
+    CoverageInfo = &covinfo;
+    KnownBits = KB;
+    MF = &mf;
+    PSI = psi;
+    BFI = bfi;
+    CurMBB = nullptr;
+    setupGeneratedPerFunctionState(mf);
+  }
+
+protected:
+  using ComplexRendererFns =
+      std::optional<SmallVector<std::function<void(MachineInstrBuilder &)>, 4>>;
+  using RecordedMIVector = SmallVector<MachineInstr *, 4>;
+  using NewMIVector = SmallVector<MachineInstrBuilder, 4>;
+
+  struct MatcherState {
+    std::vector<ComplexRendererFns::value_type> Renderers;
+    RecordedMIVector MIs;
+    DenseMap<unsigned, unsigned> TempRegisters;
+    /// Named operands that predicate with 'let PredicateCodeUsesOperands = 1'
+    /// referenced in its argument list. Operands are inserted at index set by
+    /// emitter, it corresponds to the order in which names appear in argument
+    /// list. Currently such predicates don't have more then 3 arguments.
+    std::array<const MachineOperand *, 3> RecordedOperands;
+
+    MatcherState(unsigned MaxRenderers);
+  };
+
+  bool shouldOptForSize(const MachineFunction *MF) const {
+    const auto &F = MF->getFunction();
+    return F.hasOptSize() || F.hasMinSize() ||
+           (PSI && BFI && CurMBB && llvm::shouldOptForSize(*CurMBB, PSI, BFI));
+  }
+
+public:
+  template <class PredicateBitset, class ComplexMatcherMemFn,
+            class CustomRendererFn>
+  struct ExecInfoTy {
+    ExecInfoTy(const LLT *TypeObjects, size_t NumTypeObjects,
+               const PredicateBitset *FeatureBitsets,
+               const ComplexMatcherMemFn *ComplexPredicates,
+               const CustomRendererFn *CustomRenderers)
+        : TypeObjects(TypeObjects), FeatureBitsets(FeatureBitsets),
+          ComplexPredicates(ComplexPredicates),
+          CustomRenderers(CustomRenderers) {
+
+      for (size_t I = 0; I < NumTypeObjects; ++I)
+        TypeIDMap[TypeObjects[I]] = I;
+    }
+    const LLT *TypeObjects;
+    const PredicateBitset *FeatureBitsets;
+    const ComplexMatcherMemFn *ComplexPredicates;
+    const CustomRendererFn *CustomRenderers;
+
+    SmallDenseMap<LLT, unsigned, 64> TypeIDMap;
+  };
+
+protected:
+  GIMatchTableExecutor();
+
+  /// Execute a given matcher table and return true if the match was successful
+  /// and false otherwise.
+  template <class TgtExecutor, class PredicateBitset, class ComplexMatcherMemFn,
+            class CustomRendererFn>
+  bool executeMatchTable(
+      TgtExecutor &Exec, NewMIVector &OutMIs, MatcherState &State,
+      const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn>
+          &ISelInfo,
+      const int64_t *MatchTable, const TargetInstrInfo &TII,
+      MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
+      const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures,
+      CodeGenCoverage *CoverageInfo) const;
+
+  virtual const int64_t *getMatchTable() const {
+    llvm_unreachable("Should have been overridden by tablegen if used");
+  }
+
+  virtual bool testImmPredicate_I64(unsigned, int64_t) const {
+    llvm_unreachable(
+        "Subclasses must override this with a tablegen-erated function");
+  }
+  virtual bool testImmPredicate_APInt(unsigned, const APInt &) const {
+    llvm_unreachable(
+        "Subclasses must override this with a tablegen-erated function");
+  }
+  virtual bool testImmPredicate_APFloat(unsigned, const APFloat &) const {
+    llvm_unreachable(
+        "Subclasses must override this with a tablegen-erated function");
+  }
+  virtual bool testMIPredicate_MI(unsigned, const MachineInstr &,
+                                  const MatcherState &State) const {
+    llvm_unreachable(
+        "Subclasses must override this with a tablegen-erated function");
+  }
+
+  bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
+                         const MachineRegisterInfo &MRI) const;
+
+  /// Return true if the specified operand is a G_PTR_ADD with a G_CONSTANT on
+  /// the right-hand side. GlobalISel's separation of pointer and integer types
+  /// means that we don't need to worry about G_OR with equivalent semantics.
+  bool isBaseWithConstantOffset(const MachineOperand &Root,
+                                const MachineRegisterInfo &MRI) const;
+
+  /// Return true if MI can obviously be folded into IntoMI.
+  /// MI and IntoMI do not need to be in the same basic blocks, but MI must
+  /// preceed IntoMI.
+  bool isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTOR_H

diff  --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
similarity index 82%
rename from llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
rename to llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
index d2a03f119156c7..12bf6bc687ab77 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h
@@ -1,4 +1,4 @@
-//===- llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h --------*- C++ -*-===//
+//===- llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h -------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,17 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 //
-/// \file This file declares the API for the instruction selector.
-/// This class is responsible for selecting machine instructions.
-/// It's implemented by the target. It's used by the InstructionSelect pass.
+/// \file This file implements GIMatchTableExecutor's `executeMatchTable`
+/// function. This is implemented in a separate file because the function is
+/// quite large.
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
-#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
+#ifndef LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
+#define LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
 
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineOperand.h"
@@ -37,24 +37,16 @@
 
 namespace llvm {
 
-/// GlobalISel PatFrag Predicates
-enum {
-  GIPFP_I64_Invalid = 0,
-  GIPFP_APInt_Invalid = 0,
-  GIPFP_APFloat_Invalid = 0,
-  GIPFP_MI_Invalid = 0,
-};
-
-template <class TgtInstructionSelector, class PredicateBitset,
-          class ComplexMatcherMemFn, class CustomRendererFn>
-bool InstructionSelector::executeMatchTable(
-    TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
-    const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn>
-        &ISelInfo,
+template <class TgtExecutor, class PredicateBitset, class ComplexMatcherMemFn,
+          class CustomRendererFn>
+bool GIMatchTableExecutor::executeMatchTable(
+    TgtExecutor &Exec, NewMIVector &OutMIs, MatcherState &State,
+    const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn>
+        &ExecInfo,
     const int64_t *MatchTable, const TargetInstrInfo &TII,
     MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
     const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures,
-    CodeGenCoverage &CoverageInfo) const {
+    CodeGenCoverage *CoverageInfo) const {
 
   uint64_t CurrentIdx = 0;
   SmallVector<uint64_t, 4> OnFailResumeAt;
@@ -66,12 +58,12 @@ bool InstructionSelector::executeMatchTable(
 
   enum RejectAction { RejectAndGiveUp, RejectAndResume };
   auto handleReject = [&]() -> RejectAction {
-    DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+    DEBUG_WITH_TYPE(TgtExecutor::getName(),
                     dbgs() << CurrentIdx << ": Rejected\n");
     if (OnFailResumeAt.empty())
       return RejectAndGiveUp;
     CurrentIdx = OnFailResumeAt.pop_back_val();
-    DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+    DEBUG_WITH_TYPE(TgtExecutor::getName(),
                     dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " ("
                            << OnFailResumeAt.size() << " try-blocks remain)\n");
     return RejectAndResume;
@@ -95,7 +87,7 @@ bool InstructionSelector::executeMatchTable(
     int64_t MatcherOpcode = MatchTable[CurrentIdx++];
     switch (MatcherOpcode) {
     case GIM_Try: {
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": Begin try-block\n");
       OnFailResumeAt.push_back(MatchTable[CurrentIdx++]);
       break;
@@ -113,14 +105,14 @@ bool InstructionSelector::executeMatchTable(
 
       MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
       if (!MO.isReg()) {
-        DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+        DEBUG_WITH_TYPE(TgtExecutor::getName(),
                         dbgs() << CurrentIdx << ": Not a register\n");
         if (handleReject() == RejectAndGiveUp)
           return false;
         break;
       }
       if (MO.getReg().isPhysical()) {
-        DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+        DEBUG_WITH_TYPE(TgtExecutor::getName(),
                         dbgs() << CurrentIdx << ": Is a physical register\n");
         if (handleReject() == RejectAndGiveUp)
           return false;
@@ -140,7 +132,7 @@ bool InstructionSelector::executeMatchTable(
                "Expected to store MIs in order");
         State.MIs.push_back(NewMI);
       }
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": MIs[" << NewInsnID
                              << "] = GIM_RecordInsn(" << InsnID << ", " << OpIdx
                              << ")\n");
@@ -149,18 +141,17 @@ bool InstructionSelector::executeMatchTable(
 
     case GIM_CheckFeatures: {
       int64_t ExpectedBitsetID = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx
                              << ": GIM_CheckFeatures(ExpectedBitsetID="
                              << ExpectedBitsetID << ")\n");
-      if ((AvailableFeatures & ISelInfo.FeatureBitsets[ExpectedBitsetID]) !=
-          ISelInfo.FeatureBitsets[ExpectedBitsetID]) {
+      if ((AvailableFeatures & ExecInfo.FeatureBitsets[ExpectedBitsetID]) !=
+          ExecInfo.FeatureBitsets[ExpectedBitsetID]) {
         if (handleReject() == RejectAndGiveUp)
           return false;
       }
       break;
     }
-
     case GIM_CheckOpcode:
     case GIM_CheckOpcodeIsEither: {
       int64_t InsnID = MatchTable[CurrentIdx++];
@@ -172,13 +163,12 @@ bool InstructionSelector::executeMatchTable(
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
       unsigned Opcode = State.MIs[InsnID]->getOpcode();
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
-        dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID
-        << "], ExpectedOpcode=" << Expected0;
-        if (MatcherOpcode == GIM_CheckOpcodeIsEither)
-          dbgs() << " || " << Expected1;
-        dbgs() << ") // Got=" << Opcode << "\n";
-      );
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
+                      dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID
+                             << "], ExpectedOpcode=" << Expected0;
+                      if (MatcherOpcode == GIM_CheckOpcodeIsEither) dbgs()
+                      << " || " << Expected1;
+                      dbgs() << ") // Got=" << Opcode << "\n";);
 
       if (Opcode != Expected0 && Opcode != Expected1) {
         if (handleReject() == RejectAndGiveUp)
@@ -195,7 +185,7 @@ bool InstructionSelector::executeMatchTable(
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
       const int64_t Opcode = State.MIs[InsnID]->getOpcode();
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), {
+      DEBUG_WITH_TYPE(TgtExecutor::getName(), {
         dbgs() << CurrentIdx << ": GIM_SwitchOpcode(MIs[" << InsnID << "], ["
                << LowerBound << ", " << UpperBound << "), Default=" << Default
                << ", JumpTable...) // Got=" << Opcode << "\n";
@@ -223,7 +213,7 @@ bool InstructionSelector::executeMatchTable(
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
       MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), {
+      DEBUG_WITH_TYPE(TgtExecutor::getName(), {
         dbgs() << CurrentIdx << ": GIM_SwitchType(MIs[" << InsnID
                << "]->getOperand(" << OpIdx << "), [" << LowerBound << ", "
                << UpperBound << "), Default=" << Default
@@ -238,8 +228,8 @@ bool InstructionSelector::executeMatchTable(
         break;
       }
       const LLT Ty = MRI.getType(MO.getReg());
-      const auto TyI = ISelInfo.TypeIDMap.find(Ty);
-      if (TyI == ISelInfo.TypeIDMap.end()) {
+      const auto TyI = ExecInfo.TypeIDMap.find(Ty);
+      if (TyI == ExecInfo.TypeIDMap.end()) {
         CurrentIdx = Default;
         break;
       }
@@ -260,7 +250,7 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckNumOperands: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t Expected = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckNumOperands(MIs["
                              << InsnID << "], Expected=" << Expected << ")\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
@@ -277,7 +267,7 @@ bool InstructionSelector::executeMatchTable(
                           ? MatchTable[CurrentIdx++]
                           : 1;
       int64_t Predicate = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckImmPredicate(MIs["
                              << InsnID << "]->getOperand(" << OpIdx
                              << "), Predicate=" << Predicate << ")\n");
@@ -285,7 +275,7 @@ bool InstructionSelector::executeMatchTable(
       assert((State.MIs[InsnID]->getOperand(OpIdx).isImm() ||
               State.MIs[InsnID]->getOperand(OpIdx).isCImm()) &&
              "Expected immediate operand");
-      assert(Predicate > GIPFP_I64_Invalid && "Expected a valid predicate");
+      assert(Predicate > GICXXPred_I64_Invalid && "Expected a valid predicate");
       int64_t Value = 0;
       if (State.MIs[InsnID]->getOperand(OpIdx).isCImm())
         Value = State.MIs[InsnID]->getOperand(OpIdx).getCImm()->getSExtValue();
@@ -302,20 +292,20 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckAPIntImmPredicate: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t Predicate = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs()
                           << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs["
                           << InsnID << "], Predicate=" << Predicate << ")\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
       assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
              "Expected G_CONSTANT");
-      assert(Predicate > GIPFP_APInt_Invalid && "Expected a valid predicate");
-      APInt Value;
-      if (State.MIs[InsnID]->getOperand(1).isCImm())
-        Value = State.MIs[InsnID]->getOperand(1).getCImm()->getValue();
-      else
+      assert(Predicate > GICXXPred_APInt_Invalid &&
+             "Expected a valid predicate");
+      if (!State.MIs[InsnID]->getOperand(1).isCImm())
         llvm_unreachable("Expected Imm or CImm operand");
 
+      const APInt &Value =
+          State.MIs[InsnID]->getOperand(1).getCImm()->getValue();
       if (!testImmPredicate_APInt(Predicate, Value))
         if (handleReject() == RejectAndGiveUp)
           return false;
@@ -324,16 +314,19 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckAPFloatImmPredicate: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t Predicate = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs()
                           << CurrentIdx << ": GIM_CheckAPFloatImmPredicate(MIs["
                           << InsnID << "], Predicate=" << Predicate << ")\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
       assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
              "Expected G_FCONSTANT");
-      assert(State.MIs[InsnID]->getOperand(1).isFPImm() && "Expected FPImm operand");
-      assert(Predicate > GIPFP_APFloat_Invalid && "Expected a valid predicate");
-      APFloat Value = State.MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF();
+      assert(State.MIs[InsnID]->getOperand(1).isFPImm() &&
+             "Expected FPImm operand");
+      assert(Predicate > GICXXPred_APFloat_Invalid &&
+             "Expected a valid predicate");
+      const APFloat &Value =
+          State.MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF();
 
       if (!testImmPredicate_APFloat(Predicate, Value))
         if (handleReject() == RejectAndGiveUp)
@@ -344,7 +337,7 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckIsBuildVectorAllZeros: {
       int64_t InsnID = MatchTable[CurrentIdx++];
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx
                              << ": GIM_CheckBuildVectorAll{Zeros|Ones}(MIs["
                              << InsnID << "])\n");
@@ -372,15 +365,14 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckCxxInsnPredicate: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t Predicate = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs()
                           << CurrentIdx << ": GIM_CheckCxxPredicate(MIs["
                           << InsnID << "], Predicate=" << Predicate << ")\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
-      assert(Predicate > GIPFP_MI_Invalid && "Expected a valid predicate");
+      assert(Predicate > GICXXPred_MI_Invalid && "Expected a valid predicate");
 
-      if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID],
-                              State.RecordedOperands))
+      if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID], State))
         if (handleReject() == RejectAndGiveUp)
           return false;
       break;
@@ -388,7 +380,7 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckHasNoUse: {
       int64_t InsnID = MatchTable[CurrentIdx++];
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckHasNoUse(MIs["
                              << InsnID << "]\n");
 
@@ -407,7 +399,7 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckAtomicOrdering: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs["
                              << InsnID << "], " << (uint64_t)Ordering << ")\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
@@ -424,7 +416,7 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckAtomicOrderingOrStrongerThan: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx
                              << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs["
                              << InsnID << "], " << (uint64_t)Ordering << ")\n");
@@ -442,7 +434,7 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckAtomicOrderingWeakerThan: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx
                              << ": GIM_CheckAtomicOrderingWeakerThan(MIs["
                              << InsnID << "], " << (uint64_t)Ordering << ")\n");
@@ -473,17 +465,16 @@ bool InstructionSelector::executeMatchTable(
       // a match earlier.
       const uint64_t LastIdx = CurrentIdx + NumAddrSpace;
 
-      const MachineMemOperand *MMO
-        = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
+      const MachineMemOperand *MMO =
+          *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
       const unsigned MMOAddrSpace = MMO->getAddrSpace();
 
       bool Success = false;
       for (int I = 0; I != NumAddrSpace; ++I) {
         unsigned AddrSpace = MatchTable[CurrentIdx++];
-        DEBUG_WITH_TYPE(
-          TgtInstructionSelector::getName(),
-          dbgs() << "addrspace(" << MMOAddrSpace << ") vs "
-                 << AddrSpace << '\n');
+        DEBUG_WITH_TYPE(TgtExecutor::getName(),
+                        dbgs() << "addrspace(" << MMOAddrSpace << ") vs "
+                               << AddrSpace << '\n');
 
         if (AddrSpace == MMOAddrSpace) {
           Success = true;
@@ -509,12 +500,13 @@ bool InstructionSelector::executeMatchTable(
         break;
       }
 
-      MachineMemOperand *MMO
-        = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      MachineMemOperand *MMO =
+          *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckMemoryAlignment"
-                      << "(MIs[" << InsnID << "]->memoperands() + " << MMOIdx
-                      << ")->getAlignment() >= " << MinAlign << ")\n");
+                             << "(MIs[" << InsnID << "]->memoperands() + "
+                             << MMOIdx << ")->getAlignment() >= " << MinAlign
+                             << ")\n");
       if (MMO->getAlign() < MinAlign && handleReject() == RejectAndGiveUp)
         return false;
 
@@ -525,10 +517,9 @@ bool InstructionSelector::executeMatchTable(
       int64_t MMOIdx = MatchTable[CurrentIdx++];
       uint64_t Size = MatchTable[CurrentIdx++];
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
-                      dbgs() << CurrentIdx
-                             << ": GIM_CheckMemorySizeEqual(MIs[" << InsnID
-                             << "]->memoperands() + " << MMOIdx
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
+                      dbgs() << CurrentIdx << ": GIM_CheckMemorySizeEqual(MIs["
+                             << InsnID << "]->memoperands() + " << MMOIdx
                              << ", Size=" << Size << ")\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
 
@@ -538,11 +529,12 @@ bool InstructionSelector::executeMatchTable(
         break;
       }
 
-      MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
+      MachineMemOperand *MMO =
+          *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
-                      dbgs() << MMO->getSize() << " bytes vs " << Size
-                             << " bytes\n");
+      DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << MMO->getSize()
+                                                     << " bytes vs " << Size
+                                                     << " bytes\n");
       if (MMO->getSize() != Size)
         if (handleReject() == RejectAndGiveUp)
           return false;
@@ -557,20 +549,19 @@ bool InstructionSelector::executeMatchTable(
       int64_t OpIdx = MatchTable[CurrentIdx++];
 
       DEBUG_WITH_TYPE(
-          TgtInstructionSelector::getName(),
+          TgtExecutor::getName(),
           dbgs() << CurrentIdx << ": GIM_CheckMemorySize"
-                 << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT
-                         ? "EqualTo"
-                         : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT
-                               ? "GreaterThan"
-                               : "LessThan")
+                 << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT ? "EqualTo"
+                     : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT
+                         ? "GreaterThan"
+                         : "LessThan")
                  << "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx
                  << ", OpIdx=" << OpIdx << ")\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
 
       MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
       if (!MO.isReg()) {
-        DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+        DEBUG_WITH_TYPE(TgtExecutor::getName(),
                         dbgs() << CurrentIdx << ": Not a register\n");
         if (handleReject() == RejectAndGiveUp)
           return false;
@@ -583,7 +574,8 @@ bool InstructionSelector::executeMatchTable(
         break;
       }
 
-      MachineMemOperand *MMO = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
+      MachineMemOperand *MMO =
+          *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
 
       unsigned Size = MRI.getType(MO.getReg()).getSizeInBits();
       if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT &&
@@ -605,14 +597,14 @@ bool InstructionSelector::executeMatchTable(
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t OpIdx = MatchTable[CurrentIdx++];
       int64_t TypeID = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckType(MIs[" << InsnID
                              << "]->getOperand(" << OpIdx
                              << "), TypeID=" << TypeID << ")\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
       MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
       if (!MO.isReg() ||
-          MRI.getType(MO.getReg()) != ISelInfo.TypeObjects[TypeID]) {
+          MRI.getType(MO.getReg()) != ExecInfo.TypeObjects[TypeID]) {
         if (handleReject() == RejectAndGiveUp)
           return false;
       }
@@ -623,7 +615,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t OpIdx = MatchTable[CurrentIdx++];
       uint64_t SizeInBits = MatchTable[CurrentIdx++];
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs["
                              << InsnID << "]->getOperand(" << OpIdx
                              << "), SizeInBits=" << SizeInBits << ")\n");
@@ -654,7 +646,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t OpIdx = MatchTable[CurrentIdx++];
       uint64_t StoreIdx = MatchTable[CurrentIdx++];
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_RecordNamedOperand(MIs["
                              << InsnID << "]->getOperand(" << OpIdx
                              << "), StoreIdx=" << StoreIdx << ")\n");
@@ -667,7 +659,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t OpIdx = MatchTable[CurrentIdx++];
       int64_t RCEnum = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckRegBankForClass(MIs["
                              << InsnID << "]->getOperand(" << OpIdx
                              << "), RCEnum=" << RCEnum << ")\n");
@@ -688,7 +680,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t OpIdx = MatchTable[CurrentIdx++];
       int64_t RendererID = MatchTable[CurrentIdx++];
       int64_t ComplexPredicateID = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": State.Renderers[" << RendererID
                              << "] = GIM_CheckComplexPattern(MIs[" << InsnID
                              << "]->getOperand(" << OpIdx
@@ -697,13 +689,12 @@ bool InstructionSelector::executeMatchTable(
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
       // FIXME: Use std::invoke() when it's available.
       ComplexRendererFns Renderer =
-          (ISel.*ISelInfo.ComplexPredicates[ComplexPredicateID])(
+          (Exec.*ExecInfo.ComplexPredicates[ComplexPredicateID])(
               State.MIs[InsnID]->getOperand(OpIdx));
       if (Renderer)
         State.Renderers[RendererID] = *Renderer;
-      else
-        if (handleReject() == RejectAndGiveUp)
-          return false;
+      else if (handleReject() == RejectAndGiveUp)
+        return false;
       break;
     }
 
@@ -711,7 +702,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t OpIdx = MatchTable[CurrentIdx++];
       int64_t Value = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckConstantInt(MIs["
                              << InsnID << "]->getOperand(" << OpIdx
                              << "), Value=" << Value << ")\n");
@@ -736,7 +727,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t OpIdx = MatchTable[CurrentIdx++];
       int64_t Value = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckLiteralInt(MIs["
                              << InsnID << "]->getOperand(" << OpIdx
                              << "), Value=" << Value << ")\n");
@@ -758,7 +749,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t OpIdx = MatchTable[CurrentIdx++];
       int64_t Value = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckIntrinsicID(MIs["
                              << InsnID << "]->getOperand(" << OpIdx
                              << "), Value=" << Value << ")\n");
@@ -773,7 +764,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t OpIdx = MatchTable[CurrentIdx++];
       int64_t Value = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckCmpPredicate(MIs["
                              << InsnID << "]->getOperand(" << OpIdx
                              << "), Value=" << Value << ")\n");
@@ -787,7 +778,7 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckIsMBB: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t OpIdx = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckIsMBB(MIs[" << InsnID
                              << "]->getOperand(" << OpIdx << "))\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
@@ -800,7 +791,7 @@ bool InstructionSelector::executeMatchTable(
     case GIM_CheckIsImm: {
       int64_t InsnID = MatchTable[CurrentIdx++];
       int64_t OpIdx = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckIsImm(MIs[" << InsnID
                              << "]->getOperand(" << OpIdx << "))\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
@@ -812,7 +803,7 @@ bool InstructionSelector::executeMatchTable(
     }
     case GIM_CheckIsSafeToFold: {
       int64_t InsnID = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckIsSafeToFold(MIs["
                              << InsnID << "])\n");
       assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
@@ -828,7 +819,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t OpIdx = MatchTable[CurrentIdx++];
       int64_t OtherInsnID = MatchTable[CurrentIdx++];
       int64_t OtherOpIdx = MatchTable[CurrentIdx++];
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_CheckIsSameOperand(MIs["
                              << InsnID << "][" << OpIdx << "], MIs["
                              << OtherInsnID << "][" << OtherOpIdx << "])\n");
@@ -854,12 +845,11 @@ bool InstructionSelector::executeMatchTable(
       break;
     }
     case GIM_Reject:
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIM_Reject\n");
       if (handleReject() == RejectAndGiveUp)
         return false;
       break;
-
     case GIR_MutateOpcode: {
       int64_t OldInsnID = MatchTable[CurrentIdx++];
       uint64_t NewInsnID = MatchTable[CurrentIdx++];
@@ -870,7 +860,7 @@ bool InstructionSelector::executeMatchTable(
       OutMIs[NewInsnID] = MachineInstrBuilder(*State.MIs[OldInsnID]->getMF(),
                                               State.MIs[OldInsnID]);
       OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs["
                              << NewInsnID << "], MIs[" << OldInsnID << "], "
                              << NewOpcode << ")\n");
@@ -885,7 +875,7 @@ bool InstructionSelector::executeMatchTable(
 
       OutMIs[NewInsnID] = BuildMI(*State.MIs[0]->getParent(), State.MIs[0],
                                   MIMetadata(*State.MIs[0]), TII.get(Opcode));
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs["
                              << NewInsnID << "], " << Opcode << ")\n");
       break;
@@ -897,7 +887,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t OpIdx = MatchTable[CurrentIdx++];
       assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
       OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs()
                           << CurrentIdx << ": GIR_Copy(OutMIs[" << NewInsnID
                           << "], MIs[" << OldInsnID << "], " << OpIdx << ")\n");
@@ -915,7 +905,7 @@ bool InstructionSelector::executeMatchTable(
         OutMIs[NewInsnID].addReg(ZeroReg);
       else
         OutMIs[NewInsnID].add(MO);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_CopyOrAddZeroReg(OutMIs["
                              << NewInsnID << "], MIs[" << OldInsnID << "], "
                              << OpIdx << ", " << ZeroReg << ")\n");
@@ -930,7 +920,7 @@ bool InstructionSelector::executeMatchTable(
       assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
       OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
                                0, SubRegIdx);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_CopySubReg(OutMIs["
                              << NewInsnID << "], MIs[" << OldInsnID << "], "
                              << OpIdx << ", " << SubRegIdx << ")\n");
@@ -942,7 +932,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t RegNum = MatchTable[CurrentIdx++];
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
       OutMIs[InsnID].addDef(RegNum, RegState::Implicit);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_AddImplicitDef(OutMIs["
                              << InsnID << "], " << RegNum << ")\n");
       break;
@@ -953,7 +943,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t RegNum = MatchTable[CurrentIdx++];
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
       OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_AddImplicitUse(OutMIs["
                              << InsnID << "], " << RegNum << ")\n");
       break;
@@ -965,10 +955,10 @@ bool InstructionSelector::executeMatchTable(
       uint64_t RegFlags = MatchTable[CurrentIdx++];
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
       OutMIs[InsnID].addReg(RegNum, RegFlags);
-      DEBUG_WITH_TYPE(
-        TgtInstructionSelector::getName(),
-        dbgs() << CurrentIdx << ": GIR_AddRegister(OutMIs["
-        << InsnID << "], " << RegNum << ", " << RegFlags << ")\n");
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
+                      dbgs()
+                          << CurrentIdx << ": GIR_AddRegister(OutMIs[" << InsnID
+                          << "], " << RegNum << ", " << RegFlags << ")\n");
       break;
     }
 
@@ -983,14 +973,14 @@ bool InstructionSelector::executeMatchTable(
 
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
 
-      OutMIs[InsnID].addReg(State.TempRegisters[TempRegID], TempRegFlags, SubReg);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
-                      dbgs() << CurrentIdx << ": GIR_AddTempRegister(OutMIs["
-                             << InsnID << "], TempRegisters[" << TempRegID
-                             << "]";
-                      if (SubReg)
-                        dbgs() << '.' << TRI.getSubRegIndexName(SubReg);
-                      dbgs() << ", " << TempRegFlags << ")\n");
+      OutMIs[InsnID].addReg(State.TempRegisters[TempRegID], TempRegFlags,
+                            SubReg);
+      DEBUG_WITH_TYPE(
+          TgtExecutor::getName(),
+          dbgs() << CurrentIdx << ": GIR_AddTempRegister(OutMIs[" << InsnID
+                 << "], TempRegisters[" << TempRegID << "]";
+          if (SubReg) dbgs() << '.' << TRI.getSubRegIndexName(SubReg);
+          dbgs() << ", " << TempRegFlags << ")\n");
       break;
     }
 
@@ -999,7 +989,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t Imm = MatchTable[CurrentIdx++];
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
       OutMIs[InsnID].addImm(Imm);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_AddImm(OutMIs[" << InsnID
                              << "], " << Imm << ")\n");
       break;
@@ -1011,7 +1001,7 @@ bool InstructionSelector::executeMatchTable(
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
       for (const auto &RenderOpFn : State.Renderers[RendererID])
         RenderOpFn(OutMIs[InsnID]);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_ComplexRenderer(OutMIs["
                              << InsnID << "], " << RendererID << ")\n");
       break;
@@ -1022,7 +1012,7 @@ bool InstructionSelector::executeMatchTable(
       int64_t RenderOpID = MatchTable[CurrentIdx++];
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
       State.Renderers[RendererID][RenderOpID](OutMIs[InsnID]);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx
                              << ": GIR_ComplexSubOperandRenderer(OutMIs["
                              << InsnID << "], " << RendererID << ", "
@@ -1038,7 +1028,7 @@ bool InstructionSelector::executeMatchTable(
       assert(MI && "Attempted to add to undefined instruction");
       State.Renderers[RendererID][RenderOpID](MI);
       MI->getOperand(MI->getNumOperands() - 1).setSubReg(SubRegIdx);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx
                              << ": GIR_ComplexSubOperandSubRegRenderer(OutMIs["
                              << InsnID << "], " << RendererID << ", "
@@ -1050,7 +1040,8 @@ bool InstructionSelector::executeMatchTable(
       int64_t NewInsnID = MatchTable[CurrentIdx++];
       int64_t OldInsnID = MatchTable[CurrentIdx++];
       assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
-      assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT && "Expected G_CONSTANT");
+      assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
+             "Expected G_CONSTANT");
       if (State.MIs[OldInsnID]->getOperand(1).isCImm()) {
         OutMIs[NewInsnID].addImm(
             State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue());
@@ -1058,7 +1049,7 @@ bool InstructionSelector::executeMatchTable(
         OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1));
       else
         llvm_unreachable("Expected Imm or CImm operand");
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs["
                              << NewInsnID << "], MIs[" << OldInsnID << "])\n");
       break;
@@ -1069,15 +1060,17 @@ bool InstructionSelector::executeMatchTable(
       int64_t NewInsnID = MatchTable[CurrentIdx++];
       int64_t OldInsnID = MatchTable[CurrentIdx++];
       assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
-      assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT && "Expected G_FCONSTANT");
+      assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
+             "Expected G_FCONSTANT");
       if (State.MIs[OldInsnID]->getOperand(1).isFPImm())
         OutMIs[NewInsnID].addFPImm(
             State.MIs[OldInsnID]->getOperand(1).getFPImm());
       else
         llvm_unreachable("Expected FPImm operand");
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
-                      dbgs() << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs["
-                             << NewInsnID << "], MIs[" << OldInsnID << "])\n");
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
+                      dbgs()
+                          << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs["
+                          << NewInsnID << "], MIs[" << OldInsnID << "])\n");
       break;
     }
 
@@ -1086,13 +1079,13 @@ bool InstructionSelector::executeMatchTable(
       int64_t OldInsnID = MatchTable[CurrentIdx++];
       int64_t RendererFnID = MatchTable[CurrentIdx++];
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs["
                              << InsnID << "], MIs[" << OldInsnID << "], "
                              << RendererFnID << ")\n");
-      (ISel.*ISelInfo.CustomRenderers[RendererFnID])(
-        OutMIs[InsnID], *State.MIs[OldInsnID],
-        -1); // Not a source operand of the old instruction.
+      (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
+          OutMIs[InsnID], *State.MIs[OldInsnID],
+          -1); // Not a source operand of the old instruction.
       break;
     }
     case GIR_CustomOperandRenderer: {
@@ -1102,15 +1095,13 @@ bool InstructionSelector::executeMatchTable(
       int64_t RendererFnID = MatchTable[CurrentIdx++];
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
 
-      DEBUG_WITH_TYPE(
-        TgtInstructionSelector::getName(),
-        dbgs() << CurrentIdx << ": GIR_CustomOperandRenderer(OutMIs["
-               << InsnID << "], MIs[" << OldInsnID << "]->getOperand("
-               << OpIdx << "), "
-        << RendererFnID << ")\n");
-      (ISel.*ISelInfo.CustomRenderers[RendererFnID])(OutMIs[InsnID],
-                                                     *State.MIs[OldInsnID],
-                                                     OpIdx);
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
+                      dbgs() << CurrentIdx
+                             << ": GIR_CustomOperandRenderer(OutMIs[" << InsnID
+                             << "], MIs[" << OldInsnID << "]->getOperand("
+                             << OpIdx << "), " << RendererFnID << ")\n");
+      (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
+          OutMIs[InsnID], *State.MIs[OldInsnID], OpIdx);
       break;
     }
     case GIR_ConstrainOperandRC: {
@@ -1124,7 +1115,7 @@ bool InstructionSelector::executeMatchTable(
       const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum);
       MachineOperand &MO = I.getOperand(OpIdx);
       constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs["
                              << InsnID << "], " << OpIdx << ", " << RCEnum
                              << ")\n");
@@ -1136,7 +1127,7 @@ bool InstructionSelector::executeMatchTable(
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
       constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
                                        RBI);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx
                              << ": GIR_ConstrainSelectedInstOperands(OutMIs["
                              << InsnID << "])\n");
@@ -1147,18 +1138,18 @@ bool InstructionSelector::executeMatchTable(
       int64_t InsnID = MatchTable[CurrentIdx++];
       assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_MergeMemOperands(OutMIs["
                              << InsnID << "]");
       int64_t MergeInsnID = GIU_MergeMemOperands_EndOfList;
       while ((MergeInsnID = MatchTable[CurrentIdx++]) !=
              GIU_MergeMemOperands_EndOfList) {
-        DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+        DEBUG_WITH_TYPE(TgtExecutor::getName(),
                         dbgs() << ", MIs[" << MergeInsnID << "]");
         for (const auto &MMO : State.MIs[MergeInsnID]->memoperands())
           OutMIs[InsnID].addMemOperand(MMO);
       }
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(), dbgs() << ")\n");
+      DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << ")\n");
       break;
     }
 
@@ -1167,7 +1158,7 @@ bool InstructionSelector::executeMatchTable(
       assert(State.MIs[InsnID] &&
              "Attempted to erase an undefined instruction");
       State.MIs[InsnID]->eraseFromParent();
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs["
                              << InsnID << "])\n");
       break;
@@ -1178,8 +1169,8 @@ bool InstructionSelector::executeMatchTable(
       int64_t TypeID = MatchTable[CurrentIdx++];
 
       State.TempRegisters[TempRegID] =
-          MRI.createGenericVirtualRegister(ISelInfo.TypeObjects[TypeID]);
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+          MRI.createGenericVirtualRegister(ExecInfo.TypeObjects[TypeID]);
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": TempRegs[" << TempRegID
                              << "] = GIR_MakeTempReg(" << TypeID << ")\n");
       break;
@@ -1187,20 +1178,20 @@ bool InstructionSelector::executeMatchTable(
 
     case GIR_Coverage: {
       int64_t RuleID = MatchTable[CurrentIdx++];
-      CoverageInfo.setCovered(RuleID);
+      assert(CoverageInfo);
+      CoverageInfo->setCovered(RuleID);
 
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
-                      dbgs()
-                          << CurrentIdx << ": GIR_Coverage(" << RuleID << ")");
+      DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx
+                                                     << ": GIR_Coverage("
+                                                     << RuleID << ")");
       break;
     }
 
     case GIR_Done:
-      DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
+      DEBUG_WITH_TYPE(TgtExecutor::getName(),
                       dbgs() << CurrentIdx << ": GIR_Done\n");
       propagateFlags(OutMIs);
       return true;
-
     default:
       llvm_unreachable("Unexpected command");
     }
@@ -1209,4 +1200,4 @@ bool InstructionSelector::executeMatchTable(
 
 } // end namespace llvm
 
-#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
+#endif // LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H

diff  --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
index fda84080636b6f..1662136cfa94af 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
@@ -7,441 +7,18 @@
 //===----------------------------------------------------------------------===//
 //
 /// \file This file declares the API for the instruction selector.
-/// This class is responsible for selecting machine instructions.
-/// It's implemented by the target. It's used by the InstructionSelect pass.
 //
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
 #define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
 
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/CodeGen/GlobalISel/Utils.h"
-#include "llvm/CodeGen/LowLevelType.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/IR/Function.h"
-#include <bitset>
-#include <cstddef>
-#include <cstdint>
-#include <functional>
-#include <initializer_list>
-#include <optional>
-#include <vector>
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
 
 namespace llvm {
-
-class BlockFrequencyInfo;
-class CodeGenCoverage;
-class MachineBasicBlock;
-class ProfileSummaryInfo;
-class APInt;
-class APFloat;
-class GISelKnownBits;
-class MachineInstr;
-class MachineInstrBuilder;
-class MachineFunction;
-class MachineOperand;
-class MachineRegisterInfo;
-class RegisterBankInfo;
-class TargetInstrInfo;
-class TargetRegisterInfo;
-
-/// Container class for CodeGen predicate results.
-/// This is convenient because std::bitset does not have a constructor
-/// with an initializer list of set bits.
-///
-/// Each InstructionSelector subclass should define a PredicateBitset class
-/// with:
-///   const unsigned MAX_SUBTARGET_PREDICATES = 192;
-///   using PredicateBitset = PredicateBitsetImpl<MAX_SUBTARGET_PREDICATES>;
-/// and updating the constant to suit the target. Tablegen provides a suitable
-/// definition for the predicates in use in <Target>GenGlobalISel.inc when
-/// GET_GLOBALISEL_PREDICATE_BITSET is defined.
-template <std::size_t MaxPredicates>
-class PredicateBitsetImpl : public std::bitset<MaxPredicates> {
-public:
-  // Cannot inherit constructors because it's not supported by VC++..
-  PredicateBitsetImpl() = default;
-
-  PredicateBitsetImpl(const std::bitset<MaxPredicates> &B)
-      : std::bitset<MaxPredicates>(B) {}
-
-  PredicateBitsetImpl(std::initializer_list<unsigned> Init) {
-    for (auto I : Init)
-      std::bitset<MaxPredicates>::set(I);
-  }
-};
-
-enum {
-  /// Begin a try-block to attempt a match and jump to OnFail if it is
-  /// unsuccessful.
-  /// - OnFail - The MatchTable entry at which to resume if the match fails.
-  ///
-  /// FIXME: This ought to take an argument indicating the number of try-blocks
-  ///        to exit on failure. It's usually one but the last match attempt of
-  ///        a block will need more. The (implemented) alternative is to tack a
-  ///        GIM_Reject on the end of each try-block which is simpler but
-  ///        requires an extra opcode and iteration in the interpreter on each
-  ///        failed match.
-  GIM_Try,
-
-  /// Switch over the opcode on the specified instruction
-  /// - InsnID - Instruction ID
-  /// - LowerBound - numerically minimum opcode supported
-  /// - UpperBound - numerically maximum + 1 opcode supported
-  /// - Default - failure jump target
-  /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets
-  GIM_SwitchOpcode,
-
-  /// Switch over the LLT on the specified instruction operand
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - LowerBound - numerically minimum Type ID supported
-  /// - UpperBound - numerically maximum + 1 Type ID supported
-  /// - Default - failure jump target
-  /// - JumpTable... - (UpperBound - LowerBound) (at least 2) jump targets
-  GIM_SwitchType,
-
-  /// Record the specified instruction.
-  /// The IgnoreCopies variant ignores COPY instructions.
-  /// - NewInsnID - Instruction ID to define
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  GIM_RecordInsn,
-  GIM_RecordInsnIgnoreCopies,
-
-  /// Check the feature bits
-  /// - Expected features
-  GIM_CheckFeatures,
-
-  /// Check the opcode on the specified instruction
-  /// - InsnID - Instruction ID
-  /// - Expected opcode
-  GIM_CheckOpcode,
-
-  /// Check the opcode on the specified instruction, checking 2 acceptable
-  /// alternatives.
-  /// - InsnID - Instruction ID
-  /// - Expected opcode
-  /// - Alternative expected opcode
-  GIM_CheckOpcodeIsEither,
-
-  /// Check the instruction has the right number of operands
-  /// - InsnID - Instruction ID
-  /// - Expected number of operands
-  GIM_CheckNumOperands,
-  /// Check an immediate predicate on the specified instruction
-  /// - InsnID - Instruction ID
-  /// - The predicate to test
-  GIM_CheckI64ImmPredicate,
-  /// Check an immediate predicate on the specified instruction via an APInt.
-  /// - InsnID - Instruction ID
-  /// - The predicate to test
-  GIM_CheckAPIntImmPredicate,
-  /// Check a floating point immediate predicate on the specified instruction.
-  /// - InsnID - Instruction ID
-  /// - The predicate to test
-  GIM_CheckAPFloatImmPredicate,
-  /// Check an immediate predicate on the specified instruction
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - The predicate to test
-  GIM_CheckImmOperandPredicate,
-  /// Check a memory operation has the specified atomic ordering.
-  /// - InsnID - Instruction ID
-  /// - Ordering - The AtomicOrdering value
-  GIM_CheckAtomicOrdering,
-  GIM_CheckAtomicOrderingOrStrongerThan,
-  GIM_CheckAtomicOrderingWeakerThan,
-  /// Check the size of the memory access for the given machine memory operand.
-  /// - InsnID - Instruction ID
-  /// - MMOIdx - MMO index
-  /// - Size - The size in bytes of the memory access
-  GIM_CheckMemorySizeEqualTo,
-
-  /// Check the address space of the memory access for the given machine memory
-  /// operand.
-  /// - InsnID - Instruction ID
-  /// - MMOIdx - MMO index
-  /// - NumAddrSpace - Number of valid address spaces
-  /// - AddrSpaceN - An allowed space of the memory access
-  /// - AddrSpaceN+1 ...
-  GIM_CheckMemoryAddressSpace,
-
-  /// Check the minimum alignment of the memory access for the given machine
-  /// memory operand.
-  /// - InsnID - Instruction ID
-  /// - MMOIdx - MMO index
-  /// - MinAlign - Minimum acceptable alignment
-  GIM_CheckMemoryAlignment,
-
-  /// Check the size of the memory access for the given machine memory operand
-  /// against the size of an operand.
-  /// - InsnID - Instruction ID
-  /// - MMOIdx - MMO index
-  /// - OpIdx - The operand index to compare the MMO against
-  GIM_CheckMemorySizeEqualToLLT,
-  GIM_CheckMemorySizeLessThanLLT,
-  GIM_CheckMemorySizeGreaterThanLLT,
-
-  /// Check if this is a vector that can be treated as a vector splat
-  /// constant. This is valid for both G_BUILD_VECTOR as well as
-  /// G_BUILD_VECTOR_TRUNC. For AllOnes refers to individual bits, so a -1
-  /// element.
-  /// - InsnID - Instruction ID
-  GIM_CheckIsBuildVectorAllOnes,
-  GIM_CheckIsBuildVectorAllZeros,
-
-  /// Check a generic C++ instruction predicate
-  /// - InsnID - Instruction ID
-  /// - PredicateID - The ID of the predicate function to call
-  GIM_CheckCxxInsnPredicate,
-
-  /// Check if there's no use of the first result.
-  /// - InsnID - Instruction ID
-  GIM_CheckHasNoUse,
-
-  /// Check the type for the specified operand
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - Expected type
-  GIM_CheckType,
-  /// Check the type of a pointer to any address space.
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - SizeInBits - The size of the pointer value in bits.
-  GIM_CheckPointerToAny,
-  /// Check the register bank for the specified operand
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - Expected register bank (specified as a register class)
-  GIM_CheckRegBankForClass,
-
-  /// Check the operand matches a complex predicate
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - RendererID - The renderer to hold the result
-  /// - Complex predicate ID
-  GIM_CheckComplexPattern,
-
-  /// Check the operand is a specific integer
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - Expected integer
-  GIM_CheckConstantInt,
-  /// Check the operand is a specific literal integer (i.e. MO.isImm() or
-  /// MO.isCImm() is true).
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - Expected integer
-  GIM_CheckLiteralInt,
-  /// Check the operand is a specific intrinsic ID
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - Expected Intrinsic ID
-  GIM_CheckIntrinsicID,
-
-  /// Check the operand is a specific predicate
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - Expected predicate
-  GIM_CheckCmpPredicate,
-
-  /// Check the specified operand is an MBB
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  GIM_CheckIsMBB,
-
-  /// Check the specified operand is an Imm
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  GIM_CheckIsImm,
-
-  /// Check if the specified operand is safe to fold into the current
-  /// instruction.
-  /// - InsnID - Instruction ID
-  GIM_CheckIsSafeToFold,
-
-  /// Check the specified operands are identical.
-  /// The IgnoreCopies variant looks through COPY instructions before
-  /// comparing the operands.
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - OtherInsnID - Other instruction ID
-  /// - OtherOpIdx - Other operand index
-  GIM_CheckIsSameOperand,
-  GIM_CheckIsSameOperandIgnoreCopies,
-
-  /// Predicates with 'let PredicateCodeUsesOperands = 1' need to examine some
-  /// named operands that will be recorded in RecordedOperands. Names of these
-  /// operands are referenced in predicate argument list. Emitter determines
-  /// StoreIdx(corresponds to the order in which names appear in argument list).
-  /// - InsnID - Instruction ID
-  /// - OpIdx - Operand index
-  /// - StoreIdx - Store location in RecordedOperands.
-  GIM_RecordNamedOperand,
-
-  /// Fail the current try-block, or completely fail to match if there is no
-  /// current try-block.
-  GIM_Reject,
-
-  //=== Renderers ===
-
-  /// 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 or add a zero register if the
-  /// operand is a zero immediate.
-  /// - NewInsnID - Instruction ID to modify
-  /// - OldInsnID - Instruction ID to copy from
-  /// - OpIdx - The operand to copy
-  /// - ZeroReg - The zero register to use
-  GIR_CopyOrAddZeroReg,
-  /// 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 a temporary register to the specified instruction
-  /// - InsnID - Instruction ID to modify
-  /// - TempRegID - The temporary register ID to add
-  /// - TempRegFlags - The register flags to set
-  GIR_AddTempRegister,
-
-  /// Add a temporary register to the specified instruction
-  /// - InsnID - Instruction ID to modify
-  /// - TempRegID - The temporary register ID to add
-  /// - TempRegFlags - The register flags to set
-  /// - SubRegIndex - The subregister index to set
-  GIR_AddTempSubRegister,
-
-  /// 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,
-  /// Render sub-operands of complex operands to the specified instruction
-  /// - InsnID - Instruction ID to modify
-  /// - RendererID - The renderer to call
-  /// - RenderOpID - The suboperand to render.
-  GIR_ComplexSubOperandRenderer,
-  /// Render subregisters of suboperands of complex operands to the
-  /// specified instruction
-  /// - InsnID - Instruction ID to modify
-  /// - RendererID - The renderer to call
-  /// - RenderOpID - The suboperand to render
-  /// - SubRegIdx - The subregister to extract
-  GIR_ComplexSubOperandSubRegRenderer,
-
-  /// Render operands to the specified instruction using a custom function
-  /// - InsnID - Instruction ID to modify
-  /// - OldInsnID - Instruction ID to get the matched operand from
-  /// - RendererFnID - Custom renderer function to call
-  GIR_CustomRenderer,
-
-  /// Render operands to the specified instruction using a custom function,
-  /// reading from a specific operand.
-  /// - InsnID - Instruction ID to modify
-  /// - OldInsnID - Instruction ID to get the matched operand from
-  /// - OpIdx - Operand index in OldInsnID the render function should read
-  /// from..
-  /// - RendererFnID - Custom renderer function to call
-  GIR_CustomOperandRenderer,
-
-  /// Render a G_CONSTANT operator as a sign-extended immediate.
-  /// - NewInsnID - Instruction ID to modify
-  /// - OldInsnID - Instruction ID to copy from
-  /// The operand index is implicitly 1.
-  GIR_CopyConstantAsSImm,
-
-  /// Render a G_FCONSTANT operator as a sign-extended immediate.
-  /// - NewInsnID - Instruction ID to modify
-  /// - OldInsnID - Instruction ID to copy from
-  /// The operand index is implicitly 1.
-  GIR_CopyFConstantAsFPImm,
-
-  /// 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
-  /// - MergeInsnID... - One or more Instruction ID to merge into the result.
-  /// - GIU_MergeMemOperands_EndOfList - Terminates the list of instructions to
-  ///                                    merge.
-  GIR_MergeMemOperands,
-
-  /// Erase from parent.
-  /// - InsnID - Instruction ID to erase
-  GIR_EraseFromParent,
-
-  /// Create a new temporary register that's not constrained.
-  /// - TempRegID - The temporary register ID to initialize.
-  /// - Expected type
-  GIR_MakeTempReg,
-
-  /// A successful emission
-  GIR_Done,
-
-  /// Increment the rule coverage counter.
-  /// - RuleID - The ID of the rule that was covered.
-  GIR_Coverage,
-
-  /// Keeping track of the number of the GI opcodes. Must be the last entry.
-  GIU_NumOpcodes,
-};
-
-enum {
-  /// Indicates the end of the variable-length MergeInsnID list in a
-  /// GIR_MergeMemOperands opcode.
-  GIU_MergeMemOperands_EndOfList = -1,
-};
-
-/// Provides the logic to select generic machine instructions.
-class InstructionSelector {
+class InstructionSelector : public GIMatchTableExecutor {
 public:
-  virtual ~InstructionSelector() = default;
+  virtual ~InstructionSelector();
 
   /// Select the (possibly generic) instruction \p I to only use target-specific
   /// opcodes. It is OK to insert multiple instructions, but they cannot be
@@ -454,135 +31,7 @@ class InstructionSelector {
   ///     for I in all mutated/inserted instructions:
   ///       !isPreISelGenericOpcode(I.getOpcode())
   virtual bool select(MachineInstr &I) = 0;
-
-  CodeGenCoverage *CoverageInfo = nullptr;
-  GISelKnownBits *KnownBits = nullptr;
-  MachineFunction *MF = nullptr;
-  ProfileSummaryInfo *PSI = nullptr;
-  BlockFrequencyInfo *BFI = nullptr;
-  // For some predicates, we need to track the current MBB.
-  MachineBasicBlock *CurMBB = nullptr;
-
-  virtual void setupGeneratedPerFunctionState(MachineFunction &MF) {
-    llvm_unreachable("TableGen should have emitted implementation");
-  }
-
-  /// Setup per-MF selector state.
-  virtual void setupMF(MachineFunction &mf, GISelKnownBits *KB,
-                       CodeGenCoverage &covinfo, ProfileSummaryInfo *psi,
-                       BlockFrequencyInfo *bfi) {
-    CoverageInfo = &covinfo;
-    KnownBits = KB;
-    MF = &mf;
-    PSI = psi;
-    BFI = bfi;
-    CurMBB = nullptr;
-    setupGeneratedPerFunctionState(mf);
-  }
-
-protected:
-  using ComplexRendererFns =
-      std::optional<SmallVector<std::function<void(MachineInstrBuilder &)>, 4>>;
-  using RecordedMIVector = SmallVector<MachineInstr *, 4>;
-  using NewMIVector = SmallVector<MachineInstrBuilder, 4>;
-
-  struct MatcherState {
-    std::vector<ComplexRendererFns::value_type> Renderers;
-    RecordedMIVector MIs;
-    DenseMap<unsigned, unsigned> TempRegisters;
-    /// Named operands that predicate with 'let PredicateCodeUsesOperands = 1'
-    /// referenced in its argument list. Operands are inserted at index set by
-    /// emitter, it corresponds to the order in which names appear in argument
-    /// list. Currently such predicates don't have more then 3 arguments.
-    std::array<const MachineOperand *, 3> RecordedOperands;
-
-    MatcherState(unsigned MaxRenderers);
-  };
-
-  bool shouldOptForSize(const MachineFunction *MF) const {
-    const auto &F = MF->getFunction();
-    return F.hasOptSize() || F.hasMinSize() ||
-           (PSI && BFI && CurMBB && llvm::shouldOptForSize(*CurMBB, PSI, BFI));
-  }
-
-public:
-  template <class PredicateBitset, class ComplexMatcherMemFn,
-            class CustomRendererFn>
-  struct ISelInfoTy {
-    ISelInfoTy(const LLT *TypeObjects, size_t NumTypeObjects,
-               const PredicateBitset *FeatureBitsets,
-               const ComplexMatcherMemFn *ComplexPredicates,
-               const CustomRendererFn *CustomRenderers)
-        : TypeObjects(TypeObjects),
-          FeatureBitsets(FeatureBitsets),
-          ComplexPredicates(ComplexPredicates),
-          CustomRenderers(CustomRenderers) {
-
-      for (size_t I = 0; I < NumTypeObjects; ++I)
-        TypeIDMap[TypeObjects[I]] = I;
-    }
-    const LLT *TypeObjects;
-    const PredicateBitset *FeatureBitsets;
-    const ComplexMatcherMemFn *ComplexPredicates;
-    const CustomRendererFn *CustomRenderers;
-
-    SmallDenseMap<LLT, unsigned, 64> TypeIDMap;
-  };
-
-protected:
-  InstructionSelector();
-
-  /// Execute a given matcher table and return true if the match was successful
-  /// and false otherwise.
-  template <class TgtInstructionSelector, class PredicateBitset,
-            class ComplexMatcherMemFn, class CustomRendererFn>
-  bool executeMatchTable(
-      TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
-      const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn>
-          &ISelInfo,
-      const int64_t *MatchTable, const TargetInstrInfo &TII,
-      MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
-      const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures,
-      CodeGenCoverage &CoverageInfo) const;
-
-  virtual const int64_t *getMatchTable() const {
-    llvm_unreachable("Should have been overridden by tablegen if used");
-  }
-
-  virtual bool testImmPredicate_I64(unsigned, int64_t) const {
-    llvm_unreachable(
-        "Subclasses must override this with a tablegen-erated function");
-  }
-  virtual bool testImmPredicate_APInt(unsigned, const APInt &) const {
-    llvm_unreachable(
-        "Subclasses must override this with a tablegen-erated function");
-  }
-  virtual bool testImmPredicate_APFloat(unsigned, const APFloat &) const {
-    llvm_unreachable(
-        "Subclasses must override this with a tablegen-erated function");
-  }
-  virtual bool testMIPredicate_MI(
-      unsigned, const MachineInstr &,
-      const std::array<const MachineOperand *, 3> &Operands) const {
-    llvm_unreachable(
-        "Subclasses must override this with a tablegen-erated function");
-  }
-
-  bool isOperandImmEqual(const MachineOperand &MO, int64_t Value,
-                         const MachineRegisterInfo &MRI) const;
-
-  /// Return true if the specified operand is a G_PTR_ADD with a G_CONSTANT on the
-  /// right-hand side. GlobalISel's separation of pointer and integer types
-  /// means that we don't need to worry about G_OR with equivalent semantics.
-  bool isBaseWithConstantOffset(const MachineOperand &Root,
-                                const MachineRegisterInfo &MRI) const;
-
-  /// Return true if MI can obviously be folded into IntoMI.
-  /// MI and IntoMI do not need to be in the same basic blocks, but MI must
-  /// preceed IntoMI.
-  bool isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const;
 };
+} // namespace llvm
 
-} // end namespace llvm
-
-#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
+#endif

diff  --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
index 09e2abbe89c633..46e6c6df5998e5 100644
--- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
+++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt
@@ -6,6 +6,7 @@ add_llvm_component_library(LLVMGlobalISel
   GlobalISel.cpp
   Combiner.cpp
   CombinerHelper.cpp
+  GIMatchTableExecutor.cpp
   GISelChangeObserver.cpp
   IRTranslator.cpp
   InlineAsmLowering.cpp

diff  --git a/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp
new file mode 100644
index 00000000000000..d747cbf5aadc84
--- /dev/null
+++ b/llvm/lib/CodeGen/GlobalISel/GIMatchTableExecutor.cpp
@@ -0,0 +1,68 @@
+//===- llvm/CodeGen/GlobalISel/GIMatchTableExecutor.cpp -------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This file implements the GIMatchTableExecutor class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
+#include "llvm/CodeGen/GlobalISel/Utils.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+
+#define DEBUG_TYPE "gi-match-table-executor"
+
+using namespace llvm;
+
+GIMatchTableExecutor::MatcherState::MatcherState(unsigned MaxRenderers)
+    : Renderers(MaxRenderers) {}
+
+GIMatchTableExecutor::GIMatchTableExecutor() = default;
+
+bool GIMatchTableExecutor::isOperandImmEqual(
+    const MachineOperand &MO, int64_t Value,
+    const MachineRegisterInfo &MRI) const {
+  if (MO.isReg() && MO.getReg())
+    if (auto VRegVal = getIConstantVRegValWithLookThrough(MO.getReg(), MRI))
+      return VRegVal->Value.getSExtValue() == Value;
+  return false;
+}
+
+bool GIMatchTableExecutor::isBaseWithConstantOffset(
+    const MachineOperand &Root, const MachineRegisterInfo &MRI) const {
+  if (!Root.isReg())
+    return false;
+
+  MachineInstr *RootI = MRI.getVRegDef(Root.getReg());
+  if (RootI->getOpcode() != TargetOpcode::G_PTR_ADD)
+    return false;
+
+  MachineOperand &RHS = RootI->getOperand(2);
+  MachineInstr *RHSI = MRI.getVRegDef(RHS.getReg());
+  if (RHSI->getOpcode() != TargetOpcode::G_CONSTANT)
+    return false;
+
+  return true;
+}
+
+bool GIMatchTableExecutor::isObviouslySafeToFold(MachineInstr &MI,
+                                                 MachineInstr &IntoMI) const {
+  // Immediate neighbours are already folded.
+  if (MI.getParent() == IntoMI.getParent() &&
+      std::next(MI.getIterator()) == IntoMI.getIterator())
+    return true;
+
+  // Convergent instructions cannot be moved in the CFG.
+  if (MI.isConvergent() && MI.getParent() != IntoMI.getParent())
+    return false;
+
+  return !MI.mayLoadOrStore() && !MI.mayRaiseFPException() &&
+         !MI.hasUnmodeledSideEffects() && MI.implicit_operands().empty();
+}

diff  --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
index 8959d215ecd1a3..c48591cc2f02fb 100644
--- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp
@@ -5,64 +5,12 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-//
-/// \file
-/// This file implements the InstructionSelector class.
-//
-//===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
-#include "llvm/CodeGen/GlobalISel/Utils.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-
-#define DEBUG_TYPE "instructionselector"
-
-using namespace llvm;
-
-InstructionSelector::MatcherState::MatcherState(unsigned MaxRenderers)
-    : Renderers(MaxRenderers) {}
-
-InstructionSelector::InstructionSelector() = default;
-
-bool InstructionSelector::isOperandImmEqual(
-    const MachineOperand &MO, int64_t Value,
-    const MachineRegisterInfo &MRI) const {
-  if (MO.isReg() && MO.getReg())
-    if (auto VRegVal = getIConstantVRegValWithLookThrough(MO.getReg(), MRI))
-      return VRegVal->Value.getSExtValue() == Value;
-  return false;
-}
-
-bool InstructionSelector::isBaseWithConstantOffset(
-    const MachineOperand &Root, const MachineRegisterInfo &MRI) const {
-  if (!Root.isReg())
-    return false;
-
-  MachineInstr *RootI = MRI.getVRegDef(Root.getReg());
-  if (RootI->getOpcode() != TargetOpcode::G_PTR_ADD)
-    return false;
-
-  MachineOperand &RHS = RootI->getOperand(2);
-  MachineInstr *RHSI = MRI.getVRegDef(RHS.getReg());
-  if (RHSI->getOpcode() != TargetOpcode::G_CONSTANT)
-    return false;
-
-  return true;
-}
 
-bool InstructionSelector::isObviouslySafeToFold(MachineInstr &MI,
-                                                MachineInstr &IntoMI) const {
-  // Immediate neighbours are already folded.
-  if (MI.getParent() == IntoMI.getParent() &&
-      std::next(MI.getIterator()) == IntoMI.getIterator())
-    return true;
+namespace llvm {
 
-  // Convergent instructions cannot be moved in the CFG.
-  if (MI.isConvergent() && MI.getParent() != IntoMI.getParent())
-    return false;
+// vtable anchor
+InstructionSelector::~InstructionSelector() = default;
 
-  return !MI.mayLoadOrStore() && !MI.mayRaiseFPException() &&
-         !MI.hasUnmodeledSideEffects() && MI.implicit_operands().empty();
-}
+} // namespace llvm

diff  --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 657053602d89f1..2f612976aa41a4 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -21,9 +21,9 @@
 #include "MCTargetDesc/AArch64AddressingModes.h"
 #include "MCTargetDesc/AArch64MCTargetDesc.h"
 #include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"

diff  --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index 43c54606a3988c..2a6ab437ccee95 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -19,8 +19,8 @@
 #include "AMDGPUTargetMachine.h"
 #include "SIMachineFunctionInfo.h"
 #include "Utils/AMDGPUBaseInfo.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
 #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"

diff  --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
index a4ab2f86d046f3..f391058a70514c 100644
--- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
+++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp
@@ -13,8 +13,8 @@
 #include "ARMRegisterBankInfo.h"
 #include "ARMSubtarget.h"
 #include "ARMTargetMachine.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/IR/IntrinsicsARM.h"

diff  --git a/llvm/lib/Target/M68k/GISel/M68kInstructionSelector.cpp b/llvm/lib/Target/M68k/GISel/M68kInstructionSelector.cpp
index a627eccd110d72..3fddf10aca2ef6 100644
--- a/llvm/lib/Target/M68k/GISel/M68kInstructionSelector.cpp
+++ b/llvm/lib/Target/M68k/GISel/M68kInstructionSelector.cpp
@@ -9,8 +9,8 @@
 #include "M68kRegisterBankInfo.h"
 #include "M68kSubtarget.h"
 #include "M68kTargetMachine.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
 #include "llvm/Support/Debug.h"
 
 #define DEBUG_TYPE "m68k-isel"

diff  --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
index 04fe0960998dd7..4478a574a24088 100644
--- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
+++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp
@@ -15,7 +15,7 @@
 #include "MipsMachineFunction.h"
 #include "MipsRegisterBankInfo.h"
 #include "MipsTargetMachine.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/IR/IntrinsicsMips.h"

diff  --git a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
index 24f02a3def06ba..3fd7a1ad9efa59 100644
--- a/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
+++ b/llvm/lib/Target/PowerPC/GISel/PPCInstructionSelector.cpp
@@ -16,9 +16,9 @@
 #include "PPCRegisterBankInfo.h"
 #include "PPCSubtarget.h"
 #include "PPCTargetMachine.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
 #include "llvm/CodeGen/MachineConstantPool.h"
 #include "llvm/CodeGen/MachineFunction.h"

diff  --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index f0dc26bff39219..691439b3a18b4c 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -14,8 +14,8 @@
 #include "RISCVRegisterBankInfo.h"
 #include "RISCVSubtarget.h"
 #include "RISCVTargetMachine.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
 #include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/Support/Debug.h"
 

diff  --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 5507e9254faee6..9152c7479d7ee9 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -20,8 +20,8 @@
 #include "SPIRVTargetMachine.h"
 #include "SPIRVUtils.h"
 #include "llvm/ADT/APFloat.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/IR/IntrinsicsSPIRV.h"

diff  --git a/llvm/lib/Target/X86/X86InstructionSelector.cpp b/llvm/lib/Target/X86/X86InstructionSelector.cpp
index fc6f3bd876acd7..6157dafb5c5106 100644
--- a/llvm/lib/Target/X86/X86InstructionSelector.cpp
+++ b/llvm/lib/Target/X86/X86InstructionSelector.cpp
@@ -19,8 +19,8 @@
 #include "X86RegisterInfo.h"
 #include "X86Subtarget.h"
 #include "X86TargetMachine.h"
+#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
-#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"
 #include "llvm/CodeGen/LowLevelType.h"
 #include "llvm/CodeGen/MachineBasicBlock.h"

diff  --git a/llvm/test/TableGen/ContextlessPredicates.td b/llvm/test/TableGen/ContextlessPredicates.td
index 083e1d214b8b84..7f081e9a0ec00a 100644
--- a/llvm/test/TableGen/ContextlessPredicates.td
+++ b/llvm/test/TableGen/ContextlessPredicates.td
@@ -14,7 +14,7 @@ def test_atomic_op_frag : PatFrag<(ops node:$ptr, node:$val),
   let IsAtomic = 1;
   let MemoryVT = i32;
 }
- 
+
 def INSN : I<(outs GPR32:$dst), (ins GPR32Op:$src1, GPR32Op:$src2), []>;
 
 def : Pat<(test_atomic_op_frag GPR32:$ptr, GPR32:$val) ,
@@ -35,7 +35,7 @@ def : Pat<(test_atomic_op_frag GPR32:$ptr, GPR32:$val) ,
 // CHECK_NOPT-NEXT:      // MIs[0] val
 // CHECK_NOPT-NEXT:      GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
 // CHECK_NOPT-NEXT:      GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
-// CHECK_NOPT-NEXT:      GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_test_atomic_op_frag,
+// CHECK_NOPT-NEXT:      GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_test_atomic_op_frag,
 // CHECK_NOPT-NEXT:      // (atomic_swap:{ *:[i32] } GPR32:{ *:[i32] }:$ptr, GPR32:{ *:[i32] }:$val)<<P:Predicate_test_atomic_op_frag>>  =>  (INSN:{ *:[i32] } GPR32:{ *:[i32] }:$ptr, GPR32:{ *:[i32] }:$val)
 // CHECK_NOPT-NEXT:      GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::INSN,
 // CHECK_NOPT-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
@@ -61,7 +61,7 @@ def : Pat<(test_atomic_op_frag GPR32:$ptr, GPR32:$val) ,
 // CHECK_OPT-NEXT:      GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
 // CHECK_OPT-NEXT:      GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
 // CHECK_OPT-NEXT:      GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
-// CHECK_OPT-NEXT:      GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_test_atomic_op_frag,
+// CHECK_OPT-NEXT:      GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_test_atomic_op_frag,
 // CHECK_OPT-NEXT:      // (atomic_swap:{ *:[i32] } GPR32:{ *:[i32] }:$ptr, GPR32:{ *:[i32] }:$val)<<P:Predicate_test_atomic_op_frag>>  =>  (INSN:{ *:[i32] } GPR32:{ *:[i32] }:$ptr, GPR32:{ *:[i32] }:$val)
 // CHECK_OPT-NEXT:      GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::INSN,
 // CHECK_OPT-NEXT:      GIR_ConstrainSelectedInstOperands, /*InsnID*/0,

diff  --git a/llvm/test/TableGen/GlobalISelEmitter-PR39045.td b/llvm/test/TableGen/GlobalISelEmitter-PR39045.td
index 3500e7d8dd6c20..55e5aa2e905d6b 100644
--- a/llvm/test/TableGen/GlobalISelEmitter-PR39045.td
+++ b/llvm/test/TableGen/GlobalISelEmitter-PR39045.td
@@ -2,8 +2,8 @@
 // RUN: FileCheck %s < %t
 
 // Both predicates should be tested
-// CHECK-DAG: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_pat_frag_b,
-// CHECK-DAG: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_pat_frag_a,
+// CHECK-DAG: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_pat_frag_b,
+// CHECK-DAG: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_pat_frag_a,
 
 include "llvm/Target/Target.td"
 include "GlobalISelEmitterCommon.td"
@@ -37,4 +37,3 @@ def : Pat <
   (pat_frag_b GPR32:$src),
   (inst_b GPR32:$src)
 >;
-

diff  --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td
index 2878718457e80d..a2284513cfb752 100644
--- a/llvm/test/TableGen/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter.td
@@ -73,19 +73,19 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
 // CHECK-NEXT:    mutable MatcherState State;
 // CHECK-NEXT:    typedef ComplexRendererFns(MyTargetInstructionSelector::*ComplexMatcherMemFn)(MachineOperand &) const;
 // CHECK-NEXT:    typedef void(MyTargetInstructionSelector::*CustomRendererFn)(MachineInstrBuilder &, const MachineInstr &, int) const;
-// CHECK-NEXT:    const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn> ISelInfo;
+// CHECK-NEXT:    const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn> ExecInfo;
 // CHECK-NEXT:    static MyTargetInstructionSelector::ComplexMatcherMemFn ComplexPredicateFns[];
 // CHECK-NEXT:    static MyTargetInstructionSelector::CustomRendererFn CustomRenderers[];
 // CHECK-NEXT:    bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const override;
 // CHECK-NEXT:    bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) const override;
 // CHECK-NEXT:    bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat &Imm) const override;
 // CHECK-NEXT:    const int64_t *getMatchTable() const override;
-// CHECK-NEXT:    bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const std::array<const MachineOperand *, 3> &Operands) const override;
+// CHECK-NEXT:    bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override;
 // CHECK-NEXT:  #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL
 
 // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_INIT
 // CHECK-NEXT:    , State(3),
-// CHECK-NEXT:    ISelInfo(TypeObjects, NumTypeObjects, FeatureBitsets, ComplexPredicateFns, CustomRenderers)
+// CHECK-NEXT:    ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets, ComplexPredicateFns, CustomRenderers)
 // CHECK-NEXT:  #endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT
 
 // CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
@@ -144,19 +144,19 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
 
 // CHECK-LABEL: // PatFrag predicates.
 // CHECK-NEXT:  enum {
-// CHECK-NEXT:    GIPFP_I64_Predicate_cimm8 = GIPFP_I64_Invalid + 1,
-// CHECK-NEXT:    GIPFP_I64_Predicate_simm8,
+// CHECK-NEXT:    GICXXPred_I64_Predicate_cimm8 = GICXXPred_I64_Invalid + 1,
+// CHECK-NEXT:    GICXXPred_I64_Predicate_simm8,
 // CHECK-NEXT:  };
 
 
 // CHECK-NEXT: bool MyTargetInstructionSelector::testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const {
 // CHECK-NEXT:   switch (PredicateID) {
-// CHECK-NEXT:   case GIPFP_I64_Predicate_cimm8: {
+// CHECK-NEXT:   case GICXXPred_I64_Predicate_cimm8: {
 // CHECK-NEXT:     return isInt<8>(Imm);
 // CHECK-NEXT:     llvm_unreachable("ImmediateCode should have returned");
 // CHECK-NEXT:     return false;
 // CHECK-NEXT:   }
-// CHECK-NEXT:   case GIPFP_I64_Predicate_simm8: {
+// CHECK-NEXT:   case GICXXPred_I64_Predicate_simm8: {
 // CHECK-NEXT:      return isInt<8>(Imm);
 // CHECK-NEXT:     llvm_unreachable("ImmediateCode should have returned");
 // CHECK-NEXT:     return false;
@@ -168,11 +168,11 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
 
 // CHECK-LABEL: // PatFrag predicates.
 // CHECK-NEXT:  enum {
-// CHECK-NEXT:    GIPFP_APFloat_Predicate_fpimmz = GIPFP_APFloat_Invalid + 1,
+// CHECK-NEXT:    GICXXPred_APFloat_Predicate_fpimmz = GICXXPred_APFloat_Invalid + 1,
 // CHECK-NEXT:  };
 // CHECK-NEXT:  bool MyTargetInstructionSelector::testImmPredicate_APFloat(unsigned PredicateID, const APFloat & Imm) const {
 // CHECK-NEXT:    switch (PredicateID) {
-// CHECK-NEXT:    case GIPFP_APFloat_Predicate_fpimmz: {
+// CHECK-NEXT:    case GICXXPred_APFloat_Predicate_fpimmz: {
 // CHECK-NEXT:      return Imm->isExactlyValue(0.0);
 // CHECK-NEXT:      llvm_unreachable("ImmediateCode should have returned");
 // CHECK-NEXT:      return false;
@@ -184,11 +184,11 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
 
 // CHECK-LABEL: // PatFrag predicates.
 // CHECK-NEXT:  enum {
-// CHECK-NEXT:    GIPFP_APInt_Predicate_simm9 = GIPFP_APInt_Invalid + 1,
+// CHECK-NEXT:    GICXXPred_APInt_Predicate_simm9 = GICXXPred_APInt_Invalid + 1,
 // CHECK-NEXT:  };
 // CHECK-NEXT:  bool MyTargetInstructionSelector::testImmPredicate_APInt(unsigned PredicateID, const APInt & Imm) const {
 // CHECK-NEXT:    switch (PredicateID) {
-// CHECK-NEXT:    case GIPFP_APInt_Predicate_simm9: {
+// CHECK-NEXT:    case GICXXPred_APInt_Predicate_simm9: {
 // CHECK-NEXT:      return isInt<9>(Imm->getSExtValue());
 // CHECK-NEXT:      llvm_unreachable("ImmediateCode should have returned");
 // CHECK-NEXT:      return false;
@@ -224,7 +224,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
 // CHECK-NEXT: State.MIs.clear();
 // CHECK-NEXT: State.MIs.push_back(&I);
 
-// CHECK:      if (executeMatchTable(*this, OutMIs, State, ISelInfo, getMatchTable(), TII, MRI, TRI, RBI, AvailableFeatures, CoverageInfo)) {
+// CHECK:      if (executeMatchTable(*this, OutMIs, State, ExecInfo, getMatchTable(), TII, MRI, TRI, RBI, AvailableFeatures, &CoverageInfo)) {
 // CHECK-NEXT:   return true;
 // CHECK-NEXT: }
 
@@ -354,12 +354,12 @@ def : Pat<(select GPR32:$src1, (complex_rr GPR32:$src2a, GPR32:$src2b),
 // R21N-NEXT:    // MIs[0] src2
 // R21N-NEXT:    GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
 //
-// R21O-NEXT:    GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_frag,
+// R21O-NEXT:    GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_frag,
 // R21C-NEXT:    GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex,
 // R21N-NEXT:    // MIs[0] src3
 // R21N-NEXT:    GIM_CheckType, /*MI*/0, /*Op*/3, /*Type*/GILLT_s32,
 // R21C-NEXT:    GIM_CheckComplexPattern, /*MI*/0, /*Op*/3, /*Renderer*/1, GICP_gi_complex,
-// R21N-NEXT:    GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_frag,
+// R21N-NEXT:    GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_frag,
 // R21C-NEXT:    // (select:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2, complex:{ *:[i32] }:$src3)<<P:Predicate_frag>> => (INSN2:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src2)
 
 // R21C-NEXT:    GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN2,
@@ -851,7 +851,7 @@ def MOV1 : I<(outs GPR32:$dst), (ins), [(set GPR32:$dst, 1)]>;
 // NOOPT-NEXT:  GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
 // NOOPT-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
 // NOOPT-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
-// NOOPT-NEXT:    GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GIPFP_I64_Predicate_simm8,
+// NOOPT-NEXT:    GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GICXXPred_I64_Predicate_simm8,
 // NOOPT-NEXT:    // MIs[0] dst
 // NOOPT-NEXT:    GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
 // NOOPT-NEXT:    GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
@@ -875,7 +875,7 @@ def MOVimm8 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, simm8:$i
 // NOOPT-NEXT:  GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
 // NOOPT-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
 // NOOPT-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
-// NOOPT-NEXT:    GIM_CheckAPIntImmPredicate, /*MI*/0, /*Predicate*/GIPFP_APInt_Predicate_simm9,
+// NOOPT-NEXT:    GIM_CheckAPIntImmPredicate, /*MI*/0, /*Predicate*/GICXXPred_APInt_Predicate_simm9,
 // NOOPT-NEXT:    // MIs[0] dst
 // NOOPT-NEXT:    GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
 // NOOPT-NEXT:    GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
@@ -899,7 +899,7 @@ def MOVimm9 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, simm9:$i
 // NOOPT-NEXT:  GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
 // NOOPT-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
 // NOOPT-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
-// NOOPT-NEXT:    GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GIPFP_I64_Predicate_cimm8,
+// NOOPT-NEXT:    GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GICXXPred_I64_Predicate_cimm8,
 // NOOPT-NEXT:    // MIs[0] dst
 // NOOPT-NEXT:    GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
 // NOOPT-NEXT:    GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
@@ -922,7 +922,7 @@ def MOVcimm8 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, cimm8:$
 // NOOPT-NEXT:  GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
 // NOOPT-NEXT:    GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
 // NOOPT-NEXT:    GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_FCONSTANT,
-// NOOPT-NEXT:    GIM_CheckAPFloatImmPredicate, /*MI*/0, /*Predicate*/GIPFP_APFloat_Predicate_fpimmz,
+// NOOPT-NEXT:    GIM_CheckAPFloatImmPredicate, /*MI*/0, /*Predicate*/GICXXPred_APFloat_Predicate_fpimmz,
 // NOOPT-NEXT:    // MIs[0] dst
 // NOOPT-NEXT:    GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
 // NOOPT-NEXT:    GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::FPR32RegClassID,

diff  --git a/llvm/test/TableGen/GlobalISelEmitterCustomPredicate.td b/llvm/test/TableGen/GlobalISelEmitterCustomPredicate.td
index 408055da34c985..49e8f4fdfe7de7 100644
--- a/llvm/test/TableGen/GlobalISelEmitterCustomPredicate.td
+++ b/llvm/test/TableGen/GlobalISelEmitterCustomPredicate.td
@@ -4,22 +4,22 @@
 //
 // CHECK: // PatFrag predicates.
 // CHECK-NEXT: enum {
-// CHECK-NEXT:   GIPFP_MI_Predicate_and_or_pat = GIPFP_MI_Invalid + 1,
-// CHECK-NEXT:   GIPFP_MI_Predicate_or_oneuse,
-// CHECK-NEXT:   GIPFP_MI_Predicate_patfrags_test_pat,
-// CHECK-NEXT:   GIPFP_MI_Predicate_sub3_pat,
+// CHECK-NEXT:   GICXXPred_MI_Predicate_and_or_pat = GICXXPred_MI_Invalid + 1,
+// CHECK-NEXT:   GICXXPred_MI_Predicate_or_oneuse,
+// CHECK-NEXT:   GICXXPred_MI_Predicate_patfrags_test_pat,
+// CHECK-NEXT:   GICXXPred_MI_Predicate_sub3_pat,
 // CHECK-NEXT: };
 
 // Verify that we emit cases for all MI predicates.
 //
 // CHECK: bool MyTargetInstructionSelector::testMIPredicate_MI(
-// CHECK:    case GIPFP_MI_Predicate_and_or_pat: {
+// CHECK:    case GICXXPred_MI_Predicate_and_or_pat: {
 // CHECK:      llvm_unreachable("GISelPredicateCode should have returned");
-// CHECK:    case GIPFP_MI_Predicate_or_oneuse: {
+// CHECK:    case GICXXPred_MI_Predicate_or_oneuse: {
 // CHECK:      llvm_unreachable("GISelPredicateCode should have returned");
-// CHECK:    case GIPFP_MI_Predicate_patfrags_test_pat: {
+// CHECK:    case GICXXPred_MI_Predicate_patfrags_test_pat: {
 // CHECK:      llvm_unreachable("GISelPredicateCode should have returned");
-// CHECK:    case GIPFP_MI_Predicate_sub3_pat: {
+// CHECK:    case GICXXPred_MI_Predicate_sub3_pat: {
 // CHECK:      llvm_unreachable("GISelPredicateCode should have returned");
 
 include "llvm/Target/Target.td"
@@ -94,7 +94,7 @@ def and_or_pat : PatFrag<
 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
 // CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/2, /*StoreIdx*/1, // Name : pred:3:y
 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/Test::DRegsRegClassID,
-// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_and_or_pat,
+// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_and_or_pat,
 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
 // CHECK-NEXT: // (and:{ *:[i32] } DOP:{ *:[i32] }:$src2:$pred:3:z, (or:{ *:[i32] } DOP:{ *:[i32] }:$src0:$pred:3:x, DOP:{ *:[i32] }:$src1:$pred:3:y))<<P:3:Predicate_and_or_pat>>  =>  (AND_OR:{ *:[i32] } DOP:{ *:[i32] }:$src0, DOP:{ *:[i32] }:$src1, DOP:{ *:[i32] }:$src2)
 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::AND_OR,
@@ -124,7 +124,7 @@ def and_or_pat : PatFrag<
 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
 // CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/0, /*Op*/2, /*StoreIdx*/2, // Name : pred:3:z
 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/Test::DRegsRegClassID,
-// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_and_or_pat,
+// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_and_or_pat,
 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
 // CHECK-NEXT: // (and:{ *:[i32] } (or:{ *:[i32] } DOP:{ *:[i32] }:$src0:$pred:3:x, DOP:{ *:[i32] }:$src1:$pred:3:y), DOP:{ *:[i32] }:$src2:$pred:3:z)<<P:3:Predicate_and_or_pat>>  =>  (AND_OR:{ *:[i32] } DOP:{ *:[i32] }:$src0, DOP:{ *:[i32] }:$src1, DOP:{ *:[i32] }:$src2)
 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::AND_OR,
@@ -168,7 +168,7 @@ def sub3_pat : PatFrag<
 // CHECK-NEXT: // MIs[0] src2
 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
 // CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/0, /*Op*/2, /*StoreIdx*/2, // Name : pred:1:z
-// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_sub3_pat,
+// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_sub3_pat,
 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
 // CHECK-NEXT: // (sub:{ *:[i32] } (sub:{ *:[i32] } i32:{ *:[i32] }:$src0:$pred:1:x, i32:{ *:[i32] }:$src1:$pred:1:y), i32:{ *:[i32] }:$src2:$pred:1:z)<<P:1:Predicate_sub3_pat>>  =>  (SUB3:{ *:[i32] } i32:{ *:[i32] }:$src0, i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2)
 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::SUB3,

diff  --git a/llvm/test/TableGen/GlobalISelEmitterOverloadedPtr.td b/llvm/test/TableGen/GlobalISelEmitterOverloadedPtr.td
index 047af1ca0524fe..0cc3485342cc61 100644
--- a/llvm/test/TableGen/GlobalISelEmitterOverloadedPtr.td
+++ b/llvm/test/TableGen/GlobalISelEmitterOverloadedPtr.td
@@ -17,7 +17,7 @@ let TargetPrefix = "mytarget" in {
 // CHECK-NEXT: // MIs[0] src
 // CHECK-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/2, /*SizeInBits*/32,
 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
-// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_frag_anyptr,
+// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_frag_anyptr,
 // CHECK-NEXT: // (intrinsic_w_chain:{ *:[i32] } {{[0-9]+}}:{ *:[iPTR] }, GPR32:{ *:[i32] }:$src)<<P:Predicate_frag_anyptr>>  =>  (ANYLOAD:{ *:[i32] } GPR32:{ *:[i32] }:$src)
 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::ANYLOAD,
 let hasSideEffects = 1 in {

diff  --git a/llvm/test/TableGen/immarg-predicated.td b/llvm/test/TableGen/immarg-predicated.td
index 16db4a80f0597b..87326c652356b8 100644
--- a/llvm/test/TableGen/immarg-predicated.td
+++ b/llvm/test/TableGen/immarg-predicated.td
@@ -12,7 +12,7 @@ def int_mytarget_sleep0 : Intrinsic<[], [llvm_i32_ty], [ImmArg<ArgIndex<0>>]>;
 // GISEL-NEXT: GIM_CheckIntrinsicID, /*MI*/0, /*Op*/0, Intrinsic::mytarget_sleep0,
 // GISEL-NEXT: // MIs[0] src
 // GISEL-NEXT: GIM_CheckIsImm, /*MI*/0, /*Op*/1,
-// GISEL-NEXT: GIM_CheckImmOperandPredicate, /*MI*/0, /*MO*/1, /*Predicate*/GIPFP_I64_Predicate_tuimm9,
+// GISEL-NEXT: GIM_CheckImmOperandPredicate, /*MI*/0, /*MO*/1, /*Predicate*/GICXXPred_I64_Predicate_tuimm9,
 // GISEL-NEXT: // (intrinsic_void {{[0-9]+}}:{ *:[iPTR] }, (timm:{ *:[i32] })<<P:Predicate_tuimm9>>:$src) => (SLEEP0 (timm:{ *:[i32] }):$src)
 // GISEL-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::SLEEP0,
 // GISEL-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src

diff  --git a/llvm/test/TableGen/predicate-patfags.td b/llvm/test/TableGen/predicate-patfags.td
index a6a44ff6938feb..17cc74206b716b 100644
--- a/llvm/test/TableGen/predicate-patfags.td
+++ b/llvm/test/TableGen/predicate-patfags.td
@@ -46,17 +46,17 @@ def TGTmul24_oneuse : PatFrag<
 
 // GISEL: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS,
 // GISEL: GIM_CheckIntrinsicID, /*MI*/1, /*Op*/1, Intrinsic::tgt_mul24,
-// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIPFP_MI_Predicate_TGTmul24_oneuse,
+// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GICXXPred_MI_Predicate_TGTmul24_oneuse,
 
 // GISEL: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS,
 // GISEL: GIM_CheckIntrinsicID, /*MI*/1, /*Op*/1, Intrinsic::tgt_mul24,
-// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIPFP_MI_Predicate_TGTmul24_oneuse,
+// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GICXXPred_MI_Predicate_TGTmul24_oneuse,
 
 // GISEL: GIM_CheckOpcode, /*MI*/1, MyTarget::G_TGT_MUL24,
-// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIPFP_MI_Predicate_TGTmul24_oneuse,
+// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GICXXPred_MI_Predicate_TGTmul24_oneuse,
 
 // GISEL: GIM_CheckOpcode, /*MI*/1, MyTarget::G_TGT_MUL24,
-// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GIPFP_MI_Predicate_TGTmul24_oneuse,
+// GISEL: GIM_CheckCxxInsnPredicate, /*MI*/1, /*FnId*/GICXXPred_MI_Predicate_TGTmul24_oneuse,
 def inst_mad24 : I<
   (outs GPR32:$dst),
   (ins GPR32:$src0, GPR32:$src1, GPR32:$src2),

diff  --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index a6dc1b167dacd2..59fa2833b05d9f 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -2235,10 +2235,10 @@ void GlobalISelEmitter::emitCxxPredicateFns(
     OS << "// PatFrag predicates.\n"
        << "enum {\n";
     std::string EnumeratorSeparator =
-        (" = GIPFP_" + TypeIdentifier + "_Invalid + 1,\n").str();
+        (" = GICXXPred_" + TypeIdentifier + "_Invalid + 1,\n").str();
     for (const auto *Record : MatchedRecords) {
-      OS << "  GIPFP_" << TypeIdentifier << "_Predicate_" << Record->getName()
-         << EnumeratorSeparator;
+      OS << "  GICXXPred_" << TypeIdentifier << "_Predicate_"
+         << Record->getName() << EnumeratorSeparator;
       EnumeratorSeparator = ",\n";
     }
     OS << "};\n";
@@ -2253,7 +2253,7 @@ void GlobalISelEmitter::emitCxxPredicateFns(
   if (!MatchedRecords.empty())
     OS << "  switch (PredicateID) {\n";
   for (const auto *Record : MatchedRecords) {
-    OS << "  case GIPFP_" << TypeIdentifier << "_Predicate_"
+    OS << "  case GICXXPred_" << TypeIdentifier << "_Predicate_"
        << Record->getName() << ": {\n"
        << "    " << Record->getValueAsString(CodeFieldName) << "\n"
        << "    llvm_unreachable(\"" << CodeFieldName
@@ -2278,9 +2278,11 @@ void GlobalISelEmitter::emitImmPredicateFns(
 void GlobalISelEmitter::emitMIPredicateFns(raw_ostream &OS) {
   return emitCxxPredicateFns(
       OS, "GISelPredicateCode", "MI", "const MachineInstr &", "MI",
-      ", const std::array<const MachineOperand *, 3> &Operands",
+      ", const MatcherState &State",
       "  const MachineFunction &MF = *MI.getParent()->getParent();\n"
       "  const MachineRegisterInfo &MRI = MF.getRegInfo();\n"
+      "  const auto &Operands = State.RecordedOperands;\n"
+      "  (void)Operands;\n"
       "  (void)MRI;",
       [](const Record *R) { return true; });
 }
@@ -2427,9 +2429,9 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
      << "InstructionSelector::*CustomRendererFn)(MachineInstrBuilder &, const "
         "MachineInstr &, int) "
         "const;\n"
-     << "  const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, "
+     << "  const ExecInfoTy<PredicateBitset, ComplexMatcherMemFn, "
         "CustomRendererFn> "
-        "ISelInfo;\n";
+        "ExecInfo;\n";
   OS << "  static " << Target.getName()
      << "InstructionSelector::ComplexMatcherMemFn ComplexPredicateFns[];\n"
      << "  static " << Target.getName()
@@ -2442,13 +2444,13 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
         "&Imm) const override;\n"
      << "  const int64_t *getMatchTable() const override;\n"
      << "  bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI"
-        ", const std::array<const MachineOperand *, 3> &Operands) "
+        ", const MatcherState &State) "
         "const override;\n"
      << "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL\n\n";
 
   OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n"
      << ", State(" << MaxTemporaries << "),\n"
-     << "ISelInfo(TypeObjects, NumTypeObjects, FeatureBitsets"
+     << "ExecInfo(TypeObjects, NumTypeObjects, FeatureBitsets"
      << ", ComplexPredicateFns, CustomRenderers)\n"
      << "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n\n";
 
@@ -2629,9 +2631,9 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
      << "  NewMIVector OutMIs;\n"
      << "  State.MIs.clear();\n"
      << "  State.MIs.push_back(&I);\n\n"
-     << "  if (executeMatchTable(*this, OutMIs, State, ISelInfo"
+     << "  if (executeMatchTable(*this, OutMIs, State, ExecInfo"
      << ", getMatchTable(), TII, MRI, TRI, RBI, AvailableFeatures"
-     << ", CoverageInfo)) {\n"
+     << ", &CoverageInfo)) {\n"
      << "    return true;\n"
      << "  }\n\n"
      << "  return false;\n"

diff  --git a/llvm/utils/TableGen/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/GlobalISelMatchTable.cpp
index a8516ddc3053f3..67c4509904d83d 100644
--- a/llvm/utils/TableGen/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/GlobalISelMatchTable.cpp
@@ -31,8 +31,8 @@ Error failUnsupported(const Twine &Reason) {
 /// Get the name of the enum value used to number the predicate function.
 std::string getEnumNameForPredicate(const TreePredicateFn &Predicate) {
   if (Predicate.hasGISelPredicateCode())
-    return "GIPFP_MI_" + Predicate.getFnName();
-  return "GIPFP_" + Predicate.getImmTypeIdentifier().str() + "_" +
+    return "GICXXPred_MI_" + Predicate.getFnName();
+  return "GICXXPred_" + Predicate.getImmTypeIdentifier().str() + "_" +
          Predicate.getFnName();
 }
 

diff  --git a/llvm/utils/TableGen/GlobalISelMatchTable.h b/llvm/utils/TableGen/GlobalISelMatchTable.h
index 07da626e75aefb..837ff402d071fd 100644
--- a/llvm/utils/TableGen/GlobalISelMatchTable.h
+++ b/llvm/utils/TableGen/GlobalISelMatchTable.h
@@ -9,7 +9,7 @@
 /// \file
 /// This file contains the code related to the GlobalISel Match Table emitted by
 /// GlobalISelEmitter.cpp. The generated match table is interpreted at runtime
-/// by `InstructionSelectorImpl.h` to match & apply ISel patterns.
+/// by `GIMatchTableExecutorImpl.h` to match & apply ISel patterns.
 ///
 //===----------------------------------------------------------------------===//
 


        


More information about the llvm-commits mailing list