llvm.org GIT mirror llvm / 6241099
Reapply r332907 "[GlobalISel] Improving InstructionSelect's performance by reducing MatchTable..." Apparently the compile time problem was caused by the fact that not all compilers / STL implementations can automatically convert std::unique_ptr<Derived> to std::unique_ptr<Base>. Fixed (hopefully) by making sure it's std::unique_ptr<Derived>&& (rvalue ref) to std::unique_ptr<Base> conversion instead. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332917 91177308-0d34-0410-b5e6-96231b3b80d8 Roman Tereshin 1 year, 4 months ago
4 changed file(s) with 1267 addition(s) and 1065 deletion(s). Raw diff Collapse all Expand all
1919 #include "llvm/ADT/Optional.h"
2020 #include "llvm/ADT/SmallVector.h"
2121 #include "llvm/Support/CodeGenCoverage.h"
22 #include "llvm/Support/LowLevelTypeImpl.h"
2223 #include
2324 #include
2425 #include
3031
3132 class APInt;
3233 class APFloat;
33 class LLT;
3434 class MachineInstr;
3535 class MachineInstrBuilder;
3636 class MachineFunction;
145145 /// - OpIdx - Operand index
146146 /// - Expected register bank (specified as a register class)
147147 GIM_CheckRegBankForClass,
148
148149 /// Check the operand matches a complex predicate
149150 /// - InsnID - Instruction ID
150151 /// - OpIdx - Operand index
151152 /// - RendererID - The renderer to hold the result
152153 /// - Complex predicate ID
153154 GIM_CheckComplexPattern,
155
154156 /// Check the operand is a specific integer
155157 /// - InsnID - Instruction ID
156158 /// - OpIdx - Operand index
167169 /// - OpIdx - Operand index
168170 /// - Expected Intrinsic ID
169171 GIM_CheckIntrinsicID,
172
170173 /// Check the specified operand is an MBB
171174 /// - InsnID - Instruction ID
172175 /// - OpIdx - Operand index
195198 /// - OldInsnID - Instruction ID to mutate
196199 /// - NewOpcode - The new opcode to use
197200 GIR_MutateOpcode,
201
198202 /// Build a new instruction
199203 /// - InsnID - Instruction ID to define
200204 /// - Opcode - The new opcode to use
205209 /// - OldInsnID - Instruction ID to copy from
206210 /// - OpIdx - The operand to copy
207211 GIR_Copy,
212
208213 /// Copy an operand to the specified instruction or add a zero register if the
209214 /// operand is a zero immediate.
210215 /// - NewInsnID - Instruction ID to modify
218223 /// - OpIdx - The operand to copy
219224 /// - SubRegIdx - The subregister to copy
220225 GIR_CopySubReg,
226
221227 /// Add an implicit register def to the specified instruction
222228 /// - InsnID - Instruction ID to modify
223229 /// - RegNum - The register to add
230236 /// - InsnID - Instruction ID to modify
231237 /// - RegNum - The register to add
232238 GIR_AddRegister,
239
233240 /// Add a temporary register to the specified instruction
234241 /// - InsnID - Instruction ID to modify
235242 /// - TempRegID - The temporary register ID to add
236243 /// - TempRegFlags - The register flags to set
237244 GIR_AddTempRegister,
245
238246 /// Add an immediate to the specified instruction
239247 /// - InsnID - Instruction ID to modify
240248 /// - Imm - The immediate to add
243251 /// - InsnID - Instruction ID to modify
244252 /// - RendererID - The renderer to call
245253 GIR_ComplexRenderer,
254
246255 /// Render sub-operands of complex operands to the specified instruction
247256 /// - InsnID - Instruction ID to modify
248257 /// - RendererID - The renderer to call
271280 /// - OpIdx - Operand index
272281 /// - RCEnum - Register class enumeration value
273282 GIR_ConstrainOperandRC,
283
274284 /// Constrain an instructions operands according to the instruction
275285 /// description.
276286 /// - InsnID - Instruction ID to modify
277287 GIR_ConstrainSelectedInstOperands,
288
278289 /// Merge all memory operands into instruction.
279290 /// - InsnID - Instruction ID to modify
280291 /// - MergeInsnID... - One or more Instruction ID to merge into the result.
281292 /// - GIU_MergeMemOperands_EndOfList - Terminates the list of instructions to
282293 /// merge.
283294 GIR_MergeMemOperands,
295
284296 /// Erase from parent.
285297 /// - InsnID - Instruction ID to erase
286298 GIR_EraseFromParent,
299
287300 /// Create a new temporary register that's not constrained.
288301 /// - TempRegID - The temporary register ID to initialize.
289302 /// - Expected type
296309 /// - RuleID - The ID of the rule that was covered.
297310 GIR_Coverage,
298311
312 /// Keeping track of the number of the GI opcodes. Must be the last entry.
299313 GIU_NumOpcodes,
300314 };
301315
340354 template
341355 class CustomRendererFn>
342356 struct ISelInfoTy {
357 ISelInfoTy(const LLT *TypeObjects, size_t NumTypeObjects,
358 const PredicateBitset *FeatureBitsets,
359 const ComplexMatcherMemFn *ComplexPredicates,
360 const CustomRendererFn *CustomRenderers)
361 : TypeObjects(TypeObjects),
362 FeatureBitsets(FeatureBitsets),
363 ComplexPredicates(ComplexPredicates),
364 CustomRenderers(CustomRenderers) {
365 }
343366 const LLT *TypeObjects;
344367 const PredicateBitset *FeatureBitsets;
345368 const ComplexMatcherMemFn *ComplexPredicates;
5252 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
5353 const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures,
5454 CodeGenCoverage &CoverageInfo) const {
55
5556 uint64_t CurrentIdx = 0;
56 SmallVector8> OnFailResumeAt;
57 SmallVector4> OnFailResumeAt;
5758
5859 enum RejectAction { RejectAndGiveUp, RejectAndResume };
5960 auto handleReject = [&]() -> RejectAction {
6162 dbgs() << CurrentIdx << ": Rejected\n");
6263 if (OnFailResumeAt.empty())
6364 return RejectAndGiveUp;
64 CurrentIdx = OnFailResumeAt.back();
65 OnFailResumeAt.pop_back();
65 CurrentIdx = OnFailResumeAt.pop_back_val();
6666 DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
6767 dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " ("
6868 << OnFailResumeAt.size() << " try-blocks remain)\n");
138138 int64_t InsnID = MatchTable[CurrentIdx++];
139139 int64_t Expected = MatchTable[CurrentIdx++];
140140
141 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
141142 unsigned Opcode = State.MIs[InsnID]->getOpcode();
143
142144 DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
143145 dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID
144146 << "], ExpectedOpcode=" << Expected
145147 << ") // Got=" << Opcode << "\n");
146 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
147148 if (Opcode != Expected) {
148149 if (handleReject() == RejectAndGiveUp)
149150 return false;
196197 << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs["
197198 << InsnID << "], Predicate=" << Predicate << ")\n");
198199 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
199 assert(State.MIs[InsnID]->getOpcode() && "Expected G_CONSTANT");
200 assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
201 "Expected G_CONSTANT");
200202 assert(Predicate > GIPFP_APInt_Invalid && "Expected a valid predicate");
201203 APInt Value;
202204 if (State.MIs[InsnID]->getOperand(1).isCImm())
235237 dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs["
236238 << InsnID << "], " << (uint64_t)Ordering << ")\n");
237239 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
238
239240 if (!State.MIs[InsnID]->hasOneMemOperand())
240241 if (handleReject() == RejectAndGiveUp)
241242 return false;
254255 << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs["
255256 << InsnID << "], " << (uint64_t)Ordering << ")\n");
256257 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
257
258258 if (!State.MIs[InsnID]->hasOneMemOperand())
259259 if (handleReject() == RejectAndGiveUp)
260260 return false;
273273 << ": GIM_CheckAtomicOrderingWeakerThan(MIs["
274274 << InsnID << "], " << (uint64_t)Ordering << ")\n");
275275 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
276
277276 if (!State.MIs[InsnID]->hasOneMemOperand())
278277 if (handleReject() == RejectAndGiveUp)
279278 return false;
374373 << "]->getOperand(" << OpIdx
375374 << "), TypeID=" << TypeID << ")\n");
376375 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
377
378376 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
379377 if (!MO.isReg() ||
380378 MRI.getType(MO.getReg()) != ISelInfo.TypeObjects[TypeID]) {
393391 << InsnID << "]->getOperand(" << OpIdx
394392 << "), SizeInBits=" << SizeInBits << ")\n");
395393 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
396
397394 // iPTR must be looked up in the target.
398395 if (SizeInBits == 0) {
399396 MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent();
465462 << InsnID << "]->getOperand(" << OpIdx
466463 << "), Value=" << Value << ")\n");
467464 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
468
469465 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
470466 if (MO.isReg()) {
471467 // isOperandImmEqual() will sign-extend to 64-bits, so should we.
561557 }
562558 case GIM_Reject:
563559 DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
564 dbgs() << CurrentIdx << ": GIM_Reject");
560 dbgs() << CurrentIdx << ": GIM_Reject\n");
565561 if (handleReject() == RejectAndGiveUp)
566562 return false;
567563 break;
853849
854850 case GIR_Done:
855851 DEBUG_WITH_TYPE(TgtInstructionSelector::getName(),
856 dbgs() << CurrentIdx << ": GIR_Done");
852 dbgs() << CurrentIdx << ": GIR_Done\n");
857853 return true;
858854
859855 default:
None // RUN: llvm-tblgen -optimize-match-table=false -gen-global-isel -I %p/../../include %s | FileCheck %s --check-prefix=CHECK --check-prefix=NOOPT
1 //
2 // The optimized table can reorder predicates between rules, but the rules
3 // order must remain the same.
4 // RUN: llvm-tblgen -optimize-match-table=true -gen-global-isel -I %p/../../include %s | FileCheck %s --check-prefix=CHECK --check-prefix=OPT
5 //
6 // Make sure the default is to optimize the table.
7 // RUN: llvm-tblgen -gen-global-isel -I %p/../../include %s | FileCheck %s --check-prefix=CHECK --check-prefix=OPT
0 // RUN: llvm-tblgen -gen-global-isel -I %p/../../include -optimize-match-table=false %s -o %T/non-optimized.cpp
1 // RUN: llvm-tblgen -gen-global-isel -I %p/../../include -optimize-match-table=true %s -o %T/optimized.cpp
2 // RUN: llvm-tblgen -gen-global-isel -I %p/../../include %s -o %T/default.cpp
3
4 // RUN: FileCheck %s --check-prefixes=CHECK,R19C,R19N -input-file=%T/non-optimized.cpp
5 // RUN: FileCheck %s --check-prefixes=CHECK,R19C,R19O -input-file=%T/optimized.cpp
6
7 // RUN: FileCheck %s --check-prefixes=CHECK,R21C,R21N -input-file=%T/non-optimized.cpp
8 // RUN: FileCheck %s --check-prefixes=CHECK,R21C,R21O -input-file=%T/optimized.cpp
9
10 // RUN: FileCheck %s --check-prefixes=CHECK,R20C,R20N -input-file=%T/non-optimized.cpp
11 // RUN: FileCheck %s --check-prefixes=CHECK,R00C,R00N -input-file=%T/non-optimized.cpp
12 // RUN: FileCheck %s --check-prefixes=CHECK,R01C,R01N -input-file=%T/non-optimized.cpp
13 // RUN: FileCheck %s --check-prefixes=CHECK,R02C,R02N,NOOPT -input-file=%T/non-optimized.cpp
14
15 // RUN: diff %T/default.cpp %T/optimized.cpp
816
917 include "llvm/Target/Target.td"
1018
8290
8391 // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_INIT
8492 // CHECK-NEXT: , State(2),
85 // CHECK-NEXT: ISelInfo({TypeObjects, FeatureBitsets, ComplexPredicateFns, CustomRenderers})
93 // CHECK-NEXT: ISelInfo(TypeObjects, NumTypeObjects, FeatureBitsets, ComplexPredicateFns, CustomRenderers)
8694 // CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT
8795
8896 // CHECK-LABEL: enum SubtargetFeatureBits : uint8_t {
113121 // CHECK-NEXT: enum {
114122 // CHECK-NEXT: GILLT_s32,
115123 // CHECK-NEXT: }
124 // CHECK-NEXT: const static size_t NumTypeObjects = 1;
116125 // CHECK-NEXT: const static LLT TypeObjects[] = {
117126 // CHECK-NEXT: LLT::scalar(32),
118127 // CHECK-NEXT: };
223232 // CHECK-NEXT: return true;
224233 // CHECK-NEXT: }
225234
226 //===- Test a pattern with multiple ComplexPatterns in multiple instrs ----===//
227 //
228
229235 // CHECK: const int64_t *
230236 // CHECK-LABEL: MyTargetInstructionSelector::getMatchTable() const {
231 // CHECK: MatchTable0[] = {
232 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
233 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
234 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
235 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
236 // CHECK-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/3, // MIs[1]
237 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/4,
238 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
239 // OPT-NEXT: // No instruction predicates
240 // CHECK-NEXT: // MIs[0] dst
241 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
242 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
243 // CHECK-NEXT: // MIs[0] src1
244 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
245 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
246 // CHECK-NEXT: // MIs[0] Operand 2
247 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
248 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex_rr,
249 // CHECK-NEXT: // MIs[0] Operand 3
250 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/3, /*Type*/GILLT_s32,
251 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_SELECT,
252 // CHECK-NEXT: // MIs[1] Operand 0
253 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
254 // CHECK-NEXT: // MIs[1] src3
255 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
256 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
257 // CHECK-NEXT: // MIs[1] src4
258 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
259 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/1, /*Op*/2, /*Renderer*/1, GICP_gi_complex,
260 // CHECK-NEXT: // MIs[1] Operand 3
261 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/3, /*Type*/GILLT_s32,
262 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/1, /*Op*/3, /*Renderer*/2, GICP_gi_complex,
263 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
264 // CHECK-NEXT: // (select:{ *:[i32] } GPR32:{ *:[i32] }:$src1, (complex_rr:{ *:[i32] } GPR32:{ *:[i32] }:$src2a, GPR32:{ *:[i32] }:$src2b), (select:{ *:[i32] } GPR32:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src4, (complex:{ *:[i32] } i32imm:{ *:[i32] }:$src5a, i32imm:{ *:[i32] }:$src5b))) => (INSN3:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2b, GPR32:{ *:[i32] }:$src2a, (INSN4:{ *:[i32] } GPR32:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src4, i32imm:{ *:[i32] }:$src5a, i32imm:{ *:[i32] }:$src5b))
265 // CHECK-NEXT: // Rule ID {{[0-9]+}}
266 // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32,
267 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/MyTarget::INSN4,
268 // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/RegState::Define,
269 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/1, /*OpIdx*/1, // src3
270 // CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/1, /*RendererID*/1,
271 // CHECK-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/1, /*RendererID*/2, /*SubOperand*/0, // src5a
272 // CHECK-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/1, /*RendererID*/2, /*SubOperand*/1, // src5b
273 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/1,
274 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN3,
275 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
276 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
277 // CHECK-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/0, /*RendererID*/0, /*SubOperand*/1, // src2b
278 // CHECK-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/0, /*RendererID*/0, /*SubOperand*/0, // src2a
279 // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0,
280 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
281 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
282 // CHECK-NEXT: GIR_Done,
283 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
237 // CHECK-NEXT: MatchTable0[] = {
238
239 //===- Test a pattern with multiple ComplexPatterns in multiple instrs ----===//
240 //
241 // R19O-NEXT: GIM_Try, /*On fail goto*//*Label [[GROUP_NUM:[0-9]+]]*/ [[GROUP:[0-9]+]],
242 // R19O-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
243 //
244 // R19C-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
245 // R19C-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
246 // R19N-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
247 // R19N-NEXT: // MIs[0] dst
248 // R19C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
249 // R19N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
250 // R19N-NEXT: // MIs[0] src1
251 // R19C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
252 // R19N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
253 // R19N-NEXT: // MIs[0] Operand 2
254 // R19C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
255 // R19N-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex_rr,
256 // R19C-NEXT: // MIs[0] Operand 3
257 // R19C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/3, /*Type*/GILLT_s32,
258 // R19C-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/3, // MIs[1]
259 // R19C-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/4,
260 // R19C-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_SELECT,
261 // R19C-NEXT: // MIs[1] Operand 0
262 // R19C-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
263 // R19N-NEXT: // MIs[1] src3
264 // R19C-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
265 // R19N-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
266 // R19N-NEXT: // MIs[1] src4
267 // R19C-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
268 // R19N-NEXT: GIM_CheckComplexPattern, /*MI*/1, /*Op*/2, /*Renderer*/1, GICP_gi_complex,
269 // R19N-NEXT: // MIs[1] Operand 3
270 // R19C-NEXT: GIM_CheckType, /*MI*/1, /*Op*/3, /*Type*/GILLT_s32,
271 // R19N-NEXT: GIM_CheckComplexPattern, /*MI*/1, /*Op*/3, /*Renderer*/2, GICP_gi_complex,
272 // R19C-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
273 // R19O-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex_rr,
274 // R19O-NEXT: GIM_CheckComplexPattern, /*MI*/1, /*Op*/2, /*Renderer*/1, GICP_gi_complex,
275 // R19O-NEXT: GIM_CheckComplexPattern, /*MI*/1, /*Op*/3, /*Renderer*/2, GICP_gi_complex,
276 // R19O-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
277 // R19O-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
278 // R19O-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
279 // R19C-NEXT: // (select:{ *:[i32] } GPR32:{ *:[i32] }:$src1, (complex_rr:{ *:[i32] } GPR32:{ *:[i32] }:$src2a, GPR32:{ *:[i32] }:$src2b), (select:{ *:[i32] } GPR32:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src4, (complex:{ *:[i32] } i32imm:{ *:[i32] }:$src5a, i32imm:{ *:[i32] }:$src5b))) => (INSN3:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2b, GPR32:{ *:[i32] }:$src2a, (INSN4:{ *:[i32] } GPR32:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src4, i32imm:{ *:[i32] }:$src5a, i32imm:{ *:[i32] }:$src5b))
280 // R19C-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32,
281 // R19C-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/MyTarget::INSN4,
282 // R19C-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/RegState::Define,
283 // R19C-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/1, /*OpIdx*/1, // src3
284 // R19C-NEXT: GIR_ComplexRenderer, /*InsnID*/1, /*RendererID*/1,
285 // R19C-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/1, /*RendererID*/2, /*SubOperand*/0, // src5a
286 // R19C-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/1, /*RendererID*/2, /*SubOperand*/1, // src5b
287 // R19C-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/1,
288 // R19C-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN3,
289 // R19C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
290 // R19C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
291 // R19C-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/0, /*RendererID*/0, /*SubOperand*/1, // src2b
292 // R19C-NEXT: GIR_ComplexSubOperandRenderer, /*InsnID*/0, /*RendererID*/0, /*SubOperand*/0, // src2a
293 // R19C-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0,
294 // R19C-NEXT: GIR_EraseFromParent, /*InsnID*/0,
295 // R19C-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
296 // R19C-NEXT: // GIR_Coverage, 19,
297 // R19C-NEXT: GIR_Done,
298 // R19C-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
299 //
300 // R19O: GIM_Reject,
301 // R19O-NEXT: // Label [[GROUP_NUM]]: @[[GROUP]]
284302
285303 def INSN3 : I<(outs GPR32:$dst),
286304 (ins GPR32Op:$src1, GPR32:$src2a, GPR32:$src2b, GPR32:$scr), []>;
294312 (INSN4 GPR32:$src3, complex:$src4, i32imm:$src5a,
295313 i32imm:$src5b))>;
296314
297 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
298 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
299 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
300 // OPT-NEXT: // No instruction predicates
301 // CHECK-NEXT: // MIs[0] dst
302 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
303 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
304 // CHECK-NEXT: // MIs[0] src1
305 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
306 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
307 // CHECK-NEXT: // MIs[0] src2
308 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
309 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex,
310 // CHECK-NEXT: // MIs[0] src3
311 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/3, /*Type*/GILLT_s32,
312 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/3, /*Renderer*/1, GICP_gi_complex,
313 // CHECK-NEXT: // (select:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2, complex:{ *:[i32] }:$src3) => (INSN2:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src2)
314 // CHECK-NEXT: // Rule ID {{[0-9]+}}
315 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN2,
316 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
317 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
318 // CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/1,
319 // CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
320 // CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*MergeInsnID's*/0, GIU_MergeMemOperands_EndOfList,
321 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
322 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
323 // CHECK-NEXT: GIR_Done,
324 // Closing the G_SELECT group.
325 // OPT-NEXT: // Label 2: @[[LABEL]]
326 // OPT-NEXT: GIM_Reject,
327 // OPT-NEXT: GIR_Done,
328 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
329 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
315 // R21O-NEXT: GIM_Try, /*On fail goto*//*Label [[GROUP_NUM:[0-9]+]]*/ [[GROUP:[0-9]+]],
316 // R21O-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
317 //
318 // R21C-NEXT: GIM_Try, /*On fail goto*//*Label [[PREV_NUM:[0-9]+]]*/ [[PREV:[0-9]+]], // Rule ID 19 //
319 // R21C-NOT: GIR_Done,
320 // R21C: // GIR_Coverage, 19,
321 // R21C-NEXT: GIR_Done,
322 // R21C-NEXT: // Label [[PREV_NUM]]: @[[PREV]]
323 // R21C-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], // Rule ID 21 //
324 //
325 // R21C-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4,
326 // R21N-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SELECT,
327 // R21N-NEXT: // MIs[0] dst
328 // R21C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
329 // R21N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
330 // R21N-NEXT: // MIs[0] src1
331 // R21C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
332 // R21N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
333 // R21N-NEXT: // MIs[0] src2
334 // R21C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
335 // R21N-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex,
336 // R21N-NEXT: // MIs[0] src3
337 // R21C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/3, /*Type*/GILLT_s32,
338 // R21O-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex,
339 // R21C-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/3, /*Renderer*/1, GICP_gi_complex,
340 // R21O-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
341 // R21O-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
342 // R21C-NEXT: // (select:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2, complex:{ *:[i32] }:$src3) => (INSN2:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src3, complex:{ *:[i32] }:$src2)
343 // R21C-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN2,
344 // R21C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
345 // R21C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
346 // R21C-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/1,
347 // R21C-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
348 // R21C-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*MergeInsnID's*/0, GIU_MergeMemOperands_EndOfList,
349 // R21C-NEXT: GIR_EraseFromParent, /*InsnID*/0,
350 // R21C-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
351 // R21C-NEXT: // GIR_Coverage, 21,
352 // R21C-NEXT: GIR_Done,
353 // R21C-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
354 //
355 // R21O-NEXT: GIM_Reject,
356 // R21O-NEXT: // Label [[GROUP_NUM]]: @[[GROUP]]
330357
331358 //===- Test a pattern with ComplexPattern operands. -----------------------===//
332359 //
333
334 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
335 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SUB,
336 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
337 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
338 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SUB,
339 // OPT-NEXT: // No instruction predicates
340 // CHECK-NEXT: // MIs[0] dst
341 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
342 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
343 // CHECK-NEXT: // MIs[0] src1
344 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
345 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
346 // CHECK-NEXT: // MIs[0] src2
347 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
348 // CHECK-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex,
349 // CHECK-NEXT: // (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2) => (INSN1:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2)
350 // CHECK-NEXT: // Rule ID {{[0-9]+}}
351 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN1,
352 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
353 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
354 // CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
355 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
356 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
357 // CHECK-NEXT: GIR_Done,
358 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
360 // R20N: GIM_Try, /*On fail goto*//*Label [[PREV_NUM:[0-9]+]]*/ [[PREV:[0-9]+]], // Rule ID 21 //
361 // R20N: // Label [[PREV_NUM]]: @[[PREV]]
362 //
363 // R20C-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], // Rule ID 20 //
364 //
365 // R20N-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
366 // R20N-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SUB,
367 // R20N-NEXT: // MIs[0] dst
368 // R20N-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
369 // R20N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
370 // R20N-NEXT: // MIs[0] src1
371 // R20C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
372 //
373 // R20N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
374 // R20C-NEXT: // MIs[0] src2
375 // R20C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
376 // R20C-NEXT: GIM_CheckComplexPattern, /*MI*/0, /*Op*/2, /*Renderer*/0, GICP_gi_complex,
377 // R20C-NEXT: // (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2) => (INSN1:{ *:[i32] } GPR32:{ *:[i32] }:$src1, complex:{ *:[i32] }:$src2)
378 // R20C-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSN1,
379 // R20C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
380 // R20C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
381 // R20C-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
382 // R20C-NEXT: GIR_EraseFromParent, /*InsnID*/0,
383 // R20C-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
384 // R20C-NEXT: // GIR_Coverage, 20,
385 // R20C-NEXT: GIR_Done,
386 // R20C-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
359387
360388 def INSN1 : I<(outs GPR32:$dst), (ins GPR32:$src1, complex:$src2), []>;
361389 def : Pat<(sub GPR32:$src1, complex:$src2), (INSN1 GPR32:$src1, complex:$src2)>;
362390
363
364391 //===- Test a pattern with multiple ComplexPattern operands. --------------===//
365392 //
366
367
368393 def : GINodeEquiv;
369394 let mayLoad = 1 in {
370395 def INSN2 : I<(outs GPR32:$dst), (ins GPR32Op:$src1, complex:$src2, complex:$src3), []>;
373398 (INSN2 GPR32:$src1, complex:$src3, complex:$src2)>;
374399
375400 //===- Test a more complex multi-instruction match. -----------------------===//
376
377 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
378 // CHECK-NEXT: GIM_CheckFeatures, GIFBS_HasA,
379 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
380 // CHECK-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
381 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/3,
382 // CHECK-NEXT: GIM_RecordInsn, /*DefineMI*/2, /*MI*/0, /*OpIdx*/2, // MIs[2]
383 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/2, /*Expected*/3,
384 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SUB,
385 // OPT-NEXT: // No instruction predicates
386 // CHECK-NEXT: // MIs[0] dst
387 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
388 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
389 // CHECK-NEXT: // MIs[0] Operand 1
390 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
391 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_SUB,
392 // CHECK-NEXT: // MIs[1] Operand 0
393 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
394 // CHECK-NEXT: // MIs[1] src1
395 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
396 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
397 // CHECK-NEXT: // MIs[1] src2
398 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
399 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
400 // CHECK-NEXT: // MIs[0] Operand 2
401 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
402 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/2, TargetOpcode::G_SUB,
403 // CHECK-NEXT: // MIs[2] Operand 0
404 // CHECK-NEXT: GIM_CheckType, /*MI*/2, /*Op*/0, /*Type*/GILLT_s32,
405 // CHECK-NEXT: // MIs[2] src3
406 // CHECK-NEXT: GIM_CheckType, /*MI*/2, /*Op*/1, /*Type*/GILLT_s32,
407 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/2, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
408 // CHECK-NEXT: // MIs[2] src4
409 // CHECK-NEXT: GIM_CheckType, /*MI*/2, /*Op*/2, /*Type*/GILLT_s32,
410 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/2, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
411 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
412 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/2,
413 // CHECK-NEXT: // (sub:{ *:[i32] } (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2), (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src3, GPR32:{ *:[i32] }:$src4)) => (INSNBOB:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3, GPR32:{ *:[i32] }:$src4)
414 // CHECK-NEXT: // Rule ID {{[0-9]+}}
415 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSNBOB,
416 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
417 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
418 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
419 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/1, // src3
420 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/2, // src4
421 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
422 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
423 // CHECK-NEXT: GIR_Done,
424 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
425 // Closing the G_SUB group.
426 // OPT-NEXT: GIM_Reject,
427 // OPT-NEXT: GIR_Done,
428 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
401 //
402 // R00C: GIM_Try, /*On fail goto*//*Label [[PREV_NUM:[0-9]+]]*/ [[PREV:[0-9]+]], // Rule ID 20 //
403 // R00C: // Label [[PREV_NUM]]: @[[PREV]]
404 //
405 // R00C-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], // Rule ID 0 //
406 // R00C-NEXT: GIM_CheckFeatures, GIFBS_HasA,
407 // R00N-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
408 // R00N-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SUB,
409 // R00N-NEXT: // MIs[0] dst
410 // R00N-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
411 // R00N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
412 // R00C-NEXT: // MIs[0] Operand 1
413 // R00C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
414 // R00C-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
415 // R00N-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/3,
416 // R00C-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_SUB,
417 // R00N-NEXT: // MIs[1] Operand 0
418 // R00N-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
419 // R00N-NEXT: // MIs[1] src1
420 // R00C-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
421 // R00N-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
422 // R00N-NEXT: // MIs[1] src2
423 // R00N-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
424 // R00N-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
425 // R00C-NEXT: // MIs[0] Operand 2
426 // R00C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
427 // R00C-NEXT: GIM_RecordInsn, /*DefineMI*/2, /*MI*/0, /*OpIdx*/2, // MIs[2]
428 // R00N-NEXT: GIM_CheckNumOperands, /*MI*/2, /*Expected*/3,
429 // R00C-NEXT: GIM_CheckOpcode, /*MI*/2, TargetOpcode::G_SUB,
430 // R00N-NEXT: // MIs[2] Operand 0
431 // R00N-NEXT: GIM_CheckType, /*MI*/2, /*Op*/0, /*Type*/GILLT_s32,
432 // R00N-NEXT: // MIs[2] src3
433 // R00C-NEXT: GIM_CheckType, /*MI*/2, /*Op*/1, /*Type*/GILLT_s32,
434 // R00N-NEXT: GIM_CheckRegBankForClass, /*MI*/2, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
435 // R00N-NEXT: // MIs[2] src4
436 // R00N-NEXT: GIM_CheckType, /*MI*/2, /*Op*/2, /*Type*/GILLT_s32,
437 // R00N-NEXT: GIM_CheckRegBankForClass, /*MI*/2, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
438 // R00C-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
439 // R00C-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/2,
440 // R00C-NEXT: // (sub:{ *:[i32] } (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2), (sub:{ *:[i32] } GPR32:{ *:[i32] }:$src3, GPR32:{ *:[i32] }:$src4)) => (INSNBOB:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3, GPR32:{ *:[i32] }:$src4)
441 // R00C-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::INSNBOB,
442 // R00C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
443 // R00C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
444 // R00C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
445 // R00C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/1, // src3
446 // R00C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/2, /*OpIdx*/2, // src4
447 // R00C-NEXT: GIR_EraseFromParent, /*InsnID*/0,
448 // R00C-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
449 // R00C-NEXT: // GIR_Coverage, 0,
450 // R00C-NEXT: GIR_Done,
451 // R00C-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
429452
430453 def INSNBOB : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3, GPR32:$src4),
431454 [(set GPR32:$dst,
434457
435458 //===- Test a simple pattern with an intrinsic. ---------------------------===//
436459 //
437
438 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
439 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_INTRINSIC,
440 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
441 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
442 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_INTRINSIC,
443 // OPT-NEXT: // No instruction predicates
444 // CHECK-NEXT: // MIs[0] dst
445 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
446 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
447 // CHECK-NEXT: // MIs[0] Operand 1
448 // CHECK-NEXT: GIM_CheckIntrinsicID, /*MI*/0, /*Op*/1, Intrinsic::mytarget_nop,
449 // CHECK-NEXT: // MIs[0] src1
450 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
451 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
452 // CHECK-NEXT: // (intrinsic_wo_chain:{ *:[i32] } [[ID:[0-9]+]]:{ *:[iPTR] }, GPR32:{ *:[i32] }:$src1) => (MOV:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
453 // CHECK-NEXT: // Rule ID {{[0-9]+}}
454
455 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV,
456 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
457 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src1
458 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
459 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
460 // CHECK-NEXT: GIR_Done,
461 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
462 // Closing the G_INTRINSIC group.
463 // OPT-NEXT: GIM_Reject,
464 // OPT-NEXT: GIR_Done,
465 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
460 // R01N: GIM_Try, /*On fail goto*//*Label [[PREV_NUM:[0-9]+]]*/ [[PREV:[0-9]+]], // Rule ID 0 //
461 // R01N: // Label [[PREV_NUM]]: @[[PREV]]
462 //
463 // R01C-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], // Rule ID 1 //
464 // R01C-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
465 //
466 // R01N-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_INTRINSIC,
467 // R01N-NEXT: // MIs[0] dst
468 // R01N-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
469 // R01N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
470 // R01N-NEXT: // MIs[0] Operand 1
471 // R01N-NEXT: GIM_CheckIntrinsicID, /*MI*/0, /*Op*/1, Intrinsic::mytarget_nop,
472 // R01N-NEXT: // MIs[0] src1
473 // R01N-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
474 //
475 // R01C-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
476 // R01C-NEXT: // (intrinsic_wo_chain:{ *:[i32] } [[ID:[0-9]+]]:{ *:[iPTR] }, GPR32:{ *:[i32] }:$src1) => (MOV:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
477 // R01C-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV,
478 // R01C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
479 // R01C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src1
480 // R01C-NEXT: GIR_EraseFromParent, /*InsnID*/0,
481 // R01C-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
482 // R01C-NEXT: // GIR_Coverage, 1,
483 // R01C-NEXT: GIR_Done,
484 // R01C-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
466485
467486 def MOV : I<(outs GPR32:$dst), (ins GPR32:$src1),
468487 [(set GPR32:$dst, (int_mytarget_nop GPR32:$src1))]>;
469488
470
471489 //===- Test a simple pattern with a default operand. ----------------------===//
472490 //
473
474 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
475 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
476 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
477 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
478 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
479 // OPT-NEXT: // No instruction predicates
480 // CHECK-NEXT: // MIs[0] dst
481 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
482 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
483 // CHECK-NEXT: // MIs[0] src1
484 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
485 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
486 // CHECK-NEXT: // MIs[0] Operand 2
487 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
488 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -2
489 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -2:{ *:[i32] }) => (XORI:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
490 // CHECK-NEXT: // Rule ID {{[0-9]+}}
491 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORI,
492 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
493 // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
494 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
495 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
496 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
497 // CHECK-NEXT: GIR_Done,
498 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
491 // R02N: GIM_Try, /*On fail goto*//*Label [[PREV_NUM:[0-9]+]]*/ [[PREV:[0-9]+]], // Rule ID 1 //
492 // R02N: // Label [[PREV_NUM]]: @[[PREV]]
493 //
494 // R02C-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], // Rule ID 2 //
495 //
496 // R02N-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
497 // R02N-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
498 // R02N-NEXT: // MIs[0] dst
499 // R02N-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
500 // R02N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
501 // R02N-NEXT: // MIs[0] src1
502 // R02C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
503 // R02N-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
504 // R02C-NEXT: // MIs[0] Operand 2
505 // R02C-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
506 // R02C-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -2
507 // R02C-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -2:{ *:[i32] }) => (XORI:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
508 // R02C-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORI,
509 // R02C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
510 // R02C-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
511 // R02C-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
512 // R02C-NEXT: GIR_EraseFromParent, /*InsnID*/0,
513 // R02C-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
514 // R02C-NEXT: // GIR_Coverage, 2,
515 // R02C-NEXT: GIR_Done,
516 // R02C-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
499517
500518 // The -2 is just to distinguish it from the 'not' case below.
501519 def XORI : I<(outs GPR32:$dst), (ins m1:$src2, GPR32:$src1),
503521
504522 //===- Test a simple pattern with a default register operand. -------------===//
505523 //
506
507 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
508 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
524 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
525 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
509526 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
510 // OPT-NEXT: // No instruction predicates
511 // CHECK-NEXT: // MIs[0] dst
512 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
513 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
514 // CHECK-NEXT: // MIs[0] src1
515 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
516 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
517 // CHECK-NEXT: // MIs[0] Operand 2
518 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
519 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -3
520 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -3:{ *:[i32] }) => (XOR:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
521 // CHECK-NEXT: // Rule ID {{[0-9]+}}
522 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XOR,
523 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
524 // CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
525 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
526 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
527 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
528 // CHECK-NEXT: GIR_Done,
529 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
527 // NOOPT-NEXT: // MIs[0] dst
528 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
529 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
530 // NOOPT-NEXT: // MIs[0] src1
531 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
532 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
533 // NOOPT-NEXT: // MIs[0] Operand 2
534 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
535 // NOOPT-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -3
536 // NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -3:{ *:[i32] }) => (XOR:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
537 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XOR,
538 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
539 // NOOPT-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
540 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
541 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
542 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
543 // NOOPT-NEXT: // GIR_Coverage, 3,
544 // NOOPT-NEXT: GIR_Done,
545 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
530546
531547 // The -3 is just to distinguish it from the 'not' case below and the other default op case above.
532548 def XOR : I<(outs GPR32:$dst), (ins Z:$src2, GPR32:$src1),
534550
535551 //===- Test a simple pattern with a multiple default operands. ------------===//
536552 //
537
538 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
539 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
553 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
554 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
540555 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
541 // OPT-NEXT: // No instruction predicates
542 // CHECK-NEXT: // MIs[0] dst
543 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
544 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
545 // CHECK-NEXT: // MIs[0] src1
546 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
547 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
548 // CHECK-NEXT: // MIs[0] Operand 2
549 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
550 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -4
551 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -4:{ *:[i32] }) => (XORlike:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
552 // CHECK-NEXT: // Rule ID {{[0-9]+}}
553 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORlike,
554 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
555 // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
556 // CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
557 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
558 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
559 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
560 // CHECK-NEXT: GIR_Done,
561 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
556 // NOOPT-NEXT: // MIs[0] dst
557 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
558 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
559 // NOOPT-NEXT: // MIs[0] src1
560 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
561 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
562 // NOOPT-NEXT: // MIs[0] Operand 2
563 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
564 // NOOPT-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -4
565 // NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -4:{ *:[i32] }) => (XORlike:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
566 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORlike,
567 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
568 // NOOPT-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
569 // NOOPT-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
570 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
571 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
572 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
573 // NOOPT-NEXT: // GIR_Coverage, 4,
574 // NOOPT-NEXT: GIR_Done,
575 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
562576
563577 // The -4 is just to distinguish it from the other 'not' cases.
564578 def XORlike : I<(outs GPR32:$dst), (ins m1Z:$src2, GPR32:$src1),
566580
567581 //===- Test a simple pattern with multiple operands with defaults. --------===//
568582 //
569
570 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
571 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
583 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
584 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
572585 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
573 // OPT-NEXT: // No instruction predicates
574 // CHECK-NEXT: // MIs[0] dst
575 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
576 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
577 // CHECK-NEXT: // MIs[0] src1
578 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
579 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
580 // CHECK-NEXT: // MIs[0] Operand 2
581 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
582 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -5,
583 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -5:{ *:[i32] }) => (XORManyDefaults:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
584 // CHECK-NEXT: // Rule ID {{[0-9]+}}
585 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORManyDefaults,
586 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
587 // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
588 // CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
589 // CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
590 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
591 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
592 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
593 // CHECK-NEXT: GIR_Done,
594 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
586 // NOOPT-NEXT: // MIs[0] dst
587 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
588 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
589 // NOOPT-NEXT: // MIs[0] src1
590 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
591 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
592 // NOOPT-NEXT: // MIs[0] Operand 2
593 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
594 // NOOPT-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -5,
595 // NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$src1, -5:{ *:[i32] }) => (XORManyDefaults:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
596 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::XORManyDefaults,
597 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
598 // NOOPT-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/-1,
599 // NOOPT-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
600 // NOOPT-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
601 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
602 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
603 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
604 // NOOPT-NEXT: // GIR_Coverage, 5,
605 // NOOPT-NEXT: GIR_Done,
606 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
595607
596608 // The -5 is just to distinguish it from the other cases.
597609 def XORManyDefaults : I<(outs GPR32:$dst), (ins m1Z:$src3, Z:$src2, GPR32:$src1),
601613 //
602614 // This must precede the 3-register variants because constant immediates have
603615 // priority over register banks.
604
605 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
606 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
616 //
617 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
618 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
607619 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_XOR,
608 // OPT-NEXT: // No instruction predicates
609 // CHECK-NEXT: // MIs[0] dst
610 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
611 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
612 // CHECK-NEXT: // MIs[0] Wm
613 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
614 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
615 // CHECK-NEXT: // MIs[0] Operand 2
616 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
617 // CHECK-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -1,
618 // CHECK-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$Wm, -1:{ *:[i32] }) => (ORN:{ *:[i32] } R0:{ *:[i32] }, GPR32:{ *:[i32] }:$Wm)
619 // CHECK-NEXT: // Rule ID {{[0-9]+}}
620 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::ORN,
621 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
622 // CHECK-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
623 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // Wm
624 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
625 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
626 // CHECK-NEXT: GIR_Done,
627 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
628 // Closing the G_XOR group.
629 // OPT-NEXT: GIM_Reject,
630 // OPT-NEXT: GIR_Done,
631 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
620 // NOOPT-NEXT: // MIs[0] dst
621 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
622 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
623 // NOOPT-NEXT: // MIs[0] Wm
624 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
625 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
626 // NOOPT-NEXT: // MIs[0] Operand 2
627 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
628 // NOOPT-NEXT: GIM_CheckConstantInt, /*MI*/0, /*Op*/2, -1,
629 // NOOPT-NEXT: // (xor:{ *:[i32] } GPR32:{ *:[i32] }:$Wm, -1:{ *:[i32] }) => (ORN:{ *:[i32] } R0:{ *:[i32] }, GPR32:{ *:[i32] }:$Wm)
630 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::ORN,
631 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
632 // NOOPT-NEXT: GIR_AddRegister, /*InsnID*/0, MyTarget::R0,
633 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // Wm
634 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
635 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
636 // NOOPT-NEXT: // GIR_Coverage, 22,
637 // NOOPT-NEXT: GIR_Done,
638 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
632639
633640 def ORN : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2), []>;
634641 def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>;
635642
636
637643 //===- Test a nested instruction match. -----------------------------------===//
638
639 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
640 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_MUL,
641 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
642 // CHECK-NEXT: GIM_CheckFeatures, GIFBS_HasA,
643 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
644 // CHECK-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
645 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/3,
644 //
645 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
646 // NOOPT-NEXT: GIM_CheckFeatures, GIFBS_HasA,
647 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
646648 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_MUL,
647 // OPT-NEXT: // No instruction predicates
648 // CHECK-NEXT: // MIs[0] dst
649 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
650 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
651 // CHECK-NEXT: // MIs[0] Operand 1
652 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
653 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_ADD,
654 // CHECK-NEXT: // MIs[1] Operand 0
655 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
656 // CHECK-NEXT: // MIs[1] src1
657 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
658 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
659 // CHECK-NEXT: // MIs[1] src2
660 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
661 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
662 // CHECK-NEXT: // MIs[0] src3
663 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
664 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
665 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
666 // CHECK-NEXT: // (mul:{ *:[i32] } (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2), GPR32:{ *:[i32] }:$src3) => (MULADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3)
667 // CHECK-NEXT: // Rule ID {{[0-9]+}}
668 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
669 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
670 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
671 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
672 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src3
673 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
674 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
675 // CHECK-NEXT: GIR_Done,
676 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
649 // NOOPT-NEXT: // MIs[0] dst
650 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
651 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
652 // NOOPT-NEXT: // MIs[0] Operand 1
653 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
654 // NOOPT-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]
655 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/3,
656 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_ADD,
657 // NOOPT-NEXT: // MIs[1] Operand 0
658 // NOOPT-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
659 // NOOPT-NEXT: // MIs[1] src1
660 // NOOPT-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
661 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
662 // NOOPT-NEXT: // MIs[1] src2
663 // NOOPT-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
664 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
665 // NOOPT-NEXT: // MIs[0] src3
666 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
667 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
668 // NOOPT-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
669 // NOOPT-NEXT: // (mul:{ *:[i32] } (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2), GPR32:{ *:[i32] }:$src3) => (MULADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3)
670 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
671 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
672 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
673 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
674 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src3
675 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
676 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
677 // NOOPT-NEXT: // GIR_Coverage, 6,
678 // NOOPT-NEXT: GIR_Done,
679 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
677680
678681 // We also get a second rule by commutativity.
679 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
680 // CHECK-NEXT: GIM_CheckFeatures, GIFBS_HasA,
681 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
682 // CHECK-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/2,
683 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/3,
682 //
683 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
684 // NOOPT-NEXT: GIM_CheckFeatures, GIFBS_HasA,
685 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
684686 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_MUL,
685 // OPT-NEXT: // No instruction predicates
686 // CHECK-NEXT: // MIs[0] dst
687 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
688 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
689 // CHECK-NEXT: // MIs[0] src3
690 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
691 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
692 // CHECK-NEXT: // MIs[0] Operand 2
693 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
694 // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_ADD,
695 // CHECK-NEXT: // MIs[1] Operand 0
696 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
697 // CHECK-NEXT: // MIs[1] src1
698 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
699 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
700 // CHECK-NEXT: // MIs[1] src2
701 // CHECK-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
702 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
703 // CHECK-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
704 // CHECK-NEXT: // (mul:{ *:[i32] } GPR32:{ *:[i32] }:$src3, (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2)) => (MULADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3)
705 // CHECK-NEXT: // Rule ID {{[0-9]+}}
706 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
707 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
708 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
709 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
710 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src3
711 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
712 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
713 // CHECK-NEXT: GIR_Done,
714 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
715 // Closing the G_MUL group.
716 // OPT-NEXT: GIM_Reject,
717 // OPT-NEXT: GIR_Done,
718 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
687 // NOOPT-NEXT: // MIs[0] dst
688 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
689 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
690 // NOOPT-NEXT: // MIs[0] src3
691 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
692 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
693 // NOOPT-NEXT: // MIs[0] Operand 2
694 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
695 // NOOPT-NEXT: GIM_RecordInsn, /*DefineMI*/1, /*MI*/0, /*OpIdx*/2,
696 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/1, /*Expected*/3,
697 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/1, TargetOpcode::G_ADD,
698 // NOOPT-NEXT: // MIs[1] Operand 0
699 // NOOPT-NEXT: GIM_CheckType, /*MI*/1, /*Op*/0, /*Type*/GILLT_s32,
700 // NOOPT-NEXT: // MIs[1] src1
701 // NOOPT-NEXT: GIM_CheckType, /*MI*/1, /*Op*/1, /*Type*/GILLT_s32,
702 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
703 // NOOPT-NEXT: // MIs[1] src2
704 // NOOPT-NEXT: GIM_CheckType, /*MI*/1, /*Op*/2, /*Type*/GILLT_s32,
705 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/1, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
706 // NOOPT-NEXT: GIM_CheckIsSafeToFold, /*InsnID*/1,
707 // NOOPT-NEXT: // (mul:{ *:[i32] } GPR32:{ *:[i32] }:$src3, (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2)) => (MULADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src3)
708 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MULADD,
709 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
710 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // src1
711 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/2, // src2
712 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src3
713 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
714 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
715 // NOOPT-NEXT: // GIR_Coverage, 25,
716 // NOOPT-NEXT: GIR_Done,
717 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
719718
720719 def MULADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2, GPR32:$src3),
721720 [(set GPR32:$dst,
723722 Requires<[HasA]>;
724723
725724 //===- Test a simple pattern with just a specific leaf immediate. ---------===//
726
727 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
728 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
729 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
730 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
725 //
726 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
727 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
731728 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
732 // OPT-NEXT: // No instruction predicates
733 // CHECK-NEXT: // MIs[0] dst
734 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
735 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
736 // CHECK-NEXT: // MIs[0] Operand 1
737 // CHECK-NEXT: GIM_CheckLiteralInt, /*MI*/0, /*Op*/1, 1,
738 // CHECK-NEXT: // 1:{ *:[i32] } => (MOV1:{ *:[i32] })
739 // CHECK-NEXT: // Rule ID {{[0-9]+}}
740 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV1,
741 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
742 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
743 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
744 // CHECK-NEXT: GIR_Done,
745 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
729 // NOOPT-NEXT: // MIs[0] dst
730 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
731 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
732 // NOOPT-NEXT: // MIs[0] Operand 1
733 // NOOPT-NEXT: GIM_CheckLiteralInt, /*MI*/0, /*Op*/1, 1,
734 // NOOPT-NEXT: // 1:{ *:[i32] } => (MOV1:{ *:[i32] })
735 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV1,
736 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
737 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
738 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
739 // NOOPT-NEXT: // GIR_Coverage, 7,
740 // NOOPT-NEXT: GIR_Done,
741 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
746742
747743 def MOV1 : I<(outs GPR32:$dst), (ins), [(set GPR32:$dst, 1)]>;
748744
749745 //===- Test a simple pattern with a leaf immediate and a predicate. -------===//
750
751 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
752 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
746 //
747 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
748 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
753749 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
754 // CHECK-NEXT: GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GIPFP_I64_Predicate_simm8,
755 // CHECK-NEXT: // MIs[0] dst
756 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
757 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
758 // CHECK-NEXT: // MIs[0] Operand 1
759 // CHECK-NEXT: // No operand predicates
760 // CHECK-NEXT: // (imm:{ *:[i32] })<>:$imm => (MOVimm8:{ *:[i32] } (imm:{ *:[i32] }):$imm)
761 // CHECK-NEXT: // Rule ID {{[0-9]+}}
762 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm8,
763 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
764 // CHECK-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
765 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
766 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
767 // CHECK-NEXT: GIR_Done,
768 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
750 // NOOPT-NEXT: GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GIPFP_I64_Predicate_simm8,
751 // NOOPT-NEXT: // MIs[0] dst
752 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
753 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
754 // NOOPT-NEXT: // MIs[0] Operand 1
755 // NOOPT-NEXT: // No operand predicates
756 // NOOPT-NEXT: // (imm:{ *:[i32] })<>:$imm => (MOVimm8:{ *:[i32] } (imm:{ *:[i32] }):$imm)
757 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm8,
758 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
759 // NOOPT-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
760 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
761 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
762 // NOOPT-NEXT: // GIR_Coverage, 8,
763 // NOOPT-NEXT: GIR_Done,
764 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
769765
770766 def simm8 : ImmLeaf(Imm); }]>;
771767 def MOVimm8 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, simm8:$imm)]>;
772768
773769 //===- Same again but use an IntImmLeaf. ----------------------------------===//
774
775 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
776 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
770 //
771 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
772 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
777773 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
778 // CHECK-NEXT: GIM_CheckAPIntImmPredicate, /*MI*/0, /*Predicate*/GIPFP_APInt_Predicate_simm9,
779 // CHECK-NEXT: // MIs[0] dst
780 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
781 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
782 // CHECK-NEXT: // MIs[0] Operand 1
783 // CHECK-NEXT: // No operand predicates
784 // CHECK-NEXT: // (imm:{ *:[i32] })<>:$imm => (MOVimm9:{ *:[i32] } (imm:{ *:[i32] }):$imm)
785 // CHECK-NEXT: // Rule ID {{[0-9]+}}
786 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm9,
787 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
788 // CHECK-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
789 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
790 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
791 // CHECK-NEXT: GIR_Done,
792 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
774 // NOOPT-NEXT: GIM_CheckAPIntImmPredicate, /*MI*/0, /*Predicate*/GIPFP_APInt_Predicate_simm9,
775 // NOOPT-NEXT: // MIs[0] dst
776 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
777 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
778 // NOOPT-NEXT: // MIs[0] Operand 1
779 // NOOPT-NEXT: // No operand predicates
780 // NOOPT-NEXT: // (imm:{ *:[i32] })<>:$imm => (MOVimm9:{ *:[i32] } (imm:{ *:[i32] }):$imm)
781 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm9,
782 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
783 // NOOPT-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
784 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
785 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
786 // NOOPT-NEXT: // GIR_Coverage, 9,
787 // NOOPT-NEXT: GIR_Done,
788 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
793789
794790 def simm9 : IntImmLeaf(Imm->getSExtValue()); }]>;
795791 def MOVimm9 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, simm9:$imm)]>;
796792
797793 //===- Test a pattern with a custom renderer. -----------------------------===//
798 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
799 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
794 //
795 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
796 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
800797 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
801 // CHECK-NEXT: GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GIPFP_I64_Predicate_cimm8,
802 // CHECK-NEXT: // MIs[0] dst
803 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
804 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
805 // CHECK-NEXT: // MIs[0] Operand 1
806 // CHECK-NEXT: // No operand predicates
807 // CHECK-NEXT: // (imm:{ *:[i32] })<><>:$imm => (MOVcimm8:{ *:[i32] } (cimm8_xform:{ *:[i32] } (imm:{ *:[i32] }):$imm))
808 // CHECK-NEXT: // Rule ID {{[0-9]+}}
809 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVcimm8,
810 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
811 // CHECK-NEXT: GIR_CustomRenderer, /*InsnID*/0, /*OldInsnID*/0, /*Renderer*/GICR_renderImm8, // imm
812 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
813 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
814 // CHECK-NEXT: GIR_Done,
815 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
816 // Closing the G_CONSTANT group.
817 // OPT-NEXT: GIM_Reject,
818 // OPT-NEXT: GIR_Done,
819 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
798 // NOOPT-NEXT: GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GIPFP_I64_Predicate_cimm8,
799 // NOOPT-NEXT: // MIs[0] dst
800 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
801 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
802 // NOOPT-NEXT: // MIs[0] Operand 1
803 // NOOPT-NEXT: // No operand predicates
804 // NOOPT-NEXT: // (imm:{ *:[i32] })<><>:$imm => (MOVcimm8:{ *:[i32] } (cimm8_xform:{ *:[i32] } (imm:{ *:[i32] }):$imm))
805 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVcimm8,
806 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
807 // NOOPT-NEXT: GIR_CustomRenderer, /*InsnID*/0, /*OldInsnID*/0, /*Renderer*/GICR_renderImm8, // imm
808 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
809 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
810 // NOOPT-NEXT: // GIR_Coverage, 10,
811 // NOOPT-NEXT: GIR_Done,
812 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
813
820814 def MOVcimm8 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, cimm8:$imm)]>;
821815
822816 //===- Test a simple pattern with a FP immediate and a predicate. ---------===//
823
824 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
825 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_FCONSTANT,
826 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
827 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
817 //
818 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
819 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
828820 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_FCONSTANT,
829 // CHECK-NEXT: GIM_CheckAPFloatImmPredicate, /*MI*/0, /*Predicate*/GIPFP_APFloat_Predicate_fpimmz,
830 // CHECK-NEXT: // MIs[0] dst
831 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
832 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::FPR32RegClassID,
833 // CHECK-NEXT: // MIs[0] Operand 1
834 // CHECK-NEXT: // No operand predicates
835 // CHECK-NEXT: // (fpimm:{ *:[f32] })<>:$imm => (MOVfpimmz:{ *:[f32] } (fpimm:{ *:[f32] }):$imm)
836 // CHECK-NEXT: // Rule ID {{[0-9]+}}
837 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVfpimmz,
838 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
839 // CHECK-NEXT: GIR_CopyFConstantAsFPImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
840 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
841 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
842 // CHECK-NEXT: GIR_Done,
843 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
844 // Closing the G_FCONSTANT group.
845 // OPT-NEXT: GIM_Reject,
846 // OPT-NEXT: GIR_Done,
847 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
821 // NOOPT-NEXT: GIM_CheckAPFloatImmPredicate, /*MI*/0, /*Predicate*/GIPFP_APFloat_Predicate_fpimmz,
822 // NOOPT-NEXT: // MIs[0] dst
823 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
824 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::FPR32RegClassID,
825 // NOOPT-NEXT: // MIs[0] Operand 1
826 // NOOPT-NEXT: // No operand predicates
827 // NOOPT-NEXT: // (fpimm:{ *:[f32] })<>:$imm => (MOVfpimmz:{ *:[f32] } (fpimm:{ *:[f32] }):$imm)
828 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVfpimmz,
829 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
830 // NOOPT-NEXT: GIR_CopyFConstantAsFPImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
831 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
832 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
833 // NOOPT-NEXT: // GIR_Coverage, 17,
834 // NOOPT-NEXT: GIR_Done,
835 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
848836
849837 //===- Test a simple pattern with inferred pointer operands. ---------------===//
850
851 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
852 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_LOAD,
853 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
854 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
838 //
839 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
840 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
855841 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_LOAD,
856 // CHECK-NEXT: GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
857 // CHECK-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic,
858 // CHECK-NEXT: // MIs[0] dst
859 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
860 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
861 // CHECK-NEXT: // MIs[0] src1
862 // CHECK-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
863 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
864 // CHECK-NEXT: // (ld:{ *:[i32] } GPR32:{ *:[i32] }:$src1)<><> => (LOAD:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
865 // CHECK-NEXT: // Rule ID {{[0-9]+}}
866 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::LOAD,
867 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
868 // CHECK-NEXT: GIR_Done,
869 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
870 // Closing the G_LOAD group.
871 // OPT-NEXT: GIM_Reject,
872 // OPT-NEXT: GIR_Done,
873 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
842 // NOOPT-NEXT: GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
843 // NOOPT-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic,
844 // NOOPT-NEXT: // MIs[0] dst
845 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
846 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
847 // NOOPT-NEXT: // MIs[0] src1
848 // NOOPT-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
849 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
850 // NOOPT-NEXT: // (ld:{ *:[i32] } GPR32:{ *:[i32] }:$src1)<><> => (LOAD:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
851 // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::LOAD,
852 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
853 // NOOPT-NEXT: // GIR_Coverage, 11,
854 // NOOPT-NEXT: GIR_Done,
855 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
874856
875857 def LOAD : I<(outs GPR32:$dst), (ins GPR32:$src1),
876858 [(set GPR32:$dst, (load GPR32:$src1))]>;
877859
878860 //===- Test a simple pattern with a sextload -------------------------------===//
879
880 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
881 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SEXTLOAD,
882 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
883 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
861 //
862 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
863 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
884864 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_SEXTLOAD,
885 // CHECK-NEXT: GIM_CheckMemorySizeEqualTo, /*MI*/0, /*MMO*/0, /*Size*/2,
886 // CHECK-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic,
887 // CHECK-NEXT: // MIs[0] dst
888 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
889 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
890 // CHECK-NEXT: // MIs[0] src1
891 // CHECK-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
892 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
893 // CHECK-NEXT: // (ld:{ *:[i32] } GPR32:{ *:[i32] }:$src1)<><><> => (SEXTLOAD:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
894 // CHECK-NEXT: // Rule ID {{[0-9]+}}
895 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::SEXTLOAD,
896 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
897 // CHECK-NEXT: GIR_Done,
898 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
899 // Closing the G_SEXT group.
900 // OPT-NEXT: GIM_Reject,
901 // OPT-NEXT: GIR_Done,
902 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
865 // NOOPT-NEXT: GIM_CheckMemorySizeEqualTo, /*MI*/0, /*MMO*/0, /*Size*/2,
866 // NOOPT-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic,
867 // NOOPT-NEXT: // MIs[0] dst
868 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
869 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
870 // NOOPT-NEXT: // MIs[0] src1
871 // NOOPT-NEXT: GIM_CheckPointerToAny, /*MI*/0, /*Op*/1, /*SizeInBits*/32,
872 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
873 // NOOPT-NEXT: // (ld:{ *:[i32] } GPR32:{ *:[i32] }:$src1)<><><> => (SEXTLOAD:{ *:[i32] } GPR32:{ *:[i32] }:$src1)
874 // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::SEXTLOAD,
875 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
876 // NOOPT-NEXT: // GIR_Coverage, 12,
877 // NOOPT-NEXT: GIR_Done,
878 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
903879
904880 def SEXTLOAD : I<(outs GPR32:$dst), (ins GPR32:$src1),
905881 [(set GPR32:$dst, (sextloadi16 GPR32:$src1))]>;
906882
907
908883 //===- Test a simple pattern with regclass operands. ----------------------===//
909
910 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
911 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_ADD,
912 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
913 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
884 //
885 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
886 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
914887 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_ADD,
915 // OPT-NEXT: // No instruction predicates
916 // CHECK-NEXT: // MIs[0] dst
917 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
918 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
919 // CHECK-NEXT: // MIs[0] src1
920 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
921 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID
922 // CHECK-NEXT: // MIs[0] src2
923 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
924 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
925 // CHECK-NEXT: // (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2) => (ADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2)
926 // CHECK-NEXT: // Rule ID {{[0-9]+}}
927 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::ADD,
928 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
929 // CHECK-NEXT: GIR_Done,
930 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
931
888 // NOOPT-NEXT: // MIs[0] dst
889 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
890 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
891 // NOOPT-NEXT: // MIs[0] src1
892 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
893 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID
894 // NOOPT-NEXT: // MIs[0] src2
895 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
896 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
897 // NOOPT-NEXT: // (add:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2) => (ADD:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2)
898 // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::ADD,
899 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
900 // NOOPT-NEXT: // GIR_Coverage, 13,
901 // NOOPT-NEXT: GIR_Done,
902 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
932903
933904 def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
934905 [(set GPR32:$dst, (add GPR32:$src1, GPR32:$src2))]>;
935906
936907 //===- Test a pattern with a tied operand in the matcher ------------------===//
937
938 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
939 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
908 //
909 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
910 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
940911 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_ADD,
941 // OPT-NEXT: // No instruction predicates
942 // CHECK-NEXT: // MIs[0] dst
943 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
944 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
945 // CHECK-NEXT: // MIs[0] src{{$}}
946 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
947 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
948 // CHECK-NEXT: // MIs[0] src{{$}}
949 // CHECK-NEXT: GIM_CheckIsSameOperand, /*MI*/0, /*OpIdx*/2, /*OtherMI*/0, /*OtherOpIdx*/1,
950 // CHECK-NEXT: // (add:{ *:[i32] } GPR32:{ *:[i32] }:$src, GPR32:{ *:[i32] }:$src) => (DOUBLE:{ *:[i32] } GPR32:{ *:[i32] }:$src)
951 // CHECK-NEXT: // Rule ID {{[0-9]+}}
952 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::DOUBLE,
953 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
954 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src
955 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
956 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
957 // CHECK-NEXT: GIR_Done,
958 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
912 // NOOPT-NEXT: // MIs[0] dst
913 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
914 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
915 // NOOPT-NEXT: // MIs[0] src{{$}}
916 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
917 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
918 // NOOPT-NEXT: // MIs[0] src{{$}}
919 // NOOPT-NEXT: GIM_CheckIsSameOperand, /*MI*/0, /*OpIdx*/2, /*OtherMI*/0, /*OtherOpIdx*/1,
920 // NOOPT-NEXT: // (add:{ *:[i32] } GPR32:{ *:[i32] }:$src, GPR32:{ *:[i32] }:$src) => (DOUBLE:{ *:[i32] } GPR32:{ *:[i32] }:$src)
921 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::DOUBLE,
922 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
923 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src
924 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
925 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
926 // NOOPT-NEXT: // GIR_Coverage, 14,
927 // NOOPT-NEXT: GIR_Done,
928 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
959929
960930 def DOUBLE : I<(outs GPR32:$dst), (ins GPR32:$src), [(set GPR32:$dst, (add GPR32:$src, GPR32:$src))]>;
961931
962932 //===- Test a simple pattern with ValueType operands. ----------------------===//
963
964 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
965 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
933 //
934 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
935 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
966936 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_ADD,
967 // OPT-NEXT: // No instruction predicates
968 // CHECK-NEXT: // MIs[0] dst
969 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
970 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
971 // CHECK-NEXT: // MIs[0] src1
972 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
973 // CHECK-NEXT: // MIs[0] src2
974 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
975 // CHECK-NEXT: // (add:{ *:[i32] } i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2) => (ADD:{ *:[i32] } i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2)
976 // CHECK-NEXT: // Rule ID {{[0-9]+}}
977 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::ADD,
978 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
979 // CHECK-NEXT: GIR_Done,
980 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
981 // Closing the G_ADD group.
982 // OPT-NEXT: GIM_Reject,
983 // OPT-NEXT: GIR_Done,
984 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
985 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
986 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_MUL,
937 // NOOPT-NEXT: // MIs[0] dst
938 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
939 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
940 // NOOPT-NEXT: // MIs[0] src1
941 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
942 // NOOPT-NEXT: // MIs[0] src2
943 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
944 // NOOPT-NEXT: // (add:{ *:[i32] } i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2) => (ADD:{ *:[i32] } i32:{ *:[i32] }:$src1, i32:{ *:[i32] }:$src2)
945 // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::ADD,
946 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
947 // NOOPT-NEXT: // GIR_Coverage, 23,
948 // NOOPT-NEXT: GIR_Done,
949 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
987950
988951 def : Pat<(add i32:$src1, i32:$src2),
989952 (ADD i32:$src1, i32:$src2)>;
990953
991
992
993954 //===- Test another simple pattern with regclass operands. ----------------===//
994
995 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
996 // CHECK-NEXT: GIM_CheckFeatures, GIFBS_HasA_HasB_HasC,
997 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
955 //
956 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
957 // NOOPT-NEXT: GIM_CheckFeatures, GIFBS_HasA_HasB_HasC,
958 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/3,
998959 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_MUL,
999 // OPT-NEXT: // No instruction predicates
1000 // CHECK-NEXT: // MIs[0] dst
1001 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
1002 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
1003 // CHECK-NEXT: // MIs[0] src1
1004 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
1005 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
1006 // CHECK-NEXT: // MIs[0] src2
1007 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
1008 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
1009 // CHECK-NEXT: // (mul:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2) => (MUL:{ *:[i32] } GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src1)
1010 // CHECK-NEXT: // Rule ID {{[0-9]+}}
1011 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MUL,
1012 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
1013 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src2
1014 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
1015 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
1016 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
1017 // CHECK-NEXT: GIR_Done,
1018 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
1019 // Closing the G_MUL group.
1020 // OPT-NEXT: GIM_Reject,
1021 // OPT-NEXT: GIR_Done,
1022 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
960 // NOOPT-NEXT: // MIs[0] dst
961 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
962 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
963 // NOOPT-NEXT: // MIs[0] src1
964 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
965 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::GPR32RegClassID,
966 // NOOPT-NEXT: // MIs[0] src2
967 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32,
968 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID,
969 // NOOPT-NEXT: // (mul:{ *:[i32] } GPR32:{ *:[i32] }:$src1, GPR32:{ *:[i32] }:$src2) => (MUL:{ *:[i32] } GPR32:{ *:[i32] }:$src2, GPR32:{ *:[i32] }:$src1)
970 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MUL,
971 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
972 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/2, // src2
973 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
974 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
975 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
976 // NOOPT-NEXT: // GIR_Coverage, 15,
977 // NOOPT-NEXT: GIR_Done,
978 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
1023979
1024980 def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1),
1025981 [(set GPR32:$dst, (mul GPR32:$src1, GPR32:$src2))]>,
1026982 Requires<[HasA, HasB, HasC]>;
1027983
1028
1029
1030984 //===- Test a COPY_TO_REGCLASS --------------------------------------------===//
1031985 //
1032
1033 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
1034 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BITCAST,
1035 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
1036 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
986 //
987 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
988 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
1037989 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BITCAST,
1038 // OPT-NEXT: // No instruction predicates
1039 // CHECK-NEXT: // MIs[0] dst
1040 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
1041 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
1042 // CHECK-NEXT: // MIs[0] src1
1043 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
1044 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::FPR32RegClassID,
1045 // CHECK-NEXT: // (bitconvert:{ *:[i32] } FPR32:{ *:[f32] }:$src1) => (COPY_TO_REGCLASS:{ *:[i32] } FPR32:{ *:[f32] }:$src1, GPR32:{ *:[i32] })
1046 // CHECK-NEXT: // Rule ID {{[0-9]+}}
1047 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/TargetOpcode::COPY,
1048 // CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC GPR32*/1,
1049 // CHECK-NEXT: GIR_Done,
1050 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
1051 // Closing the G_BITCAST group.
1052 // OPT-NEXT: GIM_Reject,
1053 // OPT-NEXT: GIR_Done,
1054 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
1055 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
1056 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
990 // NOOPT-NEXT: // MIs[0] dst
991 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
992 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
993 // NOOPT-NEXT: // MIs[0] src1
994 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/1, /*Type*/GILLT_s32,
995 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::FPR32RegClassID,
996 // NOOPT-NEXT: // (bitconvert:{ *:[i32] } FPR32:{ *:[f32] }:$src1) => (COPY_TO_REGCLASS:{ *:[i32] } FPR32:{ *:[f32] }:$src1, GPR32:{ *:[i32] })
997 // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/TargetOpcode::COPY,
998 // NOOPT-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC GPR32*/1,
999 // NOOPT-NEXT: // GIR_Coverage, 24,
1000 // NOOPT-NEXT: GIR_Done,
1001 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
10571002
10581003 def : Pat<(i32 (bitconvert FPR32:$src1)),
10591004 (COPY_TO_REGCLASS FPR32:$src1, GPR32)>;
10601005
1061
1062
10631006 //===- Test a simple pattern with just a leaf immediate. ------------------===//
1064
1065 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
1066 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
1007 //
1008 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
1009 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
10671010 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
1068 // OPT-NEXT: // No instruction predicates
1069 // CHECK-NEXT: // MIs[0] dst
1070 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
1071 // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
1072 // CHECK-NEXT: // MIs[0] Operand 1
1073 // CHECK-NEXT: // No operand predicates
1074 // CHECK-NEXT: // (imm:{ *:[i32] }):$imm => (MOVimm:{ *:[i32] } (imm:{ *:[i32] }):$imm)
1075 // CHECK-NEXT: // Rule ID {{[0-9]+}}
1076 // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm,
1077 // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
1078 // CHECK-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
1079 // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
1080 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
1081 // CHECK-NEXT: GIR_Done,
1082 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
1083 // OPT-NEXT: GIM_Reject,
1084 // OPT-NEXT: GIR_Done,
1085 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
1011 // NOOPT-NEXT: // MIs[0] dst
1012 // NOOPT-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32,
1013 // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID,
1014 // NOOPT-NEXT: // MIs[0] Operand 1
1015 // NOOPT-NEXT: // No operand predicates
1016 // NOOPT-NEXT: // (imm:{ *:[i32] }):$imm => (MOVimm:{ *:[i32] } (imm:{ *:[i32] }):$imm)
1017 // NOOPT-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm,
1018 // NOOPT-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
1019 // NOOPT-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
1020 // NOOPT-NEXT: GIR_EraseFromParent, /*InsnID*/0,
1021 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
1022 // NOOPT-NEXT: // GIR_Coverage, 16,
1023 // NOOPT-NEXT: GIR_Done,
1024 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
10861025
10871026 def MOVimm : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, imm:$imm)]>;
1088
1089
10901027
10911028 def fpimmz : FPImmLeafisExactlyValue(0.0); }]>;
10921029 def MOVfpimmz : I<(outs FPR32:$dst), (ins f32imm:$imm), [(set FPR32:$dst, fpimmz:$imm)]>;
10931030
1094
1095
10961031 //===- Test a pattern with an MBB operand. --------------------------------===//
1097
1098 // OPT-NEXT: GIM_Try, /*On fail goto*//*Label [[GRP_LABEL_NUM:[0-9]+]]*/ [[GRP_LABEL:[0-9]+]],
1099 // OPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BR,
1100 // CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
1101 // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/1,
1032 //
1033 // NOOPT-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]],
1034 // NOOPT-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/1,
11021035 // NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BR,
1103 // OPT-NEXT: // No instruction predicates
1104 // CHECK-NEXT: // MIs[0] target
1105 // CHECK-NEXT: GIM_CheckIsMBB, /*MI*/0, /*Op*/0,
1106 // CHECK-NEXT: // (br (bb:{ *:[Other] }):$target) => (BR (bb:{ *:[Other] }):$target)
1107 // CHECK-NEXT: // Rule ID {{[0-9]+}}
1108 // CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::BR,
1109 // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
1110 // CHECK-NEXT: GIR_Done,
1111 // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
1112 // Closing the G_BR group.
1113 // OPT-NEXT: GIM_Reject,
1114 // OPT-NEXT: GIR_Done,
1115 // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]]
1036 // NOOPT-NEXT: // MIs[0] target
1037 // NOOPT-NEXT: GIM_CheckIsMBB, /*MI*/0, /*Op*/0,
1038 // NOOPT-NEXT: // (br (bb:{ *:[Other] }):$target) => (BR (bb:{ *:[Other] }):$target)
1039 // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::BR,
1040 // NOOPT-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
1041 // NOOPT-NEXT: // GIR_Coverage, 18,
1042 // NOOPT-NEXT: GIR_Done,
1043 // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]]
11161044
11171045 def BR : I<(outs), (ins unknown:$target),
11181046 [(br bb:$target)]>;
11191047
1120 // CHECK-NEXT: GIM_Reject,
1121 // CHECK-NEXT: };
1122 // CHECK-NEXT: return MatchTable0;
1048 // NOOPT-NEXT: GIM_Reject,
1049 // NOOPT-NEXT: };
1050 // NOOPT-NEXT: return MatchTable0;
9999 LLT Ty;
100100
101101 public:
102 LLTCodeGen() = default;
102103 LLTCodeGen(const LLT &Ty) : Ty(Ty) {}
103104
104105 std::string getCxxEnumValue() const {
400401 /// A bitfield of RecordFlagsBits flags.
401402 unsigned Flags;
402403
404 /// The actual run-time value, if known
405 int64_t RawValue;
406
403407 MatchTableRecord(Optional LabelID_, StringRef EmitStr,
404 unsigned NumElements, unsigned Flags)
408 unsigned NumElements, unsigned Flags,
409 int64_t RawValue = std::numeric_limits::min())
405410 : LabelID(LabelID_.hasValue() ? LabelID_.getValue() : ~0u),
406 EmitStr(EmitStr), NumElements(NumElements), Flags(Flags) {
411 EmitStr(EmitStr), NumElements(NumElements), Flags(Flags),
412 RawValue(RawValue) {
413
407414 assert((!LabelID_.hasValue() || LabelID != ~0u) &&
408415 "This value is reserved for non-labels");
409416 }
417 MatchTableRecord(const MatchTableRecord &Other) = default;
418 MatchTableRecord(MatchTableRecord &&Other) = default;
419
420 /// Useful if a Match Table Record gets optimized out
421 void turnIntoComment() {
422 Flags |= MTRF_Comment;
423 Flags &= ~MTRF_CommaFollows;
424 NumElements = 0;
425 }
426
427 /// For Jump Table generation purposes
428 bool operator<(const MatchTableRecord &Other) const {
429 return RawValue < Other.RawValue;
430 }
431 int64_t getRawValue() const { return RawValue; }
410432
411433 void emit(raw_ostream &OS, bool LineBreakNextAfterThis,
412434 const MatchTable &Table) const;
452474 return MatchTableRecord(None, NamedValue, 1,
453475 MatchTableRecord::MTRF_CommaFollows);
454476 }
477 static MatchTableRecord NamedValue(StringRef NamedValue, int64_t RawValue) {
478 return MatchTableRecord(None, NamedValue, 1,
479 MatchTableRecord::MTRF_CommaFollows, RawValue);
480 }
455481 static MatchTableRecord NamedValue(StringRef Namespace,
456482 StringRef NamedValue) {
457483 return MatchTableRecord(None, (Namespace + "::" + NamedValue).str(), 1,
458484 MatchTableRecord::MTRF_CommaFollows);
485 }
486 static MatchTableRecord NamedValue(StringRef Namespace, StringRef NamedValue,
487 int64_t RawValue) {
488 return MatchTableRecord(None, (Namespace + "::" + NamedValue).str(), 1,
489 MatchTableRecord::MTRF_CommaFollows, RawValue);
459490 }
460491 static MatchTableRecord IntValue(int64_t IntValue) {
461492 return MatchTableRecord(None, llvm::to_string(IntValue), 1,
585616 class Matcher {
586617 public:
587618 virtual ~Matcher() = default;
619 virtual void optimize() {}
588620 virtual void emit(MatchTable &Table) = 0;
589 virtual std::unique_ptr forgetFirstCondition() = 0;
621
622 virtual bool hasFirstCondition() const = 0;
623 virtual const PredicateMatcher &getFirstCondition() const = 0;
624 virtual std::unique_ptr popFirstCondition() = 0;
590625 };
591626
592627 MatchTable MatchTable::buildTable(ArrayRef Rules,
598633 return Table << MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak;
599634 }
600635
601 class GroupMatcher : public Matcher {
602 SmallVector, 8> Conditions;
603 SmallVector Rules;
604
605 public:
606 void addCondition(std::unique_ptr &&Predicate) {
607 Conditions.emplace_back(std::move(Predicate));
608 }
609 void addRule(Matcher &Rule) { Rules.push_back(&Rule); }
610 const std::unique_ptr &conditions_back() const {
611 return Conditions.back();
612 }
613 bool lastConditionMatches(const PredicateMatcher &Predicate) const;
614 bool conditions_empty() const { return Conditions.empty(); }
615 void clear() {
616 Conditions.clear();
617 Rules.clear();
618 }
636 class GroupMatcher final : public Matcher {
637 /// Conditions that form a common prefix of all the matchers contained.
638 SmallVector, 1> Conditions;
639
640 /// All the nested matchers, sharing a common prefix.
641 std::vector Matchers;
642
643 /// An owning collection for any auxiliary matchers created while optimizing
644 /// nested matchers contained.
645 std::vector> MatcherStorage;
646
647 public:
648 /// Add a matcher to the collection of nested matchers if it meets the
649 /// requirements, and return true. If it doesn't, do nothing and return false.
650 ///
651 /// Expected to preserve its argument, so it could be moved out later on.
652 bool addMatcher(Matcher &Candidate);
653
654 /// Mark the matcher as fully-built and ensure any invariants expected by both
655 /// optimize() and emit(...) methods. Generally, both sequences of calls
656 /// are expected to lead to a sensible result:
657 ///
658 /// addMatcher(...)*; finalize(); optimize(); emit(...); and
659 /// addMatcher(...)*; finalize(); emit(...);
660 ///
661 /// or generally
662 ///
663 /// addMatcher(...)*; finalize(); { optimize()*; emit(...); }*
664 ///
665 /// Multiple calls to optimize() are expected to be handled gracefully, though
666 /// optimize() is not expected to be idempotent. Multiple calls to finalize()
667 /// aren't generally supported. emit(...) is expected to be non-mutating and
668 /// producing the exact same results upon repeated calls.
669 ///
670 /// addMatcher() calls after the finalize() call are not supported.
671 ///
672 /// finalize() and optimize() are both allowed to mutate the contained
673 /// matchers, so moving them out after finalize() is not supported.
674 void finalize();
675 void optimize() override {}
619676 void emit(MatchTable &Table) override;
620677
621 std::unique_ptr forgetFirstCondition() override {
622 // We shouldn't need to mess up with groups, since we
623 // should have merged everything shareable upfront.
624 // If we start to look into reordering predicates,
625 // we may want to reconsider this.
626 assert(0 && "Groups should be formed maximal for now");
627 llvm_unreachable("No need for this for now");
628 }
678 /// Could be used to move out the matchers added previously, unless finalize()
679 /// has been already called. If any of the matchers are moved out, the group
680 /// becomes safe to destroy, but not safe to re-use for anything else.
681 iterator_range::iterator> matchers() {
682 return make_range(Matchers.begin(), Matchers.end());
683 }
684 size_t size() const { return Matchers.size(); }
685 bool empty() const { return Matchers.empty(); }
686
687 std::unique_ptr popFirstCondition() override {
688 assert(!Conditions.empty() &&
689 "Trying to pop a condition from a condition-less group");
690 std::unique_ptr P = std::move(Conditions.front());
691 Conditions.erase(Conditions.begin());
692 return P;
693 }
694 const PredicateMatcher &getFirstCondition() const override {
695 assert(!Conditions.empty() &&
696 "Trying to get a condition from a condition-less group");
697 return *Conditions.front();
698 }
699 bool hasFirstCondition() const override { return !Conditions.empty(); }
700
701 private:
702 /// See if a candidate matcher could be added to this group solely by
703 /// analyzing its first condition.
704 bool candidateConditionMatches(const PredicateMatcher &Predicate) const;
629705 };
630706
631707 /// Generates code to check that a match rule matches.
639715 /// FIXME: This currently supports a single match position but could be
640716 /// extended to support multiple positions to support div/rem fusion or
641717 /// load-multiple instructions.
642 std::vector> Matchers;
718 using MatchersTy = std::vector> ;
719 MatchersTy Matchers;
643720
644721 /// A list of actions that need to be taken when all predicates in this rule
645722 /// have succeeded.
646723 ActionList Actions;
647724
648 using DefinedInsnVariablesMap =
649 std::map;
650
651 /// A map of instruction matchers to the local variables created by
652 /// emitCaptureOpcodes().
725 using DefinedInsnVariablesMap = std::map;
726
727 /// A map of instruction matchers to the local variables
653728 DefinedInsnVariablesMap InsnVariableIDs;
654729
655 using MutatableInsnSet = SmallPtrSet<const InstructionMatcher *, 4>;
730 using MutatableInsnSet = SmallPtrSet<InstructionMatcher *, 4>;
656731
657732 // The set of instruction matchers that have not yet been claimed for mutation
658733 // by a BuildMI.
662737 /// the renderers.
663738 StringMap DefinedOperands;
664739
665 /// ID for the next instruction variable defined with defineInsnVar()
740 /// ID for the next instruction variable defined with implicitlyDefineInsnVar()
666741 unsigned NextInsnVarID;
667742
668743 /// ID for the next output instruction allocated with allocateOutputInsnID()
672747 unsigned NextTempRegID;
673748
674749 std::vector RequiredFeatures;
750 std::vector> EpilogueMatchers;
675751
676752 ArrayRef SrcLoc;
677753
705781 action_iterator insertAction(action_iterator InsertPt, Args &&... args);
706782
707783 /// Define an instruction without emitting any code to do so.
708 /// This is used for the root of the match.
709 unsigned implicitlyDefineInsnVar(const InstructionMatcher &Matcher);
710 void clearImplicitMap() {
711 NextInsnVarID = 0;
712 InsnVariableIDs.clear();
713 };
714 /// Define an instruction and emit corresponding state-machine opcodes.
715 unsigned defineInsnVar(MatchTable &Table, const InstructionMatcher &Matcher,
716 unsigned InsnVarID, unsigned OpIdx);
717 unsigned getInsnVarID(const InstructionMatcher &InsnMatcher) const;
784 unsigned implicitlyDefineInsnVar(InstructionMatcher &Matcher);
785
786 unsigned getInsnVarID(InstructionMatcher &InsnMatcher) const;
718787 DefinedInsnVariablesMap::const_iterator defined_insn_vars_begin() const {
719788 return InsnVariableIDs.begin();
720789 }
736805 mutatable_insns() const {
737806 return make_range(mutatable_insns_begin(), mutatable_insns_end());
738807 }
739 void reserveInsnMatcherForMutation(const InstructionMatcher *InsnMatcher) {
808 void reserveInsnMatcherForMutation(InstructionMatcher *InsnMatcher) {
740809 bool R = MutatableInsns.erase(InsnMatcher);
741810 assert(R && "Reserving a mutatable insn that isn't available");
742811 (void)R;
764833 return I->second;
765834 }
766835
767 const InstructionMatcher &getInstructionMatcher(StringRef SymbolicName) const;
836 InstructionMatcher &getInstructionMatcher(StringRef SymbolicName) const;
768837 const OperandMatcher &getOperandMatcher(StringRef Name) const;
769838
770 void emitCaptureOpcodes(MatchTable &Table);
771
839 void optimize() override;
772840 void emit(MatchTable &Table) override;
773841
774842 /// Compare the priority of this object and B.
780848 /// matcher.
781849 unsigned countRendererFns() const;
782850
783 std::unique_ptr forgetFirstCondition() override;
851 std::unique_ptr popFirstCondition() override;
852 const PredicateMatcher &getFirstCondition() const override;
853 LLTCodeGen getFirstConditionAsRootType();
854 bool hasFirstCondition() const override;
855 unsigned getNumOperands() const;
784856
785857 // FIXME: Remove this as soon as possible
786858 InstructionMatcher &insnmatchers_front() const { return *Matchers.front(); }
788860 unsigned allocateOutputInsnID() { return NextOutputInsnID++; }
789861 unsigned allocateTempRegID() { return NextTempRegID++; }
790862
863 iterator_range insnmatchers() {
864 return make_range(Matchers.begin(), Matchers.end());
865 }
791866 bool insnmatchers_empty() const { return Matchers.empty(); }
792867 void insnmatchers_pop_front() { Matchers.erase(Matchers.begin()); }
793868 };
798873
799874 template class PredicateListMatcher {
800875 private:
801 typedef std::vector> PredicateVec;
802 PredicateVec Predicates;
803
804876 /// Template instantiations should specialize this to return a string to use
805877 /// for the comment emitted when there are no predicates.
806878 std::string getNoPredicateComment() const;
807879
808 public:
809 /// Construct a new operand predicate and add it to the matcher.
880 protected:
881 using PredicatesTy = std::deque>;
882 PredicatesTy Predicates;
883
884 /// Track if the list of predicates was manipulated by one of the optimization
885 /// methods.
886 bool Optimized = false;
887
888 public:
889 /// Construct a new predicate and add it to the matcher.
810890 template
811 Optional addPredicate(Args&&... args) {
812 Predicates.emplace_back(
813 llvm::make_unique(std::forward(args)...));
814 return static_cast(Predicates.back().get());
815 }
816
817 typename PredicateVec::const_iterator predicates_begin() const {
891 Optional addPredicate(Args &&... args);
892
893 typename PredicatesTy::iterator predicates_begin() {
818894 return Predicates.begin();
819895 }
820 typename PredicateVec::const_iterator predicates_end() const {
896 typename PredicatesTy::iterator predicates_end() {
821897 return Predicates.end();
822898 }
823 iterator_rangeVec::const_iterator> predicates() const {
899 iterator_rangesTy::iterator> predicates() {
824900 return make_range(predicates_begin(), predicates_end());
825901 }
826 typename PredicateVec::size_type predicates_size() const {
902 typename PredicatesTy::size_type predicates_size() const {
827903 return Predicates.size();
828904 }
829905 bool predicates_empty() const { return Predicates.empty(); }
830906
831907 std::unique_ptr predicates_pop_front() {
832908 std::unique_ptr Front = std::move(Predicates.front());
833 Predicates.erase(Predicates.begin());
909 Predicates.pop_front();
910 Optimized = true;
834911 return Front;
912 }
913
914 void prependPredicate(std::unique_ptr &&Predicate) {
915 Predicates.push_front(std::move(Predicate));
916 }
917
918 void eraseNullPredicates() {
919 const auto NewEnd =
920 std::stable_partition(Predicates.begin(), Predicates.end(),
921 std::logical_not>());
922 if (NewEnd != Predicates.begin()) {
923 Predicates.erase(Predicates.begin(), NewEnd);
924 Optimized = true;
925 }
835926 }
836927
837928 /// Emit MatchTable opcodes that tests whether all the predicates are met.
838929 template
839 void emitPredicateListOpcodes(MatchTable &Table, Args &&... args) const {
840 if (Predicates.empty()) {
930 void emitPredicateListOpcodes(MatchTable &Table, Args &&... args) {
931 if (Predicates.empty() && !Optimized) {
841932 Table << MatchTable::Comment(getNoPredicateComment())
842933 << MatchTable::LineBreak;
843934 return;
844935 }
845936
846 unsigned OpIdx = (*predicates_begin())->getOpIdx();
847 (void)OpIdx;
848 for (const auto &Predicate : predicates()) {
849 assert(Predicate->getOpIdx() == OpIdx &&
850 "Checks touch different operands?");
937 for (const auto &Predicate : predicates())
851938 Predicate->emitPredicateOpcodes(Table, std::forward(args)...);
852 }
853939 }
854940 };
855941
867953 /// are currently not compared between each other.
868954 enum PredicateKind {
869955 IPM_Opcode,
956 IPM_NumOperands,
870957 IPM_ImmPredicate,
871958 IPM_AtomicOrderingMMO,
872959 IPM_MemoryLLTSize,
892979 PredicateMatcher(PredicateKind Kind, unsigned InsnVarID, unsigned OpIdx = ~0)
893980 : Kind(Kind), InsnVarID(InsnVarID), OpIdx(OpIdx) {}
894981
982 unsigned getInsnVarID() const { return InsnVarID; }
895983 unsigned getOpIdx() const { return OpIdx; }
984
896985 virtual ~PredicateMatcher() = default;
897986 /// Emit MatchTable opcodes that check the predicate for the given operand.
898987 virtual void emitPredicateOpcodes(MatchTable &Table,
901990 PredicateKind getKind() const { return Kind; }
902991
903992 virtual bool isIdentical(const PredicateMatcher &B) const {
904 if (InsnVarID != 0 || OpIdx != (unsigned)~0) {
905 // We currently don't hoist the record of instruction properly.
906 // Therefore we can only work on the orig instruction (InsnVarID
907 // == 0).
908 LLVM_DEBUG(dbgs() << "Non-zero instr ID not supported yet\n");
909 return false;
910 }
911993 return B.getKind() == getKind() && InsnVarID == B.InsnVarID &&
912994 OpIdx == B.OpIdx;
913995 }
996
997 virtual bool isIdenticalDownToValue(const PredicateMatcher &B) const {
998 return hasValue() && PredicateMatcher::isIdentical(B);
999 }
1000
1001 virtual MatchTableRecord getValue() const {
1002 assert(hasValue() && "Can not get a value of a value-less predicate!");
1003 llvm_unreachable("Not implemented yet");
1004 }
1005 virtual bool hasValue() const { return false; }
1006
1007 /// Report the maximum number of temporary operands needed by the predicate
1008 /// matcher.
1009 virtual unsigned countRendererFns() const { return 0; }
9141010 };
9151011
9161012 /// Generates code to check a predicate of an operand.
9261022 : PredicateMatcher(Kind, InsnVarID, OpIdx) {}
9271023 virtual ~OperandPredicateMatcher() {}
9281024
929 /// Emit MatchTable opcodes to capture instructions into the MIs table.
930 ///
931 /// Only InstructionOperandMatcher needs to do anything for this method the
932 /// rest just walk the tree.
933 virtual void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule) const {}
934
9351025 /// Compare the priority of this object and B.
9361026 ///
9371027 /// Returns true if this object is more important than B.
9381028 virtual bool isHigherPriorityThan(const OperandPredicateMatcher &B) const;
939
940 /// Report the maximum number of temporary operands needed by the predicate
941 /// matcher.
942 virtual unsigned countRendererFns() const { return 0; }
9431029 };
9441030
9451031 template <>
9581044 : OperandPredicateMatcher(OPM_SameOperand, InsnVarID, OpIdx),
9591045 MatchingName(MatchingName) {}
9601046
961 static bool classof(const OperandPredicateMatcher *P) {
1047 static bool classof(const PredicateMatcher *P) {
9621048 return P->getKind() == OPM_SameOperand;
9631049 }
9641050
9651051 void emitPredicateOpcodes(MatchTable &Table,
9661052 RuleMatcher &Rule) const override;
1053
1054 bool isIdentical(const PredicateMatcher &B) const override {
1055 return OperandPredicateMatcher::isIdentical(B) &&
1056 MatchingName == cast(&B)->MatchingName;
1057 }
9671058 };
9681059
9691060 /// Generates code to check that an operand is a particular LLT.
9721063 LLTCodeGen Ty;
9731064
9741065 public:
1066 static std::map TypeIDValues;
1067
1068 static void initTypeIDValuesMap() {
1069 TypeIDValues.clear();
1070
1071 unsigned ID = 0;
1072 for (const LLTCodeGen LLTy : KnownTypes)
1073 TypeIDValues[LLTy] = ID++;
1074 }
1075
9751076 LLTOperandMatcher(unsigned InsnVarID, unsigned OpIdx, const LLTCodeGen &Ty)
9761077 : OperandPredicateMatcher(OPM_LLT, InsnVarID, OpIdx), Ty(Ty) {
9771078 KnownTypes.insert(Ty);
9841085 return OperandPredicateMatcher::isIdentical(B) &&
9851086 Ty == cast(&B)->Ty;
9861087 }
1088 MatchTableRecord getValue() const override {
1089 const auto VI = TypeIDValues.find(Ty);
1090 if (VI == TypeIDValues.end())
1091 return MatchTable::NamedValue(getTy().getCxxEnumValue());
1092 return MatchTable::NamedValue(getTy().getCxxEnumValue(), VI->second);
1093 }
1094 bool hasValue() const override {
1095 if (TypeIDValues.size() != KnownTypes.size())
1096 initTypeIDValuesMap();
1097 return TypeIDValues.count(Ty);
1098 }
1099
1100 LLTCodeGen getTy() const { return Ty; }
9871101
9881102 void emitPredicateOpcodes(MatchTable &Table,
9891103 RuleMatcher &Rule) const override {
9901104 Table << MatchTable::Opcode("GIM_CheckType") << MatchTable::Comment("MI")
9911105 << MatchTable::IntValue(InsnVarID) << MatchTable::Comment("Op")
9921106 << MatchTable::IntValue(OpIdx) << MatchTable::Comment("Type")
993 << MatchTable::NamedValue(Ty.getCxxEnumValue())
994 << MatchTable::LineBreak;
1107 << getValue() << MatchTable::LineBreak;
9951108 }
9961109 };
1110
1111 std::map LLTOperandMatcher::TypeIDValues;
9971112
9981113 /// Generates code to check that an operand is a pointer to any address space.
9991114 ///
12261341 assert(SymbolicName.empty() && "Operand already has a symbolic name");
12271342 SymbolicName = Name;
12281343 }
1229 unsigned getOperandIndex() const { return OpIdx; }
1344
1345 /// Construct a new operand predicate and add it to the matcher.
1346 template
1347 Optional addPredicate(Args &&... args) {
1348 if (isSameAsAnotherOperand())
1349 return None;
1350 Predicates.emplace_back(llvm::make_unique(
1351 getInsnVarID(), getOpIdx(), std::forward(args)...));
1352 return static_cast(Predicates.back().get());
1353 }
1354
1355 unsigned getOpIdx() const { return OpIdx; }
12301356 unsigned getInsnVarID() const;
12311357
12321358 std::string getOperandExpr(unsigned InsnVarID) const {
12391365 Error addTypeCheckPredicate(const TypeSetByHwMode &VTy,
12401366 bool OperandIsAPointer);
12411367
1242 /// Emit MatchTable opcodes to capture instructions into the MIs table.
1243 void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule) const {
1244 for (const auto &Predicate : predicates())
1245 Predicate->emitCaptureOpcodes(Table, Rule);
1246 }
1247
12481368 /// Emit MatchTable opcodes that test whether the instruction named in
12491369 /// InsnVarID matches all the predicates and all the operands.
1250 void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule) const {
1251 std::string Comment;
1252 raw_string_ostream CommentOS(Comment);
1253 CommentOS << "MIs[" << getInsnVarID() << "] ";
1254 if (SymbolicName.empty())
1255 CommentOS << "Operand " << OpIdx;
1256 else
1257 CommentOS << SymbolicName;
1258 Table << MatchTable::Comment(CommentOS.str()) << MatchTable::LineBreak;
1370 void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule) {
1371 if (!Optimized) {
1372 std::string Comment;
1373 raw_string_ostream CommentOS(Comment);
1374 CommentOS << "MIs[" << getInsnVarID() << "] ";
1375 if (SymbolicName.empty())
1376 CommentOS << "Operand " << OpIdx;
1377 else
1378 CommentOS << SymbolicName;
1379 Table << MatchTable::Comment(CommentOS.str()) << MatchTable::LineBreak;
1380 }
12591381
12601382 emitPredicateListOpcodes(Table, Rule);
12611383 }
12631385 /// Compare the priority of this object and B.
12641386 ///
12651387 /// Returns true if this object is more important than B.
1266 bool isHigherPriorityThan(const OperandMatcher &B) const {
1388 bool isHigherPriorityThan(OperandMatcher &B) {
12671389 // Operand matchers involving more predicates have higher priority.
12681390 if (predicates_size() > B.predicates_size())
12691391 return true;
12711393 return false;
12721394
12731395 // This assumes that predicates are added in a consistent order.
1274 for (const auto &Predicate : zip(predicates(), B.predicates())) {
1396 for (auto &&Predicate : zip(predicates(), B.predicates())) {
12751397 if (std::get<0>(Predicate)->isHigherPriorityThan(*std::get<1>(Predicate)))
12761398 return true;
12771399 if (std::get<1>(Predicate)->isHigherPriorityThan(*std::get<0>(Predicate)))
12831405
12841406 /// Report the maximum number of temporary operands needed by the operand
12851407 /// matcher.
1286 unsigned countRendererFns() const {
1408 unsigned countRendererFns() {
12871409 return std::accumulate(
12881410 predicates().begin(), predicates().end(), 0,
12891411 [](unsigned A,
12961418 return AllocatedTemporariesBaseID;
12971419 }
12981420
1299 bool isSameAsAnotherOperand() const {
1421 bool isSameAsAnotherOperand() {
13001422 for (const auto &Predicate : predicates())
13011423 if (isa(Predicate))
13021424 return true;
13031425 return false;
13041426 }
13051427 };
1306
1307 // Specialize OperandMatcher::addPredicate() to refrain from adding redundant
1308 // predicates.
1309 template <>
1310 template
1311 Optional
1312 PredicateListMatcher::addPredicate(Args &&... args) {
1313 auto *OpMatcher = static_cast(this);
1314 if (static_cast(this)->isSameAsAnotherOperand())
1315 return None;
1316 Predicates.emplace_back(llvm::make_unique(OpMatcher->getInsnVarID(),
1317 OpMatcher->getOperandIndex(),
1318 std::forward(args)...));
1319 return static_cast(Predicates.back().get());
1320 }
13211428
13221429 Error OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode &VTy,
13231430 bool OperandIsAPointer) {
13621469 isHigherPriorityThan(const InstructionPredicateMatcher &B) const {
13631470 return Kind < B.Kind;
13641471 };
1365
1366 /// Report the maximum number of temporary operands needed by the predicate
1367 /// matcher.
1368 virtual unsigned countRendererFns() const { return 0; }
13691472 };
13701473
13711474 template <>
13721475 std::string
1373 PredicateListMatcher<InstructionPredicateMatcher>::getNoPredicateComment() const {
1476 PredicateListMatcher<PredicateMatcher>::getNoPredicateComment() const {
13741477 return "No instruction predicates";
13751478 }
13761479
13791482 protected:
13801483 const CodeGenInstruction *I;
13811484
1382 public:
1485 static DenseMap OpcodeValues;
1486
1487 public:
1488 static void initOpcodeValuesMap(const CodeGenTarget &Target) {
1489 OpcodeValues.clear();
1490
1491 unsigned OpcodeValue = 0;
1492 for (const CodeGenInstruction *I : Target.getInstructionsByEnumValue())
1493 OpcodeValues[I] = OpcodeValue++;
1494 }
1495
13831496 InstructionOpcodeMatcher(unsigned InsnVarID, const CodeGenInstruction *I)
13841497 : InstructionPredicateMatcher(IPM_Opcode, InsnVarID), I(I) {}
13851498
13911504 return InstructionPredicateMatcher::isIdentical(B) &&
13921505 I == cast(&B)->I;
13931506 }
1507 MatchTableRecord getValue() const override {
1508 const auto VI = OpcodeValues.find(I);
1509 if (VI != OpcodeValues.end())
1510 return MatchTable::NamedValue(I->Namespace, I->TheDef->getName(),
1511 VI->second);
1512 return MatchTable::NamedValue(I->Namespace, I->TheDef->getName());
1513 }
1514 bool hasValue() const override { return OpcodeValues.count(I); }
13941515
13951516 void emitPredicateOpcodes(MatchTable &Table,
13961517 RuleMatcher &Rule) const override {
13971518 Table << MatchTable::Opcode("GIM_CheckOpcode") << MatchTable::Comment("MI")
1398 << MatchTable::IntValue(InsnVarID)
1399 << MatchTable::NamedValue(I->Namespace, I->TheDef->getName())
1519 << MatchTable::IntValue(InsnVarID) << getValue()
14001520 << MatchTable::LineBreak;
14011521 }
14021522
14231543 bool isConstantInstruction() const {
14241544 return I->TheDef->getName() == "G_CONSTANT";
14251545 }
1546
1547 unsigned getNumOperands() const { return I->Operands.size(); }
1548
1549 StringRef getOperandType(unsigned OpIdx) const {
1550 return I->Operands[OpIdx].OperandType;
1551 }
14261552 };
1553
1554 DenseMap
1555 InstructionOpcodeMatcher::OpcodeValues;
14271556
14281557 /// Generates code to check that this instruction is a constant whose value
14291558 /// meets an immediate predicate.
15021631 : InstructionPredicateMatcher(IPM_AtomicOrderingMMO, InsnVarID),
15031632 Order(Order), Comparator(Comparator) {}
15041633
1505 static bool classof(const InstructionPredicateMatcher *P) {
1634 static bool classof(const PredicateMatcher *P) {
15061635 return P->getKind() == IPM_AtomicOrderingMMO;
1636 }
1637
1638 bool isIdentical(const PredicateMatcher &B) const override {
1639 if (!InstructionPredicateMatcher::isIdentical(B))
1640 return false;
1641 const auto &R = *cast(&B);
1642 return Order == R.Order && Comparator == R.Comparator;
15071643 }
15081644
15091645 void emitPredicateOpcodes(MatchTable &Table,
16041740 /// Typical predicates include:
16051741 /// * Has a specific opcode.
16061742 /// * Has an nsw/nuw flag or doesn't.
1607 class InstructionMatcher
1608 : public PredicateListMatcherPredicateMatcher> {
1743 class InstructionMatcher final : public PredicateListMatcher<PredicateMatcher> {
16091744 protected:
16101745 typedef std::vector> OperandVec;
16111746
16261761 InsnVarID = Rule.implicitlyDefineInsnVar(*this);
16271762 }
16281763
1764 /// Construct a new instruction predicate and add it to the matcher.
1765 template
1766 Optional addPredicate(Args &&... args) {
1767 Predicates.emplace_back(
1768 llvm::make_unique(getInsnVarID(), std::forward(args)...));
1769 return static_cast(Predicates.back().get());
1770 }
1771
16291772 RuleMatcher &getRuleMatcher() const { return Rule; }
16301773
1631 unsigned getVarID() const { return InsnVarID; }
1774 unsigned getInsnVarID() const { return InsnVarID; }
16321775
16331776 /// Add an operand to the matcher.
16341777 OperandMatcher &addOperand(unsigned OpIdx, const std::string &SymbolicName,
16441787 OperandMatcher &getOperand(unsigned OpIdx) {
16451788 auto I = std::find_if(Operands.begin(), Operands.end(),
16461789 [&OpIdx](const std::unique_ptr &X) {
1647 return X->getOperandIndex() == OpIdx;
1790 return X->getOpIdx() == OpIdx;
16481791 });
16491792 if (I != Operands.end())
16501793 return **I;
16671810
16681811 void pop_front() { Operands.erase(Operands.begin()); }
16691812
1670 /// Emit MatchTable opcodes to check the shape of the match and capture
1671 /// instructions into the MIs table.
1672 void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule) {
1813 void optimize() {}
1814
1815 /// Emit MatchTable opcodes that test whether the instruction named in
1816 /// InsnVarName matches all the predicates and all the operands.
1817 void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule) {
16731818 Table << MatchTable::Opcode("GIM_CheckNumOperands")
16741819 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
16751820 << MatchTable::Comment("Expected")
16761821 << MatchTable::IntValue(getNumOperands()) << MatchTable::LineBreak;
1677 for (const auto &Operand : Operands)
1678 Operand->emitCaptureOpcodes(Table, Rule);
1679 }
1680
1681 /// Emit MatchTable opcodes that test whether the instruction named in
1682 /// InsnVarName matches all the predicates and all the operands.
1683 void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule) const {
1822
16841823 emitPredicateListOpcodes(Table, Rule);
1824
16851825 for (const auto &Operand : Operands)
16861826 Operand->emitPredicateOpcodes(Table, Rule);
16871827 }
16891829 /// Compare the priority of this object and B.
16901830 ///
16911831 /// Returns true if this object is more important than B.
1692 bool isHigherPriorityThan(const InstructionMatcher &B) const {
1832 bool isHigherPriorityThan(InstructionMatcher &B) {
16931833 // Instruction matchers involving more operands have higher priority.
16941834 if (Operands.size() > B.Operands.size())
16951835 return true;
16961836 if (Operands.size() < B.Operands.size())
16971837 return false;
16981838
1699 for (const auto &Predicate : zip(predicates(), B.predicates())) {
1700 if (std::get<0>(Predicate)->isHigherPriorityThan(*std::get<1>(Predicate)))
1839 for (auto &&P : zip(predicates(), B.predicates())) {
1840 auto L = static_cast(std::get<0>(P).get());
1841 auto R = static_cast(std::get<1>(P).get());
1842 if (L->isHigherPriorityThan(*R))
17011843 return true;
1702 if (std::get<1>(Predicate)->isHigherPriorityThan(*std::get<0>(Predicate)))
1844 if (R->isHigherPriorityThan(*L))
17031845 return false;
17041846 }
17051847
17151857
17161858 /// Report the maximum number of temporary operands needed by the instruction
17171859 /// matcher.
1718 unsigned countRendererFns() const {
1719 return std::accumulate(predicates().begin(), predicates().end(), 0,
1720 [](unsigned A,
1721 const std::unique_ptr
1722 &Predicate) {
1723 return A + Predicate->countRendererFns();
1724 }) +
1860 unsigned countRendererFns() {
1861 return std::accumulate(
1862 predicates().begin(), predicates().end(), 0,
1863 [](unsigned A,
1864 const std::unique_ptr &Predicate) {
1865 return A + Predicate->countRendererFns();
1866 }) +
17251867 std::accumulate(
17261868 Operands.begin(), Operands.end(), 0,
17271869 [](unsigned A, const std::unique_ptr &Operand) {
17291871 });
17301872 }
17311873
1732 bool isConstantInstruction() const {
1733 for (const auto &P : predicates())
1734 if (const InstructionOpcodeMatcher *Opcode =
1735 dyn_cast(P.get()))
1736 return Opcode->isConstantInstruction();
1737 return false;
1874 InstructionOpcodeMatcher &getOpcodeMatcher() {
1875 for (auto &P : predicates())
1876 if (auto *OpMatcher = dyn_cast(P.get()))
1877 return *OpMatcher;
1878 llvm_unreachable("Didn't find an opcode matcher");
1879 }
1880
1881 bool isConstantInstruction() {
1882 return getOpcodeMatcher().isConstantInstruction();
17381883 }
17391884 };
17401885
1741 template <>
1742 template
1743 Optional
1744 PredicateListMatcher::addPredicate(
1745 Args &&... args) {
1746 InstructionMatcher *InstMatcher = static_cast(this);
1747 Predicates.emplace_back(llvm::make_unique(InstMatcher->getVarID(),
1748 std::forward(args)...));
1749 return static_cast(Predicates.back().get());
1886 unsigned RuleMatcher::getNumOperands() const {
1887 return Matchers.front()->getNumOperands();
1888 }
1889
1890 LLTCodeGen RuleMatcher::getFirstConditionAsRootType() {
1891 InstructionMatcher &InsnMatcher = *Matchers.front();
1892 if (!InsnMatcher.predicates_empty())
1893 if (const auto *TM =
1894 dyn_cast(&**InsnMatcher.predicates_begin()))
1895 if (TM->getInsnVarID() == 0 && TM->getOpIdx() == 0)
1896 return TM->getTy();
1897 return {};
17501898 }
17511899
17521900 /// Generates code to check that the operand is a register defined by an
17741922
17751923 InstructionMatcher &getInsnMatcher() const { return *InsnMatcher; }
17761924
1777 void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
1778 unsigned InsnID =
1779 Rule.defineInsnVar(Table, *InsnMatcher, InsnVarID, getOpIdx());
1780 (void)InsnID;
1781 assert(InsnMatcher->getVarID() == InsnID &&
1782 "Mismatch between build and emit");
1783 InsnMatcher->emitCaptureOpcodes(Table, Rule);
1925 void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule) const {
1926 const unsigned NewInsnVarID = InsnMatcher->getInsnVarID();
1927 Table << MatchTable::Opcode("GIM_RecordInsn")
1928 << MatchTable::Comment("DefineMI")
1929 << MatchTable::IntValue(NewInsnVarID) << MatchTable::Comment("MI")
1930 << MatchTable::IntValue(getInsnVarID())
1931 << MatchTable::Comment("OpIdx") << MatchTable::IntValue(getOpIdx())
1932 << MatchTable::Comment("MIs[" + llvm::to_string(NewInsnVarID) + "]")
1933 << MatchTable::LineBreak;
17841934 }
17851935
17861936 void emitPredicateOpcodes(MatchTable &Table,
17871937 RuleMatcher &Rule) const override {
1938 emitCaptureOpcodes(Table, Rule);
17881939 InsnMatcher->emitPredicateOpcodes(Table, Rule);
17891940 }
17901941
18582009 Table << MatchTable::Opcode("GIR_Copy") << MatchTable::Comment("NewInsnID")
18592010 << MatchTable::IntValue(NewInsnID) << MatchTable::Comment("OldInsnID")
18602011 << MatchTable::IntValue(OldInsnVarID) << MatchTable::Comment("OpIdx")
1861 << MatchTable::IntValue(Operand.getOperandIndex())
2012 << MatchTable::IntValue(Operand.getOpIdx())
18622013 << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
18632014 }
18642015 };
18942045 << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID)
18952046 << MatchTable::Comment("OldInsnID")
18962047 << MatchTable::IntValue(OldInsnVarID) << MatchTable::Comment("OpIdx")
1897 << MatchTable::IntValue(Operand.getOperandIndex())
2048 << MatchTable::IntValue(Operand.getOpIdx())
18982049 << MatchTable::NamedValue(
18992050 (ZeroRegisterDef->getValue("Namespace")
19002051 ? ZeroRegisterDef->getValueAsString("Namespace")
19252076 const StringRef getSymbolicName() const { return SymbolicName; }
19262077
19272078 void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
1928 const InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
2079 InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
19292080 unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher);
19302081 Table << MatchTable::Opcode(Signed ? "GIR_CopyConstantAsSImm"
19312082 : "GIR_CopyConstantAsUImm")
19562107 const StringRef getSymbolicName() const { return SymbolicName; }
19572108
19582109 void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
1959 const InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
2110 InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
19602111 unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher);
19612112 Table << MatchTable::Opcode("GIR_CopyFConstantAsFPImm")
19622113 << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID)
19962147 << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID)
19972148 << MatchTable::Comment("OldInsnID")
19982149 << MatchTable::IntValue(OldInsnVarID) << MatchTable::Comment("OpIdx")
1999 << MatchTable::IntValue(Operand.getOperandIndex())
2150 << MatchTable::IntValue(Operand.getOpIdx())
20002151 << MatchTable::Comment("SubRegIdx")
20012152 << MatchTable::IntValue(SubReg->EnumValue)
20022153 << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
21452296 }
21462297
21472298 void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
2148 const InstructionMatcher &InsnMatcher =
2149 Rule.getInstructionMatcher(SymbolicName);
2299 InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
21502300 unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher);
21512301 Table << MatchTable::Opcode("GIR_CustomRenderer")
21522302 << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
21922342 private:
21932343 unsigned InsnID;
21942344 const CodeGenInstruction *I;
2195 const InstructionMatcher *Matched;
2345 InstructionMatcher *Matched;
21962346 std::vector> OperandRenderers;
21972347
21982348 /// True if the instruction can be built solely by mutating the opcode.
22072357 if (const auto *Copy = dyn_cast(&*Renderer.value())) {
22082358 const OperandMatcher &OM = Rule.getOperandMatcher(Copy->getSymbolicName());
22092359 if (Insn != &OM.getInstructionMatcher() ||
2210 OM.getOperandIndex() != Renderer.index())
2360 OM.getOpIdx() != Renderer.index())
22112361 return false;
22122362 } else
22132363 return false;
22242374 const CodeGenInstruction *getCGI() const { return I; }
22252375
22262376 void chooseInsnToMutate(RuleMatcher &Rule) {
2227 for (const auto *MutateCandidate : Rule.mutatable_insns()) {
2377 for (auto *MutateCandidate : Rule.mutatable_insns()) {
22282378 if (canMutate(Rule, MutateCandidate)) {
22292379 // Take the first one we're offered that we're able to mutate.
22302380 Rule.reserveInsnMatcherForMutation(MutateCandidate);
24162566 llvm::make_unique(std::forward(args)...));
24172567 }
24182568
2419 unsigned
2420 RuleMatcher::implicitlyDefineInsnVar(const InstructionMatcher &Matcher) {
2569 unsigned RuleMatcher::implicitlyDefineInsnVar(InstructionMatcher &Matcher) {
24212570 unsigned NewInsnVarID = NextInsnVarID++;
24222571 InsnVariableIDs[&Matcher] = NewInsnVarID;
24232572 return NewInsnVarID;
24242573 }
24252574
2426 unsigned RuleMatcher::defineInsnVar(MatchTable &Table,
2427 const InstructionMatcher &Matcher,
2428 unsigned InsnID, unsigned OpIdx) {
2429 unsigned NewInsnVarID = implicitlyDefineInsnVar(Matcher);
2430 Table << MatchTable::Opcode("GIM_RecordInsn")
2431 << MatchTable::Comment("DefineMI") << MatchTable::IntValue(NewInsnVarID)
2432 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnID)
2433 << MatchTable::Comment("OpIdx") << MatchTable::IntValue(OpIdx)
2434 << MatchTable::Comment("MIs[" + llvm::to_string(NewInsnVarID) + "]")
2435 << MatchTable::LineBreak;
2436 return NewInsnVarID;
2437 }
2438
2439 unsigned RuleMatcher::getInsnVarID(const InstructionMatcher &InsnMatcher) const {
2575 unsigned RuleMatcher::getInsnVarID(InstructionMatcher &InsnMatcher) const {
24402576 const auto &I = InsnVariableIDs.find(&InsnMatcher);
24412577 if (I != InsnVariableIDs.end())
24422578 return I->second;
24542590 OM.addPredicate(OM.getSymbolicName());
24552591 }
24562592
2457 const InstructionMatcher &
2593 InstructionMatcher &
24582594 RuleMatcher::getInstructionMatcher(StringRef SymbolicName) const {
24592595 for (const auto &I : InsnVariableIDs)
24602596 if (I.first->getSymbolicName() == SymbolicName)
24732609 return *I->second;
24742610 }
24752611
2476 /// Emit MatchTable opcodes to check the shape of the match and capture
2477 /// instructions into local variables.
2478 void RuleMatcher::emitCaptureOpcodes(MatchTable &Table) {
2479 assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet");
2480 unsigned InsnVarID = implicitlyDefineInsnVar(*Matchers.front());
2481 (void)InsnVarID;
2482 assert(Matchers.front()->getVarID() == InsnVarID &&
2483 "IDs differ between build and emit");
2484 Matchers.front()->emitCaptureOpcodes(Table, *this);
2485 }
2486
24872612 void RuleMatcher::emit(MatchTable &Table) {
24882613 if (Matchers.empty())
24892614 llvm_unreachable("Unexpected empty matcher!");
2490
2491 // Reset the ID generation so that the emitted IDs match the ones
2492 // we set while building the InstructionMatcher and such.
2493 clearImplicitMap();
24942615
24952616 // The representation supports rules that require multiple roots such as:
24962617 // %ptr(p0) = ...
25052626
25062627 unsigned LabelID = Table.allocateLabelID();
25072628 Table << MatchTable::Opcode("GIM_Try", +1)
2508 << MatchTable::Comment("On fail goto") << MatchTable::JumpTarget(LabelID)
2629 << MatchTable::Comment("On fail goto")
2630 << MatchTable::JumpTarget(LabelID)
2631 << MatchTable::Comment(("Rule ID " + Twine(RuleID) + " //").str())
25092632 << MatchTable::LineBreak;
25102633
25112634 if (!RequiredFeatures.empty()) {
25132636 << MatchTable::NamedValue(getNameForFeatureBitset(RequiredFeatures))
25142637 << MatchTable::LineBreak;
25152638 }
2516
2517 emitCaptureOpcodes(Table);
25182639
25192640 Matchers.front()->emitPredicateOpcodes(Table, *this);
25202641
25752696 }
25762697 }
25772698
2699 for (const auto &PM : EpilogueMatchers)
2700 PM->emitPredicateOpcodes(Table, *this);
2701
25782702 for (const auto &MA : Actions)
25792703 MA->emitActionOpcodes(Table, *this);
25802704
25812705 if (Table.isWithCoverage())
25822706 Table << MatchTable::Opcode("GIR_Coverage") << MatchTable::IntValue(RuleID)
2707 << MatchTable::LineBreak;
2708 else
2709 Table << MatchTable::Comment(("GIR_Coverage, " + Twine(RuleID) + ",").str())
25832710 << MatchTable::LineBreak;
25842711
25852712 Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak
26482775 RuleMatcher &Rule) const {
26492776 const OperandMatcher &OtherOM = Rule.getOperandMatcher(MatchingName);
26502777 unsigned OtherInsnVarID = Rule.getInsnVarID(OtherOM.getInstructionMatcher());
2651 assert(OtherInsnVarID == OtherOM.getInstructionMatcher().getVarID());
2778 assert(OtherInsnVarID == OtherOM.getInstructionMatcher().getInsnVarID());
26522779
26532780 Table << MatchTable::Opcode("GIM_CheckIsSameOperand")
26542781 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
26562783 << MatchTable::Comment("OtherMI")
26572784 << MatchTable::IntValue(OtherInsnVarID)
26582785 << MatchTable::Comment("OtherOpIdx")
2659 << MatchTable::IntValue(OtherOM.getOperandIndex())
2786 << MatchTable::IntValue(OtherOM.getOpIdx())
26602787 << MatchTable::LineBreak;
26612788 }
26622789
26992826 // Rule coverage information.
27002827 Optional RuleCoverage;
27012828
2829 void gatherOpcodeValues();
2830 void gatherTypeIDValues();
27022831 void gatherNodeEquivs();
27032832 Record *findNodeEquiv(Record *N) const;
27042833 const CodeGenInstruction *getEquivNode(Record &Equiv,
27492878
27502879 void declareSubtargetFeature(Record *Predicate);
27512880
2881 MatchTable buildMatchTable(MutableArrayRef Rules, bool Optimize,
2882 bool WithCoverage);
2883
2884 public:
27522885 /// Takes a sequence of \p Rules and group them based on the predicates
2753 /// they share. \p StorageGroupMatcher is used as a memory container
2886 /// they share. \p MatcherStorage is used as a memory container
27542887 /// for the group that are created as part of this process.
2755 /// The optimization process does not change the relative order of
2756 /// the rules. In particular, we don't try to share predicates if
2757 /// that means reordering the rules (e.g., we won't group R1 and R3
2758 /// in the following example as it would imply reordering R2 and R3
2759 /// => R1 p1, R2 p2, R3 p1).
27602888 ///
2761 /// What this optimization does looks like:
2889 /// What this optimization does looks like if GroupT = GroupMatcher:
27622890 /// Output without optimization:
27632891 /// \verbatim
27642892 /// # R1
27792907 /// # R2
27802908 /// # predicate C
27812909 /// \endverbatim
2782 std::vector optimizeRules(
2910 template
2911 static std::vector optimizeRules(
27832912 ArrayRef Rules,
2784 std::vector> &StorageGroupMatcher);
2785
2786 MatchTable buildMatchTable(MutableArrayRef Rules, bool Optimize,
2787 bool WithCoverage);
2913 std::vector> &MatcherStorage);
27882914 };
2915
2916 void GlobalISelEmitter::gatherOpcodeValues() {
2917 InstructionOpcodeMatcher::initOpcodeValuesMap(Target);
2918 }
2919
2920 void GlobalISelEmitter::gatherTypeIDValues() {
2921 LLTOperandMatcher::initTypeIDValuesMap();
2922 }
27892923
27902924 void GlobalISelEmitter::gatherNodeEquivs() {
27912925 assert(NodeEquivs.empty());
35213655 M.addAction(llvm::to_string(*P.getSrcPattern()) +
35223656 " => " +
35233657 llvm::to_string(*P.getDstPattern()));
3524 M.addAction("Rule ID " + llvm::to_string(M.getRuleID()));
35253658
35263659 if (auto Error = importRulePredicates(M, P.getPredicates()))
35273660 return std::move(Error);
37773910 << "}\n";
37783911 }
37793912
3913 template
37803914 std::vector GlobalISelEmitter::optimizeRules(
37813915 ArrayRef Rules,
3782 std::vectorGroupMatcher>> &StorageGroupMatcher) {
3916 std::vectorMatcher>> &MatcherStorage) {
3917
37833918 std::vector OptRules;
3784 // Start with a stupid grouping for now.
3785 std::unique_ptr CurrentGroup = make_unique();
3786 assert(CurrentGroup->conditions_empty());
3787 unsigned NbGroup = 0;
3919 std::unique_ptr CurrentGroup = make_unique();
3920 assert(CurrentGroup->empty() && "Newly created group isn't empty!");
3921 unsigned NumGroups = 0;
3922
3923 auto ProcessCurrentGroup = [&]() {
3924 if (CurrentGroup->empty())
3925 // An empty group is good to be reused:
3926 return;
3927
3928 // If the group isn't large enough to provide any benefit, move all the
3929 // added rules out of it and make sure to re-create the group to properly
3930 // re-initialize it:
3931 if (CurrentGroup->size() < 2)
3932 for (Matcher *M : CurrentGroup->matchers())
3933 OptRules.push_back(M);
3934 else {
3935 CurrentGroup->finalize();
3936 OptRules.push_back(CurrentGroup.get());
3937 MatcherStorage.emplace_back(std::move(CurrentGroup));
3938 ++NumGroups;
3939 }
3940 CurrentGroup = make_unique();
3941 };
37883942 for (Matcher *Rule : Rules) {
3789 std::unique_ptr Predicate = Rule->forgetFirstCondition();
3790 if (!CurrentGroup->conditions_empty() &&
3791 !CurrentGroup->lastConditionMatches(*Predicate)) {
3792 // Start a new group.
3793 ++NbGroup;
3794 OptRules.push_back(CurrentGroup.get());
3795 StorageGroupMatcher.emplace_back(std::move(CurrentGroup));
3796 CurrentGroup = make_unique();
3797 assert(CurrentGroup->conditions_empty());
3798 }
3799 if (CurrentGroup->conditions_empty())
3800 CurrentGroup->addCondition(std::move(Predicate));
3801 CurrentGroup->addRule(*Rule);
3802 }
3803 if (!CurrentGroup->conditions_empty()) {
3804 ++NbGroup;
3805 OptRules.push_back(CurrentGroup.get());
3806 StorageGroupMatcher.emplace_back(std::move(CurrentGroup));
3807 }
3808 LLVM_DEBUG(dbgs() << "NbGroup: " << NbGroup << "\n");
3943 // Greedily add as many matchers as possible to the current group:
3944 if (CurrentGroup->addMatcher(*Rule))
3945 continue;
3946
3947 ProcessCurrentGroup();
3948 assert(CurrentGroup->empty() && "A group wasn't properly re-initialized");
3949
3950 // Try to add the pending matcher to a newly created empty group:
3951 if (!CurrentGroup->addMatcher(*Rule))
3952 // If we couldn't add the matcher to an empty group, that group type
3953 // doesn't support that kind of matchers at all, so just skip it:
3954 OptRules.push_back(Rule);
3955 }
3956 ProcessCurrentGroup();
3957
3958 DEBUG(dbgs() << "NumGroups: " << NumGroups << "\n");
3959 assert(CurrentGroup->empty() && "The last group wasn't properly processed");
38093960 return OptRules;
38103961 }
38113962
38193970 if (!Optimize)
38203971 return MatchTable::buildTable(InputRules, WithCoverage);
38213972
3822 std::vector> StorageGroupMatcher;
3973 for (Matcher *Rule : InputRules)
3974 Rule->optimize();
3975
3976 std::vector> MatcherStorage;
38233977 std::vector OptRules =
3824 optimizeRules(InputRules, StorageGroupMatcher);
3978 optimizeRules(InputRules, MatcherStorage);
3979
3980 for (Matcher *Rule : OptRules)
3981 Rule->optimize();
38253982
38263983 return MatchTable::buildTable(OptRules, WithCoverage);
38273984 }
38403997 }
38413998 }
38423999 }
4000
4001 // Track the run-time opcode values
4002 gatherOpcodeValues();
4003 // Track the run-time LLT ID values
4004 gatherTypeIDValues();
38434005
38444006 // Track the GINodeEquiv definitions.
38454007 gatherNodeEquivs();
39294091
39304092 OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n"
39314093 << ", State(" << MaxTemporaries << "),\n"
3932 << "ISelInfo({TypeObjects, FeatureBitsets, ComplexPredicateFns, "
3933 "CustomRenderers})\n"
4094 << "ISelInfo(TypeObjects, NumTypeObjects, FeatureBitsets"
4095 << ", ComplexPredicateFns, CustomRenderers)\n"
39344096 << "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n\n";
39354097
39364098 OS << "#ifdef GET_GLOBALISEL_IMPL\n";
39724134 TypeObject.emitCxxEnumValue(OS);
39734135 OS << ",\n";
39744136 }
3975 OS << "};\n"
4137 OS << "};\n";
4138 OS << "const static size_t NumTypeObjects = " << TypeObjects.size() << ";\n"
39764139 << "const static LLT TypeObjects[] = {\n";
39774140 for (const auto &TypeObject : TypeObjects) {
39784141 OS << " ";
41514314 Predicate, SubtargetFeatureInfo(Predicate, SubtargetFeatures.size()));
41524315 }
41534316
4154 std::unique_ptr RuleMatcher::forgetFirstCondition() {
4317 void RuleMatcher::optimize() {
4318 for (auto &Item : InsnVariableIDs) {
4319 InstructionMatcher &InsnMatcher = *Item.first;
4320 for (auto &OM : InsnMatcher.operands()) {
4321 // Register Banks checks rarely fail, but often crash as targets usually
4322 // provide only partially defined RegisterBankInfo::getRegBankFromRegClass
4323 // method. Often the problem is hidden as non-optimized MatchTable checks
4324 // banks rather late, most notably after checking target / function /
4325 // module features and a few opcodes. That makes these checks a)
4326 // beneficial to delay until the very end (we don't want to perform a lot
4327 // of checks that all pass and then fail at the very end) b) not safe to
4328 // have as early checks.
4329 for (auto &OP : OM->predicates())
4330 if (isa(OP) ||
4331 isa(OP))
4332 EpilogueMatchers.emplace_back(std::move(OP));
4333 OM->eraseNullPredicates();
4334 }
4335 InsnMatcher.optimize();
4336 }
4337 llvm::sort(
4338 EpilogueMatchers.begin(), EpilogueMatchers.end(),
4339 [](const std::unique_ptr &L,
4340 const std::unique_ptr &R) {
4341 return std::make_tuple(L->getKind(), L->getInsnVarID(), L->getOpIdx()) <
4342 std::make_tuple(R->getKind(), R->getInsnVarID(), R->getOpIdx());
4343 });
4344 }
4345
4346 bool RuleMatcher::hasFirstCondition() const {
4347 if (insnmatchers_empty())
4348 return false;
4349 InstructionMatcher &Matcher = insnmatchers_front();
4350 if (!Matcher.predicates_empty())
4351 return true;
4352 for (auto &OM : Matcher.operands())
4353 for (auto &OP : OM->predicates())
4354 if (!isa(OP))
4355 return true;
4356 return false;
4357 }
4358
4359 const PredicateMatcher &RuleMatcher::getFirstCondition() const {
41554360 assert(!insnmatchers_empty() &&
4156 "Trying to forget something that does not exist");
4361 "Trying to get a condition from an empty RuleMatcher");
41574362
41584363 InstructionMatcher &Matcher = insnmatchers_front();
4159 std::unique_ptr Condition;
41604364 if (!Matcher.predicates_empty())
4161 Condition = Matcher.predicates_pop_front();
4162 if (!Condition) {
4163 // If there is no more predicate on the instruction itself, look at its
4164 // operands.
4165 assert(!Matcher.operands_empty() &&
4166 "Empty instruction should have been discarded");
4167 OperandMatcher &OpMatcher = **Matcher.operands_begin();
4168 assert(!OpMatcher.predicates_empty() && "no operand constraint");
4169 Condition = OpMatcher.predicates_pop_front();
4170 // If this operand is free of constraints, rip it off.
4171 if (OpMatcher.predicates_empty())
4172 Matcher.pop_front();
4173 }
4174 // Rip the instruction off when it is empty.
4175 if (Matcher.operands_empty() && Matcher.predicates_empty())
4176 insnmatchers_pop_front();
4177 return Condition;
4178 }
4179
4180 bool GroupMatcher::lastConditionMatches(
4365 return **Matcher.predicates_begin();
4366 // If there is no more predicate on the instruction itself, look at its
4367 // operands.
4368 for (auto &OM : Matcher.operands())
4369 for (auto &OP : OM->predicates())
4370 if (!isa(OP))
4371 return *OP;
4372
4373 llvm_unreachable("Trying to get a condition from an InstructionMatcher with "
4374 "no conditions");
4375 }
4376
4377 std::unique_ptr RuleMatcher::popFirstCondition() {
4378 assert(!insnmatchers_empty() &&
4379 "Trying to pop a condition from an empty RuleMatcher");
4380
4381 InstructionMatcher &Matcher = insnmatchers_front();
4382 if (!Matcher.predicates_empty())
4383 return Matcher.predicates_pop_front();
4384 // If there is no more predicate on the instruction itself, look at its
4385 // operands.
4386 for (auto &OM : Matcher.operands())
4387 for (auto &OP : OM->predicates())
4388 if (!isa(OP)) {
4389 std::unique_ptr Result = std::move(OP);
4390 OM->eraseNullPredicates();
4391 return Result;
4392 }
4393
4394 llvm_unreachable("Trying to pop a condition from an InstructionMatcher with "
4395 "no conditions");
4396 }
4397
4398 bool GroupMatcher::candidateConditionMatches(
41814399 const PredicateMatcher &Predicate) const {
4182 const auto &LastCondition = conditions_back();
4183 return Predicate.isIdentical(*LastCondition);
4400
4401 if (empty()) {
4402 // Sharing predicates for nested instructions is not supported yet as we
4403 // currently don't hoist the GIM_RecordInsn's properly, therefore we can
4404 // only work on the original root instruction (InsnVarID == 0):
4405 if (Predicate.getInsnVarID() != 0)
4406 return false;
4407 // ... otherwise an empty group can handle any predicate with no specific
4408 // requirements:
4409 return true;
4410 }
4411
4412 const Matcher &Representative = **Matchers.begin();
4413 const auto &RepresentativeCondition = Representative.getFirstCondition();
4414 // ... if not empty, the group can only accomodate matchers with the exact
4415 // same first condition:
4416 return Predicate.isIdentical(RepresentativeCondition);
4417 }
4418
4419 bool GroupMatcher::addMatcher(Matcher &Candidate) {
4420 if (!Candidate.hasFirstCondition())
4421 return false;
4422
4423 const PredicateMatcher &Predicate = Candidate.getFirstCondition();
4424 if (!candidateConditionMatches(Predicate))
4425 return false;
4426
4427 Matchers.push_back(&Candidate);
4428 return true;
4429 }
4430
4431 void GroupMatcher::finalize() {
4432 assert(Conditions.empty() && "Already finalized?");
4433 if (empty())
4434 return;
4435
4436 Matcher &FirstRule = **Matchers.begin();
4437
4438 Conditions.push_back(FirstRule.popFirstCondition());
4439 for (unsigned I = 1, E = Matchers.size(); I < E; ++I)
4440 Matchers[I]->popFirstCondition();
41844441 }
41854442
41864443 void GroupMatcher::emit(MatchTable &Table) {
4187 unsigned LabelID = Table.allocateLabelID();
4188 if (!conditions_empty()) {
4444 unsigned LabelID = ~0U;
4445 if (!Conditions.empty()) {
4446 LabelID = Table.allocateLabelID();
41894447 Table << MatchTable::Opcode("GIM_Try", +1)
41904448 << MatchTable::Comment("On fail goto")
41914449 << MatchTable::JumpTarget(LabelID) << MatchTable::LineBreak;
4192 for (auto &Condition : Conditions)
4193 Condition->emitPredicateOpcodes(
4194 Table, *static_cast(*Rules.begin()));
4195 }
4196 // Emit the conditions.
4197 // Then checks apply the rules.
4198 for (const auto &Rule : Rules)
4199 Rule->emit(Table);
4200 // If we don't succeeded for that block, that means we are not going to select
4201 // this instruction.
4202 if (!conditions_empty()) {
4203 Table << MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak;
4204 Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak
4450 }
4451 for (auto &Condition : Conditions)
4452 Condition->emitPredicateOpcodes(
4453 Table, *static_cast(*Matchers.begin()));
4454
4455 for (const auto &M : Matchers)
4456 M->emit(Table);
4457
4458 // Exit the group
4459 if (!Conditions.empty())
4460 Table << MatchTable::Opcode("GIM_Reject", -1) << MatchTable::LineBreak
42054461 << MatchTable::Label(LabelID);
4206 }
4207 }
4208
4209 unsigned OperandMatcher::getInsnVarID() const { return Insn.getVarID(); }
4462 }
4463
4464 unsigned OperandMatcher::getInsnVarID() const { return Insn.getInsnVarID(); }
42104465
42114466 } // end anonymous namespace
42124467