Skip to content

Commit

Permalink
[sycl-post-link] Internalize non SYCL_EXTERNAL functions (#14318)
Browse files Browse the repository at this point in the history
With -support-dynamic-linking, non SYCL_EXTERNAL functions are
internalized.

---------

Signed-off-by: Lu, John <john.lu@intel.com>
  • Loading branch information
LU-JOHN authored Jul 3, 2024
1 parent a458595 commit 9d4b5ef
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 2 deletions.
11 changes: 11 additions & 0 deletions llvm/lib/SYCLLowerIR/ModuleSplitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -643,13 +644,23 @@ void ModuleDesc::restoreLinkageOfDirectInvokeSimdTargets() {
}
}

// Predicate for Internalize pass.
bool mustPreserveGV(const GlobalValue &GV) {
if (const Function *F = dyn_cast<Function>(&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() {
ModuleAnalysisManager MAM;
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.
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/tools/sycl-post-link/exclude_external_functions.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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" }

Expand Down
129 changes: 129 additions & 0 deletions llvm/test/tools/sycl-post-link/internalize_functions.ll
Original file line number Diff line number Diff line change
@@ -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" }

0 comments on commit 9d4b5ef

Please sign in to comment.