1//===- llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h --------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// \file This file declares the API for the instruction selector.
11/// This class is responsible for selecting machine instructions.
12/// It's implemented by the target. It's used by the InstructionSelect pass.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
17#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
18
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
21#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineOperand.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/ErrorHandling.h"
27#include "llvm/Support/raw_ostream.h"
28#include "llvm/Target/TargetInstrInfo.h"
29#include "llvm/Target/TargetOpcodes.h"
30#include "llvm/Target/TargetRegisterInfo.h"
31#include <cassert>
32#include <cstddef>
33#include <cstdint>
34
35namespace llvm {
36
37/// GlobalISel PatFrag Predicates
38enum {
39  GIPFP_I64_Invalid = 0,
40  GIPFP_APInt_Invalid = 0,
41  GIPFP_APFloat_Invalid = 0,
42};
43
44template <class TgtInstructionSelector, class PredicateBitset,
45          class ComplexMatcherMemFn>
46bool InstructionSelector::executeMatchTable(
47    TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
48    const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
49    const int64_t *MatchTable, const TargetInstrInfo &TII,
50    MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
51    const RegisterBankInfo &RBI,
52    const PredicateBitset &AvailableFeatures) const {
53  uint64_t CurrentIdx = 0;
54  SmallVector<uint64_t, 8> OnFailResumeAt;
55
56  enum RejectAction { RejectAndGiveUp, RejectAndResume };
57  auto handleReject = [&]() -> RejectAction {
58    DEBUG(dbgs() << CurrentIdx << ": Rejected\n");
59    if (OnFailResumeAt.empty())
60      return RejectAndGiveUp;
61    CurrentIdx = OnFailResumeAt.back();
62    OnFailResumeAt.pop_back();
63    DEBUG(dbgs() << CurrentIdx << ": Resume at " << CurrentIdx << " ("
64                 << OnFailResumeAt.size() << " try-blocks remain)\n");
65    return RejectAndResume;
66  };
67
68  while (true) {
69    assert(CurrentIdx != ~0u && "Invalid MatchTable index");
70    switch (MatchTable[CurrentIdx++]) {
71    case GIM_Try: {
72      DEBUG(dbgs() << CurrentIdx << ": Begin try-block\n");
73      OnFailResumeAt.push_back(MatchTable[CurrentIdx++]);
74      break;
75    }
76
77    case GIM_RecordInsn: {
78      int64_t NewInsnID = MatchTable[CurrentIdx++];
79      int64_t InsnID = MatchTable[CurrentIdx++];
80      int64_t OpIdx = MatchTable[CurrentIdx++];
81
82      // As an optimisation we require that MIs[0] is always the root. Refuse
83      // any attempt to modify it.
84      assert(NewInsnID != 0 && "Refusing to modify MIs[0]");
85
86      MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
87      if (!MO.isReg()) {
88        DEBUG(dbgs() << CurrentIdx << ": Not a register\n");
89        if (handleReject() == RejectAndGiveUp)
90          return false;
91        break;
92      }
93      if (TRI.isPhysicalRegister(MO.getReg())) {
94        DEBUG(dbgs() << CurrentIdx << ": Is a physical register\n");
95        if (handleReject() == RejectAndGiveUp)
96          return false;
97        break;
98      }
99
100      MachineInstr *NewMI = MRI.getVRegDef(MO.getReg());
101      if ((size_t)NewInsnID < State.MIs.size())
102        State.MIs[NewInsnID] = NewMI;
103      else {
104        assert((size_t)NewInsnID == State.MIs.size() &&
105               "Expected to store MIs in order");
106        State.MIs.push_back(NewMI);
107      }
108      DEBUG(dbgs() << CurrentIdx << ": MIs[" << NewInsnID
109                   << "] = GIM_RecordInsn(" << InsnID << ", " << OpIdx
110                   << ")\n");
111      break;
112    }
113
114    case GIM_CheckFeatures: {
115      int64_t ExpectedBitsetID = MatchTable[CurrentIdx++];
116      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckFeatures(ExpectedBitsetID="
117                   << ExpectedBitsetID << ")\n");
118      if ((AvailableFeatures & MatcherInfo.FeatureBitsets[ExpectedBitsetID]) !=
119          MatcherInfo.FeatureBitsets[ExpectedBitsetID]) {
120        if (handleReject() == RejectAndGiveUp)
121          return false;
122      }
123      break;
124    }
125
126    case GIM_CheckOpcode: {
127      int64_t InsnID = MatchTable[CurrentIdx++];
128      int64_t Expected = MatchTable[CurrentIdx++];
129
130      unsigned Opcode = State.MIs[InsnID]->getOpcode();
131      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckOpcode(MIs[" << InsnID
132                   << "], ExpectedOpcode=" << Expected << ") // Got=" << Opcode
133                   << "\n");
134      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
135      if (Opcode != Expected) {
136        if (handleReject() == RejectAndGiveUp)
137          return false;
138      }
139      break;
140    }
141
142    case GIM_CheckNumOperands: {
143      int64_t InsnID = MatchTable[CurrentIdx++];
144      int64_t Expected = MatchTable[CurrentIdx++];
145      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckNumOperands(MIs[" << InsnID
146                   << "], Expected=" << Expected << ")\n");
147      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
148      if (State.MIs[InsnID]->getNumOperands() != Expected) {
149        if (handleReject() == RejectAndGiveUp)
150          return false;
151      }
152      break;
153    }
154    case GIM_CheckI64ImmPredicate: {
155      int64_t InsnID = MatchTable[CurrentIdx++];
156      int64_t Predicate = MatchTable[CurrentIdx++];
157      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckI64ImmPredicate(MIs[" << InsnID
158                   << "], Predicate=" << Predicate << ")\n");
159      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
160      assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
161             "Expected G_CONSTANT");
162      assert(Predicate > GIPFP_I64_Invalid && "Expected a valid predicate");
163      int64_t Value = 0;
164      if (State.MIs[InsnID]->getOperand(1).isCImm())
165        Value = State.MIs[InsnID]->getOperand(1).getCImm()->getSExtValue();
166      else if (State.MIs[InsnID]->getOperand(1).isImm())
167        Value = State.MIs[InsnID]->getOperand(1).getImm();
168      else
169        llvm_unreachable("Expected Imm or CImm operand");
170
171      if (!MatcherInfo.I64ImmPredicateFns[Predicate](Value))
172        if (handleReject() == RejectAndGiveUp)
173          return false;
174      break;
175    }
176    case GIM_CheckAPIntImmPredicate: {
177      int64_t InsnID = MatchTable[CurrentIdx++];
178      int64_t Predicate = MatchTable[CurrentIdx++];
179      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckAPIntImmPredicate(MIs["
180                   << InsnID << "], Predicate=" << Predicate << ")\n");
181      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
182      assert(State.MIs[InsnID]->getOpcode() && "Expected G_CONSTANT");
183      assert(Predicate > GIPFP_APInt_Invalid && "Expected a valid predicate");
184      APInt Value;
185      if (State.MIs[InsnID]->getOperand(1).isCImm())
186        Value = State.MIs[InsnID]->getOperand(1).getCImm()->getValue();
187      else
188        llvm_unreachable("Expected Imm or CImm operand");
189
190      if (!MatcherInfo.APIntImmPredicateFns[Predicate](Value))
191        if (handleReject() == RejectAndGiveUp)
192          return false;
193      break;
194    }
195    case GIM_CheckAPFloatImmPredicate: {
196      int64_t InsnID = MatchTable[CurrentIdx++];
197      int64_t Predicate = MatchTable[CurrentIdx++];
198      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckAPFloatImmPredicate(MIs[" << InsnID
199                   << "], Predicate=" << Predicate << ")\n");
200      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
201      assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_FCONSTANT &&
202             "Expected G_FCONSTANT");
203      assert(State.MIs[InsnID]->getOperand(1).isFPImm() && "Expected FPImm operand");
204      assert(Predicate > GIPFP_APFloat_Invalid && "Expected a valid predicate");
205      APFloat Value = State.MIs[InsnID]->getOperand(1).getFPImm()->getValueAPF();
206
207      if (!MatcherInfo.APFloatImmPredicateFns[Predicate](Value))
208        if (handleReject() == RejectAndGiveUp)
209          return false;
210      break;
211    }
212    case GIM_CheckNonAtomic: {
213      int64_t InsnID = MatchTable[CurrentIdx++];
214      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckNonAtomic(MIs[" << InsnID
215                   << "])\n");
216      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
217      assert((State.MIs[InsnID]->getOpcode() == TargetOpcode::G_LOAD ||
218              State.MIs[InsnID]->getOpcode() == TargetOpcode::G_STORE) &&
219             "Expected G_LOAD/G_STORE");
220
221      if (!State.MIs[InsnID]->hasOneMemOperand())
222        if (handleReject() == RejectAndGiveUp)
223          return false;
224
225      for (const auto &MMO : State.MIs[InsnID]->memoperands())
226        if (MMO->getOrdering() != AtomicOrdering::NotAtomic)
227          if (handleReject() == RejectAndGiveUp)
228            return false;
229      break;
230    }
231
232    case GIM_CheckType: {
233      int64_t InsnID = MatchTable[CurrentIdx++];
234      int64_t OpIdx = MatchTable[CurrentIdx++];
235      int64_t TypeID = MatchTable[CurrentIdx++];
236      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckType(MIs[" << InsnID
237                   << "]->getOperand(" << OpIdx << "), TypeID=" << TypeID
238                   << ")\n");
239      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
240      if (MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg()) !=
241          MatcherInfo.TypeObjects[TypeID]) {
242        if (handleReject() == RejectAndGiveUp)
243          return false;
244      }
245      break;
246    }
247    case GIM_CheckPointerToAny: {
248      int64_t InsnID = MatchTable[CurrentIdx++];
249      int64_t OpIdx = MatchTable[CurrentIdx++];
250      int64_t SizeInBits = MatchTable[CurrentIdx++];
251
252      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckPointerToAny(MIs[" << InsnID
253                   << "]->getOperand(" << OpIdx
254                   << "), SizeInBits=" << SizeInBits << ")\n");
255      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
256
257      // iPTR must be looked up in the target.
258      if (SizeInBits == 0) {
259        MachineFunction *MF = State.MIs[InsnID]->getParent()->getParent();
260        SizeInBits = MF->getDataLayout().getPointerSizeInBits(0);
261      }
262
263      assert(SizeInBits != 0 && "Pointer size must be known");
264
265      const LLT &Ty = MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg());
266      if (!Ty.isPointer() || Ty.getSizeInBits() != SizeInBits) {
267        if (handleReject() == RejectAndGiveUp)
268          return false;
269      }
270      break;
271    }
272    case GIM_CheckRegBankForClass: {
273      int64_t InsnID = MatchTable[CurrentIdx++];
274      int64_t OpIdx = MatchTable[CurrentIdx++];
275      int64_t RCEnum = MatchTable[CurrentIdx++];
276      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckRegBankForClass(MIs[" << InsnID
277                   << "]->getOperand(" << OpIdx << "), RCEnum=" << RCEnum
278                   << ")\n");
279      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
280      if (&RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum)) !=
281          RBI.getRegBank(State.MIs[InsnID]->getOperand(OpIdx).getReg(), MRI,
282                         TRI)) {
283        if (handleReject() == RejectAndGiveUp)
284          return false;
285      }
286      break;
287    }
288
289    case GIM_CheckComplexPattern: {
290      int64_t InsnID = MatchTable[CurrentIdx++];
291      int64_t OpIdx = MatchTable[CurrentIdx++];
292      int64_t RendererID = MatchTable[CurrentIdx++];
293      int64_t ComplexPredicateID = MatchTable[CurrentIdx++];
294      DEBUG(dbgs() << CurrentIdx << ": State.Renderers[" << RendererID
295                   << "] = GIM_CheckComplexPattern(MIs[" << InsnID
296                   << "]->getOperand(" << OpIdx
297                   << "), ComplexPredicateID=" << ComplexPredicateID << ")\n");
298      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
299      // FIXME: Use std::invoke() when it's available.
300      ComplexRendererFn Renderer =
301          (ISel.*MatcherInfo.ComplexPredicates[ComplexPredicateID])(
302              State.MIs[InsnID]->getOperand(OpIdx));
303      if (Renderer.hasValue())
304        State.Renderers[RendererID] = Renderer.getValue();
305      else
306        if (handleReject() == RejectAndGiveUp)
307          return false;
308      break;
309    }
310
311    case GIM_CheckConstantInt: {
312      int64_t InsnID = MatchTable[CurrentIdx++];
313      int64_t OpIdx = MatchTable[CurrentIdx++];
314      int64_t Value = MatchTable[CurrentIdx++];
315      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckConstantInt(MIs[" << InsnID
316                   << "]->getOperand(" << OpIdx << "), Value=" << Value
317                   << ")\n");
318      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
319      if (!isOperandImmEqual(State.MIs[InsnID]->getOperand(OpIdx), Value,
320                             MRI)) {
321        if (handleReject() == RejectAndGiveUp)
322          return false;
323      }
324      break;
325    }
326
327    case GIM_CheckLiteralInt: {
328      int64_t InsnID = MatchTable[CurrentIdx++];
329      int64_t OpIdx = MatchTable[CurrentIdx++];
330      int64_t Value = MatchTable[CurrentIdx++];
331      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckLiteralInt(MIs[" << InsnID
332                   << "]->getOperand(" << OpIdx << "), Value=" << Value
333                   << ")\n");
334      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
335      MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
336      if (!MO.isCImm() || !MO.getCImm()->equalsInt(Value)) {
337        if (handleReject() == RejectAndGiveUp)
338          return false;
339      }
340      break;
341    }
342
343    case GIM_CheckIntrinsicID: {
344      int64_t InsnID = MatchTable[CurrentIdx++];
345      int64_t OpIdx = MatchTable[CurrentIdx++];
346      int64_t Value = MatchTable[CurrentIdx++];
347      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckIntrinsicID(MIs[" << InsnID
348                   << "]->getOperand(" << OpIdx << "), Value=" << Value
349                   << ")\n");
350      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
351      MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
352      if (!MO.isIntrinsicID() || MO.getIntrinsicID() != Value)
353        if (handleReject() == RejectAndGiveUp)
354          return false;
355      break;
356    }
357
358    case GIM_CheckIsMBB: {
359      int64_t InsnID = MatchTable[CurrentIdx++];
360      int64_t OpIdx = MatchTable[CurrentIdx++];
361      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckIsMBB(MIs[" << InsnID
362                   << "]->getOperand(" << OpIdx << "))\n");
363      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
364      if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB()) {
365        if (handleReject() == RejectAndGiveUp)
366          return false;
367      }
368      break;
369    }
370
371    case GIM_CheckIsSafeToFold: {
372      int64_t InsnID = MatchTable[CurrentIdx++];
373      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckIsSafeToFold(MIs[" << InsnID
374                   << "])\n");
375      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
376      if (!isObviouslySafeToFold(*State.MIs[InsnID])) {
377        if (handleReject() == RejectAndGiveUp)
378          return false;
379      }
380      break;
381    }
382    case GIM_CheckIsSameOperand: {
383      int64_t InsnID = MatchTable[CurrentIdx++];
384      int64_t OpIdx = MatchTable[CurrentIdx++];
385      int64_t OtherInsnID = MatchTable[CurrentIdx++];
386      int64_t OtherOpIdx = MatchTable[CurrentIdx++];
387      DEBUG(dbgs() << CurrentIdx << ": GIM_CheckIsSameOperand(MIs[" << InsnID
388                   << "][" << OpIdx << "], MIs[" << OtherInsnID << "]["
389                   << OtherOpIdx << "])\n");
390      assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
391      assert(State.MIs[OtherInsnID] != nullptr && "Used insn before defined");
392      if (!State.MIs[InsnID]->getOperand(OpIdx).isIdenticalTo(
393              State.MIs[OtherInsnID]->getOperand(OtherOpIdx))) {
394        if (handleReject() == RejectAndGiveUp)
395          return false;
396      }
397      break;
398    }
399    case GIM_Reject:
400      DEBUG(dbgs() << CurrentIdx << ": GIM_Reject");
401      if (handleReject() == RejectAndGiveUp)
402        return false;
403      break;
404
405    case GIR_MutateOpcode: {
406      int64_t OldInsnID = MatchTable[CurrentIdx++];
407      int64_t NewInsnID = MatchTable[CurrentIdx++];
408      int64_t NewOpcode = MatchTable[CurrentIdx++];
409      assert((size_t)NewInsnID == OutMIs.size() &&
410             "Expected to store MIs in order");
411      OutMIs.push_back(MachineInstrBuilder(*State.MIs[OldInsnID]->getMF(),
412                                           State.MIs[OldInsnID]));
413      OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
414      DEBUG(dbgs() << CurrentIdx << ": GIR_MutateOpcode(OutMIs[" << NewInsnID
415                   << "], MIs[" << OldInsnID << "], " << NewOpcode << ")\n");
416      break;
417    }
418
419    case GIR_BuildMI: {
420      int64_t InsnID = MatchTable[CurrentIdx++];
421      int64_t Opcode = MatchTable[CurrentIdx++];
422      assert((size_t)InsnID == OutMIs.size() &&
423             "Expected to store MIs in order");
424      (void)InsnID;
425      OutMIs.push_back(BuildMI(*State.MIs[0]->getParent(), State.MIs[0],
426                               State.MIs[0]->getDebugLoc(), TII.get(Opcode)));
427      DEBUG(dbgs() << CurrentIdx << ": GIR_BuildMI(OutMIs[" << InsnID << "], "
428                   << Opcode << ")\n");
429      break;
430    }
431
432    case GIR_Copy: {
433      int64_t NewInsnID = MatchTable[CurrentIdx++];
434      int64_t OldInsnID = MatchTable[CurrentIdx++];
435      int64_t OpIdx = MatchTable[CurrentIdx++];
436      assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
437      OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
438      DEBUG(dbgs() << CurrentIdx << ": GIR_Copy(OutMIs[" << NewInsnID
439                   << "], MIs[" << OldInsnID << "], " << OpIdx << ")\n");
440      break;
441    }
442
443    case GIR_CopySubReg: {
444      int64_t NewInsnID = MatchTable[CurrentIdx++];
445      int64_t OldInsnID = MatchTable[CurrentIdx++];
446      int64_t OpIdx = MatchTable[CurrentIdx++];
447      int64_t SubRegIdx = MatchTable[CurrentIdx++];
448      assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
449      OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
450                               0, SubRegIdx);
451      DEBUG(dbgs() << CurrentIdx << ": GIR_CopySubReg(OutMIs[" << NewInsnID
452                   << "], MIs[" << OldInsnID << "], " << OpIdx << ", "
453                   << SubRegIdx << ")\n");
454      break;
455    }
456
457    case GIR_AddImplicitDef: {
458      int64_t InsnID = MatchTable[CurrentIdx++];
459      int64_t RegNum = MatchTable[CurrentIdx++];
460      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
461      OutMIs[InsnID].addDef(RegNum, RegState::Implicit);
462      DEBUG(dbgs() << CurrentIdx << ": GIR_AddImplicitDef(OutMIs[" << InsnID
463                   << "], " << RegNum << ")\n");
464      break;
465    }
466
467    case GIR_AddImplicitUse: {
468      int64_t InsnID = MatchTable[CurrentIdx++];
469      int64_t RegNum = MatchTable[CurrentIdx++];
470      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
471      OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
472      DEBUG(dbgs() << CurrentIdx << ": GIR_AddImplicitUse(OutMIs[" << InsnID
473                   << "], " << RegNum << ")\n");
474      break;
475    }
476
477    case GIR_AddRegister: {
478      int64_t InsnID = MatchTable[CurrentIdx++];
479      int64_t RegNum = MatchTable[CurrentIdx++];
480      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
481      OutMIs[InsnID].addReg(RegNum);
482      DEBUG(dbgs() << CurrentIdx << ": GIR_AddRegister(OutMIs[" << InsnID
483                   << "], " << RegNum << ")\n");
484      break;
485    }
486
487    case GIR_AddImm: {
488      int64_t InsnID = MatchTable[CurrentIdx++];
489      int64_t Imm = MatchTable[CurrentIdx++];
490      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
491      OutMIs[InsnID].addImm(Imm);
492      DEBUG(dbgs() << CurrentIdx << ": GIR_AddImm(OutMIs[" << InsnID << "], "
493                   << Imm << ")\n");
494      break;
495    }
496
497    case GIR_ComplexRenderer: {
498      int64_t InsnID = MatchTable[CurrentIdx++];
499      int64_t RendererID = MatchTable[CurrentIdx++];
500      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
501      for (const auto &RenderOpFn : State.Renderers[RendererID])
502        RenderOpFn(OutMIs[InsnID]);
503      DEBUG(dbgs() << CurrentIdx << ": GIR_ComplexRenderer(OutMIs[" << InsnID
504                   << "], " << RendererID << ")\n");
505      break;
506    }
507    case GIR_ComplexSubOperandRenderer: {
508      int64_t InsnID = MatchTable[CurrentIdx++];
509      int64_t RendererID = MatchTable[CurrentIdx++];
510      int64_t RenderOpID = MatchTable[CurrentIdx++];
511      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
512      State.Renderers[RendererID][RenderOpID](OutMIs[InsnID]);
513      DEBUG(dbgs() << CurrentIdx << ": GIR_ComplexSubOperandRenderer(OutMIs["
514                   << InsnID << "], " << RendererID << ", " << RenderOpID
515                   << ")\n");
516      break;
517    }
518
519    case GIR_CopyConstantAsSImm: {
520      int64_t NewInsnID = MatchTable[CurrentIdx++];
521      int64_t OldInsnID = MatchTable[CurrentIdx++];
522      assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
523      assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT && "Expected G_CONSTANT");
524      if (State.MIs[OldInsnID]->getOperand(1).isCImm()) {
525        OutMIs[NewInsnID].addImm(
526            State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue());
527      } else if (State.MIs[OldInsnID]->getOperand(1).isImm())
528        OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1));
529      else
530        llvm_unreachable("Expected Imm or CImm operand");
531      DEBUG(dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs[" << NewInsnID
532                   << "], MIs[" << OldInsnID << "])\n");
533      break;
534    }
535
536    case GIR_ConstrainOperandRC: {
537      int64_t InsnID = MatchTable[CurrentIdx++];
538      int64_t OpIdx = MatchTable[CurrentIdx++];
539      int64_t RCEnum = MatchTable[CurrentIdx++];
540      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
541      constrainOperandRegToRegClass(*OutMIs[InsnID].getInstr(), OpIdx,
542                                    *TRI.getRegClass(RCEnum), TII, TRI, RBI);
543      DEBUG(dbgs() << CurrentIdx << ": GIR_ConstrainOperandRC(OutMIs[" << InsnID
544                   << "], " << OpIdx << ", " << RCEnum << ")\n");
545      break;
546    }
547
548    case GIR_ConstrainSelectedInstOperands: {
549      int64_t InsnID = MatchTable[CurrentIdx++];
550      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
551      constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
552                                       RBI);
553      DEBUG(dbgs() << CurrentIdx
554                   << ": GIR_ConstrainSelectedInstOperands(OutMIs[" << InsnID
555                   << "])\n");
556      break;
557    }
558
559    case GIR_MergeMemOperands: {
560      int64_t InsnID = MatchTable[CurrentIdx++];
561      assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
562
563      DEBUG(dbgs() << CurrentIdx << ": GIR_MergeMemOperands(OutMIs[" << InsnID
564                   << "]");
565      int64_t MergeInsnID = GIU_MergeMemOperands_EndOfList;
566      while ((MergeInsnID = MatchTable[CurrentIdx++]) !=
567             GIU_MergeMemOperands_EndOfList) {
568        DEBUG(dbgs() << ", MIs[" << MergeInsnID << "]");
569        for (const auto &MMO : State.MIs[MergeInsnID]->memoperands())
570          OutMIs[InsnID].addMemOperand(MMO);
571      }
572      DEBUG(dbgs() << ")\n");
573      break;
574    }
575
576    case GIR_EraseFromParent: {
577      int64_t InsnID = MatchTable[CurrentIdx++];
578      assert(State.MIs[InsnID] &&
579             "Attempted to erase an undefined instruction");
580      State.MIs[InsnID]->eraseFromParent();
581      DEBUG(dbgs() << CurrentIdx << ": GIR_EraseFromParent(MIs[" << InsnID
582                   << "])\n");
583      break;
584    }
585
586    case GIR_Done:
587      DEBUG(dbgs() << CurrentIdx << ": GIR_Done");
588      return true;
589
590    default:
591      llvm_unreachable("Unexpected command");
592    }
593  }
594}
595
596} // end namespace llvm
597
598#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
599