从Clang生成OpenCL LLVM IR

从Clang生成OpenCL LLVM IR,clang,opencl,llvm,llvm-ir,Clang,Opencl,Llvm,Llvm Ir,我正在使用以下命令行执行clang: clang -Dcl_clang_storage_class_specifiers -isystem $LIBCLC/generic/include -include clc/clc.h -target nvptx--nvidiacl -x cl some_kernel.cl -emit-llvm -S -o some_kernel.ll 结果是: ; ModuleID = 'kernel.cl' target datalayout = "e-p:32:3

我正在使用以下命令行执行clang:

clang -Dcl_clang_storage_class_specifiers -isystem $LIBCLC/generic/include -include clc/clc.h -target nvptx--nvidiacl -x cl some_kernel.cl -emit-llvm -S -o some_kernel.ll
结果是:

; ModuleID = 'kernel.cl'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"
target triple = "nvptx--nvidiacl"

; Function Attrs: noinline nounwind
define void @vector_add(float addrspace(1)* nocapture %vec1, float addrspace(1)* nocapture %vec2, float addrspace(1)* nocapture %vec3) #0 {
  %1 = tail call i32 @get_global_id(i32 0) #2
  %2 = getelementptr inbounds float addrspace(1)* %vec1, i32 1
  %3 = load float addrspace(1)* %2, align 4, !tbaa !2
  %4 = getelementptr inbounds float addrspace(1)* %vec2, i32 2
  %5 = load float addrspace(1)* %4, align 4, !tbaa !2
  %6 = fadd float %3, %5
  %7 = fmul float %6, 5.000000e+00
  %8 = getelementptr inbounds float addrspace(1)* %vec3, i32 %1
  store float %7, float addrspace(1)* %8, align 4, !tbaa !2
  ret void
}

declare i32 @get_global_id(i32) #1

attributes #0 = { noinline nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { nounwind }

!opencl.kernels = !{!0}
!nvvm.annotations = !{!1}

!0 = metadata !{void (float addrspace(1)*, float addrspace(1)*, float addrspace(1)*)* @vector_add}
!1 = metadata !{void (float addrspace(1)*, float addrspace(1)*, float addrspace(1)*)* @vector_add, metadata !"kernel", i32 1}
!2 = metadata !{metadata !"float", metadata !3}
!3 = metadata !{metadata !"omnipotent char", metadata !4}
!4 = metadata !{metadata !"Simple C/C++ TBAA"}
正如您在参数列表中看到的,它生成一个nocapture ABI

但当我尝试使用此代码执行此操作时:

/*Create a diagnostics*/
mCompilerInst.createDiagnostics();


/*Creating NVIDIA-CL*/
clang::TargetOptions  TO;
TO.Triple = "nvptx--nvidiacl";
TargetInfo* feTarget =
    clang::TargetInfo::CreateTargetInfo(mCompilerInst.getDiagnostics(), &TO);
mCompilerInst.setTarget(feTarget);

/*Commandline Parameters*/
std::vector<const char*> args;
args.push_back("-Dcl_clang_storage_class_specifiers");
args.push_back("-include");
args.push_back("clc/clc.h");
args.push_back("-xcl");
args.push_back("-S");
/* Create the compiler invocation */
clang::CompilerInvocation::CreateFromArgs(mCompilerInst.getInvocation(), &args[0], &args[0] + args.size(), mCompilerInst.getDiagnostics());

CodeGenerator* llvmCodeGen = clang::CreateLLVMCodeGen(
    mCompilerInst.getDiagnostics(), "kernel.cl", mCompilerInst.getCodeGenOpts(),mCompilerInst.getTargetOpts(),ctx);
ParseAST(mCompilerInst.getPreprocessor(),llvmCodeGen,mCompilerInst.getASTContext());
mCompilerInst.getDiagnosticClient().EndSourceFile();


if(mCompilerInst.getDiagnostics().hasErrorOccurred()) {
    llvm::outs() << "CAN'T COMPILE THE CODE";
}

/*GOING FOR THE LLVM BYTE_CODE*/
llvm::Module* module = llvmCodeGen->GetModule();

std::ofstream myfile;
myfile.open ("result",(std::ios::binary|std::ios::out));
llvm::AssemblyAnnotationWriter writer;
llvm::raw_os_ostream raw_stream(myfile);
module->print(raw_stream, &writer);
myfile.flush();
myfile.close();
基本上是不匹配的,我不知道为什么。为什么没有“无捕捉”?我认为额外的代码是由于缺少“nocapture”而生成的。

命令行

clang ... -emit-llvm ...
运行Clang驱动程序,该驱动程序首先运行Clang前端以生成LLVM IR,然后运行LLVM以处理IR,然后发出已处理的IR

代码

ParseAST(mCompilerInst.getPreprocessor(),llvmCodeGen,mCompilerInst.getASTContext());
另一方面,只将AST解析到IR文件中,然后不做任何进一步的处理。您根本没有调用LLVM,只调用了Clang前端,这就是您看到不同代码的原因。它实际上有相同的语义*-只是没有优化

要解决这个问题,您需要在模块上实际运行一些过程(或者更好地使用过程管理器)。你可以看一看这方面的帮助


*实际上,这两个模块并不相等。第1个代码相当于:

kernel void vector_add(global float* vec1, global float* vec2, global float* vec3) {
    int i = get_global_id(0);
    vec3[i] = (vec1[1] + vec2[2]) * 5f;
}
第二个是:

kernel void vector_add(global float* vec1, global float* vec2, global float* vec3) {
    int i = get_global_id(0);
    vec3[i] = (vec1[i] + vec2[i]) * 5f;
}

注意使用的不同索引(
i
vs
1
2
)-我猜第二个版本就是您想要的。如果这不是一个简单的复制粘贴错误,我建议您重新检查您的流,以验证您正在处理正确的文件。

很抱歉,第一个文件的%1%2尚未出现。您可以在Clang后立即获得“纯”IR,而无需通过将
-mllvm-disable llvm optzns
传递到Clang命令行进行任何优化。
kernel void vector_add(global float* vec1, global float* vec2, global float* vec3) {
    int i = get_global_id(0);
    vec3[i] = (vec1[i] + vec2[i]) * 5f;
}