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 auto *Alloca = dyn_cast<AllocaInst>(LifetimeArg0);
452 if (!Alloca || !Alloca->isStaticAlloca()) {
453 II->eraseFromParent();
454 return true;
455 }
456
457 IRBuilder<> Builder(II);
458 std::optional<TypeSize> Size =
459 Alloca->getAllocationSize(Alloca->getDataLayout());
460 Value *SizeVal = Builder.getInt64(Size ? *Size : -1);
461 Builder.CreateIntrinsic(NewID, Alloca->getType(), {SizeVal, LifetimeArg0});
462 II->eraseFromParent();
463 return true;
464}
465
466static void
468 SmallVector<Instruction *> &EraseFromParent) {
469 auto *FPI = cast<ConstrainedFPIntrinsic>(II);
470 Value *A = FPI->getArgOperand(0);
471 Value *Mul = FPI->getArgOperand(1);
472 Value *Add = FPI->getArgOperand(2);
473 IRBuilder<> Builder(II->getParent());
474 Builder.SetInsertPoint(II);
475 std::optional<RoundingMode> Rounding = FPI->getRoundingMode();
476 Value *Product = Builder.CreateFMul(A, Mul, II->getName() + ".mul");
477 Value *Result = Builder.CreateConstrainedFPBinOp(
478 Intrinsic::experimental_constrained_fadd, Product, Add, {},
479 II->getName() + ".add", nullptr, Rounding);
480 II->replaceAllUsesWith(Result);
481 EraseFromParent.push_back(II);
482}
483
484// llvm.minimum/llvm.maximum return NaN if either operand is NaN and order -0.0
485// before +0.0, whereas OpenCL.std fmin/fmax and GLSL.std.450 NMin/NMax return
486// the other operand for a NaN and may return either zero. Expand them like
487// SPIRV-LLVM-Translator does, so that both produce the same OpenCL SPIR-V. For
488// llvm.minimum (llvm.maximum is symmetrical):
489// %m = call @llvm.minnum(%x, %y)
490// ; unless nsz: for non-NaN operands, the result has the sign of %x if that
491// ; is set (maximum: clear), and the sign of %y otherwise. This only changes
492// ; %m if it is a zero of the wrong sign.
493// %xsign = call @llvm.copysign(1.0, %x)
494// %xneg = fcmp olt %xsign, 0.0
495// %s = select %xneg, %x, %y
496// %m.s = call @llvm.copysign(%m, %s)
497// ; unless nnan
498// %uno = fcmp uno %x, %y
499// %res = select %uno, NaN, %m.s
500static Value *expandFMinimumMaximum(IRBuilderBase &Builder, bool IsMax,
501 Value *X, Value *Y, FastMathFlags FMF) {
502 Type *Ty = X->getType();
503 Value *Res = Builder.CreateIntrinsic(
504 IsMax ? Intrinsic::maxnum : Intrinsic::minnum, {Ty}, {X, Y}, FMF);
505 if (!FMF.noSignedZeros()) {
506 Value *XSign = Builder.CreateCopySign(ConstantFP::get(Ty, 1.0), X);
507 Value *XNeg = Builder.CreateFCmpOLT(XSign, ConstantFP::getZero(Ty));
508 Value *Sign = IsMax ? Builder.CreateSelect(XNeg, Y, X)
509 : Builder.CreateSelect(XNeg, X, Y);
510 Res = Builder.CreateCopySign(Res, Sign);
511 }
512 if (!FMF.noNaNs()) {
513 Value *Uno = Builder.CreateFCmpUNO(X, Y);
514 Res = Builder.CreateSelect(Uno, ConstantFP::getQNaN(Ty), Res);
515 }
516 return Res;
517}
518
520 SmallVector<Instruction *> &EraseFromParent) {
521 IRBuilder<> Builder(II);
523 Builder, II->getIntrinsicID() == Intrinsic::maximum, II->getArgOperand(0),
524 II->getArgOperand(1), II->getFastMathFlags());
525 Res->takeName(II);
526 II->replaceAllUsesWith(Res);
527 EraseFromParent.push_back(II);
528}
529
530// ExpandReductions only expands llvm.vector.reduce.fminimum/fmaximum on vectors
531// with a power-of-two number of elements. Expand the others into a chain of
532// llvm.minimum/llvm.maximum, expanded as above.
533static void
535 SmallVector<Instruction *> &EraseFromParent) {
536 bool IsMax = II->getIntrinsicID() == Intrinsic::vector_reduce_fmaximum;
537 Value *Vec = II->getArgOperand(0);
538 unsigned NumElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
539 IRBuilder<> Builder(II);
541 for (unsigned I = 0; I < NumElts; ++I)
542 Elts.push_back(Builder.CreateExtractElement(Vec, I));
543 Value *Res = Elts[0];
544 for (Value *Elt : drop_begin(Elts))
545 Res =
546 expandFMinimumMaximum(Builder, IsMax, Res, Elt, II->getFastMathFlags());
547 Res->takeName(II);
548 II->replaceAllUsesWith(Res);
549 EraseFromParent.push_back(II);
550}
551
552// Substitutes calls to LLVM intrinsics with either calls to SPIR-V intrinsics
553// or calls to proper generated functions. Returns True if F was modified.
554bool SPIRVPrepareFunctionsImpl::substituteIntrinsicCalls(Function *F) {
555 if (F->isDeclaration())
556 return false;
557
558 bool Changed = false;
559 const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
560 SmallVector<Instruction *> EraseFromParent;
561 const TargetTransformInfo &TTI = GetTTI(*F);
562 for (BasicBlock &BB : *F) {
563 for (Instruction &I : make_early_inc_range(BB)) {
564 auto Call = dyn_cast<CallInst>(&I);
565 if (!Call)
566 continue;
568 if (!CF || !CF->isIntrinsic())
569 continue;
570 auto *II = cast<IntrinsicInst>(Call);
571 if (Intrinsic::isTargetIntrinsic(II->getIntrinsicID()) &&
572 II->getCalledOperand()->getName().starts_with("llvm.spv"))
573 continue;
574 switch (II->getIntrinsicID()) {
575 case Intrinsic::memset:
576 case Intrinsic::bswap:
578 break;
579 case Intrinsic::fshl:
580 case Intrinsic::fshr:
582 Changed = true;
583 break;
584 case Intrinsic::minimum:
585 case Intrinsic::maximum:
586 lowerFMinimumMaximum(II, EraseFromParent);
587 Changed = true;
588 break;
589 case Intrinsic::vector_reduce_fminimum:
590 case Intrinsic::vector_reduce_fmaximum:
591 lowerVectorReduceFMinimumMaximum(II, EraseFromParent);
592 Changed = true;
593 break;
594 case Intrinsic::assume:
595 case Intrinsic::expect:
596 case Intrinsic::expect_with_probability:
597 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
599 Changed = true;
600 break;
601 case Intrinsic::lifetime_start:
602 if (!STI.isShader()) {
604 II, Intrinsic::SPVIntrinsics::spv_lifetime_start);
605 } else {
606 II->eraseFromParent();
607 Changed = true;
608 }
609 break;
610 case Intrinsic::lifetime_end:
611 if (!STI.isShader()) {
613 II, Intrinsic::SPVIntrinsics::spv_lifetime_end);
614 } else {
615 II->eraseFromParent();
616 Changed = true;
617 }
618 break;
619 case Intrinsic::ptr_annotation:
621 Changed = true;
622 break;
623 case Intrinsic::experimental_constrained_fmuladd:
624 lowerConstrainedFmuladd(II, EraseFromParent);
625 Changed = true;
626 break;
627 case Intrinsic::experimental_constrained_fcmp:
628 case Intrinsic::experimental_constrained_fcmps:
630 EraseFromParent);
631 Changed = true;
632 break;
633 default:
634 // Drop assume-like intrinsics that have no SPIR-V representation.
635 if (II->isAssumeLikeIntrinsic()) {
636 if (!II->getType()->isVoidTy())
637 II->replaceAllUsesWith(PoisonValue::get(II->getType()));
638 II->eraseFromParent();
639 Changed = true;
640 break;
641 }
642 if (STI.getTargetTriple().getVendor() == Triple::AMD ||
643 any_of(SPVAllowUnknownIntrinsics, [II](auto &&Prefix) {
644 if (Prefix.empty())
645 return false;
646 return II->getCalledFunction()->getName().starts_with(Prefix);
647 }))
649 break;
650 }
651 }
652 }
653 for (auto *I : EraseFromParent)
654 I->eraseFromParent();
655 return Changed;
656}
657
658static void
660 SmallVector<std::pair<int, Type *>> ChangedTys,
661 StringRef Name, StringRef AsmConstraints = "") {
662
663 LLVMContext &Ctx = NMD->getParent()->getContext();
664 Type *I32Ty = IntegerType::getInt32Ty(Ctx);
665
667 MDArgs.push_back(MDString::get(Ctx, Name));
668 transform(ChangedTys, std::back_inserter(MDArgs), [=, &Ctx](auto &&CTy) {
669 return MDNode::get(
670 Ctx, {ConstantAsMetadata::get(ConstantInt::get(I32Ty, CTy.first, true)),
672 });
673 if (!AsmConstraints.empty())
674 MDArgs.push_back(MDNode::get(Ctx, MDString::get(Ctx, AsmConstraints)));
675 NMD->addOperand(MDNode::get(Ctx, MDArgs));
676}
677
678// Returns F if aggregate argument/return types are not present or cloned F
679// function with the types replaced by i32 types. The change in types is
680// noted in 'spv.cloned_funcs' metadata for later restoration.
681Function *
682SPIRVPrepareFunctionsImpl::removeAggregateTypesFromSignature(Function *F) {
683 bool IsRetAggr = F->getReturnType()->isAggregateType();
684 // Allow intrinsics with aggregate return/argument types to reach GlobalISel.
685 // Renaming/mutating the signature of an intrinsic would desync its name from
686 // its argument types and break the IR verifier.
687 if (F->isIntrinsic())
688 return F;
689
690 IRBuilder<> B(*F->getParent());
691
692 bool HasAggrArg = llvm::any_of(F->args(), [](Argument &Arg) {
693 return Arg.getType()->isAggregateType();
694 });
695 bool DoClone = IsRetAggr || HasAggrArg;
696 if (!DoClone)
697 return F;
698 SmallVector<std::pair<int, Type *>, 4> ChangedTypes;
699 Type *RetType = IsRetAggr ? B.getInt32Ty() : F->getReturnType();
700 if (IsRetAggr)
701 ChangedTypes.push_back(std::pair<int, Type *>(-1, F->getReturnType()));
702 SmallVector<Type *, 4> ArgTypes;
703 for (const auto &Arg : F->args()) {
704 if (Arg.getType()->isAggregateType()) {
705 ArgTypes.push_back(B.getInt32Ty());
706 ChangedTypes.push_back(
707 std::pair<int, Type *>(Arg.getArgNo(), Arg.getType()));
708 } else
709 ArgTypes.push_back(Arg.getType());
710 }
711 FunctionType *NewFTy =
712 FunctionType::get(RetType, ArgTypes, F->getFunctionType()->isVarArg());
713 Function *NewF =
714 Function::Create(NewFTy, F->getLinkage(), F->getAddressSpace(),
715 F->getName(), F->getParent());
716
718 auto NewFArgIt = NewF->arg_begin();
719 for (auto &Arg : F->args()) {
720 StringRef ArgName = Arg.getName();
721 NewFArgIt->setName(ArgName);
722 VMap[&Arg] = &(*NewFArgIt++);
723 }
725
726 CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
727 Returns);
728 NewF->takeName(F);
729 NewF->setComdat(F->getComdat());
730
732 NewF->getParent()->getOrInsertNamedMetadata("spv.cloned_funcs"),
733 std::move(ChangedTypes), NewF->getName());
734
735 for (User *U : F->users()) {
736 if (auto *CB = dyn_cast<CallBase>(U); CB && CB->getCalledFunction() == F)
737 CB->mutateFunctionType(NewF->getFunctionType());
738 }
739 // NewF keeps F's address space, so their pointer types match and
740 // RAUW is safe despite the differing signatures.
741 assert(F->getType() == NewF->getType() &&
742 "RAUW requires F and NewF to share the same pointer type");
743 F->replaceAllUsesWith(NewF);
744
745 // register the mutation
746 if (RetType != F->getReturnType())
747 TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
748 NewF, F->getReturnType());
749 return NewF;
750}
751
752// Returns true iff `F`'s name resolves (after OpenCL/SPIR-V demangling and
753// builtin-name lookup) to the SPIR-V friendly built-in `__spirv_AbortKHR`.
754static bool isAbortKHRBuiltin(const Function &F) {
755 if (F.isIntrinsic())
756 return false;
757 StringRef Name = F.getName();
758 // Quick reject: the mangled or unmangled name must contain the substring.
759 if (!Name.contains("__spirv_AbortKHR"))
760 return false;
761 std::string Demangled = getOclOrSpirvBuiltinDemangledName(Name);
762 if (Demangled.empty())
763 return false;
764 return SPIRV::lookupBuiltinNameHelper(Demangled) == "__spirv_AbortKHR";
765}
766
767// Rewrites a single call to `__spirv_AbortKHR` into a call to the
768// `llvm.spv.abort` target intrinsic, then re-terminates the block with
769// `unreachable`. OpAbortKHR is itself a SPIR-V function-termination
770// instruction and must be the last instruction in its block, so any trailing
771// stores/lifetime intrinsics/`ret` emitted by the OpenCL ABI are dropped.
772// `changeToUnreachable` cleans up any successor PHI predecessor entries.
774 IRBuilder<> B(CI);
775 Value *Msg = CI->getArgOperand(0);
776 // The OpenCL C ABI may pass aggregate arguments by pointer (byval). In that
777 // case load the underlying value so that OpAbortKHR receives the composite
778 // itself, as required by the SPV_KHR_abort spec ("Message Type must be a
779 // concrete type").
780 if (CI->isByValArgument(0)) {
781 Type *AggTy = CI->getParamByValType(0);
782 Msg = B.CreateLoad(AggTy, Msg);
783 }
784 B.CreateIntrinsic(Intrinsic::spv_abort, {Msg->getType()}, {Msg});
786}
787
788// Replace OpenCL/SPIR-V style calls to `__spirv_AbortKHR(message)` (i.e.
789// calls to `F` when `F` is the `__spirv_AbortKHR` built-in) with calls to the
790// `llvm.spv.abort` target intrinsic.
791bool SPIRVPrepareFunctionsImpl::substituteAbortKHRCalls(Function *F) {
792 if (!isAbortKHRBuiltin(*F))
793 return false;
794
795 bool Changed = false;
796 for (User *U : make_early_inc_range(F->users())) {
797 auto *CI = dyn_cast<CallInst>(U);
798 if (!CI || CI->getCalledFunction() != F)
799 continue;
800 if (CI->arg_size() != 1)
801 continue;
803 Changed = true;
804 }
805
806 return Changed;
807}
808
809// When the SPV_KHR_abort extension is enabled, `llvm.trap` and
810// `llvm.ubsantrap` are lowered to `OpAbortKHR` during instruction selection.
811// `OpAbortKHR` is itself a SPIR-V block terminator, so any instructions that
812// follow the trap call within the same basic block (e.g. `ret`, lifetime
813// markers) would produce SPIR-V ops after `OpAbortKHR` and break validation.
814// Terminate the block right after each call to the trap intrinsics by replacing
815// the next instruction with `unreachable`.
816bool SPIRVPrepareFunctionsImpl::terminateBlocksAfterTrap(Module &M,
817 Intrinsic::ID IID) {
818 assert((IID == Intrinsic::trap || IID == Intrinsic::ubsantrap) &&
819 "Expected trap intrinsic ID");
820
822 if (!F)
823 return false;
824
825 // If the target doesn't support SPV_KHR_abort, we won't be able to lower
826 // the trap intrinsic to OpAbortKHR, so we can skip the block-terminating
827 // transformation.
828 const auto &ST = TM.getSubtarget<SPIRVSubtarget>(*F);
829 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
830 return false;
831
832 bool Changed = false;
833 for (User *U : make_early_inc_range(F->users())) {
834 auto *CI = dyn_cast<CallInst>(U);
835 if (!CI || CI->getCalledFunction() != F)
836 continue;
837 Instruction *Next = CI->getNextNode();
839 continue;
841 Changed = true;
842 }
843 return Changed;
844}
845
846static std::string fixMultiOutputConstraintString(StringRef Constraints) {
847 // We should only have one =r return for the made up ASM type.
849 SplitString(Constraints, Tmp, ",");
850 std::string SafeConstraints("=r,");
851 for (unsigned I = 0u; I != Tmp.size() - 1; ++I) {
852 if (Tmp[I].starts_with('=') && (Tmp[I][1] == '&' || isalnum(Tmp[I][1])))
853 continue;
854 SafeConstraints.append(Tmp[I]).append({','});
855 }
856 SafeConstraints.append(Tmp.back());
857
858 return SafeConstraints;
859}
860
861// Mutates indirect and inline ASM callsites iff aggregate argument/return types
862// are present with the types replaced by i32 types. The change in types is
863// noted in 'spv.mutated_callsites' metadata for later restoration. For ASM we
864// also have to mutate the constraint string as IRTranslator tries to handle
865// multiple outputs and expects an aggregate return type in their presence.
866bool SPIRVPrepareFunctionsImpl::removeAggregateTypesFromCalls(Function *F) {
867 if (F->isDeclaration() || F->isIntrinsic())
868 return false;
869
871 for (auto &&I : instructions(F)) {
872 if (auto *CB = dyn_cast<CallBase>(&I)) {
873 if (!CB->getCalledOperand() || CB->getCalledFunction())
874 continue;
875 if (CB->getType()->isAggregateType() ||
876 any_of(CB->args(),
877 [](auto &&Arg) { return Arg->getType()->isAggregateType(); }))
878 Calls.emplace_back(CB, nullptr);
879 }
880 }
881
882 if (Calls.empty())
883 return false;
884
885 IRBuilder<> B(*F->getParent());
886
887 unsigned MutatedCallIdx = 0;
888 for (auto &&[CB, NewFnTy] : Calls) {
890 SmallVector<Type *> NewArgTypes;
891
892 Type *RetTy = CB->getType();
893 if (RetTy->isAggregateType()) {
894 ChangedTypes.emplace_back(-1, RetTy);
895 RetTy = B.getInt32Ty();
896 }
897
898 for (auto &&Arg : CB->args()) {
899 if (Arg->getType()->isAggregateType()) {
900 NewArgTypes.push_back(B.getInt32Ty());
901 ChangedTypes.emplace_back(Arg.getOperandNo(), Arg->getType());
902 } else {
903 NewArgTypes.push_back(Arg->getType());
904 }
905 }
906 NewFnTy = FunctionType::get(RetTy, NewArgTypes,
907 CB->getFunctionType()->isVarArg());
908
909 // Keyed via instruction metadata, not a name.
910 std::string Key =
911 ("spv.mutated_callsite." + F->getName() + "." + Twine(MutatedCallIdx++))
912 .str();
913 CB->setMetadata(
914 "spv.mutated_callsite",
915 MDNode::get(F->getContext(), MDString::get(F->getContext(), Key)));
916
917 std::string Constraints;
918 if (auto *ASM = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
919 Constraints = ASM->getConstraintString();
920
921 CB->setCalledOperand(InlineAsm::get(
922 NewFnTy, ASM->getAsmString(),
923 fixMultiOutputConstraintString(Constraints), ASM->hasSideEffects(),
924 ASM->isAlignStack(), ASM->getDialect(), ASM->canThrow()));
925 }
926
928 F->getParent()->getOrInsertNamedMetadata("spv.mutated_callsites"),
929 std::move(ChangedTypes), Key, Constraints);
930 }
931
932 for (auto &&[CB, NewFTy] : Calls) {
933 if (NewFTy->getReturnType() != CB->getType())
934 TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
935 CB, CB->getType());
936 CB->mutateFunctionType(NewFTy);
937 }
938
939 return true;
940}
941
942bool SPIRVPrepareFunctionsImpl::runOnModule(Module &M) {
943 // Resolve the SPIR-V environment from module content before any
944 // function-level processing. This must happen before legalization so that
945 // isShader()/isKernel() return correct values.
946 const_cast<SPIRVTargetMachine &>(TM)
947 .getMutableSubtargetImpl()
948 ->resolveEnvFromModule(M);
949
950 bool Changed = false;
951 if (M.getFunctionDefs().empty()) {
952 // If there are no function definitions, insert a service
953 // function so that the global/constant tracking intrinsics
954 // will be created. Without these intrinsics the generated SPIR-V
955 // will be empty. The service function itself is not emitted.
957 BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry", SF);
958 IRBuilder<> IRB(BB);
959 IRB.CreateRetVoid();
960 Changed = true;
961 }
962
963 Changed |= terminateBlocksAfterTrap(M, Intrinsic::trap);
964 Changed |= terminateBlocksAfterTrap(M, Intrinsic::ubsantrap);
965
966 for (GlobalVariable &GV : M.globals()) {
967 // Strip + tag available_externally globals so AuxData can re-emit the
968 // original linkage as NonSemantic.AuxData::Linkage.
969 if (GV.hasAvailableExternallyLinkage() && !GV.isDeclaration()) {
971 GV.setLinkage(GlobalValue::ExternalLinkage);
972 Changed = true;
973 }
974 }
975
976 std::vector<Function *> FuncsWorklist;
977 for (Function &F : M) {
978 // MachineFunctionPass skips available_externally; strip + tag so AuxData
979 // can re-emit the original linkage as NonSemantic.AuxData::Linkage.
980 if (F.hasAvailableExternallyLinkage() && !F.isDeclaration()) {
983 Changed = true;
984 }
985 Changed |= substituteAbortKHRCalls(&F);
986 Changed |= substituteIntrinsicCalls(&F);
987 Changed |= sortBlocks(F);
988 Changed |= removeAggregateTypesFromCalls(&F);
989 FuncsWorklist.push_back(&F);
990 }
991
992 for (auto *F : FuncsWorklist) {
993 Function *NewF = removeAggregateTypesFromSignature(F);
994
995 if (NewF != F) {
996 F->eraseFromParent();
997 Changed = true;
998 }
999 }
1000 return Changed;
1001}
1002
1007 auto GetTTI = [&FAM](Function &F) -> const TargetTransformInfo & {
1008 return FAM.getResult<TargetIRAnalysis>(F);
1009 };
1010 return SPIRVPrepareFunctionsImpl(TM, GetTTI).runOnModule(M)
1013}
1014
1015ModulePass *
1017 return new SPIRVPrepareFunctionsLegacy(TM);
1018}
SDValue Pred
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:559
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:853
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
arg_iterator arg_begin()
Definition Function.h:862
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:880
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:1534
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition IRBuilder.h:1194
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1441
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1513
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:602
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
Definition IRBuilder.h:1189
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:197
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1594
ConstantInt * getInt(const APInt &AI)
Get a constant integer value.
Definition IRBuilder.h:486
Value * CreateURem(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1501
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2990
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:595
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:105
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:327
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:512
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:389
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:548
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:314
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:395
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:2592
@ 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:879