1 // RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \
2 // RUN: -combiners=MyCombiner %s | \
5 include "llvm/Target/Target.td"
6 include "llvm/Target/GlobalISel/Combine.td"
8 def MyTargetISA : InstrInfo;
9 def MyTarget : Target { let InstructionSet = MyTargetISA; }
13 def HasAnswerToEverything : Predicate<"Subtarget->getAnswerToUniverse() == 42 && Subtarget->getAnswerToLife() == 42">;
15 def WipOpcodeTest0 : GICombineRule<
17 (match (wip_match_opcode G_TRUNC):$d),
20 def WipOpcodeTest1 : GICombineRule<
22 (match (wip_match_opcode G_TRUNC, G_SEXT):$d),
25 // Note: also checks that spaces in the type name are removed.
26 def reg_matchinfo : GIDefMatchData<"Register ">;
27 def InstTest0 : GICombineRule<
28 (defs root:$d, reg_matchinfo:$r0, reg_matchinfo:$r1),
29 (match (COPY $a, $b):$d),
30 (apply [{ APPLY ${r0}, ${r1} }])>;
32 let Predicates = [HasAnswerToEverything] in
33 def InstTest1 : GICombineRule<
34 (defs root:$d, reg_matchinfo:$r0),
35 (match (COPY $a, $b):$d,
37 [{ return CHECK ${a}, ${b}, ${c}, ${d} }]),
40 def InOutInstTest0 : GICombineRule<
42 (match (G_ZEXT $tmp, $ext),
43 (G_STORE $tmp, $ptr):$root),
44 (apply (G_STORE $ext, $ptr):$root, "APPLY ${ext} ${ptr} ${root}")>;
46 // Imm operand of G_CONSTANT should match a literal int, while the second
47 // should match a constant.
48 def InOutInstTest1 : GICombineRule<
51 (G_CONSTANT $x, -42:$z),
52 (G_AND $dst, $x, (i32 43))),
53 (apply (G_TRUNC $dst, $z))>;
55 def MatchICst: GICombinePatFrag<
57 (ins gi_mo:$foo, gi_imm:$cst),
58 [(pattern "return matchIConstant(${foo}, ${cst});")]>;
60 def PatFragTest0 : GICombineRule<
62 (match (G_ZEXT $dst, $cst), (MatchICst $cst, (i32 0))),
63 (apply (COPY $dst, (i32 0)))>;
65 // TODO: add test with temp reg use
67 def MyCombiner: GICombiner<"GenMyCombiner", [
77 // We have at most 2 registers used by one rule at a time, so we should only have 2 registers MDInfos.
79 // CHECK: struct MatchInfosTy {
80 // CHECK-NEXT: Register MDInfo0, MDInfo1;
84 // CHECK: switch (PredicateID) {
85 // CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner0: {
86 // CHECK-NEXT: return CHECK State.MIs[0]->getOperand(0), State.MIs[0]->getOperand(1), State.MIs[1]->getOperand(1), State.MIs[0]
88 // CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner1: {
89 // CHECK-NEXT: return matchIConstant(State.MIs[0]->getOperand(1), 0);
92 // Verify we reset MatchData on each tryCombineAll
93 // CHECK: bool GenMyCombiner::tryCombineAll(MachineInstr &I) const {
94 // CHECK-NEXT: const TargetSubtargetInfo &ST = MF.getSubtarget();
95 // CHECK-NEXT: const PredicateBitset AvailableFeatures = getAvailableFeatures();
96 // CHECK-NEXT: B.setInstrAndDebugLoc(I);
97 // CHECK-NEXT: State.MIs.clear();
98 // CHECK-NEXT: State.MIs.push_back(&I);
99 // CHECK-NEXT: MatchInfos = MatchInfosTy();
101 // CHECK-NEXT: if (executeMatchTable(*this, State, ExecInfo, B, getMatchTable(), *ST.getInstrInfo(), MRI, *MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures, /*CoverageInfo*/ nullptr))
102 // CHECK-NEXT: return true;
105 // CHECK-NEXT: return false;
110 // CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner0 = GICXXCustomAction_Invalid + 1,
111 // CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner1,
112 // CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner2,
114 // CHECK-NEXT: void GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const {
115 // CHECK-NEXT: switch(ApplyID) {
116 // CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner0:{
118 // CHECK-NEXT: return;
120 // CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner1:{
121 // CHECK-NEXT: APPLY MatchInfos.MDInfo0, MatchInfos.MDInfo1
122 // CHECK-NEXT: return;
124 // CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner2:{
125 // CHECK-NEXT: APPLY State.MIs[1]->getOperand(1) State.MIs[0]->getOperand(1) OutMIs[0]
126 // CHECK-NEXT: return;
129 // CHECK-NEXT: llvm_unreachable("Unknown Apply Action");
132 // Verify match table.
133 // CHECK: const int64_t *GenMyCombiner::getMatchTable() const {
134 // CHECK-NEXT: constexpr static int64_t MatchTable0[] = {
135 // CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/19, 126, /*)*//*default:*//*Label 6*/ 267,
136 // CHECK-NEXT: /*TargetOpcode::COPY*//*Label 0*/ 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
137 // CHECK-NEXT: /*TargetOpcode::G_AND*//*Label 1*/ 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
138 // CHECK-NEXT: /*TargetOpcode::G_STORE*//*Label 2*/ 181, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139 // CHECK-NEXT: /*TargetOpcode::G_TRUNC*//*Label 3*/ 216, 0, 0, 0, 0,
140 // CHECK-NEXT: /*TargetOpcode::G_SEXT*//*Label 4*/ 231, 0,
141 // CHECK-NEXT: /*TargetOpcode::G_ZEXT*//*Label 5*/ 239,
142 // CHECK-NEXT: // Label 0: @112
143 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ 133, // Rule ID 4 //
144 // CHECK-NEXT: GIM_CheckFeatures, GIFBS_HasAnswerToEverything,
145 // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule3Enabled,
146 // CHECK-NEXT: // MIs[0] a
147 // CHECK-NEXT: // No operand predicates
148 // CHECK-NEXT: // MIs[0] b
149 // CHECK-NEXT: GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
150 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_ZEXT,
151 // CHECK-NEXT: // MIs[1] c
152 // CHECK-NEXT: // No operand predicates
153 // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_GICombiner0,
154 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
155 // CHECK-NEXT: // Combiner Rule #3: InstTest1
156 // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0,
157 // CHECK-NEXT: GIR_Done,
158 // CHECK-NEXT: // Label 7: @133
159 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ 140, // Rule ID 3 //
160 // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule2Enabled,
161 // CHECK-NEXT: // MIs[0] a
162 // CHECK-NEXT: // No operand predicates
163 // CHECK-NEXT: // MIs[0] b
164 // CHECK-NEXT: // No operand predicates
165 // CHECK-NEXT: // Combiner Rule #2: InstTest0
166 // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner1,
167 // CHECK-NEXT: GIR_Done,
168 // CHECK-NEXT: // Label 8: @140
169 // CHECK-NEXT: GIM_Reject,
170 // CHECK-NEXT: // Label 1: @141
171 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ 180, // Rule ID 6 //
172 // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule5Enabled,
173 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
174 // CHECK-NEXT: // MIs[0] dst
175 // CHECK-NEXT: // No operand predicates
176 // CHECK-NEXT: // MIs[0] x
177 // CHECK-NEXT: GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
178 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_CONSTANT,
179 // CHECK-NEXT: // MIs[1] z
180 // CHECK-NEXT: GIM_CheckLiteralInt, /*MI*/1, /*Op*/1, -42,
181 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, 43,
182 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
183 // CHECK-NEXT: // Combiner Rule #5: InOutInstTest1
184 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::G_TRUNC,
185 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
186 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // z
187 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
188 // CHECK-NEXT: GIR_Done,
189 // CHECK-NEXT: // Label 9: @180
190 // CHECK-NEXT: GIM_Reject,
191 // CHECK-NEXT: // Label 2: @181
192 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 10*/ 215, // Rule ID 5 //
193 // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule4Enabled,
194 // CHECK-NEXT: // MIs[0] tmp
195 // CHECK-NEXT: GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/0, // MIs[1]
196 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_ZEXT,
197 // CHECK-NEXT: // MIs[1] ext
198 // CHECK-NEXT: // No operand predicates
199 // CHECK-NEXT: // MIs[0] ptr
200 // CHECK-NEXT: // No operand predicates
201 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
202 // CHECK-NEXT: // Combiner Rule #4: InOutInstTest0
203 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::G_STORE,
204 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // ext
205 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // ptr
206 // CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*MergeInsnID's*/0, 1, GIU_MergeMemOperands_EndOfList,
207 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
208 // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner2,
209 // CHECK-NEXT: GIR_Done,
210 // CHECK-NEXT: // Label 10: @215
211 // CHECK-NEXT: GIM_Reject,
212 // CHECK-NEXT: // Label 3: @216
213 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 11*/ 223, // Rule ID 0 //
214 // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule0Enabled,
215 // CHECK-NEXT: // Combiner Rule #0: WipOpcodeTest0; wip_match_opcode 'G_TRUNC'
216 // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0,
217 // CHECK-NEXT: GIR_Done,
218 // CHECK-NEXT: // Label 11: @223
219 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 12*/ 230, // Rule ID 1 //
220 // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule1Enabled,
221 // CHECK-NEXT: // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_TRUNC'
222 // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0,
223 // CHECK-NEXT: GIR_Done,
224 // CHECK-NEXT: // Label 12: @230
225 // CHECK-NEXT: GIM_Reject,
226 // CHECK-NEXT: // Label 4: @231
227 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 13*/ 238, // Rule ID 2 //
228 // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule1Enabled,
229 // CHECK-NEXT: // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_SEXT'
230 // CHECK-NEXT: GIR_CustomAction, GICXXCustomAction_CombineApplyGICombiner0,
231 // CHECK-NEXT: GIR_Done,
232 // CHECK-NEXT: // Label 13: @238
233 // CHECK-NEXT: GIM_Reject,
234 // CHECK-NEXT: // Label 5: @239
235 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 14*/ 266, // Rule ID 7 //
236 // CHECK-NEXT: GIM_CheckSimplePredicate, GICXXPred_Simple_IsRule6Enabled,
237 // CHECK-NEXT: // MIs[0] dst
238 // CHECK-NEXT: // No operand predicates
239 // CHECK-NEXT: // MIs[0] cst
240 // CHECK-NEXT: // No operand predicates
241 // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GICXXPred_MI_Predicate_GICombiner1,
242 // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32,
243 // CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/0,
244 // CHECK-NEXT: // Combiner Rule #6: PatFragTest0 @ [__PatFragTest0_match_1[0]]
245 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::COPY,
246 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
247 // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0,
248 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
249 // CHECK-NEXT: GIR_Done,
250 // CHECK-NEXT: // Label 14: @266
251 // CHECK-NEXT: GIM_Reject,
252 // CHECK-NEXT: // Label 6: @267
253 // CHECK-NEXT: GIM_Reject,
255 // CHECK-NEXT: return MatchTable0;