diff --git a/llvm/include/llvm/Target/TargetMacroFusion.td b/llvm/include/llvm/Target/TargetMacroFusion.td index eafc0b08c1ed..3913a6f92015 100644 --- a/llvm/include/llvm/Target/TargetMacroFusion.td +++ b/llvm/include/llvm/Target/TargetMacroFusion.td @@ -55,11 +55,20 @@ class TieReg : 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 FirstInstHasSameReg : 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 : SecondFusionPredicate { +class SecondInstHasSameReg : SecondFusionPredicate { int FirstOpIdx = firstOpIdx; int SecondOpIdx = secondOpIdx; } @@ -129,7 +138,7 @@ class SimpleFusion, WildcardTrue, FirstFusionPredicateWithMCInstPredicate, - SameReg<0, 1>, + SecondInstHasSameReg<0, 1>, OneUse, TieReg<0, 1>, ], diff --git a/llvm/test/TableGen/MacroFusion.td b/llvm/test/TableGen/MacroFusion.td index 66cff7ec4ef4..5732c6c655d7 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", + [FirstInstHasSameReg<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 TestGenSubtargetInfo::getMacroFusions() const { // CHECK-SUBTARGET-NEXT: std::vector 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 0b77586b39d2..93bdea665d5c 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("FirstInstHasSameReg")) { + 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("SecondInstHasSameReg")) { int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx"); int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx");