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 }
773 uint64_t InsnID = readULEB();
774 uint64_t OpIdx = readULEB();
775 uint64_t SizeInBits = readULEB();
776
777 DEBUG_WITH_TYPE(TgtExecutor::getName(),
778 dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs["
779 << InsnID << "]->getOperand(" << OpIdx
780 << "), SizeInBits=" << SizeInBits << ")\n");
781 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
782 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
783 const LLT Ty = MRI.getType(MO.getReg());
784
785 // iPTR must be looked up in the target.
786 if (SizeInBits == 0) {
787 MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent();
788 const unsigned AddrSpace = Ty.getAddressSpace();
789 SizeInBits = MF->getDataLayout().getPointerSizeInBits(AddrSpace);
790 }
791
792 assert(SizeInBits != 0 && "Pointer size must be known");
793
794 if (MO.isReg()) {
795 if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits)
796 if (handleReject() == RejectAndGiveUp)
797 return false;
798 } else if (handleReject() == RejectAndGiveUp)
799 return false;
800
801 break;
802 }
804 uint64_t InsnID = readULEB();
805 uint64_t OpIdx = readULEB();
806 uint64_t StoreIdx = readULEB();
807
808 DEBUG_WITH_TYPE(TgtExecutor::getName(),
809 dbgs() << CurrentIdx << ": GIM_RecordNamedOperand(MIs["
810 << InsnID << "]->getOperand(" << OpIdx
811 << "), StoreIdx=" << StoreIdx << ")\n");
812 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
813 assert(StoreIdx < State.RecordedOperands.size() && "Index out of range");
814 State.RecordedOperands[StoreIdx] = &State.MIs[InsnID]->getOperand(OpIdx);
815 break;
816 }
817 case GIM_RecordRegType: {
818 uint64_t InsnID = readULEB();
819 uint64_t OpIdx = readULEB();
820 int TypeIdx = readS8();
821
822 DEBUG_WITH_TYPE(TgtExecutor::getName(),
823 dbgs() << CurrentIdx << ": GIM_RecordRegType(MIs["
824 << InsnID << "]->getOperand(" << OpIdx
825 << "), TypeIdx=" << TypeIdx << ")\n");
826 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
827 assert(TypeIdx < 0 && "Temp types always have negative indexes!");
828 // Indexes start at -1.
829 TypeIdx = 1 - TypeIdx;
830 const auto &Op = State.MIs[InsnID]->getOperand(OpIdx);
831 if (State.RecordedTypes.size() <= (uint64_t)TypeIdx)
832 State.RecordedTypes.resize(TypeIdx + 1, LLT());
833 State.RecordedTypes[TypeIdx] = MRI.getType(Op.getReg());
834 break;
835 }
836
839 uint64_t InsnID =
840 (MatcherOpcode == GIM_RootCheckRegBankForClass) ? 0 : readULEB();
841 uint64_t OpIdx = readULEB();
842 uint16_t RCEnum = readU16();
843 DEBUG_WITH_TYPE(TgtExecutor::getName(),
844 dbgs() << CurrentIdx << ": GIM_CheckRegBankForClass(MIs["
845 << InsnID << "]->getOperand(" << OpIdx
846 << "), RCEnum=" << RCEnum << ")\n");
847 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
848 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
849 if (!MO.isReg() ||
850 &RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum),
851 MRI.getType(MO.getReg())) !=
852 RBI.getRegBank(MO.getReg(), MRI, TRI)) {
853 if (handleReject() == RejectAndGiveUp)
854 return false;
855 }
856 break;
857 }
858
860 uint64_t InsnID = readULEB();
861 uint64_t OpIdx = readULEB();
862 uint16_t RendererID = readU16();
863 uint16_t ComplexPredicateID = readU16();
864 DEBUG_WITH_TYPE(TgtExecutor::getName(),
865 dbgs() << CurrentIdx << ": State.Renderers[" << RendererID
866 << "] = GIM_CheckComplexPattern(MIs[" << InsnID
867 << "]->getOperand(" << OpIdx
868 << "), ComplexPredicateID=" << ComplexPredicateID
869 << ")\n");
870 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
871 // FIXME: Use std::invoke() when it's available.
872 ComplexRendererFns Renderer =
873 (Exec.*ExecInfo.ComplexPredicates[ComplexPredicateID])(
874 State.MIs[InsnID]->getOperand(OpIdx));
875 if (Renderer)
876 State.Renderers[RendererID] = std::move(*Renderer);
877 else if (handleReject() == RejectAndGiveUp)
878 return false;
879 break;
880 }
881
884 const bool IsInt8 = (MatcherOpcode == GIM_CheckConstantInt8);
885
886 uint64_t InsnID = readULEB();
887 uint64_t OpIdx = readULEB();
888 uint64_t Value = IsInt8 ? (int64_t)readS8() : readU64();
889 DEBUG_WITH_TYPE(TgtExecutor::getName(),
890 dbgs() << CurrentIdx << ": GIM_CheckConstantInt(MIs["
891 << InsnID << "]->getOperand(" << OpIdx
892 << "), Value=" << Value << ")\n");
893 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
894 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
895 if (MO.isReg()) {
896 // isOperandImmEqual() will sign-extend to 64-bits, so should we.
897 LLT Ty = MRI.getType(MO.getReg());
898 // If the type is > 64 bits, it can't be a constant int, so we bail
899 // early because SignExtend64 will assert otherwise.
900 if (Ty.getScalarSizeInBits() > 64) {
901 if (handleReject() == RejectAndGiveUp)
902 return false;
903 break;
904 }
905
906 Value = SignExtend64(Value, Ty.getScalarSizeInBits());
907 if (!isOperandImmEqual(MO, Value, MRI, /*Splat=*/true)) {
908 if (handleReject() == RejectAndGiveUp)
909 return false;
910 }
911 } else if (handleReject() == RejectAndGiveUp)
912 return false;
913
914 break;
915 }
916
917 case GIM_CheckLiteralInt: {
918 uint64_t InsnID = readULEB();
919 uint64_t OpIdx = readULEB();
920 int64_t Value = readU64();
921 DEBUG_WITH_TYPE(TgtExecutor::getName(),
922 dbgs() << CurrentIdx << ": GIM_CheckLiteralInt(MIs["
923 << InsnID << "]->getOperand(" << OpIdx
924 << "), Value=" << Value << ")\n");
925 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
926 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
927 if (MO.isImm() && MO.getImm() == Value)
928 break;
929
930 if (MO.isCImm() && MO.getCImm()->equalsInt(Value))
931 break;
932
933 if (handleReject() == RejectAndGiveUp)
934 return false;
935
936 break;
937 }
938
940 uint64_t InsnID = readULEB();
941 uint64_t OpIdx = readULEB();
942 uint16_t Value = readU16();
943 DEBUG_WITH_TYPE(TgtExecutor::getName(),
944 dbgs() << CurrentIdx << ": GIM_CheckIntrinsicID(MIs["
945 << InsnID << "]->getOperand(" << OpIdx
946 << "), Value=" << Value << ")\n");
947 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
948 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
949 if (!MO.isIntrinsicID() || MO.getIntrinsicID() != Value)
950 if (handleReject() == RejectAndGiveUp)
951 return false;
952 break;
953 }
955 uint64_t InsnID = readULEB();
956 uint64_t OpIdx = readULEB();
957 uint16_t Value = readU16();
958 DEBUG_WITH_TYPE(TgtExecutor::getName(),
959 dbgs() << CurrentIdx << ": GIM_CheckCmpPredicate(MIs["
960 << InsnID << "]->getOperand(" << OpIdx
961 << "), Value=" << Value << ")\n");
962 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
963 MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
964 if (!MO.isPredicate() || MO.getPredicate() != Value)
965 if (handleReject() == RejectAndGiveUp)
966 return false;
967 break;
968 }
969 case GIM_CheckIsMBB: {
970 uint64_t InsnID = readULEB();
971 uint64_t OpIdx = readULEB();
972 DEBUG_WITH_TYPE(TgtExecutor::getName(),
973 dbgs() << CurrentIdx << ": GIM_CheckIsMBB(MIs[" << InsnID
974 << "]->getOperand(" << OpIdx << "))\n");
975 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
976 if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB()) {
977 if (handleReject() == RejectAndGiveUp)
978 return false;
979 }
980 break;
981 }
982 case GIM_CheckIsImm: {
983 uint64_t InsnID = readULEB();
984 uint64_t OpIdx = readULEB();
985 DEBUG_WITH_TYPE(TgtExecutor::getName(),
986 dbgs() << CurrentIdx << ": GIM_CheckIsImm(MIs[" << InsnID
987 << "]->getOperand(" << OpIdx << "))\n");
988 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
989 if (!State.MIs[InsnID]->getOperand(OpIdx).isImm()) {
990 if (handleReject() == RejectAndGiveUp)
991 return false;
992 }
993 break;
994 }
996 uint64_t NumInsn = MatchTable[CurrentIdx++];
997 DEBUG_WITH_TYPE(TgtExecutor::getName(),
998 dbgs() << CurrentIdx << ": GIM_CheckIsSafeToFold(N = "
999 << NumInsn << ")\n");
1000 MachineInstr &Root = *State.MIs[0];
1001 for (unsigned K = 1, E = NumInsn + 1; K < E; ++K) {
1002 if (!isObviouslySafeToFold(*State.MIs[K], Root)) {
1003 if (handleReject() == RejectAndGiveUp)
1004 return false;
1005 }
1006 }
1007 break;
1008 }
1011 uint64_t InsnID = readULEB();
1012 uint64_t OpIdx = readULEB();
1013 uint64_t OtherInsnID = readULEB();
1014 uint64_t OtherOpIdx = readULEB();
1015 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1016 dbgs() << CurrentIdx << ": GIM_CheckIsSameOperand(MIs["
1017 << InsnID << "][" << OpIdx << "], MIs["
1018 << OtherInsnID << "][" << OtherOpIdx << "])\n");
1019 assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
1020 assert(State.MIs[OtherInsnID] != nullptr && "Used insn before defined");
1021
1022 MachineOperand &Op = State.MIs[InsnID]->getOperand(OpIdx);
1023 MachineOperand &OtherOp = State.MIs[OtherInsnID]->getOperand(OtherOpIdx);
1024
1025 if (MatcherOpcode == GIM_CheckIsSameOperandIgnoreCopies) {
1026 if (Op.isReg() && OtherOp.isReg()) {
1027 if (getSrcRegIgnoringCopies(Op.getReg(), MRI) ==
1028 getSrcRegIgnoringCopies(OtherOp.getReg(), MRI))
1029 break;
1030 }
1031 }
1032
1033 if (!Op.isIdenticalTo(OtherOp)) {
1034 if (handleReject() == RejectAndGiveUp)
1035 return false;
1036 }
1037 break;
1038 }
1040 uint64_t OldInsnID = readULEB();
1041 uint64_t OldOpIdx = readULEB();
1042 uint64_t NewInsnID = readULEB();
1043 uint64_t NewOpIdx = readULEB();
1044
1045 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1046 dbgs() << CurrentIdx << ": GIM_CheckCanReplaceReg(MIs["
1047 << OldInsnID << "][" << OldOpIdx << "] = MIs["
1048 << NewInsnID << "][" << NewOpIdx << "])\n");
1049
1050 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1051 Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg();
1052 if (!canReplaceReg(Old, New, MRI)) {
1053 if (handleReject() == RejectAndGiveUp)
1054 return false;
1055 }
1056 break;
1057 }
1058 case GIM_MIFlags: {
1059 uint64_t InsnID = readULEB();
1060 uint32_t Flags = readU32();
1061
1062 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1063 dbgs() << CurrentIdx << ": GIM_MIFlags(MIs[" << InsnID
1064 << "], " << Flags << ")\n");
1065 if ((State.MIs[InsnID]->getFlags() & Flags) != Flags) {
1066 if (handleReject() == RejectAndGiveUp)
1067 return false;
1068 }
1069 break;
1070 }
1071 case GIM_MIFlagsNot: {
1072 uint64_t InsnID = readULEB();
1073 uint32_t Flags = readU32();
1074
1075 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1076 dbgs() << CurrentIdx << ": GIM_MIFlagsNot(MIs[" << InsnID
1077 << "], " << Flags << ")\n");
1078 if ((State.MIs[InsnID]->getFlags() & Flags)) {
1079 if (handleReject() == RejectAndGiveUp)
1080 return false;
1081 }
1082 break;
1083 }
1084 case GIM_Reject:
1085 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1086 dbgs() << CurrentIdx << ": GIM_Reject\n");
1087 if (handleReject() == RejectAndGiveUp)
1088 return false;
1089 break;
1090 case GIR_MutateOpcode: {
1091 uint64_t OldInsnID = readULEB();
1092 uint64_t NewInsnID = readULEB();
1093 uint32_t NewOpcode = readU16();
1094 if (NewInsnID >= OutMIs.size())
1095 OutMIs.resize(NewInsnID + 1);
1096 initializeOutMIFlagState(NewInsnID + 1);
1097
1098 MachineInstr *OldMI = State.MIs[OldInsnID];
1099 if (Observer)
1100 Observer->changingInstr(*OldMI);
1101 OutMIs[NewInsnID] = MachineInstrBuilder(*OldMI->getMF(), OldMI);
1102 OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
1103 if (Observer)
1104 Observer->changedInstr(*OldMI);
1105 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1106 dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs["
1107 << NewInsnID << "], MIs[" << OldInsnID << "], "
1108 << NewOpcode << ")\n");
1109 break;
1110 }
1111
1112 case GIR_BuildRootMI:
1113 case GIR_BuildMI: {
1114 uint64_t NewInsnID = (MatcherOpcode == GIR_BuildRootMI) ? 0 : readULEB();
1115 uint32_t Opcode = readU16();
1116 if (NewInsnID >= OutMIs.size())
1117 OutMIs.resize(NewInsnID + 1);
1118 initializeOutMIFlagState(NewInsnID + 1);
1119
1120 initializeBuilder();
1121 OutMIs[NewInsnID] = Builder.buildInstr(Opcode);
1122 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1123 dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs["
1124 << NewInsnID << "], " << Opcode << ")\n");
1125 break;
1126 }
1127
1128 case GIR_BuildConstant: {
1129 uint64_t TempRegID = readULEB();
1130 uint64_t Imm = readU64();
1131 initializeBuilder();
1132 Builder.buildConstant(State.TempRegisters[TempRegID], Imm);
1133 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1134 dbgs() << CurrentIdx << ": GIR_BuildConstant(TempReg["
1135 << TempRegID << "], Imm=" << Imm << ")\n");
1136 break;
1137 }
1138
1139 case GIR_RootToRootCopy:
1140 case GIR_Copy: {
1141 uint64_t NewInsnID =
1142 (MatcherOpcode == GIR_RootToRootCopy) ? 0 : readULEB();
1143 uint64_t OldInsnID =
1144 (MatcherOpcode == GIR_RootToRootCopy) ? 0 : readULEB();
1145 uint64_t OpIdx = readULEB();
1146 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1147 OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
1148 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1149 dbgs()
1150 << CurrentIdx << ": GIR_Copy(OutMIs[" << NewInsnID
1151 << "], MIs[" << OldInsnID << "], " << OpIdx << ")\n");
1152 break;
1153 }
1154
1155 case GIR_CopyRemaining: {
1156 uint64_t NewInsnID = readULEB();
1157 uint64_t OldInsnID = readULEB();
1158 uint64_t OpIdx = readULEB();
1159 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1160 MachineInstr &OldMI = *State.MIs[OldInsnID];
1161 MachineInstrBuilder &NewMI = OutMIs[NewInsnID];
1162 for (const auto &Op : drop_begin(OldMI.operands(), OpIdx))
1163 NewMI.add(Op);
1164 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1165 dbgs() << CurrentIdx << ": GIR_CopyRemaining(OutMIs["
1166 << NewInsnID << "], MIs[" << OldInsnID
1167 << "], /*start=*/" << OpIdx << ")\n");
1168 break;
1169 }
1170
1171 case GIR_CopyOrAddZeroReg: {
1172 uint64_t NewInsnID = readULEB();
1173 uint64_t OldInsnID = readULEB();
1174 uint64_t OpIdx = readULEB();
1175 uint16_t ZeroReg = readU16();
1176 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1177 MachineOperand &MO = State.MIs[OldInsnID]->getOperand(OpIdx);
1178 if (isOperandImmEqual(MO, 0, MRI))
1179 OutMIs[NewInsnID].addReg(ZeroReg);
1180 else
1181 OutMIs[NewInsnID].add(MO);
1182 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1183 dbgs() << CurrentIdx << ": GIR_CopyOrAddZeroReg(OutMIs["
1184 << NewInsnID << "], MIs[" << OldInsnID << "], "
1185 << OpIdx << ", " << ZeroReg << ")\n");
1186 break;
1187 }
1188
1189 case GIR_CopySubReg: {
1190 uint64_t NewInsnID = readULEB();
1191 uint64_t OldInsnID = readULEB();
1192 uint64_t OpIdx = readULEB();
1193 uint16_t SubRegIdx = readU16();
1194 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1195 OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
1196 {}, SubRegIdx);
1197 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1198 dbgs() << CurrentIdx << ": GIR_CopySubReg(OutMIs["
1199 << NewInsnID << "], MIs[" << OldInsnID << "], "
1200 << OpIdx << ", " << SubRegIdx << ")\n");
1201 break;
1202 }
1203
1204 case GIR_AddImplicitDef: {
1205 uint64_t InsnID = readULEB();
1206 uint16_t RegNum = readU16();
1207 RegState Flags = static_cast<RegState>(readU16());
1208 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1209 Flags |= RegState::Implicit;
1210 OutMIs[InsnID].addDef(RegNum, Flags);
1211 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1212 dbgs() << CurrentIdx << ": GIR_AddImplicitDef(OutMIs["
1213 << InsnID << "], " << RegNum << ", "
1214 << static_cast<uint16_t>(Flags) << ")\n");
1215 break;
1216 }
1217
1218 case GIR_AddImplicitUse: {
1219 uint64_t InsnID = readULEB();
1220 uint16_t RegNum = readU16();
1221 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1222 OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
1223 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1224 dbgs() << CurrentIdx << ": GIR_AddImplicitUse(OutMIs["
1225 << InsnID << "], " << RegNum << ")\n");
1226 break;
1227 }
1228
1229 case GIR_AddRegister: {
1230 uint64_t InsnID = readULEB();
1231 uint16_t RegNum = readU16();
1232 RegState RegFlags = static_cast<RegState>(readU16());
1233 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1234 OutMIs[InsnID].addReg(RegNum, RegFlags);
1235 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1236 dbgs() << CurrentIdx << ": GIR_AddRegister(OutMIs["
1237 << InsnID << "], " << RegNum << ", "
1238 << static_cast<uint16_t>(RegFlags) << ")\n");
1239 break;
1240 }
1241 case GIR_AddIntrinsicID: {
1242 uint64_t InsnID = readULEB();
1243 uint16_t Value = readU16();
1244 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1245 OutMIs[InsnID].addIntrinsicID((Intrinsic::ID)Value);
1246 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1247 dbgs() << CurrentIdx << ": GIR_AddIntrinsicID(OutMIs["
1248 << InsnID << "], " << Value << ")\n");
1249 break;
1250 }
1252 uint64_t InsnID = readULEB();
1253 uint64_t OpIdx = readULEB();
1254 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1255 dbgs() << CurrentIdx << ": GIR_SetImplicitDefDead(OutMIs["
1256 << InsnID << "], OpIdx=" << OpIdx << ")\n");
1257 MachineInstr *MI = OutMIs[InsnID];
1258 assert(MI && "Modifying undefined instruction");
1259 MI->getOperand(MI->getNumExplicitOperands() + OpIdx).setIsDead();
1260 break;
1261 }
1262 case GIR_SetMIFlags: {
1263 uint64_t InsnID = readULEB();
1264 uint32_t Flags = readU32();
1265
1266 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1267 dbgs() << CurrentIdx << ": GIR_SetMIFlags(OutMIs["
1268 << InsnID << "], " << Flags << ")\n");
1269 MachineInstr *MI = OutMIs[InsnID];
1270 assert(MI && "Modifying undefined instruction");
1271 MI->setFlags(MI->getFlags() | Flags);
1272 initializeOutMIFlagState(OutMIs.size());
1273 OutMIFlagsToDrop[InsnID] &= ~Flags;
1274 break;
1275 }
1276 case GIR_UnsetMIFlags: {
1277 uint64_t InsnID = readULEB();
1278 uint32_t Flags = readU32();
1279
1280 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1281 dbgs() << CurrentIdx << ": GIR_UnsetMIFlags(OutMIs["
1282 << InsnID << "], " << Flags << ")\n");
1283 MachineInstr *MI = OutMIs[InsnID];
1284 assert(MI && "Modifying undefined instruction");
1285 MI->setFlags(MI->getFlags() & ~Flags);
1286 initializeOutMIFlagState(OutMIs.size());
1287 OutMIFlagsToDrop[InsnID] |= Flags;
1288 break;
1289 }
1290 case GIR_CopyMIFlags: {
1291 uint64_t InsnID = readULEB();
1292 uint64_t OldInsnID = readULEB();
1293
1294 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1295 dbgs() << CurrentIdx << ": GIR_CopyMIFlags(OutMIs["
1296 << InsnID << "], MIs[" << OldInsnID << "])\n");
1297 MachineInstr *MI = OutMIs[InsnID];
1298 assert(MI && "Modifying undefined instruction");
1299 uint32_t Flags = State.MIs[OldInsnID]->getFlags();
1300 MI->setFlags(MI->getFlags() | Flags);
1301 initializeOutMIFlagState(OutMIs.size());
1302 OutMIFlagsToDrop[InsnID] &= ~Flags;
1303 break;
1304 }
1308 uint64_t InsnID = readULEB();
1309 uint64_t TempRegID = readULEB();
1310 RegState TempRegFlags = {};
1311 if (MatcherOpcode != GIR_AddSimpleTempRegister)
1312 TempRegFlags = static_cast<RegState>(readU16());
1313 uint16_t SubReg = 0;
1314 if (MatcherOpcode == GIR_AddTempSubRegister)
1315 SubReg = readU16();
1316
1317 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1318
1319 OutMIs[InsnID].addReg(State.TempRegisters[TempRegID], TempRegFlags,
1320 SubReg);
1322 TgtExecutor::getName(),
1323 dbgs() << CurrentIdx << ": GIR_AddTempRegister(OutMIs[" << InsnID
1324 << "], TempRegisters[" << TempRegID << "]";
1325 if (SubReg) dbgs() << '.' << TRI.getSubRegIndexName(SubReg);
1326 dbgs() << ", " << static_cast<uint16_t>(TempRegFlags) << ")\n");
1327 break;
1328 }
1329
1330 case GIR_AddImm8:
1331 case GIR_AddImm: {
1332 const bool IsAdd8 = (MatcherOpcode == GIR_AddImm8);
1333 uint64_t InsnID = readULEB();
1334 uint64_t Imm = IsAdd8 ? (int64_t)readS8() : readU64();
1335 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1336 OutMIs[InsnID].addImm(Imm);
1337 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1338 dbgs() << CurrentIdx << ": GIR_AddImm(OutMIs[" << InsnID
1339 << "], " << Imm << ")\n");
1340 break;
1341 }
1342
1343 case GIR_AddCImm: {
1344 uint64_t InsnID = readULEB();
1345 int TypeID = readS8();
1346 uint64_t Imm = readU64();
1347 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1348
1349 unsigned Width = getTypeFromIdx(TypeID).getScalarSizeInBits();
1350 LLVMContext &Ctx = MF->getFunction().getContext();
1351 OutMIs[InsnID].addCImm(
1352 ConstantInt::get(IntegerType::get(Ctx, Width), Imm, /*signed*/ true));
1353 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1354 dbgs() << CurrentIdx << ": GIR_AddCImm(OutMIs[" << InsnID
1355 << "], TypeID=" << TypeID << ", Imm=" << Imm
1356 << ")\n");
1357 break;
1358 }
1359
1360 case GIR_AddCFPImm: {
1361 uint64_t InsnID = readULEB();
1362 int TypeID = readS8();
1363 uint64_t Imm = readU64();
1364 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1365
1366 LLT Ty = getTypeFromIdx(TypeID);
1367 unsigned Width = Ty.getScalarSizeInBits();
1368 LLVMContext &Ctx = MF->getFunction().getContext();
1369 APFloat APF(getFltSemanticForLLT(Ty.getScalarType()), APInt(Width, Imm));
1370 OutMIs[InsnID].addFPImm(ConstantFP::get(Ctx, APF));
1371 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1372 dbgs() << CurrentIdx << ": GIR_AddCFPImm(OutMIs["
1373 << InsnID << "], TypeID=" << TypeID
1374 << ", Imm=" << Imm << ")\n");
1375 break;
1376 }
1377
1378 case GIR_ComplexRenderer: {
1379 uint64_t InsnID = readULEB();
1380 uint16_t RendererID = readU16();
1381 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1382 for (const auto &RenderOpFn : State.Renderers[RendererID])
1383 RenderOpFn(OutMIs[InsnID]);
1384 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1385 dbgs() << CurrentIdx << ": GIR_ComplexRenderer(OutMIs["
1386 << InsnID << "], " << RendererID << ")\n");
1387 break;
1388 }
1390 uint64_t InsnID = readULEB();
1391 uint16_t RendererID = readU16();
1392 uint64_t RenderOpID = readULEB();
1393 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1394 State.Renderers[RendererID][RenderOpID](OutMIs[InsnID]);
1395 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1396 dbgs() << CurrentIdx
1397 << ": GIR_ComplexSubOperandRenderer(OutMIs["
1398 << InsnID << "], " << RendererID << ", "
1399 << RenderOpID << ")\n");
1400 break;
1401 }
1403 uint64_t InsnID = readULEB();
1404 uint16_t RendererID = readU16();
1405 uint64_t RenderOpID = readULEB();
1406 uint16_t SubRegIdx = readU16();
1407 MachineInstrBuilder &MI = OutMIs[InsnID];
1408 assert(MI && "Attempted to add to undefined instruction");
1409 State.Renderers[RendererID][RenderOpID](MI);
1410 MI->getOperand(MI->getNumOperands() - 1).setSubReg(SubRegIdx);
1411 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1412 dbgs() << CurrentIdx
1413 << ": GIR_ComplexSubOperandSubRegRenderer(OutMIs["
1414 << InsnID << "], " << RendererID << ", "
1415 << RenderOpID << ", " << SubRegIdx << ")\n");
1416 break;
1417 }
1418
1420 uint64_t NewInsnID = readULEB();
1421 uint64_t OldInsnID = readULEB();
1422 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1423 assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
1424 "Expected G_CONSTANT");
1425 if (State.MIs[OldInsnID]->getOperand(1).isCImm()) {
1426 OutMIs[NewInsnID].addImm(
1427 State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue());
1428 } else if (State.MIs[OldInsnID]->getOperand(1).isImm())
1429 OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1));
1430 else
1431 llvm_unreachable("Expected Imm or CImm operand");
1432 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1433 dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs["
1434 << NewInsnID << "], MIs[" << OldInsnID << "])\n");
1435 break;
1436 }
1437
1438 // TODO: Needs a test case once we have a pattern that uses this.
1440 uint64_t NewInsnID = readULEB();
1441 uint64_t OldInsnID = readULEB();
1442 assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
1443 assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
1444 "Expected G_FCONSTANT");
1445 if (State.MIs[OldInsnID]->getOperand(1).isFPImm())
1446 OutMIs[NewInsnID].addFPImm(
1447 State.MIs[OldInsnID]->getOperand(1).getFPImm());
1448 else
1449 llvm_unreachable("Expected FPImm operand");
1450 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1451 dbgs()
1452 << CurrentIdx << ": GIR_CopyFPConstantAsFPImm(OutMIs["
1453 << NewInsnID << "], MIs[" << OldInsnID << "])\n");
1454 break;
1455 }
1456
1457 case GIR_CustomRenderer: {
1458 uint64_t InsnID = readULEB();
1459 uint64_t OldInsnID = readULEB();
1460 uint16_t RendererFnID = readU16();
1461 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1462 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1463 dbgs() << CurrentIdx << ": GIR_CustomRenderer(OutMIs["
1464 << InsnID << "], MIs[" << OldInsnID << "], "
1465 << RendererFnID << ")\n");
1466 (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
1467 OutMIs[InsnID], *State.MIs[OldInsnID],
1468 -1); // Not a source operand of the old instruction.
1469 break;
1470 }
1472 uint16_t FnID = readU16();
1473 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1474 dbgs() << CurrentIdx << ": GIR_DoneWithCustomAction(FnID="
1475 << FnID << ")\n");
1476 assert(FnID > GICXXCustomAction_Invalid && "Expected a valid FnID");
1477 if (runCustomAction(FnID, State, OutMIs)) {
1478 initializeOutMIFlagState(OutMIs.size());
1479 for (unsigned I = 0, E = OutMIs.size(); I != E; ++I)
1480 OutMIFlagsToDrop[I] &= ~OutMIs[I]->getFlags();
1481 propagateFlags();
1482 return true;
1483 }
1484
1485 if (handleReject() == RejectAndGiveUp)
1486 return false;
1487 break;
1488 }
1490 uint64_t InsnID = readULEB();
1491 uint64_t OldInsnID = readULEB();
1492 uint64_t OpIdx = readULEB();
1493 uint16_t RendererFnID = readU16();
1494 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1495
1496 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1497 dbgs() << CurrentIdx
1498 << ": GIR_CustomOperandRenderer(OutMIs[" << InsnID
1499 << "], MIs[" << OldInsnID << "]->getOperand("
1500 << OpIdx << "), " << RendererFnID << ")\n");
1501 (Exec.*ExecInfo.CustomRenderers[RendererFnID])(
1502 OutMIs[InsnID], *State.MIs[OldInsnID], OpIdx);
1503 break;
1504 }
1506 uint64_t InsnID = readULEB();
1507 uint64_t OpIdx = readULEB();
1508 uint16_t RCEnum = readU16();
1509 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1510 MachineInstr &I = *OutMIs[InsnID].getInstr();
1511 MachineFunction &MF = *I.getParent()->getParent();
1512 MachineRegisterInfo &MRI = MF.getRegInfo();
1513 const TargetRegisterClass &RC = *TRI.getRegClass(RCEnum);
1514 MachineOperand &MO = I.getOperand(OpIdx);
1515 constrainOperandRegClass(MF, TRI, MRI, TII, RBI, I, RC, MO);
1516 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1517 dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs["
1518 << InsnID << "], " << OpIdx << ", " << RCEnum
1519 << ")\n");
1520 break;
1521 }
1522
1525 uint64_t InsnID = (MatcherOpcode == GIR_RootConstrainSelectedInstOperands)
1526 ? 0
1527 : readULEB();
1528 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1529 constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
1530 RBI);
1531 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1532 dbgs() << CurrentIdx
1533 << ": GIR_ConstrainSelectedInstOperands(OutMIs["
1534 << InsnID << "])\n");
1535 break;
1536 }
1537 case GIR_MergeMemOperands: {
1538 uint64_t InsnID = readULEB();
1539 uint64_t NumInsn = MatchTable[CurrentIdx++];
1540 assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
1541
1542 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1543 dbgs() << CurrentIdx << ": GIR_MergeMemOperands(OutMIs["
1544 << InsnID << "]");
1545 for (unsigned K = 0; K < NumInsn; ++K) {
1546 uint64_t NextID = readULEB();
1547 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1548 dbgs() << ", MIs[" << NextID << "]");
1549 for (const auto &MMO : State.MIs[NextID]->memoperands())
1550 OutMIs[InsnID].addMemOperand(MMO);
1551 }
1552 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << ")\n");
1553 break;
1554 }
1555 case GIR_EraseFromParent: {
1556 uint64_t InsnID = readULEB();
1557 MachineInstr *MI = State.MIs[InsnID];
1558 assert(MI && "Attempted to erase an undefined instruction");
1559 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1560 dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs["
1561 << InsnID << "])\n");
1562 eraseImpl(MI);
1563 break;
1564 }
1566 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1567 dbgs()
1568 << CurrentIdx << ": GIR_EraseRootFromParent_Done\n");
1569 eraseImpl(State.MIs[0]);
1570 propagateFlags();
1571 return true;
1572 }
1573 case GIR_MakeTempReg: {
1574 uint64_t TempRegID = readULEB();
1575 int TypeID = readS8();
1576
1577 State.TempRegisters[TempRegID] =
1578 MRI.createGenericVirtualRegister(getTypeFromIdx(TypeID));
1579 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1580 dbgs() << CurrentIdx << ": TempRegs[" << TempRegID
1581 << "] = GIR_MakeTempReg(" << TypeID << ")\n");
1582 break;
1583 }
1584 case GIR_ReplaceReg: {
1585 uint64_t OldInsnID = readULEB();
1586 uint64_t OldOpIdx = readULEB();
1587 uint64_t NewInsnID = readULEB();
1588 uint64_t NewOpIdx = readULEB();
1589
1590 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1591 dbgs() << CurrentIdx << ": GIR_ReplaceReg(MIs["
1592 << OldInsnID << "][" << OldOpIdx << "] = MIs["
1593 << NewInsnID << "][" << NewOpIdx << "])\n");
1594
1595 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1596 Register New = State.MIs[NewInsnID]->getOperand(NewOpIdx).getReg();
1597 if (Observer)
1598 Observer->changingAllUsesOfReg(MRI, Old);
1599 MRI.replaceRegWith(Old, New);
1600 if (Observer)
1601 Observer->finishedChangingAllUsesOfReg();
1602 break;
1603 }
1605 uint64_t OldInsnID = readULEB();
1606 uint64_t OldOpIdx = readULEB();
1607 uint64_t TempRegID = readULEB();
1608
1609 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1610 dbgs() << CurrentIdx << ": GIR_ReplaceRegWithTempReg(MIs["
1611 << OldInsnID << "][" << OldOpIdx << "] = TempRegs["
1612 << TempRegID << "])\n");
1613
1614 Register Old = State.MIs[OldInsnID]->getOperand(OldOpIdx).getReg();
1615 Register New = State.TempRegisters[TempRegID];
1616 if (Observer)
1617 Observer->changingAllUsesOfReg(MRI, Old);
1618 MRI.replaceRegWith(Old, New);
1619 if (Observer)
1620 Observer->finishedChangingAllUsesOfReg();
1621 break;
1622 }
1623 case GIR_Coverage: {
1624 uint32_t RuleID = readU32();
1626 CoverageInfo->setCovered(RuleID);
1627
1628 DEBUG_WITH_TYPE(TgtExecutor::getName(), dbgs() << CurrentIdx
1629 << ": GIR_Coverage("
1630 << RuleID << ")");
1631 break;
1632 }
1633
1634 case GIR_Done:
1635 DEBUG_WITH_TYPE(TgtExecutor::getName(),
1636 dbgs() << CurrentIdx << ": GIR_Done\n");
1637 propagateFlags();
1638 return true;
1639 default:
1640 llvm_unreachable("Unexpected command");
1641 }
1642 }
1643}
1644
1645} // end namespace llvm
1646
1647#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
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
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:767
iterator end()
Definition DenseMap.h:687
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 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: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_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_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.
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