<div dir="ltr"><div>Please disregard this patch.<br></div><div>Because of clover-side suggestions, I've chosen another approach for this. Please see the patch:</div><div>[llvm] [PATCH] AMDGPU: Add pass to lower OpenCL image and sampler arguments.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jul 10, 2015 at 11:08 PM, Tom Stellard <span dir="ltr"><<a href="mailto:tom@stellard.net" target="_blank">tom@stellard.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Fri, Jul 10, 2015 at 07:45:46AM +0200, Zoltan Gilian wrote:<br>
> Added a pass to replace calls to the llvm.AMDGPU.get.image.id.[23]d dummy<br>
> intrinsics with a compile-time constant image ID for OpenCL images.<br>
> The image ID is the index of the image argument among the image[23]d_t<br>
> arguments of the OpenCL kernel.<br>
<br>
</span>LGTM.<br>
<div class="HOEnZb"><div class="h5"><br>
> ---<br>
>  lib/Target/AMDGPU/AMDGPU.h                         |   1 +<br>
>  .../AMDGPU/AMDGPUImageIDIntrinsicsReplacer.cpp     |  98 ++++++++++++++++<br>
>  lib/Target/AMDGPU/AMDGPUTargetMachine.cpp          |   1 +<br>
>  test/CodeGen/AMDGPU/image-id.ll                    | 129 +++++++++++++++++++++<br>
>  4 files changed, 229 insertions(+)<br>
>  create mode 100644 lib/Target/AMDGPU/AMDGPUImageIDIntrinsicsReplacer.cpp<br>
>  create mode 100644 test/CodeGen/AMDGPU/image-id.ll<br>
><br>
> diff --git a/lib/Target/AMDGPU/AMDGPU.h b/lib/Target/AMDGPU/AMDGPU.h<br>
> index 0a05d25..9586afd 100644<br>
> --- a/lib/Target/AMDGPU/AMDGPU.h<br>
> +++ b/lib/Target/AMDGPU/AMDGPU.h<br>
> @@ -64,6 +64,7 @@ FunctionPass *createAMDGPUPromoteAlloca(const AMDGPUSubtarget &ST);<br>
>  Pass *createAMDGPUStructurizeCFGPass();<br>
>  FunctionPass *createAMDGPUISelDag(TargetMachine &tm);<br>
>  ModulePass *createAMDGPUAlwaysInlinePass();<br>
> +FunctionPass *createAMDGPUImageIDIntrinsicsReplacer();<br>
><br>
>  void initializeSIFixControlFlowLiveIntervalsPass(PassRegistry&);<br>
>  extern char &SIFixControlFlowLiveIntervalsID;<br>
> diff --git a/lib/Target/AMDGPU/AMDGPUImageIDIntrinsicsReplacer.cpp b/lib/Target/AMDGPU/AMDGPUImageIDIntrinsicsReplacer.cpp<br>
> new file mode 100644<br>
> index 0000000..68fff54<br>
> --- /dev/null<br>
> +++ b/lib/Target/AMDGPU/AMDGPUImageIDIntrinsicsReplacer.cpp<br>
> @@ -0,0 +1,98 @@<br>
> +//===-- AMDGPUImageIDIntrinsicsReplacer.cpp --------------------------===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +//<br>
> +/// \file<br>
> +/// This pass replaces image ID getter pseudointrinsics with compile-time<br>
> +/// constant ID values for OpenCL images. The ID is the index of the image<br>
> +/// argument among the image[23]d_t arguments of the OpenCL kernel.<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#include "AMDGPU.h"<br>
> +#include "llvm/Analysis/Passes.h"<br>
> +#include "llvm/IR/Constants.h"<br>
> +#include "llvm/IR/Function.h"<br>
> +#include "llvm/IR/Instructions.h"<br>
> +#include "llvm/IR/Module.h"<br>
> +<br>
> +#include <vector><br>
> +<br>
> +using namespace llvm;<br>
> +<br>
> +namespace {<br>
> +<br>
> +class AMDGPUImageIDIntrinsicsReplacer : public FunctionPass {<br>
> +  static char ID;<br>
> +  Type *Int32Type;<br>
> +<br>
> +public:<br>
> +  AMDGPUImageIDIntrinsicsReplacer() : FunctionPass(ID) {}<br>
> +<br>
> +  bool doInitialization(Module &M) override {<br>
> +    Int32Type = Type::getInt32Ty(M.getContext());<br>
> +    return true;<br>
> +  }<br>
> +<br>
> +  bool runOnFunction(Function &F) override {<br>
> +    bool modified = false;<br>
> +    int32_t NumImageArgs = 0;<br>
> +<br>
> +    std::vector<Instruction *> InstsToErase;<br>
> +<br>
> +    for (const auto &Arg : F.args()) {<br>
> +<br>
> +      // Skip non-image types.<br>
> +      Type *ArgType = Arg.getType();<br>
> +      if (!ArgType->isPointerTy())<br>
> +        continue;<br>
> +      Type *ElemType = ArgType->getPointerElementType();<br>
> +      if (!ElemType->isStructTy())<br>
> +        continue;<br>
> +      const llvm::StringRef &TypeName = ElemType->getStructName();<br>
> +      if (!TypeName.startswith("opencl.image2d_t") &&<br>
> +          !TypeName.startswith("opencl.image3d_t"))<br>
> +        continue;<br>
> +      int32_t ImageIndex = NumImageArgs++;<br>
> +<br>
> +      // Iterate uses to find ID getters.<br>
> +      for (const auto &Use : Arg.uses()) {<br>
> +<br>
> +        // Only process calls to ID getter intrinsics.<br>
> +        auto Inst = dyn_cast<CallInst>(Use.getUser());<br>
> +        if (!Inst)<br>
> +          continue;<br>
> +<br>
> +        StringRef Name = Inst->getCalledFunction()->getName();<br>
> +        if (Name != "llvm.AMDGPU.get.image.id.2d" &&<br>
> +            Name != "llvm.AMDGPU.get.image.id.3d") {<br>
> +          continue;<br>
> +        }<br>
> +<br>
> +        Inst->replaceAllUsesWith(ConstantInt::get(Int32Type, ImageIndex));<br>
> +        InstsToErase.push_back(Inst);<br>
> +        modified = true;<br>
> +      }<br>
> +    }<br>
> +    for (size_t i = 0; i < InstsToErase.size(); ++i) {<br>
> +      InstsToErase[i]->eraseFromParent();<br>
> +    }<br>
> +<br>
> +    return modified;<br>
> +  }<br>
> +<br>
> +  const char *getPassName() const override {<br>
> +    return "AMDGPU Image ID Intrinsics Replacer";<br>
> +  }<br>
> +};<br>
> +<br>
> +char AMDGPUImageIDIntrinsicsReplacer::ID = 0;<br>
> +}<br>
> +<br>
> +FunctionPass *llvm::createAMDGPUImageIDIntrinsicsReplacer() {<br>
> +  return new AMDGPUImageIDIntrinsicsReplacer();<br>
> +}<br>
> diff --git a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp<br>
> index f395565..d69858e 100644<br>
> --- a/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp<br>
> +++ b/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp<br>
> @@ -188,6 +188,7 @@ AMDGPUPassConfig::addPreISel() {<br>
>    addPass(createFlattenCFGPass());<br>
>    if (ST.IsIRStructurizerEnabled())<br>
>      addPass(createStructurizeCFGPass());<br>
> +  addPass(createAMDGPUImageIDIntrinsicsReplacer());<br>
>    return false;<br>
>  }<br>
><br>
> diff --git a/test/CodeGen/AMDGPU/image-id.ll b/test/CodeGen/AMDGPU/image-id.ll<br>
> new file mode 100644<br>
> index 0000000..a5da037<br>
> --- /dev/null<br>
> +++ b/test/CodeGen/AMDGPU/image-id.ll<br>
> @@ -0,0 +1,129 @@<br>
> +; RUN: llc -march=r600 -mcpu=juniper < %s | FileCheck -check-prefix=EG -check-prefix=FUNC %s<br>
> +<br>
> +; FUNC-LABEL: {{^}}test_2d_1:<br>
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]<br>
> +; EG: MOV [[VAL]], literal.x<br>
> +; EG-NEXT: LSHR<br>
> +; EG-NEXT: 0(<br>
> +define void @test_2d_1(%opencl.image2d_t addrspace(1)* %in,<br>
> +                                 i32 addrspace(1)* %out) {<br>
> +entry:<br>
> +  %0 = call i32 @llvm.AMDGPU.get.image.id.2d(<br>
> +      %opencl.image2d_t addrspace(1)* %in) #0<br>
> +  store i32 %0, i32 addrspace(1)* %out<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; FUNC-LABEL: {{^}}test_2d_21:<br>
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]<br>
> +; EG: MOV [[VAL]], literal.x<br>
> +; EG-NEXT: LSHR<br>
> +; EG-NEXT: 0(<br>
> +define void @test_2d_21(%opencl.image2d_t addrspace(1)* %in1,<br>
> +                     %opencl.image2d_t addrspace(1)* %in2,<br>
> +                                 i32 addrspace(1)* %out) {<br>
> +entry:<br>
> +  %0 = call i32 @llvm.AMDGPU.get.image.id.2d(<br>
> +      %opencl.image2d_t addrspace(1)* %in1) #0<br>
> +  store i32 %0, i32 addrspace(1)* %out<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; FUNC-LABEL: {{^}}test_2d_22:<br>
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]<br>
> +; EG: MOV [[VAL]], literal.x<br>
> +; EG-NEXT: LSHR<br>
> +; EG-NEXT: 1(<br>
> +define void @test_2d_22(%opencl.image2d_t addrspace(1)* %in1,<br>
> +                     %opencl.image2d_t addrspace(1)* %in2,<br>
> +                                 i32 addrspace(1)* %out) {<br>
> +entry:<br>
> +  %0 = call i32 @llvm.AMDGPU.get.image.id.2d(<br>
> +      %opencl.image2d_t addrspace(1)* %in2) #0<br>
> +  store i32 %0, i32 addrspace(1)* %out<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; FUNC-LABEL: {{^}}test_2d_3:<br>
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]<br>
> +; EG: MOV [[VAL]], literal.x<br>
> +; EG-NEXT: LSHR<br>
> +; EG-NEXT: 2(<br>
> +define void @test_2d_3(%opencl.image2d_t addrspace(1)* %in1,<br>
> +                    %opencl.image3d_t addrspace(1)* %in2,<br>
> +                    %opencl.image2d_t addrspace(1)* %in3,<br>
> +                                 i32 addrspace(1)* %out) {<br>
> +entry:<br>
> +  %0 = call i32 @llvm.AMDGPU.get.image.id.2d(<br>
> +      %opencl.image2d_t addrspace(1)* %in3) #0<br>
> +  store i32 %0, i32 addrspace(1)* %out<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; FUNC-LABEL: {{^}}test_3d_1:<br>
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]<br>
> +; EG: MOV [[VAL]], literal.x<br>
> +; EG-NEXT: LSHR<br>
> +; EG-NEXT: 0(<br>
> +define void @test_3d_1(%opencl.image3d_t addrspace(1)* %in,<br>
> +                                 i32 addrspace(1)* %out) {<br>
> +entry:<br>
> +  %0 = call i32 @llvm.AMDGPU.get.image.id.3d(<br>
> +      %opencl.image3d_t addrspace(1)* %in) #0<br>
> +  store i32 %0, i32 addrspace(1)* %out<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; FUNC-LABEL: {{^}}test_3d_21:<br>
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]<br>
> +; EG: MOV [[VAL]], literal.x<br>
> +; EG-NEXT: LSHR<br>
> +; EG-NEXT: 0(<br>
> +define void @test_3d_21(%opencl.image3d_t addrspace(1)* %in1,<br>
> +                     %opencl.image3d_t addrspace(1)* %in2,<br>
> +                                 i32 addrspace(1)* %out) {<br>
> +entry:<br>
> +  %0 = call i32 @llvm.AMDGPU.get.image.id.3d(<br>
> +      %opencl.image3d_t addrspace(1)* %in1) #0<br>
> +  store i32 %0, i32 addrspace(1)* %out<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; FUNC-LABEL: {{^}}test_3d_22:<br>
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]<br>
> +; EG: MOV [[VAL]], literal.x<br>
> +; EG-NEXT: LSHR<br>
> +; EG-NEXT: 1(<br>
> +define void @test_3d_22(%opencl.image3d_t addrspace(1)* %in1,<br>
> +                     %opencl.image3d_t addrspace(1)* %in2,<br>
> +                                 i32 addrspace(1)* %out) {<br>
> +entry:<br>
> +  %0 = call i32 @llvm.AMDGPU.get.image.id.3d(<br>
> +      %opencl.image3d_t addrspace(1)* %in2) #0<br>
> +  store i32 %0, i32 addrspace(1)* %out<br>
> +  ret void<br>
> +}<br>
> +<br>
> +; FUNC-LABEL: {{^}}test_3d_3:<br>
> +; EG: MEM_RAT_CACHELESS STORE_RAW [[VAL:T[0-9]+\.X]]<br>
> +; EG: MOV [[VAL]], literal.x<br>
> +; EG-NEXT: LSHR<br>
> +; EG-NEXT: 2(<br>
> +define void @test_3d_3(%opencl.image3d_t addrspace(1)* %in1,<br>
> +                    %opencl.image2d_t addrspace(1)* %in2,<br>
> +                    %opencl.image3d_t addrspace(1)* %in3,<br>
> +                                 i32 addrspace(1)* %out) {<br>
> +entry:<br>
> +  %0 = call i32 @llvm.AMDGPU.get.image.id.3d(<br>
> +      %opencl.image3d_t addrspace(1)* %in3) #0<br>
> +  store i32 %0, i32 addrspace(1)* %out<br>
> +  ret void<br>
> +}<br>
> +<br>
> +%opencl.image2d_t = type opaque<br>
> +%opencl.image3d_t = type opaque<br>
> +<br>
> +declare i32 @llvm.AMDGPU.get.image.id.2d(%opencl.image2d_t addrspace(1)*) #0<br>
> +declare i32 @llvm.AMDGPU.get.image.id.3d(%opencl.image3d_t addrspace(1)*) #0<br>
> +<br>
> +attributes #0 = { readnone }<br>
> --<br>
> 2.4.2<br>
><br>
</div></div></blockquote></div><br></div>