Skip to content

Commit 34e1f7c

Browse files
[sycl-post-link] Do not drop SYCL_EXTERNAL functions (#3793)
There are a few use cases where unreferenced device functions should go through sycl-post-link. Such functions may be referenced later, for example on a SPIRV level. Dynamic linking of device binary images is one such case. I.e. when the kernel will have an import list with functionality implemented in a dynamic library. DPCPP RT will resolve imported functions, which could be implemented as SYCL_EXTERNAL functions. Thus we need to allow SYCL_EXTERNAL to go through sycl-post-link to make it work. ESIMD/ISPC interoperability is another motivation for this functionality.
1 parent 7cb6ad2 commit 34e1f7c

File tree

13 files changed

+297
-33
lines changed

13 files changed

+297
-33
lines changed

llvm/test/tools/sycl-post-link/erase_used.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ target triple = "spir64-unknown-unknown-sycldevice"
1010
; CHECK-NOT: llvm.used
1111
@llvm.used = appending global [2 x i8*] [i8* bitcast (void ()* @foo to i8*), i8* bitcast (void ()* @bar to i8*)], section "llvm.metadata"
1212

13-
define weak_odr spir_kernel void @foo() {
13+
define weak_odr spir_kernel void @foo() #0 {
1414
ret void
1515
}
1616

17-
define weak_odr spir_kernel void @bar() {
17+
define weak_odr spir_kernel void @bar() #0 {
1818
ret void
1919
}
20+
21+
attributes #0 = { "sycl-module-id"="a.cpp" }

llvm/test/tools/sycl-post-link/spec-constants/spec_const_and_split.ll

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,27 @@
1919

2020
declare dso_local spir_func zeroext i1 @_Z33__sycl_getScalarSpecConstantValueIbET_PKc(i8 addrspace(4)*)
2121

22-
define dso_local spir_kernel void @KERNEL_AAA() {
22+
define dso_local spir_kernel void @KERNEL_AAA() #0 {
2323
%1 = call spir_func zeroext i1 @_Z33__sycl_getScalarSpecConstantValueIbET_PKc(i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([10 x i8], [10 x i8]* @SCSymID, i64 0, i64 0) to i8 addrspace(4)*))
2424
; CHECK-IR0: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 1, i1 false)
2525
%2 = call spir_func zeroext i1 @_Z33__sycl_getScalarSpecConstantValueIbET_PKc(i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([11 x i8], [11 x i8]* @SCSymID2, i64 0, i64 0) to i8 addrspace(4)*))
2626
; CHECK-IR0: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 0, i1 false)
2727
ret void
2828
}
2929

30-
define dso_local spir_kernel void @KERNEL_BBB() {
30+
define dso_local spir_kernel void @KERNEL_BBB() #0 {
3131
%1 = call spir_func zeroext i1 @_Z33__sycl_getScalarSpecConstantValueIbET_PKc(i8 addrspace(4)* addrspacecast (i8* getelementptr inbounds ([10 x i8], [10 x i8]* @SCSymID, i64 0, i64 0) to i8 addrspace(4)*))
3232
; CHECK-IR1: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 0, i1 false)
3333
ret void
3434
}
3535

36-
define dso_local spir_kernel void @KERNEL_CCC() {
36+
define dso_local spir_kernel void @KERNEL_CCC() #0 {
3737
; CHECK-IR2: define{{.*}}spir_kernel void @KERNEL_CCC
3838
ret void
3939
}
4040

41+
attributes #0 = { "sycl-module-id"="a.cpp" }
42+
4143
; CHECK-IR0: !sycl.specialization-constants = !{![[#MD0:]], ![[#MD1:]]}
4244
; CHECK-IR0: ![[#MD0:]] = !{!"SpecConst2", i32 0, i32 0, i32 1}
4345
; CHECK-IR0: ![[#MD1:]] = !{!"SpecConst", i32 1, i32 0, i32 1}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: sycl-post-link -ir-output-only -split=auto -S %s -o %t.ll
2+
; RUN: FileCheck %s -input-file=%t.ll
3+
4+
; This test checks that known SPIRV and SYCL builtin functions
5+
; (that are also marked with SYCL_EXTRENAL) are not considered
6+
; as module entry points and thus are not added as entry to the
7+
; device binary symbol table. So, they can be dropped if
8+
; unreferenced.
9+
10+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
11+
target triple = "spir64-unknown-linux-sycldevice"
12+
13+
define dso_local spir_func void @_Z28__spirv_GlobalInvocationId_xv() #0 {
14+
ret void
15+
}
16+
define dso_local spir_func void @_Z28__spXrv_GlobalInvocationId_xv() #0 {
17+
ret void
18+
}
19+
20+
define dso_local spir_func void @_Z33__sycl_getScalarSpecConstantValue() #0 {
21+
ret void
22+
}
23+
define dso_local spir_func void @_Z33__sXcl_getScalarSpecConstantValue() #0 {
24+
ret void
25+
}
26+
27+
attributes #0 = { "sycl-module-id"="a.cpp" }
28+
29+
; CHECK-NOT: define dso_local spir_func void @_Z28__spirv_GlobalInvocationId_xv()
30+
; CHECK-NOT: define dso_local spir_func void @_Z33__sycl_getScalarSpecConstantValue()
31+
32+
; CHECK-DAG: define dso_local spir_func void @_Z28__spXrv_GlobalInvocationId_xv()
33+
; CHECK-DAG: define dso_local spir_func void @_Z33__sXcl_getScalarSpecConstantValue()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: sycl-post-link -ir-output-only -split=auto -S %s -o %t.ll
2+
; RUN: FileCheck %s -input-file=%t.ll
3+
4+
; This test checks that unreferenced functions without sycl-module-id
5+
; attribute are dropped from the module after splitting.
6+
7+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
8+
target triple = "spir64-unknown-linux-sycldevice"
9+
10+
define dso_local spir_func void @externalDeviceFunc() #0 {
11+
ret void
12+
}
13+
14+
define dso_local spir_func void @unreferencedFunc() {
15+
ret void
16+
}
17+
18+
attributes #0 = { "sycl-module-id"="a.cpp" }
19+
20+
; CHECK: define dso_local spir_func void @externalDeviceFunc()
21+
; CHECK-NOT: define dso_local spir_func void @unreferencedFunc()
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: sycl-post-link -ir-output-only -split=auto -S %s -o %t.ll
2+
; RUN: FileCheck %s -input-file=%t.ll
3+
4+
; This test checks that indirectly referenced functions (with sycl-module-id
5+
; attribute) are not dropped from the module.
6+
7+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
8+
target triple = "spir64-unknown-linux-sycldevice"
9+
10+
define dso_local spir_func void @indRefDeviceFunc() #0 {
11+
ret void
12+
}
13+
14+
attributes #0 = { "sycl-module-id"="a.cpp" "referenced-indirectly"}
15+
16+
; CHECK: define dso_local spir_func void @indRefDeviceFunc()
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; RUN: sycl-post-link -split=auto -split-esimd -lower-esimd -O0 -S %s -o %t.table
2+
; RUN: FileCheck %s -input-file=%t_esimd_0.ll
3+
4+
; This test checks that unreferenced functions with sycl-module-id
5+
; attribute are not dropped from the module and ESIMD lowering
6+
; happens for them as well.
7+
8+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
9+
target triple = "spir64-unknown-linux-sycldevice"
10+
11+
@__spirv_BuiltInGlobalInvocationId = external dso_local local_unnamed_addr addrspace(1) constant <3 x i64>, align 32
12+
13+
define dso_local spir_func void @externalESIMDDeviceFunc() #0 !sycl_explicit_simd !0 {
14+
entry:
15+
%0 = load <3 x i64>, <3 x i64> addrspace(4)* addrspacecast (<3 x i64> addrspace(1)* @__spirv_BuiltInGlobalInvocationId to <3 x i64> addrspace(4)*), align 32
16+
%1 = extractelement <3 x i64> %0, i64 0
17+
ret void
18+
}
19+
20+
attributes #0 = { "sycl-module-id"="a.cpp" }
21+
22+
!0 = !{}
23+
24+
; CHECK: define dso_local spir_func void @externalESIMDDeviceFunc()
25+
; CHECK: entry:
26+
; CHECK: call <3 x i32> @llvm.genx.local.id.v3i32()
27+
; CHECK: call <3 x i32> @llvm.genx.local.size.v3i32()
28+
; CHECK: call i32 @llvm.genx.group.id.x()
29+
; CHECK: ret void
30+
; CHECK: }
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
; RUN: sycl-post-link -ir-output-only -split=auto -S %s -o %t.ll
2+
; RUN: FileCheck %s -input-file=%t.ll
3+
4+
; This test checks that unreferenced functions with sycl-module-id
5+
; attribute are not dropped from the module after splitting
6+
; in global mode.
7+
8+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
9+
target triple = "spir64-unknown-linux-sycldevice"
10+
11+
define dso_local spir_func void @externalDeviceFunc() #0 {
12+
ret void
13+
}
14+
15+
define dso_local spir_kernel void @kernel1() #0 {
16+
ret void
17+
}
18+
19+
attributes #0 = { "sycl-module-id"="a.cpp" }
20+
21+
; CHECK-DAG: define dso_local spir_func void @externalDeviceFunc()
22+
; CHECK-DAG: define dso_local spir_kernel void @kernel1()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; RUN: sycl-post-link -split=kernel -symbols -S %s -o %t.table
2+
; RUN: FileCheck %s -input-file=%t_0.ll --check-prefixes CHECK-IR1
3+
; RUN: FileCheck %s -input-file=%t_1.ll --check-prefixes CHECK-IR2
4+
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM1
5+
; RUN: FileCheck %s -input-file=%t_1.sym --check-prefixes CHECK-SYM2
6+
7+
; This test checks that unreferenced functions with sycl-module-id
8+
; attribute are not dropped from the module after splitting
9+
; in per-kernel mode.
10+
11+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
12+
target triple = "spir64-unknown-linux-sycldevice"
13+
14+
define dso_local spir_func void @externalDeviceFunc() #0 {
15+
ret void
16+
}
17+
18+
define dso_local spir_kernel void @kernel1() #0 {
19+
ret void
20+
}
21+
22+
attributes #0 = { "sycl-module-id"="a.cpp" }
23+
24+
; CHECK-IR1: define dso_local spir_func void @externalDeviceFunc()
25+
; CHECK-IR2: define dso_local spir_kernel void @kernel1()
26+
27+
; CHECK-SYM1: externalDeviceFunc
28+
; CHECK-SYM2: kernel1
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
; RUN: sycl-post-link -split=source -symbols -S %s -o %t.table
2+
; RUN: FileCheck %s -input-file=%t_0.ll --check-prefixes CHECK-IR1
3+
; RUN: FileCheck %s -input-file=%t_1.ll --check-prefixes CHECK-IR2
4+
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM1
5+
; RUN: FileCheck %s -input-file=%t_1.sym --check-prefixes CHECK-SYM2
6+
7+
; This test checks that unreferenced functions with sycl-module-id
8+
; attribute are not dropped from the module after splitting
9+
; in per-source mode.
10+
11+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
12+
target triple = "spir64-unknown-linux-sycldevice"
13+
14+
define dso_local spir_func void @externalDeviceFunc() #0 {
15+
ret void
16+
}
17+
18+
define dso_local spir_kernel void @kernel1() #1 {
19+
ret void
20+
}
21+
22+
attributes #0 = { "sycl-module-id"="a.cpp" }
23+
attributes #1 = { "sycl-module-id"="b.cpp" }
24+
25+
; CHECK-IR1: define dso_local spir_func void @externalDeviceFunc()
26+
; CHECK-IR2: define dso_local spir_kernel void @kernel1()
27+
28+
; CHECK-SYM1: externalDeviceFunc
29+
; CHECK-SYM2: kernel1
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; RUN: sycl-post-link -split=source -symbols -S %s -o %t.table
2+
; RUN: FileCheck %s -input-file=%t_0.ll --check-prefixes CHECK-IR1
3+
; RUN: FileCheck %s -input-file=%t_1.ll --check-prefixes CHECK-IR2
4+
; RUN: FileCheck %s -input-file=%t_0.sym --check-prefixes CHECK-SYM1
5+
; RUN: FileCheck %s -input-file=%t_1.sym --check-prefixes CHECK-SYM2
6+
7+
; This test checks that the definition of function externalDeviceFunc is
8+
; present in both resulting modules when per-source split is requested.
9+
10+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
11+
target triple = "spir64-unknown-linux-sycldevice"
12+
13+
define dso_local spir_func void @externalDeviceFunc() #0 {
14+
ret void
15+
}
16+
17+
define dso_local spir_kernel void @kernel1() #1 {
18+
call void @externalDeviceFunc()
19+
ret void
20+
}
21+
22+
attributes #0 = { "sycl-module-id"="a.cpp" }
23+
attributes #1 = { "sycl-module-id"="b.cpp" }
24+
25+
; CHECK-IR1: define dso_local spir_func void @externalDeviceFunc()
26+
; CHECK-IR2: define dso_local spir_func void @externalDeviceFunc()
27+
; CHECK-IR2: define dso_local spir_kernel void @kernel1()
28+
29+
; CHECK-SYM1: externalDeviceFunc
30+
; CHECK-SYM2: kernel1

llvm/test/tools/sycl-post-link/sym_but_no_split.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@
66
; RUN: FileCheck %s -input-file=%t.files.table --check-prefixes CHECK-TABLE
77
; RUN: FileCheck %s -input-file=%t.files_0.sym --match-full-lines --check-prefixes CHECK-SYM
88

9-
define dso_local spir_kernel void @KERNEL_AAA() {
9+
define dso_local spir_kernel void @KERNEL_AAA() #0 {
1010
; CHECK-SYM-NOT: {{[a-zA-Z0-9._@]+}}
1111
; CHECK-SYM: KERNEL_AAA
1212
entry:
1313
ret void
1414
}
1515

16-
define dso_local spir_kernel void @KERNEL_BBB() {
16+
define dso_local spir_kernel void @KERNEL_BBB() #0 {
1717
; CHECK-SYM-NEXT: KERNEL_BBB
1818
; CHECK-SYM-EMPTY:
1919
entry:
2020
ret void
2121
}
2222

23+
attributes #0 = { "sycl-module-id"="a.cpp" }
24+
2325
; CHECK-TABLE: [Code|Properties|Symbols]
2426
; CHECK-TABLE-NEXT: {{.*}}files_0.sym
2527
; CHECK-TABLE-EMPTY:

0 commit comments

Comments
 (0)