From 9d4b5ef1572ff84b51ecc05e4faef0a6f2427ddd Mon Sep 17 00:00:00 2001 From: LU-JOHN Date: Wed, 3 Jul 2024 18:26:33 -0500 Subject: [PATCH] [sycl-post-link] Internalize non SYCL_EXTERNAL functions (#14318) With -support-dynamic-linking, non SYCL_EXTERNAL functions are internalized. --------- Signed-off-by: Lu, John --- llvm/lib/SYCLLowerIR/ModuleSplitter.cpp | 11 ++ .../exclude_external_functions.ll | 4 +- .../sycl-post-link/internalize_functions.ll | 129 ++++++++++++++++++ 3 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 llvm/test/tools/sycl-post-link/internalize_functions.ll diff --git a/llvm/lib/SYCLLowerIR/ModuleSplitter.cpp b/llvm/lib/SYCLLowerIR/ModuleSplitter.cpp index 0c024610c8235..68104e85e4362 100644 --- a/llvm/lib/SYCLLowerIR/ModuleSplitter.cpp +++ b/llvm/lib/SYCLLowerIR/ModuleSplitter.cpp @@ -29,6 +29,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/GlobalDCE.h" +#include "llvm/Transforms/IPO/Internalize.h" #include "llvm/Transforms/IPO/StripDeadPrototypes.h" #include "llvm/Transforms/IPO/StripSymbols.h" #include "llvm/Transforms/Utils/Cloning.h" @@ -643,6 +644,14 @@ void ModuleDesc::restoreLinkageOfDirectInvokeSimdTargets() { } } +// Predicate for Internalize pass. +bool mustPreserveGV(const GlobalValue &GV) { + if (const Function *F = dyn_cast(&GV)) + if (!canBeImportedFunction(*F)) + return false; + return true; +} + // TODO: try to move all passes (cleanup, spec consts, compile time properties) // in one place and execute MPM.run() only once. void ModuleDesc::cleanup() { @@ -650,6 +659,8 @@ void ModuleDesc::cleanup() { MAM.registerPass([&] { return PassInstrumentationAnalysis(); }); ModulePassManager MPM; // Do cleanup. + if (SupportDynamicLinking) + MPM.addPass(InternalizePass(mustPreserveGV)); MPM.addPass(GlobalDCEPass()); // Delete unreachable globals. MPM.addPass(StripDeadDebugInfoPass()); // Remove dead debug info. MPM.addPass(StripDeadPrototypesPass()); // Remove dead func decls. diff --git a/llvm/test/tools/sycl-post-link/exclude_external_functions.ll b/llvm/test/tools/sycl-post-link/exclude_external_functions.ll index f9c7a3e58f376..f30ba2c53fb3d 100644 --- a/llvm/test/tools/sycl-post-link/exclude_external_functions.ll +++ b/llvm/test/tools/sycl-post-link/exclude_external_functions.ll @@ -29,8 +29,8 @@ ; and is included in the device image. ; Function __private starts with "__" and thus is included in the device image. ; CHECK-SYM-2: childB -; CHECK-LL-2: define weak_odr spir_func void @internal() { -; CHECK-LL-2: define weak_odr spir_func void @__private() #0 { +; CHECK-LL-2: define internal spir_func void @internal() { +; CHECK-LL-2: define internal spir_func void @__private() #0 { ; CHECK-LL-2: define weak_odr spir_func void @childB() #0 { ; CHECK-LL-2: attributes #0 = { "sycl-module-id"="a.cpp" } diff --git a/llvm/test/tools/sycl-post-link/internalize_functions.ll b/llvm/test/tools/sycl-post-link/internalize_functions.ll new file mode 100644 index 0000000000000..03179dd8f5ed4 --- /dev/null +++ b/llvm/test/tools/sycl-post-link/internalize_functions.ll @@ -0,0 +1,129 @@ +; Test that when -support-dynamic-linking is used +; non SYCL-EXTERNAL functions are internalized. +; Variables must not be internalized. + +; RUN: sycl-post-link -symbols -support-dynamic-linking -split=kernel -S < %s -o %t.table +; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM-0 +; RUN: FileCheck %s -input-file=%t_0.ll --check-prefixes CHECK-LL-0 + +; CHECK-SYM-0: foo0 + +; Non SYCL-EXTERNAL Functions are internalized +; foo0 is a SYCL-EXTERNAL function +; CHECK-LL-0-DAG: define weak_odr spir_kernel void @foo0() #0 { +; Internalize does not change available_externally +; CHECK-LL-0-DAG: define available_externally spir_func void @internalA() { +; CHECK-LL-0-DAG: define internal spir_func void @internalB() { +; CHECK-LL-0-DAG: define internal spir_func void @internalC() { +; CHECK-LL-0-DAG: define internal spir_func void @internalD() { +; CHECK-LL-0-DAG: define internal spir_func void @internalE() { +; CHECK-LL-0-DAG: define internal spir_func void @internalF() { +; private is already internalized +; CHECK-LL-0-DAG: define private spir_func void @internalG() { +; CHECK-LL-0-DAG: define internal spir_func void @internalH() { +; CHECK-LL-0-DAG: define internal spir_func void @internalI() { +; CHECK-LL-0-DAG: attributes #0 = { "sycl-module-id"="a.cpp" } + +; Ensure variables are unchanged +; CHECK-LL-0-DAG: @ae = available_externally addrspace(1) global i32 79, align 4 +; CHECK-LL-0-DAG: @i1 = addrspace(1) global i32 1, align 4 +; CHECK-LL-0-DAG: @i2 = internal addrspace(1) global i32 2, align 4 +; CHECK-LL-0-DAG: @i3 = addrspace(1) global i32 3, align 4 +; CHECK-LL-0-DAG: @i4 = common addrspace(1) global i32 0, align 4 +; CHECK-LL-0-DAG: @i5 = internal addrspace(1) global i32 0, align 4 +; CHECK-LL-0-DAG: @color_table = addrspace(2) constant [2 x i32] [i32 0, i32 1], align 4 +; CHECK-LL-0-DAG: @noise_table = external addrspace(2) constant [256 x i32] +; CHECK-LL-0-DAG: @w = addrspace(1) constant i32 0, align 4 +; CHECK-LL-0-DAG: @f.color_table = internal addrspace(2) constant [2 x i32] [i32 2, i32 3], align 4 +; CHECK-LL-0-DAG: @e = external addrspace(1) global i32 +; CHECK-LL-0-DAG: @f.t = internal addrspace(1) global i32 5, align 4 +; CHECK-LL-0-DAG: @f.stint = internal addrspace(1) global i32 0, align 4 +; CHECK-LL-0-DAG: @f.inside = internal addrspace(1) global i32 0, align 4 +; CHECK-LL-0-DAG: @f.b = internal addrspace(2) constant float 1.000000e+00, align 4 + +target triple = "spir64-unknown-unknown" + +@ae = available_externally addrspace(1) global i32 79, align 4 +@i1 = addrspace(1) global i32 1, align 4 +@i2 = internal addrspace(1) global i32 2, align 4 +@i3 = addrspace(1) global i32 3, align 4 +@i4 = common addrspace(1) global i32 0, align 4 +@i5 = internal addrspace(1) global i32 0, align 4 +@color_table = addrspace(2) constant [2 x i32] [i32 0, i32 1], align 4 +@noise_table = external addrspace(2) constant [256 x i32] +@w = addrspace(1) constant i32 0, align 4 +@f.color_table = internal addrspace(2) constant [2 x i32] [i32 2, i32 3], align 4 +@e = external addrspace(1) global i32 +@f.t = internal addrspace(1) global i32 5, align 4 +@f.stint = internal addrspace(1) global i32 0, align 4 +@f.inside = internal addrspace(1) global i32 0, align 4 +@f.b = internal addrspace(2) constant float 1.000000e+00, align 4 + +define available_externally spir_func void @internalA() { + ret void +} + +define dso_local spir_func void @internalB() { + ret void +} + +define external spir_func void @internalC() { + ret void +} + +define internal spir_func void @internalD() { + ret void +} + +define linkonce spir_func void @internalE() { + ret void +} + +define linkonce_odr spir_func void @internalF() { + ret void +} + +define private spir_func void @internalG() { + ret void +} + +define weak spir_func void @internalH() { + ret void +} + +define weak_odr spir_func void @internalI() { + ret void +} + +define weak_odr spir_kernel void @foo0() #0 { + call void @internalA() + call void @internalB() + call void @internalC() + call void @internalD() + call void @internalE() + call void @internalF() + call void @internalG() + call void @internalH() + call void @internalI() + + %1 = load i32, ptr addrspace(1) @ae + %2 = load i32, ptr addrspace(1) @i1 + %3 = load i32, ptr addrspace(1) @i2 + %4 = load i32, ptr addrspace(1) @i3 + %5 = load i32, ptr addrspace(1) @i4 + %6 = load i32, ptr addrspace(1) @i5 + %7 = load i32, ptr addrspace(2) @color_table + %8 = load i32, ptr addrspace(2) @noise_table + %9 = load i32, ptr addrspace(1) @w + %10 = load i32, ptr addrspace(2) @f.color_table + %11 = load i32, ptr addrspace(1) @e + %12 = load i32, ptr addrspace(1) @f.t + %13 = load i32, ptr addrspace(1) @f.stint + %14 = load i32, ptr addrspace(1) @f.inside + %15 = load i32, ptr addrspace(2) @f.b + + + ret void +} + +attributes #0 = { "sycl-module-id"="a.cpp" }