2016-02-12 20 views
1

clang編譯器包含CUDA頭文件host_defines.h,其中__shared__定義爲__attribute__((shared))。當CUDA源文件使用clang編譯爲內部表示(IR)時,__shared__轉換爲addrspace(3)。這些地址空間可以在鐺文件llvm/tools/clang/lib/Basic/Targets.cpp行號1601被觀察爲一個數組編譯CUDA文件時從Clang編譯器中的___屬性___((共享))轉換爲addrspace(3)

static const unsigned NVPTXAddrSpaceMap[] = { 
    1, // opencl_global 
    3, // opencl_local 
    4, // opencl_constant 
    // FIXME: generic has to be added to the target 
    0, // opencl_generic 
    1, // cuda_device 
    4, // cuda_constant 
    3, // cuda_shared 
}; 

因此具體的問題是在該轉換的階段,__attribute__((shared))被轉換爲addrspace(3)。看着鏗鏘的解析和樂器部分並沒有透露這一點。有人可以幫忙嗎?

回答

4

shared屬性在clang的Attr.td文件中定義,稱爲CUDAShared,在內部表示爲CUDASharedAttr。 對於任何Attrbiute,在Leading和解析階段爲Attr.td中定義的所有屬性執行Lexing和解析。在這個階段你不會找到任何必要的見解。

您會看到有價值代碼CUDASharedAttr的第一個點位於clang/lib/Sema/SemaDeclAttr.cpp。 Sema類構建AST,並在SemaDeclAttr.cpp中完成每個屬性的處理。 對於特定CUDASharedAttrhandleSimpleAttribute<CUDASharedAttr>(S, D, Attr);被調用。該函數只是將屬性插入給定的聲明(Decl& D)。

現在屬性被附加到一個Decl中,您可以查詢該聲明是否使用以下屬性:D.hasAttr<CUDASharedAttr>()。例如,在SemaDecl.cpp中強制執行CUDA共享內存聲明的限制,並將共享內存變量的存儲類設置爲靜態。

您將再次找到CUDASharedAttr bin clang/lib/CodeGen/CodeGenModule.cpp,其中發出實際LLVM IR。 在CodeGenModule.cpp您有以下功能:

unsigned CodeGenModule::GetGlobalVarAddressSpace(const VarDecl *D, 
               unsigned AddrSpace) { 
    if (LangOpts.CUDA && LangOpts.CUDAIsDevice) { 
    if (D->hasAttr<CUDAConstantAttr>()) 
     AddrSpace = getContext().getTargetAddressSpace(LangAS::cuda_constant); 
    else if (D->hasAttr<CUDASharedAttr>()) 
     AddrSpace = getContext().getTargetAddressSpace(LangAS::cuda_shared); 
    else 
     AddrSpace = getContext().getTargetAddressSpace(LangAS::cuda_device); 
    } 

    return AddrSpace; 
} 

功能querys從實際的目標共享功能的地址空間,即對於nvptx針對您發佈的地址空間映射用於:

static const unsigned NVPTXAddrSpaceMap[] = { 
    1, // opencl_global 
    3, // opencl_local 
    4, // opencl_constant 
    // FIXME: generic has to be added to the target 
    0, // opencl_generic 
    1, // cuda_device 
    4, // cuda_constant 
    3, // cuda_shared 
}; 

LangAS::cuda_shared對應的地址空間3.

經過這些步驟,你會得到一個全局變量與地址空間3最終IR模塊中是這樣的:

; ModuleID = 'sm.cu' 
    target datalayout = "e-p:64:64:64-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 = "nvptx64-unknown-unknown" 

    @vec= internal unnamed_addr addrspace(3) global [32 x i32] zeroinitializer, align 4 

    ; Function Attrs: nounwind readnone 
    declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() #0 

    ; Function Attrs: nounwind readnone 
    declare i32 @llvm.nvvm.read.ptx.sreg.tid.y() #0 

    define ptx_kernel void @__pacxx_kernel0(i32 addrspace(1)* %tmp) { 
    %1 = tail call spir_func i32 @llvm.nvvm.read.ptx.sreg.tid.x() #1 
    %2 = zext i32 %1 to i64 
    %3 = getelementptr i32, i32 addrspace(1)* %tmp, i64 %2 
    %4 = load i32, i32 addrspace(1)* %3, align 4 
    %5 = getelementptr [32 x i32], [32 x i32] addrspace(3)* @vec, i64 0, i64 %2 
    store i32 %4, i32 addrspace(3)* %5, align 4 
    %6 = tail call spir_func i32 @llvm.nvvm.read.ptx.sreg.tid.y() #1 
    %7 = zext i32 %6 to i64 
    %8 = getelementptr [32 x i32], [32 x i32] addrspace(3)* @vec, i64 0, i64 %7 
    %9 = load i32, i32 addrspace(3)* %8, align 4 
    %10 = getelementptr i32, i32 addrspace(1)* %tmp, i64 %7 
    store i32 %9, i32 addrspace(1)* %10, align 4 
    ret void 
    } 
+1

要增加對類似於「\ __ shared__」的CUDA中的新內存類型「\ __ noc__」的支持,我修改了所需的clang和llvm文件。從答案中,我瞭解了程序流並在/llvm/tools/clang/lib/Headers/\__clang_cuda_runtime_wrapper.h中添加了#define \ __ noc__ \ __ attribute __((noc)),其中host_defines包含在clang中。當我編譯llvm並安裝時,生成的IR文件沒有某些字段,例如「Function Attrs:uwtable」。當clang在\ __ noc__中沒有#define時使用,這個問題就不存在了。任何直覺都將非常有幫助 –

+2

uwtable通常來自異常處理。沒有代碼很難診斷。 –

+1

遵循答案中的步驟,看起來clang編譯器忽略添加的新內存類型。爲了更好地瞭解問題,請添加:http:// stackoverflow。COM /問題/ 35519825 /添加支持換一個存儲器型相似到共享在-CUDA的使用-鐺-LLVM –