Skip to content

Commit ac50115

Browse files
committed
[MacroFusion] Support commutable instructions
If the second instruction is commutable, we should be able to check its commutable operands. A simple RISCV fusion is contained in this PR to show the functionality is correct, I may remove it when landing. Fixes llvm#82738
1 parent de1f338 commit ac50115

File tree

5 files changed

+114
-17
lines changed

5 files changed

+114
-17
lines changed

llvm/include/llvm/Target/TargetSchedule.td

+12-5
Original file line numberDiff line numberDiff line change
@@ -622,11 +622,22 @@ class BothFusionPredicateWithMCInstPredicate<MCInstPredicate pred>
622622
// Tie firstOpIdx and secondOpIdx. The operand of `FirstMI` at position
623623
// `firstOpIdx` should be the same as the operand of `SecondMI` at position
624624
// `secondOpIdx`.
625+
// If the operand at `secondOpIdx` has commutable operand, then the commutable
626+
// operand will be checked too.
625627
class TieReg<int firstOpIdx, int secondOpIdx> : BothFusionPredicate {
626628
int FirstOpIdx = firstOpIdx;
627629
int SecondOpIdx = secondOpIdx;
628630
}
629631

632+
// The operand of `SecondMI` at position `firstOpIdx` should be the same as the
633+
// operand at position `secondOpIdx`.
634+
// If the operand at `secondOpIdx` has commutable operand, then the commutable
635+
// operand will be checked too.
636+
class SameReg<int firstOpIdx, int secondOpIdx> : SecondFusionPredicate {
637+
int FirstOpIdx = firstOpIdx;
638+
int SecondOpIdx = secondOpIdx;
639+
}
640+
630641
// A predicate for wildcard. The generated code will be like:
631642
// ```
632643
// if (!FirstMI)
@@ -688,11 +699,7 @@ class SimpleFusion<string name, string fieldName, string desc,
688699
SecondFusionPredicateWithMCInstPredicate<secondPred>,
689700
WildcardTrue,
690701
FirstFusionPredicateWithMCInstPredicate<firstPred>,
691-
SecondFusionPredicateWithMCInstPredicate<
692-
CheckAny<[
693-
CheckIsVRegOperand<0>,
694-
CheckSameRegOperand<0, 1>
695-
]>>,
702+
SameReg<0, 1>,
696703
OneUse,
697704
TieReg<0, 1>,
698705
],

llvm/lib/Target/RISCV/RISCVMacroFusion.td

+21
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,24 @@ def TuneLDADDFusion
9191
CheckIsImmOperand<2>,
9292
CheckImmOperand<2, 0>
9393
]>>;
94+
95+
// These should be covered by Zba extension.
96+
// * shift left by one and add:
97+
// slli r1, r0, 1
98+
// add r1, r1, r2
99+
// * shift left by two and add:
100+
// slli r1, r0, 2
101+
// add r1, r1, r2
102+
// * shift left by three and add:
103+
// slli r1, r0, 3
104+
// add r1, r1, r2
105+
def ShiftNAddFusion
106+
: SimpleFusion<"shift-n-add-fusion", "HasShiftNAddFusion",
107+
"Enable SLLI+ADD to be fused to shift left by 1/2/3 and add",
108+
CheckAll<[
109+
CheckOpcode<[SLLI]>,
110+
CheckAny<[CheckImmOperand<2, 1>,
111+
CheckImmOperand<2, 2>,
112+
CheckImmOperand<2, 3>]>
113+
]>,
114+
CheckOpcode<[ADD]>>;

llvm/test/CodeGen/RISCV/macro-fusions.mir

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# REQUIRES: asserts
22
# RUN: llc -mtriple=riscv64-linux-gnu -x=mir < %s \
33
# RUN: -debug-only=machine-scheduler -start-before=machine-scheduler 2>&1 \
4-
# RUN: -mattr=+lui-addi-fusion,+auipc-addi-fusion,+zexth-fusion,+zextw-fusion,+shifted-zextw-fusion,+ld-add-fusion \
4+
# RUN: -mattr=+lui-addi-fusion,+auipc-addi-fusion,+zexth-fusion,+zextw-fusion,+shifted-zextw-fusion,+ld-add-fusion,+shift-n-add-fusion \
55
# RUN: | FileCheck %s
66

77
# CHECK: lui_addi:%bb.0
@@ -174,3 +174,31 @@ body: |
174174
$x11 = COPY %5
175175
PseudoRET
176176
...
177+
178+
# CHECK: shift_n_add:%bb.0
179+
# CHECK: Macro fuse: {{.*}}SLLI - ADD
180+
---
181+
name: shift_n_add
182+
tracksRegLiveness: true
183+
body: |
184+
bb.0.entry:
185+
liveins: $x10, $x11
186+
$x10 = SLLI $x10, 1
187+
$x12 = XORI $x11, 3
188+
$x10 = ADD $x10, $x11
189+
PseudoRET
190+
...
191+
192+
# CHECK: shift_n_add_commutable:%bb.0
193+
# CHECK: Macro fuse: {{.*}}SLLI - ADD
194+
---
195+
name: shift_n_add_commutable
196+
tracksRegLiveness: true
197+
body: |
198+
bb.0.entry:
199+
liveins: $x10, $x11
200+
$x10 = SLLI $x10, 1
201+
$x12 = XORI $x11, 3
202+
$x10 = ADD $x11, $x10
203+
PseudoRET
204+
...

llvm/test/TableGen/MacroFusion.td

+17-9
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,15 @@ def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion",
9999
// CHECK-PREDICATOR-NEXT: if (( MI->getOpcode() != Test::Inst0 ))
100100
// CHECK-PREDICATOR-NEXT: return false;
101101
// CHECK-PREDICATOR-NEXT: }
102-
// CHECK-PREDICATOR-NEXT: {
103-
// CHECK-PREDICATOR-NEXT: const MachineInstr *MI = &SecondMI;
104-
// CHECK-PREDICATOR-NEXT: if (!(
105-
// CHECK-PREDICATOR-NEXT: MI->getOperand(0).getReg().isVirtual()
106-
// CHECK-PREDICATOR-NEXT: || MI->getOperand(0).getReg() == MI->getOperand(1).getReg()
107-
// CHECK-PREDICATOR-NEXT: ))
108-
// CHECK-PREDICATOR-NEXT: return false;
102+
// CHECK-PREDICATOR-NEXT: if (!SecondMI.getOperand(0).getReg().isVirtual()) {
103+
// CHECK-PREDICATOR-NEXT: if (SecondMI.getOperand(0).getReg() != SecondMI.getOperand(1).getReg()) {
104+
// CHECK-PREDICATOR-NEXT: if (!SecondMI.getDesc().isCommutable())
105+
// CHECK-PREDICATOR-NEXT: return false;
106+
// CHECK-PREDICATOR-NEXT: unsigned SrcOpIdx1 = 1, SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;
107+
// CHECK-PREDICATOR-NEXT: if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2))
108+
// CHECK-PREDICATOR-NEXT: if (SecondMI.getOperand(0).getReg() != SecondMI.getOperand(SrcOpIdx2).getReg())
109+
// CHECK-PREDICATOR-NEXT: return false;
110+
// CHECK-PREDICATOR-NEXT: }
109111
// CHECK-PREDICATOR-NEXT: }
110112
// CHECK-PREDICATOR-NEXT: {
111113
// CHECK-PREDICATOR-NEXT: Register FirstDest = FirstMI->getOperand(0).getReg();
@@ -114,8 +116,14 @@ def TestFusion: SimpleFusion<"test-fusion", "HasTestFusion", "Test Fusion",
114116
// CHECK-PREDICATOR-NEXT: }
115117
// CHECK-PREDICATOR-NEXT: if (!(FirstMI->getOperand(0).isReg() &&
116118
// CHECK-PREDICATOR-NEXT: SecondMI.getOperand(1).isReg() &&
117-
// CHECK-PREDICATOR-NEXT: FirstMI->getOperand(0).getReg() == SecondMI.getOperand(1).getReg()))
118-
// CHECK-PREDICATOR-NEXT: return false;
119+
// CHECK-PREDICATOR-NEXT: FirstMI->getOperand(0).getReg() == SecondMI.getOperand(1).getReg())) {
120+
// CHECK-PREDICATOR-NEXT: if (!SecondMI.getDesc().isCommutable())
121+
// CHECK-PREDICATOR-NEXT: return false;
122+
// CHECK-PREDICATOR-NEXT: unsigned SrcOpIdx1 = 1, SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;
123+
// CHECK-PREDICATOR-NEXT: if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2))
124+
// CHECK-PREDICATOR-NEXT: if (FirstMI->getOperand(0).getReg() != SecondMI.getOperand(SrcOpIdx2).getReg())
125+
// CHECK-PREDICATOR-NEXT: return false;
126+
// CHECK-PREDICATOR-NEXT: }
119127
// CHECK-PREDICATOR-NEXT: return true;
120128
// CHECK-PREDICATOR-NEXT: }
121129
// CHECK-PREDICATOR-NEXT: } // end namespace llvm

llvm/utils/TableGen/MacroFusionPredicatorEmitter.cpp

+35-2
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,28 @@ void MacroFusionPredicatorEmitter::emitSecondPredicate(Record *Predicate,
182182
OS << ")\n";
183183
OS.indent(4) << " return false;\n";
184184
OS.indent(2) << "}\n";
185+
} else if (Predicate->isSubClassOf("SameReg")) {
186+
int FirstOpIdx = Predicate->getValueAsInt("FirstOpIdx");
187+
int SecondOpIdx = Predicate->getValueAsInt("SecondOpIdx");
188+
189+
OS.indent(2) << "if (!SecondMI.getOperand(" << FirstOpIdx
190+
<< ").getReg().isVirtual()) {\n";
191+
OS.indent(4) << "if (SecondMI.getOperand(" << FirstOpIdx
192+
<< ").getReg() != SecondMI.getOperand(" << SecondOpIdx
193+
<< ").getReg()) {\n";
194+
195+
OS.indent(6) << "if (!SecondMI.getDesc().isCommutable())\n";
196+
OS.indent(6) << " return false;\n";
197+
198+
OS.indent(6) << "unsigned SrcOpIdx1 = " << SecondOpIdx
199+
<< ", SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;\n";
200+
OS.indent(6)
201+
<< "if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2))\n";
202+
OS.indent(6) << " if (SecondMI.getOperand(" << FirstOpIdx
203+
<< ").getReg() != SecondMI.getOperand(SrcOpIdx2).getReg())\n";
204+
OS.indent(6) << " return false;\n";
205+
OS.indent(4) << "}\n";
206+
OS.indent(2) << "}\n";
185207
} else {
186208
PrintFatalError(Predicate->getLoc(),
187209
"Unsupported predicate for second instruction: " +
@@ -206,8 +228,19 @@ void MacroFusionPredicatorEmitter::emitBothPredicate(Record *Predicate,
206228
<< ").isReg() &&\n";
207229
OS.indent(2) << " FirstMI->getOperand(" << FirstOpIdx
208230
<< ").getReg() == SecondMI.getOperand(" << SecondOpIdx
209-
<< ").getReg()))\n";
210-
OS.indent(2) << " return false;\n";
231+
<< ").getReg())) {\n";
232+
233+
OS.indent(4) << "if (!SecondMI.getDesc().isCommutable())\n";
234+
OS.indent(4) << " return false;\n";
235+
236+
OS.indent(4) << "unsigned SrcOpIdx1 = " << SecondOpIdx
237+
<< ", SrcOpIdx2 = TargetInstrInfo::CommuteAnyOperandIndex;\n";
238+
OS.indent(4)
239+
<< "if (TII.findCommutedOpIndices(SecondMI, SrcOpIdx1, SrcOpIdx2))\n";
240+
OS.indent(4) << " if (FirstMI->getOperand(" << FirstOpIdx
241+
<< ").getReg() != SecondMI.getOperand(SrcOpIdx2).getReg())\n";
242+
OS.indent(4) << " return false;\n";
243+
OS.indent(2) << "}\n";
211244
} else
212245
PrintFatalError(Predicate->getLoc(),
213246
"Unsupported predicate for both instruction: " +

0 commit comments

Comments
 (0)