1 //===-- SPIRVEmitIntrinsics.cpp - emit SPIRV intrinsics ---------*- 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 // The pass emits SPIRV intrinsics keeping essential high-level information for 10 // the translation of LLVM IR to SPIR-V. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "SPIRV.h" 15 #include "SPIRVTargetMachine.h" 16 #include "SPIRVUtils.h" 17 #include "llvm/IR/IRBuilder.h" 18 #include "llvm/IR/InstIterator.h" 19 #include "llvm/IR/InstVisitor.h" 20 #include "llvm/IR/IntrinsicsSPIRV.h" 21 22 #include <queue> 23 24 // This pass performs the following transformation on LLVM IR level required 25 // for the following translation to SPIR-V: 26 // - replaces direct usages of aggregate constants with target-specific 27 // intrinsics; 28 // - replaces aggregates-related instructions (extract/insert, ld/st, etc) 29 // with a target-specific intrinsics; 30 // - emits intrinsics for the global variable initializers since IRTranslator 31 // doesn't handle them and it's not very convenient to translate them 32 // ourselves; 33 // - emits intrinsics to keep track of the string names assigned to the values; 34 // - emits intrinsics to keep track of constants (this is necessary to have an 35 // LLVM IR constant after the IRTranslation is completed) for their further 36 // deduplication; 37 // - emits intrinsics to keep track of original LLVM types of the values 38 // to be able to emit proper SPIR-V types eventually. 39 // 40 // TODO: consider removing spv.track.constant in favor of spv.assign.type. 41 42 using namespace llvm; 43 44 namespace llvm { 45 void initializeSPIRVEmitIntrinsicsPass(PassRegistry &); 46 } // namespace llvm 47 48 namespace { 49 class SPIRVEmitIntrinsics 50 : public FunctionPass, 51 public InstVisitor<SPIRVEmitIntrinsics, Instruction *> { 52 SPIRVTargetMachine *TM = nullptr; 53 IRBuilder<> *IRB = nullptr; 54 Function *F = nullptr; 55 bool TrackConstants = true; 56 DenseMap<Instruction *, Constant *> AggrConsts; 57 DenseSet<Instruction *> AggrStores; 58 void preprocessCompositeConstants(); 59 void preprocessUndefs(); 60 CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types, 61 Value *Arg, Value *Arg2, 62 ArrayRef<Constant *> Imms) { 63 ConstantAsMetadata *CM = ValueAsMetadata::getConstant(Arg); 64 MDTuple *TyMD = MDNode::get(F->getContext(), CM); 65 MetadataAsValue *VMD = MetadataAsValue::get(F->getContext(), TyMD); 66 SmallVector<Value *, 4> Args; 67 Args.push_back(Arg2); 68 Args.push_back(VMD); 69 for (auto *Imm : Imms) 70 Args.push_back(Imm); 71 return IRB->CreateIntrinsic(IntrID, {Types}, Args); 72 } 73 void replaceMemInstrUses(Instruction *Old, Instruction *New); 74 void processInstrAfterVisit(Instruction *I); 75 void insertAssignPtrTypeIntrs(Instruction *I); 76 void insertAssignTypeIntrs(Instruction *I); 77 void processGlobalValue(GlobalVariable &GV); 78 79 public: 80 static char ID; 81 SPIRVEmitIntrinsics() : FunctionPass(ID) { 82 initializeSPIRVEmitIntrinsicsPass(*PassRegistry::getPassRegistry()); 83 } 84 SPIRVEmitIntrinsics(SPIRVTargetMachine *_TM) : FunctionPass(ID), TM(_TM) { 85 initializeSPIRVEmitIntrinsicsPass(*PassRegistry::getPassRegistry()); 86 } 87 Instruction *visitInstruction(Instruction &I) { return &I; } 88 Instruction *visitSwitchInst(SwitchInst &I); 89 Instruction *visitGetElementPtrInst(GetElementPtrInst &I); 90 Instruction *visitBitCastInst(BitCastInst &I); 91 Instruction *visitInsertElementInst(InsertElementInst &I); 92 Instruction *visitExtractElementInst(ExtractElementInst &I); 93 Instruction *visitInsertValueInst(InsertValueInst &I); 94 Instruction *visitExtractValueInst(ExtractValueInst &I); 95 Instruction *visitLoadInst(LoadInst &I); 96 Instruction *visitStoreInst(StoreInst &I); 97 Instruction *visitAllocaInst(AllocaInst &I); 98 Instruction *visitAtomicCmpXchgInst(AtomicCmpXchgInst &I); 99 Instruction *visitUnreachableInst(UnreachableInst &I); 100 bool runOnFunction(Function &F) override; 101 }; 102 } // namespace 103 104 char SPIRVEmitIntrinsics::ID = 0; 105 106 INITIALIZE_PASS(SPIRVEmitIntrinsics, "emit-intrinsics", "SPIRV emit intrinsics", 107 false, false) 108 109 static inline bool isAssignTypeInstr(const Instruction *I) { 110 return isa<IntrinsicInst>(I) && 111 cast<IntrinsicInst>(I)->getIntrinsicID() == Intrinsic::spv_assign_type; 112 } 113 114 static bool isMemInstrToReplace(Instruction *I) { 115 return isa<StoreInst>(I) || isa<LoadInst>(I) || isa<InsertValueInst>(I) || 116 isa<ExtractValueInst>(I) || isa<AtomicCmpXchgInst>(I); 117 } 118 119 static bool isAggrToReplace(const Value *V) { 120 return isa<ConstantAggregate>(V) || isa<ConstantDataArray>(V) || 121 (isa<ConstantAggregateZero>(V) && !V->getType()->isVectorTy()); 122 } 123 124 static void setInsertPointSkippingPhis(IRBuilder<> &B, Instruction *I) { 125 if (isa<PHINode>(I)) 126 B.SetInsertPoint(I->getParent(), I->getParent()->getFirstInsertionPt()); 127 else 128 B.SetInsertPoint(I); 129 } 130 131 static bool requireAssignPtrType(Instruction *I) { 132 if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I)) 133 return true; 134 135 return false; 136 } 137 138 static bool requireAssignType(Instruction *I) { 139 IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(I); 140 if (Intr) { 141 switch (Intr->getIntrinsicID()) { 142 case Intrinsic::invariant_start: 143 case Intrinsic::invariant_end: 144 return false; 145 } 146 } 147 return true; 148 } 149 150 void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old, 151 Instruction *New) { 152 while (!Old->user_empty()) { 153 auto *U = Old->user_back(); 154 if (isAssignTypeInstr(U)) { 155 IRB->SetInsertPoint(U); 156 SmallVector<Value *, 2> Args = {New, U->getOperand(1)}; 157 IRB->CreateIntrinsic(Intrinsic::spv_assign_type, {New->getType()}, Args); 158 U->eraseFromParent(); 159 } else if (isMemInstrToReplace(U) || isa<ReturnInst>(U) || 160 isa<CallInst>(U)) { 161 U->replaceUsesOfWith(Old, New); 162 } else { 163 llvm_unreachable("illegal aggregate intrinsic user"); 164 } 165 } 166 Old->eraseFromParent(); 167 } 168 169 void SPIRVEmitIntrinsics::preprocessUndefs() { 170 std::queue<Instruction *> Worklist; 171 for (auto &I : instructions(F)) 172 Worklist.push(&I); 173 174 while (!Worklist.empty()) { 175 Instruction *I = Worklist.front(); 176 Worklist.pop(); 177 178 for (auto &Op : I->operands()) { 179 auto *AggrUndef = dyn_cast<UndefValue>(Op); 180 if (!AggrUndef || !Op->getType()->isAggregateType()) 181 continue; 182 183 IRB->SetInsertPoint(I); 184 auto *IntrUndef = IRB->CreateIntrinsic(Intrinsic::spv_undef, {}, {}); 185 Worklist.push(IntrUndef); 186 I->replaceUsesOfWith(Op, IntrUndef); 187 AggrConsts[IntrUndef] = AggrUndef; 188 } 189 } 190 } 191 192 void SPIRVEmitIntrinsics::preprocessCompositeConstants() { 193 std::queue<Instruction *> Worklist; 194 for (auto &I : instructions(F)) 195 Worklist.push(&I); 196 197 while (!Worklist.empty()) { 198 auto *I = Worklist.front(); 199 assert(I); 200 bool KeepInst = false; 201 for (const auto &Op : I->operands()) { 202 auto BuildCompositeIntrinsic = [&KeepInst, &Worklist, &I, &Op, 203 this](Constant *AggrC, 204 ArrayRef<Value *> Args) { 205 IRB->SetInsertPoint(I); 206 auto *CCI = 207 IRB->CreateIntrinsic(Intrinsic::spv_const_composite, {}, {Args}); 208 Worklist.push(CCI); 209 I->replaceUsesOfWith(Op, CCI); 210 KeepInst = true; 211 AggrConsts[CCI] = AggrC; 212 }; 213 214 if (auto *AggrC = dyn_cast<ConstantAggregate>(Op)) { 215 SmallVector<Value *> Args(AggrC->op_begin(), AggrC->op_end()); 216 BuildCompositeIntrinsic(AggrC, Args); 217 } else if (auto *AggrC = dyn_cast<ConstantDataArray>(Op)) { 218 SmallVector<Value *> Args; 219 for (unsigned i = 0; i < AggrC->getNumElements(); ++i) 220 Args.push_back(AggrC->getElementAsConstant(i)); 221 BuildCompositeIntrinsic(AggrC, Args); 222 } else if (isa<ConstantAggregateZero>(Op) && 223 !Op->getType()->isVectorTy()) { 224 auto *AggrC = cast<ConstantAggregateZero>(Op); 225 SmallVector<Value *> Args(AggrC->op_begin(), AggrC->op_end()); 226 BuildCompositeIntrinsic(AggrC, Args); 227 } 228 } 229 if (!KeepInst) 230 Worklist.pop(); 231 } 232 } 233 234 Instruction *SPIRVEmitIntrinsics::visitSwitchInst(SwitchInst &I) { 235 SmallVector<Value *, 4> Args; 236 for (auto &Op : I.operands()) 237 if (Op.get()->getType()->isSized()) 238 Args.push_back(Op); 239 IRB->SetInsertPoint(&I); 240 IRB->CreateIntrinsic(Intrinsic::spv_switch, {I.getOperand(0)->getType()}, 241 {Args}); 242 return &I; 243 } 244 245 Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) { 246 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()}; 247 SmallVector<Value *, 4> Args; 248 Args.push_back(IRB->getInt1(I.isInBounds())); 249 for (auto &Op : I.operands()) 250 Args.push_back(Op); 251 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args}); 252 I.replaceAllUsesWith(NewI); 253 I.eraseFromParent(); 254 return NewI; 255 } 256 257 Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) { 258 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()}; 259 SmallVector<Value *> Args(I.op_begin(), I.op_end()); 260 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_bitcast, {Types}, {Args}); 261 std::string InstName = I.hasName() ? I.getName().str() : ""; 262 I.replaceAllUsesWith(NewI); 263 I.eraseFromParent(); 264 NewI->setName(InstName); 265 return NewI; 266 } 267 268 Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) { 269 SmallVector<Type *, 4> Types = {I.getType(), I.getOperand(0)->getType(), 270 I.getOperand(1)->getType(), 271 I.getOperand(2)->getType()}; 272 SmallVector<Value *> Args(I.op_begin(), I.op_end()); 273 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_insertelt, {Types}, {Args}); 274 std::string InstName = I.hasName() ? I.getName().str() : ""; 275 I.replaceAllUsesWith(NewI); 276 I.eraseFromParent(); 277 NewI->setName(InstName); 278 return NewI; 279 } 280 281 Instruction * 282 SPIRVEmitIntrinsics::visitExtractElementInst(ExtractElementInst &I) { 283 SmallVector<Type *, 3> Types = {I.getType(), I.getVectorOperandType(), 284 I.getIndexOperand()->getType()}; 285 SmallVector<Value *, 2> Args = {I.getVectorOperand(), I.getIndexOperand()}; 286 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_extractelt, {Types}, {Args}); 287 std::string InstName = I.hasName() ? I.getName().str() : ""; 288 I.replaceAllUsesWith(NewI); 289 I.eraseFromParent(); 290 NewI->setName(InstName); 291 return NewI; 292 } 293 294 Instruction *SPIRVEmitIntrinsics::visitInsertValueInst(InsertValueInst &I) { 295 SmallVector<Type *, 1> Types = {I.getInsertedValueOperand()->getType()}; 296 SmallVector<Value *> Args; 297 for (auto &Op : I.operands()) 298 if (isa<UndefValue>(Op)) 299 Args.push_back(UndefValue::get(IRB->getInt32Ty())); 300 else 301 Args.push_back(Op); 302 for (auto &Op : I.indices()) 303 Args.push_back(IRB->getInt32(Op)); 304 Instruction *NewI = 305 IRB->CreateIntrinsic(Intrinsic::spv_insertv, {Types}, {Args}); 306 replaceMemInstrUses(&I, NewI); 307 return NewI; 308 } 309 310 Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) { 311 SmallVector<Value *> Args; 312 for (auto &Op : I.operands()) 313 Args.push_back(Op); 314 for (auto &Op : I.indices()) 315 Args.push_back(IRB->getInt32(Op)); 316 auto *NewI = 317 IRB->CreateIntrinsic(Intrinsic::spv_extractv, {I.getType()}, {Args}); 318 I.replaceAllUsesWith(NewI); 319 I.eraseFromParent(); 320 return NewI; 321 } 322 323 Instruction *SPIRVEmitIntrinsics::visitLoadInst(LoadInst &I) { 324 if (!I.getType()->isAggregateType()) 325 return &I; 326 TrackConstants = false; 327 const auto *TLI = TM->getSubtargetImpl()->getTargetLowering(); 328 MachineMemOperand::Flags Flags = 329 TLI->getLoadMemOperandFlags(I, F->getParent()->getDataLayout()); 330 auto *NewI = 331 IRB->CreateIntrinsic(Intrinsic::spv_load, {I.getOperand(0)->getType()}, 332 {I.getPointerOperand(), IRB->getInt16(Flags), 333 IRB->getInt8(I.getAlign().value())}); 334 replaceMemInstrUses(&I, NewI); 335 return NewI; 336 } 337 338 Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) { 339 if (!AggrStores.contains(&I)) 340 return &I; 341 TrackConstants = false; 342 const auto *TLI = TM->getSubtargetImpl()->getTargetLowering(); 343 MachineMemOperand::Flags Flags = 344 TLI->getStoreMemOperandFlags(I, F->getParent()->getDataLayout()); 345 auto *PtrOp = I.getPointerOperand(); 346 auto *NewI = IRB->CreateIntrinsic( 347 Intrinsic::spv_store, {I.getValueOperand()->getType(), PtrOp->getType()}, 348 {I.getValueOperand(), PtrOp, IRB->getInt16(Flags), 349 IRB->getInt8(I.getAlign().value())}); 350 I.eraseFromParent(); 351 return NewI; 352 } 353 354 Instruction *SPIRVEmitIntrinsics::visitAllocaInst(AllocaInst &I) { 355 TrackConstants = false; 356 Type *PtrTy = I.getType(); 357 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_alloca, {PtrTy}, {}); 358 std::string InstName = I.hasName() ? I.getName().str() : ""; 359 I.replaceAllUsesWith(NewI); 360 I.eraseFromParent(); 361 NewI->setName(InstName); 362 return NewI; 363 } 364 365 Instruction *SPIRVEmitIntrinsics::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { 366 assert(I.getType()->isAggregateType() && "Aggregate result is expected"); 367 SmallVector<Value *> Args; 368 for (auto &Op : I.operands()) 369 Args.push_back(Op); 370 Args.push_back(IRB->getInt32(I.getSyncScopeID())); 371 Args.push_back(IRB->getInt32( 372 static_cast<uint32_t>(getMemSemantics(I.getSuccessOrdering())))); 373 Args.push_back(IRB->getInt32( 374 static_cast<uint32_t>(getMemSemantics(I.getFailureOrdering())))); 375 auto *NewI = IRB->CreateIntrinsic(Intrinsic::spv_cmpxchg, 376 {I.getPointerOperand()->getType()}, {Args}); 377 replaceMemInstrUses(&I, NewI); 378 return NewI; 379 } 380 381 Instruction *SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) { 382 IRB->SetInsertPoint(&I); 383 IRB->CreateIntrinsic(Intrinsic::spv_unreachable, {}, {}); 384 return &I; 385 } 386 387 void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV) { 388 // Skip special artifical variable llvm.global.annotations. 389 if (GV.getName() == "llvm.global.annotations") 390 return; 391 if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) { 392 Constant *Init = GV.getInitializer(); 393 Type *Ty = isAggrToReplace(Init) ? IRB->getInt32Ty() : Init->getType(); 394 Constant *Const = isAggrToReplace(Init) ? IRB->getInt32(1) : Init; 395 auto *InitInst = IRB->CreateIntrinsic(Intrinsic::spv_init_global, 396 {GV.getType(), Ty}, {&GV, Const}); 397 InitInst->setArgOperand(1, Init); 398 } 399 if ((!GV.hasInitializer() || isa<UndefValue>(GV.getInitializer())) && 400 GV.getNumUses() == 0) 401 IRB->CreateIntrinsic(Intrinsic::spv_unref_global, GV.getType(), &GV); 402 } 403 404 void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I) { 405 if (I->getType()->isVoidTy() || !requireAssignPtrType(I)) 406 return; 407 408 setInsertPointSkippingPhis(*IRB, I->getNextNode()); 409 410 Constant *EltTyConst; 411 unsigned AddressSpace = 0; 412 if (auto *AI = dyn_cast<AllocaInst>(I)) { 413 EltTyConst = Constant::getNullValue(AI->getAllocatedType()); 414 AddressSpace = AI->getAddressSpace(); 415 } else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) { 416 EltTyConst = Constant::getNullValue(GEP->getResultElementType()); 417 AddressSpace = GEP->getPointerAddressSpace(); 418 } else { 419 llvm_unreachable("Unexpected instruction!"); 420 } 421 422 buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {I->getType()}, EltTyConst, I, 423 {IRB->getInt32(AddressSpace)}); 424 } 425 426 void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I) { 427 Type *Ty = I->getType(); 428 if (!Ty->isVoidTy() && requireAssignType(I) && !requireAssignPtrType(I)) { 429 setInsertPointSkippingPhis(*IRB, I->getNextNode()); 430 Type *TypeToAssign = Ty; 431 if (auto *II = dyn_cast<IntrinsicInst>(I)) { 432 if (II->getIntrinsicID() == Intrinsic::spv_const_composite || 433 II->getIntrinsicID() == Intrinsic::spv_undef) { 434 auto t = AggrConsts.find(II); 435 assert(t != AggrConsts.end()); 436 TypeToAssign = t->second->getType(); 437 } 438 } 439 Constant *Const = Constant::getNullValue(TypeToAssign); 440 buildIntrWithMD(Intrinsic::spv_assign_type, {Ty}, Const, I, {}); 441 } 442 for (const auto &Op : I->operands()) { 443 if (isa<ConstantPointerNull>(Op) || isa<UndefValue>(Op) || 444 // Check GetElementPtrConstantExpr case. 445 (isa<ConstantExpr>(Op) && isa<GEPOperator>(Op))) { 446 setInsertPointSkippingPhis(*IRB, I); 447 if (isa<UndefValue>(Op) && Op->getType()->isAggregateType()) 448 buildIntrWithMD(Intrinsic::spv_assign_type, {IRB->getInt32Ty()}, Op, 449 UndefValue::get(IRB->getInt32Ty()), {}); 450 else 451 buildIntrWithMD(Intrinsic::spv_assign_type, {Op->getType()}, Op, Op, 452 {}); 453 } 454 } 455 } 456 457 void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I) { 458 auto *II = dyn_cast<IntrinsicInst>(I); 459 if (II && II->getIntrinsicID() == Intrinsic::spv_const_composite && 460 TrackConstants) { 461 IRB->SetInsertPoint(I->getNextNode()); 462 Type *Ty = IRB->getInt32Ty(); 463 auto t = AggrConsts.find(I); 464 assert(t != AggrConsts.end()); 465 auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant, {Ty, Ty}, 466 t->second, I, {}); 467 I->replaceAllUsesWith(NewOp); 468 NewOp->setArgOperand(0, I); 469 } 470 for (const auto &Op : I->operands()) { 471 if ((isa<ConstantAggregateZero>(Op) && Op->getType()->isVectorTy()) || 472 isa<PHINode>(I) || isa<SwitchInst>(I)) 473 TrackConstants = false; 474 if ((isa<ConstantData>(Op) || isa<ConstantExpr>(Op)) && TrackConstants) { 475 unsigned OpNo = Op.getOperandNo(); 476 if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) || 477 (II->paramHasAttr(OpNo, Attribute::ImmArg)))) 478 continue; 479 IRB->SetInsertPoint(I); 480 auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant, 481 {Op->getType(), Op->getType()}, Op, Op, {}); 482 I->setOperand(OpNo, NewOp); 483 } 484 } 485 if (I->hasName()) { 486 setInsertPointSkippingPhis(*IRB, I->getNextNode()); 487 std::vector<Value *> Args = {I}; 488 addStringImm(I->getName(), *IRB, Args); 489 IRB->CreateIntrinsic(Intrinsic::spv_assign_name, {I->getType()}, Args); 490 } 491 } 492 493 bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) { 494 if (Func.isDeclaration()) 495 return false; 496 F = &Func; 497 IRB = new IRBuilder<>(Func.getContext()); 498 AggrConsts.clear(); 499 AggrStores.clear(); 500 501 // StoreInst's operand type can be changed during the next transformations, 502 // so we need to store it in the set. Also store already transformed types. 503 for (auto &I : instructions(Func)) { 504 StoreInst *SI = dyn_cast<StoreInst>(&I); 505 if (!SI) 506 continue; 507 Type *ElTy = SI->getValueOperand()->getType(); 508 if (ElTy->isAggregateType() || ElTy->isVectorTy()) 509 AggrStores.insert(&I); 510 } 511 512 IRB->SetInsertPoint(&Func.getEntryBlock(), Func.getEntryBlock().begin()); 513 for (auto &GV : Func.getParent()->globals()) 514 processGlobalValue(GV); 515 516 preprocessUndefs(); 517 preprocessCompositeConstants(); 518 SmallVector<Instruction *> Worklist; 519 for (auto &I : instructions(Func)) 520 Worklist.push_back(&I); 521 522 for (auto &I : Worklist) { 523 insertAssignPtrTypeIntrs(I); 524 insertAssignTypeIntrs(I); 525 } 526 527 for (auto *I : Worklist) { 528 TrackConstants = true; 529 if (!I->getType()->isVoidTy() || isa<StoreInst>(I)) 530 IRB->SetInsertPoint(I->getNextNode()); 531 I = visit(*I); 532 processInstrAfterVisit(I); 533 } 534 return true; 535 } 536 537 FunctionPass *llvm::createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM) { 538 return new SPIRVEmitIntrinsics(TM); 539 } 540