jhuber6 created this revision. jhuber6 added reviewers: jdoerfert, saiislam, JonChesterfield, ABataev, tianshilei1992, RaviNarayanaswamy, gregrodgers. Herald added subscribers: mattd, asavonic, guansong, yaxunl. Herald added a project: All. jhuber6 requested review of this revision. Herald added subscribers: cfe-commits, sstefan1. Herald added a project: clang.
In OpenMP target offloading an in other offloading languages, we maintain a difference between device functions and kernel functions. Kernel functions must be visible to the host and act as the entry point to the target device. Device functions however cannot be called directly by the host and must be called by a kernel function. Currently, we make all definitions on the device protected by default. Because device functions cannot be called or used by the host they should have hidden visibility. This allows for the definitions to be better optimized via LTO or other passes. This patch marks every device function in the AST as having `hidden` visibility. The kernel function is generated later at code-gen and we set its visibility explicitly so it should not be affected. This prevents the user from overriding the visibility, but since the user can't do anything with these symbols anyway there is no point exporting them right now. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D136111 Files: clang/lib/AST/Decl.cpp clang/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp clang/test/OpenMP/nvptx_unsupported_type_codegen.cpp clang/test/OpenMP/target_attribute_convergent.cpp Index: clang/test/OpenMP/target_attribute_convergent.cpp =================================================================== --- clang/test/OpenMP/target_attribute_convergent.cpp +++ clang/test/OpenMP/target_attribute_convergent.cpp @@ -9,5 +9,5 @@ #pragma omp end declare target // CHECK: Function Attrs: {{.*}}convergent{{.*}} -// CHECK: define protected void @_Z3foov() [[ATTRIBUTE_NUMBER:#[0-9]+]] +// CHECK: define hidden void @_Z3foov() [[ATTRIBUTE_NUMBER:#[0-9]+]] // CHECK: attributes [[ATTRIBUTE_NUMBER]] = { {{.*}}convergent{{.*}} } Index: clang/test/OpenMP/nvptx_unsupported_type_codegen.cpp =================================================================== --- clang/test/OpenMP/nvptx_unsupported_type_codegen.cpp +++ clang/test/OpenMP/nvptx_unsupported_type_codegen.cpp @@ -34,18 +34,18 @@ #pragma omp declare target T a = T(); T f = a; -// CHECK: define{{ protected | }}void @{{.+}}foo{{.+}}([[T]]* noundef byval([[T]]) align {{.+}}) +// CHECK: define{{ hidden | }}void @{{.+}}foo{{.+}}([[T]]* noundef byval([[T]]) align {{.+}}) void foo(T a = T()) { return; } -// CHECK: define{{ protected | }}[6 x i64] @{{.+}}bar{{.+}}() +// CHECK: define{{ hidden | }}[6 x i64] @{{.+}}bar{{.+}}() T bar() { // CHECK: bitcast [[T]]* %{{.+}} to [6 x i64]* // CHECK-NEXT: load [6 x i64], [6 x i64]* %{{.+}}, // CHECK-NEXT: ret [6 x i64] return T(); } -// CHECK: define{{ protected | }}void @{{.+}}baz{{.+}}() +// CHECK: define{{ hidden | }}void @{{.+}}baz{{.+}}() void baz() { // CHECK: call [6 x i64] @{{.+}}bar{{.+}}() // CHECK-NEXT: bitcast [[T]]* %{{.+}} to [6 x i64]* @@ -54,17 +54,17 @@ } T1 a1 = T1(); T1 f1 = a1; -// CHECK: define{{ protected | }}void @{{.+}}foo1{{.+}}([[T1]]* noundef byval([[T1]]) align {{.+}}) +// CHECK: define{{ hidden | }}void @{{.+}}foo1{{.+}}([[T1]]* noundef byval([[T1]]) align {{.+}}) void foo1(T1 a = T1()) { return; } -// CHECK: define{{ protected | }}[[T1]] @{{.+}}bar1{{.+}}() +// CHECK: define{{ hidden | }}[[T1]] @{{.+}}bar1{{.+}}() T1 bar1() { // CHECK: load [[T1]], [[T1]]* // CHECK-NEXT: ret [[T1]] return T1(); } -// CHECK: define{{ protected | }}void @{{.+}}baz1{{.+}}() +// CHECK: define{{ hidden | }}void @{{.+}}baz1{{.+}}() void baz1() { // CHECK: call [[T1]] @{{.+}}bar1{{.+}}() T1 t = bar1(); Index: clang/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp =================================================================== --- clang/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp +++ clang/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp @@ -34,12 +34,12 @@ #pragma omp declare target (bar) int caz() { return 0; } -// DEVICE-DAG: define{{ protected | }}noundef i32 [[FOO:@.*foo.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[BAR:@.*bar.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[BAZ:@.*baz.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[DOO:@.*doo.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[CAR:@.*car.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[CAZ:@.*caz.*]]() +// DEVICE-DAG: define hidden noundef i32 [[FOO:@.*foo.*]]() +// DEVICE-DAG: define hidden noundef i32 [[BAR:@.*bar.*]]() +// DEVICE-DAG: define hidden noundef i32 [[BAZ:@.*baz.*]]() +// DEVICE-DAG: define hidden noundef i32 [[DOO:@.*doo.*]]() +// DEVICE-DAG: define hidden noundef i32 [[CAR:@.*car.*]]() +// DEVICE-DAG: define hidden noundef i32 [[CAZ:@.*caz.*]]() static int c = foo() + bar() + baz(); #pragma omp declare target (c) Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -835,6 +835,12 @@ if (Function->getStorageClass() == SC_PrivateExtern) LV.mergeVisibility(HiddenVisibility, true); + // OpenMP target declare device functions are not callable from the host so + // they should not be exported from the device image. This applies to all + // functions as the host-callable kernel functions are emitted at codegen. + if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice) + LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false); + // Note that Sema::MergeCompatibleFunctionDecls already takes care of // merging storage classes and visibility attributes, so we don't have to // look at previous decls in here.
Index: clang/test/OpenMP/target_attribute_convergent.cpp =================================================================== --- clang/test/OpenMP/target_attribute_convergent.cpp +++ clang/test/OpenMP/target_attribute_convergent.cpp @@ -9,5 +9,5 @@ #pragma omp end declare target // CHECK: Function Attrs: {{.*}}convergent{{.*}} -// CHECK: define protected void @_Z3foov() [[ATTRIBUTE_NUMBER:#[0-9]+]] +// CHECK: define hidden void @_Z3foov() [[ATTRIBUTE_NUMBER:#[0-9]+]] // CHECK: attributes [[ATTRIBUTE_NUMBER]] = { {{.*}}convergent{{.*}} } Index: clang/test/OpenMP/nvptx_unsupported_type_codegen.cpp =================================================================== --- clang/test/OpenMP/nvptx_unsupported_type_codegen.cpp +++ clang/test/OpenMP/nvptx_unsupported_type_codegen.cpp @@ -34,18 +34,18 @@ #pragma omp declare target T a = T(); T f = a; -// CHECK: define{{ protected | }}void @{{.+}}foo{{.+}}([[T]]* noundef byval([[T]]) align {{.+}}) +// CHECK: define{{ hidden | }}void @{{.+}}foo{{.+}}([[T]]* noundef byval([[T]]) align {{.+}}) void foo(T a = T()) { return; } -// CHECK: define{{ protected | }}[6 x i64] @{{.+}}bar{{.+}}() +// CHECK: define{{ hidden | }}[6 x i64] @{{.+}}bar{{.+}}() T bar() { // CHECK: bitcast [[T]]* %{{.+}} to [6 x i64]* // CHECK-NEXT: load [6 x i64], [6 x i64]* %{{.+}}, // CHECK-NEXT: ret [6 x i64] return T(); } -// CHECK: define{{ protected | }}void @{{.+}}baz{{.+}}() +// CHECK: define{{ hidden | }}void @{{.+}}baz{{.+}}() void baz() { // CHECK: call [6 x i64] @{{.+}}bar{{.+}}() // CHECK-NEXT: bitcast [[T]]* %{{.+}} to [6 x i64]* @@ -54,17 +54,17 @@ } T1 a1 = T1(); T1 f1 = a1; -// CHECK: define{{ protected | }}void @{{.+}}foo1{{.+}}([[T1]]* noundef byval([[T1]]) align {{.+}}) +// CHECK: define{{ hidden | }}void @{{.+}}foo1{{.+}}([[T1]]* noundef byval([[T1]]) align {{.+}}) void foo1(T1 a = T1()) { return; } -// CHECK: define{{ protected | }}[[T1]] @{{.+}}bar1{{.+}}() +// CHECK: define{{ hidden | }}[[T1]] @{{.+}}bar1{{.+}}() T1 bar1() { // CHECK: load [[T1]], [[T1]]* // CHECK-NEXT: ret [[T1]] return T1(); } -// CHECK: define{{ protected | }}void @{{.+}}baz1{{.+}}() +// CHECK: define{{ hidden | }}void @{{.+}}baz1{{.+}}() void baz1() { // CHECK: call [[T1]] @{{.+}}bar1{{.+}}() T1 t = bar1(); Index: clang/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp =================================================================== --- clang/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp +++ clang/test/OpenMP/nvptx_declare_target_var_ctor_dtor_codegen.cpp @@ -34,12 +34,12 @@ #pragma omp declare target (bar) int caz() { return 0; } -// DEVICE-DAG: define{{ protected | }}noundef i32 [[FOO:@.*foo.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[BAR:@.*bar.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[BAZ:@.*baz.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[DOO:@.*doo.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[CAR:@.*car.*]]() -// DEVICE-DAG: define{{ protected | }}noundef i32 [[CAZ:@.*caz.*]]() +// DEVICE-DAG: define hidden noundef i32 [[FOO:@.*foo.*]]() +// DEVICE-DAG: define hidden noundef i32 [[BAR:@.*bar.*]]() +// DEVICE-DAG: define hidden noundef i32 [[BAZ:@.*baz.*]]() +// DEVICE-DAG: define hidden noundef i32 [[DOO:@.*doo.*]]() +// DEVICE-DAG: define hidden noundef i32 [[CAR:@.*car.*]]() +// DEVICE-DAG: define hidden noundef i32 [[CAZ:@.*caz.*]]() static int c = foo() + bar() + baz(); #pragma omp declare target (c) Index: clang/lib/AST/Decl.cpp =================================================================== --- clang/lib/AST/Decl.cpp +++ clang/lib/AST/Decl.cpp @@ -835,6 +835,12 @@ if (Function->getStorageClass() == SC_PrivateExtern) LV.mergeVisibility(HiddenVisibility, true); + // OpenMP target declare device functions are not callable from the host so + // they should not be exported from the device image. This applies to all + // functions as the host-callable kernel functions are emitted at codegen. + if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice) + LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false); + // Note that Sema::MergeCompatibleFunctionDecls already takes care of // merging storage classes and visibility attributes, so we don't have to // look at previous decls in here.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits