[llvm] d2028c3 - [TableGen] Add checks for CheckRegOperand/CheckImmOperand (#215230)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 16 21:34:27 PDT 2026


Author: renndong
Date: 2026-08-17T04:34:21Z
New Revision: d2028c30be01d0f358bfb576a68cac2b0bc94c7e

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

LOG: [TableGen] Add checks for CheckRegOperand/CheckImmOperand (#215230)

`CheckRegOperand`, `CheckImmOperand`, and their related predicates
currently call `getReg()` and `getImm()` without first verifying that
the operand is a register or an immediate. Users must explicitly use
`CheckIsRegOperand` and `CheckIsImmOperand` to avoid errors for other
operand kinds, as exposed by #213815.

This PR adds default `isReg()` and `isImm()` checks to those predicates
before accessing the corresponding values, and also removes redundant
`CheckIsRegOperand` and `CheckIsImmOperand` checks from existing users
in the X86, ARM, and RISCV backends.

Added: 
    llvm/test/TableGen/PredicateExpander.td

Modified: 
    llvm/include/llvm/Target/TargetInstrPredicate.td
    llvm/lib/Target/AArch64/AArch64SchedPredNeoverse.td
    llvm/lib/Target/AArch64/AArch64SchedPredicates.td
    llvm/lib/Target/ARM/ARMScheduleM85.td
    llvm/lib/Target/RISCV/RISCVInstrPredicates.td
    llvm/lib/Target/RISCV/RISCVMacroFusion.td
    llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td
    llvm/test/TableGen/MacroFusion.td
    llvm/test/TableGen/ResolveSchedClass.td
    llvm/utils/TableGen/Common/PredicateExpander.cpp
    llvm/utils/TableGen/Common/PredicateExpander.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Target/TargetInstrPredicate.td b/llvm/include/llvm/Target/TargetInstrPredicate.td
index b5419cb9f3867..d8610bc019701 100644
--- a/llvm/include/llvm/Target/TargetInstrPredicate.td
+++ b/llvm/include/llvm/Target/TargetInstrPredicate.td
@@ -13,22 +13,37 @@
 //
 // Here is an example of an MCInstPredicate definition in TableGen:
 //
-// def MCInstPredicateExample : CheckAll<[
-//    CheckOpcode<[BLR]>,
-//    CheckIsRegOperand<0>,
-//    CheckNot<CheckRegOperand<0, LR>>]>;
+// def BLRWithRegOpOtherThanLR : CheckAll<[
+//   CheckOpcode<[BLR]>,
+//   CheckIsRegOperand<0>,
+//   CheckNot<CheckRegOperand<0, LR>>]>;
 //
 // The syntax for MCInstPredicate is declarative, and predicate definitions can
 // be composed together in order to generate more complex constraints.
 //
 // The `CheckAll` from the example defines a composition of three 
diff erent
-// predicates.  Definition `MCInstPredicateExample` identifies instructions
+// predicates. Definition `BLRWithRegOpOtherThanLR` identifies instructions
 // whose opcode is BLR, and whose first operand is a register 
diff erent from
 // register `LR`.
 //
 // Every MCInstPredicate class has a well-known semantic in tablegen. For
 // example, `CheckOpcode` is a special type of predicate used to describe a
-// constraint on the value of an instruction opcode.
+// constraint on the value of an instruction opcode, while `CheckIsRegOperand`
+// checks whether an instruction operand is a register operand.
+// `CheckRegOperand` performs this check implicitly before comparing the
+// register value. Therefore, a preceding `CheckIsRegOperand` is redundant
+// when `CheckRegOperand` is used directly. When `CheckRegOperand` is negated,
+// we can also omit the preceding `CheckIsRegOperand` if we don't care about
+// the type of the operand (e.g. an immediate or a register) but only care
+// about the fact that the operand is not the specified register. For example:
+//
+// def BLRWithOpAnythingButLR : CheckAll<[
+//   CheckOpcode<[BLR]>,
+//   CheckNot<CheckRegOperand<0, LR>>]>;
+//
+// This predicate ensures that the opcode is BLR and the first operand is not
+// the register `LR`. It is allowed to be anything other than `LR`, including
+// immediate, etc.
 //
 // MCInstPredicate definitions are typically used by scheduling models to
 // construct MCSchedPredicate definitions (see the definition of class
@@ -37,14 +52,19 @@
 // when defining the set of SchedReadVariant and SchedWriteVariant of a
 // processor scheduling model.
 //
-// The `MCInstPredicateExample` definition above is equivalent (and therefore
-// could replace) the following definition from a previous ExynosM3 model (see
-// AArch64SchedExynosM3.td):
+// The `BLRWithRegOpOtherThanLR` definition above is equivalent (and therefore
+// could replace) the following definition:
 //
-// def M3BranchLinkFastPred  : SchedPredicate<[{
+// def BLRWithRegOpOtherThanLRPred : SchedPredicate<[{
 //    MI->getOpcode() == AArch64::BLR &&
 //    MI->getOperand(0).isReg() &&
-//    MI->getOperand(0).getReg() != AArch64::LR}]>;
+//    !(MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == AArch64::LR)}]>;
+//
+// The `BLRWithOpAnythingButLR` definition is equivalent to:
+//
+// def BLRWithOpAnythingButLRPred : SchedPredicate<[{
+//    MI->getOpcode() == AArch64::BLR &&
+//    !(MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == AArch64::LR)}]>;
 //
 // The main advantage of using MCInstPredicate instead of SchedPredicate is
 // portability: users don't need to specify predicates in C++. As a consequence
@@ -122,9 +142,8 @@ class CheckOperandBase<int Index, string Fn = ""> : MCOperandPredicate<Index> {
   string FunctionMapper = Fn;
 }
 
-// Check that the machine register operand at position `Index` references
-// register R. This predicate assumes that we already checked that the machine
-// operand at position `Index` is a register operand.
+// Check that the machine register operand at position `Index` is a
+// register operand that references register `R`.
 class CheckRegOperand<int Index, Register R> : CheckOperandBase<Index> {
   Register Reg = R;
 }
@@ -137,10 +156,10 @@ class CheckInvalidRegOperand<int Index> : CheckOperandBase<Index>;
 class CheckValidRegOperand<int Index> :
   CheckNot<CheckInvalidRegOperand<Index>>;
 
-// Check that the operand at position `Index` is immediate `Imm`.
-// If field `FunctionMapper` is a non-empty string, then function
-// `FunctionMapper` is applied to the operand value, and the return value is then
-// compared against `Imm`.
+// Check that the operand at position `Index` is an immediate operand whose
+// value equals `Imm`. If field `FunctionMapper` is a non-empty string, then 
+// function `FunctionMapper` is applied to the operand value, and the return
+// value is then compared against `Imm`.
 class CheckImmOperand<int Index, int Imm> : CheckOperandBase<Index> {
   int ImmVal = Imm;
 }
@@ -152,33 +171,37 @@ class CheckImmOperand_s<int Index, string Value> : CheckOperandBase<Index> {
   string ImmVal = Value;
 }
 
-// Check that the operand at position `Index` is less than `Imm`.
-// If field `FunctionMapper` is a non-empty string, then function
-// `FunctionMapper` is applied to the operand value, and the return value is then
-// compared against `Imm`.
+// Check that the operand at position `Index` is an immediate operand whose
+// value is less than `Imm`. If field `FunctionMapper` is a non-empty string,
+// then function `FunctionMapper` is applied to the operand value, and the
+// return value is then compared against `Imm`.
 class CheckImmOperandLT<int Index, int Imm> : CheckOperandBase<Index> {
   int ImmVal = Imm;
 }
 
-// Check that the operand at position `Index` is greater than `Imm`.
-// If field `FunctionMapper` is a non-empty string, then function
-// `FunctionMapper` is applied to the operand value, and the return value is then
-// compared against `Imm`.
+// Check that the operand at position `Index` is an immediate operand whose
+// value is greater than `Imm`. If field `FunctionMapper` is a non-empty string,
+// then function `FunctionMapper` is applied to the operand value, and the
+// return value is then compared against `Imm`.
 class CheckImmOperandGT<int Index, int Imm> : CheckOperandBase<Index> {
   int ImmVal = Imm;
 }
 
-// Check that the operand at position `Index` is less than or equal to `Imm`.
-// If field `FunctionMapper` is a non-empty string, then function
-// `FunctionMapper` is applied to the operand value, and the return value is then
-// compared against `Imm`.
-class CheckImmOperandLE<int Index, int Imm> : CheckNot<CheckImmOperandGT<Index, Imm>>;
+// Check that the operand at position `Index` is an immediate operand whose
+// value is less than or equal to `Imm`. If field `FunctionMapper` is a
+// non-empty string, then function `FunctionMapper` is applied to the operand
+// value, and the return value is then compared against `Imm`.
+class CheckImmOperandLE<int Index, int Imm> : CheckOperandBase<Index> {
+  int ImmVal = Imm;
+}
 
-// Check that the operand at position `Index` is greater than or equal to `Imm`.
-// If field `FunctionMapper` is a non-empty string, then function
-// `FunctionMapper` is applied to the operand value, and the return value is then
-// compared against `Imm`.
-class CheckImmOperandGE<int Index, int Imm> : CheckNot<CheckImmOperandLT<Index, Imm>>;
+// Check that the operand at position `Index` is an immediate operand whose
+// value is greater than or equal to `Imm`. If field `FunctionMapper` is a
+// non-empty string, then function `FunctionMapper` is applied to the operand
+// value, and the return value is then compared against `Imm`.
+class CheckImmOperandGE<int Index, int Imm> : CheckOperandBase<Index> {
+  int ImmVal = Imm;
+}
 
 // Expands to a call to `FunctionMapper` if field `FunctionMapper` is set.
 // Otherwise, it expands to a CheckNot<CheckInvalidRegOperand<Index>>.
@@ -231,12 +254,15 @@ class CheckAll<list<MCInstPredicate> Sequence>
 class CheckAny<list<MCInstPredicate> Sequence>
     : CheckPredicateSequence<Sequence>;
 
-// Check that the operand at position `Index` is in range [Start, End].
-// If field `FunctionMapper` is a non-empty string, then function
-// `FunctionMapper` is applied to the operand value, and the return value is then
-// compared against range [Start, End].
+// Check that the operand at position `Index` is an immediate operand whose
+// value is in range [Start, End]. If field `FunctionMapper` is a non-empty
+// string, then function `FunctionMapper` is applied to the operand value,
+// and the return value is then compared against range [Start, End].
 class CheckImmOperandRange<int Index, int Start, int End>
-  : CheckAll<[CheckImmOperandGE<Index, Start>, CheckImmOperandLE<Index, End>]>;
+    : CheckOperandBase<Index> {
+  int StartVal = Start;
+  int EndVal = End;
+}
 
 // Used to expand the body of a function predicate. See the definition of
 // TIIPredicate below.

diff  --git a/llvm/lib/Target/AArch64/AArch64SchedPredNeoverse.td b/llvm/lib/Target/AArch64/AArch64SchedPredNeoverse.td
index 41ea3551f35c0..737d7fe9ecc8c 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedPredNeoverse.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedPredNeoverse.td
@@ -66,7 +66,6 @@ def NeoverseZeroMove : MCSchedPredicate<
                            // MOV Wd, #0
                            // MOV Xd, #0
                            CheckAll<[CheckOpcode<[MOVZWi, MOVZXi]>,
-                                     CheckIsImmOperand<1>,
                                      CheckImmOperand<1, 0>,
                                      CheckImmOperand<2, 0>]>,
                            // MOV Wd, WZR
@@ -103,7 +102,6 @@ def NeoverseAllActivePredicate : MCSchedPredicate<
                                        CheckOpcode<[
                                          PTRUE_B, PTRUE_H, PTRUE_S, PTRUE_D,
                                          PTRUES_B, PTRUES_H, PTRUES_S, PTRUES_D]>,
-                                       CheckIsImmOperand<1>,
                                        CheckImmOperand<1, 31>]>,
                                    ]>>;
 

diff  --git a/llvm/lib/Target/AArch64/AArch64SchedPredicates.td b/llvm/lib/Target/AArch64/AArch64SchedPredicates.td
index 870a82bdffd74..cbaaafccd164d 100644
--- a/llvm/lib/Target/AArch64/AArch64SchedPredicates.td
+++ b/llvm/lib/Target/AArch64/AArch64SchedPredicates.td
@@ -294,9 +294,7 @@ def IsCopyIdiomFn     : TIIPredicate<"isCopyIdiom",
                                           [ADDWri, ADDXri],
                                           MCReturnStatement<
                                             CheckAll<
-                                              [CheckIsRegOperand<0>,
-                                               CheckIsRegOperand<1>,
-                                               CheckAny<
+                                              [CheckAny<
                                                  [CheckRegOperand<0, WSP>,
                                                   CheckRegOperand<0, SP>,
                                                   CheckRegOperand<1, WSP>,
@@ -391,40 +389,34 @@ def IsFastSBFMImmPred : MCSchedPredicate<CheckAny<[
        IsSBFMASRImm<SBFMXri, 64> ]>>;
 
 // Identify whether destination operand is a W-form register.
-def CheckIsWRegOp0 : CheckAll<[
-  CheckIsRegOperand<0>,
-  CheckAny<[
-    CheckRegOperand<0, W0>,  CheckRegOperand<0, W1>,  CheckRegOperand<0, W2>,
-    CheckRegOperand<0, W3>,  CheckRegOperand<0, W4>,  CheckRegOperand<0, W5>,
-    CheckRegOperand<0, W6>,  CheckRegOperand<0, W7>,  CheckRegOperand<0, W8>,
-    CheckRegOperand<0, W9>,  CheckRegOperand<0, W10>, CheckRegOperand<0, W11>,
-    CheckRegOperand<0, W12>, CheckRegOperand<0, W13>, CheckRegOperand<0, W14>,
-    CheckRegOperand<0, W15>, CheckRegOperand<0, W16>, CheckRegOperand<0, W17>,
-    CheckRegOperand<0, W18>, CheckRegOperand<0, W19>, CheckRegOperand<0, W20>,
-    CheckRegOperand<0, W21>, CheckRegOperand<0, W22>, CheckRegOperand<0, W23>,
-    CheckRegOperand<0, W24>, CheckRegOperand<0, W25>, CheckRegOperand<0, W26>,
-    CheckRegOperand<0, W27>, CheckRegOperand<0, W28>, CheckRegOperand<0, W29>,
-    CheckRegOperand<0, W30>, CheckRegOperand<0, WZR>, CheckRegOperand<0, WSP>
-  ]>
+def CheckIsWRegOp0 : CheckAny<[
+  CheckRegOperand<0, W0>,  CheckRegOperand<0, W1>,  CheckRegOperand<0, W2>,
+  CheckRegOperand<0, W3>,  CheckRegOperand<0, W4>,  CheckRegOperand<0, W5>,
+  CheckRegOperand<0, W6>,  CheckRegOperand<0, W7>,  CheckRegOperand<0, W8>,
+  CheckRegOperand<0, W9>,  CheckRegOperand<0, W10>, CheckRegOperand<0, W11>,
+  CheckRegOperand<0, W12>, CheckRegOperand<0, W13>, CheckRegOperand<0, W14>,
+  CheckRegOperand<0, W15>, CheckRegOperand<0, W16>, CheckRegOperand<0, W17>,
+  CheckRegOperand<0, W18>, CheckRegOperand<0, W19>, CheckRegOperand<0, W20>,
+  CheckRegOperand<0, W21>, CheckRegOperand<0, W22>, CheckRegOperand<0, W23>,
+  CheckRegOperand<0, W24>, CheckRegOperand<0, W25>, CheckRegOperand<0, W26>,
+  CheckRegOperand<0, W27>, CheckRegOperand<0, W28>, CheckRegOperand<0, W29>,
+  CheckRegOperand<0, W30>, CheckRegOperand<0, WZR>, CheckRegOperand<0, WSP>
 ]>;
 def IsWFormPred : MCSchedPredicate<CheckIsWRegOp0>;
 
 // Identify whether destination operand is an X-form register.
-def CheckIsXRegOp0 : CheckAll<[
-  CheckIsRegOperand<0>,
-  CheckAny<[
-    CheckRegOperand<0, X0>,  CheckRegOperand<0, X1>,  CheckRegOperand<0, X2>,
-    CheckRegOperand<0, X3>,  CheckRegOperand<0, X4>,  CheckRegOperand<0, X5>,
-    CheckRegOperand<0, X6>,  CheckRegOperand<0, X7>,  CheckRegOperand<0, X8>,
-    CheckRegOperand<0, X9>,  CheckRegOperand<0, X10>, CheckRegOperand<0, X11>,
-    CheckRegOperand<0, X12>, CheckRegOperand<0, X13>, CheckRegOperand<0, X14>,
-    CheckRegOperand<0, X15>, CheckRegOperand<0, X16>, CheckRegOperand<0, X17>,
-    CheckRegOperand<0, X18>, CheckRegOperand<0, X19>, CheckRegOperand<0, X20>,
-    CheckRegOperand<0, X21>, CheckRegOperand<0, X22>, CheckRegOperand<0, X23>,
-    CheckRegOperand<0, X24>, CheckRegOperand<0, X25>, CheckRegOperand<0, X26>,
-    CheckRegOperand<0, X27>, CheckRegOperand<0, X28>, CheckRegOperand<0, FP>,
-    CheckRegOperand<0, LR>, CheckRegOperand<0, XZR>, CheckRegOperand<0, SP>
-  ]>
+def CheckIsXRegOp0 : CheckAny<[
+  CheckRegOperand<0, X0>,  CheckRegOperand<0, X1>,  CheckRegOperand<0, X2>,
+  CheckRegOperand<0, X3>,  CheckRegOperand<0, X4>,  CheckRegOperand<0, X5>,
+  CheckRegOperand<0, X6>,  CheckRegOperand<0, X7>,  CheckRegOperand<0, X8>,
+  CheckRegOperand<0, X9>,  CheckRegOperand<0, X10>, CheckRegOperand<0, X11>,
+  CheckRegOperand<0, X12>, CheckRegOperand<0, X13>, CheckRegOperand<0, X14>,
+  CheckRegOperand<0, X15>, CheckRegOperand<0, X16>, CheckRegOperand<0, X17>,
+  CheckRegOperand<0, X18>, CheckRegOperand<0, X19>, CheckRegOperand<0, X20>,
+  CheckRegOperand<0, X21>, CheckRegOperand<0, X22>, CheckRegOperand<0, X23>,
+  CheckRegOperand<0, X24>, CheckRegOperand<0, X25>, CheckRegOperand<0, X26>,
+  CheckRegOperand<0, X27>, CheckRegOperand<0, X28>, CheckRegOperand<0, FP>,
+  CheckRegOperand<0, LR>, CheckRegOperand<0, XZR>, CheckRegOperand<0, SP>
 ]>;
 def IsXFormPred : MCSchedPredicate<CheckIsXRegOp0>;
 
@@ -432,21 +424,18 @@ def IsXOrWDest : MCSchedPredicate<
   CheckAll<[CheckAny<[CheckIsXRegOp0, CheckIsWRegOp0]>]>
 >;
 
-def CheckIsZRegOp0 : CheckAll<[
-  CheckIsRegOperand<0>,
-  CheckAny<[
-    CheckRegOperand<0, Z0>,  CheckRegOperand<0, Z1>,  CheckRegOperand<0, Z2>,
-    CheckRegOperand<0, Z3>,  CheckRegOperand<0, Z4>,  CheckRegOperand<0, Z5>,
-    CheckRegOperand<0, Z6>,  CheckRegOperand<0, Z7>,  CheckRegOperand<0, Z8>,
-    CheckRegOperand<0, Z9>,  CheckRegOperand<0, Z10>, CheckRegOperand<0, Z11>,
-    CheckRegOperand<0, Z12>, CheckRegOperand<0, Z13>, CheckRegOperand<0, Z14>,
-    CheckRegOperand<0, Z15>, CheckRegOperand<0, Z16>, CheckRegOperand<0, Z17>,
-    CheckRegOperand<0, Z18>, CheckRegOperand<0, Z19>, CheckRegOperand<0, Z20>,
-    CheckRegOperand<0, Z21>, CheckRegOperand<0, Z22>, CheckRegOperand<0, Z23>,
-    CheckRegOperand<0, Z24>, CheckRegOperand<0, Z25>, CheckRegOperand<0, Z26>,
-    CheckRegOperand<0, Z27>, CheckRegOperand<0, Z28>, CheckRegOperand<0, Z29>,
-    CheckRegOperand<0, Z30>, CheckRegOperand<0, Z31>
-  ]>
+def CheckIsZRegOp0 : CheckAny<[
+  CheckRegOperand<0, Z0>,  CheckRegOperand<0, Z1>,  CheckRegOperand<0, Z2>,
+  CheckRegOperand<0, Z3>,  CheckRegOperand<0, Z4>,  CheckRegOperand<0, Z5>,
+  CheckRegOperand<0, Z6>,  CheckRegOperand<0, Z7>,  CheckRegOperand<0, Z8>,
+  CheckRegOperand<0, Z9>,  CheckRegOperand<0, Z10>, CheckRegOperand<0, Z11>,
+  CheckRegOperand<0, Z12>, CheckRegOperand<0, Z13>, CheckRegOperand<0, Z14>,
+  CheckRegOperand<0, Z15>, CheckRegOperand<0, Z16>, CheckRegOperand<0, Z17>,
+  CheckRegOperand<0, Z18>, CheckRegOperand<0, Z19>, CheckRegOperand<0, Z20>,
+  CheckRegOperand<0, Z21>, CheckRegOperand<0, Z22>, CheckRegOperand<0, Z23>,
+  CheckRegOperand<0, Z24>, CheckRegOperand<0, Z25>, CheckRegOperand<0, Z26>,
+  CheckRegOperand<0, Z27>, CheckRegOperand<0, Z28>, CheckRegOperand<0, Z29>,
+  CheckRegOperand<0, Z30>, CheckRegOperand<0, Z31>
 ]>;
 
 

diff  --git a/llvm/lib/Target/ARM/ARMScheduleM85.td b/llvm/lib/Target/ARM/ARMScheduleM85.td
index beeda468397ec..8b5e19501516b 100644
--- a/llvm/lib/Target/ARM/ARMScheduleM85.td
+++ b/llvm/lib/Target/ARM/ARMScheduleM85.td
@@ -605,9 +605,7 @@ let SingleIssue = 1 in {
   def M85VMSRLate  : SchedWriteRes<[M85UnitVPort]> { let Latency = 3; }
 }
 
-def M85FPSCRFlagPred : MCSchedPredicate<
-                           CheckAll<[CheckIsRegOperand<0>,
-                                     CheckRegOperand<0, PC>]>>;
+def M85FPSCRFlagPred : MCSchedPredicate<CheckRegOperand<0, PC>>;
 
 def M85VMRSFPSCR : SchedWriteVariant<[
   SchedVar<M85FPSCRFlagPred, [M85VMRSEarly]>,

diff  --git a/llvm/lib/Target/RISCV/RISCVInstrPredicates.td b/llvm/lib/Target/RISCV/RISCVInstrPredicates.td
index cff834150cfeb..e90ee9996d30c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrPredicates.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrPredicates.td
@@ -33,7 +33,6 @@ def isSEXT_W
                    MCReturnStatement<CheckAll<[
                      CheckOpcode<[ADDIW]>,
                      CheckIsRegOperand<1>,
-                     CheckIsImmOperand<2>,
                      CheckImmOperand<2, 0>
                    ]>>>;
 
@@ -43,7 +42,6 @@ def isZEXT_W
                    MCReturnStatement<CheckAll<[
                      CheckOpcode<[ADD_UW]>,
                      CheckIsRegOperand<1>,
-                     CheckIsRegOperand<2>,
                      CheckRegOperand<2, X0>
                    ]>>>;
 
@@ -53,7 +51,6 @@ def isZEXT_B
                    MCReturnStatement<CheckAll<[
                      CheckOpcode<[ANDI]>,
                      CheckIsRegOperand<1>,
-                     CheckIsImmOperand<2>,
                      CheckImmOperand<2, 255>
                    ]>>>;
 
@@ -184,7 +181,6 @@ def isLoadImmediate
     : TIIPredicate<"isLoadImmediate",
                    MCReturnStatement<CheckAll<[
                      CheckOpcode<[ADDI]>,
-                     CheckIsRegOperand<1>,
                      CheckRegOperand<1, X0>,
                      CheckIsImmOperand<2>
                    ]>>>;
@@ -193,7 +189,6 @@ def isNonZeroLoadImmediate
     : TIIPredicate<"isNonZeroLoadImmediate",
                    MCReturnStatement<CheckAll<[
                      CheckOpcode<[ADDI]>,
-                     CheckIsRegOperand<1>,
                      CheckRegOperand<1, X0>,
                      CheckIsImmOperand<2>,
                      CheckNot<CheckImmOperand<2, 0>>
@@ -203,7 +198,6 @@ def isLPAD
     : TIIPredicate<"isLPAD",
                    MCReturnStatement<CheckAll<[
                      CheckOpcode<[AUIPC]>,
-                     CheckIsRegOperand<0>,
                      CheckRegOperand<0, X0>,
                    ]>>>;
 

diff  --git a/llvm/lib/Target/RISCV/RISCVMacroFusion.td b/llvm/lib/Target/RISCV/RISCVMacroFusion.td
index cf11cbac583e6..875cbebc67f0b 100644
--- a/llvm/lib/Target/RISCV/RISCVMacroFusion.td
+++ b/llvm/lib/Target/RISCV/RISCVMacroFusion.td
@@ -36,12 +36,10 @@ def TuneZExtHFusion
                  "Enable SLLI+SRLI to be fused to zero extension of halfword",
                  CheckAll<[
                    CheckOpcode<[SLLI]>,
-                   CheckIsImmOperand<2>,
                    CheckImmOperand<2, 48>
                  ]>,
                  CheckAll<[
                    CheckOpcode<[SRLI]>,
-                   CheckIsImmOperand<2>,
                    CheckImmOperand<2, 48>
                  ]>>;
 
@@ -53,12 +51,10 @@ def TuneZExtWFusion
                  "Enable SLLI+SRLI to be fused to zero extension of word",
                  CheckAll<[
                    CheckOpcode<[SLLI]>,
-                   CheckIsImmOperand<2>,
                    CheckImmOperand<2, 32>
                  ]>,
                  CheckAll<[
                    CheckOpcode<[SRLI]>,
-                   CheckIsImmOperand<2>,
                    CheckImmOperand<2, 32>
                  ]>>;
 
@@ -71,12 +67,10 @@ def TuneShiftedZExtWFusion
                  "Enable SLLI+SRLI to be fused when computing (shifted) word zero extension",
                  CheckAll<[
                    CheckOpcode<[SLLI]>,
-                   CheckIsImmOperand<2>,
                    CheckImmOperand<2, 32>
                  ]>,
                  CheckAll<[
                    CheckOpcode<[SRLI]>,
-                   CheckIsImmOperand<2>,
                    CheckImmOperandRange<2, 0, 31>
                  ]>>;
 
@@ -88,7 +82,6 @@ def TuneLDADDFusion
                  CheckOpcode<[ADD]>,
                  CheckAll<[
                    CheckOpcode<[LD]>,
-                   CheckIsImmOperand<2>,
                    CheckImmOperand<2, 0>
                  ]>>;
 
@@ -227,7 +220,6 @@ def TuneFusionAddMem
              SecondFusionPredicateWithMCInstPredicate<
                CheckAll<[
                  CheckOpcode<LoadStore>,
-                 CheckIsImmOperand<2>,
                  CheckImmOperand<2, 0>
                ]>
              >,

diff  --git a/llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td b/llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td
index 2fedb06bb3006..d1fc6ca0db983 100644
--- a/llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td
+++ b/llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td
@@ -24,7 +24,6 @@ def TuneMOVIMMALUXqciFusion
                  CheckAny<[
                    CheckAll<[
                      CheckOpcode<[ADDI]>,
-                     CheckIsRegOperand<1>,
                      CheckRegOperand<1, X0>
                    ]>,
                    CheckOpcode<LoadImmOp>,
@@ -45,7 +44,6 @@ def TuneMOVIMMMULXqciFusion
                  CheckAny<[
                    CheckAll<[
                      CheckOpcode<[ADDI]>,
-                     CheckIsRegOperand<1>,
                      CheckRegOperand<1, X0>
                    ]>,
                    CheckOpcode<LoadImmOp>,
@@ -59,7 +57,6 @@ def TuneMOVIMMLoadStoreXqciFusion
                  CheckAny<[
                    CheckAll<[
                      CheckOpcode<[ADDI]>,
-                     CheckIsRegOperand<1>,
                      CheckRegOperand<1, X0>
                    ]>,
                    CheckOpcode<LoadImmOp>,
@@ -73,7 +70,6 @@ def TuneMOVIMMJumpXqciFusion
                  CheckAny<[
                    CheckAll<[
                      CheckOpcode<[ADDI]>,
-                     CheckIsRegOperand<1>,
                      CheckRegOperand<1, X0>
                    ]>,
                    CheckOpcode<LoadImmOp>,
@@ -90,7 +86,6 @@ def TuneMOVIMMLongAccumXciFusion
                  CheckAny<[
                    CheckAll<[
                      CheckOpcode<[ADDI]>,
-                     CheckIsRegOperand<1>,
                      CheckRegOperand<1, X0>
                    ]>,
                    CheckOpcode<LoadImmOp>,
@@ -104,7 +99,6 @@ def TuneMovALUXqciFusion
                  "Enable MOV + long accumulate macrofusion",
                  CheckAll<[
                    CheckOpcode<[ADDI]>,
-                   CheckIsImmOperand<2>,
                    CheckImmOperand<2, 0>,
                  ]>,
                  CheckOpcode<LongAccumXqciOp>,

diff  --git a/llvm/test/TableGen/MacroFusion.td b/llvm/test/TableGen/MacroFusion.td
index da4adf75ac7eb..909298f0f4bd3 100644
--- a/llvm/test/TableGen/MacroFusion.td
+++ b/llvm/test/TableGen/MacroFusion.td
@@ -117,12 +117,12 @@ def TestPostRAOnlyFusion: SimpleFusion<"test-postra-only", "HasTestPostRAOnlyFus
 // CHECK-PREDICATOR-NEXT:    {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} auto &MRI = SecondMI.getMF()->getRegInfo();
 // CHECK-PREDICATOR-NEXT:    {
 // CHECK-PREDICATOR-NEXT:      {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} const MachineInstr *MI = FirstMI;
-// CHECK-PREDICATOR-NEXT:      if (MI->getOperand(0).getReg() != Test::X0)
+// CHECK-PREDICATOR-NEXT:      if (!(MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == Test::X0))
 // CHECK-PREDICATOR-NEXT:        return false;
 // CHECK-PREDICATOR-NEXT:    }
 // CHECK-PREDICATOR-NEXT:    {
 // CHECK-PREDICATOR-NEXT:      {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} const MachineInstr *MI = &SecondMI;
-// CHECK-PREDICATOR-NEXT:      if (MI->getOperand(0).getReg() != Test::X0)
+// CHECK-PREDICATOR-NEXT:      if (!(MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == Test::X0))
 // CHECK-PREDICATOR-NEXT:        return false;
 // CHECK-PREDICATOR-NEXT:    }
 // CHECK-PREDICATOR-NEXT:    if (SecondMI.getMF()->getProperties().hasNoVRegs())
@@ -145,7 +145,7 @@ def TestPostRAOnlyFusion: SimpleFusion<"test-postra-only", "HasTestPostRAOnlyFus
 // CHECK-PREDICATOR-NEXT:      {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} const MachineInstr *MI = &SecondMI;
 // CHECK-PREDICATOR-NEXT:      if (!(
 // CHECK-PREDICATOR-NEXT:          ( MI->getOpcode() == Test::Inst1 )
-// CHECK-PREDICATOR-NEXT:          && MI->getOperand(0).getReg() == Test::X0
+// CHECK-PREDICATOR-NEXT:          && (MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == Test::X0)
 // CHECK-PREDICATOR-NEXT:        ))
 // CHECK-PREDICATOR-NEXT:        return false;
 // CHECK-PREDICATOR-NEXT:    }
@@ -227,7 +227,7 @@ def TestPostRAOnlyFusion: SimpleFusion<"test-postra-only", "HasTestPostRAOnlyFus
 // CHECK-PREDICATOR-NEXT:      {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} const MachineInstr *MI = &SecondMI;
 // CHECK-PREDICATOR-NEXT:      if (!(
 // CHECK-PREDICATOR-NEXT:          ( MI->getOpcode() == Test::Inst1 )
-// CHECK-PREDICATOR-NEXT:          && MI->getOperand(0).getReg() == Test::X0
+// CHECK-PREDICATOR-NEXT:          && (MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == Test::X0)
 // CHECK-PREDICATOR-NEXT:        ))
 // CHECK-PREDICATOR-NEXT:        return false;
 // CHECK-PREDICATOR-NEXT:    }
@@ -349,7 +349,7 @@ def TestPostRAOnlyFusion: SimpleFusion<"test-postra-only", "HasTestPostRAOnlyFus
 // CHECK-PREDICATOR-NEXT:      {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} const MachineInstr *MI = &SecondMI;
 // CHECK-PREDICATOR-NEXT:      if (!(
 // CHECK-PREDICATOR-NEXT:          ( MI->getOpcode() == Test::Inst2 )
-// CHECK-PREDICATOR-NEXT:          && MI->getOperand(0).getReg() == Test::X0
+// CHECK-PREDICATOR-NEXT:          && (MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == Test::X0)
 // CHECK-PREDICATOR-NEXT:        ))
 // CHECK-PREDICATOR-NEXT:        return false;
 // CHECK-PREDICATOR-NEXT:    }

diff  --git a/llvm/test/TableGen/PredicateExpander.td b/llvm/test/TableGen/PredicateExpander.td
new file mode 100644
index 0000000000000..b98bc6b2eb153
--- /dev/null
+++ b/llvm/test/TableGen/PredicateExpander.td
@@ -0,0 +1,285 @@
+// RUN: llvm-tblgen -gen-instr-info -I %p/../../include %s | FileCheck %s
+
+include "llvm/Target/Target.td"
+
+def TestInstrInfo : InstrInfo;
+def Test : Target {
+  let InstructionSet = TestInstrInfo;
+}
+
+let Namespace = "Test" in {
+  def R0 : Register<"r0">;
+  def GPR : RegisterClass<"GPR", [i32], 32, (add R0)>;
+
+  let OutOperandList = (outs), InOperandList = (ins) in
+  def Inst : Instruction;
+}
+
+defm : RemapAllTargetPseudoPointerOperands<GPR>;
+
+def CheckImmEq
+  : TIIPredicate<"checkImmEq", MCReturnStatement<CheckImmOperand<0, 7>>>;
+def CheckImmEqString
+  : TIIPredicate<"checkImmEqString",
+      MCReturnStatement<CheckImmOperand_s<1, "Test::Value">>>;
+def CheckImmSimple
+  : TIIPredicate<"checkImmSimple", MCReturnStatement<CheckImmOperandSimple<1>>>;
+def CheckImmLT
+  : TIIPredicate<"checkImmLT", MCReturnStatement<CheckImmOperandLT<2, 17>>>;
+def CheckImmLE
+  : TIIPredicate<"checkImmLE", MCReturnStatement<CheckImmOperandLE<2, 18>>>;
+def CheckImmGT
+  : TIIPredicate<"checkImmGT", MCReturnStatement<CheckImmOperandGT<2, 19>>>;
+def CheckImmGE
+  : TIIPredicate<"checkImmGE", MCReturnStatement<CheckImmOperandGE<2, 20>>>;
+def CheckImmRange
+  : TIIPredicate<"checkImmRange", MCReturnStatement<CheckImmOperandRange<2, 21, 23>>>;
+
+def CheckNotImmEq
+  : TIIPredicate<"checkNotImmEq", MCReturnStatement<CheckNot<CheckImmOperand<1, 15>>>>;
+def CheckNotImmSimple
+  : TIIPredicate<"checkNotImmSimple", MCReturnStatement<CheckNot<CheckImmOperandSimple<1>>>>;
+
+def CheckRegEq
+  : TIIPredicate<"checkRegEq",
+      MCReturnStatement<CheckRegOperand<1, R0>>>;
+def CheckRegSimple
+  : TIIPredicate<"checkRegSimple",
+      MCReturnStatement<CheckRegOperandSimple<1>>>;
+
+def CheckNotRegEq
+  : TIIPredicate<"checkNotRegEq", MCReturnStatement<CheckNot<CheckRegOperand<2, R0>>>>;
+def CheckNotRegSimple
+  : TIIPredicate<"checkNotRegSimple", MCReturnStatement<CheckNot<CheckRegOperandSimple<2>>>>;
+
+let FunctionMapper = "mapImm" in {
+  def MappedImmEq : CheckImmOperand<2, 9>;
+  def MappedImmEqString : CheckImmOperand_s<2, "Test::Value">;
+  def MappedImmGE : CheckImmOperandGE<2, 25>;
+  def MappedImmSimple : CheckImmOperandSimple<1>;
+  def MappedImmLE : CheckImmOperandLE<2, 10>;
+  def MappedImmLT : CheckImmOperandLT<2, 11>;
+  def MappedImmGT : CheckImmOperandGT<2, 13>;
+  def MappedImmRange : CheckImmOperandRange<2, 9, 31>;
+}
+
+let FunctionMapper = "mapReg" in {
+  def MappedRegEq : CheckRegOperand<1, R0>;
+  def MappedRegSimple : CheckRegOperandSimple<1>;
+}
+
+def CheckMappedImmEq
+  : TIIPredicate<"checkMappedImmEq", MCReturnStatement<MappedImmEq>>;
+def CheckMappedImmEqString
+  : TIIPredicate<"checkMappedImmEqString", MCReturnStatement<MappedImmEqString>>;
+def CheckMappedImmSimple
+  : TIIPredicate<"checkMappedImmSimple", MCReturnStatement<MappedImmSimple>>;
+def CheckMappedImmLT
+  : TIIPredicate<"checkMappedImmLT", MCReturnStatement<MappedImmLT>>;
+def CheckMappedImmLE
+  : TIIPredicate<"checkMappedImmLE", MCReturnStatement<MappedImmLE>>;
+def CheckMappedImmGT
+  : TIIPredicate<"checkMappedImmGT", MCReturnStatement<MappedImmGT>>;
+def CheckMappedImmGE
+  : TIIPredicate<"checkMappedImmGE", MCReturnStatement<MappedImmGE>>;
+def CheckMappedImmRange
+  : TIIPredicate<"checkMappedImmRange", MCReturnStatement<MappedImmRange>>;
+
+def CheckMappedRegEq
+  : TIIPredicate<"checkMappedRegEq", MCReturnStatement<MappedRegEq>>;
+def CheckMappedRegSimple
+  : TIIPredicate<"checkMappedRegSimple", MCReturnStatement<MappedRegSimple>>;
+
+// CHECK: bool TestInstrInfo::checkImmEq(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 7);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkImmEqString(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == Test::Value);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkImmGE(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() >= 20);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkImmGT(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() > 19);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkImmLE(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() <= 18);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkImmLT(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() < 17);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkImmRange(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() >= 21 && MI.getOperand(2).getImm() <= 23);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkImmSimple(const MachineInstr &MI) {
+// CHECK-NEXT:   return true;
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedImmEq(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) == 9);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedImmEqString(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) == Test::Value);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedImmGE(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) >= 25);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedImmGT(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) > 13);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedImmLE(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) <= 10);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedImmLT(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) < 11);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedImmRange(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) >= 9 && mapImm(MI.getOperand(2).getImm()) <= 31);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedImmSimple(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isImm() && mapImm(MI.getOperand(1).getImm()));
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedRegEq(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isReg() && mapReg(MI.getOperand(1).getReg()) == Test::R0);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkMappedRegSimple(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isReg() && mapReg(MI.getOperand(1).getReg()));
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkNotImmEq(const MachineInstr &MI) {
+// CHECK-NEXT:   return !(MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 15);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkNotImmSimple(const MachineInstr &MI) {
+// CHECK-NEXT:   return false;
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkNotRegEq(const MachineInstr &MI) {
+// CHECK-NEXT:   return !(MI.getOperand(2).isReg() && MI.getOperand(2).getReg() == Test::R0);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkNotRegSimple(const MachineInstr &MI) {
+// CHECK-NEXT:   return !(MI.getOperand(2).isReg() && MI.getOperand(2).getReg().isValid());
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkRegEq(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == Test::R0);
+// CHECK-NEXT: }
+
+// CHECK: bool TestInstrInfo::checkRegSimple(const MachineInstr &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isValid());
+// CHECK-NEXT: }
+
+// CHECK: namespace llvm::Test_MC {
+
+// CHECK: bool checkImmEq(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 7);
+// CHECK-NEXT: }
+
+// CHECK: bool checkImmEqString(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == Test::Value);
+// CHECK-NEXT: }
+
+// CHECK: bool checkImmGE(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() >= 20);
+// CHECK-NEXT: }
+
+// CHECK: bool checkImmGT(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() > 19);
+// CHECK-NEXT: }
+
+// CHECK: bool checkImmLE(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() <= 18);
+// CHECK-NEXT: }
+
+// CHECK: bool checkImmLT(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() < 17);
+// CHECK-NEXT: }
+
+// CHECK: bool checkImmRange(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() >= 21 && MI.getOperand(2).getImm() <= 23);
+// CHECK-NEXT: }
+
+// CHECK: bool checkImmSimple(const MCInst &MI) {
+// CHECK-NEXT:   return true;
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedImmEq(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) == 9);
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedImmEqString(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) == Test::Value);
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedImmGE(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) >= 25);
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedImmGT(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) > 13);
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedImmLE(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) <= 10);
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedImmLT(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) < 11);
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedImmRange(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(2).isImm() && mapImm(MI.getOperand(2).getImm()) >= 9 && mapImm(MI.getOperand(2).getImm()) <= 31);
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedImmSimple(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isImm() && mapImm(MI.getOperand(1).getImm()));
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedRegEq(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isReg() && mapReg(MI.getOperand(1).getReg()) == Test::R0);
+// CHECK-NEXT: }
+
+// CHECK: bool checkMappedRegSimple(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isReg() && mapReg(MI.getOperand(1).getReg()));
+// CHECK-NEXT: }
+
+// CHECK: bool checkNotImmEq(const MCInst &MI) {
+// CHECK-NEXT:   return !(MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 15);
+// CHECK-NEXT: }
+
+// CHECK: bool checkNotImmSimple(const MCInst &MI) {
+// CHECK-NEXT:   return false;
+// CHECK-NEXT: }
+
+// CHECK: bool checkNotRegEq(const MCInst &MI) {
+// CHECK-NEXT:   return !(MI.getOperand(2).isReg() && MI.getOperand(2).getReg() == Test::R0);
+// CHECK-NEXT: }
+
+// CHECK: bool checkNotRegSimple(const MCInst &MI) {
+// CHECK-NEXT:   return !(MI.getOperand(2).isReg() && MI.getOperand(2).getReg().isValid());
+// CHECK-NEXT: }
+
+// CHECK: bool checkRegEq(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == Test::R0);
+// CHECK-NEXT: }
+
+// CHECK: bool checkRegSimple(const MCInst &MI) {
+// CHECK-NEXT:   return (MI.getOperand(1).isReg() && MI.getOperand(1).getReg().isValid());
+// CHECK-NEXT: }

diff  --git a/llvm/test/TableGen/ResolveSchedClass.td b/llvm/test/TableGen/ResolveSchedClass.td
index 665f5db85f227..dc5ac9ca07d54 100644
--- a/llvm/test/TableGen/ResolveSchedClass.td
+++ b/llvm/test/TableGen/ResolveSchedClass.td
@@ -72,9 +72,9 @@ def ProcessorA: ProcessorModel<"ProcessorA", SchedModel_A, []>;
 // CHECK-NEXT:   if (CPUID == {{.*}}) { // SchedModel_A
 // CHECK-NEXT:     if (STI.hasFeature(TestTarget::FeatureFoo))
 // CHECK-NEXT:       return {{.*}}; // SchedWriteResA
-// CHECK-NEXT:     if (STI.hasFeature(TestTarget::FeatureFoo) && MI->getOperand(1).getImm() == 0)
+// CHECK-NEXT:     if (STI.hasFeature(TestTarget::FeatureFoo) && (MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0))
 // CHECK-NEXT:       return {{.*}}; // SchedWriteResC
-// CHECK-NEXT:     if (!(MI->getOperand(3).getImm() == 0 && !STI.hasFeature(TestTarget::FeatureFoo)))
+// CHECK-NEXT:     if (!((MI->getOperand(3).isImm() && MI->getOperand(3).getImm() == 0) && !STI.hasFeature(TestTarget::FeatureFoo)))
 // CHECK-NEXT: 	     return {{.*}}; // SchedWriteResE
 // CHECK-NEXT:     return {{.*}}; // SchedWriteResB
 
@@ -91,10 +91,10 @@ def ProcessorA: ProcessorModel<"ProcessorA", SchedModel_A, []>;
 // CHECK-NEXT:     if (SchedModel->getProcessorID() == {{.*}}) { // SchedModel_A
 // CHECK-NEXT:       if (this->hasFeature(TestTarget::FeatureFoo))
 // CHECK-NEXT:         return {{.*}}; // SchedWriteResA
-// CHECK-NEXT:       if (this->hasFeature(TestTarget::FeatureFoo) && MI->getOperand(1).getImm() == 0)
+// CHECK-NEXT:       if (this->hasFeature(TestTarget::FeatureFoo) && (MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0))
 // CHECK-NEXT:         return {{.*}}; // SchedWriteResC
-// CHECK-NEXT:       if ((this->hasFeature(TestTarget::FeatureFoo) && MI->getOperand(1).getImm() == 0) || !(this->hasFeature(TestTarget::FeatureBar) || (/*hello=*/false)))
+// CHECK-NEXT:       if ((this->hasFeature(TestTarget::FeatureFoo) && (MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0)) || !(this->hasFeature(TestTarget::FeatureBar) || (/*hello=*/false)))
 // CHECK-NEXT:         return {{.*}}; // SchedWriteResD
-// CHECK-NEXT:       if (!(MI->getOperand(3).getImm() == 0 && !this->hasFeature(TestTarget::FeatureFoo)))
+// CHECK-NEXT:       if (!((MI->getOperand(3).isImm() && MI->getOperand(3).getImm() == 0) && !this->hasFeature(TestTarget::FeatureFoo)))
 // CHECK-NEXT: 	       return {{.*}}; // SchedWriteResE
 // CHECK-NEXT:       return {{.*}}; // SchedWriteResB

diff  --git a/llvm/utils/TableGen/Common/PredicateExpander.cpp b/llvm/utils/TableGen/Common/PredicateExpander.cpp
index c6d73f9c6721b..4d4826c6ec3be 100644
--- a/llvm/utils/TableGen/Common/PredicateExpander.cpp
+++ b/llvm/utils/TableGen/Common/PredicateExpander.cpp
@@ -19,68 +19,86 @@ using namespace llvm;
 void PredicateExpander::expandTrue(raw_ostream &OS) { OS << "true"; }
 void PredicateExpander::expandFalse(raw_ostream &OS) { OS << "false"; }
 
-void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
-                                              int ImmVal,
-                                              StringRef FunctionMapper) {
+void PredicateExpander::expandCheckImmOperandCommon(raw_ostream &OS,
+                                                    int OpIndex, int ImmVal,
+                                                    StringRef FunctionMapper,
+                                                    StringRef CmpOperator) {
+  OS << (shouldNegate() ? "!(" : "(");
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").isImm()";
+  OS << " && ";
   if (!FunctionMapper.empty())
     OS << FunctionMapper << "(";
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
      << ").getImm()";
   if (!FunctionMapper.empty())
     OS << ")";
-  OS << (shouldNegate() ? " != " : " == ") << ImmVal;
+  OS << " " << CmpOperator << " " << ImmVal;
+  OS << ")";
 }
 
 void PredicateExpander::expandCheckImmOperand(raw_ostream &OS, int OpIndex,
                                               StringRef ImmVal,
                                               StringRef FunctionMapper) {
   if (ImmVal.empty())
-    expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
+    return expandCheckImmOperandSimple(OS, OpIndex, FunctionMapper);
 
+  OS << (shouldNegate() ? "!(" : "(");
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").isImm()";
+  OS << " && ";
   if (!FunctionMapper.empty())
     OS << FunctionMapper << "(";
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
      << ").getImm()";
   if (!FunctionMapper.empty())
     OS << ")";
-  OS << (shouldNegate() ? " != " : " == ") << ImmVal;
+  OS << " == " << ImmVal;
+  OS << ")";
 }
 
 void PredicateExpander::expandCheckImmOperandSimple(raw_ostream &OS,
                                                     int OpIndex,
                                                     StringRef FunctionMapper) {
-  if (shouldNegate())
-    OS << "!";
-  if (!FunctionMapper.empty())
-    OS << FunctionMapper << "(";
+  if (FunctionMapper.empty())
+    return shouldNegate() ? expandFalse(OS) : expandTrue(OS);
+
+  OS << (shouldNegate() ? "!(" : "(");
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
-     << ").getImm()";
-  if (!FunctionMapper.empty())
-    OS << ")";
-}
+     << ").isImm()";
+  OS << " && ";
+  OS << FunctionMapper << "("
+     << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").getImm()"
+     << ")"
+     << ")";
+}
+
+void PredicateExpander::expandCheckImmOperandRange(raw_ostream &OS, int OpIndex,
+                                                   int StartVal, int EndVal,
+                                                   StringRef FunctionMapper) {
+  OS << (shouldNegate() ? "!(" : "(");
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").isImm()";
+  OS << " && ";
 
-void PredicateExpander::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,
-                                                int ImmVal,
-                                                StringRef FunctionMapper) {
   if (!FunctionMapper.empty())
     OS << FunctionMapper << "(";
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
      << ").getImm()";
   if (!FunctionMapper.empty())
     OS << ")";
-  OS << (shouldNegate() ? " >= " : " < ") << ImmVal;
-}
+  OS << " >= " << StartVal;
+  OS << " && ";
 
-void PredicateExpander::expandCheckImmOperandGT(raw_ostream &OS, int OpIndex,
-                                                int ImmVal,
-                                                StringRef FunctionMapper) {
   if (!FunctionMapper.empty())
     OS << FunctionMapper << "(";
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
      << ").getImm()";
   if (!FunctionMapper.empty())
     OS << ")";
-  OS << (shouldNegate() ? " <= " : " > ") << ImmVal;
+  OS << " <= " << EndVal;
+  OS << ")";
 }
 
 void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
@@ -88,45 +106,71 @@ void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
                                               StringRef FunctionMapper) {
   assert(Reg->isSubClassOf("Register") && "Expected a register Record!");
 
+  OS << (shouldNegate() ? "!(" : "(");
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").isReg()";
+  OS << " && ";
   if (!FunctionMapper.empty())
     OS << FunctionMapper << "(";
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
      << ").getReg()";
   if (!FunctionMapper.empty())
     OS << ")";
-  OS << (shouldNegate() ? " != " : " == ");
+  OS << " == ";
   const StringRef Str = Reg->getValueAsString("Namespace");
   if (!Str.empty())
     OS << Str << "::";
-  OS << Reg->getName();
+  OS << Reg->getName() << ")";
 }
 
 void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
                                                     int OpIndex,
                                                     StringRef FunctionMapper) {
-  if (shouldNegate())
-    OS << "!";
-  if (!FunctionMapper.empty())
-    OS << FunctionMapper << "(";
+  // Expand to CheckNot<CheckInvalidRegOperand<OpIndex>> when
+  // FunctionMapper is not set.
+  if (FunctionMapper.empty()) {
+    flipNegatePredicate();
+    expandCheckInvalidRegOperand(OS, OpIndex);
+    flipNegatePredicate();
+    return;
+  }
+  OS << (shouldNegate() ? "!(" : "(");
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").isReg()";
+  OS << " && ";
+  OS << FunctionMapper << "(";
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
      << ").getReg()";
-  if (!FunctionMapper.empty())
-    OS << ")";
+  OS << ")"
+     << ")";
 }
 
 void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
                                                      int OpIndex) {
-  if (!shouldNegate())
-    OS << "!";
+  OS << (shouldNegate() ? "(" : "!(");
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").isReg()";
+  OS << " && ";
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
      << ").getReg().isValid()";
+  OS << ")";
 }
 
 void PredicateExpander::expandCheckSameRegOperand(raw_ostream &OS, int First,
                                                   int Second) {
+  OS << (shouldNegate() ? "!(" : "(");
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
+     << ").isReg()";
+  OS << " && ";
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << Second
+     << ").isReg()";
+  OS << " && ";
   OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << First
-     << ").getReg() " << (shouldNegate() ? "!=" : "==") << " MI"
-     << (isByRef() ? "." : "->") << "getOperand(" << Second << ").getReg()";
+     << ").getReg() "
+     << "=="
+     << " MI" << (isByRef() ? "." : "->") << "getOperand(" << Second
+     << ").getReg()";
+  OS << ")";
 }
 
 void PredicateExpander::expandCheckNumOperands(raw_ostream &OS, int NumOps) {
@@ -205,8 +249,13 @@ void PredicateExpander::expandCheckIsRegOperand(raw_ostream &OS, int OpIndex) {
 }
 
 void PredicateExpander::expandCheckIsVRegOperand(raw_ostream &OS, int OpIndex) {
-  OS << (shouldNegate() ? "!" : "") << "MI" << (isByRef() ? "." : "->")
-     << "getOperand(" << OpIndex << ").getReg().isVirtual()";
+  OS << (shouldNegate() ? "!(" : "(");
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").isReg()";
+  OS << " && ";
+  OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
+     << ").getReg().isVirtual()";
+  OS << ")";
 }
 
 void PredicateExpander::expandCheckIsImmOperand(raw_ostream &OS, int OpIndex) {
@@ -345,9 +394,9 @@ void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
     return expandCheckInvalidRegOperand(OS, Rec->getValueAsInt("OpIndex"));
 
   if (Rec->isSubClassOf("CheckImmOperand"))
-    return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
-                                 Rec->getValueAsInt("ImmVal"),
-                                 Rec->getValueAsString("FunctionMapper"));
+    return expandCheckImmOperandCommon(
+        OS, Rec->getValueAsInt("OpIndex"), Rec->getValueAsInt("ImmVal"),
+        Rec->getValueAsString("FunctionMapper"), "==");
 
   if (Rec->isSubClassOf("CheckImmOperand_s"))
     return expandCheckImmOperand(OS, Rec->getValueAsInt("OpIndex"),
@@ -355,14 +404,29 @@ void PredicateExpander::expandPredicate(raw_ostream &OS, const Record *Rec) {
                                  Rec->getValueAsString("FunctionMapper"));
 
   if (Rec->isSubClassOf("CheckImmOperandLT"))
-    return expandCheckImmOperandLT(OS, Rec->getValueAsInt("OpIndex"),
-                                   Rec->getValueAsInt("ImmVal"),
-                                   Rec->getValueAsString("FunctionMapper"));
+    return expandCheckImmOperandCommon(
+        OS, Rec->getValueAsInt("OpIndex"), Rec->getValueAsInt("ImmVal"),
+        Rec->getValueAsString("FunctionMapper"), "<");
 
   if (Rec->isSubClassOf("CheckImmOperandGT"))
-    return expandCheckImmOperandGT(OS, Rec->getValueAsInt("OpIndex"),
-                                   Rec->getValueAsInt("ImmVal"),
-                                   Rec->getValueAsString("FunctionMapper"));
+    return expandCheckImmOperandCommon(
+        OS, Rec->getValueAsInt("OpIndex"), Rec->getValueAsInt("ImmVal"),
+        Rec->getValueAsString("FunctionMapper"), ">");
+
+  if (Rec->isSubClassOf("CheckImmOperandLE"))
+    return expandCheckImmOperandCommon(
+        OS, Rec->getValueAsInt("OpIndex"), Rec->getValueAsInt("ImmVal"),
+        Rec->getValueAsString("FunctionMapper"), "<=");
+
+  if (Rec->isSubClassOf("CheckImmOperandGE"))
+    return expandCheckImmOperandCommon(
+        OS, Rec->getValueAsInt("OpIndex"), Rec->getValueAsInt("ImmVal"),
+        Rec->getValueAsString("FunctionMapper"), ">=");
+
+  if (Rec->isSubClassOf("CheckImmOperandRange"))
+    return expandCheckImmOperandRange(
+        OS, Rec->getValueAsInt("OpIndex"), Rec->getValueAsInt("StartVal"),
+        Rec->getValueAsInt("EndVal"), Rec->getValueAsString("FunctionMapper"));
 
   if (Rec->isSubClassOf("CheckImmOperandSimple"))
     return expandCheckImmOperandSimple(OS, Rec->getValueAsInt("OpIndex"),

diff  --git a/llvm/utils/TableGen/Common/PredicateExpander.h b/llvm/utils/TableGen/Common/PredicateExpander.h
index 4439327af2b03..6555c89d02217 100644
--- a/llvm/utils/TableGen/Common/PredicateExpander.h
+++ b/llvm/utils/TableGen/Common/PredicateExpander.h
@@ -52,16 +52,15 @@ class PredicateExpander {
 
   void expandTrue(raw_ostream &OS);
   void expandFalse(raw_ostream &OS);
-  void expandCheckImmOperand(raw_ostream &OS, int OpIndex, int ImmVal,
-                             StringRef FunctionMapper);
+  void expandCheckImmOperandCommon(raw_ostream &OS, int OpIndex, int ImmVal,
+                                   StringRef FunctionMapper,
+                                   StringRef CmpOperator);
   void expandCheckImmOperand(raw_ostream &OS, int OpIndex, StringRef ImmVal,
-                             StringRef FunctionMapperer);
+                             StringRef FunctionMapper);
   void expandCheckImmOperandSimple(raw_ostream &OS, int OpIndex,
                                    StringRef FunctionMapper);
-  void expandCheckImmOperandLT(raw_ostream &OS, int OpIndex, int ImmVal,
-                               StringRef FunctionMapper);
-  void expandCheckImmOperandGT(raw_ostream &OS, int OpIndex, int ImmVal,
-                               StringRef FunctionMapper);
+  void expandCheckImmOperandRange(raw_ostream &OS, int OpIndex, int StartVal,
+                                  int EndVal, StringRef FunctionMapper);
   void expandCheckRegOperand(raw_ostream &OS, int OpIndex, const Record *Reg,
                              StringRef FunctionMapper);
   void expandCheckRegOperandSimple(raw_ostream &OS, int OpIndex,


        


More information about the llvm-commits mailing list