41 StringRef GetImageSizeFunc =
"llvm.OpenCL.image.get.size";
42 StringRef GetImageFormatFunc =
"llvm.OpenCL.image.get.format";
43 StringRef GetImageResourceIDFunc =
"llvm.OpenCL.image.get.resource.id";
44 StringRef GetSamplerResourceIDFunc =
"llvm.OpenCL.sampler.get.resource.id";
46 StringRef ImageSizeArgMDType =
"__llvm_image_size";
47 StringRef ImageFormatArgMDType =
"__llvm_image_format";
49 StringRef KernelsMDNodeName =
"opencl.kernels";
51 "kernel_arg_addr_space",
52 "kernel_arg_access_qual",
54 "kernel_arg_base_type",
55 "kernel_arg_type_qual"};
56 const unsigned NumKernelArgMDNodes = 5;
60 MDVector ArgVector[NumKernelArgMDNodes];
67 return TypeString ==
"image2d_t" || TypeString ==
"image3d_t";
72 return TypeString ==
"sampler_t";
81 if (NumOps != NumKernelArgMDNodes + 1)
84 auto F = mdconst::dyn_extract<Function>(Node->
getOperand(0));
89 size_t ExpectNumArgNodeOps =
F->arg_size() + 1;
90 for (
size_t i = 0;
i < NumKernelArgMDNodes; ++
i) {
100 if (!StringNode || StringNode->
getString() != KernelArgMDNodeNames[
i])
110 return cast<MDString>(ArgAQNode->
getOperand(ArgIdx + 1))->getString();
116 return cast<MDString>(ArgTypeNode->
getOperand(ArgIdx + 1))->getString();
122 for (
unsigned i = 0;
i < NumKernelArgMDNodes; ++
i) {
131 assert(V.size() == NumKernelArgMDNodes);
132 for (
unsigned i = 0;
i < NumKernelArgMDNodes; ++
i) {
133 MD.ArgVector[
i].push_back(V[
i]);
139 class AMDGPUOpenCLImageTypeLoweringPass :
public ModulePass {
145 Type *ImageFormatType;
151 bool Modified =
false;
153 for (
auto &
Use : ImageArg.
uses()) {
163 Value *Replacement =
nullptr;
165 if (Name.
startswith(GetImageResourceIDFunc)) {
167 }
else if (Name.
startswith(GetImageSizeFunc)) {
168 Replacement = &ImageSizeArg;
169 }
else if (Name.
startswith(GetImageFormatFunc)) {
170 Replacement = &ImageFormatArg;
176 InstsToErase.push_back(Inst);
184 bool Modified =
false;
186 for (
const auto &
Use : SamplerArg.
uses()) {
192 Function *F = Inst->getCalledFunction();
196 Value *Replacement =
nullptr;
198 if (Name == GetSamplerResourceIDFunc) {
204 Inst->replaceAllUsesWith(Replacement);
205 InstsToErase.push_back(Inst);
212 bool replaceImageAndSamplerUses(
Function *F,
MDNode *KernelMDNode) {
217 bool Modified =
false;
218 InstsToErase.clear();
227 if (AccessQual ==
"read_only") {
228 ResourceID = NumReadOnlyImageArgs++;
229 }
else if (AccessQual ==
"write_only") {
230 ResourceID = NumWriteOnlyImageArgs++;
237 Modified |= replaceImageUses(Arg, ResourceID, SizeArg, FormatArg);
241 uint32_t ResourceID = NumSamplerArgs++;
242 Modified |= replaceSamplerUses(Arg, ResourceID);
245 for (
unsigned i = 0;
i < InstsToErase.size(); ++
i) {
246 InstsToErase[
i]->eraseFromParent();
252 std::tuple<Function *, MDNode *>
254 bool Modified =
false;
260 KernelArgMD NewArgMDs;
266 MDVector ArgMD =
GetArgMD(KernelMDNode,
i + 1);
285 return std::make_tuple(
nullptr,
nullptr);
292 auto NewFArgIt = NewF->arg_begin();
293 for (
auto &Arg: F->
args()) {
296 VMap[&Arg] = &(*NewFArgIt++);
308 for (
unsigned i = 0;
i < NumKernelArgMDNodes; ++
i)
312 return std::make_tuple(NewF, NewMDNode);
315 bool transformKernels(
Module &M) {
320 bool Modified =
false;
329 std::tie(NewF, NewMDNode) = addImplicitArgs(F, KernelMDNode);
339 KernelMDNode = NewMDNode;
343 Modified |= replaceImageAndSamplerUses(F, KernelMDNode);
352 bool runOnModule(
Module &M)
override {
358 return transformKernels(M);
362 return "AMDGPU OpenCL Image Type Pass";
371 return new AMDGPUOpenCLImageTypeLoweringPass();
void push_back(const T &Elt)
LinkageTypes getLinkage() const
iterator_range< use_iterator > uses()
LLVM Argument representation.
static bool IsImageType(StringRef TypeString)
A Module instance is used to store all the information related to an LLVM module. ...
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
static MDString * get(LLVMContext &Context, StringRef Str)
unsigned getNumOperands() const
Return number of MDNode operands.
static StringRef AccessQualFromMD(MDNode *KernelMDNode, unsigned ArgIdx)
This class represents a function call, abstracting a target machine's calling convention.
void setOperand(unsigned I, MDNode *New)
StringRef getName() const
Return a constant reference to the value's name.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
A Use represents the edge between a Value definition and its users.
void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap, bool ModuleLevelChanges, 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...
Class to represent function types.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
static MDVector GetArgMD(MDNode *KernelMDNode, unsigned OpIdx)
Type * getParamType(unsigned i) const
Parameter type accessors.
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
Look up the specified function in the module symbol table.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
MDNode * getOperand(unsigned i) const
User * getUser() const
Returns the User that contains this Use.
static Function * GetFunctionFromMDNode(MDNode *Node)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
StringRef getString() const
const MDOperand & getOperand(unsigned I) const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
AttributeSet getAttributes() const
Return the attribute list for this Function.
void push_back(pointer val)
static StringRef ArgTypeFromMD(MDNode *KernelMDNode, unsigned ArgIdx)
void eraseFromParent() override
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
static void PushArgMD(KernelArgMD &MD, const MDVector &V)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
static IntegerType * getInt32Ty(LLVMContext &C)
FunctionType * getFunctionType() const
Returns the FunctionType for me.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
static bool IsSamplerType(StringRef TypeString)
Type * getReturnType() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
unsigned getArgNo() const
Return the index of this formal argument in its containing function.
unsigned getNumOperands() const
StringRef - Represent a constant reference to a string, i.e.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=nullptr)
ModulePass * createAMDGPUOpenCLImageTypeLoweringPass()
iterator_range< arg_iterator > args()
LLVMContext & getContext() const
Get the global data context.