Skip to content

[sycl-post-link] Handle spec constants after device code split #3748

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,60 @@
; device code splitting and specialization constant processing are
; requested.
;
; Additionally this test checks that sycl-post-link creates specialization
; constant property correctly: i.e. it doesn't put all specialization constants
; into properties of each device image

; RUN: sycl-post-link -split=kernel -spec-const=rt -S %s -o %t.files.table
; RUN: FileCheck %s -input-file=%t.files_0.ll --check-prefixes CHECK0,CHECK
; RUN: FileCheck %s -input-file=%t.files_1.ll --check-prefixes CHECK1,CHECK
; RUN: FileCheck %s -input-file=%t.files_0.ll --check-prefixes CHECK-IR0,CHECK-IR
; RUN: FileCheck %s -input-file=%t.files_1.ll --check-prefixes CHECK-IR1,CHECK-IR
; RUN: FileCheck %s -input-file=%t.files_2.ll --check-prefixes CHECK-IR2,CHECK-IR
; RUN: FileCheck %s -input-file=%t.files_0.prop --check-prefixes CHECK-PROP0
; RUN: FileCheck %s -input-file=%t.files_1.prop --check-prefixes CHECK-PROP1
; RUN: FileCheck %s -input-file=%t.files_2.prop --check-prefixes CHECK-PROP2

@SCSymID = private unnamed_addr constant [10 x i8] c"SpecConst\00", align 1
; CHECK-NOT: @SCSymID
@SCSymID2 = private unnamed_addr constant [11 x i8] c"SpecConst2\00", align 1
; CHECK-IR-NOT: @SCSymID
; CHECK-IR-NOT: @SCSymID2

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

define dso_local spir_kernel void @KERNEL_AAA() {
%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)*))
; CHECK0: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 0, i1 false)
; CHECK-IR0: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 1, i1 false)
%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)*))
; CHECK-IR0: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 0, i1 false)
ret void
}

define dso_local spir_kernel void @KERNEL_BBB() {
%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)*))
; CHECK1: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 0, i1 false)
; CHECK-IR1: %{{[0-9]+}} = call i1 @_Z20__spirv_SpecConstantib(i32 0, i1 false)
ret void
}

define dso_local spir_kernel void @KERNEL_CCC() {
; CHECK-IR2: define{{.*}}spir_kernel void @KERNEL_CCC
ret void
}

; CHECK: !sycl.specialization-constants = !{![[#MD:]]}
; CHECK-IR0: !sycl.specialization-constants = !{![[#MD0:]], ![[#MD1:]]}
; CHECK-IR0: ![[#MD0:]] = !{!"SpecConst2", i32 0, i32 0, i32 1}
; CHECK-IR0: ![[#MD1:]] = !{!"SpecConst", i32 1, i32 0, i32 1}
;
; CHECK-IR1: !sycl.specialization-constants = !{![[#MD0:]]}
; CHECK-IR1: ![[#MD0:]] = !{!"SpecConst", i32 0, i32 0, i32 1}
;
; CHECK-IR2: !sycl.specialization-constants = !{}

; CHECK: ![[#MD:]] = !{!"SpecConst", i32 0, i32 0, i32 1}
; CHECK-PROP0: [SYCL/specialization constants]
; CHECK-PROP0: SpecConst=2|
; CHECK-PROP0: SpecConst2=2|
;
; CHECK-PROP1: [SYCL/specialization constants]
; CHECK-PROP1: SpecConst=2|
; CHECK-PROP1-NOT: SpecConst2
;
; CHECK-PROP2: [SYCL/specialization constants]
; CHECK-PROP2-EMPTY:
32 changes: 17 additions & 15 deletions llvm/tools/sycl-post-link/sycl-post-link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,33 +549,35 @@ static TableFiles processOneModule(std::unique_ptr<Module> M, bool IsEsimd,
bool SpecConstsMet = false;
bool SetSpecConstAtRT = DoSpecConst && (SpecConstLower == SC_USE_RT_VAL);

if (DoSplit)
splitModule(*M, GlobalsSet, ResultModules);
// post-link always produces a code result, even if it is unmodified input
if (ResultModules.empty())
ResultModules.push_back(std::move(M));

if (DoSpecConst) {
// perform the spec constant intrinsics transformation and enumeration on
// the whole module
ModulePassManager RunSpecConst;
ModuleAnalysisManager MAM;
SpecConstantsPass SCP(SetSpecConstAtRT);
// Register required analysis
MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
RunSpecConst.addPass(SCP);
if (!DoSplit)
// This pass deletes unreachable globals. Code splitter runs it later.
RunSpecConst.addPass(GlobalDCEPass());
PreservedAnalyses Res = RunSpecConst.run(*M, MAM);
SpecConstsMet = !Res.areAllPreserved();
// This pass deletes unreachable globals.
RunSpecConst.addPass(GlobalDCEPass());

for (auto &MPtr : ResultModules) {
// perform the spec constant intrinsics transformation on each resulting
// module
PreservedAnalyses Res = RunSpecConst.run(*MPtr, MAM);
SpecConstsMet |= !Res.areAllPreserved();
}
}

if (IROutputOnly) {
// the result is the transformed input LLVMIR file rather than a file table
saveModule(*M, OutputFilename);
saveModule(*ResultModules.front(), OutputFilename);
return TblFiles;
}
if (DoSplit) {
splitModule(*M, GlobalsSet, ResultModules);
// post-link always produces a code result, even if it is unmodified input
if (ResultModules.size() == 0)
ResultModules.push_back(std::move(M));
} else
ResultModules.push_back(std::move(M));

{
// Reuse input module with only regular SYCL kernels if there were
Expand Down