Skip to content

Conversation

mshockwave
Copy link
Member

Introduce a new SchedPredicate, FeatureSchedPredicate, that holds true when a certain SubtargetFeature is enabled. This could be useful when we want to configure a scheduling model with subtarget features.

I add this as a separate SchedPredicate rather than piggy-back on the existing SchedPredicate<[{....}]> because first and foremost, SchedPredicate is expected to only operate on MachineInstr, so it does not appear in MCGenSubtargetInfo::resolveVariantSchedClass but only show up in TargetGenSubtargetInfo::resolveSchedClass. Yet I think FeatureSchedPredicate will be useful for both MCInst and MachineInstr. There is another subtle difference between resolveVariantSchedClass and resolveSchedClass regarding how we access the MCSubtargetInfo instance, if we really want to express FeatureSchedPredicate using SchedPredicate<[{.....}]>.

So I thought it'll be easier to add another new SchedPredicate for SubtargetFeature.


This stacks on top of #161886

@llvmbot
Copy link
Member

llvmbot commented Oct 3, 2025

@llvm/pr-subscribers-tablegen

Author: Min-Yih Hsu (mshockwave)

Changes

Introduce a new SchedPredicate, FeatureSchedPredicate, that holds true when a certain SubtargetFeature is enabled. This could be useful when we want to configure a scheduling model with subtarget features.

I add this as a separate SchedPredicate rather than piggy-back on the existing SchedPredicate&lt;[{....}]&gt; because first and foremost, SchedPredicate is expected to only operate on MachineInstr, so it does not appear in MCGenSubtargetInfo::resolveVariantSchedClass but only show up in TargetGenSubtargetInfo::resolveSchedClass. Yet I think FeatureSchedPredicate will be useful for both MCInst and MachineInstr. There is another subtle difference between resolveVariantSchedClass and resolveSchedClass regarding how we access the MCSubtargetInfo instance, if we really want to express FeatureSchedPredicate using SchedPredicate&lt;[{.....}]&gt;.

So I thought it'll be easier to add another new SchedPredicate for SubtargetFeature.


This stacks on top of #161886


Full diff: https://github.com/llvm/llvm-project/pull/161888.diff

3 Files Affected:

  • (modified) llvm/include/llvm/Target/TargetSchedule.td (+5)
  • (added) llvm/test/TableGen/ResolveSchedClass.td (+64)
  • (modified) llvm/utils/TableGen/SubtargetEmitter.cpp (+19-5)
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
new file mode 100644
index 0000000000000..c1cadb359ca03
--- /dev/null
+++ b/llvm/test/TableGen/ResolveSchedClass.td
@@ -0,0 +1,64 @@
+// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s -o - | FileCheck %s
+
+include "llvm/Target/Target.td"
+
+def TestTargetInstrInfo : InstrInfo;
+
+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 0f42d49a6bea1..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");
   });
 }
 
@@ -1761,7 +1773,7 @@ void SubtargetEmitter::emitSchedModelHelpers(const std::string &ClassName,
      << "\n::resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI,"
      << " const MCInstrInfo *MCII, unsigned CPUID) const {\n"
      << "  return " << Target << "_MC"
-     << "::resolveVariantSchedClassImpl(SchedClass, MI, MCII, CPUID);\n"
+     << "::resolveVariantSchedClassImpl(SchedClass, MI, MCII, *this, CPUID);\n"
      << "} // " << ClassName << "::resolveVariantSchedClass\n\n";
 
   STIPredicateExpander PE(Target, /*Indent=*/0);
@@ -1923,7 +1935,8 @@ void SubtargetEmitter::parseFeaturesFunction(raw_ostream &OS) {
 void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
   OS << "namespace " << Target << "_MC {\n"
      << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,\n"
-     << "    const MCInst *MI, const MCInstrInfo *MCII, unsigned CPUID) {\n";
+     << "    const MCInst *MI, const MCInstrInfo *MCII, "
+     << "const MCSubtargetInfo &STI, unsigned CPUID) {\n";
   emitSchedModelHelpersImpl(OS, /* OnlyExpandMCPredicates */ true);
   OS << "}\n";
   OS << "} // end namespace " << Target << "_MC\n\n";
@@ -1945,7 +1958,7 @@ void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
      << "      const MCInst *MI, const MCInstrInfo *MCII,\n"
      << "      unsigned CPUID) const override {\n"
      << "    return " << Target << "_MC"
-     << "::resolveVariantSchedClassImpl(SchedClass, MI, MCII, CPUID);\n";
+     << "::resolveVariantSchedClassImpl(SchedClass, MI, MCII, *this, CPUID);\n";
   OS << "  }\n";
   if (TGT.getHwModes().getNumModeIds() > 1) {
     OS << "  unsigned getHwModeSet() const override;\n";
@@ -2073,7 +2086,8 @@ void SubtargetEmitter::run(raw_ostream &OS) {
   OS << "class DFAPacketizer;\n";
   OS << "namespace " << Target << "_MC {\n"
      << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,"
-     << " const MCInst *MI, const MCInstrInfo *MCII, unsigned CPUID);\n"
+     << " const MCInst *MI, const MCInstrInfo *MCII, "
+     << "const MCSubtargetInfo &STI, unsigned CPUID);\n"
      << "} // end namespace " << Target << "_MC\n\n";
   OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
      << "  explicit " << ClassName << "(const Triple &TT, StringRef CPU, "

@mshockwave mshockwave requested review from lenary and topperc October 3, 2025 23:17
Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -1586,6 +1586,23 @@ static void emitPredicates(const CodeGenSchedTransition &T,
continue;
}

if (Rec->isSubClassOf("FeatureSchedPredicate")) {
const Record *FR = Rec->getValueAsDef("Feature");
if (PE.shouldExpandForMC())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Braces

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@mshockwave mshockwave force-pushed the patch/sched-variant-sti-feature branch from 0b8913f to 0260c70 Compare October 4, 2025 01:28
@mshockwave mshockwave merged commit 977b546 into llvm:main Oct 4, 2025
9 checks passed
@mshockwave mshockwave deleted the patch/sched-variant-sti-feature branch October 4, 2025 03:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants