35class SPIRVPrepareFunctions :
public ModulePass {
55char SPIRVPrepareFunctions::ID = 0;
58 "SPIRV prepare functions",
false,
false)
63 bool IsRetAggr =
F->getReturnType()->isAggregateType();
66 return Arg.getType()->isAggregateType();
68 bool DoClone = IsRetAggr || HasAggrArg;
72 Type *RetType = IsRetAggr ?
B.getInt32Ty() :
F->getReturnType();
74 ChangedTypes.
push_back(std::pair<int, Type *>(-1,
F->getReturnType()));
76 for (
const auto &
Arg :
F->args()) {
77 if (
Arg.getType()->isAggregateType()) {
80 std::pair<int, Type *>(
Arg.getArgNo(),
Arg.getType()));
85 FunctionType::get(RetType, ArgTypes,
F->getFunctionType()->isVarArg());
91 for (
auto &
Arg :
F->args()) {
93 NewFArgIt->setName(ArgName);
94 VMap[&
Arg] = &(*NewFArgIt++);
103 F->getParent()->getOrInsertNamedMetadata(
"spv.cloned_funcs");
106 for (
auto &ChangedTyP : ChangedTypes)
109 {ConstantAsMetadata::get(B.getInt32(ChangedTyP.first)),
110 ValueAsMetadata::get(Constant::getNullValue(ChangedTyP.second))}));
115 if (
auto *CI = dyn_cast<CallInst>(U))
117 U->replaceUsesOfWith(
F, NewF);
124 assert(IntrinsicFunc &&
"Missing function");
125 std::string FuncName = IntrinsicFunc->
getName().
str();
126 std::replace(FuncName.begin(), FuncName.end(),
'.',
'_');
127 FuncName =
"spirv." + FuncName;
136 if (
F &&
F->getFunctionType() == FT)
150 if (
auto *MSI = dyn_cast<MemSetInst>(Intrinsic))
151 if (isa<Constant>(MSI->getValue()) && isa<ConstantInt>(MSI->getLength()))
155 if (Intrinsic->isVolatile())
156 FuncName +=
".volatile";
160 Intrinsic->setCalledFunction(
F);
165 M->getOrInsertFunction(FuncName, Intrinsic->getFunctionType());
166 auto IntrinsicID = Intrinsic->getIntrinsicID();
167 Intrinsic->setCalledFunction(FC);
169 F = dyn_cast<Function>(FC.getCallee());
170 assert(
F &&
"Callee must be a function");
172 switch (IntrinsicID) {
173 case Intrinsic::memset: {
174 auto *MSI =
static_cast<MemSetInst *
>(Intrinsic);
182 IsVolatile->setName(
"isvolatile");
185 auto *MemSet = IRB.
CreateMemSet(Dest, Val, Len, MSI->getDestAlign(),
189 MemSet->eraseFromParent();
192 case Intrinsic::bswap: {
195 auto *BSwap = IRB.
CreateIntrinsic(Intrinsic::bswap, Intrinsic->getType(),
214 Type *FSHRetTy = FSHFuncTy->getReturnType();
219 if (!FSHFunc->
empty()) {
233 Value *BitWidthForInsts =
237 Value *RotateModVal =
239 Value *FirstShift =
nullptr, *SecShift =
nullptr;
252 Value *SubRotateVal = IRB.
CreateSub(BitWidthForInsts, RotateModVal);
270 if (!UMulFunc->
empty())
296 Type *FSHLRetTy = UMulFuncTy->getReturnType();
307 auto Call = dyn_cast<CallInst>(&
I);
310 Call->setTailCall(
false);
311 Function *CF = Call->getCalledFunction();
314 auto *II = cast<IntrinsicInst>(Call);
315 if (II->getIntrinsicID() == Intrinsic::memset ||
316 II->getIntrinsicID() == Intrinsic::bswap)
318 else if (II->getIntrinsicID() == Intrinsic::fshl ||
319 II->getIntrinsicID() == Intrinsic::fshr)
321 else if (II->getIntrinsicID() == Intrinsic::umul_with_overflow)
327bool SPIRVPrepareFunctions::runOnModule(
Module &M) {
331 std::vector<Function *> FuncsWorklist;
332 bool Changed =
false;
334 FuncsWorklist.push_back(&
F);
336 for (
auto *Func : FuncsWorklist) {
337 Function *
F = processFunctionSignature(Func);
339 bool CreatedNewF =
F !=
Func;
341 if (
Func->isDeclaration()) {
342 Changed |= CreatedNewF;
347 Func->eraseFromParent();
354 return new SPIRVPrepareFunctions();
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void lowerIntrinsicToFunction(Module *M, IntrinsicInst *Intrinsic)
static void lowerUMulWithOverflow(Module *M, IntrinsicInst *UMulIntrinsic)
std::string lowerLLVMIntrinsicName(IntrinsicInst *II)
static void substituteIntrinsicCalls(Module *M, Function *F)
static void buildUMulWithOverflowFunc(Module *M, Function *UMulFunc)
static void lowerFunnelShifts(Module *M, IntrinsicInst *FSHIntrinsic)
static Function * getOrCreateFunction(Module *M, Type *RetTy, ArrayRef< Type * > ArgTypes, StringRef Name)
Represent the analysis usage information of a pass.
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
FunctionType * getFunctionType() const
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
This is the shared class of boolean and integer constants.
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 Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Type * getReturnType() const
Returns the type of the ret val.
void setCallingConv(CallingConv::ID CC)
Argument * getArg(unsigned i) const
void setDSOLocal(bool Local)
@ ExternalLinkage
Externally visible function.
Value * CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name="")
Return a vector value that contains.
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, Instruction *FMFSource=nullptr, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memset to the specified pointer and the specified value.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
ReturnInst * CreateRet(Value *V)
Create a 'ret <val>' instruction.
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
ReturnInst * CreateRetVoid()
Create a 'ret void' instruction.
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
ConstantInt * getInt(const APInt &AI)
Get a constant integer value.
Value * CreateURem(Value *LHS, Value *RHS, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
void LowerIntrinsicCall(CallInst *CI)
Replace a call to the specified intrinsic function.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDString * get(LLVMContext &Context, StringRef Str)
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
void addOperand(MDNode *M)
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
LLVM Value Representation.
void setName(const Twine &Name)
Change the name of the value.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
Type * getElementType() const
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ SPIR_FUNC
Used for SPIR non-kernel device functions.
This is an optimization pass for GlobalISel generic memory operations.
void initializeSPIRVPrepareFunctionsPass(PassRegistry &)
ModulePass * createSPIRVPrepareFunctionsPass()
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...
constexpr unsigned BitWidth
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.
void expandMemSetAsLoop(MemSetInst *MemSet)
Expand MemSet as a loop. MemSet is not deleted.