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