xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVPrepareFunctions.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 "SPIRVSubtarget.h"
23 #include "SPIRVTargetMachine.h"
24 #include "SPIRVUtils.h"
25 #include "llvm/ADT/StringExtras.h"
26 #include "llvm/Analysis/ValueTracking.h"
27 #include "llvm/CodeGen/IntrinsicLowering.h"
28 #include "llvm/IR/IRBuilder.h"
29 #include "llvm/IR/IntrinsicInst.h"
30 #include "llvm/IR/Intrinsics.h"
31 #include "llvm/IR/IntrinsicsSPIRV.h"
32 #include "llvm/Transforms/Utils/Cloning.h"
33 #include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
34 #include <regex>
35 
36 using namespace llvm;
37 
38 namespace {
39 
40 class SPIRVPrepareFunctions : public ModulePass {
41   const SPIRVTargetMachine &TM;
42   bool substituteIntrinsicCalls(Function *F);
43   Function *removeAggregateTypesFromSignature(Function *F);
44 
45 public:
46   static char ID;
SPIRVPrepareFunctions(const SPIRVTargetMachine & TM)47   SPIRVPrepareFunctions(const SPIRVTargetMachine &TM)
48       : ModulePass(ID), TM(TM) {}
49 
50   bool runOnModule(Module &M) override;
51 
getPassName() const52   StringRef getPassName() const override { return "SPIRV prepare functions"; }
53 
getAnalysisUsage(AnalysisUsage & AU) const54   void getAnalysisUsage(AnalysisUsage &AU) const override {
55     ModulePass::getAnalysisUsage(AU);
56   }
57 };
58 
59 } // namespace
60 
61 char SPIRVPrepareFunctions::ID = 0;
62 
63 INITIALIZE_PASS(SPIRVPrepareFunctions, "prepare-functions",
64                 "SPIRV prepare functions", false, false)
65 
lowerLLVMIntrinsicName(IntrinsicInst * II)66 static std::string lowerLLVMIntrinsicName(IntrinsicInst *II) {
67   Function *IntrinsicFunc = II->getCalledFunction();
68   assert(IntrinsicFunc && "Missing function");
69   std::string FuncName = IntrinsicFunc->getName().str();
70   llvm::replace(FuncName, '.', '_');
71   FuncName = "spirv." + FuncName;
72   return FuncName;
73 }
74 
getOrCreateFunction(Module * M,Type * RetTy,ArrayRef<Type * > ArgTypes,StringRef Name)75 static Function *getOrCreateFunction(Module *M, Type *RetTy,
76                                      ArrayRef<Type *> ArgTypes,
77                                      StringRef Name) {
78   FunctionType *FT = FunctionType::get(RetTy, ArgTypes, false);
79   Function *F = M->getFunction(Name);
80   if (F && F->getFunctionType() == FT)
81     return F;
82   Function *NewF = Function::Create(FT, GlobalValue::ExternalLinkage, Name, M);
83   if (F)
84     NewF->setDSOLocal(F->isDSOLocal());
85   NewF->setCallingConv(CallingConv::SPIR_FUNC);
86   return NewF;
87 }
88 
lowerIntrinsicToFunction(IntrinsicInst * Intrinsic)89 static bool lowerIntrinsicToFunction(IntrinsicInst *Intrinsic) {
90   // For @llvm.memset.* intrinsic cases with constant value and length arguments
91   // are emulated via "storing" a constant array to the destination. For other
92   // cases we wrap the intrinsic in @spirv.llvm_memset_* function and expand the
93   // intrinsic to a loop via expandMemSetAsLoop().
94   if (auto *MSI = dyn_cast<MemSetInst>(Intrinsic))
95     if (isa<Constant>(MSI->getValue()) && isa<ConstantInt>(MSI->getLength()))
96       return false; // It is handled later using OpCopyMemorySized.
97 
98   Module *M = Intrinsic->getModule();
99   std::string FuncName = lowerLLVMIntrinsicName(Intrinsic);
100   if (Intrinsic->isVolatile())
101     FuncName += ".volatile";
102   // Redirect @llvm.intrinsic.* call to @spirv.llvm_intrinsic_*
103   Function *F = M->getFunction(FuncName);
104   if (F) {
105     Intrinsic->setCalledFunction(F);
106     return true;
107   }
108   // TODO copy arguments attributes: nocapture writeonly.
109   FunctionCallee FC =
110       M->getOrInsertFunction(FuncName, Intrinsic->getFunctionType());
111   auto IntrinsicID = Intrinsic->getIntrinsicID();
112   Intrinsic->setCalledFunction(FC);
113 
114   F = dyn_cast<Function>(FC.getCallee());
115   assert(F && "Callee must be a function");
116 
117   switch (IntrinsicID) {
118   case Intrinsic::memset: {
119     auto *MSI = static_cast<MemSetInst *>(Intrinsic);
120     Argument *Dest = F->getArg(0);
121     Argument *Val = F->getArg(1);
122     Argument *Len = F->getArg(2);
123     Argument *IsVolatile = F->getArg(3);
124     Dest->setName("dest");
125     Val->setName("val");
126     Len->setName("len");
127     IsVolatile->setName("isvolatile");
128     BasicBlock *EntryBB = BasicBlock::Create(M->getContext(), "entry", F);
129     IRBuilder<> IRB(EntryBB);
130     auto *MemSet = IRB.CreateMemSet(Dest, Val, Len, MSI->getDestAlign(),
131                                     MSI->isVolatile());
132     IRB.CreateRetVoid();
133     expandMemSetAsLoop(cast<MemSetInst>(MemSet));
134     MemSet->eraseFromParent();
135     break;
136   }
137   case Intrinsic::bswap: {
138     BasicBlock *EntryBB = BasicBlock::Create(M->getContext(), "entry", F);
139     IRBuilder<> IRB(EntryBB);
140     auto *BSwap = IRB.CreateIntrinsic(Intrinsic::bswap, Intrinsic->getType(),
141                                       F->getArg(0));
142     IRB.CreateRet(BSwap);
143     IntrinsicLowering IL(M->getDataLayout());
144     IL.LowerIntrinsicCall(BSwap);
145     break;
146   }
147   default:
148     break;
149   }
150   return true;
151 }
152 
getAnnotation(Value * AnnoVal,Value * OptAnnoVal)153 static std::string getAnnotation(Value *AnnoVal, Value *OptAnnoVal) {
154   if (auto *Ref = dyn_cast_or_null<GetElementPtrInst>(AnnoVal))
155     AnnoVal = Ref->getOperand(0);
156   if (auto *Ref = dyn_cast_or_null<BitCastInst>(OptAnnoVal))
157     OptAnnoVal = Ref->getOperand(0);
158 
159   std::string Anno;
160   if (auto *C = dyn_cast_or_null<Constant>(AnnoVal)) {
161     StringRef Str;
162     if (getConstantStringInfo(C, Str))
163       Anno = Str;
164   }
165   // handle optional annotation parameter in a way that Khronos Translator do
166   // (collect integers wrapped in a struct)
167   if (auto *C = dyn_cast_or_null<Constant>(OptAnnoVal);
168       C && C->getNumOperands()) {
169     Value *MaybeStruct = C->getOperand(0);
170     if (auto *Struct = dyn_cast<ConstantStruct>(MaybeStruct)) {
171       for (unsigned I = 0, E = Struct->getNumOperands(); I != E; ++I) {
172         if (auto *CInt = dyn_cast<ConstantInt>(Struct->getOperand(I)))
173           Anno += (I == 0 ? ": " : ", ") +
174                   std::to_string(CInt->getType()->getIntegerBitWidth() == 1
175                                      ? CInt->getZExtValue()
176                                      : CInt->getSExtValue());
177       }
178     } else if (auto *Struct = dyn_cast<ConstantAggregateZero>(MaybeStruct)) {
179       // { i32 i32 ... } zeroinitializer
180       for (unsigned I = 0, E = Struct->getType()->getStructNumElements();
181            I != E; ++I)
182         Anno += I == 0 ? ": 0" : ", 0";
183     }
184   }
185   return Anno;
186 }
187 
parseAnnotation(Value * I,const std::string & Anno,LLVMContext & Ctx,Type * Int32Ty)188 static SmallVector<Metadata *> parseAnnotation(Value *I,
189                                                const std::string &Anno,
190                                                LLVMContext &Ctx,
191                                                Type *Int32Ty) {
192   // Try to parse the annotation string according to the following rules:
193   // annotation := ({kind} | {kind:value,value,...})+
194   // kind := number
195   // value := number | string
196   static const std::regex R(
197       "\\{(\\d+)(?:[:,](\\d+|\"[^\"]*\")(?:,(\\d+|\"[^\"]*\"))*)?\\}");
198   SmallVector<Metadata *> MDs;
199   int Pos = 0;
200   for (std::sregex_iterator
201            It = std::sregex_iterator(Anno.begin(), Anno.end(), R),
202            ItEnd = std::sregex_iterator();
203        It != ItEnd; ++It) {
204     if (It->position() != Pos)
205       return SmallVector<Metadata *>{};
206     Pos = It->position() + It->length();
207     std::smatch Match = *It;
208     SmallVector<Metadata *> MDsItem;
209     for (std::size_t i = 1; i < Match.size(); ++i) {
210       std::ssub_match SMatch = Match[i];
211       std::string Item = SMatch.str();
212       if (Item.length() == 0)
213         break;
214       if (Item[0] == '"') {
215         Item = Item.substr(1, Item.length() - 2);
216         // Acceptable format of the string snippet is:
217         static const std::regex RStr("^(\\d+)(?:,(\\d+))*$");
218         if (std::smatch MatchStr; std::regex_match(Item, MatchStr, RStr)) {
219           for (std::size_t SubIdx = 1; SubIdx < MatchStr.size(); ++SubIdx)
220             if (std::string SubStr = MatchStr[SubIdx].str(); SubStr.length())
221               MDsItem.push_back(ConstantAsMetadata::get(
222                   ConstantInt::get(Int32Ty, std::stoi(SubStr))));
223         } else {
224           MDsItem.push_back(MDString::get(Ctx, Item));
225         }
226       } else if (int32_t Num; llvm::to_integer(StringRef(Item), Num, 10)) {
227         MDsItem.push_back(
228             ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Num)));
229       } else {
230         MDsItem.push_back(MDString::get(Ctx, Item));
231       }
232     }
233     if (MDsItem.size() == 0)
234       return SmallVector<Metadata *>{};
235     MDs.push_back(MDNode::get(Ctx, MDsItem));
236   }
237   return Pos == static_cast<int>(Anno.length()) ? MDs
238                                                 : SmallVector<Metadata *>{};
239 }
240 
lowerPtrAnnotation(IntrinsicInst * II)241 static void lowerPtrAnnotation(IntrinsicInst *II) {
242   LLVMContext &Ctx = II->getContext();
243   Type *Int32Ty = Type::getInt32Ty(Ctx);
244 
245   // Retrieve an annotation string from arguments.
246   Value *PtrArg = nullptr;
247   if (auto *BI = dyn_cast<BitCastInst>(II->getArgOperand(0)))
248     PtrArg = BI->getOperand(0);
249   else
250     PtrArg = II->getOperand(0);
251   std::string Anno =
252       getAnnotation(II->getArgOperand(1),
253                     4 < II->arg_size() ? II->getArgOperand(4) : nullptr);
254 
255   // Parse the annotation.
256   SmallVector<Metadata *> MDs = parseAnnotation(II, Anno, Ctx, Int32Ty);
257 
258   // If the annotation string is not parsed successfully we don't know the
259   // format used and output it as a general UserSemantic decoration.
260   // Otherwise MDs is a Metadata tuple (a decoration list) in the format
261   // expected by `spirv.Decorations`.
262   if (MDs.size() == 0) {
263     auto UserSemantic = ConstantAsMetadata::get(ConstantInt::get(
264         Int32Ty, static_cast<uint32_t>(SPIRV::Decoration::UserSemantic)));
265     MDs.push_back(MDNode::get(Ctx, {UserSemantic, MDString::get(Ctx, Anno)}));
266   }
267 
268   // Build the internal intrinsic function.
269   IRBuilder<> IRB(II->getParent());
270   IRB.SetInsertPoint(II);
271   IRB.CreateIntrinsic(
272       Intrinsic::spv_assign_decoration, {PtrArg->getType()},
273       {PtrArg, MetadataAsValue::get(Ctx, MDNode::get(Ctx, MDs))});
274   II->replaceAllUsesWith(II->getOperand(0));
275 }
276 
lowerFunnelShifts(IntrinsicInst * FSHIntrinsic)277 static void lowerFunnelShifts(IntrinsicInst *FSHIntrinsic) {
278   // Get a separate function - otherwise, we'd have to rework the CFG of the
279   // current one. Then simply replace the intrinsic uses with a call to the new
280   // function.
281   // Generate LLVM IR for  i* @spirv.llvm_fsh?_i* (i* %a, i* %b, i* %c)
282   Module *M = FSHIntrinsic->getModule();
283   FunctionType *FSHFuncTy = FSHIntrinsic->getFunctionType();
284   Type *FSHRetTy = FSHFuncTy->getReturnType();
285   const std::string FuncName = lowerLLVMIntrinsicName(FSHIntrinsic);
286   Function *FSHFunc =
287       getOrCreateFunction(M, FSHRetTy, FSHFuncTy->params(), FuncName);
288 
289   if (!FSHFunc->empty()) {
290     FSHIntrinsic->setCalledFunction(FSHFunc);
291     return;
292   }
293   BasicBlock *RotateBB = BasicBlock::Create(M->getContext(), "rotate", FSHFunc);
294   IRBuilder<> IRB(RotateBB);
295   Type *Ty = FSHFunc->getReturnType();
296   // Build the actual funnel shift rotate logic.
297   // In the comments, "int" is used interchangeably with "vector of int
298   // elements".
299   FixedVectorType *VectorTy = dyn_cast<FixedVectorType>(Ty);
300   Type *IntTy = VectorTy ? VectorTy->getElementType() : Ty;
301   unsigned BitWidth = IntTy->getIntegerBitWidth();
302   ConstantInt *BitWidthConstant = IRB.getInt({BitWidth, BitWidth});
303   Value *BitWidthForInsts =
304       VectorTy
305           ? IRB.CreateVectorSplat(VectorTy->getNumElements(), BitWidthConstant)
306           : BitWidthConstant;
307   Value *RotateModVal =
308       IRB.CreateURem(/*Rotate*/ FSHFunc->getArg(2), BitWidthForInsts);
309   Value *FirstShift = nullptr, *SecShift = nullptr;
310   if (FSHIntrinsic->getIntrinsicID() == Intrinsic::fshr) {
311     // Shift the less significant number right, the "rotate" number of bits
312     // will be 0-filled on the left as a result of this regular shift.
313     FirstShift = IRB.CreateLShr(FSHFunc->getArg(1), RotateModVal);
314   } else {
315     // Shift the more significant number left, the "rotate" number of bits
316     // will be 0-filled on the right as a result of this regular shift.
317     FirstShift = IRB.CreateShl(FSHFunc->getArg(0), RotateModVal);
318   }
319   // We want the "rotate" number of the more significant int's LSBs (MSBs) to
320   // occupy the leftmost (rightmost) "0 space" left by the previous operation.
321   // Therefore, subtract the "rotate" number from the integer bitsize...
322   Value *SubRotateVal = IRB.CreateSub(BitWidthForInsts, RotateModVal);
323   if (FSHIntrinsic->getIntrinsicID() == Intrinsic::fshr) {
324     // ...and left-shift the more significant int by this number, zero-filling
325     // the LSBs.
326     SecShift = IRB.CreateShl(FSHFunc->getArg(0), SubRotateVal);
327   } else {
328     // ...and right-shift the less significant int by this number, zero-filling
329     // the MSBs.
330     SecShift = IRB.CreateLShr(FSHFunc->getArg(1), SubRotateVal);
331   }
332   // A simple binary addition of the shifted ints yields the final result.
333   IRB.CreateRet(IRB.CreateOr(FirstShift, SecShift));
334 
335   FSHIntrinsic->setCalledFunction(FSHFunc);
336 }
337 
lowerExpectAssume(IntrinsicInst * II)338 static void lowerExpectAssume(IntrinsicInst *II) {
339   // If we cannot use the SPV_KHR_expect_assume extension, then we need to
340   // ignore the intrinsic and move on. It should be removed later on by LLVM.
341   // Otherwise we should lower the intrinsic to the corresponding SPIR-V
342   // instruction.
343   // For @llvm.assume we have OpAssumeTrueKHR.
344   // For @llvm.expect we have OpExpectKHR.
345   //
346   // We need to lower this into a builtin and then the builtin into a SPIR-V
347   // instruction.
348   if (II->getIntrinsicID() == Intrinsic::assume) {
349     Function *F = Intrinsic::getOrInsertDeclaration(
350         II->getModule(), Intrinsic::SPVIntrinsics::spv_assume);
351     II->setCalledFunction(F);
352   } else if (II->getIntrinsicID() == Intrinsic::expect) {
353     Function *F = Intrinsic::getOrInsertDeclaration(
354         II->getModule(), Intrinsic::SPVIntrinsics::spv_expect,
355         {II->getOperand(0)->getType()});
356     II->setCalledFunction(F);
357   } else {
358     llvm_unreachable("Unknown intrinsic");
359   }
360 }
361 
toSpvOverloadedIntrinsic(IntrinsicInst * II,Intrinsic::ID NewID,ArrayRef<unsigned> OpNos)362 static bool toSpvOverloadedIntrinsic(IntrinsicInst *II, Intrinsic::ID NewID,
363                                      ArrayRef<unsigned> OpNos) {
364   Function *F = nullptr;
365   if (OpNos.empty()) {
366     F = Intrinsic::getOrInsertDeclaration(II->getModule(), NewID);
367   } else {
368     SmallVector<Type *, 4> Tys;
369     for (unsigned OpNo : OpNos)
370       Tys.push_back(II->getOperand(OpNo)->getType());
371     F = Intrinsic::getOrInsertDeclaration(II->getModule(), NewID, Tys);
372   }
373   II->setCalledFunction(F);
374   return true;
375 }
376 
377 // Substitutes calls to LLVM intrinsics with either calls to SPIR-V intrinsics
378 // or calls to proper generated functions. Returns True if F was modified.
substituteIntrinsicCalls(Function * F)379 bool SPIRVPrepareFunctions::substituteIntrinsicCalls(Function *F) {
380   bool Changed = false;
381   const SPIRVSubtarget &STI = TM.getSubtarget<SPIRVSubtarget>(*F);
382   for (BasicBlock &BB : *F) {
383     for (Instruction &I : BB) {
384       auto Call = dyn_cast<CallInst>(&I);
385       if (!Call)
386         continue;
387       Function *CF = Call->getCalledFunction();
388       if (!CF || !CF->isIntrinsic())
389         continue;
390       auto *II = cast<IntrinsicInst>(Call);
391       switch (II->getIntrinsicID()) {
392       case Intrinsic::memset:
393       case Intrinsic::bswap:
394         Changed |= lowerIntrinsicToFunction(II);
395         break;
396       case Intrinsic::fshl:
397       case Intrinsic::fshr:
398         lowerFunnelShifts(II);
399         Changed = true;
400         break;
401       case Intrinsic::assume:
402       case Intrinsic::expect:
403         if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
404           lowerExpectAssume(II);
405         Changed = true;
406         break;
407       case Intrinsic::lifetime_start:
408         if (!STI.isShader()) {
409           Changed |= toSpvOverloadedIntrinsic(
410               II, Intrinsic::SPVIntrinsics::spv_lifetime_start, {1});
411         }
412         break;
413       case Intrinsic::lifetime_end:
414         if (!STI.isShader()) {
415           Changed |= toSpvOverloadedIntrinsic(
416               II, Intrinsic::SPVIntrinsics::spv_lifetime_end, {1});
417         }
418         break;
419       case Intrinsic::ptr_annotation:
420         lowerPtrAnnotation(II);
421         Changed = true;
422         break;
423       }
424     }
425   }
426   return Changed;
427 }
428 
429 // Returns F if aggregate argument/return types are not present or cloned F
430 // function with the types replaced by i32 types. The change in types is
431 // noted in 'spv.cloned_funcs' metadata for later restoration.
432 Function *
removeAggregateTypesFromSignature(Function * F)433 SPIRVPrepareFunctions::removeAggregateTypesFromSignature(Function *F) {
434   bool IsRetAggr = F->getReturnType()->isAggregateType();
435   // Allow intrinsics with aggregate return type to reach GlobalISel
436   if (F->isIntrinsic() && IsRetAggr)
437     return F;
438 
439   IRBuilder<> B(F->getContext());
440 
441   bool HasAggrArg = llvm::any_of(F->args(), [](Argument &Arg) {
442     return Arg.getType()->isAggregateType();
443   });
444   bool DoClone = IsRetAggr || HasAggrArg;
445   if (!DoClone)
446     return F;
447   SmallVector<std::pair<int, Type *>, 4> ChangedTypes;
448   Type *RetType = IsRetAggr ? B.getInt32Ty() : F->getReturnType();
449   if (IsRetAggr)
450     ChangedTypes.push_back(std::pair<int, Type *>(-1, F->getReturnType()));
451   SmallVector<Type *, 4> ArgTypes;
452   for (const auto &Arg : F->args()) {
453     if (Arg.getType()->isAggregateType()) {
454       ArgTypes.push_back(B.getInt32Ty());
455       ChangedTypes.push_back(
456           std::pair<int, Type *>(Arg.getArgNo(), Arg.getType()));
457     } else
458       ArgTypes.push_back(Arg.getType());
459   }
460   FunctionType *NewFTy =
461       FunctionType::get(RetType, ArgTypes, F->getFunctionType()->isVarArg());
462   Function *NewF =
463       Function::Create(NewFTy, F->getLinkage(), F->getName(), *F->getParent());
464 
465   ValueToValueMapTy VMap;
466   auto NewFArgIt = NewF->arg_begin();
467   for (auto &Arg : F->args()) {
468     StringRef ArgName = Arg.getName();
469     NewFArgIt->setName(ArgName);
470     VMap[&Arg] = &(*NewFArgIt++);
471   }
472   SmallVector<ReturnInst *, 8> Returns;
473 
474   CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
475                     Returns);
476   NewF->takeName(F);
477 
478   NamedMDNode *FuncMD =
479       F->getParent()->getOrInsertNamedMetadata("spv.cloned_funcs");
480   SmallVector<Metadata *, 2> MDArgs;
481   MDArgs.push_back(MDString::get(B.getContext(), NewF->getName()));
482   for (auto &ChangedTyP : ChangedTypes)
483     MDArgs.push_back(MDNode::get(
484         B.getContext(),
485         {ConstantAsMetadata::get(B.getInt32(ChangedTyP.first)),
486          ValueAsMetadata::get(Constant::getNullValue(ChangedTyP.second))}));
487   MDNode *ThisFuncMD = MDNode::get(B.getContext(), MDArgs);
488   FuncMD->addOperand(ThisFuncMD);
489 
490   for (auto *U : make_early_inc_range(F->users())) {
491     if (auto *CI = dyn_cast<CallInst>(U))
492       CI->mutateFunctionType(NewF->getFunctionType());
493     U->replaceUsesOfWith(F, NewF);
494   }
495 
496   // register the mutation
497   if (RetType != F->getReturnType())
498     TM.getSubtarget<SPIRVSubtarget>(*F).getSPIRVGlobalRegistry()->addMutated(
499         NewF, F->getReturnType());
500   return NewF;
501 }
502 
runOnModule(Module & M)503 bool SPIRVPrepareFunctions::runOnModule(Module &M) {
504   bool Changed = false;
505   for (Function &F : M) {
506     Changed |= substituteIntrinsicCalls(&F);
507     Changed |= sortBlocks(F);
508   }
509 
510   std::vector<Function *> FuncsWorklist;
511   for (auto &F : M)
512     FuncsWorklist.push_back(&F);
513 
514   for (auto *F : FuncsWorklist) {
515     Function *NewF = removeAggregateTypesFromSignature(F);
516 
517     if (NewF != F) {
518       F->eraseFromParent();
519       Changed = true;
520     }
521   }
522   return Changed;
523 }
524 
525 ModulePass *
createSPIRVPrepareFunctionsPass(const SPIRVTargetMachine & TM)526 llvm::createSPIRVPrepareFunctionsPass(const SPIRVTargetMachine &TM) {
527   return new SPIRVPrepareFunctions(TM);
528 }
529