[llvm] [TableGen][SchedModel] Introduce a new SchedPredicate that checks against SubtargetFeature (PR #161888)
Min-Yih Hsu via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 3 18:28:30 PDT 2025
https://github.com/mshockwave updated https://github.com/llvm/llvm-project/pull/161888
>From c0bc72bbc3246c51de9e3cfbd7ebc86f1614d54d Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Fri, 3 Oct 2025 09:42:33 -0700
Subject: [PATCH 1/3] [TableGen][SchedModel] Introduce a new SchedPredicate
that checks against SubtargetFeature
---
llvm/include/llvm/Target/TargetSchedule.td | 5 +++
llvm/test/TableGen/ResolveSchedClass.td | 46 ++++++++++++++++++++++
llvm/utils/TableGen/SubtargetEmitter.cpp | 14 ++++++-
3 files changed, 64 insertions(+), 1 deletion(-)
diff --git a/llvm/include/llvm/Target/TargetSchedule.td b/llvm/include/llvm/Target/TargetSchedule.td
index f55bff16dcecd..95622b8e73e8b 100644
--- a/llvm/include/llvm/Target/TargetSchedule.td
+++ b/llvm/include/llvm/Target/TargetSchedule.td
@@ -377,6 +377,11 @@ class MCSchedPredicate<MCInstPredicate P> : SchedPredicateBase {
SchedMachineModel SchedModel = ?;
}
+class FeatureSchedPredicate<SubtargetFeature SF> : SchedPredicateBase {
+ SubtargetFeature Feature = SF;
+ SchedMachineModel SchedModel = ?;
+}
+
// Define a predicate to determine which SchedVariant applies to a
// particular MachineInstr. The code snippet is used as an
// if-statement's expression. Available variables are MI, SchedModel,
diff --git a/llvm/test/TableGen/ResolveSchedClass.td b/llvm/test/TableGen/ResolveSchedClass.td
index 8c9ef1eab3566..c1cadb359ca03 100644
--- a/llvm/test/TableGen/ResolveSchedClass.td
+++ b/llvm/test/TableGen/ResolveSchedClass.td
@@ -8,11 +8,57 @@ def TestTarget : Target {
let InstructionSet = TestTargetInstrInfo;
}
+def FeatureFoo : SubtargetFeature<"foo", "HasFoo", "true", "enable foo">;
+
+def ResX0 : ProcResource<1>;
+
+let OutOperandList = (outs), InOperandList = (ins) in
+def Inst_A : Instruction;
+
+def SchedModel_A: SchedMachineModel {
+ let CompleteModel = false;
+}
+
+let SchedModel = SchedModel_A in {
+def SchedWriteResA : SchedWriteRes<[ResX0]> {
+ let Latency = 2;
+}
+def SchedWriteResB : SchedWriteRes<[ResX0]> {
+ let Latency = 4;
+}
+
+// Check SchedPredicate with subtarget feature.
+def FeatureFooPred : FeatureSchedPredicate<FeatureFoo>;
+
+def Variant : SchedWriteVariant<[
+ SchedVar<FeatureFooPred, [SchedWriteResA]>,
+ SchedVar<NoSchedPred, [SchedWriteResB]>
+]>;
+
+def : InstRW<[Variant], (instrs Inst_A)>;
+}
+
+def ProcessorA: ProcessorModel<"ProcessorA", SchedModel_A, []>;
+
// CHECK: unsigned resolveVariantSchedClassImpl(unsigned SchedClass,
// CHECK-NEXT: const MCInst *MI, const MCInstrInfo *MCII, const MCSubtargetInfo &STI, unsigned CPUID)
+// CHECK: case {{.*}}: // Inst_A
+// CHECK-NEXT: if (CPUID == {{.*}}) { // SchedModel_A
+// CHECK-NEXT: if (STI.hasFeature(TestTarget::FeatureFoo))
+// CHECK-NEXT: return {{.*}}; // SchedWriteResA
+// CHECK-NEXT: return {{.*}}; // SchedWriteResB
// CHECK: unsigned resolveVariantSchedClass(unsigned SchedClass,
// CHECK-NEXT: const MCInst *MI, const MCInstrInfo *MCII,
// CHECK-NEXT: unsigned CPUID) const override {
// CHECK-NEXT: return TestTarget_MC::resolveVariantSchedClassImpl(SchedClass, MI, MCII, *this, CPUID);
// CHECK-NEXT: }
+
+// CHECK: unsigned TestTargetGenSubtargetInfo
+// CHECK-NEXT: ::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI, const TargetSchedModel *SchedModel) const {
+// CHECK-NEXT: switch (SchedClass) {
+// CHECK-NEXT: case {{.*}}: // Inst_A
+// CHECK-NEXT: if (SchedModel->getProcessorID() == {{.*}}) { // SchedModel_A
+// CHECK-NEXT: if (this->hasFeature(TestTarget::FeatureFoo))
+// CHECK-NEXT: return {{.*}}; // SchedWriteResA
+// CHECK-NEXT: return {{.*}}; // SchedWriteResB
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index b0a309cdbfef8..9d463228be682 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -1586,6 +1586,17 @@ static void emitPredicates(const CodeGenSchedTransition &T,
continue;
}
+ if (Rec->isSubClassOf("FeatureSchedPredicate")) {
+ const Record *FR = Rec->getValueAsDef("Feature");
+ if (PE.shouldExpandForMC())
+ SS << "STI.";
+ else
+ SS << "this->";
+ SS << "hasFeature(" << PE.getTargetName() << "::" << FR->getName()
+ << ")";
+ continue;
+ }
+
// Expand this legacy predicate and wrap it around braces if there is more
// than one predicate to expand.
SS << ((NumNonTruePreds > 1) ? "(" : "")
@@ -1618,7 +1629,8 @@ static void emitSchedModelHelperEpilogue(raw_ostream &OS,
static bool hasMCSchedPredicates(const CodeGenSchedTransition &T) {
return all_of(T.PredTerm, [](const Record *Rec) {
- return Rec->isSubClassOf("MCSchedPredicate");
+ return Rec->isSubClassOf("MCSchedPredicate") ||
+ Rec->isSubClassOf("FeatureSchedPredicate");
});
}
>From d32dd3e87dfafaa715b23db8518c939253ab04f3 Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Fri, 3 Oct 2025 11:26:18 -0700
Subject: [PATCH 2/3] fixup! Add a little more comment
---
llvm/include/llvm/Target/TargetSchedule.td | 1 +
llvm/utils/TableGen/SubtargetEmitter.cpp | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/llvm/include/llvm/Target/TargetSchedule.td b/llvm/include/llvm/Target/TargetSchedule.td
index 95622b8e73e8b..d6a40598a7ea2 100644
--- a/llvm/include/llvm/Target/TargetSchedule.td
+++ b/llvm/include/llvm/Target/TargetSchedule.td
@@ -377,6 +377,7 @@ class MCSchedPredicate<MCInstPredicate P> : SchedPredicateBase {
SchedMachineModel SchedModel = ?;
}
+// A scheduling predicate whose logic depends on a SubtargetFeature.
class FeatureSchedPredicate<SubtargetFeature SF> : SchedPredicateBase {
SubtargetFeature Feature = SF;
SchedMachineModel SchedModel = ?;
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 9d463228be682..c6b2154485b2b 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -1589,8 +1589,14 @@ static void emitPredicates(const CodeGenSchedTransition &T,
if (Rec->isSubClassOf("FeatureSchedPredicate")) {
const Record *FR = Rec->getValueAsDef("Feature");
if (PE.shouldExpandForMC())
+ // MC version of this predicate will be emitted into
+ // resolveVariantSchedClassImpl, which accesses MCSubtargetInfo
+ // through argument STI.
SS << "STI.";
else
+ // Otherwise, this predicate will be emitted directly into
+ // TargetGenSubtargetInfo::resolveSchedClass, which can just access
+ // TargetSubtargetInfo / MCSubtargetInfo through `this`.
SS << "this->";
SS << "hasFeature(" << PE.getTargetName() << "::" << FR->getName()
<< ")";
>From 0260c70a6e5d4cef7992f93d9b8409d9aa5200c3 Mon Sep 17 00:00:00 2001
From: Min-Yih Hsu <min.hsu at sifive.com>
Date: Fri, 3 Oct 2025 18:28:06 -0700
Subject: [PATCH 3/3] fixup! Add braces
---
llvm/utils/TableGen/SubtargetEmitter.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index c6b2154485b2b..2f15cc8c76548 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -1588,16 +1588,17 @@ static void emitPredicates(const CodeGenSchedTransition &T,
if (Rec->isSubClassOf("FeatureSchedPredicate")) {
const Record *FR = Rec->getValueAsDef("Feature");
- if (PE.shouldExpandForMC())
+ if (PE.shouldExpandForMC()) {
// MC version of this predicate will be emitted into
// resolveVariantSchedClassImpl, which accesses MCSubtargetInfo
// through argument STI.
SS << "STI.";
- else
+ } else {
// Otherwise, this predicate will be emitted directly into
// TargetGenSubtargetInfo::resolveSchedClass, which can just access
// TargetSubtargetInfo / MCSubtargetInfo through `this`.
SS << "this->";
+ }
SS << "hasFeature(" << PE.getTargetName() << "::" << FR->getName()
<< ")";
continue;
More information about the llvm-commits
mailing list