[TableGen][MacroFusion] Predicate if the first inst has the same register (#137778)
We rename `SameReg` to `SecondInstHasSameReg ` and add `FirstInstHasSameReg ` 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.
This commit is contained in:
parent
c14acb7442
commit
9570bf978d
@ -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 FirstInstHasSameReg<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 SecondInstHasSameReg<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>,
|
||||
SecondInstHasSameReg<0, 1>,
|
||||
OneUse,
|
||||
TieReg<0, 1>,
|
||||
],
|
||||
|
@ -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<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;
|
||||
|
@ -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");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user