LLVM 23.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
29#include "llvm/IR/Constants.h"
30#include "llvm/IR/DataLayout.h"
31#include "llvm/IR/Type.h"
33#include "llvm/Support/Debug.h"
35#include <cassert>
36#include <cstddef>
37#include <cstdint>
38
39namespace llvm {
40
41template <class TgtExecutor, class PredicateBitset, class ComplexMatcherMemFn,
42 class CustomRendererFn>
44 TgtExecutor &Exec, MatcherState &State,
46 &ExecInfo,
47 MachineIRBuilder &Builder, const uint8_t *MatchTable,
49 const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI,
50 const PredicateBitset &AvailableFeatures,
52
53 uint64_t CurrentIdx = 0;
54 SmallVector<uint64_t, 4> OnFailResumeAt;
55 NewMIVector OutMIs;
56
57 GISelChangeObserver *Observer = Builder.getObserver();
58 // Bypass the flag check on the instruction, and only look at the MCInstrDesc.
59 bool NoFPException = !State.MIs[0]->getDesc().mayRaiseFPException();
60
61 const uint32_t Flags = State.MIs[0]->getFlags();
62 bool BuilderInitialized = false;
63 const auto initializeBuilder = [&]() {
64 if (BuilderInitialized)
65 return;
66 // Delay setting the insertion point and debug location until a successful
67 // action needs the builder.
68 Builder.setInstrAndDebugLoc(*State.MIs[0]);
69 BuilderInitialized = true;
70 };
71
72 enum RejectAction { RejectAndGiveUp, RejectAndResume };
73 auto handleReject = [&]() -> RejectAction {
74 DEBUG_WITH_TYPE(TgtExecutor::getName(),
75 dbgs() << CurrentIdx << ": Rejected\n");
76 if (OnFailResumeAt.empty())
77 return RejectAndGiveUp;
78 CurrentIdx = OnFailResumeAt.pop_back_val();
79 DEBUG_WITH_TYPE(TgtExecutor::getName(),
80 dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " ("
81 << OnFailResumeAt.size() << " try-blocks remain)\n");
82 return RejectAndResume;
83 };
84
85 const auto propagateFlags = [&]() {
86 for (auto MIB : OutMIs) {
87 // Set the NoFPExcept flag when no original matched instruction could
88 // raise an FP exception, but the new instruction potentially might.
89 uint32_t MIBFlags = Flags | MIB.getInstr()->getFlags();
90 if (NoFPException && MIB->mayRaiseFPException())
91 MIBFlags |= MachineInstr::NoFPExcept;
92 if (Observer)
93 Observer->changingInstr(*MIB);
94 MIB.setMIFlags(MIBFlags);
95 if (Observer)
96 Observer->changedInstr(*MIB);
97 }
98 };
99
100 // If the index is >= 0, it's an index in the type objects generated by
101 // TableGen. If the index is <0, it's an index in the recorded types object.
102 const auto getTypeFromIdx = [&](int64_t Idx) -> LLT {
103 if (Idx >= 0)
104 return ExecInfo.TypeObjects[Idx];
105 return State.RecordedTypes[1 - Idx];
106 };
107
108 const auto readULEB = [&]() {
109 return fastDecodeULEB128(MatchTable, CurrentIdx);
110 };
111
112 // Convenience function to return a signed value. This avoids
113 // us forgetting to first cast to int8_t before casting to a
114 // wider signed int type.
115 // if we casted uint8 directly to a wider type we'd lose
116 // negative values.
117 const auto readS8 = [&]() { return (int8_t)MatchTable[CurrentIdx++]; };
118
119 const auto readU16 = [&]() {
120 auto V = readBytesAs<uint16_t>(MatchTable + CurrentIdx);
121 CurrentIdx += 2;
122 return V;
123 };
124
125 const auto readU32 = [&]() {
126 auto V = readBytesAs<uint32_t>(MatchTable + CurrentIdx);
127 CurrentIdx += 4;
128 return V;
129 };
130
131 const auto readU64 = [&]() {
132 auto V = readBytesAs<uint64_t>(MatchTable + CurrentIdx);
133 CurrentIdx += 8;
134 return V;
135 };
136
137 const auto eraseImpl = [&](MachineInstr *MI) {
138 initializeBuilder();
139 // If we're erasing the insertion point, ensure we don't leave a dangling
140 // pointer in the builder.
141 if (Builder.getInsertPt() == MI)
142 Builder.setInsertPt(*MI->getParent(), ++MI->getIterator());
143 if (Observer)
144 Observer->erasingInstr(*MI);
145 MI->eraseFromParent();
146 };
147
148 while (true) {
149 assert(CurrentIdx != ~0u && "Invalid MatchTable index");
150 uint8_t MatcherOpcode = MatchTable[CurrentIdx++];
151 switch (MatcherOpcode) {
152 case GIM_Try: {
153 DEBUG_WITH_TYPE(TgtExecutor::getName(),
154 dbgs() << CurrentIdx << ": Begin try-block\n");
155 OnFailResumeAt.push_back(readU32());
156 break;
157 }
159 // This is optimized so that if the feature is not present, we don't even
160 // modify OnFailResumeAt. Instead we directly jump to OnFail.
161 unsigned OnFail = readU32();
162 uint16_t ExpectedBitsetID = readU16();
163 DEBUG_WITH_TYPE(TgtExecutor::getName(),
164 dbgs() << CurrentIdx
165 << ": GIM_Try_CheckFeatures(ExpectedBitsetID="
166 << ExpectedBitsetID << ")\n");
167 if ((AvailableFeatures & ExecInfo.FeatureBitsets[ExpectedBitsetID]) !=
168 ExecInfo.FeatureBitsets[ExpectedBitsetID]) {
169 DEBUG_WITH_TYPE(TgtExecutor::getName(),
170 dbgs() << CurrentIdx
171 << ": Features do not match, rejected\n");
172 CurrentIdx = OnFail;
173 } else {
174 OnFailResumeAt.push_back(OnFail);
175 }
176 break;
177 }
178 case GIM_RecordInsn:
180 uint64_t NewInsnID = readULEB();
181 uint64_t InsnID = readULEB();
182 uint64_t OpIdx = readULEB();
183
184 // As an optimisation we require that MIs[0] is always the root. Refuse
185 // any attempt to modify it.
186 assert(NewInsnID != 0 && "Refusing to modify MIs[0]");
187
188 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
189 if (!MO.isReg()) {
190 DEBUG_WITH_TYPE(TgtExecutor::getName(),
191 dbgs() << CurrentIdx << ": Not a register\n");
192 if (handleReject() == RejectAndGiveUp)
193 return false;
194 break;
195 }
196 if (MO.getReg().isPhysical()) {
197 DEBUG_WITH_TYPE(TgtExecutor::getName(),
198 dbgs() << CurrentIdx << ": Is a physical register\n");
199 if (handleReject() == RejectAndGiveUp)
200 return false;
201 break;
202 }
203
204 MachineInstr *NewMI;
205 if (MatcherOpcode == GIM_RecordInsnIgnoreCopies)
206 NewMI = getDefIgnoringCopies(MO.getReg(), MRI);
207 else
208 NewMI = MRI.getVRegDef(MO.getReg());
209
210 if ((size_t)NewInsnID < State.MIs.size())
211 State.MIs[NewInsnID] = NewMI;
212 else {
213 assert((size_t)NewInsnID == State.MIs.size() &&
214 "Expected to store MIs in order");
215 State.MIs.push_back(NewMI);
216 }
217 DEBUG_WITH_TYPE(TgtExecutor::getName(),
218 dbgs() << CurrentIdx << ": MIs[" << NewInsnID
219 << "] = GIM_RecordInsn(" << InsnID << ", " << OpIdx
220 << ")\n");
221 break;
222 }
223 case GIM_CheckOpcode:
225 uint64_t InsnID = readULEB();
226 uint16_t Expected0 = readU16();
227 uint16_t Expected1 = -1;
228 if (MatcherOpcode == GIM_CheckOpcodeIsEither)
229 Expected1 = readU16();
230
231 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
232 unsigned Opcode = State.MIs[InsnID]->getOpcode();
233
234 DEBUG_WITH_TYPE(TgtExecutor::getName(), {
235 dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID
236 << "], ExpectedOpcode=" << Expected0;
237 if (MatcherOpcode == GIM_CheckOpcodeIsEither)
238 dbgs() << " || " << Expected1;
239 dbgs() << ") // Got=" << Opcode << "\n";
240 });
241
242 if (Opcode != Expected0 && Opcode != Expected1) {
243 if (handleReject() == RejectAndGiveUp)
244 return false;
245 }
246 break;
247 }
248 case GIM_SwitchOpcode: {
249 uint64_t InsnID = readULEB();
250 uint16_t LowerBound = readU16();
251 uint16_t UpperBound = readU16();
252 uint32_t Default = readU32();
253
254 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
255 const int64_t Opcode = State.MIs[InsnID]->getOpcode();
256
257 DEBUG_WITH_TYPE(TgtExecutor::getName(), {
258 dbgs() << CurrentIdx << ": GIM_SwitchOpcode(MIs[" << InsnID << "], ["
259 << LowerBound << ", " << UpperBound << "), Default=" << Default
260 << ", JumpTable...) // Got=" << Opcode << "\n";
261 });
262 if (Opcode < LowerBound || UpperBound <= Opcode) {
263 CurrentIdx = Default;
264 break;
265 }
266 const auto EntryIdx = (Opcode - LowerBound);
267 // Each entry is 4 bytes
268 CurrentIdx =
269 readBytesAs<uint32_t>(MatchTable + CurrentIdx + (EntryIdx * 4));
270 if (!CurrentIdx) {
271 CurrentIdx = Default;
272 break;
273 }
274 OnFailResumeAt.push_back(Default);
275 break;
276 }
277
278 case GIM_SwitchType:
279 case GIM_SwitchTypeShape: {
280 uint64_t InsnID = readULEB();
281 uint64_t OpIdx = readULEB();
282 uint16_t LowerBound = readU16();
283 uint16_t UpperBound = readU16();
284 int64_t Default = readU32();
285 bool IsShape = MatcherOpcode == GIM_SwitchTypeShape;
286
287 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
288 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
289
290 DEBUG_WITH_TYPE(TgtExecutor::getName(), {
291 dbgs() << CurrentIdx << ": GIM_SwitchType" << (IsShape ? "Shape" : "")
292 << "(MIs[" << InsnID << "]->getOperand(" << OpIdx << "), ["
293 << LowerBound << ", " << UpperBound << "), Default=" << Default
294 << ", JumpTable...) // Got=";
295 if (!MO.isReg())
296 dbgs() << "Not a VReg\n";
297 else
298 dbgs() << MRI.getType(MO.getReg()) << "\n";
299 });
300 if (!MO.isReg()) {
301 CurrentIdx = Default;
302 break;
303 }
304
305 LLT Ty = MRI.getType(MO.getReg());
306 if (IsShape)
307 Ty = Ty.changeElementType(LLT::scalar(Ty.getScalarSizeInBits()));
308
309 const auto TyI = ExecInfo.TypeIDMap.find(Ty.getUniqueRAWLLTData());
310 if (TyI == ExecInfo.TypeIDMap.end()) {
311 CurrentIdx = Default;
312 break;
313 }
314 const int64_t TypeID = TyI->second;
315 if (TypeID < LowerBound || UpperBound <= TypeID) {
316 CurrentIdx = Default;
317 break;
318 }
319 const auto NumEntry = (TypeID - LowerBound);
320 // Each entry is 4 bytes
321 CurrentIdx =
322 readBytesAs<uint32_t>(MatchTable + CurrentIdx + (NumEntry * 4));
323 if (!CurrentIdx) {
324 CurrentIdx = Default;
325 break;
326 }
327 OnFailResumeAt.push_back(Default);
328 break;
329 }
330
333 uint64_t InsnID = readULEB();
334 uint64_t Expected = readULEB();
335 const bool IsLE = (MatcherOpcode == GIM_CheckNumOperandsLE);
336 DEBUG_WITH_TYPE(TgtExecutor::getName(),
337 dbgs() << CurrentIdx << ": GIM_CheckNumOperands"
338 << (IsLE ? "LE" : "GE") << "(MIs[" << InsnID
339 << "], Expected=" << Expected << ")\n");
340 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
341 const unsigned NumOps = State.MIs[InsnID]->getNumOperands();
342 if (IsLE ? (NumOps > Expected) : (NumOps < Expected)) {
343 if (handleReject() == RejectAndGiveUp)
344 return false;
345 }
346 break;
347 }
349 uint64_t InsnID = readULEB();
350 uint64_t Expected = readULEB();
351 DEBUG_WITH_TYPE(TgtExecutor::getName(),
352 dbgs() << CurrentIdx << ": GIM_CheckNumOperands(MIs["
353 << InsnID << "], Expected=" << Expected << ")\n");
354 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
355 if (State.MIs[InsnID]->getNumOperands() != Expected) {
356 if (handleReject() == RejectAndGiveUp)
357 return false;
358 }
359 break;
360 }
363 uint64_t InsnID = readULEB();
364 unsigned OpIdx =
365 MatcherOpcode == GIM_CheckImmOperandPredicate ? readULEB() : 1;
366 uint16_t Predicate = readU16();
367 DEBUG_WITH_TYPE(TgtExecutor::getName(),
368 dbgs() << CurrentIdx << ": GIM_CheckImmPredicate(MIs["
369 << InsnID << "]->getOperand(" << OpIdx
370 << "), Predicate=" << Predicate << ")\n");
371 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
372 assert((State.MIs[InsnID]->getOperand(OpIdx).isImm() ||
373 State.MIs[InsnID]->getOperand(OpIdx).isCImm()) &&
374 "Expected immediate operand");
375 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
376 int64_t Value = 0;
377 if (State.MIs[InsnID]->getOperand(OpIdx).isCImm())
378 Value = State.MIs[InsnID]->getOperand(OpIdx).getCImm()->getSExtValue();
379 else if (State.MIs[InsnID]->getOperand(OpIdx).isImm())
380 Value = State.MIs[InsnID]->getOperand(OpIdx).getImm();
381 else
382 llvm_unreachable("Expected Imm or CImm operand");
383
385 if (handleReject() == RejectAndGiveUp)
386 return false;
387 break;
388 }
390 uint64_t InsnID = readULEB();
391 uint16_t Predicate = readU16();
392 DEBUG_WITH_TYPE(TgtExecutor::getName(),
393 dbgs()
394 << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs["
395 << InsnID << "], Predicate=" << Predicate << ")\n");
396 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
397 assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
398 "Expected G_CONSTANT");
399 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
400 if (!State.MIs[InsnID]->getOperand(1).isCImm())
401 llvm_unreachable("Expected Imm or CImm operand");
402
403 const APInt &Value =
404 State.MIs[InsnID]->getOperand(1).getCImm()->getValue();
406 if (handleReject() == RejectAndGiveUp)
407 return false;
408 break;
409 }
411 uint64_t InsnID = readULEB();
412 uint16_t Predicate = readU16();
413 DEBUG_WITH_TYPE(TgtExecutor::getName(),
414 dbgs()
415 << CurrentIdx << ": GIM_CheckAPFloatImmPredicate(MIs["
416 << InsnID << "], Predicate=" << Predicate << ")\n");
417 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
418 assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
419 "Expected G_FCONSTANT");
420 assert(State.MIs[InsnID]->getOperand(1).isFPImm() &&
421 "Expected FPImm operand");
422 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
423 const APFloat &Value =
424 State.MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF();
425
427 if (handleReject() == RejectAndGiveUp)
428 return false;
429 break;
430 }
432 uint64_t InsnID = readULEB();
433 uint64_t OpIdx = readULEB();
434 uint16_t Predicate = readU16();
435 DEBUG_WITH_TYPE(TgtExecutor::getName(),
436 dbgs() << CurrentIdx
437 << ": GIM_CheckLeafOperandPredicate(MIs[" << InsnID
438 << "]->getOperand(" << OpIdx
439 << "), Predicate=" << Predicate << ")\n");
440 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
441 assert(State.MIs[InsnID]->getOperand(OpIdx).isReg() &&
442 "Expected register operand");
443 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
444 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
445
446 if (!testMOPredicate_MO(Predicate, MO, State))
447 if (handleReject() == RejectAndGiveUp)
448 return false;
449 break;
450 }
453 uint64_t InsnID = readULEB();
454
455 DEBUG_WITH_TYPE(TgtExecutor::getName(),
456 dbgs() << CurrentIdx
457 << ": GIM_CheckBuildVectorAll{Zeros|Ones}(MIs["
458 << InsnID << "])\n");
459 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
460
461 const MachineInstr *MI = State.MIs[InsnID];
462 assert((MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR ||
463 MI->getOpcode() == TargetOpcode::G_BUILD_VECTOR_TRUNC) &&
464 "Expected G_BUILD_VECTOR or G_BUILD_VECTOR_TRUNC");
465
466 if (MatcherOpcode == GIM_CheckIsBuildVectorAllOnes) {
467 if (!isBuildVectorAllOnes(*MI, MRI)) {
468 if (handleReject() == RejectAndGiveUp)
469 return false;
470 }
471 } else {
472 if (!isBuildVectorAllZeros(*MI, MRI)) {
473 if (handleReject() == RejectAndGiveUp)
474 return false;
475 }
476 }
477
478 break;
479 }
481 // Note: we don't check for invalid here because this is purely a hook to
482 // allow some executors (such as the combiner) to check arbitrary,
483 // contextless predicates, such as whether a rule is enabled or not.
484 uint16_t Predicate = readU16();
485 DEBUG_WITH_TYPE(TgtExecutor::getName(),
486 dbgs() << CurrentIdx
487 << ": GIM_CheckSimplePredicate(Predicate="
488 << Predicate << ")\n");
489 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
491 if (handleReject() == RejectAndGiveUp)
492 return false;
493 }
494 break;
495 }
497 uint64_t InsnID = readULEB();
498 uint16_t Predicate = readU16();
499 DEBUG_WITH_TYPE(TgtExecutor::getName(),
500 dbgs()
501 << CurrentIdx << ": GIM_CheckCxxPredicate(MIs["
502 << InsnID << "], Predicate=" << Predicate << ")\n");
503 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
504 assert(Predicate > GICXXPred_Invalid && "Expected a valid predicate");
505
506 if (!testMIPredicate_MI(Predicate, *State.MIs[InsnID], State))
507 if (handleReject() == RejectAndGiveUp)
508 return false;
509 break;
510 }
511 case GIM_CheckHasNoUse: {
512 uint64_t InsnID = readULEB();
513
514 DEBUG_WITH_TYPE(TgtExecutor::getName(),
515 dbgs() << CurrentIdx << ": GIM_CheckHasNoUse(MIs["
516 << InsnID << "]\n");
517
518 const MachineInstr *MI = State.MIs[InsnID];
519 assert(MI && "Used insn before defined");
520 assert(MI->getNumDefs() > 0 && "No defs");
521 const Register Res = MI->getOperand(0).getReg();
522
523 if (!MRI.use_nodbg_empty(Res)) {
524 if (handleReject() == RejectAndGiveUp)
525 return false;
526 }
527 break;
528 }
529 case GIM_CheckHasOneUse: {
530 uint64_t InsnID = readULEB();
531
532 DEBUG_WITH_TYPE(TgtExecutor::getName(),
533 dbgs() << CurrentIdx << ": GIM_CheckHasOneUse(MIs["
534 << InsnID << "]\n");
535
536 const MachineInstr *MI = State.MIs[InsnID];
537 assert(MI && "Used insn before defined");
538 assert(MI->getNumDefs() > 0 && "No defs");
539 const Register Res = MI->getOperand(0).getReg();
540
541 if (!MRI.hasOneNonDBGUse(Res)) {
542 if (handleReject() == RejectAndGiveUp)
543 return false;
544 }
545 break;
546 }
548 uint64_t InsnID = readULEB();
549 auto Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
550 DEBUG_WITH_TYPE(TgtExecutor::getName(),
551 dbgs() << CurrentIdx << ": GIM_CheckAtomicOrdering(MIs["
552 << InsnID << "], " << (uint64_t)Ordering << ")\n");
553 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
554 if (!State.MIs[InsnID]->hasOneMemOperand())
555 if (handleReject() == RejectAndGiveUp)
556 return false;
557
558 for (const auto &MMO : State.MIs[InsnID]->memoperands())
559 if (MMO->getMergedOrdering() != Ordering)
560 if (handleReject() == RejectAndGiveUp)
561 return false;
562 break;
563 }
565 uint64_t InsnID = readULEB();
566 auto Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
567 DEBUG_WITH_TYPE(TgtExecutor::getName(),
568 dbgs() << CurrentIdx
569 << ": GIM_CheckAtomicOrderingOrStrongerThan(MIs["
570 << InsnID << "], " << (uint64_t)Ordering << ")\n");
571 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
572 if (!State.MIs[InsnID]->hasOneMemOperand())
573 if (handleReject() == RejectAndGiveUp)
574 return false;
575
576 for (const auto &MMO : State.MIs[InsnID]->memoperands())
577 if (!isAtLeastOrStrongerThan(MMO->getMergedOrdering(), Ordering))
578 if (handleReject() == RejectAndGiveUp)
579 return false;
580 break;
581 }
583 uint64_t InsnID = readULEB();
584 auto Ordering = (AtomicOrdering)MatchTable[CurrentIdx++];
585 DEBUG_WITH_TYPE(TgtExecutor::getName(),
586 dbgs() << CurrentIdx
587 << ": GIM_CheckAtomicOrderingWeakerThan(MIs["
588 << InsnID << "], " << (uint64_t)Ordering << ")\n");
589 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
590 if (!State.MIs[InsnID]->hasOneMemOperand())
591 if (handleReject() == RejectAndGiveUp)
592 return false;
593
594 for (const auto &MMO : State.MIs[InsnID]->memoperands())
595 if (!isStrongerThan(Ordering, MMO->getMergedOrdering()))
596 if (handleReject() == RejectAndGiveUp)
597 return false;
598 break;
599 }
601 uint64_t InsnID = readULEB();
602 uint64_t MMOIdx = readULEB();
603 // This accepts a list of possible address spaces.
604 const uint64_t NumAddrSpace = MatchTable[CurrentIdx++];
605
606 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
607 if (handleReject() == RejectAndGiveUp)
608 return false;
609 break;
610 }
611
612 // Need to still jump to the end of the list of address spaces if we find
613 // a match earlier.
614 const uint64_t LastIdx = CurrentIdx + NumAddrSpace;
615
616 const MachineMemOperand *MMO =
617 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
618 const unsigned MMOAddrSpace = MMO->getAddrSpace();
619
620 bool Success = false;
621 for (unsigned I = 0; I != NumAddrSpace; ++I) {
622 uint64_t AddrSpace = readULEB();
623 DEBUG_WITH_TYPE(TgtExecutor::getName(),
624 dbgs() << "addrspace(" << MMOAddrSpace << ") vs "
625 << AddrSpace << '\n');
626
627 if (AddrSpace == MMOAddrSpace) {
628 Success = true;
629 break;
630 }
631 }
632
633 CurrentIdx = LastIdx;
634 if (!Success && handleReject() == RejectAndGiveUp)
635 return false;
636 break;
637 }
639 uint64_t InsnID = readULEB();
640 uint64_t MMOIdx = readULEB();
641 uint64_t MinAlign = MatchTable[CurrentIdx++];
642
643 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
644
645 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
646 if (handleReject() == RejectAndGiveUp)
647 return false;
648 break;
649 }
650
651 MachineMemOperand *MMO =
652 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
653 DEBUG_WITH_TYPE(TgtExecutor::getName(),
654 dbgs() << CurrentIdx << ": GIM_CheckMemoryAlignment"
655 << "(MIs[" << InsnID << "]->memoperands() + "
656 << MMOIdx << ")->getAlignment() >= " << MinAlign
657 << ")\n");
658 if (MMO->getAlign() < MinAlign && handleReject() == RejectAndGiveUp)
659 return false;
660
661 break;
662 }
664 uint64_t InsnID = readULEB();
665 uint64_t MMOIdx = readULEB();
666 uint32_t Size = readU32();
667
668 DEBUG_WITH_TYPE(TgtExecutor::getName(),
669 dbgs() << CurrentIdx << ": GIM_CheckMemorySizeEqual(MIs["
670 << InsnID << "]->memoperands() + " << MMOIdx
671 << ", Size=" << Size << ")\n");
672 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
673
674 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
675 if (handleReject() == RejectAndGiveUp)
676 return false;
677 break;
678 }
679
680 MachineMemOperand *MMO =
681 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
682
683 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << MMO->getSize()
684 << " bytes vs " << Size
685 << " bytes\n");
686 if (MMO->getSize() != Size)
687 if (handleReject() == RejectAndGiveUp)
688 return false;
689
690 break;
691 }
695 uint64_t InsnID = readULEB();
696 uint64_t MMOIdx = readULEB();
697 uint64_t OpIdx = readULEB();
698
700 TgtExecutor::getName(),
701 dbgs() << CurrentIdx << ": GIM_CheckMemorySize"
702 << (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT ? "EqualTo"
703 : MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT
704 ? "GreaterThan"
705 : "LessThan")
706 << "LLT(MIs[" << InsnID << "]->memoperands() + " << MMOIdx
707 << ", OpIdx=" << OpIdx << ")\n");
708 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
709
710 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
711 if (!MO.isReg()) {
712 DEBUG_WITH_TYPE(TgtExecutor::getName(),
713 dbgs() << CurrentIdx << ": Not a register\n");
714 if (handleReject() == RejectAndGiveUp)
715 return false;
716 break;
717 }
718
719 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
720 if (handleReject() == RejectAndGiveUp)
721 return false;
722 break;
723 }
724
725 MachineMemOperand *MMO =
726 *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
727
728 const TypeSize Size = MRI.getType(MO.getReg()).getSizeInBits();
729 if (MatcherOpcode == GIM_CheckMemorySizeEqualToLLT &&
730 MMO->getSizeInBits() != Size) {
731 if (handleReject() == RejectAndGiveUp)
732 return false;
733 } else if (MatcherOpcode == GIM_CheckMemorySizeLessThanLLT &&
735 if (handleReject() == RejectAndGiveUp)
736 return false;
737 } else if (MatcherOpcode == GIM_CheckMemorySizeGreaterThanLLT &&
739 if (handleReject() == RejectAndGiveUp)
740 return false;
741
742 break;
743 }
745 case GIM_CheckType: {
746 uint64_t InsnID = (MatcherOpcode == GIM_RootCheckType) ? 0 : readULEB();
747 uint64_t OpIdx = readULEB();
748 int TypeID = readS8();
749 DEBUG_WITH_TYPE(TgtExecutor::getName(),
750 dbgs() << CurrentIdx << ": GIM_CheckType(MIs[" << InsnID
751 << "]->getOperand(" << OpIdx
752 << "), TypeID=" << TypeID << ")\n");
753 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
754 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
755 if (!MO.isReg() || MRI.getType(MO.getReg()) != getTypeFromIdx(TypeID)) {
756 if (handleReject() == RejectAndGiveUp)
757 return false;
758 }
759 break;
760 }
762 uint64_t InsnID = readULEB();
763 uint64_t OpIdx = readULEB();
764 uint64_t SizeInBits = readULEB();
765
766 DEBUG_WITH_TYPE(TgtExecutor::getName(),
767 dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs["
768 << InsnID << "]->getOperand(" << OpIdx
769 << "), SizeInBits=" << SizeInBits << ")\n");
770 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
771 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
772 const LLT Ty = MRI.getType(MO.getReg());
773
774 // iPTR must be looked up in the target.
775 if (SizeInBits == 0) {
776 MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent();
777 const unsigned AddrSpace = Ty.getAddressSpace();
778 SizeInBits = MF->getDataLayout().getPointerSizeInBits(AddrSpace);
779 }
780
781 assert(SizeInBits != 0 && "Pointer size must be known");
782
783 if (MO.isReg()) {
784 if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits)
785 if (handleReject() == RejectAndGiveUp)
786 return false;
787 } else if (handleReject() == RejectAndGiveUp)
788 return false;
789
790 break;
791 }
793 uint64_t InsnID = readULEB();
794 uint64_t OpIdx = readULEB();
795 uint64_t StoreIdx = readULEB();
796
797 DEBUG_WITH_TYPE(TgtExecutor::getName(),
798 dbgs() << CurrentIdx << ": GIM_RecordNamedOperand(MIs["
799 << InsnID << "]->getOperand(" << OpIdx
800 << "), StoreIdx=" << StoreIdx << ")\n");
801 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
802 assert(StoreIdx < State.RecordedOperands.size() && "Index out of range");
803 State.RecordedOperands[StoreIdx] = &State.MIs[InsnID]->getOperand(OpIdx);
804 break;
805 }
806 case GIM_RecordRegType: {
807 uint64_t InsnID = readULEB();
808 uint64_t OpIdx = readULEB();
809 int TypeIdx = readS8();
810
811 DEBUG_WITH_TYPE(TgtExecutor::getName(),
812 dbgs() << CurrentIdx << ": GIM_RecordRegType(MIs["
813 << InsnID << "]->getOperand(" << OpIdx
814 << "), TypeIdx=" << TypeIdx << ")\n");
815 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
816 assert(TypeIdx < 0 && "Temp types always have negative indexes!");
817 // Indexes start at -1.
818 TypeIdx = 1 - TypeIdx;
819 const auto &Op = State.MIs[InsnID]->getOperand(OpIdx);
820 if (State.RecordedTypes.size() <= (uint64_t)TypeIdx)
821 State.RecordedTypes.resize(TypeIdx + 1, LLT());
822 State.RecordedTypes[TypeIdx] = MRI.getType(Op.getReg());
823 break;
824 }
825
828 uint64_t InsnID =
829 (MatcherOpcode == GIM_RootCheckRegBankForClass) ? 0 : readULEB();
830 uint64_t OpIdx = readULEB();
831 uint16_t RCEnum = readU16();
832 DEBUG_WITH_TYPE(TgtExecutor::getName(),
833 dbgs() << CurrentIdx << ": GIM_CheckRegBankForClass(MIs["
834 << InsnID << "]->getOperand(" << OpIdx
835 << "), RCEnum=" << RCEnum << ")\n");
836 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
837 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
838 if (!MO.isReg() ||
839 &RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum),
840 MRI.getType(MO.getReg())) !=
841 RBI.getRegBank(MO.getReg(), MRI, TRI)) {
842 if (handleReject() == RejectAndGiveUp)
843 return false;
844 }
845 break;
846 }
847
849 uint64_t InsnID = readULEB();
850 uint64_t OpIdx = readULEB();
851 uint16_t RendererID = readU16();
852 uint16_t ComplexPredicateID = readU16();
853 DEBUG_WITH_TYPE(TgtExecutor::getName(),
854 dbgs() << CurrentIdx << ": State.Renderers[" << RendererID
855 << "] = GIM_CheckComplexPattern(MIs[" << InsnID
856 << "]->getOperand(" << OpIdx
857 << "), ComplexPredicateID=" << ComplexPredicateID
858 << ")\n");
859 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
860 // FIXME: Use std::invoke() when it's available.
861 ComplexRendererFns Renderer =
862 (Exec.*ExecInfo.ComplexPredicates[ComplexPredicateID])(
863 State.MIs[InsnID]->getOperand(OpIdx));
864 if (Renderer)
865 State.Renderers[RendererID] = *Renderer;
866 else if (handleReject() == RejectAndGiveUp)
867 return false;
868 break;
869 }
870
873 const bool IsInt8 = (MatcherOpcode == GIM_CheckConstantInt8);
874
875 uint64_t InsnID = readULEB();
876 uint64_t OpIdx = readULEB();
877 uint64_t Value = IsInt8 ? (int64_t)readS8() : readU64();
878 DEBUG_WITH_TYPE(TgtExecutor::getName(),
879 dbgs() << CurrentIdx << ": GIM_CheckConstantInt(MIs["
880 << InsnID << "]->getOperand(" << OpIdx
881 << "), Value=" << Value << ")\n");
882 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
883 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
884 if (MO.isReg()) {
885 // isOperandImmEqual() will sign-extend to 64-bits, so should we.
886 LLT Ty = MRI.getType(MO.getReg());
887 // If the type is > 64 bits, it can't be a constant int, so we bail
888 // early because SignExtend64 will assert otherwise.
889 if (Ty.getScalarSizeInBits() > 64) {
890 if (handleReject() == RejectAndGiveUp)
891 return false;
892 break;
893 }
894
895 Value = SignExtend64(Value, Ty.getScalarSizeInBits());
896 if (!isOperandImmEqual(MO, Value, MRI, /*Splat=*/true)) {
897 if (handleReject() == RejectAndGiveUp)
898 return false;
899 }
900 } else if (handleReject() == RejectAndGiveUp)
901 return false;
902
903 break;
904 }
905
906 case GIM_CheckLiteralInt: {
907 uint64_t InsnID = readULEB();
908 uint64_t OpIdx = readULEB();
909 int64_t Value = readU64();
910 DEBUG_WITH_TYPE(TgtExecutor::getName(),
911 dbgs() << CurrentIdx << ": GIM_CheckLiteralInt(MIs["
912 << InsnID << "]->getOperand(" << OpIdx
913 << "), Value=" << Value << ")\n");
914 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
915 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
916 if (MO.isImm() && MO.getImm() == Value)
917 break;
918
919 if (MO.isCImm() && MO.getCImm()->equalsInt(Value))
920 break;
921
922 if (handleReject() == RejectAndGiveUp)
923 return false;
924
925 break;
926 }
927
929 uint64_t InsnID = readULEB();
930 uint64_t OpIdx = readULEB();
931 uint16_t Value = readU16();
932 DEBUG_WITH_TYPE(TgtExecutor::getName(),
933 dbgs() << CurrentIdx << ": GIM_CheckIntrinsicID(MIs["
934 << InsnID << "]->getOperand(" << OpIdx
935 << "), Value=" << Value << ")\n");
936 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
937 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
938 if (!MO.isIntrinsicID() || MO.getIntrinsicID() != Value)
939 if (handleReject() == RejectAndGiveUp)
940 return false;
941 break;
942 }
944 uint64_t InsnID = readULEB();
945 uint64_t OpIdx = readULEB();
946 uint16_t Value = readU16();
947 DEBUG_WITH_TYPE(TgtExecutor::getName(),
948 dbgs() << CurrentIdx << ": GIM_CheckCmpPredicate(MIs["
949 << InsnID << "]->getOperand(" << OpIdx
950 << "), Value=" << Value << ")\n");
951 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
952 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
953 if (!MO.isPredicate() || MO.getPredicate() != Value)
954 if (handleReject() == RejectAndGiveUp)
955 return false;
956 break;
957 }
958 case GIM_CheckIsMBB: {
959 uint64_t InsnID = readULEB();
960 uint64_t OpIdx = readULEB();
961 DEBUG_WITH_TYPE(TgtExecutor::getName(),
962 dbgs() << CurrentIdx << ": GIM_CheckIsMBB(MIs[" << InsnID
963 << "]->getOperand(" << OpIdx << "))\n");
964 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
965 if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB()) {
966 if (handleReject() == RejectAndGiveUp)
967 return false;
968 }
969 break;
970 }
971 case GIM_CheckIsImm: {
972 uint64_t InsnID = readULEB();
973 uint64_t OpIdx = readULEB();
974 DEBUG_WITH_TYPE(TgtExecutor::getName(),
975 dbgs() << CurrentIdx << ": GIM_CheckIsImm(MIs[" << InsnID
976 << "]->getOperand(" << OpIdx << "))\n");
977 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
978 if (!State.MIs[InsnID]->getOperand(OpIdx).isImm()) {
979 if (handleReject() == RejectAndGiveUp)
980 return false;
981 }
982 break;
983 }
985 uint64_t NumInsn = MatchTable[CurrentIdx++];
986 DEBUG_WITH_TYPE(TgtExecutor::getName(),
987 dbgs() << CurrentIdx << ": GIM_CheckIsSafeToFold(N = "
988 << NumInsn << ")\n");
989 MachineInstr &Root = *State.MIs[0];
990 for (unsigned K = 1, E = NumInsn + 1; K < E; ++K) {
991 if (!isObviouslySafeToFold(*State.MIs[K], Root)) {
992 if (handleReject() == RejectAndGiveUp)
993 return false;
994 }
995 }
996 break;
997 }
1000 uint64_t InsnID = readULEB();
1001 uint64_t OpIdx = readULEB();
1002 uint64_t OtherInsnID = readULEB();
1003 uint64_t OtherOpIdx = readULEB();
1004 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1005 dbgs() << CurrentIdx << ": GIM_CheckIsSameOperand(MIs["
1006 << InsnID << "][" << OpIdx << "], MIs["
1007 << OtherInsnID << "][" << OtherOpIdx << "])\n");
1008 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
1009 assert(State.MIs[OtherInsnID] != nullptr && "Used insn before defined");
1010
1011 MachineOperand &Op = State.MIs[InsnID]->getOperand(OpIdx);
1012 MachineOperand &OtherOp = State.MIs[OtherInsnID]->getOperand(OtherOpIdx);
1013
1014 if (MatcherOpcode == GIM_CheckIsSameOperandIgnoreCopies) {
1015 if (Op.isReg() && OtherOp.isReg()) {
1016 if (getSrcRegIgnoringCopies(Op.getReg(), MRI) ==
1017 getSrcRegIgnoringCopies(OtherOp.getReg(), MRI))
1018 break;
1019 }
1020 }
1021
1022 if (!Op.isIdenticalTo(OtherOp)) {
1023 if (handleReject() == RejectAndGiveUp)
1024 return false;
1025 }
1026 break;
1027 }
1029 uint64_t OldInsnID = readULEB();
1030 uint64_t OldOpIdx = readULEB();
1031 uint64_t NewInsnID = readULEB();
1032 uint64_t NewOpIdx = readULEB();
1033
1034 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1035 dbgs() << CurrentIdx << ": GIM_CheckCanReplaceReg(MIs["
1036 << OldInsnID << "][" << OldOpIdx << "] = MIs["
1037 << NewInsnID << "][" << NewOpIdx << "])\n");
1038
1039 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1040 Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg();
1041 if (!canReplaceReg(Old, New, MRI)) {
1042 if (handleReject() == RejectAndGiveUp)
1043 return false;
1044 }
1045 break;
1046 }
1047 case GIM_MIFlags: {
1048 uint64_t InsnID = readULEB();
1049 uint32_t Flags = readU32();
1050
1051 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1052 dbgs() << CurrentIdx << ": GIM_MIFlags(MIs[" << InsnID
1053 << "], " << Flags << ")\n");
1054 if ((State.MIs[InsnID]->getFlags() & Flags) != Flags) {
1055 if (handleReject() == RejectAndGiveUp)
1056 return false;
1057 }
1058 break;
1059 }
1060 case GIM_MIFlagsNot: {
1061 uint64_t InsnID = readULEB();
1062 uint32_t Flags = readU32();
1063
1064 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1065 dbgs() << CurrentIdx << ": GIM_MIFlagsNot(MIs[" << InsnID
1066 << "], " << Flags << ")\n");
1067 if ((State.MIs[InsnID]->getFlags() & Flags)) {
1068 if (handleReject() == RejectAndGiveUp)
1069 return false;
1070 }
1071 break;
1072 }
1073 case GIM_Reject:
1074 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1075 dbgs() << CurrentIdx << ": GIM_Reject\n");
1076 if (handleReject() == RejectAndGiveUp)
1077 return false;
1078 break;
1079 case GIR_MutateOpcode: {
1080 uint64_t OldInsnID = readULEB();
1081 uint64_t NewInsnID = readULEB();
1082 uint32_t NewOpcode = readU16();
1083 if (NewInsnID >= OutMIs.size())
1084 OutMIs.resize(NewInsnID + 1);
1085
1086 MachineInstr *OldMI = State.MIs[OldInsnID];
1087 if (Observer)
1088 Observer->changingInstr(*OldMI);
1089 OutMIs[NewInsnID] = MachineInstrBuilder(*OldMI->getMF(), OldMI);
1090 OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
1091 if (Observer)
1092 Observer->changedInstr(*OldMI);
1093 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1094 dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs["
1095 << NewInsnID << "], MIs[" << OldInsnID << "], "
1096 << NewOpcode << ")\n");
1097 break;
1098 }
1099
1100 case GIR_BuildRootMI:
1101 case GIR_BuildMI: {
1102 uint64_t NewInsnID = (MatcherOpcode == GIR_BuildRootMI) ? 0 : readULEB();
1103 uint32_t Opcode = readU16();
1104 if (NewInsnID >= OutMIs.size())
1105 OutMIs.resize(NewInsnID + 1);
1106
1107 initializeBuilder();
1108 OutMIs[NewInsnID] = Builder.buildInstr(Opcode);
1109 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1110 dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs["
1111 << NewInsnID << "], " << Opcode << ")\n");
1112 break;
1113 }
1114
1115 case GIR_BuildConstant: {
1116 uint64_t TempRegID = readULEB();
1117 uint64_t Imm = readU64();
1118 initializeBuilder();
1119 Builder.buildConstant(State.TempRegisters[TempRegID], Imm);
1120 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1121 dbgs() << CurrentIdx << ": GIR_BuildConstant(TempReg["
1122 << TempRegID << "], Imm=" << Imm << ")\n");
1123 break;
1124 }
1125
1126 case GIR_RootToRootCopy:
1127 case GIR_Copy: {
1128 uint64_t NewInsnID =
1129 (MatcherOpcode == GIR_RootToRootCopy) ? 0 : readULEB();
1130 uint64_t OldInsnID =
1131 (MatcherOpcode == GIR_RootToRootCopy) ? 0 : readULEB();
1132 uint64_t OpIdx = readULEB();
1133 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1134 OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
1135 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1136 dbgs()
1137 << CurrentIdx << ": GIR_Copy(OutMIs[" << NewInsnID
1138 << "], MIs[" << OldInsnID << "], " << OpIdx << ")\n");
1139 break;
1140 }
1141
1142 case GIR_CopyRemaining: {
1143 uint64_t NewInsnID = readULEB();
1144 uint64_t OldInsnID = readULEB();
1145 uint64_t OpIdx = readULEB();
1146 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1147 MachineInstr &OldMI = *State.MIs[OldInsnID];
1148 MachineInstrBuilder &NewMI = OutMIs[NewInsnID];
1149 for (const auto &Op : drop_begin(OldMI.operands(), OpIdx))
1150 NewMI.add(Op);
1151 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1152 dbgs() << CurrentIdx << ": GIR_CopyRemaining(OutMIs["
1153 << NewInsnID << "], MIs[" << OldInsnID
1154 << "], /*start=*/" << OpIdx << ")\n");
1155 break;
1156 }
1157
1158 case GIR_CopyOrAddZeroReg: {
1159 uint64_t NewInsnID = readULEB();
1160 uint64_t OldInsnID = readULEB();
1161 uint64_t OpIdx = readULEB();
1162 uint16_t ZeroReg = readU16();
1163 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1164 MachineOperand &MO = State.MIs[OldInsnID]->getOperand(OpIdx);
1165 if (isOperandImmEqual(MO, 0, MRI))
1166 OutMIs[NewInsnID].addReg(ZeroReg);
1167 else
1168 OutMIs[NewInsnID].add(MO);
1169 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1170 dbgs() << CurrentIdx << ": GIR_CopyOrAddZeroReg(OutMIs["
1171 << NewInsnID << "], MIs[" << OldInsnID << "], "
1172 << OpIdx << ", " << ZeroReg << ")\n");
1173 break;
1174 }
1175
1176 case GIR_CopySubReg: {
1177 uint64_t NewInsnID = readULEB();
1178 uint64_t OldInsnID = readULEB();
1179 uint64_t OpIdx = readULEB();
1180 uint16_t SubRegIdx = readU16();
1181 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1182 OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
1183 {}, SubRegIdx);
1184 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1185 dbgs() << CurrentIdx << ": GIR_CopySubReg(OutMIs["
1186 << NewInsnID << "], MIs[" << OldInsnID << "], "
1187 << OpIdx << ", " << SubRegIdx << ")\n");
1188 break;
1189 }
1190
1191 case GIR_AddImplicitDef: {
1192 uint64_t InsnID = readULEB();
1193 uint16_t RegNum = readU16();
1194 RegState Flags = static_cast<RegState>(readU16());
1195 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1196 Flags |= RegState::Implicit;
1197 OutMIs[InsnID].addDef(RegNum, Flags);
1198 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1199 dbgs() << CurrentIdx << ": GIR_AddImplicitDef(OutMIs["
1200 << InsnID << "], " << RegNum << ", "
1201 << static_cast<uint16_t>(Flags) << ")\n");
1202 break;
1203 }
1204
1205 case GIR_AddImplicitUse: {
1206 uint64_t InsnID = readULEB();
1207 uint16_t RegNum = readU16();
1208 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1209 OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
1210 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1211 dbgs() << CurrentIdx << ": GIR_AddImplicitUse(OutMIs["
1212 << InsnID << "], " << RegNum << ")\n");
1213 break;
1214 }
1215
1216 case GIR_AddRegister: {
1217 uint64_t InsnID = readULEB();
1218 uint16_t RegNum = readU16();
1219 RegState RegFlags = static_cast<RegState>(readU16());
1220 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1221 OutMIs[InsnID].addReg(RegNum, RegFlags);
1222 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1223 dbgs() << CurrentIdx << ": GIR_AddRegister(OutMIs["
1224 << InsnID << "], " << RegNum << ", "
1225 << static_cast<uint16_t>(RegFlags) << ")\n");
1226 break;
1227 }
1228 case GIR_AddIntrinsicID: {
1229 uint64_t InsnID = readULEB();
1230 uint16_t Value = readU16();
1231 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1232 OutMIs[InsnID].addIntrinsicID((Intrinsic::ID)Value);
1233 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1234 dbgs() << CurrentIdx << ": GIR_AddIntrinsicID(OutMIs["
1235 << InsnID << "], " << Value << ")\n");
1236 break;
1237 }
1239 uint64_t InsnID = readULEB();
1240 uint64_t OpIdx = readULEB();
1241 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1242 dbgs() << CurrentIdx << ": GIR_SetImplicitDefDead(OutMIs["
1243 << InsnID << "], OpIdx=" << OpIdx << ")\n");
1244 MachineInstr *MI = OutMIs[InsnID];
1245 assert(MI && "Modifying undefined instruction");
1246 MI->getOperand(MI->getNumExplicitOperands() + OpIdx).setIsDead();
1247 break;
1248 }
1249 case GIR_SetMIFlags: {
1250 uint64_t InsnID = readULEB();
1251 uint32_t Flags = readU32();
1252
1253 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1254 dbgs() << CurrentIdx << ": GIR_SetMIFlags(OutMIs["
1255 << InsnID << "], " << Flags << ")\n");
1256 MachineInstr *MI = OutMIs[InsnID];
1257 MI->setFlags(MI->getFlags() | Flags);
1258 break;
1259 }
1260 case GIR_UnsetMIFlags: {
1261 uint64_t InsnID = readULEB();
1262 uint32_t Flags = readU32();
1263
1264 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1265 dbgs() << CurrentIdx << ": GIR_UnsetMIFlags(OutMIs["
1266 << InsnID << "], " << Flags << ")\n");
1267 MachineInstr *MI = OutMIs[InsnID];
1268 MI->setFlags(MI->getFlags() & ~Flags);
1269 break;
1270 }
1271 case GIR_CopyMIFlags: {
1272 uint64_t InsnID = readULEB();
1273 uint64_t OldInsnID = readULEB();
1274
1275 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1276 dbgs() << CurrentIdx << ": GIR_CopyMIFlags(OutMIs["
1277 << InsnID << "], MIs[" << OldInsnID << "])\n");
1278 MachineInstr *MI = OutMIs[InsnID];
1279 MI->setFlags(MI->getFlags() | State.MIs[OldInsnID]->getFlags());
1280 break;
1281 }
1285 uint64_t InsnID = readULEB();
1286 uint64_t TempRegID = readULEB();
1287 RegState TempRegFlags = {};
1288 if (MatcherOpcode != GIR_AddSimpleTempRegister)
1289 TempRegFlags = static_cast<RegState>(readU16());
1290 uint16_t SubReg = 0;
1291 if (MatcherOpcode == GIR_AddTempSubRegister)
1292 SubReg = readU16();
1293
1294 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1295
1296 OutMIs[InsnID].addReg(State.TempRegisters[TempRegID], TempRegFlags,
1297 SubReg);
1299 TgtExecutor::getName(),
1300 dbgs() << CurrentIdx << ": GIR_AddTempRegister(OutMIs[" << InsnID
1301 << "], TempRegisters[" << TempRegID << "]";
1302 if (SubReg) dbgs() << '.' << TRI.getSubRegIndexName(SubReg);
1303 dbgs() << ", " << static_cast<uint16_t>(TempRegFlags) << ")\n");
1304 break;
1305 }
1306
1307 case GIR_AddImm8:
1308 case GIR_AddImm: {
1309 const bool IsAdd8 = (MatcherOpcode == GIR_AddImm8);
1310 uint64_t InsnID = readULEB();
1311 uint64_t Imm = IsAdd8 ? (int64_t)readS8() : readU64();
1312 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1313 OutMIs[InsnID].addImm(Imm);
1314 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1315 dbgs() << CurrentIdx << ": GIR_AddImm(OutMIs[" << InsnID
1316 << "], " << Imm << ")\n");
1317 break;
1318 }
1319
1320 case GIR_AddCImm: {
1321 uint64_t InsnID = readULEB();
1322 int TypeID = readS8();
1323 uint64_t Imm = readU64();
1324 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1325
1326 unsigned Width = ExecInfo.TypeObjects[TypeID].getScalarSizeInBits();
1327 LLVMContext &Ctx = MF->getFunction().getContext();
1328 OutMIs[InsnID].addCImm(
1329 ConstantInt::get(IntegerType::get(Ctx, Width), Imm, /*signed*/ true));
1330 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1331 dbgs() << CurrentIdx << ": GIR_AddCImm(OutMIs[" << InsnID
1332 << "], TypeID=" << TypeID << ", Imm=" << Imm
1333 << ")\n");
1334 break;
1335 }
1336
1337 case GIR_ComplexRenderer: {
1338 uint64_t InsnID = readULEB();
1339 uint16_t RendererID = readU16();
1340 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1341 for (const auto &RenderOpFn : State.Renderers[RendererID])
1342 RenderOpFn(OutMIs[InsnID]);
1343 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1344 dbgs() << CurrentIdx << ": GIR_ComplexRenderer(OutMIs["
1345 << InsnID << "], " << RendererID << ")\n");
1346 break;
1347 }
1349 uint64_t InsnID = readULEB();
1350 uint16_t RendererID = readU16();
1351 uint64_t RenderOpID = readULEB();
1352 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1353 State.Renderers[RendererID][RenderOpID](OutMIs[InsnID]);
1354 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1355 dbgs() << CurrentIdx
1356 << ": GIR_ComplexSubOperandRenderer(OutMIs["
1357 << InsnID << "], " << RendererID << ", "
1358 << RenderOpID << ")\n");
1359 break;
1360 }
1362 uint64_t InsnID = readULEB();
1363 uint16_t RendererID = readU16();
1364 uint64_t RenderOpID = readULEB();
1365 uint16_t SubRegIdx = readU16();
1366 MachineInstrBuilder &MI = OutMIs[InsnID];
1367 assert(MI && "Attempted to add to undefined instruction");
1368 State.Renderers[RendererID][RenderOpID](MI);
1369 MI->getOperand(MI->getNumOperands() - 1).setSubReg(SubRegIdx);
1370 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1371 dbgs() << CurrentIdx
1372 << ": GIR_ComplexSubOperandSubRegRenderer(OutMIs["
1373 << InsnID << "], " << RendererID << ", "
1374 << RenderOpID << ", " << SubRegIdx << ")\n");
1375 break;
1376 }
1377
1379 uint64_t NewInsnID = readULEB();
1380 uint64_t OldInsnID = readULEB();
1381 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1382 assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
1383 "Expected G_CONSTANT");
1384 if (State.MIs[OldInsnID]->getOperand(1).isCImm()) {
1385 OutMIs[NewInsnID].addImm(
1386 State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue());
1387 } else if (State.MIs[OldInsnID]->getOperand(1).isImm())
1388 OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1));
1389 else
1390 llvm_unreachable("Expected Imm or CImm operand");
1391 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1392 dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs["
1393 << NewInsnID << "], MIs[" << OldInsnID << "])\n");
1394 break;
1395 }
1396
1397 // TODO: Needs a test case once we have a pattern that uses this.
1399 uint64_t NewInsnID = readULEB();
1400 uint64_t OldInsnID = readULEB();
1401 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1402 assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
1403 "Expected G_FCONSTANT");
1404 if (State.MIs[OldInsnID]->getOperand(1).isFPImm())
1405 OutMIs[NewInsnID].addFPImm(
1406 State.MIs[OldInsnID]->getOperand(1).getFPImm());
1407 else
1408 llvm_unreachable("Expected FPImm operand");
1409 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1410 dbgs()
1411 << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs["
1412 << NewInsnID << "], MIs[" << OldInsnID << "])\n");
1413 break;
1414 }
1415
1416 case GIR_CustomRenderer: {
1417 uint64_t InsnID = readULEB();
1418 uint64_t OldInsnID = readULEB();
1419 uint16_t RendererFnID = readU16();
1420 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1421 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1422 dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs["
1423 << InsnID << "], MIs[" << OldInsnID << "], "
1424 << RendererFnID << ")\n");
1425 (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
1426 OutMIs[InsnID], *State.MIs[OldInsnID],
1427 -1); // Not a source operand of the old instruction.
1428 break;
1429 }
1431 uint16_t FnID = readU16();
1432 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1433 dbgs() << CurrentIdx << ": GIR_DoneWithCustomAction(FnID="
1434 << FnID << ")\n");
1435 assert(FnID > GICXXCustomAction_Invalid && "Expected a valid FnID");
1436 if (runCustomAction(FnID, State, OutMIs)) {
1437 propagateFlags();
1438 return true;
1439 }
1440
1441 if (handleReject() == RejectAndGiveUp)
1442 return false;
1443 break;
1444 }
1446 uint64_t InsnID = readULEB();
1447 uint64_t OldInsnID = readULEB();
1448 uint64_t OpIdx = readULEB();
1449 uint16_t RendererFnID = readU16();
1450 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1451
1452 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1453 dbgs() << CurrentIdx
1454 << ": GIR_CustomOperandRenderer(OutMIs[" << InsnID
1455 << "], MIs[" << OldInsnID << "]->getOperand("
1456 << OpIdx << "), " << RendererFnID << ")\n");
1457 (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
1458 OutMIs[InsnID], *State.MIs[OldInsnID], OpIdx);
1459 break;
1460 }
1462 uint64_t InsnID = readULEB();
1463 uint64_t OpIdx = readULEB();
1464 uint16_t RCEnum = readU16();
1465 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1466 MachineInstr &I = *OutMIs[InsnID].getInstr();
1467 MachineFunction &MF = *I.getParent()->getParent();
1468 MachineRegisterInfo &MRI = MF.getRegInfo();
1469 const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum);
1470 MachineOperand &MO = I.getOperand(OpIdx);
1471 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO);
1472 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1473 dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs["
1474 << InsnID << "], " << OpIdx << ", " << RCEnum
1475 << ")\n");
1476 break;
1477 }
1478
1481 uint64_t InsnID = (MatcherOpcode == GIR_RootConstrainSelectedInstOperands)
1482 ? 0
1483 : readULEB();
1484 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1485 constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
1486 RBI);
1487 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1488 dbgs() << CurrentIdx
1489 << ": GIR_ConstrainSelectedInstOperands(OutMIs["
1490 << InsnID << "])\n");
1491 break;
1492 }
1493 case GIR_MergeMemOperands: {
1494 uint64_t InsnID = readULEB();
1495 uint64_t NumInsn = MatchTable[CurrentIdx++];
1496 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1497
1498 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1499 dbgs() << CurrentIdx << ": GIR_MergeMemOperands(OutMIs["
1500 << InsnID << "]");
1501 for (unsigned K = 0; K < NumInsn; ++K) {
1502 uint64_t NextID = readULEB();
1503 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1504 dbgs() << ", MIs[" << NextID << "]");
1505 for (const auto &MMO : State.MIs[NextID]->memoperands())
1506 OutMIs[InsnID].addMemOperand(MMO);
1507 }
1508 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << ")\n");
1509 break;
1510 }
1511 case GIR_EraseFromParent: {
1512 uint64_t InsnID = readULEB();
1513 MachineInstr *MI = State.MIs[InsnID];
1514 assert(MI && "Attempted to erase an undefined instruction");
1515 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1516 dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs["
1517 << InsnID << "])\n");
1518 eraseImpl(MI);
1519 break;
1520 }
1522 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1523 dbgs()
1524 << CurrentIdx << ": GIR_EraseRootFromParent_Done\n");
1525 eraseImpl(State.MIs[0]);
1526 propagateFlags();
1527 return true;
1528 }
1529 case GIR_MakeTempReg: {
1530 uint64_t TempRegID = readULEB();
1531 int TypeID = readS8();
1532
1533 State.TempRegisters[TempRegID] =
1534 MRI.createGenericVirtualRegister(getTypeFromIdx(TypeID));
1535 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1536 dbgs() << CurrentIdx << ": TempRegs[" << TempRegID
1537 << "] = GIR_MakeTempReg(" << TypeID << ")\n");
1538 break;
1539 }
1540 case GIR_ReplaceReg: {
1541 uint64_t OldInsnID = readULEB();
1542 uint64_t OldOpIdx = readULEB();
1543 uint64_t NewInsnID = readULEB();
1544 uint64_t NewOpIdx = readULEB();
1545
1546 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1547 dbgs() << CurrentIdx << ": GIR_ReplaceReg(MIs["
1548 << OldInsnID << "][" << OldOpIdx << "] = MIs["
1549 << NewInsnID << "][" << NewOpIdx << "])\n");
1550
1551 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1552 Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg();
1553 if (Observer)
1554 Observer->changingAllUsesOfReg(MRI, Old);
1555 MRI.replaceRegWith(Old, New);
1556 if (Observer)
1557 Observer->finishedChangingAllUsesOfReg();
1558 break;
1559 }
1561 uint64_t OldInsnID = readULEB();
1562 uint64_t OldOpIdx = readULEB();
1563 uint64_t TempRegID = readULEB();
1564
1565 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1566 dbgs() << CurrentIdx << ": GIR_ReplaceRegWithTempReg(MIs["
1567 << OldInsnID << "][" << OldOpIdx << "] = TempRegs["
1568 << TempRegID << "])\n");
1569
1570 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1571 Register New = State.TempRegisters[TempRegID];
1572 if (Observer)
1573 Observer->changingAllUsesOfReg(MRI, Old);
1574 MRI.replaceRegWith(Old, New);
1575 if (Observer)
1576 Observer->finishedChangingAllUsesOfReg();
1577 break;
1578 }
1579 case GIR_Coverage: {
1580 uint32_t RuleID = readU32();
1582 CoverageInfo->setCovered(RuleID);
1583
1584 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx
1585 << ": GIR_Coverage("
1586 << RuleID << ")");
1587 break;
1588 }
1589
1590 case GIR_Done:
1591 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1592 dbgs() << CurrentIdx << ": GIR_Done\n");
1593 propagateFlags();
1594 return true;
1595 default:
1596 llvm_unreachable("Unexpected command");
1597 }
1598 }
1599}
1600
1601} // end namespace llvm
1602
1603#endif // LLVM_CODEGEN_GLOBALISEL_GIMATCHTABLEEXECUTORIMPL_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This contains common code to allow clients to notify changes to machine instr.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineIRBuilder class.
Register const TargetRegisterInfo * TRI
Type::TypeID TypeID
MachineInstr unsigned OpIdx
This file defines the SmallVector class.
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition Debug.h:72
Class for arbitrary precision integers.
Definition APInt.h:78
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:194
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
iterator end()
Definition DenseMap.h:85
Tagged union holding either a T or a Error.
Definition Error.h:485
virtual bool testSimplePredicate(unsigned) const
bool executeMatchTable(TgtExecutor &Exec, MatcherState &State, const ExecInfoTy< PredicateBitset, ComplexMatcherMemFn, CustomRendererFn > &ExecInfo, MachineIRBuilder &Builder, const uint8_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.
virtual bool testImmPredicate_APFloat(unsigned, const APFloat &) const
virtual bool testMOPredicate_MO(unsigned, const MachineOperand &, const MatcherState &State) 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
SmallVector< MachineInstrBuilder, 4 > NewMIVector
static Ty readBytesAs(const uint8_t *MatchTable)
std::optional< SmallVector< std::function< void(MachineInstrBuilder &)>, 4 > > ComplexRendererFns
static LLVM_ATTRIBUTE_ALWAYS_INLINE uint64_t fastDecodeULEB128(const uint8_t *LLVM_ATTRIBUTE_RESTRICT MatchTable, uint64_t &CurrentIdx)
LLVM_ABI bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI, bool Splat=false) const
LLVM_ABI bool isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const
Return true if MI can obviously be folded into IntoMI.
virtual bool runCustomAction(unsigned, const MatcherState &State, NewMIVector &OutMIs) const
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.
LLVM_ABI 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.
LLVM_ABI void changingAllUsesOfReg(const MachineRegisterInfo &MRI, Register Reg)
All the instructions using the given register are being changed.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:350
constexpr unsigned getScalarSizeInBits() const
constexpr LLT changeElementType(LLT NewEltTy) const
If this type is a vector, return a vector with the same number of elements but the new element type.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
TypeSize getValue() const
Helper class to build MachineInstr.
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
mop_range operands()
LLVM_ABI 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.
LocationSize getSize() const
Return the size in bytes of the memory reference.
unsigned getAddrSpace() const
LLVM_ABI Align getAlign() const
Return the minimum known alignment in bytes of the actual memory reference.
LocationSize getSizeInBits() const
Return the size in bits of the 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 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,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")
Create and return a new generic virtual register with low-level type Ty.
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
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:20
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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:75
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:230
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:237
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
LLVM_ABI 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:1444
LLVM_ABI 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:57
RegState
Flags to represent properties of register accesses.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
LLVM_ABI void 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:156
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
Definition Utils.cpp:494
constexpr T MinAlign(U A, V B)
A and B are either alignments or offsets.
Definition MathExtras.h:357
LLVM_ABI bool canReplaceReg(Register DstReg, Register SrcReg, MachineRegisterInfo &MRI)
Check if DstReg can be replaced with SrcReg depending on the register constraints.
Definition Utils.cpp:200
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isAtLeastOrStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
LLVM_ABI 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:1450
@ Success
The lock was released successfully.
AtomicOrdering
Atomic ordering for LLVM's memory model.
DWARFExpression::Operation Op
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:572
LLVM_ABI Register getSrcRegIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the source register for Reg, folding away any trivial copies.
Definition Utils.cpp:501
@ GICXXCustomAction_Invalid
@ GIR_AddIntrinsicID
Adds an intrinsic ID to the specified instruction.
@ 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.
@ GIM_RootCheckType
GIM_CheckType but InsnID is omitted and defaults to zero.
@ GIM_RootCheckRegBankForClass
GIM_CheckRegBankForClass but InsnID is omitted and defaults to zero.
@ 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.
@ GIR_RootConstrainSelectedInstOperands
GIR_ConstrainSelectedInstOperands but InsnID is omitted and defaults to zero.
@ 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.
@ 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
Checks if the matched instructions numbered [1, 1+N) can be folded into the root (inst 0).
@ 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_AddSimpleTempRegister
Add a temporary register to the specified instruction without setting any flags.
@ 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.
@ GIR_CopyRemaining
Copies all operand starting from OpIdx in OldInsnID into the new instruction NewInsnID.
@ 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.
@ GIR_AddImm8
Add signed 8 bit immediate to the specified instruction.
@ GIM_CheckIsSameOperandIgnoreCopies
@ GIM_CheckIsMBB
Check the specified operand is an MBB.
@ GIM_CheckNumOperandsLE
Check the instruction has a number of operands <= or >= than given number.
@ GIM_Try_CheckFeatures
GIM_Try only if the feature bits match.
@ 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.
@ GIM_CheckLeafOperandPredicate
Check a leaf predicate on the specified instruction.
@ GIM_CheckHasOneUse
Check if there's one use of the first result.
@ GIR_EraseRootFromParent_Done
Combines both a GIR_EraseFromParent 0 + GIR_Done.
@ GIR_CopyMIFlags
Copy the MIFlags of a matched instruction into an output instruction.
@ GIR_DoneWithCustomAction
Calls a C++ function that concludes the current match.
@ GIR_BuildMI
Build a new instruction.
@ GIM_RecordInsn
Record the specified instruction.
@ GIM_CheckIsImm
Check the specified operand is an Imm.
@ GIR_BuildRootMI
GIR_BuildMI but InsnID is omitted and defaults to zero.
@ 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_CheckConstantInt8
Check the operand is a specific 8-bit signed integer.
@ 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.
@ GIM_SwitchTypeShape
Switch over the shape of an LLT on the specified instruction operand.
@ GIR_RootToRootCopy
GIR_Copy but with both New/OldInsnIDs omitted and defaulting to zero.
@ 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.
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
bool isStrongerThan(AtomicOrdering AO, AtomicOrdering Other)
Returns true if ao is stronger than other as defined by the AtomicOrdering lattice,...
SmallDenseMap< uint64_t, unsigned, 64 > TypeIDMap
const ComplexMatcherMemFn * ComplexPredicates