如何将opencl-kernel-file(.cl)编译为LLVM IR

时间:2018-01-11 04:30:12

标签: opencl llvm llvm-clang llvm-ir

这个问题与LLVM / clang有关。
我已经知道如何使用OpenCL API编译opencl-kernel-file(.cl)(clBuildProgram()和clGetProgramBuildInfo())

我的问题是:
如何使用OpenCL 1.2或更高版本将opencl-kernel-file(.cl)编译为LLVM IR?
 换句话说,如何在不使用libclc的情况下将opnecl-kernel-file(.cl)编译为LLVM IR?

我尝试了各种方法来获取OpenCL-Kernel-File的LLVM-IR。

我首先遵循了clang用户手册。(https://clang.llvm.org/docs/UsersManual.html#opencl-features)但它没有运行。

其次,我找到了一种使用libclc的方法 命令是这样的:

clang++ -emit-llvm -c -target -nvptx64-nvidial-nvcl -Dcl_clang_storage_class_specifiers -include /usr/local/include/clc/clc.h -fpack-struct=64 -o "$@".bc "$@" <br>
llvm-link "$@".bc /usr/local/lib/clc/nvptx64--nvidiacl.bc -o "$@".linked.bc <br>
llc -mcpu=sm_52 -march=nvptx64 "$@".linked.bc -o "$@".nvptx.s<br>


这种方法工作正常,但由于libclc是在OpenCL 1.1规范之上构建的,因此无法与OpenCL 1.2或更高版本的代码(如使用printf的代码)一起使用。

此方法使用libclc,它以新函数的形式实现OpenCL内置函数。您可以在结果opencl二进制文件的程序集(ptx)中观察到它直接进入函数调用而不是将其转换为内联汇编。我担心这会影响gpu行为和性能,例如执行时间。

所以现在我正在寻找一种使用libclc替换编译的方法 作为最后的手段,我考虑将libclc用于NVPTX后端和LLGP的AMDGPU后端。
但如果还有另一种方式,我想用它 (我希望OpenCL前端我还没有发现铿锵声)

我的计划方案是:

  1. 有opencl内核源文件(.cl)
  2. 将文件编译为LLVM IR
  3. IR的IR级别流程
  4. 将IR编译(使用llc)到二进制
    • 与每个gpu目标(nvptx,amdgcn ..)
  5. 使用二进制文件,使用clCreateProgramWithBinary()运行主机(.c或.cpp与lib OpenCL)
  6. 现在,当我将内核源文件编译为LLVM IR时,我必须包含libclc的头文件(上面命令的第一个中的-include选项)来编译内置函数。我必须在编译IR之前链接libclc库到二进制

    我的环境如下:

    • GTX960
           - NVIDIA的二进制文件以nvptx格式出现      - 我使用sm_52 nvptx作为我的gpu。
    • Ubuntu Linux 16.04 LTS
    • LLVM / Clang 5.0.0
           - 如果还有其他方法,我愿意更改LLVM版本。

    感谢您的建议!

3 个答案:

答案 0 :(得分:0)

  

(我希望我还没有发现OpenCL前端存在于clang中)

在clang中有一个OpenCL前端 - 你正在使用它,否则你无法用clang编译一行OpenCL。前端是Clang识别OpenCL语言。 LLVM中没有OpenCL 后端,它不是LLVM的工作;它是各种OpenCL实现的工作,以提供适当的库。 Clang + LLVM只识别语言并将其编译为bitcode&amp;机器二进制文件,这就完成了。

  

在结果opencl二进制文件的汇编(ptx)中,它直接进入函数调用,而不是将其转换为内联汇编。

如果找到,可以尝试链接到不同的库而不是libclc。也许NVidia的CUDA在某处有一些bitcode库,然后又是许可问题...顺便说一句,你是否100%确定你需要LLVM IR?使用OpenCL运行时或使用SPIR-V获取OpenCL二进制文件可能会让您获得更快的二进制文件和当然不会那么痛苦。即使你设法得到一个不错的LLVM IR,你也需要一些实际接受它的运行时(我可能是错的,但我怀疑专有的AMD / NVIDIA OpenCL只会接受随机LLVM IR作为输入)。

答案 1 :(得分:0)

Clang没有提供标准的CL声明头文件(例如,C的stdio.h),这就是为什么你得到“未定义的类型浮点数”等等。

如果你得到一个这样的标题,你可以使用“clang -include cl.h -x cl [你的文件名在这里]”将其标记为隐式包含

可以从

的参考OpenCL编译器实现中检索一个这样的声明头

https://github.com/KhronosGroup/SPIR-Tools/blob/master/headers/opencl_spir.h

顺便说一下,考虑使用这个生成SPIR(尽管是1.0)的编译器,它可以作为输入提供给OpenCL驱动程序。

答案 2 :(得分:0)

Clang 9(及更高版本)可以编译用OpenCL C语言编写的OpenCL内核。您可以通过传递-emit-llvm标志(添加-S来告诉Clang发出LLVM-IR,以文本而不是字节码格式输出IR),然后使用以下命令指定OpenCL标准的版本: -cl-std=CL2.0。 Clang当前最多支持OpenCL 2.0。

默认情况下,Clang不会添加标准的OpenCL标头,因此,如果您的内核使用任何OpenCL内置函数,您可能会看到类似以下的错误:

clang-9 -c -x cl -emit-llvm -S -cl-std=CL2.0 my_kernel.cl -o my_kernel.ll
my_kernel.cl:17:12: error: implicit declaration of function 'get_global_id' is invalid in OpenCL
  int i = get_global_id(0);
          ^
1 error generated.

您可以通过将-finclude-default-header标志传递给Clang前端来告诉Clang包含standard OpenCL headers,例如

clang-9 -c -x cl -emit-llvm -S -cl-std=CL2.0 -Xclang -finclude-default-header my_kernel.cl -o my_kernel.ll