[llvm] [PATCH] AMDGPU: Add pass to lower OpenCL image and sampler arguments.
Zoltán Gilián
zoltan.gilian at gmail.com
Mon Aug 3 08:50:59 PDT 2015
Ping.
Note: clover-side of this functionality has already been reviewed.
On Mon, Jul 27, 2015 at 2:11 PM, Zoltan Gilian <zoltan.gilian at gmail.com> wrote:
> The pass adds new kernel arguments for image attributes, and
> resolves calls to dummy attribute and resource id getter functions.
> ---
> lib/Target/AMDGPU/AMDGPU.h | 1 +
> .../AMDGPU/AMDGPUOpenCLImageTypeLoweringPass.cpp | 369 +++++++++++++++++++
> lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 2 +
> test/CodeGen/AMDGPU/image-attributes.ll | 206 +++++++++++
> test/CodeGen/AMDGPU/image-resource-id.ll | 409 +++++++++++++++++++++
> test/CodeGen/AMDGPU/sampler-resource-id.ll | 65 ++++
> 6 files changed, 1052 insertions(+)
> create mode 100644 lib/Target/AMDGPU/AMDGPUOpenCLImageTypeLoweringPass.cpp
> create mode 100644 test/CodeGen/AMDGPU/image-attributes.ll
> create mode 100644 test/CodeGen/AMDGPU/image-resource-id.ll
> create mode 100644 test/CodeGen/AMDGPU/sampler-resource-id.ll
>
> diff --git a/lib/Target/AMDGPU/AMDGPU.h b/lib/Target/AMDGPU/AMDGPU.h
> index 0a05d25..33026f5 100644
> --- a/lib/Target/AMDGPU/AMDGPU.h
> +++ b/lib/Target/AMDGPU/AMDGPU.h
> @@ -64,6 +64,7 @@ FunctionPass *createAMDGPUPromoteAlloca(const AMDGPUSubtarget &ST);
> Pass *createAMDGPUStructurizeCFGPass();
> FunctionPass *createAMDGPUISelDag(TargetMachine &tm);
> ModulePass *createAMDGPUAlwaysInlinePass();
> +ModulePass *createAMDGPUOpenCLImageTypeLoweringPass();
>
> void initializeSIFixControlFlowLiveIntervalsPass(PassRegistry&);
> extern char &SIFixControlFlowLiveIntervalsID;
> diff --git a/lib/Target/AMDGPU/AMDGPUOpenCLImageTypeLoweringPass.cpp b/lib/Target/AMDGPU/AMDGPUOpenCLImageTypeLoweringPass.cpp
> new file mode 100644
> index 0000000..086493b
> --- /dev/null
> +++ b/lib/Target/AMDGPU/AMDGPUOpenCLImageTypeLoweringPass.cpp
> @@ -0,0 +1,369 @@
> +//===-- AMDGPUOpenCLImageTypeLoweringPass.cpp -----------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +/// \file
> +/// This pass resolves calls to OpenCL image attribute, image resource ID and
> +/// sampler resource ID getter functions.
> +///
> +/// Image attributes (size and format) are expected to be passed to the kernel
> +/// as kernel arguments immediately following the image argument itself,
> +/// therefore this pass adds image size and format arguments to the kernel
> +/// functions in the module. The kernel functions with image arguments are
> +/// re-created using the new signature. The new arguments are added to the
> +/// kernel metadata with kernel_arg_type set to "image_size" or "image_format".
> +/// Note: this pass may invalidate pointers to functions.
> +///
> +/// Resource IDs of read-only images, write-only images and samplers are
> +/// defined to be their index among the kernel arguments of the same
> +/// type and access qualifier.
> +//===----------------------------------------------------------------------===//
> +
> +#include "AMDGPU.h"
> +#include "llvm/ADT/DenseSet.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/ADT/SmallVector.h"
> +#include "llvm/Analysis/Passes.h"
> +#include "llvm/IR/Constants.h"
> +#include "llvm/IR/Function.h"
> +#include "llvm/IR/Instructions.h"
> +#include "llvm/IR/Module.h"
> +#include "llvm/Transforms/Utils/Cloning.h"
> +
> +using namespace llvm;
> +
> +namespace {
> +
> +StringRef GetImageSizeFunc = "llvm.OpenCL.image.get.size";
> +StringRef GetImageFormatFunc = "llvm.OpenCL.image.get.format";
> +StringRef GetImageResourceIDFunc = "llvm.OpenCL.image.get.resource.id";
> +StringRef GetSamplerResourceIDFunc = "llvm.OpenCL.sampler.get.resource.id";
> +
> +StringRef ImageSizeArgMDType = "__llvm_image_size";
> +StringRef ImageFormatArgMDType = "__llvm_image_format";
> +
> +StringRef KernelsMDNodeName = "opencl.kernels";
> +StringRef KernelArgMDNodeNames[] = {
> + "kernel_arg_addr_space",
> + "kernel_arg_access_qual",
> + "kernel_arg_type",
> + "kernel_arg_base_type",
> + "kernel_arg_type_qual"};
> +constexpr unsigned NumKernelArgMDNodes = array_lengthof(KernelArgMDNodeNames);
> +
> +typedef SmallVector<Metadata *, 8> MDVector;
> +struct KernelArgMD {
> + MDVector ArgVector[NumKernelArgMDNodes];
> +};
> +
> +} // end anonymous namespace
> +
> +static inline bool
> +IsImageType(StringRef TypeString) {
> + return TypeString == "image2d_t" || TypeString == "image3d_t";
> +}
> +
> +static inline bool
> +IsSamplerType(StringRef TypeString) {
> + return TypeString == "sampler_t";
> +}
> +
> +static Function *
> +GetFunctionFromMDNode(MDNode *Node) {
> + if (!Node)
> + return nullptr;
> +
> + size_t NumOps = Node->getNumOperands();
> + if (NumOps != NumKernelArgMDNodes + 1)
> + return nullptr;
> +
> + auto F = mdconst::dyn_extract<Function>(Node->getOperand(0));
> + if (!F)
> + return nullptr;
> +
> + // Sanity checks.
> + size_t ExpectNumArgNodeOps = F->arg_size() + 1;
> + for (size_t i = 0; i < NumKernelArgMDNodes; ++i) {
> + MDNode *ArgNode = dyn_cast_or_null<MDNode>(Node->getOperand(i + 1));
> + if (ArgNode->getNumOperands() != ExpectNumArgNodeOps)
> + return nullptr;
> + if (!ArgNode->getOperand(0))
> + return nullptr;
> + assert(cast<MDString>(ArgNode->getOperand(0))->getString() ==
> + KernelArgMDNodeNames[i] && "Wrong kernel arg metadata name");
> + }
> +
> + return F;
> +}
> +
> +static StringRef
> +AccessQualFromMD(MDNode *KernelMDNode, unsigned ArgIdx) {
> + MDNode *ArgAQNode = cast<MDNode>(KernelMDNode->getOperand(2));
> + return cast<MDString>(ArgAQNode->getOperand(ArgIdx + 1))->getString();
> +}
> +
> +static StringRef
> +ArgTypeFromMD(MDNode *KernelMDNode, unsigned ArgIdx) {
> + MDNode *ArgTypeNode = cast<MDNode>(KernelMDNode->getOperand(3));
> + return cast<MDString>(ArgTypeNode->getOperand(ArgIdx + 1))->getString();
> +}
> +
> +static MDVector
> +GetArgMD(MDNode *KernelMDNode, unsigned OpIdx) {
> + MDVector Res;
> + for (unsigned i = 0; i < NumKernelArgMDNodes; ++i) {
> + MDNode *Node = cast<MDNode>(KernelMDNode->getOperand(i + 1));
> + Res.push_back(Node->getOperand(OpIdx));
> + }
> + return Res;
> +}
> +
> +static void
> +PushArgMD(KernelArgMD &MD, const MDVector &V) {
> + assert(V.size() == NumKernelArgMDNodes);
> + for (unsigned i = 0; i < NumKernelArgMDNodes; ++i) {
> + MD.ArgVector[i].push_back(V[i]);
> + }
> +}
> +
> +namespace {
> +
> +class AMDGPUOpenCLImageTypeLoweringPass : public ModulePass {
> + static char ID;
> +
> + LLVMContext *Context;
> + Type *Int32Type;
> + Type *ImageSizeType;
> + Type *ImageFormatType;
> + SmallVector<Instruction *, 4> InstsToErase;
> +
> + bool replaceImageUses(Argument &ImageArg, uint32_t ResourceID,
> + Argument &ImageSizeArg,
> + Argument &ImageFormatArg) {
> + bool Modified = false;
> +
> + for (auto &Use : ImageArg.uses()) {
> + auto Inst = dyn_cast<CallInst>(Use.getUser());
> + if (!Inst) {
> + continue;
> + }
> +
> + Function *F = Inst->getCalledFunction();
> + if (!F)
> + continue;
> +
> + Value *Replacement = nullptr;
> + StringRef Name = F->getName();
> + if (Name.startswith(GetImageResourceIDFunc)) {
> + Replacement = ConstantInt::get(Int32Type, ResourceID);
> + } else if (Name.startswith(GetImageSizeFunc)) {
> + Replacement = &ImageSizeArg;
> + } else if (Name.startswith(GetImageFormatFunc)) {
> + Replacement = &ImageFormatArg;
> + } else {
> + continue;
> + }
> +
> + Inst->replaceAllUsesWith(Replacement);
> + InstsToErase.push_back(Inst);
> + Modified = true;
> + }
> +
> + return Modified;
> + }
> +
> + bool replaceSamplerUses(Argument &SamplerArg, uint32_t ResourceID) {
> + bool Modified = false;
> +
> + for (const auto &Use : SamplerArg.uses()) {
> + auto Inst = dyn_cast<CallInst>(Use.getUser());
> + if (!Inst) {
> + continue;
> + }
> +
> + Function *F = Inst->getCalledFunction();
> + if (!F)
> + continue;
> +
> + Value *Replacement = nullptr;
> + StringRef Name = F->getName();
> + if (Name == GetSamplerResourceIDFunc) {
> + Replacement = ConstantInt::get(Int32Type, ResourceID);
> + } else {
> + continue;
> + }
> +
> + Inst->replaceAllUsesWith(Replacement);
> + InstsToErase.push_back(Inst);
> + Modified = true;
> + }
> +
> + return Modified;
> + }
> +
> + bool replaceImageAndSamplerUses(Function *F, MDNode *KernelMDNode) {
> + uint32_t NumReadOnlyImageArgs = 0;
> + uint32_t NumWriteOnlyImageArgs = 0;
> + uint32_t NumSamplerArgs = 0;
> +
> + bool Modified = false;
> + InstsToErase.clear();
> + for (auto ArgI = F->arg_begin(); ArgI != F->arg_end(); ++ArgI) {
> + Argument &Arg = *ArgI;
> + StringRef Type = ArgTypeFromMD(KernelMDNode, Arg.getArgNo());
> +
> + // Handle image types.
> + if (IsImageType(Type)) {
> + StringRef AccessQual = AccessQualFromMD(KernelMDNode, Arg.getArgNo());
> + uint32_t ResourceID;
> + if (AccessQual == "read_only") {
> + ResourceID = NumReadOnlyImageArgs++;
> + } else if (AccessQual == "write_only") {
> + ResourceID = NumWriteOnlyImageArgs++;
> + } else {
> + llvm_unreachable("Wrong image access qualifier.");
> + }
> +
> + Argument &SizeArg = *(++ArgI);
> + Argument &FormatArg = *(++ArgI);
> + Modified |= replaceImageUses(Arg, ResourceID, SizeArg, FormatArg);
> +
> + // Handle sampler type.
> + } else if (IsSamplerType(Type)) {
> + uint32_t ResourceID = NumSamplerArgs++;
> + Modified |= replaceSamplerUses(Arg, ResourceID);
> + }
> + }
> + for (unsigned i = 0; i < InstsToErase.size(); ++i) {
> + InstsToErase[i]->eraseFromParent();
> + }
> +
> + return Modified;
> + }
> +
> + std::tuple<Function *, MDNode *>
> + addImplicitArgs(Function *F, MDNode *KernelMDNode) {
> + bool Modified = false;
> +
> + FunctionType *FT = F->getFunctionType();
> + SmallVector<Type *, 8> ArgTypes;
> +
> + // Metadata operands for new MDNode.
> + KernelArgMD NewArgMDs;
> + PushArgMD(NewArgMDs, GetArgMD(KernelMDNode, 0));
> +
> + // Add implicit arguments to the signature.
> + for (unsigned i = 0; i < FT->getNumParams(); ++i) {
> + ArgTypes.push_back(FT->getParamType(i));
> + MDVector ArgMD = GetArgMD(KernelMDNode, i + 1);
> + PushArgMD(NewArgMDs, ArgMD);
> +
> + if (!IsImageType(ArgTypeFromMD(KernelMDNode, i)))
> + continue;
> +
> + // Add size implicit argument.
> + ArgTypes.push_back(ImageSizeType);
> + ArgMD[2] = ArgMD[3] = MDString::get(*Context, ImageSizeArgMDType);
> + PushArgMD(NewArgMDs, ArgMD);
> +
> + // Add format implicit argument.
> + ArgTypes.push_back(ImageFormatType);
> + ArgMD[2] = ArgMD[3] = MDString::get(*Context, ImageFormatArgMDType);
> + PushArgMD(NewArgMDs, ArgMD);
> +
> + Modified = true;
> + }
> + if (!Modified) {
> + return std::make_tuple(nullptr, nullptr);
> + }
> +
> + // Create function with new signature and clone the old body into it.
> + auto NewFT = FunctionType::get(FT->getReturnType(), ArgTypes, false);
> + auto NewF = Function::Create(NewFT, F->getLinkage(), F->getName());
> + ValueToValueMapTy VMap;
> + auto NewFArgIt = NewF->arg_begin();
> + for (auto &Arg: F->args()) {
> + auto ArgName = Arg.getName();
> + NewFArgIt->setName(ArgName);
> + VMap[&Arg] = &(*NewFArgIt++);
> + if (IsImageType(ArgTypeFromMD(KernelMDNode, Arg.getArgNo()))) {
> + (NewFArgIt++)->setName(Twine("__size_") + ArgName);
> + (NewFArgIt++)->setName(Twine("__format_") + ArgName);
> + }
> + }
> + SmallVector<ReturnInst*, 8> Returns;
> + CloneFunctionInto(NewF, F, VMap, /*ModuleLevelChanges=*/false, Returns);
> +
> + // Build new MDNode.
> + SmallVector<llvm::Metadata *, 6> KernelMDArgs;
> + KernelMDArgs.push_back(ConstantAsMetadata::get(NewF));
> + for (unsigned i = 0; i < NumKernelArgMDNodes; ++i)
> + KernelMDArgs.push_back(MDNode::get(*Context, NewArgMDs.ArgVector[i]));
> + MDNode *NewMDNode = MDNode::get(*Context, KernelMDArgs);
> +
> + return std::make_tuple(NewF, NewMDNode);
> + }
> +
> + bool transformKernels(Module &M) {
> + NamedMDNode *KernelsMDNode = M.getNamedMetadata(KernelsMDNodeName);
> + if (!KernelsMDNode)
> + return false;
> +
> + bool Modified = false;
> + for (unsigned i = 0; i < KernelsMDNode->getNumOperands(); ++i) {
> + MDNode *KernelMDNode = KernelsMDNode->getOperand(i);
> + Function *F = GetFunctionFromMDNode(KernelMDNode);
> + if (!F)
> + continue;
> +
> + Function *NewF;
> + MDNode *NewMDNode;
> + std::tie(NewF, NewMDNode) = addImplicitArgs(F, KernelMDNode);
> + if (NewF) {
> + // Replace old function and metadata with new ones.
> + F->eraseFromParent();
> + M.getFunctionList().push_back(NewF);
> + M.getOrInsertFunction(NewF->getName(), NewF->getFunctionType(),
> + NewF->getAttributes());
> + KernelsMDNode->setOperand(i, NewMDNode);
> +
> + F = NewF;
> + KernelMDNode = NewMDNode;
> + Modified = true;
> + }
> +
> + Modified |= replaceImageAndSamplerUses(F, KernelMDNode);
> + }
> +
> + return Modified;
> + }
> +
> + public:
> + AMDGPUOpenCLImageTypeLoweringPass() : ModulePass(ID) {}
> +
> + bool runOnModule(Module &M) override {
> + Context = &M.getContext();
> + Int32Type = Type::getInt32Ty(M.getContext());
> + ImageSizeType = ArrayType::get(Int32Type, 3);
> + ImageFormatType = ArrayType::get(Int32Type, 2);
> +
> + return transformKernels(M);
> + }
> +
> + const char *getPassName() const override {
> + return "AMDGPU OpenCL Image Type Pass";
> + }
> +};
> +
> +char AMDGPUOpenCLImageTypeLoweringPass::ID = 0;
> +
> +} // end anonymous namespace
> +
> +ModulePass *llvm::createAMDGPUOpenCLImageTypeLoweringPass() {
> + return new AMDGPUOpenCLImageTypeLoweringPass();
> +}
> diff --git a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
> index 2297b52..9d82be6 100644
> --- a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
> +++ b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
> @@ -172,6 +172,8 @@ void AMDGPUPassConfig::addIRPasses() {
> // functions, then we will generate code for the first function
> // without ever running any passes on the second.
> addPass(createBarrierNoopPass());
> + // Handle uses of OpenCL image2d_t, image3d_t and sampler_t arguments.
> + addPass(createAMDGPUOpenCLImageTypeLoweringPass());
> TargetPassConfig::addIRPasses();
> }
>
> diff --git a/test/CodeGen/AMDGPU/image-attributes.ll b/test/CodeGen/AMDGPU/image-attributes.ll
> new file mode 100644
> index 0000000..7a5a734
> --- /dev/null
> +++ b/test/CodeGen/AMDGPU/image-attributes.ll
> @@ -0,0 +1,206 @@
> +; RUN: llc -march=r600 -mcpu=juniper < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
> +
> +; === WIDTH ==================================================================
> +; 9 implicit args = 9 dwords to first image argument.
> +; First width at dword index 9+1 -> KC0[2].Z
> +
> +; FUNC-LABEL: {{^}}width_2d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[2].Z
> +define void @width_2d (%opencl.image2d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [3 x i32] @llvm.OpenCL.image.get.size.2d(
> + %opencl.image2d_t addrspace(1)* %in) #0
> + %1 = extractvalue [3 x i32] %0, 0
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}width_3d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[2].Z
> +define void @width_3d (%opencl.image3d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [3 x i32] @llvm.OpenCL.image.get.size.3d(
> + %opencl.image3d_t addrspace(1)* %in) #0
> + %1 = extractvalue [3 x i32] %0, 0
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +; === HEIGHT =================================================================
> +; First height at dword index 9+2 -> KC0[2].W
> +
> +; FUNC-LABEL: {{^}}height_2d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[2].W
> +define void @height_2d (%opencl.image2d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [3 x i32] @llvm.OpenCL.image.get.size.2d(
> + %opencl.image2d_t addrspace(1)* %in) #0
> + %1 = extractvalue [3 x i32] %0, 1
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}height_3d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[2].W
> +define void @height_3d (%opencl.image3d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [3 x i32] @llvm.OpenCL.image.get.size.3d(
> + %opencl.image3d_t addrspace(1)* %in) #0
> + %1 = extractvalue [3 x i32] %0, 1
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +; === DEPTH ==================================================================
> +; First depth at dword index 9+3 -> KC0[3].X
> +
> +; FUNC-LABEL: {{^}}depth_3d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[3].X
> +define void @depth_3d (%opencl.image3d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [3 x i32] @llvm.OpenCL.image.get.size.3d(
> + %opencl.image3d_t addrspace(1)* %in) #0
> + %1 = extractvalue [3 x i32] %0, 2
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +; === CHANNEL DATA TYPE ======================================================
> +; First channel data type at dword index 9+4 -> KC0[3].Y
> +
> +; FUNC-LABEL: {{^}}data_type_2d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[3].Y
> +define void @data_type_2d (%opencl.image2d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [2 x i32] @llvm.OpenCL.image.get.format.2d(
> + %opencl.image2d_t addrspace(1)* %in) #0
> + %1 = extractvalue [2 x i32] %0, 0
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}data_type_3d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[3].Y
> +define void @data_type_3d (%opencl.image3d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [2 x i32] @llvm.OpenCL.image.get.format.3d(
> + %opencl.image3d_t addrspace(1)* %in) #0
> + %1 = extractvalue [2 x i32] %0, 0
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +; === CHANNEL ORDER ==========================================================
> +; First channel order at dword index 9+5 -> KC0[3].Z
> +
> +; FUNC-LABEL: {{^}}channel_order_2d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[3].Z
> +define void @channel_order_2d (%opencl.image2d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [2 x i32] @llvm.OpenCL.image.get.format.2d(
> + %opencl.image2d_t addrspace(1)* %in) #0
> + %1 = extractvalue [2 x i32] %0, 1
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}channel_order_3d:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[3].Z
> +define void @channel_order_3d (%opencl.image3d_t addrspace(1)* %in,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [2 x i32] @llvm.OpenCL.image.get.format.3d(
> + %opencl.image3d_t addrspace(1)* %in) #0
> + %1 = extractvalue [2 x i32] %0, 1
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +; === 2ND IMAGE ==============================================================
> +; 9 implicit args + 2 explicit args + 5 implicit args for 1st image argument
> +; = 16 dwords to 2nd image argument.
> +; Height of the second image is at 16+2 -> KC0[4].Z
> +;
> +; FUNC-LABEL: {{^}}image_arg_2nd:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], KC0[4].Z
> +define void @image_arg_2nd (%opencl.image3d_t addrspace(1)* %in1,
> + i32 %x,
> + %opencl.image2d_t addrspace(1)* %in2,
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call [3 x i32] @llvm.OpenCL.image.get.size.2d(
> + %opencl.image2d_t addrspace(1)* %in2) #0
> + %1 = extractvalue [3 x i32] %0, 1
> + store i32 %1, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +%opencl.image2d_t = type opaque
> +%opencl.image3d_t = type opaque
> +
> +declare [3 x i32] @llvm.OpenCL.image.get.size.2d(%opencl.image2d_t addrspace(1)*) #0
> +declare [3 x i32] @llvm.OpenCL.image.get.size.3d(%opencl.image3d_t addrspace(1)*) #0
> +declare [2 x i32] @llvm.OpenCL.image.get.format.2d(%opencl.image2d_t addrspace(1)*) #0
> +declare [2 x i32] @llvm.OpenCL.image.get.format.3d(%opencl.image3d_t addrspace(1)*) #0
> +
> +attributes #0 = { readnone }
> +
> +!opencl.kernels = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
> +!0 = !{void (%opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @width_2d,
> + !10, !20, !30, !40, !50}
> +!1 = !{void (%opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @width_3d,
> + !10, !21, !31, !41, !50}
> +!2 = !{void (%opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @height_2d,
> + !10, !20, !30, !40, !50}
> +!3 = !{void (%opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @height_3d,
> + !10, !21, !31, !41, !50}
> +!4 = !{void (%opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @depth_3d,
> + !10, !21, !31, !41, !50}
> +!5 = !{void (%opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @data_type_2d,
> + !10, !20, !30, !40, !50}
> +!6 = !{void (%opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @data_type_3d,
> + !10, !21, !31, !41, !50}
> +!7 = !{void (%opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @channel_order_2d,
> + !10, !20, !30, !40, !50}
> +!8 = !{void (%opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @channel_order_3d,
> + !10, !21, !31, !41, !50}
> +!9 = !{void (%opencl.image3d_t addrspace(1)*, i32, %opencl.image2d_t addrspace(1)*,
> + i32 addrspace(1)*)* @image_arg_2nd, !12, !22, !32, !42, !52}
> +
> +!10 = !{!"kernel_arg_addr_space", i32 1, i32 1}
> +!20 = !{!"kernel_arg_access_qual", !"read_only", !"none"}
> +!21 = !{!"kernel_arg_access_qual", !"read_only", !"none"}
> +!30 = !{!"kernel_arg_type", !"image2d_t", !"int*"}
> +!31 = !{!"kernel_arg_type", !"image3d_t", !"int*"}
> +!40 = !{!"kernel_arg_base_type", !"image2d_t", !"int*"}
> +!41 = !{!"kernel_arg_base_type", !"image3d_t", !"int*"}
> +!50 = !{!"kernel_arg_type_qual", !"", !""}
> +
> +!12 = !{!"kernel_arg_addr_space", i32 1, i32 0, i32 1, i32 1}
> +!22 = !{!"kernel_arg_access_qual", !"read_only", !"none", !"write_only", !"none"}
> +!32 = !{!"kernel_arg_type", !"image3d_t", !"sampler_t", !"image2d_t", !"int*"}
> +!42 = !{!"kernel_arg_base_type", !"image3d_t", !"sampler_t", !"image2d_t", !"int*"}
> +!52 = !{!"kernel_arg_type_qual", !"", !"", !"", !""}
> diff --git a/test/CodeGen/AMDGPU/image-resource-id.ll b/test/CodeGen/AMDGPU/image-resource-id.ll
> new file mode 100644
> index 0000000..d4cf349
> --- /dev/null
> +++ b/test/CodeGen/AMDGPU/image-resource-id.ll
> @@ -0,0 +1,409 @@
> +; RUN: llc -march=r600 -mcpu=juniper < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
> +
> +; === 1 image arg, read_only ===================================================
> +
> +; FUNC-LABEL: {{^}}test_2d_rd_1_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_2d_rd_1_0(%opencl.image2d_t addrspace(1)* %in, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_3d_rd_1_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_3d_rd_1_0(%opencl.image3d_t addrspace(1)* %in, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; === 1 image arg, write_only ==================================================
> +
> +; FUNC-LABEL: {{^}}test_2d_wr_1_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_2d_wr_1_0(%opencl.image2d_t addrspace(1)* %in, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_3d_wr_1_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_3d_wr_1_0(%opencl.image3d_t addrspace(1)* %in, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; === 2 image args, read_only ==================================================
> +
> +; FUNC-LABEL: {{^}}test_2d_rd_2_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_2d_rd_2_0(%opencl.image2d_t addrspace(1)* %in1, ; read_only
> + %opencl.image2d_t addrspace(1)* %in2, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in1) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_2d_rd_2_1:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_2d_rd_2_1(%opencl.image2d_t addrspace(1)* %in1, ; read_only
> + %opencl.image2d_t addrspace(1)* %in2, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in2) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_3d_rd_2_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_3d_rd_2_0(%opencl.image3d_t addrspace(1)* %in1, ; read_only
> + %opencl.image3d_t addrspace(1)* %in2, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in1) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_3d_rd_2_1:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_3d_rd_2_1(%opencl.image3d_t addrspace(1)* %in1, ; read_only
> + %opencl.image3d_t addrspace(1)* %in2, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in2) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; === 2 image args, write_only =================================================
> +
> +; FUNC-LABEL: {{^}}test_2d_wr_2_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_2d_wr_2_0(%opencl.image2d_t addrspace(1)* %in1, ; write_only
> + %opencl.image2d_t addrspace(1)* %in2, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in1) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_2d_wr_2_1:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_2d_wr_2_1(%opencl.image2d_t addrspace(1)* %in1, ; write_only
> + %opencl.image2d_t addrspace(1)* %in2, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in2) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_3d_wr_2_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_3d_wr_2_0(%opencl.image3d_t addrspace(1)* %in1, ; write_only
> + %opencl.image3d_t addrspace(1)* %in2, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in1) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_3d_wr_2_1:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_3d_wr_2_1(%opencl.image3d_t addrspace(1)* %in1, ; write_only
> + %opencl.image3d_t addrspace(1)* %in2, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in2) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; === 3 image args, read_only ==================================================
> +
> +; FUNC-LABEL: {{^}}test_2d_rd_3_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 2(
> +define void @test_2d_rd_3_0(%opencl.image2d_t addrspace(1)* %in1, ; read_only
> + %opencl.image3d_t addrspace(1)* %in2, ; read_only
> + %opencl.image2d_t addrspace(1)* %in3, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in3) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +; FUNC-LABEL: {{^}}test_3d_rd_3_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 2(
> +define void @test_3d_rd_3_0(%opencl.image3d_t addrspace(1)* %in1, ; read_only
> + %opencl.image2d_t addrspace(1)* %in2, ; read_only
> + %opencl.image3d_t addrspace(1)* %in3, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in3) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; === 3 image args, write_only =================================================
> +
> +; FUNC-LABEL: {{^}}test_2d_wr_3_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 2(
> +define void @test_2d_wr_3_0(%opencl.image2d_t addrspace(1)* %in1, ; write_only
> + %opencl.image3d_t addrspace(1)* %in2, ; write_only
> + %opencl.image2d_t addrspace(1)* %in3, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in3) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +; FUNC-LABEL: {{^}}test_3d_wr_3_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 2(
> +define void @test_3d_wr_3_0(%opencl.image3d_t addrspace(1)* %in1, ; write_only
> + %opencl.image2d_t addrspace(1)* %in2, ; write_only
> + %opencl.image3d_t addrspace(1)* %in3, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in3) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; === 3 image args, mixed ======================================================
> +
> +; FUNC-LABEL: {{^}}test_2d_mix_3_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_2d_mix_3_0(%opencl.image2d_t addrspace(1)* %in1, ; write_only
> + %opencl.image3d_t addrspace(1)* %in2, ; read_only
> + %opencl.image2d_t addrspace(1)* %in3, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in3) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_3d_mix_3_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_3d_mix_3_0(%opencl.image3d_t addrspace(1)* %in1, ; write_only
> + %opencl.image2d_t addrspace(1)* %in2, ; read_only
> + %opencl.image3d_t addrspace(1)* %in3, ; read_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in3) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_2d_mix_3_1:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_2d_mix_3_1(%opencl.image2d_t addrspace(1)* %in1, ; write_only
> + %opencl.image3d_t addrspace(1)* %in2, ; read_only
> + %opencl.image2d_t addrspace(1)* %in3, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.2d(
> + %opencl.image2d_t addrspace(1)* %in3) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_3d_mix_3_1:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_3d_mix_3_1(%opencl.image3d_t addrspace(1)* %in1, ; write_only
> + %opencl.image2d_t addrspace(1)* %in2, ; read_only
> + %opencl.image3d_t addrspace(1)* %in3, ; write_only
> + i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.image.get.resource.id.3d(
> + %opencl.image3d_t addrspace(1)* %in3) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +%opencl.image2d_t = type opaque
> +%opencl.image3d_t = type opaque
> +
> +declare i32 @llvm.OpenCL.image.get.resource.id.2d(%opencl.image2d_t addrspace(1)*) #0
> +declare i32 @llvm.OpenCL.image.get.resource.id.3d(%opencl.image3d_t addrspace(1)*) #0
> +
> +attributes #0 = { readnone }
> +
> +!opencl.kernels = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13,
> + !14, !15, !16, !17, !18, !19}
> +!0 = !{void (%opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @test_2d_rd_1_0,
> + !110, !120, !130, !140, !150}
> +!1 = !{void (%opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @test_3d_rd_1_0,
> + !110, !120, !131, !141, !150}
> +!2 = !{void (%opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @test_2d_wr_1_0,
> + !110, !121, !130, !140, !150}
> +!3 = !{void (%opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @test_3d_wr_1_0,
> + !110, !121, !131, !141, !150}
> +!110 = !{!"kernel_arg_addr_space", i32 1, i32 1}
> +!120 = !{!"kernel_arg_access_qual", !"read_only", !"none"}
> +!121 = !{!"kernel_arg_access_qual", !"write_only", !"none"}
> +!130 = !{!"kernel_arg_type", !"image2d_t", !"int*"}
> +!131 = !{!"kernel_arg_type", !"image3d_t", !"int*"}
> +!140 = !{!"kernel_arg_base_type", !"image2d_t", !"int*"}
> +!141 = !{!"kernel_arg_base_type", !"image3d_t", !"int*"}
> +!150 = !{!"kernel_arg_type_qual", !"", !""}
> +
> +!4 = !{void (%opencl.image2d_t addrspace(1)*, %opencl.image2d_t addrspace(1)*,
> + i32 addrspace(1)*)* @test_2d_rd_2_0, !112, !122, !132, !142, !152}
> +!5 = !{void (%opencl.image2d_t addrspace(1)*, %opencl.image2d_t addrspace(1)*,
> + i32 addrspace(1)*)* @test_2d_rd_2_1, !112, !122, !132, !142, !152}
> +!6 = !{void (%opencl.image3d_t addrspace(1)*, %opencl.image3d_t addrspace(1)*,
> + i32 addrspace(1)*)* @test_3d_rd_2_0, !112, !122, !133, !143, !152}
> +!7 = !{void (%opencl.image3d_t addrspace(1)*, %opencl.image3d_t addrspace(1)*,
> + i32 addrspace(1)*)* @test_3d_rd_2_1, !112, !122, !133, !143, !152}
> +!8 = !{void (%opencl.image2d_t addrspace(1)*, %opencl.image2d_t addrspace(1)*,
> + i32 addrspace(1)*)* @test_2d_wr_2_0, !112, !123, !132, !142, !152}
> +!9 = !{void (%opencl.image2d_t addrspace(1)*, %opencl.image2d_t addrspace(1)*,
> + i32 addrspace(1)*)* @test_2d_wr_2_1, !112, !123, !132, !142, !152}
> +!10 = !{void (%opencl.image3d_t addrspace(1)*, %opencl.image3d_t addrspace(1)*,
> + i32 addrspace(1)*)* @test_3d_wr_2_0, !112, !123, !133, !143, !152}
> +!11 = !{void (%opencl.image3d_t addrspace(1)*, %opencl.image3d_t addrspace(1)*,
> + i32 addrspace(1)*)* @test_3d_wr_2_1, !112, !123, !133, !143, !152}
> +!112 = !{!"kernel_arg_addr_space", i32 1, i32 1, i32 1}
> +!122 = !{!"kernel_arg_access_qual", !"read_only", !"read_only", !"none"}
> +!123 = !{!"kernel_arg_access_qual", !"write_only", !"write_only", !"none"}
> +!132 = !{!"kernel_arg_type", !"image2d_t", !"image2d_t", !"int*"}
> +!133 = !{!"kernel_arg_type", !"image3d_t", !"image3d_t", !"int*"}
> +!142 = !{!"kernel_arg_base_type", !"image2d_t", !"image2d_t", !"int*"}
> +!143 = !{!"kernel_arg_base_type", !"image3d_t", !"image3d_t", !"int*"}
> +!152 = !{!"kernel_arg_type_qual", !"", !"", !""}
> +
> +!12 = !{void (%opencl.image2d_t addrspace(1)*, %opencl.image3d_t addrspace(1)*,
> + %opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @test_2d_rd_3_0,
> + !114, !124, !134, !144, !154}
> +!13 = !{void (%opencl.image3d_t addrspace(1)*, %opencl.image2d_t addrspace(1)*,
> + %opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @test_3d_rd_3_0,
> + !114, !124, !135, !145, !154}
> +!14 = !{void (%opencl.image2d_t addrspace(1)*, %opencl.image3d_t addrspace(1)*,
> + %opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @test_2d_wr_3_0,
> + !114, !125, !134, !144, !154}
> +!15 = !{void (%opencl.image3d_t addrspace(1)*, %opencl.image2d_t addrspace(1)*,
> + %opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @test_3d_wr_3_0,
> + !114, !125, !135, !145, !154}
> +!16 = !{void (%opencl.image2d_t addrspace(1)*, %opencl.image3d_t addrspace(1)*,
> + %opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @test_2d_mix_3_0,
> + !114, !126, !134, !144, !154}
> +!17 = !{void (%opencl.image3d_t addrspace(1)*, %opencl.image2d_t addrspace(1)*,
> + %opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @test_3d_mix_3_0,
> + !114, !126, !135, !145, !154}
> +!18 = !{void (%opencl.image2d_t addrspace(1)*, %opencl.image3d_t addrspace(1)*,
> + %opencl.image2d_t addrspace(1)*, i32 addrspace(1)*)* @test_2d_mix_3_1,
> + !114, !127, !134, !144, !154}
> +!19 = !{void (%opencl.image3d_t addrspace(1)*, %opencl.image2d_t addrspace(1)*,
> + %opencl.image3d_t addrspace(1)*, i32 addrspace(1)*)* @test_3d_mix_3_1,
> + !114, !127, !135, !145, !154}
> +!114 = !{!"kernel_arg_addr_space", i32 1, i32 1, i32 1, i32 1}
> +!124 = !{!"kernel_arg_access_qual", !"read_only", !"read_only", !"read_only", !"none"}
> +!125 = !{!"kernel_arg_access_qual", !"write_only", !"write_only", !"write_only", !"none"}
> +!126 = !{!"kernel_arg_access_qual", !"write_only", !"read_only", !"read_only", !"none"}
> +!127 = !{!"kernel_arg_access_qual", !"write_only", !"read_only", !"write_only", !"none"}
> +!134 = !{!"kernel_arg_type", !"image2d_t", !"image3d_t", !"image2d_t", !"int*"}
> +!135 = !{!"kernel_arg_type", !"image3d_t", !"image2d_t", !"image3d_t", !"int*"}
> +!144 = !{!"kernel_arg_base_type", !"image2d_t", !"image3d_t", !"image2d_t", !"int*"}
> +!145 = !{!"kernel_arg_base_type", !"image3d_t", !"image2d_t", !"image3d_t", !"int*"}
> +!154 = !{!"kernel_arg_type_qual", !"", !"", !"", !""}
> diff --git a/test/CodeGen/AMDGPU/sampler-resource-id.ll b/test/CodeGen/AMDGPU/sampler-resource-id.ll
> new file mode 100644
> index 0000000..c41d345
> --- /dev/null
> +++ b/test/CodeGen/AMDGPU/sampler-resource-id.ll
> @@ -0,0 +1,65 @@
> +; RUN: llc -march=r600 -mcpu=juniper < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s
> +
> +; FUNC-LABEL: {{^}}test_0:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 0(
> +define void @test_0(i32 %in0, i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.sampler.get.resource.id(i32 %in0) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_1:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 1(
> +define void @test_1(i32 %in0, i32 %in1, i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.sampler.get.resource.id(i32 %in1) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +; FUNC-LABEL: {{^}}test_2:
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]
> +; EG: MOV [[VAL]], literal.x
> +; EG-NEXT: LSHR
> +; EG-NEXT: 2(
> +define void @test_2(i32 %in0, i32 %in1, i32 %in2, i32 addrspace(1)* %out) {
> +entry:
> + %0 = call i32 @llvm.OpenCL.sampler.get.resource.id(i32 %in2) #0
> + store i32 %0, i32 addrspace(1)* %out
> + ret void
> +}
> +
> +
> +declare i32 @llvm.OpenCL.sampler.get.resource.id(i32) #0
> +
> +attributes #0 = { readnone }
> +
> +!opencl.kernels = !{!0, !1, !2}
> +
> +!0 = !{void (i32, i32 addrspace(1)*)* @test_0, !10, !20, !30, !40, !50}
> +!10 = !{!"kernel_arg_addr_space", i32 0, i32 1}
> +!20 = !{!"kernel_arg_access_qual", !"none", !"none"}
> +!30 = !{!"kernel_arg_type", !"sampler_t", !"int*"}
> +!40 = !{!"kernel_arg_base_type", !"sampler_t", !"int*"}
> +!50 = !{!"kernel_arg_type_qual", !"", !""}
> +
> +!1 = !{void (i32, i32, i32 addrspace(1)*)* @test_1, !11, !21, !31, !41, !51}
> +!11 = !{!"kernel_arg_addr_space", i32 0, i32 0, i32 1}
> +!21 = !{!"kernel_arg_access_qual", !"none", !"none", !"none"}
> +!31 = !{!"kernel_arg_type", !"sampler_t", !"sampler_t", !"int*"}
> +!41 = !{!"kernel_arg_base_type", !"sampler_t", !"sampler_t", !"int*"}
> +!51 = !{!"kernel_arg_type_qual", !"", !"", !""}
> +
> +!2 = !{void (i32, i32, i32, i32 addrspace(1)*)* @test_2, !12, !22, !32, !42, !52}
> +!12 = !{!"kernel_arg_addr_space", i32 0, i32 0, i32 0, i32 1}
> +!22 = !{!"kernel_arg_access_qual", !"none", !"none", !"none", !"none"}
> +!32 = !{!"kernel_arg_type", !"sampler_t", !"sampler_t", !"sampler_t", !"int*"}
> +!42 = !{!"kernel_arg_base_type", !"sampler_t", !"sampler_t", !"sampler_t", !"int*"}
> +!52 = !{!"kernel_arg_type_qual", !"", !"", !"", !""}
> --
> 2.4.6
>
More information about the llvm-commits
mailing list