llvm.org GIT mirror llvm / 6e0e075
[GlobalISel] Improving InstructionSelect's performance by reducing MatchTable, mostly NFC, perf patch 1 This patch starts a series of patches that decrease time spent by GlobalISel in its InstructionSelect pass by roughly 60% for -O0 builds for large inputs as measured on sqlite3-amalgamation (http://sqlite.org/download.html) targeting AArch64. The performance improvements are achieved solely by reducing the number of matching GIM_* opcodes executed by the MatchTable's interpreter during the selection by approx. a factor of 30, which also brings contribution of this particular part of the selection process to the overall runtime of InstructionSelect pass down from approx. 60-70% to 5-7%, thus making further improvements in this particular direction not very profitable. The improvements described above are expected for any target that doesn't have many complex patterns. The targets that do should strictly benefit from the changes, but by how much exactly is hard to estimate beforehand. It's also likely that such target WILL benefit from further improvements to MatchTable, most likely the ones that bring it closer to a perfect decision tree. This commit specifically is rather large mostly NFC commit that does necessary preparation work and refactoring, there will be a following series of small patches introducing a specific optimization each shortly after. This commit specifically is expected to cause a small compile time regression (around 2.5% of InstructionSelect pass time), which should be fixed by the next commit of the series. Every commit planned shares the same Phabricator Review. Reviewers: qcolombet, dsanders, bogner, aemerson, javed.absar Reviewed By: qcolombet Subscribers: rovka, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D44700 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332907 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 auto 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