LLVM 18.0.0git
GIMatchTableExecutorImpl.h
Go to the documentation of this file.
1//===- llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h -------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file This file implements GIMatchTableExecutor's `executeMatchTable`
10/// function. This is implemented in a separate file because the function is
11/// quite large.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
16#define LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
17
30#include "llvm/IR/Constants.h"
31#include "llvm/IR/DataLayout.h"
32#include "llvm/IR/Type.h"
34#include "llvm/Support/Debug.h"
37#include <cassert>
38#include <cstddef>
39#include <cstdint>
40
41namespace llvm {
42
43template <class TgtExecutor, class PredicateBitset, class ComplexMatcherMemFn,
44 class CustomRendererFn>
46 TgtExecutor &Exec, MatcherState &State,
48 &ExecInfo,
49 MachineIRBuilder &Builder, const int64_t *MatchTable,
51 const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI,
52 const PredicateBitset &AvailableFeatures,
53 CodeGenCoverage *CoverageInfo) const {
54
55 uint64_t CurrentIdx = 0;
56 SmallVector<uint64_t, 4> OnFailResumeAt;
57 NewMIVector OutMIs;
58
59 GISelChangeObserver *Observer = Builder.getObserver();
60 // Bypass the flag check on the instruction, and only look at the MCInstrDesc.
61 bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException();
62
63 const uint16_t Flags = State.MIs[0]->getFlags();
64
65 enum RejectAction { RejectAndGiveUp, RejectAndResume };
66 auto handleReject = [&]() -> RejectAction {
67 DEBUG_WITH_TYPE(TgtExecutor::getName(),
68 dbgs() << CurrentIdx << ": Rejected\n");
69 if (OnFailResumeAt.empty())
70 return RejectAndGiveUp;
71 CurrentIdx = OnFailResumeAt.pop_back_val();
72 DEBUG_WITH_TYPE(TgtExecutor::getName(),
73 dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " ("
74 << OnFailResumeAt.size() << " try-blocks remain)\n");
75 return RejectAndResume;
76 };
77
78 const auto propagateFlags = [&]() {
79 for (auto MIB : OutMIs) {
80 // Set the NoFPExcept flag when no original matched instruction could
81 // raise an FP exception, but the new instruction potentially might.
82 uint16_t MIBFlags = Flags;
83 if (NoFPException && MIB->mayRaiseFPException())
84 MIBFlags |= MachineInstr::NoFPExcept;
85 if (Observer)
86 Observer->changingInstr(*MIB);
87 MIB.setMIFlags(MIBFlags);
88 if (Observer)
89 Observer->changedInstr(*MIB);
90 }
91 };
92
93 // If the index is >= 0, it's an index in the type objects generated by
94 // TableGen. If the index is <0, it's an index in the recorded types object.
95 auto getTypeFromIdx = [&](int64_t Idx) -> LLT {
96 if (Idx >= 0)
97 return ExecInfo.TypeObjects[Idx];
98 return State.RecordedTypes[1 - Idx];
99 };
100
101 while (true) {
102 assert(CurrentIdx != ~0u && "Invalid MatchTable index");
103 int64_t MatcherOpcode = MatchTable[CurrentIdx++];
104 switch (MatcherOpcode) {
105 case GIM_Try: {
106 DEBUG_WITH_TYPE(TgtExecutor::getName(),
107 dbgs() << CurrentIdx << ": Begin try-block\n");
108 OnFailResumeAt.push_back(MatchTable[CurrentIdx++]);
109 break;
110 }
111
112 case GIM_RecordInsn:
114 int64_t NewInsnID = MatchTable[CurrentIdx++];
115 int64_t InsnID = MatchTable[CurrentIdx++];
116 int64_t OpIdx = MatchTable[CurrentIdx++];
117
118 // As an optimisation we require that MIs[0] is always the root. Refuse
119 // any attempt to modify it.
120 assert(NewInsnID != 0 && "Refusing to modify MIs[0]");
121
122 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
123 if (!MO.isReg()) {
124 DEBUG_WITH_TYPE(TgtExecutor::getName(),
125 dbgs() << CurrentIdx << ": Not a register\n");
126 if (handleReject() == RejectAndGiveUp)
127 return false;
128 break;
129 }
130 if (MO.getReg().isPhysical()) {
131 DEBUG_WITH_TYPE(TgtExecutor::getName(),
132 dbgs() << CurrentIdx << ": Is a physical register\n");
133 if (handleReject() == RejectAndGiveUp)
134 return false;
135 break;
136 }
137
138 MachineInstr *NewMI;
139 if (MatcherOpcode == GIM_RecordInsnIgnoreCopies)
140 NewMI = getDefIgnoringCopies(MO.getReg(), MRI);
141 else
142 NewMI = MRI.getVRegDef(MO.getReg());
143
144 if ((size_t)NewInsnID < State.MIs.size())
145 State.MIs[NewInsnID] = NewMI;
146 else {
147 assert((size_t)NewInsnID == State.MIs.size() &&
148 "Expected to store MIs in order");
149 State.MIs.push_back(NewMI);
150 }
151 DEBUG_WITH_TYPE(TgtExecutor::getName(),
152 dbgs() << CurrentIdx << ": MIs[" << NewInsnID
153 << "] = GIM_RecordInsn(" << InsnID << ", " << OpIdx
154 << ")\n");
155 break;
156 }
157
158 case GIM_CheckFeatures: {
159 int64_t ExpectedBitsetID = MatchTable[CurrentIdx++];
160 DEBUG_WITH_TYPE(TgtExecutor::getName(),
161 dbgs() << CurrentIdx
162 << ": GIM_CheckFeatures(ExpectedBitsetID="
163 << ExpectedBitsetID << ")\n");
164 if ((AvailableFeatures & ExecInfo.FeatureBitsets[ExpectedBitsetID]) !=
165 ExecInfo.FeatureBitsets[ExpectedBitsetID]) {
166 if (handleReject() == RejectAndGiveUp)
167 return false;
168 }
169 break;
170 }
171 case GIM_CheckOpcode:
173 int64_t InsnID = MatchTable[CurrentIdx++];
174 int64_t Expected0 = MatchTable[CurrentIdx++];
175 int64_t Expected1 = -1;
176 if (MatcherOpcode == GIM_CheckOpcodeIsEither)
177 Expected1 = MatchTable[CurrentIdx++];
178
179 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
180 unsigned Opcode = State.MIs[InsnID]->getOpcode();
181
182 DEBUG_WITH_TYPE(TgtExecutor::getName(),
183 dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID
184 << "], ExpectedOpcode=" << Expected0;
185 if (MatcherOpcode == GIM_CheckOpcodeIsEither) dbgs()
186 << " || " << Expected1;
187 dbgs() << ") // Got=" << Opcode << "\n";);
188
189 if (Opcode != Expected0 && Opcode != Expected1) {
190 if (handleReject() == RejectAndGiveUp)
191 return false;
192 }
193 break;
194 }
195 case GIM_SwitchOpcode: {
196 int64_t InsnID = MatchTable[CurrentIdx++];
197 int64_t LowerBound = MatchTable[CurrentIdx++];
198 int64_t UpperBound = MatchTable[CurrentIdx++];
199 int64_t Default = MatchTable[CurrentIdx++];
200
201 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
202 const int64_t Opcode = State.MIs[InsnID]->getOpcode();
203
204 DEBUG_WITH_TYPE(TgtExecutor::getName(), {
205 dbgs() << CurrentIdx << ": GIM_SwitchOpcode(MIs[" << InsnID << "], ["
206 << LowerBound << ", " << UpperBound << "), Default=" << Default
207 << ", JumpTable...) // Got=" << Opcode << "\n";
208 });
209 if (Opcode < LowerBound || UpperBound <= Opcode) {
210 CurrentIdx = Default;
211 break;
212 }
213 CurrentIdx = MatchTable[CurrentIdx + (Opcode - LowerBound)];
214 if (!CurrentIdx) {
215 CurrentIdx = Default;
216 break;
217 }
218 OnFailResumeAt.push_back(Default);
219 break;
220 }
221
222 case GIM_SwitchType: {
223 int64_t InsnID = MatchTable[CurrentIdx++];
224 int64_t OpIdx = MatchTable[CurrentIdx++];
225 int64_t LowerBound = MatchTable[CurrentIdx++];
226 int64_t UpperBound = MatchTable[CurrentIdx++];
227 int64_t Default = MatchTable[CurrentIdx++];
228
229 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
230 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
231
232 DEBUG_WITH_TYPE(TgtExecutor::getName(), {
233 dbgs() << CurrentIdx << ": GIM_SwitchType(MIs[" << InsnID
234 << "]->getOperand(" << OpIdx << "), [" << LowerBound << ", "
235 << UpperBound << "), Default=" << Default
236 << ", JumpTable...) // Got=";
237 if (!MO.isReg())
238 dbgs() << "Not a VReg\n";
239 else
240 dbgs() << MRI.getType(MO.getReg()) << "\n";
241 });
242 if (!MO.isReg()) {
243 CurrentIdx = Default;
244 break;
245 }
246 const LLT Ty = MRI.getType(MO.getReg());
247 const auto TyI = ExecInfo.TypeIDMap.find(Ty);
248 if (TyI == ExecInfo.TypeIDMap.end()) {
249 CurrentIdx = Default;
250 break;
251 }
252 const int64_t TypeID = TyI->second;
253 if (TypeID < LowerBound || UpperBound <= TypeID) {
254 CurrentIdx = Default;
255 break;
256 }
257 CurrentIdx = MatchTable[CurrentIdx + (TypeID - LowerBound)];
258 if (!CurrentIdx) {
259 CurrentIdx = Default;
260 break;
261 }
262 OnFailResumeAt.push_back(Default);
263 break;
264 }
265
267 int64_t InsnID = MatchTable[CurrentIdx++];
268 int64_t Expected = MatchTable[CurrentIdx++];
269 DEBUG_WITH_TYPE(TgtExecutor::getName(),
270 dbgs() << CurrentIdx << ": GIM_CheckNumOperands(MIs["
271 << InsnID << "], Expected=" << Expected << ")\n");
272 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
273 if (State.MIs[InsnID]->getNumOperands() != Expected) {
274 if (handleReject() == RejectAndGiveUp)
275 return false;
276 }
277 break;
278 }
281 int64_t InsnID = MatchTable[CurrentIdx++];
282 int64_t OpIdx = MatcherOpcode == GIM_CheckImmOperandPredicate
283 ? MatchTable[CurrentIdx++]
284 : 1;
285 int64_t Predicate = MatchTable[CurrentIdx++];
286 DEBUG_WITH_TYPE(TgtExecutor::getName(),
287 dbgs() << CurrentIdx << ": GIM_CheckImmPredicate(MIs["
288 << InsnID << "]->getOperand(" << OpIdx
289 << "), Predicate=" << Predicate << ")\n");
290 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
291 assert((State.MIs[InsnID]->getOperand(OpIdx).isImm() ||
292 State.MIs[InsnID]->getOperand(OpIdx).isCImm()) &&
293 "Expected immediate operand");
294 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
295 int64_t Value = 0;
296 if (State.MIs[InsnID]->getOperand(OpIdx).isCImm())
297 Value = State.MIs[InsnID]->getOperand(OpIdx).getCImm()->getSExtValue();
298 else if (State.MIs[InsnID]->getOperand(OpIdx).isImm())
299 Value = State.MIs[InsnID]->getOperand(OpIdx).getImm();
300 else
301 llvm_unreachable("Expected Imm or CImm operand");
302
303 if (!testImmPredicate_I64(Predicate, Value))
304 if (handleReject() == RejectAndGiveUp)
305 return false;
306 break;
307 }
309 int64_t InsnID = MatchTable[CurrentIdx++];
310 int64_t Predicate = MatchTable[CurrentIdx++];
311 DEBUG_WITH_TYPE(TgtExecutor::getName(),
312 dbgs()
313 << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs["
314 << InsnID << "], Predicate=" << Predicate << ")\n");
315 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
316 assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
317 "Expected G_CONSTANT");
318 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
319 if (!State.MIs[InsnID]->getOperand(1).isCImm())
320 llvm_unreachable("Expected Imm or CImm operand");
321
322 const APInt &Value =
323 State.MIs[InsnID]->getOperand(1).getCImm()->getValue();
324 if (!testImmPredicate_APInt(Predicate, Value))
325 if (handleReject() == RejectAndGiveUp)
326 return false;
327 break;
328 }
330 int64_t InsnID = MatchTable[CurrentIdx++];
331 int64_t Predicate = MatchTable[CurrentIdx++];
332 DEBUG_WITH_TYPE(TgtExecutor::getName(),
333 dbgs()
334 << CurrentIdx << ": GIM_CheckAPFloatImmPredicate(MIs["
335 << InsnID << "], Predicate=" << Predicate << ")\n");
336 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
337 assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
338 "Expected G_FCONSTANT");
339 assert(State.MIs[InsnID]->getOperand(1).isFPImm() &&
340 "Expected FPImm operand");
341 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
342 const APFloat &Value =
343 State.MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF();
344
345 if (!testImmPredicate_APFloat(Predicate, Value))
346 if (handleReject() == RejectAndGiveUp)
347 return false;
348 break;
349 }
352 int64_t InsnID = MatchTable[CurrentIdx++];
353
354 DEBUG_WITH_TYPE(TgtExecutor::getName(),
355 dbgs() << CurrentIdx
356 << ": GIM_CheckBuildVectorAll{Zeros|Ones}(MIs["
357 << InsnID << "])\n");
358 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
359
360 const MachineInstr *MI = State.MIs[InsnID];
361 assert((MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR ||
362 MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC) &&
363 "Expected G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC");
364
365 if (MatcherOpcode == GIM_CheckIsBuildVectorAllOnes) {
366 if (!isBuildVectorAllOnes(*MI, MRI)) {
367 if (handleReject() == RejectAndGiveUp)
368 return false;
369 }
370 } else {
371 if (!isBuildVectorAllZeros(*MI, MRI)) {
372 if (handleReject() == RejectAndGiveUp)
373 return false;
374 }
375 }
376
377 break;
378 }
380 // Note: we don't check for invalid here because this is purely a hook to
381 // allow some executors (such as the combiner) to check arbitrary,
382 // contextless predicates, such as whether a rule is enabled or not.
383 int64_t Predicate = MatchTable[CurrentIdx++];
384 DEBUG_WITH_TYPE(TgtExecutor::getName(),
385 dbgs() << CurrentIdx
386 << ": GIM_CheckSimplePredicate(Predicate="
387 << Predicate << ")\n");
388 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
389 if (!testSimplePredicate(Predicate)) {
390 if (handleReject() == RejectAndGiveUp)
391 return false;
392 }
393 break;
394 }
396 int64_t InsnID = MatchTable[CurrentIdx++];
397 int64_t Predicate = MatchTable[CurrentIdx++];
398 DEBUG_WITH_TYPE(TgtExecutor::getName(),
399 dbgs()
400 << CurrentIdx << ": GIM_CheckCxxPredicate(MIs["
401 << InsnID << "], Predicate=" << Predicate << ")\n");
402 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
403 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
404
405 if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID], State))
406 if (handleReject() == RejectAndGiveUp)
407 return false;
408 break;
409 }
410 case GIM_CheckHasNoUse: {
411 int64_t InsnID = MatchTable[CurrentIdx++];
412
413 DEBUG_WITH_TYPE(TgtExecutor::getName(),
414 dbgs() << CurrentIdx << ": GIM_CheckHasNoUse(MIs["
415 << InsnID << "]\n");
416
417 const MachineInstr *MI = State.MIs[InsnID];
418 assert(MI && "Used insn before defined");
419 assert(MI->getNumDefs() > 0 && "No defs");
420 const Register Res = MI->getOperand(0).getReg();
421
422 if (!MRI.use_nodbg_empty(Res)) {
423 if (handleReject() == RejectAndGiveUp)
424 return false;
425 }
426
427 break;
428 }
430 int64_t InsnID = MatchTable[CurrentIdx++];
431 AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
432 DEBUG_WITH_TYPE(TgtExecutor::getName(),
433 dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs["
434 << InsnID << "], " << (uint64_t)Ordering << ")\n");
435 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
436 if (!State.MIs[InsnID]->hasOneMemOperand())
437 if (handleReject() == RejectAndGiveUp)
438 return false;
439
440 for (const auto &MMO : State.MIs[InsnID]->memoperands())
441 if (MMO->getMergedOrdering() != Ordering)
442 if (handleReject() == RejectAndGiveUp)
443 return false;
444 break;
445 }
447 int64_t InsnID = MatchTable[CurrentIdx++];
448 AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
449 DEBUG_WITH_TYPE(TgtExecutor::getName(),
450 dbgs() << CurrentIdx
451 << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs["
452 << InsnID << "], " << (uint64_t)Ordering << ")\n");
453 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
454 if (!State.MIs[InsnID]->hasOneMemOperand())
455 if (handleReject() == RejectAndGiveUp)
456 return false;
457
458 for (const auto &MMO : State.MIs[InsnID]->memoperands())
459 if (!isAtLeastOrStrongerThan(MMO->getMergedOrdering(), Ordering))
460 if (handleReject() == RejectAndGiveUp)
461 return false;
462 break;
463 }
465 int64_t InsnID = MatchTable[CurrentIdx++];
466 AtomicOrdering Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
467 DEBUG_WITH_TYPE(TgtExecutor::getName(),
468 dbgs() << CurrentIdx
469 << ": GIM_CheckAtomicOrderingWeakerThan(MIs["
470 << InsnID << "], " << (uint64_t)Ordering << ")\n");
471 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
472 if (!State.MIs[InsnID]->hasOneMemOperand())
473 if (handleReject() == RejectAndGiveUp)
474 return false;
475
476 for (const auto &MMO : State.MIs[InsnID]->memoperands())
477 if (!isStrongerThan(Ordering, MMO->getMergedOrdering()))
478 if (handleReject() == RejectAndGiveUp)
479 return false;
480 break;
481 }
483 int64_t InsnID = MatchTable[CurrentIdx++];
484 int64_t MMOIdx = MatchTable[CurrentIdx++];
485 // This accepts a list of possible address spaces.
486 const int NumAddrSpace = MatchTable[CurrentIdx++];
487
488 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
489 if (handleReject() == RejectAndGiveUp)
490 return false;
491 break;
492 }
493
494 // Need to still jump to the end of the list of address spaces if we find
495 // a match earlier.
496 const uint64_t LastIdx = CurrentIdx + NumAddrSpace;
497
498 const MachineMemOperand *MMO =
499 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
500 const unsigned MMOAddrSpace = MMO->getAddrSpace();
501
502 bool Success = false;
503 for (int I = 0; I != NumAddrSpace; ++I) {
504 unsigned AddrSpace = MatchTable[CurrentIdx++];
505 DEBUG_WITH_TYPE(TgtExecutor::getName(),
506 dbgs() << "addrspace(" << MMOAddrSpace << ") vs "
507 << AddrSpace << '\n');
508
509 if (AddrSpace == MMOAddrSpace) {
510 Success = true;
511 break;
512 }
513 }
514
515 CurrentIdx = LastIdx;
516 if (!Success && handleReject() == RejectAndGiveUp)
517 return false;
518 break;
519 }
521 int64_t InsnID = MatchTable[CurrentIdx++];
522 int64_t MMOIdx = MatchTable[CurrentIdx++];
523 unsigned MinAlign = MatchTable[CurrentIdx++];
524
525 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
526
527 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
528 if (handleReject() == RejectAndGiveUp)
529 return false;
530 break;
531 }
532
533 MachineMemOperand *MMO =
534 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
535 DEBUG_WITH_TYPE(TgtExecutor::getName(),
536 dbgs() << CurrentIdx << ": GIM_CheckMemoryAlignment"
537 << "(MIs[" << InsnID << "]->memoperands() + "
538 << MMOIdx << ")->getAlignment() >= " << MinAlign
539 << ")\n");
540 if (MMO->getAlign() < MinAlign && handleReject() == RejectAndGiveUp)
541 return false;
542
543 break;
544 }
546 int64_t InsnID = MatchTable[CurrentIdx++];
547 int64_t MMOIdx = MatchTable[CurrentIdx++];
548 uint64_t Size = MatchTable[CurrentIdx++];
549
550 DEBUG_WITH_TYPE(TgtExecutor::getName(),
551 dbgs() << CurrentIdx << ": GIM_CheckMemorySizeEqual(MIs["
552 << InsnID << "]->memoperands() + " << MMOIdx
553 << ", Size=" << Size << ")\n");
554 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
555
556 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
557 if (handleReject() == RejectAndGiveUp)
558 return false;
559 break;
560 }
561
562 MachineMemOperand *MMO =
563 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
564
565 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << MMO->getSize()
566 << " bytes vs " << Size
567 << " bytes\n");
568 if (MMO->getSize() != Size)
569 if (handleReject() == RejectAndGiveUp)
570 return false;
571
572 break;
573 }
577 int64_t InsnID = MatchTable[CurrentIdx++];
578 int64_t MMOIdx = MatchTable[CurrentIdx++];
579 int64_t OpIdx = MatchTable[CurrentIdx++];
580
582 TgtExecutor::getName(),
583 dbgs() << CurrentIdx << ": GIM_CheckMemorySize"
584 << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT ? "EqualTo"
585 : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT
586 ? "GreaterThan"
587 : "LessThan")
588 << "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx
589 << ", OpIdx=" << OpIdx << ")\n");
590 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
591
592 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
593 if (!MO.isReg()) {
594 DEBUG_WITH_TYPE(TgtExecutor::getName(),
595 dbgs() << CurrentIdx << ": Not a register\n");
596 if (handleReject() == RejectAndGiveUp)
597 return false;
598 break;
599 }
600
601 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
602 if (handleReject() == RejectAndGiveUp)
603 return false;
604 break;
605 }
606
607 MachineMemOperand *MMO =
608 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
609
610 unsigned Size = MRI.getType(MO.getReg()).getSizeInBits();
611 if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT &&
612 MMO->getSizeInBits() != Size) {
613 if (handleReject() == RejectAndGiveUp)
614 return false;
615 } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT &&
616 MMO->getSizeInBits() >= Size) {
617 if (handleReject() == RejectAndGiveUp)
618 return false;
619 } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT &&
620 MMO->getSizeInBits() <= Size)
621 if (handleReject() == RejectAndGiveUp)
622 return false;
623
624 break;
625 }
626 case GIM_CheckType: {
627 int64_t InsnID = MatchTable[CurrentIdx++];
628 int64_t OpIdx = MatchTable[CurrentIdx++];
629 int64_t TypeID = MatchTable[CurrentIdx++];
630 DEBUG_WITH_TYPE(TgtExecutor::getName(),
631 dbgs() << CurrentIdx << ": GIM_CheckType(MIs[" << InsnID
632 << "]->getOperand(" << OpIdx
633 << "), TypeID=" << TypeID << ")\n");
634 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
635 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
636 if (!MO.isReg() || MRI.getType(MO.getReg()) != getTypeFromIdx(TypeID)) {
637 if (handleReject() == RejectAndGiveUp)
638 return false;
639 }
640 break;
641 }
643 int64_t InsnID = MatchTable[CurrentIdx++];
644 int64_t OpIdx = MatchTable[CurrentIdx++];
645 uint64_t SizeInBits = MatchTable[CurrentIdx++];
646
647 DEBUG_WITH_TYPE(TgtExecutor::getName(),
648 dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs["
649 << InsnID << "]->getOperand(" << OpIdx
650 << "), SizeInBits=" << SizeInBits << ")\n");
651 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
652 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
653 const LLT Ty = MRI.getType(MO.getReg());
654
655 // iPTR must be looked up in the target.
656 if (SizeInBits == 0) {
657 MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent();
658 const unsigned AddrSpace = Ty.getAddressSpace();
659 SizeInBits = MF->getDataLayout().getPointerSizeInBits(AddrSpace);
660 }
661
662 assert(SizeInBits != 0 && "Pointer size must be known");
663
664 if (MO.isReg()) {
665 if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits)
666 if (handleReject() == RejectAndGiveUp)
667 return false;
668 } else if (handleReject() == RejectAndGiveUp)
669 return false;
670
671 break;
672 }
674 int64_t InsnID = MatchTable[CurrentIdx++];
675 int64_t OpIdx = MatchTable[CurrentIdx++];
676 uint64_t StoreIdx = MatchTable[CurrentIdx++];
677
678 DEBUG_WITH_TYPE(TgtExecutor::getName(),
679 dbgs() << CurrentIdx << ": GIM_RecordNamedOperand(MIs["
680 << InsnID << "]->getOperand(" << OpIdx
681 << "), StoreIdx=" << StoreIdx << ")\n");
682 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
683 assert(StoreIdx < State.RecordedOperands.size() && "Index out of range");
684 State.RecordedOperands[StoreIdx] = &State.MIs[InsnID]->getOperand(OpIdx);
685 break;
686 }
687 case GIM_RecordRegType: {
688 int64_t InsnID = MatchTable[CurrentIdx++];
689 int64_t OpIdx = MatchTable[CurrentIdx++];
690 int64_t TypeIdx = MatchTable[CurrentIdx++];
691
692 DEBUG_WITH_TYPE(TgtExecutor::getName(),
693 dbgs() << CurrentIdx << ": GIM_RecordRegType(MIs["
694 << InsnID << "]->getOperand(" << OpIdx
695 << "), TypeIdx=" << TypeIdx << ")\n");
696 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
697 assert(TypeIdx <= 0 && "Temp types always have negative indexes!");
698 // Indexes start at -1.
699 TypeIdx = 1 - TypeIdx;
700 const auto &Op = State.MIs[InsnID]->getOperand(OpIdx);
701 if (State.RecordedTypes.size() <= (uint64_t)TypeIdx)
702 State.RecordedTypes.resize(TypeIdx + 1, LLT());
703 State.RecordedTypes[TypeIdx] = MRI.getType(Op.getReg());
704 break;
705 }
707 int64_t InsnID = MatchTable[CurrentIdx++];
708 int64_t OpIdx = MatchTable[CurrentIdx++];
709 int64_t RCEnum = MatchTable[CurrentIdx++];
710 DEBUG_WITH_TYPE(TgtExecutor::getName(),
711 dbgs() << CurrentIdx << ": GIM_CheckRegBankForClass(MIs["
712 << InsnID << "]->getOperand(" << OpIdx
713 << "), RCEnum=" << RCEnum << ")\n");
714 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
715 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
716 if (!MO.isReg() ||
717 &RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum),
718 MRI.getType(MO.getReg())) !=
719 RBI.getRegBank(MO.getReg(), MRI, TRI)) {
720 if (handleReject() == RejectAndGiveUp)
721 return false;
722 }
723 break;
724 }
725
727 int64_t InsnID = MatchTable[CurrentIdx++];
728 int64_t OpIdx = MatchTable[CurrentIdx++];
729 int64_t RendererID = MatchTable[CurrentIdx++];
730 int64_t ComplexPredicateID = MatchTable[CurrentIdx++];
731 DEBUG_WITH_TYPE(TgtExecutor::getName(),
732 dbgs() << CurrentIdx << ": State.Renderers[" << RendererID
733 << "] = GIM_CheckComplexPattern(MIs[" << InsnID
734 << "]->getOperand(" << OpIdx
735 << "), ComplexPredicateID=" << ComplexPredicateID
736 << ")\n");
737 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
738 // FIXME: Use std::invoke() when it's available.
739 ComplexRendererFns Renderer =
740 (Exec.*ExecInfo.ComplexPredicates[ComplexPredicateID])(
741 State.MIs[InsnID]->getOperand(OpIdx));
742 if (Renderer)
743 State.Renderers[RendererID] = *Renderer;
744 else if (handleReject() == RejectAndGiveUp)
745 return false;
746 break;
747 }
748
750 int64_t InsnID = MatchTable[CurrentIdx++];
751 int64_t OpIdx = MatchTable[CurrentIdx++];
752 int64_t Value = MatchTable[CurrentIdx++];
753 DEBUG_WITH_TYPE(TgtExecutor::getName(),
754 dbgs() << CurrentIdx << ": GIM_CheckConstantInt(MIs["
755 << InsnID << "]->getOperand(" << OpIdx
756 << "), Value=" << Value << ")\n");
757 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
758 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
759 if (MO.isReg()) {
760 // isOperandImmEqual() will sign-extend to 64-bits, so should we.
761 LLT Ty = MRI.getType(MO.getReg());
762 // If the type is > 64 bits, it can't be a constant int, so we bail
763 // early because SignExtend64 will assert otherwise.
764 if (Ty.getScalarSizeInBits() > 64) {
765 if (handleReject() == RejectAndGiveUp)
766 return false;
767 break;
768 }
769
771 if (!isOperandImmEqual(MO, Value, MRI, /*Splat=*/true)) {
772 if (handleReject() == RejectAndGiveUp)
773 return false;
774 }
775 } else if (handleReject() == RejectAndGiveUp)
776 return false;
777
778 break;
779 }
780
781 case GIM_CheckLiteralInt: {
782 int64_t InsnID = MatchTable[CurrentIdx++];
783 int64_t OpIdx = MatchTable[CurrentIdx++];
784 int64_t Value = MatchTable[CurrentIdx++];
785 DEBUG_WITH_TYPE(TgtExecutor::getName(),
786 dbgs() << CurrentIdx << ": GIM_CheckLiteralInt(MIs["
787 << InsnID << "]->getOperand(" << OpIdx
788 << "), Value=" << Value << ")\n");
789 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
790 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
791 if (MO.isImm() && MO.getImm() == Value)
792 break;
793
794 if (MO.isCImm() && MO.getCImm()->equalsInt(Value))
795 break;
796
797 if (handleReject() == RejectAndGiveUp)
798 return false;
799
800 break;
801 }
802
804 int64_t InsnID = MatchTable[CurrentIdx++];
805 int64_t OpIdx = MatchTable[CurrentIdx++];
806 int64_t Value = MatchTable[CurrentIdx++];
807 DEBUG_WITH_TYPE(TgtExecutor::getName(),
808 dbgs() << CurrentIdx << ": GIM_CheckIntrinsicID(MIs["
809 << InsnID << "]->getOperand(" << OpIdx
810 << "), Value=" << Value << ")\n");
811 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
812 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
813 if (!MO.isIntrinsicID() || MO.getIntrinsicID() != Value)
814 if (handleReject() == RejectAndGiveUp)
815 return false;
816 break;
817 }
819 int64_t InsnID = MatchTable[CurrentIdx++];
820 int64_t OpIdx = MatchTable[CurrentIdx++];
821 int64_t Value = MatchTable[CurrentIdx++];
822 DEBUG_WITH_TYPE(TgtExecutor::getName(),
823 dbgs() << CurrentIdx << ": GIM_CheckCmpPredicate(MIs["
824 << InsnID << "]->getOperand(" << OpIdx
825 << "), Value=" << Value << ")\n");
826 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
827 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
828 if (!MO.isPredicate() || MO.getPredicate() != Value)
829 if (handleReject() == RejectAndGiveUp)
830 return false;
831 break;
832 }
833 case GIM_CheckIsMBB: {
834 int64_t InsnID = MatchTable[CurrentIdx++];
835 int64_t OpIdx = MatchTable[CurrentIdx++];
836 DEBUG_WITH_TYPE(TgtExecutor::getName(),
837 dbgs() << CurrentIdx << ": GIM_CheckIsMBB(MIs[" << InsnID
838 << "]->getOperand(" << OpIdx << "))\n");
839 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
840 if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB()) {
841 if (handleReject() == RejectAndGiveUp)
842 return false;
843 }
844 break;
845 }
846 case GIM_CheckIsImm: {
847 int64_t InsnID = MatchTable[CurrentIdx++];
848 int64_t OpIdx = MatchTable[CurrentIdx++];
849 DEBUG_WITH_TYPE(TgtExecutor::getName(),
850 dbgs() << CurrentIdx << ": GIM_CheckIsImm(MIs[" << InsnID
851 << "]->getOperand(" << OpIdx << "))\n");
852 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
853 if (!State.MIs[InsnID]->getOperand(OpIdx).isImm()) {
854 if (handleReject() == RejectAndGiveUp)
855 return false;
856 }
857 break;
858 }
860 int64_t InsnID = MatchTable[CurrentIdx++];
861 DEBUG_WITH_TYPE(TgtExecutor::getName(),
862 dbgs() << CurrentIdx << ": GIM_CheckIsSafeToFold(MIs["
863 << InsnID << "])\n");
864 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
865 if (!isObviouslySafeToFold(*State.MIs[InsnID], *State.MIs[0])) {
866 if (handleReject() == RejectAndGiveUp)
867 return false;
868 }
869 break;
870 }
873 int64_t InsnID = MatchTable[CurrentIdx++];
874 int64_t OpIdx = MatchTable[CurrentIdx++];
875 int64_t OtherInsnID = MatchTable[CurrentIdx++];
876 int64_t OtherOpIdx = MatchTable[CurrentIdx++];
877 DEBUG_WITH_TYPE(TgtExecutor::getName(),
878 dbgs() << CurrentIdx << ": GIM_CheckIsSameOperand(MIs["
879 << InsnID << "][" << OpIdx << "], MIs["
880 << OtherInsnID << "][" << OtherOpIdx << "])\n");
881 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
882 assert(State.MIs[OtherInsnID] != nullptr && "Used insn before defined");
883
884 MachineOperand &Op = State.MIs[InsnID]->getOperand(OpIdx);
885 MachineOperand &OtherOp = State.MIs[OtherInsnID]->getOperand(OtherOpIdx);
886
887 if (MatcherOpcode == GIM_CheckIsSameOperandIgnoreCopies) {
888 if (Op.isReg() && OtherOp.isReg()) {
889 if (getSrcRegIgnoringCopies(Op.getReg(), MRI) ==
891 break;
892 }
893 }
894
895 if (!Op.isIdenticalTo(OtherOp)) {
896 if (handleReject() == RejectAndGiveUp)
897 return false;
898 }
899 break;
900 }
902 int64_t OldInsnID = MatchTable[CurrentIdx++];
903 int64_t OldOpIdx = MatchTable[CurrentIdx++];
904 int64_t NewInsnID = MatchTable[CurrentIdx++];
905 int64_t NewOpIdx = MatchTable[CurrentIdx++];
906
907 DEBUG_WITH_TYPE(TgtExecutor::getName(),
908 dbgs() << CurrentIdx << ": GIM_CheckCanReplaceReg(MIs["
909 << OldInsnID << "][" << OldOpIdx << "] = MIs["
910 << NewInsnID << "][" << NewOpIdx << "])\n");
911
912 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
913 Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg();
914 if (!canReplaceReg(Old, New, MRI)) {
915 if (handleReject() == RejectAndGiveUp)
916 return false;
917 }
918 break;
919 }
920 case GIM_MIFlags: {
921 int64_t InsnID = MatchTable[CurrentIdx++];
922 uint32_t Flags = (uint32_t)MatchTable[CurrentIdx++];
923
924 DEBUG_WITH_TYPE(TgtExecutor::getName(),
925 dbgs() << CurrentIdx << ": GIM_MIFlags(MIs[" << InsnID
926 << "], " << Flags << ")\n");
927 if ((State.MIs[InsnID]->getFlags() & Flags) != Flags) {
928 if (handleReject() == RejectAndGiveUp)
929 return false;
930 }
931 break;
932 }
933 case GIM_MIFlagsNot: {
934 int64_t InsnID = MatchTable[CurrentIdx++];
935 uint32_t Flags = (uint32_t)MatchTable[CurrentIdx++];
936
937 DEBUG_WITH_TYPE(TgtExecutor::getName(),
938 dbgs() << CurrentIdx << ": GIM_MIFlagsNot(MIs[" << InsnID
939 << "], " << Flags << ")\n");
940 if ((State.MIs[InsnID]->getFlags() & Flags)) {
941 if (handleReject() == RejectAndGiveUp)
942 return false;
943 }
944 break;
945 }
946 case GIM_Reject:
947 DEBUG_WITH_TYPE(TgtExecutor::getName(),
948 dbgs() << CurrentIdx << ": GIM_Reject\n");
949 if (handleReject() == RejectAndGiveUp)
950 return false;
951 break;
952 case GIR_MutateOpcode: {
953 int64_t OldInsnID = MatchTable[CurrentIdx++];
954 uint64_t NewInsnID = MatchTable[CurrentIdx++];
955 int64_t NewOpcode = MatchTable[CurrentIdx++];
956 if (NewInsnID >= OutMIs.size())
957 OutMIs.resize(NewInsnID + 1);
958
959 MachineInstr *OldMI = State.MIs[OldInsnID];
960 if (Observer)
961 Observer->changingInstr(*OldMI);
962 OutMIs[NewInsnID] = MachineInstrBuilder(*OldMI->getMF(), OldMI);
963 OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
964 if (Observer)
965 Observer->changedInstr(*OldMI);
966 DEBUG_WITH_TYPE(TgtExecutor::getName(),
967 dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs["
968 << NewInsnID << "], MIs[" << OldInsnID << "], "
969 << NewOpcode << ")\n");
970 break;
971 }
972
973 case GIR_BuildMI: {
974 uint64_t NewInsnID = MatchTable[CurrentIdx++];
975 int64_t Opcode = MatchTable[CurrentIdx++];
976 if (NewInsnID >= OutMIs.size())
977 OutMIs.resize(NewInsnID + 1);
978
979 OutMIs[NewInsnID] = Builder.buildInstr(Opcode);
980 DEBUG_WITH_TYPE(TgtExecutor::getName(),
981 dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs["
982 << NewInsnID << "], " << Opcode << ")\n");
983 break;
984 }
985
986 case GIR_BuildConstant: {
987 int64_t TempRegID = MatchTable[CurrentIdx++];
988 int64_t Imm = MatchTable[CurrentIdx++];
989 Builder.buildConstant(State.TempRegisters[TempRegID], Imm);
990 DEBUG_WITH_TYPE(TgtExecutor::getName(),
991 dbgs() << CurrentIdx << ": GIR_BuildConstant(TempReg["
992 << TempRegID << "], Imm=" << Imm << ")\n");
993 break;
994 }
995
996 case GIR_Copy: {
997 int64_t NewInsnID = MatchTable[CurrentIdx++];
998 int64_t OldInsnID = MatchTable[CurrentIdx++];
999 int64_t OpIdx = MatchTable[CurrentIdx++];
1000 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1001 OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
1002 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1003 dbgs()
1004 << CurrentIdx << ": GIR_Copy(OutMIs[" << NewInsnID
1005 << "], MIs[" << OldInsnID << "], " << OpIdx << ")\n");
1006 break;
1007 }
1008
1009 case GIR_CopyOrAddZeroReg: {
1010 int64_t NewInsnID = MatchTable[CurrentIdx++];
1011 int64_t OldInsnID = MatchTable[CurrentIdx++];
1012 int64_t OpIdx = MatchTable[CurrentIdx++];
1013 int64_t ZeroReg = MatchTable[CurrentIdx++];
1014 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1015 MachineOperand &MO = State.MIs[OldInsnID]->getOperand(OpIdx);
1016 if (isOperandImmEqual(MO, 0, MRI))
1017 OutMIs[NewInsnID].addReg(ZeroReg);
1018 else
1019 OutMIs[NewInsnID].add(MO);
1020 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1021 dbgs() << CurrentIdx << ": GIR_CopyOrAddZeroReg(OutMIs["
1022 << NewInsnID << "], MIs[" << OldInsnID << "], "
1023 << OpIdx << ", " << ZeroReg << ")\n");
1024 break;
1025 }
1026
1027 case GIR_CopySubReg: {
1028 int64_t NewInsnID = MatchTable[CurrentIdx++];
1029 int64_t OldInsnID = MatchTable[CurrentIdx++];
1030 int64_t OpIdx = MatchTable[CurrentIdx++];
1031 int64_t SubRegIdx = MatchTable[CurrentIdx++];
1032 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1033 OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
1034 0, SubRegIdx);
1035 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1036 dbgs() << CurrentIdx << ": GIR_CopySubReg(OutMIs["
1037 << NewInsnID << "], MIs[" << OldInsnID << "], "
1038 << OpIdx << ", " << SubRegIdx << ")\n");
1039 break;
1040 }
1041
1042 case GIR_AddImplicitDef: {
1043 int64_t InsnID = MatchTable[CurrentIdx++];
1044 int64_t RegNum = MatchTable[CurrentIdx++];
1045 auto Flags = (uint64_t)MatchTable[CurrentIdx++];
1046 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1047 Flags |= RegState::Implicit;
1048 OutMIs[InsnID].addDef(RegNum, Flags);
1049 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1050 dbgs() << CurrentIdx << ": GIR_AddImplicitDef(OutMIs["
1051 << InsnID << "], " << RegNum << ")\n");
1052 break;
1053 }
1054
1055 case GIR_AddImplicitUse: {
1056 int64_t InsnID = MatchTable[CurrentIdx++];
1057 int64_t RegNum = MatchTable[CurrentIdx++];
1058 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1059 OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
1060 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1061 dbgs() << CurrentIdx << ": GIR_AddImplicitUse(OutMIs["
1062 << InsnID << "], " << RegNum << ")\n");
1063 break;
1064 }
1065
1066 case GIR_AddRegister: {
1067 int64_t InsnID = MatchTable[CurrentIdx++];
1068 int64_t RegNum = MatchTable[CurrentIdx++];
1069 uint64_t RegFlags = MatchTable[CurrentIdx++];
1070 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1071 OutMIs[InsnID].addReg(RegNum, RegFlags);
1072 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1073 dbgs()
1074 << CurrentIdx << ": GIR_AddRegister(OutMIs[" << InsnID
1075 << "], " << RegNum << ", " << RegFlags << ")\n");
1076 break;
1077 }
1079 int64_t InsnID = MatchTable[CurrentIdx++];
1080 int64_t OpIdx = MatchTable[CurrentIdx++];
1081 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1082 dbgs() << CurrentIdx << ": GIR_SetImplicitDefDead(OutMIs["
1083 << InsnID << "], OpIdx=" << OpIdx << ")\n");
1084 MachineInstr *MI = OutMIs[InsnID];
1085 assert(MI && "Modifying undefined instruction");
1086 MI->getOperand(MI->getNumExplicitOperands() + OpIdx).setIsDead();
1087 break;
1088 }
1089 case GIR_SetMIFlags: {
1090 int64_t InsnID = MatchTable[CurrentIdx++];
1091 uint32_t Flags = (uint32_t)MatchTable[CurrentIdx++];
1092
1093 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1094 dbgs() << CurrentIdx << ": GIR_SetMIFlags(OutMIs["
1095 << InsnID << "], " << Flags << ")\n");
1096 MachineInstr *MI = OutMIs[InsnID];
1097 MI->setFlags(MI->getFlags() | Flags);
1098 break;
1099 }
1100 case GIR_UnsetMIFlags: {
1101 int64_t InsnID = MatchTable[CurrentIdx++];
1102 uint32_t Flags = (uint32_t)MatchTable[CurrentIdx++];
1103
1104 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1105 dbgs() << CurrentIdx << ": GIR_UnsetMIFlags(OutMIs["
1106 << InsnID << "], " << Flags << ")\n");
1107 MachineInstr *MI = OutMIs[InsnID];
1108 MI->setFlags(MI->getFlags() & ~Flags);
1109 break;
1110 }
1111 case GIR_CopyMIFlags: {
1112 int64_t InsnID = MatchTable[CurrentIdx++];
1113 int64_t OldInsnID = MatchTable[CurrentIdx++];
1114
1115 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1116 dbgs() << CurrentIdx << ": GIR_CopyMIFlags(OutMIs["
1117 << InsnID << "], MIs[" << OldInsnID << "])\n");
1118 MachineInstr *MI = OutMIs[InsnID];
1119 MI->setFlags(MI->getFlags() | State.MIs[OldInsnID]->getFlags());
1120 break;
1121 }
1124 int64_t InsnID = MatchTable[CurrentIdx++];
1125 int64_t TempRegID = MatchTable[CurrentIdx++];
1126 uint64_t TempRegFlags = MatchTable[CurrentIdx++];
1127 unsigned SubReg = 0;
1128 if (MatcherOpcode == GIR_AddTempSubRegister)
1129 SubReg = MatchTable[CurrentIdx++];
1130
1131 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1132
1133 OutMIs[InsnID].addReg(State.TempRegisters[TempRegID], TempRegFlags,
1134 SubReg);
1136 TgtExecutor::getName(),
1137 dbgs() << CurrentIdx << ": GIR_AddTempRegister(OutMIs[" << InsnID
1138 << "], TempRegisters[" << TempRegID << "]";
1139 if (SubReg) dbgs() << '.' << TRI.getSubRegIndexName(SubReg);
1140 dbgs() << ", " << TempRegFlags << ")\n");
1141 break;
1142 }
1143
1144 case GIR_AddImm: {
1145 int64_t InsnID = MatchTable[CurrentIdx++];
1146 int64_t Imm = MatchTable[CurrentIdx++];
1147 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1148 OutMIs[InsnID].addImm(Imm);
1149 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1150 dbgs() << CurrentIdx << ": GIR_AddImm(OutMIs[" << InsnID
1151 << "], " << Imm << ")\n");
1152 break;
1153 }
1154
1155 case GIR_AddCImm: {
1156 int64_t InsnID = MatchTable[CurrentIdx++];
1157 int64_t TypeID = MatchTable[CurrentIdx++];
1158 int64_t Imm = MatchTable[CurrentIdx++];
1159 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1160
1161 unsigned Width = ExecInfo.TypeObjects[TypeID].getScalarSizeInBits();
1163 OutMIs[InsnID].addCImm(
1164 ConstantInt::get(IntegerType::get(Ctx, Width), Imm, /*signed*/ true));
1165 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1166 dbgs() << CurrentIdx << ": GIR_AddCImm(OutMIs[" << InsnID
1167 << "], TypeID=" << TypeID << ", Imm=" << Imm
1168 << ")\n");
1169 break;
1170 }
1171
1172 case GIR_ComplexRenderer: {
1173 int64_t InsnID = MatchTable[CurrentIdx++];
1174 int64_t RendererID = MatchTable[CurrentIdx++];
1175 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1176 for (const auto &RenderOpFn : State.Renderers[RendererID])
1177 RenderOpFn(OutMIs[InsnID]);
1178 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1179 dbgs() << CurrentIdx << ": GIR_ComplexRenderer(OutMIs["
1180 << InsnID << "], " << RendererID << ")\n");
1181 break;
1182 }
1184 int64_t InsnID = MatchTable[CurrentIdx++];
1185 int64_t RendererID = MatchTable[CurrentIdx++];
1186 int64_t RenderOpID = MatchTable[CurrentIdx++];
1187 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1188 State.Renderers[RendererID][RenderOpID](OutMIs[InsnID]);
1189 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1190 dbgs() << CurrentIdx
1191 << ": GIR_ComplexSubOperandRenderer(OutMIs["
1192 << InsnID << "], " << RendererID << ", "
1193 << RenderOpID << ")\n");
1194 break;
1195 }
1197 int64_t InsnID = MatchTable[CurrentIdx++];
1198 int64_t RendererID = MatchTable[CurrentIdx++];
1199 int64_t RenderOpID = MatchTable[CurrentIdx++];
1200 int64_t SubRegIdx = MatchTable[CurrentIdx++];
1201 MachineInstrBuilder &MI = OutMIs[InsnID];
1202 assert(MI && "Attempted to add to undefined instruction");
1203 State.Renderers[RendererID][RenderOpID](MI);
1204 MI->getOperand(MI->getNumOperands() - 1).setSubReg(SubRegIdx);
1205 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1206 dbgs() << CurrentIdx
1207 << ": GIR_ComplexSubOperandSubRegRenderer(OutMIs["
1208 << InsnID << "], " << RendererID << ", "
1209 << RenderOpID << ", " << SubRegIdx << ")\n");
1210 break;
1211 }
1212
1214 int64_t NewInsnID = MatchTable[CurrentIdx++];
1215 int64_t OldInsnID = MatchTable[CurrentIdx++];
1216 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1217 assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
1218 "Expected G_CONSTANT");
1219 if (State.MIs[OldInsnID]->getOperand(1).isCImm()) {
1220 OutMIs[NewInsnID].addImm(
1221 State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue());
1222 } else if (State.MIs[OldInsnID]->getOperand(1).isImm())
1223 OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1));
1224 else
1225 llvm_unreachable("Expected Imm or CImm operand");
1226 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1227 dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs["
1228 << NewInsnID << "], MIs[" << OldInsnID << "])\n");
1229 break;
1230 }
1231
1232 // TODO: Needs a test case once we have a pattern that uses this.
1234 int64_t NewInsnID = MatchTable[CurrentIdx++];
1235 int64_t OldInsnID = MatchTable[CurrentIdx++];
1236 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1237 assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
1238 "Expected G_FCONSTANT");
1239 if (State.MIs[OldInsnID]->getOperand(1).isFPImm())
1240 OutMIs[NewInsnID].addFPImm(
1241 State.MIs[OldInsnID]->getOperand(1).getFPImm());
1242 else
1243 llvm_unreachable("Expected FPImm operand");
1244 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1245 dbgs()
1246 << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs["
1247 << NewInsnID << "], MIs[" << OldInsnID << "])\n");
1248 break;
1249 }
1250
1251 case GIR_CustomRenderer: {
1252 int64_t InsnID = MatchTable[CurrentIdx++];
1253 int64_t OldInsnID = MatchTable[CurrentIdx++];
1254 int64_t RendererFnID = MatchTable[CurrentIdx++];
1255 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1256 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1257 dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs["
1258 << InsnID << "], MIs[" << OldInsnID << "], "
1259 << RendererFnID << ")\n");
1260 (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
1261 OutMIs[InsnID], *State.MIs[OldInsnID],
1262 -1); // Not a source operand of the old instruction.
1263 break;
1264 }
1265 case GIR_CustomAction: {
1266 int64_t FnID = MatchTable[CurrentIdx++];
1267 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1268 dbgs() << CurrentIdx << ": GIR_CustomAction(FnID=" << FnID
1269 << ")\n");
1270 assert(FnID > GICXXCustomAction_Invalid && "Expected a valid FnID");
1271 runCustomAction(FnID, State, OutMIs);
1272 break;
1273 }
1275 int64_t InsnID = MatchTable[CurrentIdx++];
1276 int64_t OldInsnID = MatchTable[CurrentIdx++];
1277 int64_t OpIdx = MatchTable[CurrentIdx++];
1278 int64_t RendererFnID = MatchTable[CurrentIdx++];
1279 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1280
1281 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1282 dbgs() << CurrentIdx
1283 << ": GIR_CustomOperandRenderer(OutMIs[" << InsnID
1284 << "], MIs[" << OldInsnID << "]->getOperand("
1285 << OpIdx << "), " << RendererFnID << ")\n");
1286 (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
1287 OutMIs[InsnID], *State.MIs[OldInsnID], OpIdx);
1288 break;
1289 }
1291 int64_t InsnID = MatchTable[CurrentIdx++];
1292 int64_t OpIdx = MatchTable[CurrentIdx++];
1293 int64_t RCEnum = MatchTable[CurrentIdx++];
1294 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1295 MachineInstr &I = *OutMIs[InsnID].getInstr();
1296 MachineFunction &MF = *I.getParent()->getParent();
1298 const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum);
1299 MachineOperand &MO = I.getOperand(OpIdx);
1300 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO);
1301 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1302 dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs["
1303 << InsnID << "], " << OpIdx << ", " << RCEnum
1304 << ")\n");
1305 break;
1306 }
1307
1309 int64_t InsnID = MatchTable[CurrentIdx++];
1310 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1311 constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
1312 RBI);
1313 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1314 dbgs() << CurrentIdx
1315 << ": GIR_ConstrainSelectedInstOperands(OutMIs["
1316 << InsnID << "])\n");
1317 break;
1318 }
1319
1320 case GIR_MergeMemOperands: {
1321 int64_t InsnID = MatchTable[CurrentIdx++];
1322 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1323
1324 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1325 dbgs() << CurrentIdx << ": GIR_MergeMemOperands(OutMIs["
1326 << InsnID << "]");
1327 int64_t MergeInsnID = GIU_MergeMemOperands_EndOfList;
1328 while ((MergeInsnID = MatchTable[CurrentIdx++]) !=
1330 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1331 dbgs() << ", MIs[" << MergeInsnID << "]");
1332 for (const auto &MMO : State.MIs[MergeInsnID]->memoperands())
1333 OutMIs[InsnID].addMemOperand(MMO);
1334 }
1335 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << ")\n");
1336 break;
1337 }
1338
1339 case GIR_EraseFromParent: {
1340 int64_t InsnID = MatchTable[CurrentIdx++];
1341 MachineInstr *MI = State.MIs[InsnID];
1342 assert(MI && "Attempted to erase an undefined instruction");
1343 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1344 dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs["
1345 << InsnID << "])\n");
1346 // If we're erasing the insertion point, ensure we don't leave a dangling
1347 // pointer in the builder.
1348 if (Builder.getInsertPt() == MI)
1349 Builder.setInsertPt(*MI->getParent(), ++MI->getIterator());
1350 if (Observer)
1351 Observer->erasingInstr(*MI);
1352 MI->eraseFromParent();
1353 break;
1354 }
1355
1356 case GIR_MakeTempReg: {
1357 int64_t TempRegID = MatchTable[CurrentIdx++];
1358 int64_t TypeID = MatchTable[CurrentIdx++];
1359
1360 State.TempRegisters[TempRegID] =
1361 MRI.createGenericVirtualRegister(getTypeFromIdx(TypeID));
1362 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1363 dbgs() << CurrentIdx << ": TempRegs[" << TempRegID
1364 << "] = GIR_MakeTempReg(" << TypeID << ")\n");
1365 break;
1366 }
1367 case GIR_ReplaceReg: {
1368 int64_t OldInsnID = MatchTable[CurrentIdx++];
1369 int64_t OldOpIdx = MatchTable[CurrentIdx++];
1370 int64_t NewInsnID = MatchTable[CurrentIdx++];
1371 int64_t NewOpIdx = MatchTable[CurrentIdx++];
1372
1373 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1374 dbgs() << CurrentIdx << ": GIR_ReplaceReg(MIs["
1375 << OldInsnID << "][" << OldOpIdx << "] = MIs["
1376 << NewInsnID << "][" << NewOpIdx << "])\n");
1377
1378 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1379 Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg();
1380 if (Observer)
1381 Observer->changingAllUsesOfReg(MRI, Old);
1382 MRI.replaceRegWith(Old, New);
1383 if (Observer)
1384 Observer->finishedChangingAllUsesOfReg();
1385 break;
1386 }
1388 int64_t OldInsnID = MatchTable[CurrentIdx++];
1389 int64_t OldOpIdx = MatchTable[CurrentIdx++];
1390 int64_t TempRegID = MatchTable[CurrentIdx++];
1391
1392 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1393 dbgs() << CurrentIdx << ": GIR_ReplaceRegWithTempReg(MIs["
1394 << OldInsnID << "][" << OldOpIdx << "] = TempRegs["
1395 << TempRegID << "])\n");
1396
1397 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1398 Register New = State.TempRegisters[TempRegID];
1399 if (Observer)
1400 Observer->changingAllUsesOfReg(MRI, Old);
1401 MRI.replaceRegWith(Old, New);
1402 if (Observer)
1403 Observer->finishedChangingAllUsesOfReg();
1404 break;
1405 }
1406 case GIR_Coverage: {
1407 int64_t RuleID = MatchTable[CurrentIdx++];
1409 CoverageInfo->setCovered(RuleID);
1410
1411 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx
1412 << ": GIR_Coverage("
1413 << RuleID << ")");
1414 break;
1415 }
1416
1417 case GIR_Done:
1418 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1419 dbgs() << CurrentIdx << ": GIR_Done\n");
1420 propagateFlags();
1421 return true;
1422 default:
1423 llvm_unreachable("Unexpected command");
1424 }
1425 }
1426}
1427
1428} // end namespace llvm
1429
1430#endif // LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
unsigned SubReg
unsigned const MachineRegisterInfo * MRI
#define Success
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition: Debug.h:64
uint64_t Size
This contains common code to allow clients to notify changes to machine instr.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineIRBuilder class.
unsigned const TargetRegisterInfo * TRI
Type::TypeID TypeID
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
static constexpr uint32_t Opcode
Definition: aarch32.h:200
Class for arbitrary precision integers.
Definition: APInt.h:76
void setCovered(uint64_t RuleID)
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:888
bool equalsInt(uint64_t V) const
A helper method that can be used to determine if the constant contained within is equal to a constant...
Definition: Constants.h:171
This class represents an Operation in the Expression.
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
Definition: DataLayout.h:410
Tagged union holding either a T or a Error.
Definition: Error.h:474
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition: Function.cpp:341
virtual bool testSimplePredicate(unsigned) const
virtual bool testImmPredicate_APFloat(unsigned, const APFloat &) const
virtual bool testImmPredicate_APInt(unsigned, const APInt &) const
virtual bool testMIPredicate_MI(unsigned, const MachineInstr &, const MatcherState &State) const
virtual bool testImmPredicate_I64(unsigned, int64_t) const
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
bool executeMatchTable(TgtExecutor &Exec, MatcherState &State, const ExecInfoTy< PredicateBitset, ComplexMatcherMemFn, CustomRendererFn > &ExecInfo, MachineIRBuilder &Builder, const int64_t *MatchTable, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, CodeGenCoverage *CoverageInfo) const
Execute a given matcher table and return true if the match was successful and false otherwise.
bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI, bool Splat=false) const
virtual void runCustomAction(unsigned, const MatcherState &State, NewMIVector &OutMIs) const
bool isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const
Return true if MI can obviously be folded into IntoMI.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
void finishedChangingAllUsesOfReg()
All instructions reported as changing by changingAllUsesOfReg() have finished being changed.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
virtual void erasingInstr(MachineInstr &MI)=0
An instruction is about to be erased.
void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition: Type.cpp:285
constexpr unsigned getScalarSizeInBits() const
Definition: LowLevelType.h:257
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:183
constexpr bool isPointer() const
Definition: LowLevelType.h:141
constexpr unsigned getAddressSpace() const
Definition: LowLevelType.h:270
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
Helper class to build MachineInstr.
GISelChangeObserver * getObserver()
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Representation of each machine instruction.
Definition: MachineInstr.h:68
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
A description of a memory reference used in the backend.
unsigned getAddrSpace() const
uint64_t getSize() const
Return the size in bytes of the memory reference.
uint64_t getSizeInBits() const
Return the size in bits of the memory reference.
Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
MachineOperand class - Representation of each machine instruction operand.
const ConstantInt * getCImm() const
bool isCImm() const
isCImm - Test if this is a MO_CImmediate operand.
int64_t getImm() const
bool isPredicate() const
bool isIntrinsicID() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
Intrinsic::ID getIntrinsicID() const
unsigned getPredicate() const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Holds all the information related to register banks.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
virtual const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const
Get a register bank that covers RC.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:95
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
void resize(size_type N)
Definition: SmallVector.h:642
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool isBuildVectorAllZeros(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
Definition: Utils.cpp:1156
Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
Definition: Utils.cpp:53
@ GIU_MergeMemOperands_EndOfList
Indicates the end of the variable-length MergeInsnID list in a GIR_MergeMemOperands opcode.
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition: Utils.cpp:152
MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition: Utils.cpp:465
bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI)
Check if DstReg can be replaced with SrcReg depending on the register constraints.
Definition: Utils.cpp:198
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
bool isBuildVectorAllOnes(const MachineInstr &MI, const MachineRegisterInfo &MRI, bool AllowUndef=false)
Return true if the specified instruction is a G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC where all of the...
Definition: Utils.cpp:1162
AtomicOrdering
Atomic ordering for LLVM's memory model.
@ GIR_ComplexRenderer
Render complex operands to the specified instruction.
@ GIR_ReplaceRegWithTempReg
Replaces all references to a register with a temporary register.
@ GIR_ComplexSubOperandRenderer
Render sub-operands of complex operands to the specified instruction.
@ GIR_MakeTempReg
Create a new temporary register that's not constrained.
@ GIM_CheckMemorySizeEqualTo
Check the size of the memory access for the given machine memory operand.
@ GIR_Done
A successful emission.
@ GIM_RecordNamedOperand
Predicates with 'let PredicateCodeUsesOperands = 1' need to examine some named operands that will be ...
@ GIM_Try
Begin a try-block to attempt a match and jump to OnFail if it is unsuccessful.
@ GIM_CheckIsBuildVectorAllOnes
Check if this is a vector that can be treated as a vector splat constant.
@ GIM_CheckNumOperands
Check the instruction has the right number of operands.
@ GIR_AddCImm
Add an CImm to the specified instruction.
@ GIR_ConstrainOperandRC
Constrain an instruction operand to a register class.
@ GIM_CheckI64ImmPredicate
Check an immediate predicate on the specified instruction.
@ GIR_AddImplicitDef
Add an implicit register def to the specified instruction.
@ GIM_CheckAPIntImmPredicate
Check an immediate predicate on the specified instruction via an APInt.
@ GIM_CheckHasNoUse
Check if there's no use of the first result.
@ GIM_CheckPointerToAny
Check the type of a pointer to any address space.
@ GIM_CheckMemorySizeEqualToLLT
Check the size of the memory access for the given machine memory operand against the size of an opera...
@ GIM_CheckComplexPattern
Check the operand matches a complex predicate.
@ GIR_CopyConstantAsSImm
Render a G_CONSTANT operator as a sign-extended immediate.
@ GIR_EraseFromParent
Erase from parent.
@ GIR_CustomAction
Calls a C++ function to perform an action when a match is complete.
@ GIM_SwitchType
Switch over the LLT on the specified instruction operand.
@ GIR_CopySubReg
Copy an operand to the specified instruction.
@ GIR_MutateOpcode
Mutate an instruction.
@ GIM_CheckIsBuildVectorAllZeros
@ GIM_CheckAtomicOrderingOrStrongerThan
@ GIR_AddRegister
Add an register to the specified instruction.
@ GIR_AddTempSubRegister
Add a temporary register to the specified instruction.
@ GIM_CheckIsSafeToFold
Check if the specified operand is safe to fold into the current instruction.
@ GIM_CheckOpcode
Check the opcode on the specified instruction.
@ GIR_ReplaceReg
Replaces all references to a register from an instruction with another register from another instruct...
@ GIM_SwitchOpcode
Switch over the opcode on the specified instruction.
@ GIM_CheckAPFloatImmPredicate
Check a floating point immediate predicate on the specified instruction.
@ GIM_Reject
Fail the current try-block, or completely fail to match if there is no current try-block.
@ GIR_AddTempRegister
Add a temporary register to the specified instruction.
@ GIR_Copy
Copy an operand to the specified instruction.
@ GIR_AddImm
Add an immediate to the specified instruction.
@ GIR_CopyFConstantAsFPImm
Render a G_FCONSTANT operator as a sign-extended immediate.
@ GIM_MIFlags
Check that a matched instruction has, or doesn't have a MIFlag.
@ GIR_CopyOrAddZeroReg
Copy an operand to the specified instruction or add a zero register if the operand is a zero immediat...
@ GIM_CheckMemoryAlignment
Check the minimum alignment of the memory access for the given machine memory operand.
@ GIM_CheckIsSameOperand
Check the specified operands are identical.
@ GIM_CheckIsSameOperandIgnoreCopies
@ GIM_CheckIsMBB
Check the specified operand is an MBB.
@ GIM_CheckMemorySizeGreaterThanLLT
@ GIM_CheckRegBankForClass
Check the register bank for the specified operand.
@ GIM_CheckLiteralInt
Check the operand is a specific literal integer (i.e.
@ GIM_CheckMemorySizeLessThanLLT
@ GIM_RecordRegType
Records an operand's register type into the set of temporary types.
@ GIR_CopyMIFlags
Copy the MIFlags of a matched instruction into an output instruction.
@ GIR_BuildMI
Build a new instruction.
@ GIM_RecordInsn
Record the specified instruction.
@ GIM_CheckIsImm
Check the specified operand is an Imm.
@ GIM_CheckFeatures
Check the feature bits.
@ GIM_CheckCanReplaceReg
Check we can replace all uses of a register with another.
@ GIM_CheckMemoryAddressSpace
Check the address space of the memory access for the given machine memory operand.
@ GIR_CustomRenderer
Render operands to the specified instruction using a custom function.
@ GIM_CheckAtomicOrdering
Check a memory operation has the specified atomic ordering.
@ GIM_CheckType
Check the type for the specified operand.
@ GIM_CheckCmpPredicate
Check the operand is a specific predicate.
@ GIM_CheckOpcodeIsEither
Check the opcode on the specified instruction, checking 2 acceptable alternatives.
@ GIR_SetImplicitDefDead
Marks the implicit def of a register as dead.
@ GIR_BuildConstant
Builds a constant and stores its result in a TempReg.
@ GIR_AddImplicitUse
Add an implicit register use to the specified instruction.
@ GIR_Coverage
Increment the rule coverage counter.
@ GIR_MergeMemOperands
Merge all memory operands into instruction.
@ GIM_CheckImmOperandPredicate
Check an immediate predicate on the specified instruction.
@ GIM_CheckAtomicOrderingWeakerThan
@ GIR_SetMIFlags
Set or unset a MIFlag on an instruction.
@ GIM_CheckIntrinsicID
Check the operand is a specific intrinsic ID.
@ GIM_CheckConstantInt
Check the operand is a specific integer.
@ GIR_ComplexSubOperandSubRegRenderer
Render subregisters of suboperands of complex operands to the specified instruction.
@ GIM_RecordInsnIgnoreCopies
@ GIR_CustomOperandRenderer
Render operands to the specified instruction using a custom function, reading from a specific operand...
@ GIR_ConstrainSelectedInstOperands
Constrain an instructions operands according to the instruction description.
@ GIM_CheckCxxInsnPredicate
Check a generic C++ instruction predicate.
@ GIM_CheckSimplePredicate
Check a trivial predicate which takes no arguments.
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
A and B are either alignments or offsets.
Definition: MathExtras.h:338
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition: MathExtras.h:452
@ GICXXCustomAction_Invalid
Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition: Utils.cpp:472
@ Default
The result values are uniform if and only if all operands are uniform.
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
SmallDenseMap< LLT, unsigned, 64 > TypeIDMap
const ComplexMatcherMemFn * ComplexPredicates
std::array< const MachineOperand *, 3 > RecordedOperands
Named operands that predicate with 'let PredicateCodeUsesOperands = 1' referenced in its argument lis...
SmallVector< LLT, 4 > RecordedTypes
Types extracted from an instruction's operand.
DenseMap< unsigned, unsigned > TempRegisters
std::vector< ComplexRendererFns::value_type > Renderers