Skip to content

Commit 6c48eb4

Browse files
committed
[TableGen] Emit llvm::is_contained when CheckOpcode accepts a large list
When the list is large, using `llvm::is_contained` is of higher performance than a sequence of comparisons. And the generated code is more readable.
1 parent 9b2fd1a commit 6c48eb4

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

llvm/test/TableGen/MacroFusion.td

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ def Inst0 : TestInst<0>;
3535
def Inst1 : TestInst<1>;
3636
let isCommutable = true in
3737
def Inst2 : TestInst<2>;
38+
def Inst3 : TestInst<3>;
39+
def Inst4 : TestInst<4>;
40+
def Inst5 : TestInst<5>;
41+
def Inst6 : TestInst<6>;
42+
def Inst7 : TestInst<7>;
3843

3944
def BothFusionPredicate: BothFusionPredicateWithMCInstPredicate<CheckRegOperand<0, X0>>;
4045
def TestBothFusionPredicate: Fusion<"test-both-fusion-predicate", "HasBothFusionPredicate",
@@ -62,13 +67,19 @@ def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion",
6267
Inst0, Inst2,
6368
secondInstPred=CheckRegOperand<0, X0>>;
6469

70+
def TestLargeCheckOpcodeFusion: SimpleFusion<"test-large-check-opcode-fusion", "TestLargeCheckOpcodeFusion",
71+
"Test Large CheckOpcode Fusion",
72+
CheckOpcode<[Inst0, Inst1, Inst2, Inst3, Inst4, Inst5, Inst6]>,
73+
CheckOpcode<[Inst0, Inst1, Inst2, Inst3, Inst4, Inst5, Inst6, Inst7]>>;
74+
6575
// CHECK-PREDICATOR: #ifdef GET_Test_MACRO_FUSION_PRED_DECL
6676
// CHECK-PREDICATOR-NEXT: #undef GET_Test_MACRO_FUSION_PRED_DECL
6777
// CHECK-PREDICATOR-EMPTY:
6878
// CHECK-PREDICATOR-NEXT: namespace llvm {
6979
// CHECK-PREDICATOR-NEXT: bool isTestBothFusionPredicate(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
7080
// CHECK-PREDICATOR-NEXT: bool isTestCommutableFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
7181
// CHECK-PREDICATOR-NEXT: bool isTestFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
82+
// CHECK-PREDICATOR-NEXT: bool isTestLargeCheckOpcodeFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
7283
// CHECK-PREDICATOR-NEXT: bool isTestSingleFusion(const TargetInstrInfo &, const TargetSubtargetInfo &, const MachineInstr *, const MachineInstr &);
7384
// CHECK-PREDICATOR-NEXT: } // end namespace llvm
7485
// CHECK-PREDICATOR-EMPTY:
@@ -180,6 +191,47 @@ def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion",
180191
// CHECK-PREDICATOR-NEXT: return false;
181192
// CHECK-PREDICATOR-NEXT: return true;
182193
// CHECK-PREDICATOR-NEXT: }
194+
// CHECK-PREDICATOR-NEXT: bool isTestLargeCheckOpcodeFusion(
195+
// CHECK-PREDICATOR-NEXT: const TargetInstrInfo &TII,
196+
// CHECK-PREDICATOR-NEXT: const TargetSubtargetInfo &STI,
197+
// CHECK-PREDICATOR-NEXT: const MachineInstr *FirstMI,
198+
// CHECK-PREDICATOR-NEXT: const MachineInstr &SecondMI) {
199+
// CHECK-PREDICATOR-NEXT: {{[[]}}{{[[]}}maybe_unused{{[]]}}{{[]]}} auto &MRI = SecondMI.getMF()->getRegInfo();
200+
// CHECK-PREDICATOR-NEXT: {
201+
// CHECK-PREDICATOR-NEXT: const MachineInstr *MI = &SecondMI;
202+
// CHECK-PREDICATOR-NEXT: if (!llvm::is_contained({Test::Inst0, Test::Inst1, Test::Inst2, Test::Inst3, Test::Inst4, Test::Inst5, Test::Inst6, Test::Inst7}, MI->getOpcode()))
203+
// CHECK-PREDICATOR-NEXT: return false;
204+
// CHECK-PREDICATOR-NEXT: }
205+
// CHECK-PREDICATOR-NEXT: if (!FirstMI)
206+
// CHECK-PREDICATOR-NEXT: return true;
207+
// CHECK-PREDICATOR-NEXT: {
208+
// CHECK-PREDICATOR-NEXT: const MachineInstr *MI = FirstMI;
209+
// CHECK-PREDICATOR-NEXT: if ((
210+
// CHECK-PREDICATOR-NEXT: MI->getOpcode() != Test::Inst0
211+
// CHECK-PREDICATOR-NEXT: && MI->getOpcode() != Test::Inst1
212+
// CHECK-PREDICATOR-NEXT: && MI->getOpcode() != Test::Inst2
213+
// CHECK-PREDICATOR-NEXT: && MI->getOpcode() != Test::Inst3
214+
// CHECK-PREDICATOR-NEXT: && MI->getOpcode() != Test::Inst4
215+
// CHECK-PREDICATOR-NEXT: && MI->getOpcode() != Test::Inst5
216+
// CHECK-PREDICATOR-NEXT: && MI->getOpcode() != Test::Inst6
217+
// CHECK-PREDICATOR-NEXT: ))
218+
// CHECK-PREDICATOR-NEXT: return false;
219+
// CHECK-PREDICATOR-NEXT: }
220+
// CHECK-PREDICATOR-NEXT: if (!SecondMI.getOperand(0).getReg().isVirtual()) {
221+
// CHECK-PREDICATOR-NEXT: if (SecondMI.getOperand(0).getReg() != SecondMI.getOperand(1).getReg())
222+
// CHECK-PREDICATOR-NEXT: return false;
223+
// CHECK-PREDICATOR-NEXT: }
224+
// CHECK-PREDICATOR-NEXT: {
225+
// CHECK-PREDICATOR-NEXT: Register FirstDest = FirstMI->getOperand(0).getReg();
226+
// CHECK-PREDICATOR-NEXT: if (FirstDest.isVirtual() && !MRI.hasOneNonDBGUse(FirstDest))
227+
// CHECK-PREDICATOR-NEXT: return false;
228+
// CHECK-PREDICATOR-NEXT: }
229+
// CHECK-PREDICATOR-NEXT: if (!(FirstMI->getOperand(0).isReg() &&
230+
// CHECK-PREDICATOR-NEXT: SecondMI.getOperand(1).isReg() &&
231+
// CHECK-PREDICATOR-NEXT: FirstMI->getOperand(0).getReg() == SecondMI.getOperand(1).getReg()))
232+
// CHECK-PREDICATOR-NEXT: return false;
233+
// CHECK-PREDICATOR-NEXT: return true;
234+
// CHECK-PREDICATOR-NEXT: }
183235
// CHECK-PREDICATOR-NEXT: bool isTestSingleFusion(
184236
// CHECK-PREDICATOR-NEXT: const TargetInstrInfo &TII,
185237
// CHECK-PREDICATOR-NEXT: const TargetSubtargetInfo &STI,
@@ -239,6 +291,7 @@ def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion",
239291
// CHECK-SUBTARGET: { "test-both-fusion-predicate", "Test BothFusionPredicate", Test::TestBothFusionPredicate
240292
// CHECK-SUBTARGET: { "test-commutable-fusion", "Test Commutable Fusion", Test::TestCommutableFusion
241293
// CHECK-SUBTARGET: { "test-fusion", "Test Fusion", Test::TestFusion
294+
// CHECK-SUBTARGET: { "test-large-check-opcode-fusion", "Test Large CheckOpcode Fusion", Test::TestLargeCheckOpcodeFusion
242295
// CHECK-SUBTARGET: { "test-single-fusion", "Test SingleFusion", Test::TestSingleFusion
243296

244297
// Check that we have generated `getMacroFusions()` function.
@@ -249,6 +302,7 @@ def TestSingleFusion: SingleFusion<"test-single-fusion", "HasTestSingleFusion",
249302
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestBothFusionPredicate)) Fusions.push_back(llvm::isTestBothFusionPredicate);
250303
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestCommutableFusion)) Fusions.push_back(llvm::isTestCommutableFusion);
251304
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestFusion)) Fusions.push_back(llvm::isTestFusion);
305+
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestLargeCheckOpcodeFusion)) Fusions.push_back(llvm::isTestLargeCheckOpcodeFusion);
252306
// CHECK-SUBTARGET-NEXT: if (hasFeature(Test::TestSingleFusion)) Fusions.push_back(llvm::isTestSingleFusion);
253307
// CHECK-SUBTARGET-NEXT: return Fusions;
254308
// CHECK-SUBTARGET-NEXT: }

llvm/utils/TableGen/Common/PredicateExpander.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,18 @@ void PredicateExpander::expandCheckOpcode(raw_ostream &OS,
152152
return;
153153
}
154154

155+
if (Opcodes.size() >= 8) {
156+
OS << (shouldNegate() ? "!" : "") << "llvm::is_contained(";
157+
ListSeparator Sep;
158+
OS << "{";
159+
for (const Record *Inst : Opcodes)
160+
OS << Sep << Inst->getValueAsString("Namespace")
161+
<< "::" << Inst->getName();
162+
OS << "}";
163+
OS << ", MI" << (isByRef() ? "." : "->") << "getOpcode())";
164+
return;
165+
}
166+
155167
OS << '(';
156168
++Indent;
157169
for (const Record *Rec : Opcodes) {

0 commit comments

Comments
 (0)