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