LLVM 23.0.0git
SPIRVPrepareFunctions.cpp
Go to the documentation of this file.
1//===-- SPIRVPrepareFunctions.cpp - modify function signatures --*- 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// This pass modifies function signatures containing aggregate arguments
10// and/or return value before IRTranslator. Information about the original
11// signatures is stored in metadata. It is used during call lowering to
12// restore correct SPIR-V types of function arguments and return values.
13// This pass also substitutes some llvm intrinsic calls with calls to newly
14// generated functions (as the Khronos LLVM/SPIR-V Translator does).
15//
16// NOTE: this pass is a module-level one due to the necessity to modify
17// GVs/functions.
18//
19//===----------------------------------------------------------------------===//
20
22#include "SPIRV.h"
23#include "SPIRVBuiltins.h"
24#include "SPIRVSubtarget.h"
25#include "SPIRVTargetMachine.h"
26#include "SPIRVUtils.h"
32#include "llvm/IR/IRBuilder.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/IntrinsicsSPIRV.h"
41#include <regex>
42
43using namespace llvm;
44
45namespace {
46
47class SPIRVPrepareFunctionsImpl {
48 const SPIRVTargetMachine &TM;
49 bool substituteIntrinsicCalls(Function *F);
50 bool substituteAbortKHRCalls(Function *F);
51 bool terminateBlocksAfterTrap(Module &M, Intrinsic::ID IID);
52 Function *removeAggregateTypesFromSignature(Function *F);
53 bool removeAggregateTypesFromCalls(Function *F);
54
55public:
56 SPIRVPrepareFunctionsImpl(const SPIRVTargetMachine &TM) : TM(TM) {}
57 bool runOnModule(Module &M);
58};
59
60class SPIRVPrepareFunctionsLegacy : public ModulePass {
61 const SPIRVTargetMachine &TM;
62
63public:
64 static char ID;
65 SPIRVPrepareFunctionsLegacy(const SPIRVTargetMachine &TM)
66 : ModulePass(ID), TM(TM) {}
67
68 bool runOnModule(Module &M) override {
69 return SPIRVPrepareFunctionsImpl(TM).runOnModule(M);
70 }
71
72 StringRef getPassName() const override { return "SPIRV prepare functions"; }
73};
74
75static cl::list<std::string> SPVAllowUnknownIntrinsics(
76 "spv-allow-unknown-intrinsics", cl::CommaSeparated,
77 cl::desc("Emit unknown intrinsics as calls to external functions. A "
78 "comma-separated input list of intrinsic prefixes must be "
79 "provided, and only intrinsics carrying a listed prefix get "
80 "emitted as described."),
81 cl::value_desc("intrinsic_prefix_0,intrinsic_prefix_1"), cl::ValueOptional);
82} // namespace
83
84char SPIRVPrepareFunctionsLegacy::ID = 0;
85
86INITIALIZE_PASS(SPIRVPrepareFunctionsLegacy, "spirv-prepare-functions",
87 "SPIRV prepare functions", false, false)
88
89static std::string lowerLLVMIntrinsicName(IntrinsicInst *II) {
90 Function *IntrinsicFunc = II->getCalledFunction();
91 assert(IntrinsicFunc && "Missing function");
92 std::string FuncName = IntrinsicFunc->getName().str();
93 llvm::replace(FuncName, '.', '_');
94 FuncName = "spirv." + FuncName;
95 return FuncName;
96}
97
99 ArrayRef<Type *> ArgTypes,
100 StringRef Name) {
101 FunctionType *FT = FunctionType::get(RetTy, ArgTypes, false);
102 Function *F = M->getFunction(Name);
103 if (F && F->getFunctionType() == FT)
104 return F;
106 if (F)
107 NewF->setDSOLocal(F->isDSOLocal());
109 return NewF;
110}
111
113 const TargetTransformInfo &TTI) {
114 // For @llvm.memset.* intrinsic cases with constant value and length arguments
115 // are emulated via "storing" a constant array to the destination. For other
116 // cases we wrap the intrinsic in @spirv.llvm_memset_* function and expand the
117 // intrinsic to a loop via expandMemSetAsLoop().
118 if (auto *MSI = dyn_cast<MemSetInst>(Intrinsic))
119 if (isa<Constant>(MSI->getValue()) && isa<ConstantInt>(MSI->getLength()))
120 return false; // It is handled later using OpCopyMemorySized.
121
122 // An intrinsic with a metadata argument has no SPIR-V lowering and can't be
123 // turned into a function.
125 const Function *F = Intrinsic->getFunction();
126 F->getContext().diagnose(DiagnosticInfoUnsupported(
127 *F,
128 "cannot lower the intrinsic '" +
129 Intrinsic->getCalledFunction()->getName() +
130 "' that takes a metadata argument",
131 Intrinsic->getDebugLoc()));
132 if (!Intrinsic->getType()->isVoidTy())
133 Intrinsic->replaceAllUsesWith(PoisonValue::get(Intrinsic->getType()));
134 Intrinsic->eraseFromParent();
135 return true;
136 }
137
138 Module *M = Intrinsic->getModule();
139 std::string FuncName = lowerLLVMIntrinsicName(Intrinsic);
140 if (Intrinsic->isVolatile())
141 FuncName += ".volatile";
142 // Redirect @llvm.intrinsic.* call to @spirv.llvm_intrinsic_*
143 Function *F = M->getFunction(FuncName);
144 if (F) {
145 Intrinsic->setCalledFunction(F);
146 return true;
147 }
148 // TODO copy arguments attributes: nocapture writeonly.
149 FunctionCallee FC =
150 M->getOrInsertFunction(FuncName, Intrinsic->getFunctionType());
151 auto IntrinsicID = Intrinsic->getIntrinsicID();
152 Intrinsic->setCalledFunction(FC);
153
154 F = dyn_cast<Function>(FC.getCallee());
155 assert(F && "Callee must be a function");
156
157 switch (IntrinsicID) {
158 case Intrinsic::memset: {
159 auto *MSI = static_cast<MemSetInst *>(Intrinsic);
160 Argument *Dest = F->getArg(0);
161 Argument *Val = F->getArg(1);
162 Argument *Len = F->getArg(2);
163 Argument *IsVolatile = F->getArg(3);
164 Dest->setName("dest");
165 Val->setName("val");
166 Len->setName("len");
167 IsVolatile->setName("isvolatile");
168 BasicBlock *EntryBB = BasicBlock::Create(M->getContext(), "entry", F);
169 IRBuilder<> IRB(EntryBB);
170 auto *MemSet = IRB.CreateMemSet(Dest, Val, Len, MSI->getDestAlign(),
171 MSI->isVolatile());
172 IRB.CreateRetVoid();
174 MemSet->eraseFromParent();
175 break;
176 }
177 case Intrinsic::bswap: {
178 BasicBlock *EntryBB = BasicBlock::Create(M->getContext(), "entry", F);
179 IRBuilder<> IRB(EntryBB);
181 Intrinsic::bswap, Intrinsic->getType(), F->getArg(0));
182 IRB.CreateRet(BSwap);
183 IntrinsicLowering IL(M->getDataLayout());
184 IL.LowerIntrinsicCall(BSwap);
185 break;
186 }
187 default:
188 break;
189 }
190 return true;
191}
192
193static std::string getAnnotation(Value *AnnoVal, Value *OptAnnoVal) {
194 if (auto *Ref = dyn_cast_or_null<GetElementPtrInst>(AnnoVal))
195 AnnoVal = Ref->getOperand(0);
196 if (auto *Ref = dyn_cast_or_null<BitCastInst>(OptAnnoVal))
197 OptAnnoVal = Ref->getOperand(0);
198
199 std::string Anno;
200 if (auto *C = dyn_cast_or_null<Constant>(AnnoVal)) {
201 StringRef Str;
202 if (getConstantStringInfo(C, Str))
203 Anno = Str;
204 }
205 // handle optional annotation parameter in a way that Khronos Translator do
206 // (collect integers wrapped in a struct)
207 if (auto *C = dyn_cast_or_null<Constant>(OptAnnoVal);
208 C && C->getNumOperands()) {
209 Value *MaybeStruct = C->getOperand(0);
210 if (auto *Struct = dyn_cast<ConstantStruct>(MaybeStruct)) {
211 for (unsigned I = 0, E = Struct->getNumOperands(); I != E; ++I) {
212 if (auto *CInt = dyn_cast<ConstantInt>(Struct->getOperand(I)))
213 Anno += (I == 0 ? ": " : ", ") +
214 std::to_string(CInt->getType()->getIntegerBitWidth() == 1
215 ? CInt->getZExtValue()
216 : CInt->getSExtValue());
217 }
218 } else if (auto *Struct = dyn_cast<ConstantAggregateZero>(MaybeStruct)) {
219 // { i32 i32 ... } zeroinitializer
220 for (unsigned I = 0, E = Struct->getType()->getStructNumElements();
221 I != E; ++I)
222 Anno += I == 0 ? ": 0" : ", 0";
223 }
224 }
225 return Anno;
226}
227
229 const std::string &Anno,
230 LLVMContext &Ctx,
231 Type *Int32Ty) {
232 // Try to parse the annotation string according to the following rules:
233 // annotation := ({kind} | {kind:value,value,...})+
234 // kind := number
235 // value := number | string
236 static const std::regex R(
237 "\\{(\\d+)(?:[:,](\\d+|\"[^\"]*\")(?:,(\\d+|\"[^\"]*\"))*)?\\}");
239 int Pos = 0;
240 for (std::sregex_iterator
241 It = std::sregex_iterator(Anno.begin(), Anno.end(), R),
242 ItEnd = std::sregex_iterator();
243 It != ItEnd; ++It) {
244 if (It->position() != Pos)
246 Pos = It->position() + It->length();
247 std::smatch Match = *It;
249 for (std::size_t i = 1; i < Match.size(); ++i) {
250 std::ssub_match SMatch = Match[i];
251 std::string Item = SMatch.str();
252 if (Item.length() == 0)
253 break;
254 if (Item[0] == '"') {
255 Item = Item.substr(1, Item.length() - 2);
256 // Acceptable format of the string snippet is:
257 static const std::regex RStr("^(\\d+)(?:,(\\d+))*$");
258 if (std::smatch MatchStr; std::regex_match(Item, MatchStr, RStr)) {
259 for (std::size_t SubIdx = 1; SubIdx < MatchStr.size(); ++SubIdx)
260 if (std::string SubStr = MatchStr[SubIdx].str(); SubStr.length())
262 ConstantInt::get(Int32Ty, std::stoi(SubStr))));
263 } else {
264 MDsItem.push_back(MDString::get(Ctx, Item));
265 }
266 } else if (int32_t Num; llvm::to_integer(StringRef(Item), Num, 10)) {
267 MDsItem.push_back(
268 ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Num)));
269 } else {
270 MDsItem.push_back(MDString::get(Ctx, Item));
271 }
272 }
273 if (MDsItem.size() == 0)
275 MDs.push_back(MDNode::get(Ctx, MDsItem));
276 }
277 return Pos == static_cast<int>(Anno.length()) ? std::move(MDs)
279}
280
282 LLVMContext &Ctx = II->getContext();
284
285 // Retrieve an annotation string from arguments.
286 Value *PtrArg = nullptr;
287 if (auto *BI = dyn_cast<BitCastInst>(II->getArgOperand(0)))
288 PtrArg = BI->getOperand(0);
289 else
290 PtrArg = II->getOperand(0);
291 std::string Anno =
292 getAnnotation(II->getArgOperand(1),
293 4 < II->arg_size() ? II->getArgOperand(4) : nullptr);
294
295 // Parse the annotation.
297
298 // If the annotation string is not parsed successfully we don't know the
299 // format used and output it as a general UserSemantic decoration.
300 // Otherwise MDs is a Metadata tuple (a decoration list) in the format
301 // expected by `spirv.Decorations`.
302 if (MDs.size() == 0) {
303 auto UserSemantic = ConstantAsMetadata::get(ConstantInt::get(
304 Int32Ty, static_cast<uint32_t>(SPIRV::Decoration::UserSemantic)));
305 MDs.push_back(MDNode::get(Ctx, {UserSemantic, MDString::get(Ctx, Anno)}));
306 }
307
308 // Build the internal intrinsic function.
309 IRBuilder<> IRB(II->getParent());
310 IRB.SetInsertPoint(II);
311 IRB.CreateIntrinsic(
312 Intrinsic::spv_assign_decoration, {PtrArg->getType()},
313 {PtrArg, MetadataAsValue::get(Ctx, MDNode::get(Ctx, MDs))});
314 II->replaceAllUsesWith(II->getOperand(0));
315}
316
317static void lowerFunnelShifts(IntrinsicInst *FSHIntrinsic) {
318 // Get a separate function - otherwise, we'd have to rework the CFG of the
319 // current one. Then simply replace the intrinsic uses with a call to the new
320 // function.
321 // Generate LLVM IR for i* @spirv.llvm_fsh?_i* (i* %a, i* %b, i* %c)
322 Module *M = FSHIntrinsic->getModule();
323 FunctionType *FSHFuncTy = FSHIntrinsic->getFunctionType();
324 Type *FSHRetTy = FSHFuncTy->getReturnType();
325 const std::string FuncName = lowerLLVMIntrinsicName(FSHIntrinsic);
326 Function *FSHFunc =
327 getOrCreateFunction(M, FSHRetTy, FSHFuncTy->params(), FuncName);
328
329 if (!FSHFunc->empty()) {
330 FSHIntrinsic->setCalledFunction(FSHFunc);
331 return;
332 }
333 BasicBlock *RotateBB = BasicBlock::Create(M->getContext(), "rotate", FSHFunc);
334 IRBuilder<> IRB(RotateBB);
335 Type *Ty = FSHFunc->getReturnType();
336 // Build the actual funnel shift rotate logic.
337 // In the comments, "int" is used interchangeably with "vector of int
338 // elements".
340 Type *IntTy = VectorTy ? VectorTy->getElementType() : Ty;
341 unsigned BitWidth = IntTy->getIntegerBitWidth();
342 ConstantInt *BitWidthConstant = IRB.getInt({BitWidth, BitWidth});
343 Value *BitWidthForInsts =
344 VectorTy
345 ? IRB.CreateVectorSplat(VectorTy->getNumElements(), BitWidthConstant)
346 : BitWidthConstant;
347 Value *RotateModVal =
348 IRB.CreateURem(/*Rotate*/ FSHFunc->getArg(2), BitWidthForInsts);
349 Value *FirstShift = nullptr, *SecShift = nullptr;
350 if (FSHIntrinsic->getIntrinsicID() == Intrinsic::fshr) {
351 // Shift the less significant number right, the "rotate" number of bits
352 // will be 0-filled on the left as a result of this regular shift.
353 FirstShift = IRB.CreateLShr(FSHFunc->getArg(1), RotateModVal);
354 } else {
355 // Shift the more significant number left, the "rotate" number of bits
356 // will be 0-filled on the right as a result of this regular shift.
357 FirstShift = IRB.CreateShl(FSHFunc->getArg(0), RotateModVal);
358 }
359 // We want the "rotate" number of the more significant int's LSBs (MSBs) to
360 // occupy the leftmost (rightmost) "0 space" left by the previous operation.
361 // Therefore, subtract the "rotate" number from the integer bitsize...
362 Value *SubRotateVal = IRB.CreateSub(BitWidthForInsts, RotateModVal);
363 if (FSHIntrinsic->getIntrinsicID() == Intrinsic::fshr) {
364 // ...and left-shift the more significant int by this number, zero-filling
365 // the LSBs.
366 SecShift = IRB.CreateShl(FSHFunc->getArg(0), SubRotateVal);
367 } else {
368 // ...and right-shift the less significant int by this number, zero-filling
369 // the MSBs.
370 SecShift = IRB.CreateLShr(FSHFunc->getArg(1), SubRotateVal);
371 }
372 // A simple binary addition of the shifted ints yields the final result.
373 IRB.CreateRet(IRB.CreateOr(FirstShift, SecShift));
374
375 FSHIntrinsic->setCalledFunction(FSHFunc);
376}
377
379 ConstrainedFPCmpIntrinsic *ConstrainedCmpIntrinsic,
380 SmallVector<Instruction *> &EraseFromParent) {
381 if (!ConstrainedCmpIntrinsic)
382 return;
383 // Extract the floating-point values being compared
384 Value *LHS = ConstrainedCmpIntrinsic->getArgOperand(0);
385 Value *RHS = ConstrainedCmpIntrinsic->getArgOperand(1);
386 FCmpInst::Predicate Pred = ConstrainedCmpIntrinsic->getPredicate();
387 IRBuilder<> Builder(ConstrainedCmpIntrinsic);
388 Value *FCmp = Builder.CreateFCmp(Pred, LHS, RHS);
389 ConstrainedCmpIntrinsic->replaceAllUsesWith(FCmp);
390 EraseFromParent.push_back(dyn_cast<Instruction>(ConstrainedCmpIntrinsic));
391}
392
394 // If we cannot use the SPV_KHR_expect_assume extension, then we need to
395 // ignore the intrinsic and move on. It should be removed later on by LLVM.
396 // Otherwise we should lower the intrinsic to the corresponding SPIR-V
397 // instruction.
398 // For @llvm.assume we have OpAssumeTrueKHR.
399 // For @llvm.expect we have OpExpectKHR.
400 //
401 // We need to lower this into a builtin and then the builtin into a SPIR-V
402 // instruction.
403 if (II->getIntrinsicID() == Intrinsic::assume) {
405 II->getModule(), Intrinsic::SPVIntrinsics::spv_assume);
406 II->setCalledFunction(F);
407 } else if (II->getIntrinsicID() == Intrinsic::expect) {
409 II->getModule(), Intrinsic::SPVIntrinsics::spv_expect,
410 {II->getOperand(0)->getType()});
411 II->setCalledFunction(F);
412 } else {
413 llvm_unreachable("Unknown intrinsic");
414 }
415}
416
418 auto *LifetimeArg0 = II->getArgOperand(0);
419
420 // If the lifetime argument is a poison value, the intrinsic has no effect.
421 if (isa<PoisonValue>(LifetimeArg0)) {
422 II->eraseFromParent();
423 return true;
424 }
425
426 IRBuilder<> Builder(II);
427 auto *Alloca = cast<AllocaInst>(LifetimeArg0);
428 std::optional<TypeSize> Size =
429 Alloca->getAllocationSize(Alloca->getDataLayout());
430 Value *SizeVal = Builder.getInt64(Size ? *Size : -1);
431 Builder.CreateIntrinsic(NewID, Alloca->getType(), {SizeVal, LifetimeArg0});
432 II->eraseFromParent();
433 return true;
434}
435
436static void
438 SmallVector<Instruction *> &EraseFromParent) {
439 auto *FPI = cast<ConstrainedFPIntrinsic>(II);
440 Value *A = FPI->getArgOperand(0);
441 Value *Mul = FPI->getArgOperand(1);
442 Value *Add = FPI->getArgOperand(2);
443 IRBuilder<> Builder(II->getParent());
444 Builder.SetInsertPoint(II);
445 std::optional<RoundingMode> Rounding = FPI->getRoundingMode();
446 Value *Product = Builder.CreateFMul(A, Mul, II->getName() + ".mul");
447 Value *Result = Builder.CreateConstrainedFPBinOp(
448 Intrinsic::experimental_constrained_fadd, Product, Add, {},
449 II->getName() + ".add", nullptr, Rounding);
450 II->replaceAllUsesWith(Result);
451 EraseFromParent.push_back(II);
452}
453
454// Substitutes calls to LLVM intrinsics with either calls to SPIR-V intrinsics
455// or calls to proper generated functions. Returns True if F was modified.
456bool SPIRVPrepareFunctionsImpl::substituteIntrinsicCalls(Function *F) {
457 bool Changed = false;
458 const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
459 SmallVector<Instruction *> EraseFromParent;
460 const TargetTransformInfo &TTI = TM.getTargetTransformInfo(*F);
461 for (BasicBlock &BB : *F) {
462 for (Instruction &I : make_early_inc_range(BB)) {
463 auto Call = dyn_cast<CallInst>(&I);
464 if (!Call)
465 continue;
467 if (!CF || !CF->isIntrinsic())
468 continue;
469 auto *II = cast<IntrinsicInst>(Call);
470 if (Intrinsic::isTargetIntrinsic(II->getIntrinsicID()) &&
471 II->getCalledOperand()->getName().starts_with("llvm.spv"))
472 continue;
473 switch (II->getIntrinsicID()) {
474 case Intrinsic::memset:
475 case Intrinsic::bswap:
477 break;
478 case Intrinsic::fshl:
479 case Intrinsic::fshr:
481 Changed = true;
482 break;
483 case Intrinsic::assume:
484 case Intrinsic::expect:
485 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
487 Changed = true;
488 break;
489 case Intrinsic::lifetime_start:
490 if (!STI.isShader()) {
492 II, Intrinsic::SPVIntrinsics::spv_lifetime_start);
493 } else {
494 II->eraseFromParent();
495 Changed = true;
496 }
497 break;
498 case Intrinsic::lifetime_end:
499 if (!STI.isShader()) {
501 II, Intrinsic::SPVIntrinsics::spv_lifetime_end);
502 } else {
503 II->eraseFromParent();
504 Changed = true;
505 }
506 break;
507 case Intrinsic::ptr_annotation:
509 Changed = true;
510 break;
511 case Intrinsic::experimental_constrained_fmuladd:
512 lowerConstrainedFmuladd(II, EraseFromParent);
513 Changed = true;
514 break;
515 case Intrinsic::experimental_constrained_fcmp:
516 case Intrinsic::experimental_constrained_fcmps:
518 EraseFromParent);
519 Changed = true;
520 break;
521 default:
522 // Drop assume-like intrinsics that have no SPIR-V representation.
523 if (II->isAssumeLikeIntrinsic()) {
524 if (!II->getType()->isVoidTy())
525 II->replaceAllUsesWith(PoisonValue::get(II->getType()));
526 II->eraseFromParent();
527 Changed = true;
528 break;
529 }
530 if (TM.getTargetTriple().getVendor() == Triple::AMD ||
531 any_of(SPVAllowUnknownIntrinsics, [II](auto &&Prefix) {
532 if (Prefix.empty())
533 return false;
534 return II->getCalledFunction()->getName().starts_with(Prefix);
535 }))
537 break;
538 }
539 }
540 }
541 for (auto *I : EraseFromParent)
542 I->eraseFromParent();
543 return Changed;
544}
545
546static void
548 SmallVector<std::pair<int, Type *>> ChangedTys,
549 StringRef Name, StringRef AsmConstraints = "") {
550
551 LLVMContext &Ctx = NMD->getParent()->getContext();
552 Type *I32Ty = IntegerType::getInt32Ty(Ctx);
553
555 MDArgs.push_back(MDString::get(Ctx, Name));
556 transform(ChangedTys, std::back_inserter(MDArgs), [=, &Ctx](auto &&CTy) {
557 return MDNode::get(
558 Ctx, {ConstantAsMetadata::get(ConstantInt::get(I32Ty, CTy.first, true)),
560 });
561 if (!AsmConstraints.empty())
562 MDArgs.push_back(MDNode::get(Ctx, MDString::get(Ctx, AsmConstraints)));
563 NMD->addOperand(MDNode::get(Ctx, MDArgs));
564}
565
566// Returns F if aggregate argument/return types are not present or cloned F
567// function with the types replaced by i32 types. The change in types is
568// noted in 'spv.cloned_funcs' metadata for later restoration.
569Function *
570SPIRVPrepareFunctionsImpl::removeAggregateTypesFromSignature(Function *F) {
571 bool IsRetAggr = F->getReturnType()->isAggregateType();
572 // Allow intrinsics with aggregate return/argument types to reach GlobalISel.
573 // Renaming/mutating the signature of an intrinsic would desync its name from
574 // its argument types and break the IR verifier.
575 if (F->isIntrinsic())
576 return F;
577
578 IRBuilder<> B(F->getContext());
579
580 bool HasAggrArg = llvm::any_of(F->args(), [](Argument &Arg) {
581 return Arg.getType()->isAggregateType();
582 });
583 bool DoClone = IsRetAggr || HasAggrArg;
584 if (!DoClone)
585 return F;
586 SmallVector<std::pair<int, Type *>, 4> ChangedTypes;
587 Type *RetType = IsRetAggr ? B.getInt32Ty() : F->getReturnType();
588 if (IsRetAggr)
589 ChangedTypes.push_back(std::pair<int, Type *>(-1, F->getReturnType()));
590 SmallVector<Type *, 4> ArgTypes;
591 for (const auto &Arg : F->args()) {
592 if (Arg.getType()->isAggregateType()) {
593 ArgTypes.push_back(B.getInt32Ty());
594 ChangedTypes.push_back(
595 std::pair<int, Type *>(Arg.getArgNo(), Arg.getType()));
596 } else
597 ArgTypes.push_back(Arg.getType());
598 }
599 FunctionType *NewFTy =
600 FunctionType::get(RetType, ArgTypes, F->getFunctionType()->isVarArg());
601 Function *NewF =
602 Function::Create(NewFTy, F->getLinkage(), F->getAddressSpace(),
603 F->getName(), F->getParent());
604
606 auto NewFArgIt = NewF->arg_begin();
607 for (auto &Arg : F->args()) {
608 StringRef ArgName = Arg.getName();
609 NewFArgIt->setName(ArgName);
610 VMap[&Arg] = &(*NewFArgIt++);
611 }
613
614 CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
615 Returns);
616 NewF->takeName(F);
617
619 NewF->getParent()->getOrInsertNamedMetadata("spv.cloned_funcs"),
620 std::move(ChangedTypes), NewF->getName());
621
622 for (auto *U : make_early_inc_range(F->users())) {
623 if (CallInst *CI;
624 (CI = dyn_cast<CallInst>(U)) && CI->getCalledFunction() == F)
625 CI->mutateFunctionType(NewF->getFunctionType());
626 if (auto *C = dyn_cast<Constant>(U))
627 C->handleOperandChange(F, NewF);
628 else
629 U->replaceUsesOfWith(F, NewF);
630 }
631
632 // register the mutation
633 if (RetType != F->getReturnType())
634 TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
635 NewF, F->getReturnType());
636 return NewF;
637}
638
639// Returns true iff `F`'s name resolves (after OpenCL/SPIR-V demangling and
640// builtin-name lookup) to the SPIR-V friendly built-in `__spirv_AbortKHR`.
641static bool isAbortKHRBuiltin(const Function &F) {
642 if (F.isIntrinsic())
643 return false;
644 StringRef Name = F.getName();
645 // Quick reject: the mangled or unmangled name must contain the substring.
646 if (!Name.contains("__spirv_AbortKHR"))
647 return false;
648 std::string Demangled = getOclOrSpirvBuiltinDemangledName(Name);
649 if (Demangled.empty())
650 return false;
651 return SPIRV::lookupBuiltinNameHelper(Demangled) == "__spirv_AbortKHR";
652}
653
654// Rewrites a single call to `__spirv_AbortKHR` into a call to the
655// `llvm.spv.abort` target intrinsic, then re-terminates the block with
656// `unreachable`. OpAbortKHR is itself a SPIR-V function-termination
657// instruction and must be the last instruction in its block, so any trailing
658// stores/lifetime intrinsics/`ret` emitted by the OpenCL ABI are dropped.
659// `changeToUnreachable` cleans up any successor PHI predecessor entries.
661 IRBuilder<> B(CI);
662 Value *Msg = CI->getArgOperand(0);
663 // The OpenCL C ABI may pass aggregate arguments by pointer (byval). In that
664 // case load the underlying value so that OpAbortKHR receives the composite
665 // itself, as required by the SPV_KHR_abort spec ("Message Type must be a
666 // concrete type").
667 if (CI->isByValArgument(0)) {
668 Type *AggTy = CI->getParamByValType(0);
669 Msg = B.CreateLoad(AggTy, Msg);
670 }
671 B.CreateIntrinsic(Intrinsic::spv_abort, {Msg->getType()}, {Msg});
673}
674
675// Replace OpenCL/SPIR-V style calls to `__spirv_AbortKHR(message)` (i.e.
676// calls to `F` when `F` is the `__spirv_AbortKHR` built-in) with calls to the
677// `llvm.spv.abort` target intrinsic.
678bool SPIRVPrepareFunctionsImpl::substituteAbortKHRCalls(Function *F) {
679 if (!isAbortKHRBuiltin(*F))
680 return false;
681
683 for (User *U : F->users()) {
684 auto *CI = dyn_cast<CallInst>(U);
685 if (!CI || CI->getCalledFunction() != F)
686 continue;
687 if (CI->arg_size() != 1)
688 continue;
689 Calls.push_back(CI);
690 }
691
692 for (CallInst *CI : Calls)
694
695 return !Calls.empty();
696}
697
698// When the SPV_KHR_abort extension is enabled, `llvm.trap` and
699// `llvm.ubsantrap` are lowered to `OpAbortKHR` during instruction selection.
700// `OpAbortKHR` is itself a SPIR-V block terminator, so any instructions that
701// follow the trap call within the same basic block (e.g. `ret`, lifetime
702// markers) would produce SPIR-V ops after `OpAbortKHR` and break validation.
703// Terminate the block right after each call to the trap intrinsics by replacing
704// the next instruction with `unreachable`.
705bool SPIRVPrepareFunctionsImpl::terminateBlocksAfterTrap(Module &M,
706 Intrinsic::ID IID) {
707 assert((IID == Intrinsic::trap || IID == Intrinsic::ubsantrap) &&
708 "Expected trap intrinsic ID");
709
711 if (!F)
712 return false;
713
714 // If the target doesn't support SPV_KHR_abort, we won't be able to lower
715 // the trap intrinsic to OpAbortKHR, so we can skip the block-terminating
716 // transformation.
717 const auto &ST = TM.getSubtarget<SPIRVSubtarget>(*F);
718 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
719 return false;
720
722 for (User *U : F->users()) {
723 auto *CI = dyn_cast<CallInst>(U);
724 if (!CI || CI->getCalledFunction() != F)
725 continue;
726 Calls.push_back(CI);
727 }
728
729 bool Changed = false;
730 for (CallInst *CI : Calls) {
731 Instruction *Next = CI->getNextNode();
733 continue;
735 Changed = true;
736 }
737 return Changed;
738}
739
740static std::string fixMultiOutputConstraintString(StringRef Constraints) {
741 // We should only have one =r return for the made up ASM type.
743 SplitString(Constraints, Tmp, ",");
744 std::string SafeConstraints("=r,");
745 for (unsigned I = 0u; I != Tmp.size() - 1; ++I) {
746 if (Tmp[I].starts_with('=') && (Tmp[I][1] == '&' || isalnum(Tmp[I][1])))
747 continue;
748 SafeConstraints.append(Tmp[I]).append({','});
749 }
750 SafeConstraints.append(Tmp.back());
751
752 return SafeConstraints;
753}
754
755// Mutates indirect and inline ASM callsites iff aggregate argument/return types
756// are present with the types replaced by i32 types. The change in types is
757// noted in 'spv.mutated_callsites' metadata for later restoration. For ASM we
758// also have to mutate the constraint string as IRTranslator tries to handle
759// multiple outputs and expects an aggregate return type in their presence.
760bool SPIRVPrepareFunctionsImpl::removeAggregateTypesFromCalls(Function *F) {
761 if (F->isDeclaration() || F->isIntrinsic())
762 return false;
763
765 for (auto &&I : instructions(F)) {
766 if (auto *CB = dyn_cast<CallBase>(&I)) {
767 if (!CB->getCalledOperand() || CB->getCalledFunction())
768 continue;
769 if (CB->getType()->isAggregateType() ||
770 any_of(CB->args(),
771 [](auto &&Arg) { return Arg->getType()->isAggregateType(); }))
772 Calls.emplace_back(CB, nullptr);
773 }
774 }
775
776 if (Calls.empty())
777 return false;
778
779 IRBuilder<> B(F->getContext());
780
781 unsigned MutatedCallIdx = 0;
782 for (auto &&[CB, NewFnTy] : Calls) {
784 SmallVector<Type *> NewArgTypes;
785
786 Type *RetTy = CB->getType();
787 if (RetTy->isAggregateType()) {
788 ChangedTypes.emplace_back(-1, RetTy);
789 RetTy = B.getInt32Ty();
790 }
791
792 for (auto &&Arg : CB->args()) {
793 if (Arg->getType()->isAggregateType()) {
794 NewArgTypes.push_back(B.getInt32Ty());
795 ChangedTypes.emplace_back(Arg.getOperandNo(), Arg->getType());
796 } else {
797 NewArgTypes.push_back(Arg->getType());
798 }
799 }
800 NewFnTy = FunctionType::get(RetTy, NewArgTypes,
801 CB->getFunctionType()->isVarArg());
802
803 // Keyed via instruction metadata, not a name.
804 std::string Key =
805 ("spv.mutated_callsite." + F->getName() + "." + Twine(MutatedCallIdx++))
806 .str();
807 CB->setMetadata(
808 "spv.mutated_callsite",
809 MDNode::get(F->getContext(), MDString::get(F->getContext(), Key)));
810
811 std::string Constraints;
812 if (auto *ASM = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
813 Constraints = ASM->getConstraintString();
814
815 CB->setCalledOperand(InlineAsm::get(
816 NewFnTy, ASM->getAsmString(),
817 fixMultiOutputConstraintString(Constraints), ASM->hasSideEffects(),
818 ASM->isAlignStack(), ASM->getDialect(), ASM->canThrow()));
819 }
820
822 F->getParent()->getOrInsertNamedMetadata("spv.mutated_callsites"),
823 std::move(ChangedTypes), Key, Constraints);
824 }
825
826 for (auto &&[CB, NewFTy] : Calls) {
827 if (NewFTy->getReturnType() != CB->getType())
828 TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
829 CB, CB->getType());
830 CB->mutateFunctionType(NewFTy);
831 }
832
833 return true;
834}
835
836bool SPIRVPrepareFunctionsImpl::runOnModule(Module &M) {
837 // Resolve the SPIR-V environment from module content before any
838 // function-level processing. This must happen before legalization so that
839 // isShader()/isKernel() return correct values.
840 const_cast<SPIRVTargetMachine &>(TM)
841 .getMutableSubtargetImpl()
842 ->resolveEnvFromModule(M);
843
844 bool Changed = false;
845 if (M.getFunctionDefs().empty()) {
846 // If there are no function definitions, insert a service
847 // function so that the global/constant tracking intrinsics
848 // will be created. Without these intrinsics the generated SPIR-V
849 // will be empty. The service function itself is not emitted.
851 BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry", SF);
852 IRBuilder<> IRB(BB);
853 IRB.CreateRetVoid();
854 Changed = true;
855 }
856
857 Changed |= terminateBlocksAfterTrap(M, Intrinsic::trap);
858 Changed |= terminateBlocksAfterTrap(M, Intrinsic::ubsantrap);
859
860 for (GlobalVariable &GV : M.globals()) {
861 // Strip + tag available_externally globals so AuxData can re-emit the
862 // original linkage as NonSemantic.AuxData::Linkage.
863 if (GV.hasAvailableExternallyLinkage() && !GV.isDeclaration()) {
865 GV.setLinkage(GlobalValue::ExternalLinkage);
866 Changed = true;
867 }
868 }
869
870 for (Function &F : M) {
871 // MachineFunctionPass skips available_externally; strip + tag so AuxData
872 // can re-emit the original linkage as NonSemantic.AuxData::Linkage.
873 if (F.hasAvailableExternallyLinkage() && !F.isDeclaration()) {
876 Changed = true;
877 }
878 Changed |= substituteAbortKHRCalls(&F);
879 Changed |= substituteIntrinsicCalls(&F);
880 Changed |= sortBlocks(F);
881 Changed |= removeAggregateTypesFromCalls(&F);
882 }
883
884 std::vector<Function *> FuncsWorklist;
885 for (auto &F : M)
886 FuncsWorklist.push_back(&F);
887
888 for (auto *F : FuncsWorklist) {
889 Function *NewF = removeAggregateTypesFromSignature(F);
890
891 if (NewF != F) {
892 F->eraseFromParent();
893 Changed = true;
894 }
895 }
896 return Changed;
897}
898
901 return SPIRVPrepareFunctionsImpl(TM).runOnModule(M)
904}
905
908 return new SPIRVPrepareFunctionsLegacy(TM);
909}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static void lowerFunnelShifts(IntrinsicInst *FSHIntrinsic)
static std::string getAnnotation(Value *AnnoVal, Value *OptAnnoVal)
static void lowerConstrainedFPCmpIntrinsic(ConstrainedFPCmpIntrinsic *ConstrainedCmpIntrinsic, SmallVector< Instruction * > &EraseFromParent)
static void lowerConstrainedFmuladd(IntrinsicInst *II, SmallVector< Instruction * > &EraseFromParent)
static void lowerPtrAnnotation(IntrinsicInst *II)
static bool lowerIntrinsicToFunction(IntrinsicInst *Intrinsic, const TargetTransformInfo &TTI)
static bool isAbortKHRBuiltin(const Function &F)
static SmallVector< Metadata * > parseAnnotation(Value *I, const std::string &Anno, LLVMContext &Ctx, Type *Int32Ty)
static std::string fixMultiOutputConstraintString(StringRef Constraints)
static void rewriteAbortKHRCall(CallInst *CI)
static void addFunctionTypeMutation(NamedMDNode *NMD, SmallVector< std::pair< int, Type * > > ChangedTys, StringRef Name, StringRef AsmConstraints="")
static bool toSpvLifetimeIntrinsic(IntrinsicInst *II, Intrinsic::ID NewID)
static void lowerExpectAssume(IntrinsicInst *II)
static Function * getOrCreateFunction(Module *M, Type *RetTy, ArrayRef< Type * > ArgTypes, StringRef Name)
#define SPIRV_WAS_AVAILABLE_EXTERNALLY_ATTR
Definition SPIRVUtils.h:541
This file contains some functions that are useful when dealing with strings.
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
This pass exposes codegen information to IR-level passes.
Value * RHS
Value * LHS
BinaryOperator * Mul
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
LLVM Basic Block Representation.
Definition BasicBlock.h:62
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool isByValArgument(unsigned ArgNo) const
Determine whether this argument is passed by value.
Type * getParamByValType(unsigned ArgNo) const
Extract the byval type for a call or parameter.
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:537
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Constrained floating point compare intrinsics.
LLVM_ABI FCmpInst::Predicate getPredicate() const
Diagnostic information for unsupported feature in backend.
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
bool empty() const
Definition Function.h:859
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:211
arg_iterator arg_begin()
Definition Function.h:868
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition Function.h:251
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:216
void setCallingConv(CallingConv::ID CC)
Definition Function.h:276
Argument * getArg(unsigned i) const
Definition Function.h:886
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1584
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition IRBuilder.h:1244
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1491
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1563
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Definition IRBuilder.h:660
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
Definition IRBuilder.h:1239
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition IRBuilder.h:207
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1644
ConstantInt * getInt(const APInt &AI)
Get a constant integer value.
Definition IRBuilder.h:544
Value * CreateURem(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1551
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2900
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
Definition InlineAsm.cpp:43
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
LLVM_ABI void LowerIntrinsicCall(CallInst *CI)
Replace a call to the specified intrinsic function.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1561
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:614
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:110
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:287
NamedMDNode * getOrInsertNamedMetadata(StringRef Name)
Return the named MDNode in the module with the specified name.
Definition Module.cpp:308
A tuple of MDNodes.
Definition Metadata.h:1749
Module * getParent()
Get the module that holds this named metadata collection.
Definition Metadata.h:1819
LLVM_ABI void addOperand(MDNode *M)
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
bool canUseExtension(SPIRV::Extension::Extension E) const
TargetTransformInfo getTargetTransformInfo(const Function &F) const override
Get a TargetTransformInfo implementation for the target.
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
const Triple & getTargetTriple() const
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
VendorType getVendor() const
Get the parsed vendor type of this triple.
Definition Triple.h:442
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:319
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:509
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:394
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
Type * getElementType() const
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SPIR_FUNC
Used for SPIR non-kernel device functions.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI bool isTargetIntrinsic(ID IID)
isTargetIntrinsic - Returns true if IID is an intrinsic specific to a certain target.
std::string lookupBuiltinNameHelper(StringRef DemangledCall, FPDecorationId *DecorationId)
Parses the name part of the demangled builtin call.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
Definition InstrProf.h:328
LLVM_ABI bool getConstantStringInfo(const Value *V, StringRef &Str, bool TrimAtNul=true)
This function computes the length of a null-terminated C string pointed to by V.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
bool sortBlocks(Function &F)
LLVM_ABI void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")
SplitString - Split up the specified string according to the specified delimiters,...
Function * getOrCreateBackendServiceFunction(Module &M)
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
Definition STLExtras.h:2025
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1745
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
Definition Local.cpp:2539
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
TargetTransformInfo TTI
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1909
@ Add
Sum of integers.
FunctionAddr VTableAddr Next
Definition InstrProf.h:141
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
LLVM_ABI void expandMemSetAsLoop(MemSetInst *MemSet, const TargetTransformInfo *TTI=nullptr)
Expand MemSet as a loop.
LLVM_ABI void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, CloneFunctionChangeType Changes, SmallVectorImpl< ReturnInst * > &Returns, const char *NameSuffix="", ClonedCodeInfo *CodeInfo=nullptr, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Clone OldFunc into NewFunc, transforming the old arguments into references to VMap values.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool to_integer(StringRef S, N &Num, unsigned Base=0)
Convert the string S to an integer of the specified type using the radix Base. If Base is 0,...
ModulePass * createSPIRVPrepareFunctionsPass(const SPIRVTargetMachine &TM)
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:860