Skip to content

Commit 5ac3b37

Browse files
committed
[TableGen/GlobalISel] Emit MI_predicate custom code for PatFrags (not only PatFrag)
When GlobalISelEmitter::emitCxxPredicateFns emitted code for MI predicates it used "PatFrag" when searching for definitions. With this patch it will search for all "PatFrags" instead. Since PatFrag derives from PatFrags the difference is that we now include all definitions using PatFrags directly as well. Thus making it possible to use GISelPredicateCode together with a PatFrags definition. It might be noted that the matcher code was emitted also for PatFrags in the past. But then one ended up with errors since the custom code in testMIPredicate_MI was missing. Differential Revision: https://reviews.llvm.org/D98486
1 parent 40fdb43 commit 5ac3b37

File tree

2 files changed

+65
-12
lines changed

2 files changed

+65
-12
lines changed

llvm/test/TableGen/GlobalISelEmitterCustomPredicate.td

+64-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
// RUN: llvm-tblgen %s -gen-global-isel -optimize-match-table=false -I %p/../../include -I %p/Common -o - | FileCheck %s
22

3+
// Verify that all MI predicates are enumerated.
4+
//
5+
// CHECK: // PatFrag predicates.
6+
// CHECK-NEXT: enum {
7+
// CHECK-NEXT: GIPFP_MI_Predicate_and_or_pat = GIPFP_MI_Invalid + 1,
8+
// CHECK-NEXT: GIPFP_MI_Predicate_or_oneuse,
9+
// CHECK-NEXT: GIPFP_MI_Predicate_patfrags_test_pat,
10+
// CHECK-NEXT: GIPFP_MI_Predicate_sub3_pat,
11+
// CHECK-NEXT: };
12+
13+
// Verify that we emit cases for all MI predicates.
14+
//
15+
// CHECK: bool MyTargetInstructionSelector::testMIPredicate_MI(
16+
// CHECK: case GIPFP_MI_Predicate_and_or_pat: {
17+
// CHECK: llvm_unreachable("GISelPredicateCode should have returned");
18+
// CHECK: case GIPFP_MI_Predicate_or_oneuse: {
19+
// CHECK: llvm_unreachable("GISelPredicateCode should have returned");
20+
// CHECK: case GIPFP_MI_Predicate_patfrags_test_pat: {
21+
// CHECK: llvm_unreachable("GISelPredicateCode should have returned");
22+
// CHECK: case GIPFP_MI_Predicate_sub3_pat: {
23+
// CHECK: llvm_unreachable("GISelPredicateCode should have returned");
24+
325
include "llvm/Target/Target.td"
426
include "GlobalISelEmitterCommon.td"
527

@@ -28,7 +50,6 @@ def DRegs : MyClass<32, [i32], (sequence "D%u", 0, 0)>;
2850
def DOP : RegisterOperand<DRegs>;
2951
def AND_OR : I<(outs DRegs:$dst), (ins DOP:$src0, DOP:$src1, DOP:$src2), []>;
3052

31-
3253
def or_oneuse : PatFrag<
3354
(ops node:$x, node:$y),
3455
(or node:$x, node:$y), [{ return foo(); }]> {
@@ -48,15 +69,15 @@ def and_or_pat : PatFrag<
4869
let PredicateCodeUsesOperands = 1;
4970
}
5071

51-
// CHECK: GIM_Try, /*On fail goto*//*Label 0*/ 99, // Rule ID 2 //
72+
// CHECK: GIM_Try, /*On fail goto*//*Label 0*/ 99, // Rule ID 6 //
5273
// CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
5374
// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_AND,
5475
// CHECK-NEXT: // MIs[0] dst
5576
// CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
5677
// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/Test::DRegsRegClassID,
5778
// CHECK-NEXT: // MIs[0] src2
5879
// CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
59-
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/0, /*Op*/1, /*StoreIdx*/2, // Name : pred:2:z
80+
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/0, /*Op*/1, /*StoreIdx*/2, // Name : pred:3:z
6081
// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/Test::DRegsRegClassID,
6182
// CHECK-NEXT: // MIs[0] Operand 2
6283
// CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
@@ -67,18 +88,18 @@ def and_or_pat : PatFrag<
6788
// CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
6889
// CHECK-NEXT: // MIs[1] src0
6990
// CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
70-
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/1, /*StoreIdx*/0, // Name : pred:2:x
91+
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/1, /*StoreIdx*/0, // Name : pred:3:x
7192
// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/Test::DRegsRegClassID,
7293
// CHECK-NEXT: // MIs[1] src1
7394
// CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
74-
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/2, /*StoreIdx*/1, // Name : pred:2:y
95+
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/2, /*StoreIdx*/1, // Name : pred:3:y
7596
// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/Test::DRegsRegClassID,
7697
// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_and_or_pat,
7798
// CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
78-
// CHECK-NEXT: // (and:{ *:[i32] } DOP:{ *:[i32] }:$src2:$pred:2:z, (or:{ *:[i32] } DOP:{ *:[i32] }:$src0:$pred:2:x, DOP:{ *:[i32] }:$src1:$pred:2:y))<<P:2:Predicate_and_or_pat>> => (AND_OR:{ *:[i32] } DOP:{ *:[i32] }:$src0, DOP:{ *:[i32] }:$src1, DOP:{ *:[i32] }:$src2)
99+
// CHECK-NEXT: // (and:{ *:[i32] } DOP:{ *:[i32] }:$src2:$pred:3:z, (or:{ *:[i32] } DOP:{ *:[i32] }:$src0:$pred:3:x, DOP:{ *:[i32] }:$src1:$pred:3:y))<<P:3:Predicate_and_or_pat>> => (AND_OR:{ *:[i32] } DOP:{ *:[i32] }:$src0, DOP:{ *:[i32] }:$src1, DOP:{ *:[i32] }:$src2)
79100
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::AND_OR,
80101

81-
// CHECK: GIM_Try, /*On fail goto*//*Label 1*/ 198, // Rule ID 1 //
102+
// CHECK: GIM_Try, /*On fail goto*//*Label 1*/ 198, // Rule ID 3 //
82103
// CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
83104
// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_AND,
84105
// CHECK-NEXT: // MIs[0] dst
@@ -93,19 +114,19 @@ def and_or_pat : PatFrag<
93114
// CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
94115
// CHECK-NEXT: // MIs[1] src0
95116
// CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
96-
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/1, /*StoreIdx*/0, // Name : pred:2:x
117+
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/1, /*StoreIdx*/0, // Name : pred:3:x
97118
// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/Test::DRegsRegClassID,
98119
// CHECK-NEXT: // MIs[1] src1
99120
// CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
100-
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/2, /*StoreIdx*/1, // Name : pred:2:y
121+
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/1, /*Op*/2, /*StoreIdx*/1, // Name : pred:3:y
101122
// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/Test::DRegsRegClassID,
102123
// CHECK-NEXT: // MIs[0] src2
103124
// CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
104-
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/0, /*Op*/2, /*StoreIdx*/2, // Name : pred:2:z
125+
// CHECK-NEXT: GIM_RecordNamedOperand, /*MI*/0, /*Op*/2, /*StoreIdx*/2, // Name : pred:3:z
105126
// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/Test::DRegsRegClassID,
106127
// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIPFP_MI_Predicate_and_or_pat,
107128
// CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
108-
// CHECK-NEXT: // (and:{ *:[i32] } (or:{ *:[i32] } DOP:{ *:[i32] }:$src0:$pred:2:x, DOP:{ *:[i32] }:$src1:$pred:2:y), DOP:{ *:[i32] }:$src2:$pred:2:z)<<P:2:Predicate_and_or_pat>> => (AND_OR:{ *:[i32] } DOP:{ *:[i32] }:$src0, DOP:{ *:[i32] }:$src1, DOP:{ *:[i32] }:$src2)
129+
// CHECK-NEXT: // (and:{ *:[i32] } (or:{ *:[i32] } DOP:{ *:[i32] }:$src0:$pred:3:x, DOP:{ *:[i32] }:$src1:$pred:3:y), DOP:{ *:[i32] }:$src2:$pred:3:z)<<P:3:Predicate_and_or_pat>> => (AND_OR:{ *:[i32] } DOP:{ *:[i32] }:$src0, DOP:{ *:[i32] }:$src1, DOP:{ *:[i32] }:$src2)
109130
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::AND_OR,
110131

111132
// Test commutative, standalone pattern.
@@ -157,3 +178,35 @@ def SUB3 : I<(outs DRegs:$dst),
157178
(ins DOP:$src0, DOP:$src1, DOP:$src2),
158179
[(set DRegs:$dst, (sub3_pat i32:$src0, i32:$src1, i32:$src2))]
159180
>;
181+
182+
183+
def patfrags_test_pat : PatFrags<
184+
(ops node:$x, node:$y, node:$z),
185+
[ (xor (add node:$x, node:$y), node:$z),
186+
(xor (sub node:$x, node:$y), node:$z)
187+
], [{ return foo(); }]> {
188+
let GISelPredicateCode = [{
189+
return doesComplexCheck(MI);
190+
}];
191+
192+
let PredicateCodeUsesOperands = 1;
193+
}
194+
195+
// CHECK: GIM_Try, /*On fail goto*//*Label 3*/ 372, // Rule ID 1 //
196+
// CHECK: // (xor:{ *:[i32] } (add:{ *:[i32] } i32:{ *:[i32] }:$src0:$pred:2:x, i32:{ *:[i32] }:$src1:$pred:2:y), i32:{ *:[i32] }:$src2:$pred:2:z)<<P:2:Predicate_patfrags_test_pat>> => (PATFRAGS:{ *:[i32] } i32:{ *:[i32] }:$src0, i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2)
197+
198+
// CHECK: GIM_Try, /*On fail goto*//*Label 4*/ 459, // Rule ID 2 //
199+
// CHECK: // (xor:{ *:[i32] } (sub:{ *:[i32] } i32:{ *:[i32] }:$src0:$pred:2:x, i32:{ *:[i32] }:$src1:$pred:2:y), i32:{ *:[i32] }:$src2:$pred:2:z)<<P:2:Predicate_patfrags_test_pat>> => (PATFRAGS:{ *:[i32] } i32:{ *:[i32] }:$src0, i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2)
200+
201+
// CHECK: GIM_Try, /*On fail goto*//*Label 5*/ 546, // Rule ID 4 //
202+
// CHECK: // (xor:{ *:[i32] } i32:{ *:[i32] }:$src2:$pred:2:z, (add:{ *:[i32] } i32:{ *:[i32] }:$src0:$pred:2:x, i32:{ *:[i32] }:$src1:$pred:2:y))<<P:2:Predicate_patfrags_test_pat>> => (PATFRAGS:{ *:[i32] } i32:{ *:[i32] }:$src0, i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2)
203+
204+
// CHECK: GIM_Try, /*On fail goto*//*Label 6*/ 633, // Rule ID 5 //
205+
// CHECK: // (xor:{ *:[i32] } i32:{ *:[i32] }:$src2:$pred:2:z, (sub:{ *:[i32] } i32:{ *:[i32] }:$src0:$pred:2:x, i32:{ *:[i32] }:$src1:$pred:2:y))<<P:2:Predicate_patfrags_test_pat>> => (PATFRAGS:{ *:[i32] } i32:{ *:[i32] }:$src0, i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2)
206+
207+
208+
// Test a commutative pattern using multiple patterns using PatFrags.
209+
def PATFRAGS : I<(outs DRegs:$dst),
210+
(ins DOP:$src0, DOP:$src1, DOP:$src2),
211+
[(set DRegs:$dst, (patfrags_test_pat i32:$src0, i32:$src1, i32:$src2))]
212+
>;

llvm/utils/TableGen/GlobalISelEmitter.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -5351,7 +5351,7 @@ void GlobalISelEmitter::emitCxxPredicateFns(
53515351
StringRef AdditionalDeclarations,
53525352
std::function<bool(const Record *R)> Filter) {
53535353
std::vector<const Record *> MatchedRecords;
5354-
const auto &Defs = RK.getAllDerivedDefinitions("PatFrag");
5354+
const auto &Defs = RK.getAllDerivedDefinitions("PatFrags");
53555355
std::copy_if(Defs.begin(), Defs.end(), std::back_inserter(MatchedRecords),
53565356
[&](Record *Record) {
53575357
return !Record->getValueAsString(CodeFieldName).empty() &&

0 commit comments

Comments
 (0)