[llvm] [TableGen][MacroFusion] Predicate if the first inst has the same register (PR #137778)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 29 03:00:00 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-tablegen
Author: Pengcheng Wang (wangpc-pp)
<details>
<summary>Changes</summary>
We rename `SameReg` to `SecondSameReg` and add `FirstSameReg` which
has the logic but applies to the first instruction.
We have some cases that require the first instruction has the same
input/output register.
---
Full diff: https://github.com/llvm/llvm-project/pull/137778.diff
3 Files Affected:
- (modified) llvm/include/llvm/Target/TargetMacroFusion.td (+11-2)
- (modified) llvm/test/TableGen/MacroFusion.td (+30-3)
- (modified) llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp (+31-1)
``````````diff
diff --git a/llvm/include/llvm/Target/TargetMacroFusion.td b/llvm/include/llvm/Target/TargetMacroFusion.td
index eafc0b08c1edf..16f30462f69f4 100644
--- a/llvm/include/llvm/Target/TargetMacroFusion.td
+++ b/llvm/include/llvm/Target/TargetMacroFusion.td
@@ -55,11 +55,20 @@ class TieReg<int firstOpIdx, int secondOpIdx> : BothFusionPredicate {
int SecondOpIdx = secondOpIdx;
}
+// The operand of `FirstMI` at position `firstOpIdx` should be the same as the
+// operand at position `secondOpIdx`.
+// If the fusion has `IsCommutable` being true and the operand at `secondOpIdx`
+// has commutable operand, then the commutable operand will be checked too.
+class FirstSameReg<int firstOpIdx, int secondOpIdx> : FirstFusionPredicate {
+ int FirstOpIdx = firstOpIdx;
+ int SecondOpIdx = secondOpIdx;
+}
+
// The operand of `SecondMI` at position `firstOpIdx` should be the same as the
// operand at position `secondOpIdx`.
// If the fusion has `IsCommutable` being true and the operand at `secondOpIdx`
// has commutable operand, then the commutable operand will be checked too.
-class SameReg<int firstOpIdx, int secondOpIdx> : SecondFusionPredicate {
+class SecondSameReg<int firstOpIdx, int secondOpIdx> : SecondFusionPredicate {
int FirstOpIdx = firstOpIdx;
int SecondOpIdx = secondOpIdx;
}
@@ -129,7 +138,7 @@ class SimpleFusion<string name, string fieldName, string desc,
SecondFusionPredicateWithMCInstPredicate<secondPred>,
WildcardTrue,
FirstFusionPredicateWithMCInstPredicate<firstPred>,
- SameReg<0, 1>,
+ SecondSameReg<0, 1>,
OneUse,
TieReg<0, 1>,
],
diff --git a/llvm/test/TableGen/MacroFusion.td b/llvm/test/TableGen/MacroFusion.td
index 66cff7ec4ef4c..06677b6b23b92 100644
--- a/llvm/test/TableGen/MacroFusion.td
+++ b/llvm/test/TableGen/MacroFusion.td
@@ -62,12 +62,19 @@ def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion",
Inst0, Inst2,
secondInstPred=CheckRegOperand<0, X0>>;
+def TestFirstSameRegFusion: Fusion<"test-first-same-reg-fusion", "HasTestFirstSameRegFusion",
+ "Test FirstSameReg",
+ [FirstSameReg<0, 1>]> {
+ bit IsCommutable = 1;
+}
+
// CHECK-PREDICATOR: #ifdef GET_Test_MACRO_FUSION_PRED_DECL
// CHECK-PREDICATOR-NEXT: #undef GET_Test_MACRO_FUSION_PRED_DECL
// CHECK-PREDICATOR-EMPTY:
// CHECK-PREDICATOR-NEXT: namespace llvm {
// CHECK-PREDICATOR-NEXT: bool isTestBothFusionPredicate(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
-// CHECK-PREDICATOR-NEXT: bool isTestCommutableFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
+// CHECK-PREDICATOR-NEXT: bool isTestCommutableFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
+// CHECK-PREDICATOR-NEXT: bool isTestFirstSameRegFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
// CHECK-PREDICATOR-NEXT: bool isTestFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
// CHECK-PREDICATOR-NEXT: bool isTestSingleFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
// CHECK-PREDICATOR-NEXT: } // end namespace llvm
@@ -144,6 +151,24 @@ def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion",
// CHECK-PREDICATOR-NEXT: }
// CHECK-PREDICATOR-NEXT: return true;
// CHECK-PREDICATOR-NEXT: }
+// CHECK-PREDICATOR-NEXT: bool isTestFirstSameRegFusion(
+// CHECK-PREDICATOR-NEXT: const TargetInstrInfo &TII,
+// CHECK-PREDICATOR-NEXT: const TargetSubtargetInfo &STI,
+// CHECK-PREDICATOR-NEXT: const MachineInstr *FirstMI,
+// CHECK-PREDICATOR-NEXT: const MachineInstr &SecondMI) {
+// CHECK-PREDICATOR-NEXT: {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} auto &MRI = SecondMI.getMF()->getRegInfo();
+// CHECK-PREDICATOR-NEXT: if (!FirstMI->getOperand(0).getReg().isVirtual()) {
+// CHECK-PREDICATOR-NEXT: if (FirstMI->getOperand(0).getReg() != FirstMI->getOperand(1).getReg()) {
+// CHECK-PREDICATOR-NEXT: if (!FirstMI->getDesc().isCommutable())
+// CHECK-PREDICATOR-NEXT: return false;
+// CHECK-PREDICATOR-NEXT: unsigned SrcOpIdx1 = 1, SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;
+// CHECK-PREDICATOR-NEXT: if (TII.findCommutedOpIndices(FirstMI, SrcOpIdx1, SrcOpIdx2))
+// CHECK-PREDICATOR-NEXT: if (FirstMI->getOperand(0).getReg() != FirstMI->getOperand(SrcOpIdx2).getReg())
+// CHECK-PREDICATOR-NEXT: return false;
+// CHECK-PREDICATOR-NEXT: }
+// CHECK-PREDICATOR-NEXT: }
+// CHECK-PREDICATOR-NEXT: return true;
+// CHECK-PREDICATOR-NEXT: }
// CHECK-PREDICATOR-NEXT: bool isTestFusion(
// CHECK-PREDICATOR-NEXT: const TargetInstrInfo &TII,
// CHECK-PREDICATOR-NEXT: const TargetSubtargetInfo &STI,
@@ -238,6 +263,7 @@ def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion",
// Check that we have generated target subfeature.
// CHECK-SUBTARGET: { "test-both-fusion-predicate", "Test BothFusionPredicate", Test::TestBothFusionPredicate
// CHECK-SUBTARGET: { "test-commutable-fusion", "Test Commutable Fusion", Test::TestCommutableFusion
+// CHECK-SUBTARGET: { "test-first-same-reg-fusion", "Test FirstSameReg", Test::TestFirstSameRegFusion
// CHECK-SUBTARGET: { "test-fusion", "Test Fusion", Test::TestFusion
// CHECK-SUBTARGET: { "test-single-fusion", "Test SingleFusion", Test::TestSingleFusion
@@ -246,8 +272,9 @@ def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion",
// CHECK-SUBTARGET: std::vector<MacroFusionPredTy> TestGenSubtargetInfo::getMacroFusions() const {
// CHECK-SUBTARGET-NEXT: std::vector<MacroFusionPredTy> Fusions;
-// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestBothFusionPredicate)) Fusions.push_back(llvm::isTestBothFusionPredicate);
-// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestCommutableFusion)) Fusions.push_back(llvm::isTestCommutableFusion);
+// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestBothFusionPredicate)) Fusions.push_back(llvm::isTestBothFusionPredicate);
+// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestCommutableFusion)) Fusions.push_back(llvm::isTestCommutableFusion);
+// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestFirstSameRegFusion)) Fusions.push_back(llvm::isTestFirstSameRegFusion);
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestFusion)) Fusions.push_back(llvm::isTestFusion);
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestSingleFusion)) Fusions.push_back(llvm::isTestSingleFusion);
// CHECK-SUBTARGET-NEXT: return Fusions;
diff --git a/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp b/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp
index ce509c7ef1aba..f8568f4cbd137 100644
--- a/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp
+++ b/llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp
@@ -155,6 +155,36 @@ void MacroFusionPredicatorEmitter::emitFirstPredicate(const Record *Predicate,
<< "if (FirstDest.isVirtual() && !MRI.hasOneNonDBGUse(FirstDest))\n";
OS.indent(4) << " return false;\n";
OS.indent(2) << "}\n";
+ } else if (Predicate->isSubClassOf("FirstSameReg")) {
+ int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx");
+ int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx");
+
+ OS.indent(2) << "if (!FirstMI->getOperand(" << FirstOpIdx
+ << ").getReg().isVirtual()) {\n";
+ OS.indent(4) << "if (FirstMI->getOperand(" << FirstOpIdx
+ << ").getReg() != FirstMI->getOperand(" << SecondOpIdx
+ << ").getReg())";
+
+ if (IsCommutable) {
+ OS << " {\n";
+ OS.indent(6) << "if (!FirstMI->getDesc().isCommutable())\n";
+ OS.indent(6) << " return false;\n";
+
+ OS.indent(6)
+ << "unsigned SrcOpIdx1 = " << SecondOpIdx
+ << ", SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;\n";
+ OS.indent(6)
+ << "if (TII.findCommutedOpIndices(FirstMI, SrcOpIdx1, SrcOpIdx2))\n";
+ OS.indent(6)
+ << " if (FirstMI->getOperand(" << FirstOpIdx
+ << ").getReg() != FirstMI->getOperand(SrcOpIdx2).getReg())\n";
+ OS.indent(6) << " return false;\n";
+ OS.indent(4) << "}\n";
+ } else {
+ OS << "\n";
+ OS.indent(4) << " return false;\n";
+ }
+ OS.indent(2) << "}\n";
} else if (Predicate->isSubClassOf("FusionPredicateWithMCInstPredicate")) {
OS.indent(2) << "{\n";
OS.indent(4) << "const MachineInstr *MI = FirstMI;\n";
@@ -186,7 +216,7 @@ void MacroFusionPredicatorEmitter::emitSecondPredicate(const Record *Predicate,
OS << ")\n";
OS.indent(4) << " return false;\n";
OS.indent(2) << "}\n";
- } else if (Predicate->isSubClassOf("SameReg")) {
+ } else if (Predicate->isSubClassOf("SecondSameReg")) {
int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx");
int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx");
``````````
</details>
https://github.com/llvm/llvm-project/pull/137778
More information about the llvm-commits
mailing list