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
22#include "SPIRV.h"
23#include "SPIRVBuiltins.h"
24#include "SPIRVSubtarget.h"
25#include "SPIRVTargetMachine.h"
26#include "SPIRVUtils.h"
32#include "llvm/IR/IRBuilder.h"
36#include "llvm/IR/Intrinsics.h"
37#include "llvm/IR/IntrinsicsSPIRV.h"
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 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 {
426 llvm_unreachable("Unknown intrinsic");
427 }
428}
429
431 auto *LifetimeArg0 = II->getArgOperand(0);
432
433 // If the lifetime argument is a poison value, the intrinsic has no effect.
434 if (isa<PoisonValue>(LifetimeArg0)) {
435 II->eraseFromParent();
436 return true;
437 }
438
439 IRBuilder<> Builder(II);
440 auto *Alloca = cast<AllocaInst>(LifetimeArg0);
441 std::optional<TypeSize> Size =
442 Alloca->getAllocationSize(Alloca->getDataLayout());
443 Value *SizeVal = Builder.getInt64(Size ? *Size : -1);
444 Builder.CreateIntrinsic(NewID, Alloca->getType(), {SizeVal, LifetimeArg0});
445 II->eraseFromParent();
446 return true;
447}
448
449static void
451 SmallVector<Instruction *> &EraseFromParent) {
452 auto *FPI = cast<ConstrainedFPIntrinsic>(II);
453 Value *A = FPI->getArgOperand(0);
454 Value *Mul = FPI->getArgOperand(1);
455 Value *Add = FPI->getArgOperand(2);
456 IRBuilder<> Builder(II->getParent());
457 Builder.SetInsertPoint(II);
458 std::optional<RoundingMode> Rounding = FPI->getRoundingMode();
459 Value *Product = Builder.CreateFMul(A, Mul, II->getName() + ".mul");
460 Value *Result = Builder.CreateConstrainedFPBinOp(
461 Intrinsic::experimental_constrained_fadd, Product, Add, {},
462 II->getName() + ".add", nullptr, Rounding);
463 II->replaceAllUsesWith(Result);
464 EraseFromParent.push_back(II);
465}
466
467// Substitutes calls to LLVM intrinsics with either calls to SPIR-V intrinsics
468// or calls to proper generated functions. Returns True if F was modified.
469bool SPIRVPrepareFunctionsImpl::substituteIntrinsicCalls(Function *F) {
470 if (F->isDeclaration())
471 return false;
472
473 bool Changed = false;
474 const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
475 SmallVector<Instruction *> EraseFromParent;
476 const TargetTransformInfo &TTI = GetTTI(*F);
477 for (BasicBlock &BB : *F) {
478 for (Instruction &I : make_early_inc_range(BB)) {
479 auto Call = dyn_cast<CallInst>(&I);
480 if (!Call)
481 continue;
483 if (!CF || !CF->isIntrinsic())
484 continue;
485 auto *II = cast<IntrinsicInst>(Call);
486 if (Intrinsic::isTargetIntrinsic(II->getIntrinsicID()) &&
487 II->getCalledOperand()->getName().starts_with("llvm.spv"))
488 continue;
489 switch (II->getIntrinsicID()) {
490 case Intrinsic::memset:
491 case Intrinsic::bswap:
493 break;
494 case Intrinsic::fshl:
495 case Intrinsic::fshr:
497 Changed = true;
498 break;
499 case Intrinsic::assume:
500 case Intrinsic::expect:
501 if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
503 Changed = true;
504 break;
505 case Intrinsic::lifetime_start:
506 if (!STI.isShader()) {
508 II, Intrinsic::SPVIntrinsics::spv_lifetime_start);
509 } else {
510 II->eraseFromParent();
511 Changed = true;
512 }
513 break;
514 case Intrinsic::lifetime_end:
515 if (!STI.isShader()) {
517 II, Intrinsic::SPVIntrinsics::spv_lifetime_end);
518 } else {
519 II->eraseFromParent();
520 Changed = true;
521 }
522 break;
523 case Intrinsic::ptr_annotation:
525 Changed = true;
526 break;
527 case Intrinsic::experimental_constrained_fmuladd:
528 lowerConstrainedFmuladd(II, EraseFromParent);
529 Changed = true;
530 break;
531 case Intrinsic::experimental_constrained_fcmp:
532 case Intrinsic::experimental_constrained_fcmps:
534 EraseFromParent);
535 Changed = true;
536 break;
537 default:
538 // Drop assume-like intrinsics that have no SPIR-V representation.
539 if (II->isAssumeLikeIntrinsic()) {
540 if (!II->getType()->isVoidTy())
541 II->replaceAllUsesWith(PoisonValue::get(II->getType()));
542 II->eraseFromParent();
543 Changed = true;
544 break;
545 }
546 if (TM.getTargetTriple().getVendor() == Triple::AMD ||
547 any_of(SPVAllowUnknownIntrinsics, [II](auto &&Prefix) {
548 if (Prefix.empty())
549 return false;
550 return II->getCalledFunction()->getName().starts_with(Prefix);
551 }))
553 break;
554 }
555 }
556 }
557 for (auto *I : EraseFromParent)
558 I->eraseFromParent();
559 return Changed;
560}
561
562static void
564 SmallVector<std::pair<int, Type *>> ChangedTys,
565 StringRef Name, StringRef AsmConstraints = "") {
566
567 LLVMContext &Ctx = NMD->getParent()->getContext();
568 Type *I32Ty = IntegerType::getInt32Ty(Ctx);
569
571 MDArgs.push_back(MDString::get(Ctx, Name));
572 transform(ChangedTys, std::back_inserter(MDArgs), [=, &Ctx](auto &&CTy) {
573 return MDNode::get(
574 Ctx, {ConstantAsMetadata::get(ConstantInt::get(I32Ty, CTy.first, true)),
576 });
577 if (!AsmConstraints.empty())
578 MDArgs.push_back(MDNode::get(Ctx, MDString::get(Ctx, AsmConstraints)));
579 NMD->addOperand(MDNode::get(Ctx, MDArgs));
580}
581
582// Returns F if aggregate argument/return types are not present or cloned F
583// function with the types replaced by i32 types. The change in types is
584// noted in 'spv.cloned_funcs' metadata for later restoration.
585Function *
586SPIRVPrepareFunctionsImpl::removeAggregateTypesFromSignature(Function *F) {
587 bool IsRetAggr = F->getReturnType()->isAggregateType();
588 // Allow intrinsics with aggregate return/argument types to reach GlobalISel.
589 // Renaming/mutating the signature of an intrinsic would desync its name from
590 // its argument types and break the IR verifier.
591 if (F->isIntrinsic())
592 return F;
593
594 IRBuilder<> B(F->getContext());
595
596 bool HasAggrArg = llvm::any_of(F->args(), [](Argument &Arg) {
597 return Arg.getType()->isAggregateType();
598 });
599 bool DoClone = IsRetAggr || HasAggrArg;
600 if (!DoClone)
601 return F;
602 SmallVector<std::pair<int, Type *>, 4> ChangedTypes;
603 Type *RetType = IsRetAggr ? B.getInt32Ty() : F->getReturnType();
604 if (IsRetAggr)
605 ChangedTypes.push_back(std::pair<int, Type *>(-1, F->getReturnType()));
606 SmallVector<Type *, 4> ArgTypes;
607 for (const auto &Arg : F->args()) {
608 if (Arg.getType()->isAggregateType()) {
609 ArgTypes.push_back(B.getInt32Ty());
610 ChangedTypes.push_back(
611 std::pair<int, Type *>(Arg.getArgNo(), Arg.getType()));
612 } else
613 ArgTypes.push_back(Arg.getType());
614 }
615 FunctionType *NewFTy =
616 FunctionType::get(RetType, ArgTypes, F->getFunctionType()->isVarArg());
617 Function *NewF =
618 Function::Create(NewFTy, F->getLinkage(), F->getAddressSpace(),
619 F->getName(), F->getParent());
620
622 auto NewFArgIt = NewF->arg_begin();
623 for (auto &Arg : F->args()) {
624 StringRef ArgName = Arg.getName();
625 NewFArgIt->setName(ArgName);
626 VMap[&Arg] = &(*NewFArgIt++);
627 }
629
630 CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
631 Returns);
632 NewF->takeName(F);
633
635 NewF->getParent()->getOrInsertNamedMetadata("spv.cloned_funcs"),
636 std::move(ChangedTypes), NewF->getName());
637
638 for (auto *U : make_early_inc_range(F->users())) {
639 if (CallInst *CI;
640 (CI = dyn_cast<CallInst>(U)) && CI->getCalledFunction() == F)
641 CI->mutateFunctionType(NewF->getFunctionType());
642 if (auto *C = dyn_cast<Constant>(U))
643 C->handleOperandChange(F, NewF);
644 else
645 U->replaceUsesOfWith(F, NewF);
646 }
647
648 // register the mutation
649 if (RetType != F->getReturnType())
650 TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
651 NewF, F->getReturnType());
652 return NewF;
653}
654
655// Returns true iff `F`'s name resolves (after OpenCL/SPIR-V demangling and
656// builtin-name lookup) to the SPIR-V friendly built-in `__spirv_AbortKHR`.
657static bool isAbortKHRBuiltin(const Function &F) {
658 if (F.isIntrinsic())
659 return false;
660 StringRef Name = F.getName();
661 // Quick reject: the mangled or unmangled name must contain the substring.
662 if (!Name.contains("__spirv_AbortKHR"))
663 return false;
664 std::string Demangled = getOclOrSpirvBuiltinDemangledName(Name);
665 if (Demangled.empty())
666 return false;
667 return SPIRV::lookupBuiltinNameHelper(Demangled) == "__spirv_AbortKHR";
668}
669
670// Rewrites a single call to `__spirv_AbortKHR` into a call to the
671// `llvm.spv.abort` target intrinsic, then re-terminates the block with
672// `unreachable`. OpAbortKHR is itself a SPIR-V function-termination
673// instruction and must be the last instruction in its block, so any trailing
674// stores/lifetime intrinsics/`ret` emitted by the OpenCL ABI are dropped.
675// `changeToUnreachable` cleans up any successor PHI predecessor entries.
677 IRBuilder<> B(CI);
678 Value *Msg = CI->getArgOperand(0);
679 // The OpenCL C ABI may pass aggregate arguments by pointer (byval). In that
680 // case load the underlying value so that OpAbortKHR receives the composite
681 // itself, as required by the SPV_KHR_abort spec ("Message Type must be a
682 // concrete type").
683 if (CI->isByValArgument(0)) {
684 Type *AggTy = CI->getParamByValType(0);
685 Msg = B.CreateLoad(AggTy, Msg);
686 }
687 B.CreateIntrinsic(Intrinsic::spv_abort, {Msg->getType()}, {Msg});
689}
690
691// Replace OpenCL/SPIR-V style calls to `__spirv_AbortKHR(message)` (i.e.
692// calls to `F` when `F` is the `__spirv_AbortKHR` built-in) with calls to the
693// `llvm.spv.abort` target intrinsic.
694bool SPIRVPrepareFunctionsImpl::substituteAbortKHRCalls(Function *F) {
695 if (!isAbortKHRBuiltin(*F))
696 return false;
697
699 for (User *U : F->users()) {
700 auto *CI = dyn_cast<CallInst>(U);
701 if (!CI || CI->getCalledFunction() != F)
702 continue;
703 if (CI->arg_size() != 1)
704 continue;
705 Calls.push_back(CI);
706 }
707
708 for (CallInst *CI : Calls)
710
711 return !Calls.empty();
712}
713
714// When the SPV_KHR_abort extension is enabled, `llvm.trap` and
715// `llvm.ubsantrap` are lowered to `OpAbortKHR` during instruction selection.
716// `OpAbortKHR` is itself a SPIR-V block terminator, so any instructions that
717// follow the trap call within the same basic block (e.g. `ret`, lifetime
718// markers) would produce SPIR-V ops after `OpAbortKHR` and break validation.
719// Terminate the block right after each call to the trap intrinsics by replacing
720// the next instruction with `unreachable`.
721bool SPIRVPrepareFunctionsImpl::terminateBlocksAfterTrap(Module &M,
722 Intrinsic::ID IID) {
723 assert((IID == Intrinsic::trap || IID == Intrinsic::ubsantrap) &&
724 "Expected trap intrinsic ID");
725
727 if (!F)
728 return false;
729
730 // If the target doesn't support SPV_KHR_abort, we won't be able to lower
731 // the trap intrinsic to OpAbortKHR, so we can skip the block-terminating
732 // transformation.
733 const auto &ST = TM.getSubtarget<SPIRVSubtarget>(*F);
734 if (!ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort))
735 return false;
736
738 for (User *U : F->users()) {
739 auto *CI = dyn_cast<CallInst>(U);
740 if (!CI || CI->getCalledFunction() != F)
741 continue;
742 Calls.push_back(CI);
743 }
744
745 bool Changed = false;
746 for (CallInst *CI : Calls) {
747 Instruction *Next = CI->getNextNode();
749 continue;
751 Changed = true;
752 }
753 return Changed;
754}
755
756static std::string fixMultiOutputConstraintString(StringRef Constraints) {
757 // We should only have one =r return for the made up ASM type.
759 SplitString(Constraints, Tmp, ",");
760 std::string SafeConstraints("=r,");
761 for (unsigned I = 0u; I != Tmp.size() - 1; ++I) {
762 if (Tmp[I].starts_with('=') && (Tmp[I][1] == '&' || isalnum(Tmp[I][1])))
763 continue;
764 SafeConstraints.append(Tmp[I]).append({','});
765 }
766 SafeConstraints.append(Tmp.back());
767
768 return SafeConstraints;
769}
770
771// Mutates indirect and inline ASM callsites iff aggregate argument/return types
772// are present with the types replaced by i32 types. The change in types is
773// noted in 'spv.mutated_callsites' metadata for later restoration. For ASM we
774// also have to mutate the constraint string as IRTranslator tries to handle
775// multiple outputs and expects an aggregate return type in their presence.
776bool SPIRVPrepareFunctionsImpl::removeAggregateTypesFromCalls(Function *F) {
777 if (F->isDeclaration() || F->isIntrinsic())
778 return false;
779
781 for (auto &&I : instructions(F)) {
782 if (auto *CB = dyn_cast<CallBase>(&I)) {
783 if (!CB->getCalledOperand() || CB->getCalledFunction())
784 continue;
785 if (CB->getType()->isAggregateType() ||
786 any_of(CB->args(),
787 [](auto &&Arg) { return Arg->getType()->isAggregateType(); }))
788 Calls.emplace_back(CB, nullptr);
789 }
790 }
791
792 if (Calls.empty())
793 return false;
794
795 IRBuilder<> B(F->getContext());
796
797 unsigned MutatedCallIdx = 0;
798 for (auto &&[CB, NewFnTy] : Calls) {
800 SmallVector<Type *> NewArgTypes;
801
802 Type *RetTy = CB->getType();
803 if (RetTy->isAggregateType()) {
804 ChangedTypes.emplace_back(-1, RetTy);
805 RetTy = B.getInt32Ty();
806 }
807
808 for (auto &&Arg : CB->args()) {
809 if (Arg->getType()->isAggregateType()) {
810 NewArgTypes.push_back(B.getInt32Ty());
811 ChangedTypes.emplace_back(Arg.getOperandNo(), Arg->getType());
812 } else {
813 NewArgTypes.push_back(Arg->getType());
814 }
815 }
816 NewFnTy = FunctionType::get(RetTy, NewArgTypes,
817 CB->getFunctionType()->isVarArg());
818
819 // Keyed via instruction metadata, not a name.
820 std::string Key =
821 ("spv.mutated_callsite." + F->getName() + "." + Twine(MutatedCallIdx++))
822 .str();
823 CB->setMetadata(
824 "spv.mutated_callsite",
825 MDNode::get(F->getContext(), MDString::get(F->getContext(), Key)));
826
827 std::string Constraints;
828 if (auto *ASM = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
829 Constraints = ASM->getConstraintString();
830
831 CB->setCalledOperand(InlineAsm::get(
832 NewFnTy, ASM->getAsmString(),
833 fixMultiOutputConstraintString(Constraints), ASM->hasSideEffects(),
834 ASM->isAlignStack(), ASM->getDialect(), ASM->canThrow()));
835 }
836
838 F->getParent()->getOrInsertNamedMetadata("spv.mutated_callsites"),
839 std::move(ChangedTypes), Key, Constraints);
840 }
841
842 for (auto &&[CB, NewFTy] : Calls) {
843 if (NewFTy->getReturnType() != CB->getType())
844 TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
845 CB, CB->getType());
846 CB->mutateFunctionType(NewFTy);
847 }
848
849 return true;
850}
851
852bool SPIRVPrepareFunctionsImpl::runOnModule(Module &M) {
853 // Resolve the SPIR-V environment from module content before any
854 // function-level processing. This must happen before legalization so that
855 // isShader()/isKernel() return correct values.
856 const_cast<SPIRVTargetMachine &>(TM)
857 .getMutableSubtargetImpl()
858 ->resolveEnvFromModule(M);
859
860 bool Changed = false;
861 if (M.getFunctionDefs().empty()) {
862 // If there are no function definitions, insert a service
863 // function so that the global/constant tracking intrinsics
864 // will be created. Without these intrinsics the generated SPIR-V
865 // will be empty. The service function itself is not emitted.
867 BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry", SF);
868 IRBuilder<> IRB(BB);
869 IRB.CreateRetVoid();
870 Changed = true;
871 }
872
873 Changed |= terminateBlocksAfterTrap(M, Intrinsic::trap);
874 Changed |= terminateBlocksAfterTrap(M, Intrinsic::ubsantrap);
875
876 for (GlobalVariable &GV : M.globals()) {
877 // Strip + tag available_externally globals so AuxData can re-emit the
878 // original linkage as NonSemantic.AuxData::Linkage.
879 if (GV.hasAvailableExternallyLinkage() && !GV.isDeclaration()) {
881 GV.setLinkage(GlobalValue::ExternalLinkage);
882 Changed = true;
883 }
884 }
885
886 for (Function &F : M) {
887 // MachineFunctionPass skips available_externally; strip + tag so AuxData
888 // can re-emit the original linkage as NonSemantic.AuxData::Linkage.
889 if (F.hasAvailableExternallyLinkage() && !F.isDeclaration()) {
892 Changed = true;
893 }
894 Changed |= substituteAbortKHRCalls(&F);
895 Changed |= substituteIntrinsicCalls(&F);
896 Changed |= sortBlocks(F);
897 Changed |= removeAggregateTypesFromCalls(&F);
898 }
899
900 std::vector<Function *> FuncsWorklist;
901 for (auto &F : M)
902 FuncsWorklist.push_back(&F);
903
904 for (auto *F : FuncsWorklist) {
905 Function *NewF = removeAggregateTypesFromSignature(F);
906
907 if (NewF != F) {
908 F->eraseFromParent();
909 Changed = true;
910 }
911 }
912 return Changed;
913}
914
919 auto GetTTI = [&FAM](Function &F) -> const TargetTransformInfo & {
920 return FAM.getResult<TargetIRAnalysis>(F);
921 };
922 return SPIRVPrepareFunctionsImpl(TM, GetTTI).runOnModule(M)
925}
926
929 return new SPIRVPrepareFunctionsLegacy(TM);
930}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
uint64_t IntrinsicInst * II
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 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 lowerConstrainedFPCmpIntrinsic(ConstrainedFPCmpIntrinsic *ConstrainedCmpIntrinsic, SmallVector< Instruction * > &EraseFromParent)
static void lowerConstrainedFmuladd(IntrinsicInst *II, SmallVector< Instruction * > &EraseFromParent)
static void lowerPtrAnnotation(IntrinsicInst *II)
static bool lowerIntrinsicToFunction(IntrinsicInst *Intrinsic, const TargetTransformInfo &TTI)
static bool isAbortKHRBuiltin(const Function &F)
static SmallVector< Metadata * > parseAnnotation(Value *I, const std::string &Anno, LLVMContext &Ctx, Type *Int32Ty)
static std::string fixMultiOutputConstraintString(StringRef Constraints)
static void rewriteAbortKHRCall(CallInst *CI)
static void addFunctionTypeMutation(NamedMDNode *NMD, SmallVector< std::pair< int, Type * > > ChangedTys, StringRef Name, StringRef AsmConstraints="")
static bool toSpvLifetimeIntrinsic(IntrinsicInst *II, Intrinsic::ID NewID)
static void lowerExpectAssume(IntrinsicInst *II)
static Function * getOrCreateFunction(Module *M, Type *RetTy, ArrayRef< Type * > ArgTypes, StringRef Name)
#define SPIRV_WAS_AVAILABLE_EXTERNALLY_ATTR
Definition SPIRVUtils.h:542
This file contains some functions that are useful when dealing with strings.
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
This pass exposes codegen information to IR-level passes.
Value * RHS
Value * LHS
BinaryOperator * Mul
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:537
This is the shared class of boolean and integer constants.
Definition Constants.h:87
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Constrained floating point compare intrinsics.
LLVM_ABI FCmpInst::Predicate getPredicate() const
Diagnostic information for unsupported feature in backend.
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
bool empty() const
Definition Function.h:836
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:211
arg_iterator arg_begin()
Definition Function.h:845
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition Function.h:251
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:216
void setCallingConv(CallingConv::ID CC)
Definition Function.h:276
Argument * getArg(unsigned i) const
Definition Function.h:863
Module * getParent()
Get the module that this global value is contained inside of...
void setDSOLocal(bool Local)
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
LLVM_ABI CallInst * CreateIntrinsicWithoutFolding(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={})
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
LLVM_ABI Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition IRBuilder.h:1532
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Definition IRBuilder.h:1192
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1439
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition IRBuilder.h:1511
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:608
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
Definition IRBuilder.h:1187
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:181
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Definition IRBuilder.h:1592
ConstantInt * getInt(const APInt &AI)
Get a constant integer value.
Definition IRBuilder.h:492
Value * CreateURem(Value *LHS, Value *RHS, const Twine &Name="")
Definition IRBuilder.h:1499
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
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:1565
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:614
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:110
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:327
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:1753
Module * getParent()
Get the module that holds this named metadata collection.
Definition Metadata.h:1823
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 Triple & getTargetTriple() const
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.
VendorType getVendor() const
Get the parsed vendor type of this triple.
Definition Triple.h:518
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:319
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:509
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:394
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
Type * getElementType() const
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SPIR_FUNC
Used for SPIR non-kernel device functions.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI bool isTargetIntrinsic(ID IID)
isTargetIntrinsic - Returns true if IID is an intrinsic specific to a certain target.
std::string lookupBuiltinNameHelper(StringRef DemangledCall, FPDecorationId *DecorationId)
Parses the name part of the demangled builtin call.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool getConstantStringInfo(const Value *V, StringRef &Str, bool TrimAtNul=true)
This function computes the length of a null-terminated C string pointed to by V.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
bool sortBlocks(Function &F)
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:2026
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:1746
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:2552
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
TargetTransformInfo TTI
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1910
@ 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