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