[PATCH] D98814: [CUDA][HIP] Mark device var used by host only
This revision was automatically updated to reflect the committed changes. yaxunl marked 2 inline comments as done. Closed by commit rGd5c0f00e216a: [CUDA][HIP] Mark device var used by host only (authored by yaxunl). Herald added a project: clang. Changed prior to commit: https://reviews.llvm.org/D98814?vs=332157=338313#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D98814/new/ https://reviews.llvm.org/D98814 Files: clang/lib/CodeGen/CGCUDANV.cpp clang/test/CodeGenCUDA/host-used-device-var.cu Index: clang/test/CodeGenCUDA/host-used-device-var.cu === --- /dev/null +++ clang/test/CodeGenCUDA/host-used-device-var.cu @@ -0,0 +1,47 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device -x hip %s \ +// RUN: -std=c++11 -O3 -mllvm -amdgpu-internalize-symbols -emit-llvm -o - \ +// RUN: | FileCheck %s + +#include "Inputs/cuda.h" + +// Check device variables used by neither host nor device functioins are not kept. + +// CHECK-NOT: @v1 +__device__ int v1; + +// CHECK-NOT: @v2 +__constant__ int v2; + +// CHECK-NOT: @_ZL2v3 +static __device__ int v3; + +// Check device variables used by host functions are kept. + +// CHECK-DAG: @u1 +__device__ int u1; + +// CHECK-DAG: @u2 +__constant__ int u2; + +// Check host-used static device var is in llvm.compiler.used. +// CHECK-DAG: @_ZL2u3 +static __device__ int u3; + +// Check device-used static device var is emitted but is not in llvm.compiler.used. +// CHECK-DAG: @_ZL2u4 +static __device__ int u4; + +// Check device variables with used attribute are always kept. +// CHECK-DAG: @u5 +__device__ __attribute__((used)) int u5; + +int fun1() { + return u1 + u2 + u3; +} + +__global__ void kern1(int **x) { + *x = +} +// Check the exact list of variables to ensure @_ZL2u4 is not among them. +// CHECK: @llvm.compiler.used = {{[^@]*}} @_ZL2u3 {{[^@]*}} @u1 {{[^@]*}} @u2 {{[^@]*}} @u5 Index: clang/lib/CodeGen/CGCUDANV.cpp === --- clang/lib/CodeGen/CGCUDANV.cpp +++ clang/lib/CodeGen/CGCUDANV.cpp @@ -1089,6 +1089,28 @@ llvm::Function *CGNVCUDARuntime::finalizeModule() { if (CGM.getLangOpts().CUDAIsDevice) { transformManagedVars(); + +// Mark ODR-used device variables as compiler used to prevent it from being +// eliminated by optimization. This is necessary for device variables +// ODR-used by host functions. Sema correctly marks them as ODR-used no +// matter whether they are ODR-used by device or host functions. +// +// We do not need to do this if the variable has used attribute since it +// has already been added. +// +// Static device variables have been externalized at this point, therefore +// variables with LLVM private or internal linkage need not be added. +for (auto & : DeviceVars) { + auto Kind = Info.Flags.getKind(); + if (!Info.Var->isDeclaration() && + !llvm::GlobalValue::isLocalLinkage(Info.Var->getLinkage()) && + (Kind == DeviceVarFlags::Variable || + Kind == DeviceVarFlags::Surface || + Kind == DeviceVarFlags::Texture) && + Info.D->isUsed() && !Info.D->hasAttr()) { +CGM.addCompilerUsedGlobal(Info.Var); + } +} return nullptr; } return makeModuleCtorFunction(); Index: clang/test/CodeGenCUDA/host-used-device-var.cu === --- /dev/null +++ clang/test/CodeGenCUDA/host-used-device-var.cu @@ -0,0 +1,47 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device -x hip %s \ +// RUN: -std=c++11 -O3 -mllvm -amdgpu-internalize-symbols -emit-llvm -o - \ +// RUN: | FileCheck %s + +#include "Inputs/cuda.h" + +// Check device variables used by neither host nor device functioins are not kept. + +// CHECK-NOT: @v1 +__device__ int v1; + +// CHECK-NOT: @v2 +__constant__ int v2; + +// CHECK-NOT: @_ZL2v3 +static __device__ int v3; + +// Check device variables used by host functions are kept. + +// CHECK-DAG: @u1 +__device__ int u1; + +// CHECK-DAG: @u2 +__constant__ int u2; + +// Check host-used static device var is in llvm.compiler.used. +// CHECK-DAG: @_ZL2u3 +static __device__ int u3; + +// Check device-used static device var is emitted but is not in llvm.compiler.used. +// CHECK-DAG: @_ZL2u4 +static __device__ int u4; + +// Check device variables with used attribute are always kept. +// CHECK-DAG: @u5 +__device__ __attribute__((used)) int u5; + +int fun1() { + return u1 + u2 + u3; +} + +__global__ void kern1(int **x) { + *x = +} +// Check the exact list of variables to ensure @_ZL2u4 is not among them. +// CHECK: @llvm.compiler.used = {{[^@]*}} @_ZL2u3 {{[^@]*}} @u1 {{[^@]*}} @u2 {{[^@]*}} @u5 Index: clang/lib/CodeGen/CGCUDANV.cpp
[PATCH] D98814: [CUDA][HIP] Mark device var used by host only
yaxunl marked 2 inline comments as done. yaxunl added inline comments. Comment at: clang/test/CodeGenCUDA/host-used-device-var.cu:31-33 +// Check device-used static device var is not in llvm.compiler.used. +// CHECK-DAG: @_ZL2u4 +static __device__ int u4; tra wrote: > I'd rephrase it as 'but is not in llvm.compiler.used' > will do Comment at: clang/test/CodeGenCUDA/host-used-device-var.cu:46 +} +// CHECK: @llvm.compiler.used = {{[^@]*}} @_ZL2u3 {{[^@]*}} @u1 {{[^@]*}} @u2 {{[^@]*}} @u5 tra wrote: > I'd add a comment that we're effectively matching the exact list of the > variables here and that ensures that `@_ZL2u4` is not among them. > will do CHANGES SINCE LAST ACTION https://reviews.llvm.org/D98814/new/ https://reviews.llvm.org/D98814 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D98814: [CUDA][HIP] Mark device var used by host only
tra accepted this revision. tra added inline comments. This revision is now accepted and ready to land. Comment at: clang/test/CodeGenCUDA/host-used-device-var.cu:31-33 +// Check device-used static device var is not in llvm.compiler.used. +// CHECK-DAG: @_ZL2u4 +static __device__ int u4; I'd rephrase it as 'but is not in llvm.compiler.used' Comment at: clang/test/CodeGenCUDA/host-used-device-var.cu:46 +} +// CHECK: @llvm.compiler.used = {{[^@]*}} @_ZL2u3 {{[^@]*}} @u1 {{[^@]*}} @u2 {{[^@]*}} @u5 I'd add a comment that we're effectively matching the exact list of the variables here and that ensures that `@_ZL2u4` is not among them. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D98814/new/ https://reviews.llvm.org/D98814 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D98814: [CUDA][HIP] Mark device var used by host only
yaxunl updated this revision to Diff 332157. yaxunl marked an inline comment as done. yaxunl added a comment. revised by Artem's comments CHANGES SINCE LAST ACTION https://reviews.llvm.org/D98814/new/ https://reviews.llvm.org/D98814 Files: clang/lib/CodeGen/CGCUDANV.cpp clang/test/CodeGenCUDA/host-used-device-var.cu Index: clang/test/CodeGenCUDA/host-used-device-var.cu === --- /dev/null +++ clang/test/CodeGenCUDA/host-used-device-var.cu @@ -0,0 +1,46 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device -x hip %s \ +// RUN: -std=c++11 -O3 -mllvm -amdgpu-internalize-symbols -emit-llvm -o - \ +// RUN: | FileCheck %s + +#include "Inputs/cuda.h" + +// Check device variables used by neither host nor device functioins are not kept. + +// CHECK-NOT: @v1 +__device__ int v1; + +// CHECK-NOT: @v2 +__constant__ int v2; + +// CHECK-NOT: @_ZL2v3 +static __device__ int v3; + +// Check device variables used by host functions are kept. + +// CHECK-DAG: @u1 +__device__ int u1; + +// CHECK-DAG: @u2 +__constant__ int u2; + +// Check host-used static device var is in llvm.compiler.used. +// CHECK-DAG: @_ZL2u3 +static __device__ int u3; + +// Check device-used static device var is not in llvm.compiler.used. +// CHECK-DAG: @_ZL2u4 +static __device__ int u4; + +// Check device variables with used attribute are always kept. +// CHECK-DAG: @u5 +__device__ __attribute__((used)) int u5; + +int fun1() { + return u1 + u2 + u3; +} + +__global__ void kern1(int **x) { + *x = +} +// CHECK: @llvm.compiler.used = {{[^@]*}} @_ZL2u3 {{[^@]*}} @u1 {{[^@]*}} @u2 {{[^@]*}} @u5 Index: clang/lib/CodeGen/CGCUDANV.cpp === --- clang/lib/CodeGen/CGCUDANV.cpp +++ clang/lib/CodeGen/CGCUDANV.cpp @@ -1084,6 +1084,28 @@ llvm::Function *CGNVCUDARuntime::finalizeModule() { if (CGM.getLangOpts().CUDAIsDevice) { transformManagedVars(); + +// Mark ODR-used device variables as compiler used to prevent it from being +// eliminated by optimization. This is necessary for device variables +// ODR-used by host functions. Sema correctly marks them as ODR-used no +// matter whether they are ODR-used by device or host functions. +// +// We do not need to do this if the variable has used attribute since it +// has already been added. +// +// Static device variables have been externalized at this point, therefore +// variables with LLVM private or internal linkage need not be added. +for (auto & : DeviceVars) { + auto Kind = Info.Flags.getKind(); + if (!Info.Var->isDeclaration() && + !llvm::GlobalValue::isLocalLinkage(Info.Var->getLinkage()) && + (Kind == DeviceVarFlags::Variable || + Kind == DeviceVarFlags::Surface || + Kind == DeviceVarFlags::Texture) && + Info.D->isUsed() && !Info.D->hasAttr()) { +CGM.addCompilerUsedGlobal(Info.Var); + } +} return nullptr; } return makeModuleCtorFunction(); Index: clang/test/CodeGenCUDA/host-used-device-var.cu === --- /dev/null +++ clang/test/CodeGenCUDA/host-used-device-var.cu @@ -0,0 +1,46 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device -x hip %s \ +// RUN: -std=c++11 -O3 -mllvm -amdgpu-internalize-symbols -emit-llvm -o - \ +// RUN: | FileCheck %s + +#include "Inputs/cuda.h" + +// Check device variables used by neither host nor device functioins are not kept. + +// CHECK-NOT: @v1 +__device__ int v1; + +// CHECK-NOT: @v2 +__constant__ int v2; + +// CHECK-NOT: @_ZL2v3 +static __device__ int v3; + +// Check device variables used by host functions are kept. + +// CHECK-DAG: @u1 +__device__ int u1; + +// CHECK-DAG: @u2 +__constant__ int u2; + +// Check host-used static device var is in llvm.compiler.used. +// CHECK-DAG: @_ZL2u3 +static __device__ int u3; + +// Check device-used static device var is not in llvm.compiler.used. +// CHECK-DAG: @_ZL2u4 +static __device__ int u4; + +// Check device variables with used attribute are always kept. +// CHECK-DAG: @u5 +__device__ __attribute__((used)) int u5; + +int fun1() { + return u1 + u2 + u3; +} + +__global__ void kern1(int **x) { + *x = +} +// CHECK: @llvm.compiler.used = {{[^@]*}} @_ZL2u3 {{[^@]*}} @u1 {{[^@]*}} @u2 {{[^@]*}} @u5 Index: clang/lib/CodeGen/CGCUDANV.cpp === --- clang/lib/CodeGen/CGCUDANV.cpp +++ clang/lib/CodeGen/CGCUDANV.cpp @@ -1084,6 +1084,28 @@ llvm::Function *CGNVCUDARuntime::finalizeModule() { if (CGM.getLangOpts().CUDAIsDevice) { transformManagedVars(); + +// Mark ODR-used device variables as compiler used to prevent it from being +// eliminated by optimization. This is necessary for device variables +// ODR-used by host
[PATCH] D98814: [CUDA][HIP] Mark device var used by host only
yaxunl marked an inline comment as done. yaxunl added inline comments. Comment at: clang/lib/CodeGen/CGCUDANV.cpp:1102 + Info.D->isUsed() && !Info.D->hasAttr()) { +CGM.addCompilerUsedGlobal(Info.Var); + } tra wrote: > Do we want to limit it further to only externally-visible variables? > I think we already externalize the variables we want to be visible across > host/device boundary. > If the variable is not visible, there's no point keeping it around as the > runtime will not be able to find it in the GPU binary. Good point. Will do CHANGES SINCE LAST ACTION https://reviews.llvm.org/D98814/new/ https://reviews.llvm.org/D98814 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D98814: [CUDA][HIP] Mark device var used by host only
tra added inline comments. Comment at: clang/lib/CodeGen/CGCUDANV.cpp:1102 + Info.D->isUsed() && !Info.D->hasAttr()) { +CGM.addCompilerUsedGlobal(Info.Var); + } Do we want to limit it further to only externally-visible variables? I think we already externalize the variables we want to be visible across host/device boundary. If the variable is not visible, there's no point keeping it around as the runtime will not be able to find it in the GPU binary. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D98814/new/ https://reviews.llvm.org/D98814 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D98814: [CUDA][HIP] Mark device var used by host only
yaxunl created this revision. yaxunl added a reviewer: tra. yaxunl requested review of this revision. Add device variables to llvm.compiler.used if they are ODR-used by either host or device functions. This is necessary to prevent them from being eliminated by whole-program optimization where the compiler has no way to know a device variable is used by some host code. https://reviews.llvm.org/D98814 Files: clang/lib/CodeGen/CGCUDANV.cpp clang/test/CodeGenCUDA/host-used-device-var.cu Index: clang/test/CodeGenCUDA/host-used-device-var.cu === --- /dev/null +++ clang/test/CodeGenCUDA/host-used-device-var.cu @@ -0,0 +1,33 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device -x hip %s \ +// RUN: -std=c++11 -O3 -mllvm -amdgpu-internalize-symbols -emit-llvm -o - \ +// RUN: | FileCheck %s + +#include "Inputs/cuda.h" + +// Check device variables used by neither host nor device functioins are not kept. + +// CHECK-NOT: @v1 +__device__ int v1; + +// CHECK-NOT: @v2 +__constant__ int v2; + +// Check device variables used by host functions are kept. + +// CHECK: @u1 +__device__ int u1; + +// CHECK: @u2 +__constant__ int u2; + +// Check device variables with used attribute are always kept. + +// CHECK: @u3 +__device__ __attribute__((used)) int u3; + +int fun1() { + return u1 + u2; +} + +// CHECK: @llvm.compiler.used = {{[^@]*}} @u1 {{[^@]*}} @u2 {{[^@]*}} @u3 Index: clang/lib/CodeGen/CGCUDANV.cpp === --- clang/lib/CodeGen/CGCUDANV.cpp +++ clang/lib/CodeGen/CGCUDANV.cpp @@ -1084,6 +1084,24 @@ llvm::Function *CGNVCUDARuntime::finalizeModule() { if (CGM.getLangOpts().CUDAIsDevice) { transformManagedVars(); + +// Mark ODR-used device variables as compiler used to prevent it from being +// eliminated by optimization. This is necessary for device variables +// ODR-used by host functions. Sema correctly marks them as ODR-used no +// matter whether they are ODR-used by device or host functions. +// +// We do not need to do this if the variable has used attribute since it +// has already been added. +for (auto & : DeviceVars) { + auto Kind = Info.Flags.getKind(); + if (!Info.Var->isDeclaration() && + (Kind == DeviceVarFlags::Variable || + Kind == DeviceVarFlags::Surface || + Kind == DeviceVarFlags::Texture) && + Info.D->isUsed() && !Info.D->hasAttr()) { +CGM.addCompilerUsedGlobal(Info.Var); + } +} return nullptr; } return makeModuleCtorFunction(); Index: clang/test/CodeGenCUDA/host-used-device-var.cu === --- /dev/null +++ clang/test/CodeGenCUDA/host-used-device-var.cu @@ -0,0 +1,33 @@ +// REQUIRES: amdgpu-registered-target +// RUN: %clang_cc1 -triple amdgcn-amd-amdhsa -fcuda-is-device -x hip %s \ +// RUN: -std=c++11 -O3 -mllvm -amdgpu-internalize-symbols -emit-llvm -o - \ +// RUN: | FileCheck %s + +#include "Inputs/cuda.h" + +// Check device variables used by neither host nor device functioins are not kept. + +// CHECK-NOT: @v1 +__device__ int v1; + +// CHECK-NOT: @v2 +__constant__ int v2; + +// Check device variables used by host functions are kept. + +// CHECK: @u1 +__device__ int u1; + +// CHECK: @u2 +__constant__ int u2; + +// Check device variables with used attribute are always kept. + +// CHECK: @u3 +__device__ __attribute__((used)) int u3; + +int fun1() { + return u1 + u2; +} + +// CHECK: @llvm.compiler.used = {{[^@]*}} @u1 {{[^@]*}} @u2 {{[^@]*}} @u3 Index: clang/lib/CodeGen/CGCUDANV.cpp === --- clang/lib/CodeGen/CGCUDANV.cpp +++ clang/lib/CodeGen/CGCUDANV.cpp @@ -1084,6 +1084,24 @@ llvm::Function *CGNVCUDARuntime::finalizeModule() { if (CGM.getLangOpts().CUDAIsDevice) { transformManagedVars(); + +// Mark ODR-used device variables as compiler used to prevent it from being +// eliminated by optimization. This is necessary for device variables +// ODR-used by host functions. Sema correctly marks them as ODR-used no +// matter whether they are ODR-used by device or host functions. +// +// We do not need to do this if the variable has used attribute since it +// has already been added. +for (auto & : DeviceVars) { + auto Kind = Info.Flags.getKind(); + if (!Info.Var->isDeclaration() && + (Kind == DeviceVarFlags::Variable || + Kind == DeviceVarFlags::Surface || + Kind == DeviceVarFlags::Texture) && + Info.D->isUsed() && !Info.D->hasAttr()) { +CGM.addCompilerUsedGlobal(Info.Var); + } +} return nullptr; } return makeModuleCtorFunction(); ___ cfe-commits mailing list cfe-commits@lists.llvm.org