LLVM 24.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
21#include "SPIRV.h"
22#include "SPIRVBuiltins.h"
23#include "SPIRVSubtarget.h"
24#include "SPIRVTargetMachine.h"
25#include "SPIRVUtils.h"
31#include "llvm/IR/IRBuilder.h"
35#include "llvm/IR/Intrinsics.h"
36#include "llvm/IR/IntrinsicsSPIRV.h"
42#include <regex>
43
44using namespace llvm;
45
46namespace {
47
48class SPIRVPrepareFunctionsImpl {
49 const SPIRVTargetMachine &TM;
50 function_ref<const TargetTransformInfo &(Function &)> GetTTI;
51 bool substituteIntrinsicCalls(Function *F);
52 bool substituteAbortKHRCalls(Function *F);
53 bool terminateBlocksAfterTrap(Module &M, Intrinsic::ID IID);
54 Function *removeAggregateTypesFromSignature(Function *F);
55 bool removeAggregateTypesFromCalls(Function *F);
56
57public:
58 SPIRVPrepareFunctionsImpl(
59 const SPIRVTargetMachine &TM,
60 function_ref<const TargetTransformInfo &(Function &)> GetTTI)
61 : TM(TM), GetTTI(GetTTI) {}
62 bool runOnModule(Module &M);
63};
64
65class SPIRVPrepareFunctionsLegacy : public ModulePass {
66 const SPIRVTargetMachine &TM;
67
68public:
69 static char ID;
70 SPIRVPrepareFunctionsLegacy(const SPIRVTargetMachine &TM)
71 : ModulePass(ID), TM(TM) {}
72
73 bool runOnModule(Module &M) override {
74 auto GetTTI = [this](Function &F) -> const TargetTransformInfo & {
75 return getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
76 };
77 return SPIRVPrepareFunctionsImpl(TM, GetTTI).runOnModule(M);
78 }
79
80 void getAnalysisUsage(AnalysisUsage &AU) const override {
81 AU.addRequired<TargetTransformInfoWrapperPass>();
82 }
83
84 StringRef getPassName() const override { return "SPIRV prepare functions"; }
85};
86
87static cl::list<std::string> SPVAllowUnknownIntrinsics(
88 "spv-allow-unknown-intrinsics", cl::CommaSeparated,
89 cl::desc("Emit unknown intrinsics as calls to external functions. A "
90 "comma-separated input list of intrinsic prefixes must be "
91 "provided, and only intrinsics carrying a listed prefix get "
92 "emitted as described."),
93 cl::value_desc("intrinsic_prefix_0,intrinsic_prefix_1"), cl::ValueOptional);
94} // namespace
95
96char SPIRVPrepareFunctionsLegacy::ID = 0;
97
98INITIALIZE_PASS_BEGIN(SPIRVPrepareFunctionsLegacy, "spirv-prepare-functions",
99 "SPIRV prepare functions", false, false)
101INITIALIZE_PASS_END(SPIRVPrepareFunctionsLegacy, "spirv-prepare-functions",
102 "SPIRV prepare functions", false, false)
103
105 Function *IntrinsicFunc = II->getCalledFunction();
106 assert(IntrinsicFunc && "Missing function");
107 std::string FuncName = IntrinsicFunc->getName().str();
108 llvm::replace(FuncName, '.', '_');
109 FuncName = "spirv." + FuncName;
110 return FuncName;
111}
112
114 ArrayRef<Type *> ArgTypes,
115 StringRef Name) {
116 FunctionType *FT = FunctionType::get(RetTy, ArgTypes, false);
117 Function *F = M->getFunction(Name);
118 if (F && F->getFunctionType() == FT)
119 return F;
121 if (F)
122 NewF->setDSOLocal(F->isDSOLocal());
124 return NewF;
125}
126
128 const TargetTransformInfo &TTI) {
129 // For @llvm.memset.* intrinsic cases with constant value and length arguments
130 // are emulated via "storing" a constant array to the destination. For other
131 // cases we wrap the intrinsic in @spirv.llvm_memset_* function and expand the
132 // intrinsic to a loop via expandMemSetAsLoop().
133 if (auto *MSI = dyn_cast<MemSetInst>(Intrinsic))
134 if (isa<Constant>(MSI->getValue()) && isa<ConstantInt>(MSI->getLength()))
135 return false; // It is handled later using OpCopyMemorySized.
136
137 // An intrinsic with a metadata argument has no SPIR-V lowering and can't be
138 // turned into a function.
140 const Function *F = Intrinsic->getFunction();
141 F->getContext().diagnose(DiagnosticInfoUnsupported(
142 *F,
143 "cannot lower the intrinsic '" +
144 Intrinsic->getCalledFunction()->getName() +
145 "' that takes a metadata argument",
146 Intrinsic->getDebugLoc()));
147 if (!Intrinsic->getType()->isVoidTy())
148 Intrinsic->replaceAllUsesWith(PoisonValue::get(Intrinsic->getType()));
149 Intrinsic->eraseFromParent();
150 return true;
151 }
152
153 Module *M = Intrinsic->getModule();
154 std::string FuncName = lowerLLVMIntrinsicName(Intrinsic);
155 if (Intrinsic->isVolatile())
156 FuncName += ".volatile";
157 // Redirect @llvm.intrinsic.* call to @spirv.llvm_intrinsic_*
158 Function *F = M->getFunction(FuncName);
159 if (F) {
160 Intrinsic->setCalledFunction(F);
161 return true;
162 }
163 FunctionCallee FC =
164 M->getOrInsertFunction(FuncName, Intrinsic->getFunctionType());
165 auto IntrinsicID = Intrinsic->getIntrinsicID();
166 Intrinsic->setCalledFunction(FC);
167 F = cast<Function>(FC.getCallee());
168 F->setAttributes(Intrinsic->getAttributes());
169
170 switch (IntrinsicID) {
171 case Intrinsic::memset: {
172 auto *MSI = static_cast<MemSetInst *>(Intrinsic);
173 Argument *Dest = F->getArg(0);
174 Argument *Val = F->getArg(1);
175 Argument *Len = F->getArg(2);
176 Argument *IsVolatile = F->getArg(3);
177 Dest->setName("dest");
178 Val->setName("val");
179 Len->setName("len");
180 IsVolatile->setName("isvolatile");
181 BasicBlock *EntryBB = BasicBlock::Create(M->getContext(), "entry", F);
182 IRBuilder<> IRB(EntryBB);
183 auto *MemSet = IRB.CreateMemSet(Dest, Val, Len, MSI->getDestAlign(),
184 MSI->isVolatile());
185 IRB.CreateRetVoid();
187 MemSet->eraseFromParent();
188 break;
189 }
190 case Intrinsic::bswap: {
191 BasicBlock *EntryBB = BasicBlock::Create(M->getContext(), "entry", F);
192 IRBuilder<> IRB(EntryBB);
194 Intrinsic::bswap, Intrinsic->getType(), F->getArg(0));
195 IRB.CreateRet(BSwap);
196 IntrinsicLowering IL(M->getDataLayout());
197 IL.LowerIntrinsicCall(BSwap);
198 break;
199 }
200 default:
201 break;
202 }
203 return true;
204}
205
206static std::string getAnnotation(Value *AnnoVal, Value *OptAnnoVal) {
207 if (auto *Ref = dyn_cast_or_null<GetElementPtrInst>(AnnoVal))
208 AnnoVal = Ref->getOperand(0);
209 if (auto *Ref = dyn_cast_or_null<BitCastInst>(OptAnnoVal))
210 OptAnnoVal = Ref->getOperand(0);
211
212 std::string Anno;
213 if (auto *C = dyn_cast_or_null<Constant>(AnnoVal)) {
214 StringRef Str;
215 if (getConstantStringInfo(C, Str))
216 Anno = Str;
217 }
218 // handle optional annotation parameter in a way that Khronos Translator do
219 // (collect integers wrapped in a struct)
220 if (auto *C = dyn_cast_or_null<Constant>(OptAnnoVal);
221 C && C->getNumOperands()) {
222 Value *MaybeStruct = C->getOperand(0);
223 if (auto *Struct = dyn_cast<ConstantStruct>(MaybeStruct)) {
224 for (unsigned I = 0, E = Struct->getNumOperands(); I != E; ++I) {
225 if (auto *CInt = dyn_cast<ConstantInt>(Struct->getOperand(I)))
226 Anno += (I == 0 ? ": " : ", ") +
227 std::to_string(CInt->getType()->getIntegerBitWidth() == 1
228 ? CInt->getZExtValue()
229 : CInt->getSExtValue());
230 }
231 } else if (auto *Struct = dyn_cast<ConstantAggregateZero>(MaybeStruct)) {
232 // { i32 i32 ... } zeroinitializer
233 for (unsigned I = 0, E = Struct->getType()->getStructNumElements();
234 I != E; ++I)
235 Anno += I == 0 ? ": 0" : ", 0";
236 }
237 }
238 return Anno;
239}
240
242 const std::string &Anno,
243 LLVMContext &Ctx,
244 Type *Int32Ty) {
245 // Try to parse the annotation string according to the following rules:
246 // annotation := ({kind} | {kind:value,value,...})+
247 // kind := number
248 // value := number | string
249 static const std::regex R(
250 "\\{(\\d+)(?:[:,](\\d+|\"[^\"]*\")(?:,(\\d+|\"[^\"]*\"))*)?\\}");
252 int Pos = 0;
253 for (std::sregex_iterator
254 It = std::sregex_iterator(Anno.begin(), Anno.end(), R),
255 ItEnd = std::sregex_iterator();
256 It != ItEnd; ++It) {
257 if (It->position() != Pos)
259 Pos = It->position() + It->length();
260 std::smatch Match = *It;
262 for (std::size_t i = 1; i < Match.size(); ++i) {
263 std::ssub_match SMatch = Match[i];
264 std::string Item = SMatch.str();
265 if (Item.length() == 0)
266 break;
267 if (Item[0] == '"') {
268 Item = Item.substr(1, Item.length() - 2);
269 // Acceptable format of the string snippet is:
270 static const std::regex RStr("^(\\d+)(?:,(\\d+))*$");
271 if (std::smatch MatchStr; std::regex_match(Item, MatchStr, RStr)) {
272 for (std::size_t SubIdx = 1; SubIdx < MatchStr.size(); ++SubIdx)
273 if (std::string SubStr = MatchStr[SubIdx].str(); SubStr.length())
275 ConstantInt::get(Int32Ty, std::stoi(SubStr))));
276 } else {
277 MDsItem.push_back(MDString::get(Ctx, Item));
278 }
279 } else if (int32_t Num; llvm::to_integer(StringRef(Item), Num, 10)) {
280 MDsItem.push_back(
281 ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Num)));
282 } else {
283 MDsItem.push_back(MDString::get(Ctx, Item));
284 }
285 }
286 if (MDsItem.size() == 0)
288 MDs.push_back(MDNode::get(Ctx, MDsItem));
289 }
290 return Pos == static_cast<int>(Anno.length()) ? std::move(MDs)
292}
293
295 LLVMContext &Ctx = II->getContext();
296 Type *Int32Ty = Type::getInt32Ty(Ctx);
297
298 // Retrieve an annotation string from arguments.
299 Value *PtrArg = nullptr;
300 if (auto *BI = dyn_cast<BitCastInst>(II->getArgOperand(0)))
301 PtrArg = BI->getOperand(0);
302 else
303 PtrArg = II->getOperand(0);
304 std::string Anno =
305 getAnnotation(II->getArgOperand(1),
306 4 < II->arg_size() ? II->getArgOperand(4) : nullptr);
307
308 // Parse the annotation.
309 SmallVector<Metadata *> MDs = parseAnnotation(II, Anno, Ctx, Int32Ty);
310
311 // If the annotation string is not parsed successfully we don't know the
312 // format used and output it as a general UserSemantic decoration.
313 // Otherwise MDs is a Metadata tuple (a decoration list) in the format
314 // expected by `spirv.Decorations`.
315 if (MDs.size() == 0) {
316 auto UserSemantic = ConstantAsMetadata::get(ConstantInt::get(
317 Int32Ty, static_cast<uint32_t>(SPIRV::Decoration::UserSemantic)));
318 MDs.push_back(MDNode::get(Ctx, {UserSemantic, MDString::get(Ctx, Anno)}));
319 }
320
321 // Build the internal intrinsic function.
322 IRBuilder<> IRB(II->getParent());
323 IRB.SetInsertPoint(II);
324 IRB.CreateIntrinsic(
325 Intrinsic::spv_assign_decoration, {PtrArg->getType()},
326 {PtrArg, MetadataAsValue::get(Ctx, MDNode::get(Ctx, MDs))});
327 II->replaceAllUsesWith(II->getOperand(0));
328}
329
330static void lowerFunnelShifts(IntrinsicInst *FSHIntrinsic) {
331 // Get a separate function - otherwise, we'd have to rework the CFG of the
332 // current one. Then simply replace the intrinsic uses with a call to the new
333 // function.
334 // Generate LLVM IR for i* @spirv.llvm_fsh?_i* (i* %a, i* %b, i* %c)
335 Module *M = FSHIntrinsic->getModule();
336 FunctionType *FSHFuncTy = FSHIntrinsic->getFunctionType();
337 Type *FSHRetTy = FSHFuncTy->getReturnType();
338 const std::string FuncName = lowerLLVMIntrinsicName(FSHIntrinsic);
339 Function *FSHFunc =
340 getOrCreateFunction(M, FSHRetTy, FSHFuncTy->params(), FuncName);
341
342 if (!FSHFunc->empty()) {
343 FSHIntrinsic->setCalledFunction(FSHFunc);
344 return;
345 }
346 BasicBlock *RotateBB = BasicBlock::Create(M->getContext(), "rotate", FSHFunc);
347 IRBuilder<> IRB(RotateBB);
348 Type *Ty = FSHFunc->getReturnType();
349 // Build the actual funnel shift rotate logic.
350 // In the comments, "int" is used interchangeably with "vector of int
351 // elements".
353 Type *IntTy = VectorTy ? VectorTy->getElementType() : Ty;
354 unsigned BitWidth = IntTy->getIntegerBitWidth();
355 ConstantInt *BitWidthConstant = IRB.getInt({BitWidth, BitWidth});
356 Value *BitWidthForInsts =
357 VectorTy
358 ? IRB.CreateVectorSplat(VectorTy->getNumElements(), BitWidthConstant)
359 : BitWidthConstant;
360 Value *RotateModVal =
361 IRB.CreateURem(/*Rotate*/ FSHFunc->getArg(2), BitWidthForInsts);
362 Value *FirstShift = nullptr, *SecShift = nullptr;
363 if (FSHIntrinsic->getIntrinsicID() == Intrinsic::fshr) {
364 // Shift the less significant number right, the "rotate" number of bits
365 // will be 0-filled on the left as a result of this regular shift.
366 FirstShift = IRB.CreateLShr(FSHFunc->getArg(1), RotateModVal);
367 } else {
368 // Shift the more significant number left, the "rotate" number of bits
369 // will be 0-filled on the right as a result of this regular shift.
370 FirstShift = IRB.CreateShl(FSHFunc->getArg(0), RotateModVal);
371 }
372 // We want the "rotate" number of the more significant int's LSBs (MSBs) to
373 // occupy the leftmost (rightmost) "0 space" left by the previous operation.
374 // Therefore, subtract the "rotate" number from the integer bitsize...
375 Value *SubRotateVal = IRB.CreateSub(BitWidthForInsts, RotateModVal);
376 if (FSHIntrinsic->getIntrinsicID() == Intrinsic::fshr) {
377 // ...and left-shift the more significant int by this number, zero-filling
378 // the LSBs.
379 SecShift = IRB.CreateShl(FSHFunc->getArg(0), SubRotateVal);
380 } else {
381 // ...and right-shift the less significant int by this number, zero-filling
382 // the MSBs.
383 SecShift = IRB.CreateLShr(FSHFunc->getArg(1), SubRotateVal);
384 }
385 // A simple binary addition of the shifted ints yields the final result.
386 IRB.CreateRet(IRB.CreateOr(FirstShift, SecShift));
387
388 FSHIntrinsic->setCalledFunction(FSHFunc);
389}
390
392 ConstrainedFPCmpIntrinsic *ConstrainedCmpIntrinsic,
393 SmallVector<Instruction *> &EraseFromParent) {
394 if (!ConstrainedCmpIntrinsic)
395 return;
396 // Extract the floating-point values being compared
397 Value *LHS = ConstrainedCmpIntrinsic->getArgOperand(0);
398 Value *RHS = ConstrainedCmpIntrinsic->getArgOperand(1);
399 FCmpInst::Predicate Pred = ConstrainedCmpIntrinsic->getPredicate();
400 IRBuilder<> Builder(ConstrainedCmpIntrinsic);
401 Value *FCmp = Builder.CreateFCmp(Pred, LHS, RHS);
402 ConstrainedCmpIntrinsic->replaceAllUsesWith(FCmp);
403 EraseFromParent.push_back(dyn_cast<Instruction>(ConstrainedCmpIntrinsic));
404}
405
407 // If we cannot use the SPV_KHR_expect_assume extension, then we need to
408 // ignore the intrinsic and move on. It should be removed later on by LLVM.
409 // Otherwise we should lower the intrinsic to the corresponding SPIR-V
410 // instruction.
411 // For @llvm.assume we have OpAssumeTrueKHR.
412 // For @llvm.expect and @llvm.expect.with.probability we have OpExpectKHR.
413 //
414 // We need to lower this into a builtin and then the builtin into a SPIR-V
415 // instruction.
416 if (II->getIntrinsicID() == Intrinsic::assume) {
418 II->getModule(), Intrinsic::SPVIntrinsics::spv_assume);
419 II->setCalledFunction(F);
420 } else if (II->getIntrinsicID() == Intrinsic::expect) {
422 II->getModule(), Intrinsic::SPVIntrinsics::spv_expect,
423 {II->getOperand(0)->getType()});
424 II->setCalledFunction(F);
425 } else if (II->getIntrinsicID() == Intrinsic::expect_with_probability) {
426 // OpExpectKHR has no probability operand. Keep the hint only if the
427 // expected value is likely, as LowerExpectIntrinsic does for PHIs.
428 Value *Res = II->getArgOperand(0);
429 double Prob =
430 cast<ConstantFP>(II->getArgOperand(2))->getValueAPF().convertToDouble();
431 if (Prob > 0.5)
432 Res = IRBuilder<>(II).CreateIntrinsic(
433 Intrinsic::SPVIntrinsics::spv_expect, {II->getType()},
434 {II->getArgOperand(0), II->getArgOperand(1)});
435 BasicBlock::iterator BI = II->getIterator();
436 ReplaceInstWithValue(BI, Res);
437 } else {
438 llvm_unreachable("Unknown intrinsic");
439 }
440}
441
443 auto *LifetimeArg0 = II->getArgOperand(0);
444
445 // If the lifetime argument is a poison value, the intrinsic has no effect.
446 if (isa<PoisonValue>(LifetimeArg0)) {
447 II->eraseFromParent();
448 return true;
449 }
450
451 IRBuilder<> Builder(II);
452 auto *Alloca = cast<AllocaInst>(LifetimeArg0);
453 std::optional<TypeSize> Size =
454 Alloca->getAllocationSize(Alloca->getDataLayout());
455 Value *SizeVal = Builder.getInt64(Size ? *Size : -1);
456 Builder.CreateIntrinsic(NewID, Alloca->getType(), {SizeVal, LifetimeArg0});
457 II->eraseFromParent();
458 return true;
459}
460
461static void
463 SmallVector<Instruction *> &EraseFromParent) {
464 auto *FPI = cast<ConstrainedFPIntrinsic>(II);
465 Value *A = FPI->getArgOperand(0);
466 Value *Mul = FPI->getArgOperand(1);
467 Value *Add = FPI->getArgOperand(2);
468 IRBuilder<> Builder(II->getParent());
469 Builder.SetInsertPoint(II);
470 std::optional<RoundingMode> Rounding = FPI->getRoundingMode();
471 Value *Product = Builder.CreateFMul(A, Mul, II->getName() + ".mul");
472 Value *Result = Builder.CreateConstrainedFPBinOp(
473 Intrinsic::experimental_constrained_fadd, Product, Add, {},
474 II->getName() + ".add", nullptr, Rounding);
475 II->replaceAllUsesWith(Result);
476 EraseFromParent.push_back(II);
477}
478
479// llvm.minimum/llvm.maximum return NaN if either operand is NaN and order -0.0
480// before +0.0, whereas OpenCL.std fmin/fmax and GLSL.std.450 NMin/NMax return
481// the other operand for a NaN and may return either zero. Expand them like
482// SPIRV-LLVM-Translator does, so that both produce the same OpenCL SPIR-V. For
483// llvm.minimum (llvm.maximum is symmetrical):
484// %m = call @llvm.minnum(%x, %y)
485// ; unless nsz: for non-NaN operands, the result has the sign of %x if that
486// ; is set (maximum: clear), and the sign of %y otherwise. This only changes
487// ; %m if it is a zero of the wrong sign.
488// %xsign = call @llvm.copysign(1.0, %x)
489// %xneg = fcmp olt %xsign, 0.0
490// %s = select %xneg, %x, %y
491// %m.s = call @llvm.copysign(%m, %s)
492// ; unless nnan
493// %uno = fcmp uno %x, %y
494// %res = select %uno, NaN, %m.s
495static Value *expandFMinimumMaximum(IRBuilderBase &Builder, bool IsMax,
496 Value *X, Value *Y, FastMathFlags FMF) {
497 Type *Ty = X->getType();
498 Value *Res = Builder.CreateIntrinsic(
499 IsMax ? Intrinsic::maxnum : Intrinsic::minnum, {Ty}, {X, Y}, FMF);
500 if (!FMF.noSignedZeros()) {
501 Value *XSign = Builder.CreateCopySign(ConstantFP::get(Ty, 1.0), X);
502 Value *XNeg = Builder.CreateFCmpOLT(XSign, ConstantFP::getZero(Ty));
503 Value *Sign = IsMax ? Builder.CreateSelect(XNeg, Y, X)
504 : Builder.CreateSelect(XNeg, X, Y);
505 Res = Builder.CreateCopySign(Res, Sign);
506 }
507 if (!FMF.noNaNs()) {
508 Value *Uno = Builder.CreateFCmpUNO(X, Y);
509 Res = Builder.CreateSelect(Uno, ConstantFP::getQNaN(Ty), Res);
510 }
511 return Res;
512}
513
515 SmallVector<Instruction *> &EraseFromParent) {
516 IRBuilder<> Builder(II);
518 Builder, II->getIntrinsicID() == Intrinsic::maximum, II->getArgOperand(0),
519 II->getArgOperand(1), II->getFastMathFlags());
520 Res->takeName(II);
521 II->replaceAllUsesWith(Res);
522 EraseFromParent.push_back(II);
523}
524
525// ExpandReductions only expands llvm.vector.reduce.fminimum/fmaximum on vectors
526// with a power-of-two number of elements. Expand the others into a chain of
527// llvm.minimum/llvm.maximum, expanded as above.
528static void
530 SmallVector<Instruction *> &EraseFromParent) {
531 bool IsMax = II->getIntrinsicID() == Intrinsic::vector_reduce_fmaximum;
532 Value *Vec = II->getArgOperand(0);
533 unsigned NumElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
534 IRBuilder<> Builder(II);
536 for (unsigned I = 0; I < NumElts; ++I)
537 Elts.push_back(Builder.CreateExtractElement(Vec, I));
538 Value *Res = Elts[0];
539 for (Value *Elt : drop_begin(Elts))
540 Res =
541 expandFMinimumMaximum(Builder, IsMax, Res, Elt, II->getFastMathFlags());
542 Res->takeName(II);
543 II->replaceAllUsesWith(Res);
544 EraseFromParent.push_back(II);
545}
546
547// Substitutes calls to LLVM intrinsics with either calls to SPIR-V intrinsics
548// or calls to proper generated functions. Returns True if F was modified.
549bool SPIRVPrepareFunctionsImpl::substituteIntrinsicCalls(Function *F) {
550 if (F->isDeclaration())
551 return false;
552
553 bool Changed = false;
554 const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
555 SmallVector<Instruction *> EraseFromParent;
556 const TargetTransformInfo &TTI = GetTTI(*F);
557 for (BasicBlock &BB : *F) {
558 for (Instruction &I : make_early_inc_range(BB)) {
559 auto Call = dyn_cast<CallInst>(&I);
560 if (!Call)
561 continue;
563 if (!CF || !CF->isIntrinsic())
564 continue;
565 auto *II = cast<IntrinsicInst>(Call);
566 if (Intrinsic::isTargetIntrinsic(II->getIntrinsicID()) &&
567 II->getCalledOperand()->getName().starts_with("llvm.spv"))
568 continue;
569 switch (II->getIntrinsicID()) {
570 case Intrinsic::memset:
571 case Intrinsic::bswap:
573 break;
574 case Intrinsic::fshl:
575 case Intrinsic::fshr:
577 Changed = true;
578 break;
579 case Intrinsic::minimum:
580 case Intrinsic::maximum:
581 lowerFMinimumMaximum(II, EraseFromParent);
582 Changed = true;
583 break;
584 case Intrinsic::vector_reduce_fminimum:
585 case Intrinsic::vector_reduce_fmaximum:
586 lowerVectorReduceFMinimumMaximum(II, EraseFromParent);
587 Changed = true;
588 break;
589 case Intrinsic::assume:
590 case Intrinsic::expect:
591 case Intrinsic::expect_with_probability:
592 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
594 Changed = true;
595 break;
596 case Intrinsic::lifetime_start:
597 if (!STI.isShader()) {
599 II, Intrinsic::SPVIntrinsics::spv_lifetime_start);
600 } else {
601 II->eraseFromParent();
602 Changed = true;
603 }
604 break;
605 case Intrinsic::lifetime_end:
606 if (!STI.isShader()) {
608 II, Intrinsic::SPVIntrinsics::spv_lifetime_end);
609 } else {
610 II->eraseFromParent();
611 Changed = true;
612 }
613 break;
614 case Intrinsic::ptr_annotation:
616 Changed = true;
617 break;
618 case Intrinsic::experimental_constrained_fmuladd:
619 lowerConstrainedFmuladd(II, EraseFromParent);
620 Changed = true;
621 break;
622 case Intrinsic::experimental_constrained_fcmp:
623 case Intrinsic::experimental_constrained_fcmps:
625 EraseFromParent);
626 Changed = true;
627 break;
628 default:
629 // Drop assume-like intrinsics that have no SPIR-V representation.
630 if (II->isAssumeLikeIntrinsic()) {
631 if (!II->getType()->isVoidTy())
632 II->replaceAllUsesWith(PoisonValue::get(II->getType()));
633 II->eraseFromParent();
634 Changed = true;
635 break;
636 }
637 if (STI.getTargetTriple().getVendor() == Triple::AMD ||
638 any_of(SPVAllowUnknownIntrinsics, [II](auto &&Prefix) {
639 if (Prefix.empty())
640 return false;
641 return II->getCalledFunction()->getName().starts_with(Prefix);
642 }))
644 break;
645 }
646 }
647 }
648 for (auto *I : EraseFromParent)
649 I->eraseFromParent();
650 return Changed;
651}
652
653static void
655 SmallVector<std::pair<int, Type *>> ChangedTys,
656 StringRef Name, StringRef AsmConstraints = "") {
657
658 LLVMContext &Ctx = NMD->getParent()->getContext();
659 Type *I32Ty = IntegerType::getInt32Ty(Ctx);
660
662 MDArgs.push_back(MDString::get(Ctx, Name));
663 transform(ChangedTys, std::back_inserter(MDArgs), [=, &Ctx](auto &&CTy) {
664 return MDNode::get(
665 Ctx, {ConstantAsMetadata::get(ConstantInt::get(I32Ty, CTy.first, true)),
667 });
668 if (!AsmConstraints.empty())
669 MDArgs.push_back(MDNode::get(Ctx, MDString::get(Ctx, AsmConstraints)));
670 NMD->addOperand(MDNode::get(Ctx, MDArgs));
671}
672
673// Returns F if aggregate argument/return types are not present or cloned F
674// function with the types replaced by i32 types. The change in types is
675// noted in 'spv.cloned_funcs' metadata for later restoration.
676Function *
677SPIRVPrepareFunctionsImpl::removeAggregateTypesFromSignature(Function *F) {
678 bool IsRetAggr = F->getReturnType()->isAggregateType();
679 // Allow intrinsics with aggregate return/argument types to reach GlobalISel.
680 // Renaming/mutating the signature of an intrinsic would desync its name from
681 // its argument types and break the IR verifier.
682 if (F->isIntrinsic())
683 return F;
684
685 IRBuilder<> B(*F->getParent());
686
687 bool HasAggrArg = llvm::any_of(F->args(), [](Argument &Arg) {
688 return Arg.getType()->isAggregateType();
689 });
690 bool DoClone = IsRetAggr || HasAggrArg;
691 if (!DoClone)
692 return F;
693 SmallVector<std::pair<int, Type *>, 4> ChangedTypes;
694 Type *RetType = IsRetAggr ? B.getInt32Ty() : F->getReturnType();
695 if (IsRetAggr)
696 ChangedTypes.push_back(std::pair<int, Type *>(-1, F->getReturnType()));
697 SmallVector<Type *, 4> ArgTypes;
698 for (const auto &Arg : F->args()) {
699 if (Arg.getType()->isAggregateType()) {
700 ArgTypes.push_back(B.getInt32Ty());
701 ChangedTypes.push_back(
702 std::pair<int, Type *>(Arg.getArgNo(), Arg.getType()));
703 } else
704 ArgTypes.push_back(Arg.getType());
705 }
706 FunctionType *NewFTy =
707 FunctionType::get(RetType, ArgTypes, F->getFunctionType()->isVarArg());
708 Function *NewF =
709 Function::Create(NewFTy, F->getLinkage(), F->getAddressSpace(),
710 F->getName(), F->getParent());
711
713 auto NewFArgIt = NewF->arg_begin();
714 for (auto &Arg : F->args()) {
715 StringRef ArgName = Arg.getName();
716 NewFArgIt->setName(ArgName);
717 VMap[&Arg] = &(*NewFArgIt++);
718 }
720
721 CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
722 Returns);
723 NewF->takeName(F);
724 NewF->setComdat(F->getComdat());
725
727 NewF->getParent()->getOrInsertNamedMetadata("spv.cloned_funcs"),
728 std::move(ChangedTypes), NewF->getName());
729
730 for (User *U : F->users()) {
731 if (auto *CB = dyn_cast<CallBase>(U); CB && CB->getCalledFunction() == F)
732 CB->mutateFunctionType(NewF->getFunctionType());
733 }
734 // NewF keeps F's address space, so their pointer types match and
735 // RAUW is safe despite the differing signatures.
736 assert(F->getType() == NewF->getType() &&
737 "RAUW requires F and NewF to share the same pointer type");
738 F->replaceAllUsesWith(NewF);
739
740 // register the mutation
741 if (RetType != F->getReturnType())
742 TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
743 NewF, F->getReturnType());
744 return NewF;
745}
746
747// Returns true iff `F`'s name resolves (after OpenCL/SPIR-V demangling and
748// builtin-name lookup) to the SPIR-V friendly built-in `__spirv_AbortKHR`.
749static bool isAbortKHRBuiltin(const Function &F) {
750 if (F.isIntrinsic())
751 return false;
752 StringRef Name = F.getName();
753 // Quick reject: the mangled or unmangled name must contain the substring.
754 if (!Name.contains("__spirv_AbortKHR"))
755 return false;
756 std::string Demangled = getOclOrSpirvBuiltinDemangledName(Name);
757 if (Demangled.empty())
758 return false;
759 return SPIRV::lookupBuiltinNameHelper(Demangled) == "__spirv_AbortKHR";
760}
761
762// Rewrites a single call to `__spirv_AbortKHR` into a call to the
763// `llvm.spv.abort` target intrinsic, then re-terminates the block with
764// `unreachable`. OpAbortKHR is itself a SPIR-V function-termination
765// instruction and must be the last instruction in its block, so any trailing
766// stores/lifetime intrinsics/`ret` emitted by the OpenCL ABI are dropped.
767// `changeToUnreachable` cleans up any successor PHI predecessor entries.
769 IRBuilder<> B(CI);
770 Value *Msg = CI->getArgOperand(0);
771 // The OpenCL C ABI may pass aggregate arguments by pointer (byval). In that
772 // case load the underlying value so that OpAbortKHR receives the composite
773 // itself, as required by the SPV_KHR_abort spec ("Message Type must be a
774 // concrete type").
775 if (CI->isByValArgument(0)) {
776 Type *AggTy = CI->getParamByValType(0);
777 Msg = B.CreateLoad(AggTy, Msg);
778 }
779 B.CreateIntrinsic(Intrinsic::spv_abort, {Msg->getType()}, {Msg});
781}
782
783// Replace OpenCL/SPIR-V style calls to `__spirv_AbortKHR(message)` (i.e.
784// calls to `F` when `F` is the `__spirv_AbortKHR` built-in) with calls to the
785// `llvm.spv.abort` target intrinsic.
786bool SPIRVPrepareFunctionsImpl::substituteAbortKHRCalls(Function *F) {
787 if (!isAbortKHRBuiltin(*F))
788 return false;
789
790 bool Changed = false;
791 for (User *U : make_early_inc_range(F->users())) {
792 auto *CI = dyn_cast<CallInst>(U);
793 if (!CI || CI->getCalledFunction() != F)
794 continue;
795 if (CI->arg_size() != 1)
796 continue;
798 Changed = true;
799 }
800
801 return Changed;
802}
803
804// When the SPV_KHR_abort extension is enabled, `llvm.trap` and
805// `llvm.ubsantrap` are lowered to `OpAbortKHR` during instruction selection.
806// `OpAbortKHR` is itself a SPIR-V block terminator, so any instructions that
807// follow the trap call within the same basic block (e.g. `ret`, lifetime
808// markers) would produce SPIR-V ops after `OpAbortKHR` and break validation.
809// Terminate the block right after each call to the trap intrinsics by replacing
810// the next instruction with `unreachable`.
811bool SPIRVPrepareFunctionsImpl::terminateBlocksAfterTrap(Module &M,
812 Intrinsic::ID IID) {
813 assert((IID == Intrinsic::trap || IID == Intrinsic::ubsantrap) &&
814 "Expected trap intrinsic ID");
815
817 if (!F)
818 return false;
819
820 // If the target doesn't support SPV_KHR_abort, we won't be able to lower
821 // the trap intrinsic to OpAbortKHR, so we can skip the block-terminating
822 // transformation.
823 const auto &ST = TM.getSubtarget<SPIRVSubtarget>(*F);
824 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
825 return false;
826
827 bool Changed = false;
828 for (User *U : make_early_inc_range(F->users())) {
829 auto *CI = dyn_cast<CallInst>(U);
830 if (!CI || CI->getCalledFunction() != F)
831 continue;
832 Instruction *Next = CI->getNextNode();
834 continue;
836 Changed = true;
837 }
838 return Changed;
839}
840
841static std::string fixMultiOutputConstraintString(StringRef Constraints) {
842 // We should only have one =r return for the made up ASM type.
844 SplitString(Constraints, Tmp, ",");
845 std::string SafeConstraints("=r,");
846 for (unsigned I = 0u; I != Tmp.size() - 1; ++I) {
847 if (Tmp[I].starts_with('=') && (Tmp[I][1] == '&' || isalnum(Tmp[I][1])))
848 continue;
849 SafeConstraints.append(Tmp[I]).append({','});
850 }
851 SafeConstraints.append(Tmp.back());
852
853 return SafeConstraints;
854}
855
856// Mutates indirect and inline ASM callsites iff aggregate argument/return types
857// are present with the types replaced by i32 types. The change in types is
858// noted in 'spv.mutated_callsites' metadata for later restoration. For ASM we
859// also have to mutate the constraint string as IRTranslator tries to handle
860// multiple outputs and expects an aggregate return type in their presence.
861bool SPIRVPrepareFunctionsImpl::removeAggregateTypesFromCalls(Function *F) {
862 if (F->isDeclaration() || F->isIntrinsic())
863 return false;
864
866 for (auto &&I : instructions(F)) {
867 if (auto *CB = dyn_cast<CallBase>(&I)) {
868 if (!CB->getCalledOperand() || CB->getCalledFunction())
869 continue;
870 if (CB->getType()->isAggregateType() ||
871 any_of(CB->args(),
872 [](auto &&Arg) { return Arg->getType()->isAggregateType(); }))
873 Calls.emplace_back(CB, nullptr);
874 }
875 }
876
877 if (Calls.empty())
878 return false;
879
880 IRBuilder<> B(*F->getParent());
881
882 unsigned MutatedCallIdx = 0;
883 for (auto &&[CB, NewFnTy] : Calls) {
885 SmallVector<Type *> NewArgTypes;
886
887 Type *RetTy = CB->getType();
888 if (RetTy->isAggregateType()) {
889 ChangedTypes.emplace_back(-1, RetTy);
890 RetTy = B.getInt32Ty();
891 }
892
893 for (auto &&Arg : CB->args()) {
894 if (Arg->getType()->isAggregateType()) {
895 NewArgTypes.push_back(B.getInt32Ty());
896 ChangedTypes.emplace_back(Arg.getOperandNo(), Arg->getType());
897 } else {
898 NewArgTypes.push_back(Arg->getType());
899 }
900 }
901 NewFnTy = FunctionType::get(RetTy, NewArgTypes,
902 CB->getFunctionType()->isVarArg());
903
904 // Keyed via instruction metadata, not a name.
905 std::string Key =
906 ("spv.mutated_callsite." + F->getName() + "." + Twine(MutatedCallIdx++))
907 .str();
908 CB->setMetadata(
909 "spv.mutated_callsite",
910 MDNode::get(F->getContext(), MDString::get(F->getContext(), Key)));
911
912 std::string Constraints;
913 if (auto *ASM = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
914 Constraints = ASM->getConstraintString();
915
916 CB->setCalledOperand(InlineAsm::get(
917 NewFnTy, ASM->getAsmString(),
918 fixMultiOutputConstraintString(Constraints), ASM->hasSideEffects(),
919 ASM->isAlignStack(), ASM->getDialect(), ASM->canThrow()));
920 }
921
923 F->getParent()->getOrInsertNamedMetadata("spv.mutated_callsites"),
924 std::move(ChangedTypes), Key, Constraints);
925 }
926
927 for (auto &&[CB, NewFTy] : Calls) {
928 if (NewFTy->getReturnType() != CB->getType())
929 TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
930 CB, CB->getType());
931 CB->mutateFunctionType(NewFTy);
932 }
933
934 return true;
935}
936
937bool SPIRVPrepareFunctionsImpl::runOnModule(Module &M) {
938 // Resolve the SPIR-V environment from module content before any
939 // function-level processing. This must happen before legalization so that
940 // isShader()/isKernel() return correct values.
941 const_cast<SPIRVTargetMachine &>(TM)
942 .getMutableSubtargetImpl()
943 ->resolveEnvFromModule(M);
944
945 bool Changed = false;
946 if (M.getFunctionDefs().empty()) {
947 // If there are no function definitions, insert a service
948 // function so that the global/constant tracking intrinsics
949 // will be created. Without these intrinsics the generated SPIR-V
950 // will be empty. The service function itself is not emitted.
952 BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry", SF);
953 IRBuilder<> IRB(BB);
954 IRB.CreateRetVoid();
955 Changed = true;
956 }
957
958 Changed |= terminateBlocksAfterTrap(M, Intrinsic::trap);
959 Changed |= terminateBlocksAfterTrap(M, Intrinsic::ubsantrap);
960
961 for (GlobalVariable &GV : M.globals()) {
962 // Strip + tag available_externally globals so AuxData can re-emit the
963 // original linkage as NonSemantic.AuxData::Linkage.
964 if (GV.hasAvailableExternallyLinkage() && !GV.isDeclaration()) {
966 GV.setLinkage(GlobalValue::ExternalLinkage);
967 Changed = true;
968 }
969 }
970
971 std::vector<Function *> FuncsWorklist;
972 for (Function &F : M) {
973 // MachineFunctionPass skips available_externally; strip + tag so AuxData
974 // can re-emit the original linkage as NonSemantic.AuxData::Linkage.
975 if (F.hasAvailableExternallyLinkage() && !F.isDeclaration()) {
978 Changed = true;
979 }
980 Changed |= substituteAbortKHRCalls(&F);
981 Changed |= substituteIntrinsicCalls(&F);
982 Changed |= sortBlocks(F);
983 Changed |= removeAggregateTypesFromCalls(&F);
984 FuncsWorklist.push_back(&F);
985 }
986
987 for (auto *F : FuncsWorklist) {
988 Function *NewF = removeAggregateTypesFromSignature(F);
989
990 if (NewF != F) {
991 F->eraseFromParent();
992 Changed = true;
993 }
994 }
995 return Changed;
996}
997
1002 auto GetTTI = [&FAM](Function &F) -> const TargetTransformInfo & {
1003 return FAM.getResult<TargetIRAnalysis>(F);
1004 };
1005 return SPIRVPrepareFunctionsImpl(TM, GetTTI).runOnModule(M)
1008}
1009
1010ModulePass *
1012 return new SPIRVPrepareFunctionsLegacy(TM);
1013}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
const char * Msg
static Value * expandFMinimumMaximum(IRBuilderBase &Builder, bool IsMax, Value *X, Value *Y, FastMathFlags FMF)
static void lowerFunnelShifts(IntrinsicInst *FSHIntrinsic)
static std::string getAnnotation(Value *AnnoVal, Value *OptAnnoVal)
spirv prepare SPIRV prepare static false std::string lowerLLVMIntrinsicName(IntrinsicInst *II)
static void lowerVectorReduceFMinimumMaximum(IntrinsicInst *II, SmallVector< Instruction * > &EraseFromParent)
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 void lowerFMinimumMaximum(IntrinsicInst *II, SmallVector< Instruction * > &EraseFromParent)
static Function * getOrCreateFunction(Module *M, Type *RetTy, ArrayRef< Type * > ArgTypes, StringRef Name)
#define SPIRV_WAS_AVAILABLE_EXTERNALLY_ATTR
Definition SPIRVUtils.h:561
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
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This pass exposes codegen information to IR-level passes.
Value * RHS
Value * LHS
BinaryOperator * Mul
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
AnalysisUsage & addRequired()
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
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
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:548
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
static LLVM_ABI ConstantFP * getQNaN(Type *Ty, bool Negative=false, APInt *Payload=nullptr)
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.
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
bool noSignedZeros() const
Definition FMF.h:67
bool noNaNs() const
Definition FMF.h:65
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:169
bool empty() const
Definition Function.h:844
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
arg_iterator arg_begin()
Definition Function.h:853
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition Function.h:252
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:217
void setCallingConv(CallingConv::ID CC)
Definition Function.h:277
Argument * getArg(unsigned i) const
Definition Function.h:871
LLVM_ABI void setComdat(Comdat *C)
Definition Globals.cpp:287
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
PointerType * getType() const
Global values are always pointers.
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
Common base class shared among various IRBuilders.
Definition IRBuilder.h:111
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:1528
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition IRBuilder.h:1188
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1435
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1507
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:596
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
Definition IRBuilder.h:1183
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:196
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1588
ConstantInt * getInt(const APInt &AI)
Get a constant integer value.
Definition IRBuilder.h:480
Value * CreateURem(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1495
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2909
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:76
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:597
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:107
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:253
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:332
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:1797
Module * getParent()
Get the module that holds this named metadata collection.
Definition Metadata.h:1867
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
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
Analysis pass providing the TargetTransformInfo.
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
Wrapper pass for TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
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:299
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:314
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:514
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:390
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:549
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:396
Type * getElementType() const
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SPIR_FUNC
Used for SPIR non-kernel device functions.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
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.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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:649
bool sortBlocks(Function &F)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI void ReplaceInstWithValue(BasicBlock::iterator &BI, Value *V)
Replace all uses of an instruction (specified by BI) with a value, then remove and delete the origina...
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:2042
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:1762
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
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:2545
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
TargetTransformInfo TTI
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:1926
@ Add
Sum of integers.
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
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:878