Maksim Sabianin 3f59a22711
[offload][SYCL] Add Module splitting by categories. (#131347)
This patch adds Module splitting by categories. The splitting algorithm
is the necessary step in the SYCL compilation pipeline. Also it could be
reused for other heterogenous targets.

The previous attempt was at #119713. In this patch there is no
dependency in `TransformUtils` on "IPO" and on "Printing Passes". In
this patch a module splitting is self-contained and it doesn't introduce
linking issues.
2025-08-05 14:04:59 +00:00

94 lines
3.2 KiB
LLVM

; Test checks "kernel" splitting mode.
; RUN: llvm-split -split-by-category=kernel -S < %s -o %t.files
; RUN: FileCheck %s -input-file=%t.files_0.ll --check-prefixes CHECK-MODULE0,CHECK
; RUN: FileCheck %s -input-file=%t.files_1.ll --check-prefixes CHECK-MODULE1,CHECK
; RUN: FileCheck %s -input-file=%t.files_2.ll --check-prefixes CHECK-MODULE2,CHECK
;CHECK-MODULE0: @GV = internal addrspace(1) constant [1 x i32] [i32 42], align 4
;CHECK-MODULE1-NOT: @GV
;CHECK-MODULE2-NOT: @GV
@GV = internal addrspace(1) constant [1 x i32] [i32 42], align 4
; CHECK-MODULE0-NOT: define dso_local spir_kernel void @TU0_kernelA
; CHECK-MODULE1-NOT: define dso_local spir_kernel void @TU0_kernelA
; CHECK-MODULE2: define dso_local spir_kernel void @TU0_kernelA
define dso_local spir_kernel void @TU0_kernelA() #0 {
entry:
; CHECK-MODULE2: call spir_func void @foo()
call spir_func void @foo()
ret void
}
; CHECK-MODULE0-NOT: define {{.*}} spir_func void @foo()
; CHECK-MODULE1-NOT: define {{.*}} spir_func void @foo()
; CHECK-MODULE2: define {{.*}} spir_func void @foo()
define dso_local spir_func void @foo() {
entry:
; CHECK-MODULE2: call spir_func void @bar()
call spir_func void @bar()
ret void
}
; CHECK-MODULE0-NOT: define {{.*}} spir_func void @bar()
; CHECK-MODULE1-NOT: define {{.*}} spir_func void @bar()
; CHECK-MODULE2: define {{.*}} spir_func void @bar()
define linkonce_odr dso_local spir_func void @bar() {
entry:
ret void
}
; CHECK-MODULE0-NOT: define dso_local spir_kernel void @TU0_kernelB()
; CHECK-MODULE1: define dso_local spir_kernel void @TU0_kernelB()
; CHECK-MODULE2-NOT: define dso_local spir_kernel void @TU0_kernelB()
define dso_local spir_kernel void @TU0_kernelB() #0 {
entry:
; CHECK-MODULE1: call spir_func void @foo1()
call spir_func void @foo1()
ret void
}
; CHECK-MODULE0-NOT: define {{.*}} spir_func void @foo1()
; CHECK-MODULE1: define {{.*}} spir_func void @foo1()
; CHECK-MODULE2-NOT: define {{.*}} spir_func void @foo1()
define dso_local spir_func void @foo1() {
entry:
ret void
}
; CHECK-MODULE0: define dso_local spir_kernel void @TU1_kernel()
; CHECK-MODULE1-NOT: define dso_local spir_kernel void @TU1_kernel()
; CHECK-MODULE2-NOT: define dso_local spir_kernel void @TU1_kernel()
define dso_local spir_kernel void @TU1_kernel() #1 {
entry:
; CHECK-MODULE0: call spir_func void @foo2()
call spir_func void @foo2()
ret void
}
; CHECK-MODULE0: define {{.*}} spir_func void @foo2()
; CHECK-MODULE1-NOT: define {{.*}} spir_func void @foo2()
; CHECK-MODULE2-NOT: define {{.*}} spir_func void @foo2()
define dso_local spir_func void @foo2() {
entry:
; CHECK-MODULE0: %0 = load i32, ptr addrspace(4) addrspacecast (ptr addrspace(1) @GV to ptr addrspace(4)), align 4
%0 = load i32, ptr addrspace(4) getelementptr inbounds ([1 x i32], ptr addrspace(4) addrspacecast (ptr addrspace(1) @GV to ptr addrspace(4)), i64 0, i64 0), align 4
ret void
}
attributes #0 = { "module-id"="TU1.cpp" }
attributes #1 = { "module-id"="TU2.cpp" }
; Metadata is saved in both modules.
; CHECK: !opencl.spir.version = !{!0, !0}
; CHECK: !spirv.Source = !{!1, !1}
!opencl.spir.version = !{!0, !0}
!spirv.Source = !{!1, !1}
; CHECK; !0 = !{i32 1, i32 2}
; CHECK; !1 = !{i32 4, i32 100000}
!0 = !{i32 1, i32 2}
!1 = !{i32 4, i32 100000}