[llvm] [TableGen] Add isReg check for CheckRegOperand predicate (PR #215230)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 12 06:06:51 PDT 2026
https://github.com/renndong updated https://github.com/llvm/llvm-project/pull/215230
>From 6f165d9537abd605645df3a63a1750a31a70e587 Mon Sep 17 00:00:00 2001
From: liumingliang <liumingliang.dev at bytedance.com>
Date: Mon, 10 Aug 2026 16:39:53 +0800
Subject: [PATCH 1/2] [TableGen] Add isReg check for CheckRegOperand predicate
CheckRegOperand and CheckRegOperandSimple currently call getReg()
without first verifying that the operand is a register. Users must
use CheckIsRegOperand explicitly to avoid errors for other operand
kinds, as exposed by #213815.
This PR adds isReg() check for two predicates before accessing the
register value. And remove redundant CheckIsRegOperand checks from
existing users for x86, ARM and RISCV backend.
---
.../llvm/Target/TargetInstrPredicate.td | 13 ++-
.../Target/AArch64/AArch64SchedPredicates.td | 85 ++++++++-----------
llvm/lib/Target/ARM/ARMScheduleM85.td | 4 +-
llvm/lib/Target/RISCV/RISCVInstrPredicates.td | 4 -
llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td | 5 --
llvm/test/TableGen/MacroFusion.td | 10 +--
.../TableGen/Common/PredicateExpander.cpp | 15 +++-
7 files changed, 63 insertions(+), 73 deletions(-)
diff --git a/llvm/include/llvm/Target/TargetInstrPredicate.td b/llvm/include/llvm/Target/TargetInstrPredicate.td
index b5419cb9f3867..21ef96b95bfb8 100644
--- a/llvm/include/llvm/Target/TargetInstrPredicate.td
+++ b/llvm/include/llvm/Target/TargetInstrPredicate.td
@@ -28,7 +28,12 @@
//
// 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 unnecessary
+// when we don't care about the type of the operand (e.g. an immediate or a
+// register) but only care the fact that it is a target register.
//
// MCInstPredicate definitions are typically used by scheduling models to
// construct MCSchedPredicate definitions (see the definition of class
@@ -44,7 +49,7 @@
// def M3BranchLinkFastPred : 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 main advantage of using MCInstPredicate instead of SchedPredicate is
// portability: users don't need to specify predicates in C++. As a consequence
@@ -123,8 +128,8 @@ class CheckOperandBase<int Index, string Fn = ""> : MCOperandPredicate<Index> {
}
// 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.
+// register R. This predicate checks whether the operand at position `Index`
+// is a register first and return false when not satisfied.
class CheckRegOperand<int Index, Register R> : CheckOperandBase<Index> {
Register Reg = R;
}
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..ff045c32759d3 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrPredicates.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrPredicates.td
@@ -43,7 +43,6 @@ def isZEXT_W
MCReturnStatement<CheckAll<[
CheckOpcode<[ADD_UW]>,
CheckIsRegOperand<1>,
- CheckIsRegOperand<2>,
CheckRegOperand<2, X0>
]>>>;
@@ -184,7 +183,6 @@ def isLoadImmediate
: TIIPredicate<"isLoadImmediate",
MCReturnStatement<CheckAll<[
CheckOpcode<[ADDI]>,
- CheckIsRegOperand<1>,
CheckRegOperand<1, X0>,
CheckIsImmOperand<2>
]>>>;
@@ -193,7 +191,6 @@ def isNonZeroLoadImmediate
: TIIPredicate<"isNonZeroLoadImmediate",
MCReturnStatement<CheckAll<[
CheckOpcode<[ADDI]>,
- CheckIsRegOperand<1>,
CheckRegOperand<1, X0>,
CheckIsImmOperand<2>,
CheckNot<CheckImmOperand<2, 0>>
@@ -203,7 +200,6 @@ def isLPAD
: TIIPredicate<"isLPAD",
MCReturnStatement<CheckAll<[
CheckOpcode<[AUIPC]>,
- CheckIsRegOperand<0>,
CheckRegOperand<0, X0>,
]>>>;
diff --git a/llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td b/llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td
index 2fedb06bb3006..42c1e5c8e50b8 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>,
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/utils/TableGen/Common/PredicateExpander.cpp b/llvm/utils/TableGen/Common/PredicateExpander.cpp
index c6d73f9c6721b..ac0942df3d112 100644
--- a/llvm/utils/TableGen/Common/PredicateExpander.cpp
+++ b/llvm/utils/TableGen/Common/PredicateExpander.cpp
@@ -88,30 +88,37 @@ 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 << "!";
+ 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 << ")";
}
void PredicateExpander::expandCheckInvalidRegOperand(raw_ostream &OS,
>From fe65a2cd17b0d9adb23a301207058771439e8182 Mon Sep 17 00:00:00 2001
From: liumingliang <liumingliang.dev at bytedance.com>
Date: Wed, 12 Aug 2026 21:05:41 +0800
Subject: [PATCH 2/2] [TableGen] Add isImm check for CheckImmOperand predicate
---
.../llvm/Target/TargetInstrPredicate.td | 88 +++---
.../AArch64/AArch64SchedPredNeoverse.td | 2 -
llvm/lib/Target/RISCV/RISCVInstrPredicates.td | 2 -
llvm/lib/Target/RISCV/RISCVMacroFusion.td | 8 -
llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td | 1 -
llvm/test/TableGen/PredicateExpander.td | 285 ++++++++++++++++++
llvm/test/TableGen/ResolveSchedClass.td | 10 +-
.../TableGen/Common/PredicateExpander.cpp | 141 ++++++---
.../utils/TableGen/Common/PredicateExpander.h | 13 +-
9 files changed, 441 insertions(+), 109 deletions(-)
create mode 100644 llvm/test/TableGen/PredicateExpander.td
diff --git a/llvm/include/llvm/Target/TargetInstrPredicate.td b/llvm/include/llvm/Target/TargetInstrPredicate.td
index 21ef96b95bfb8..3cf3dfed167c8 100644
--- a/llvm/include/llvm/Target/TargetInstrPredicate.td
+++ b/llvm/include/llvm/Target/TargetInstrPredicate.td
@@ -15,25 +15,23 @@
//
// def MCInstPredicateExample : 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 different
+// The `CheckAll` from the example defines a composition of two different
// predicates. Definition `MCInstPredicateExample` identifies instructions
-// whose opcode is BLR, and whose first operand is a register different from
-// register `LR`.
+// whose opcode is BLR, and whose first operand is either not a register
+// operand or does not reference 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, 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 unnecessary
-// when we don't care about the type of the operand (e.g. an immediate or a
-// register) but only care the fact that it is a target register.
+// constraint on the value of an instruction opcode, while `CheckRegOperand`
+// checks whether an instruction operand is a register operand and matches a
+// specified register. Therefore, a preceding `CheckIsRegOperand` is unnecessary
+// as the `CheckRegOperand` predicate will necessarily be false if the operand
+// isn't a register.
//
// MCInstPredicate definitions are typically used by scheduling models to
// construct MCSchedPredicate definitions (see the definition of class
@@ -48,8 +46,8 @@
//
// def M3BranchLinkFastPred : SchedPredicate<[{
// MI->getOpcode() == AArch64::BLR &&
-// MI->getOperand(0).isReg() &&
-// !(MI->getOperand(0).isReg() && MI->getOperand(0).getReg() == AArch64::LR)}]>;
+// !(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
@@ -127,9 +125,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 checks whether the operand at position `Index`
-// is a register first and return false when not satisfied.
+// 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;
}
@@ -142,10 +139,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;
}
@@ -157,33 +154,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>>.
@@ -236,12 +237,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/RISCV/RISCVInstrPredicates.td b/llvm/lib/Target/RISCV/RISCVInstrPredicates.td
index ff045c32759d3..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>
]>>>;
@@ -52,7 +51,6 @@ def isZEXT_B
MCReturnStatement<CheckAll<[
CheckOpcode<[ANDI]>,
CheckIsRegOperand<1>,
- CheckIsImmOperand<2>,
CheckImmOperand<2, 255>
]>>>;
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 42c1e5c8e50b8..d1fc6ca0db983 100644
--- a/llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td
+++ b/llvm/lib/Target/RISCV/RISCVMacroFusionXQCI.td
@@ -99,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/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 ac0942df3d112..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::expandCheckImmOperandLT(raw_ostream &OS, int OpIndex,
- int ImmVal,
- StringRef FunctionMapper) {
+void PredicateExpander::expandCheckImmOperandRange(raw_ostream &OS, int OpIndex,
+ int StartVal, int EndVal,
+ StringRef 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 << " >= " << 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,
@@ -108,32 +126,51 @@ void PredicateExpander::expandCheckRegOperand(raw_ostream &OS, int OpIndex,
void PredicateExpander::expandCheckRegOperandSimple(raw_ostream &OS,
int OpIndex,
StringRef 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 << " && ";
- if (!FunctionMapper.empty())
- OS << FunctionMapper << "(";
+ OS << FunctionMapper << "(";
OS << "MI" << (isByRef() ? "." : "->") << "getOperand(" << OpIndex
<< ").getReg()";
- if (!FunctionMapper.empty())
- OS << ")";
- 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) {
@@ -212,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) {
@@ -352,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"),
@@ -362,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