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