Skip to content

Commit bf5d9d5

Browse files
author
Artem Gindinson
authored
[SYCL] Test compiler diagnostics for unsupported printf usages (#5306)
Additionally, fix the diagnostic output for cases with an incorrect wrapper name and unify the punctuation style of the existing diagnostics. Signed-off-by: Artem Gindinson <[email protected]>
1 parent 97e6d2d commit bf5d9d5

File tree

6 files changed

+213
-2
lines changed

6 files changed

+213
-2
lines changed

llvm/lib/SYCLLowerIR/MutatePrintfAddrspace.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ size_t setFuncCallsOntoCASPrintf(Function *F, Function *CASPrintfFunc,
210210
"passing format strings directly into experimental::printf calls, "
211211
"avoiding indirection via wrapper function arguments.";
212212
if (!WrapperFunc->getName().contains("6oneapi12experimental6printf")) {
213-
emitError(WrapperFunc, CI, BadWrapperErrorMsg);
213+
emitError(F, CI, BadWrapperErrorMsg);
214214
return 0;
215215
}
216216
for (User *WrapperU : WrapperFunc->users()) {
@@ -239,7 +239,7 @@ size_t setFuncCallsOntoCASPrintf(Function *F, Function *CASPrintfFunc,
239239
F, CI,
240240
"Make sure each format string literal is "
241241
"known at compile time or use OpenCL constant address space literals "
242-
"for device-side printf calls");
242+
"for device-side printf calls.");
243243
return 0;
244244
}
245245
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include <CL/sycl.hpp>
2+
3+
SYCL_EXTERNAL void custom_wrapper(const char *S) {
4+
sycl::ext::oneapi::experimental::printf(S);
5+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include <CL/sycl.hpp>
2+
3+
using namespace sycl;
4+
5+
int foo(int k) {
6+
queue q;
7+
buffer<int, 1> buf(k);
8+
q.submit([&](handler &cgh) {
9+
auto acc = buf.get_access(cgh);
10+
cgh.single_task([=]() {
11+
if (acc[0] == 0)
12+
ext::oneapi::experimental::printf("String 0\n");
13+
else
14+
ext::oneapi::experimental::printf("String 1\n");
15+
});
16+
});
17+
return 0;
18+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
;; This tests diagnostic emission whenever printf's format string argument
2+
;; is taken from the argument list of a user wrapper function, but then the
3+
;; user-provided wrapper does not get inlined (while the library-provided
4+
;; experimental::printf wrapper does).
5+
6+
;; The IR for test purposes is based on the following source/compilation (custom
7+
;; build of SYCL Clang with SYCLMutatePrintfAddrspacePass turned off):
8+
;; clang++ -fsycl -fsycl-device-only Inputs/experimental-printf-bad-inline-test.cpp -S -D__SYCL_USE_NON_VARIADIC_SPIRV_OCL_PRINTF__ -O2
9+
10+
; RUN: not opt < %s --SYCLMutatePrintfAddrspace -S --enable-new-pm=0 2>&1 | FileCheck %s
11+
; RUN: not opt < %s --passes=SYCLMutatePrintfAddrspace -S 2>&1 | FileCheck %s
12+
; CHECK: error: experimental::printf requires format string to reside in constant address space. The compiler wasn't able to automatically convert your format string into constant address space when processing builtin _Z18__spirv_ocl_printf{{.*}} called in function {{.*}}custom_wrapper{{.*}}.
13+
; CHECK-NEXT: Consider simplifying the code by passing format strings directly into experimental::printf calls, avoiding indirection via wrapper function arguments.
14+
15+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
16+
target triple = "spir64-unknown-unknown"
17+
18+
%"class.cl::sycl::id" = type { %"class.cl::sycl::detail::array" }
19+
%"class.cl::sycl::detail::array" = type { [1 x i64] }
20+
21+
; Function Attrs: convergent mustprogress norecurse
22+
define dso_local spir_func void @_Z14custom_wrapperPKc(i8 addrspace(4)* %S) local_unnamed_addr #0 {
23+
entry:
24+
%call.i = tail call spir_func i32 @_Z18__spirv_ocl_printfIJEEiPKcDpT_(i8 addrspace(4)* %S) #3
25+
ret void
26+
}
27+
28+
; Function Attrs: convergent
29+
declare dso_local spir_func i32 @_Z18__spirv_ocl_printfIJEEiPKcDpT_(i8 addrspace(4)*) local_unnamed_addr #1
30+
31+
attributes #0 = { convergent mustprogress norecurse "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="experimental-printf.cpp" }
32+
attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
33+
attributes #2 = { convergent norecurse "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="experimental-printf-bad-inline-test.cpp" "uniform-work-group-size"="true" }
34+
attributes #3 = { convergent }
35+
36+
!llvm.module.flags = !{!0, !1}
37+
!opencl.spir.version = !{!2}
38+
!spirv.Source = !{!3}
39+
!llvm.ident = !{!4}
40+
41+
!0 = !{i32 1, !"wchar_size", i32 4}
42+
!1 = !{i32 7, !"frame-pointer", i32 2}
43+
!2 = !{i32 1, i32 2}
44+
!3 = !{i32 4, i32 100000}
45+
!4 = !{!"clang version 14.0.0"}
46+
!5 = !{i32 -1, i32 -1, i32 -1, i32 -1}
47+
!6 = !{i1 false, i1 true, i1 true, i1 false}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
;; This tests diagnostic emission upon compile-time-unknown format string.
2+
;; In this instance, a select instruction is given as the first argument
3+
;; to __spirv_ocl_printf - as a result, moving the function into the constant AS
4+
;; becomes impossible.
5+
6+
;; The IR is based on the following source/compilation (custom
7+
;; build of SYCL Clang with SYCLMutatePrintfAddrspacePass turned off):
8+
;; clang++ -fsycl -fsycl-device-only Inputs/experimental-printf-compile-time-unknown.cpp -S -D__SYCL_USE_NON_VARIADIC_SPIRV_OCL_PRINTF__
9+
10+
; RUN: not opt < %s --SYCLMutatePrintfAddrspace -S --enable-new-pm=0 2>&1 | FileCheck %s
11+
; RUN: not opt < %s --passes=SYCLMutatePrintfAddrspace -S 2>&1 | FileCheck %s
12+
; CHECK: error: experimental::printf requires format string to reside in constant address space. The compiler wasn't able to automatically convert your format string into constant address space when processing builtin _Z18__spirv_ocl_printf{{.*}} called in function {{.*}}foo{{.*}}.
13+
; CHECK-NEXT: Make sure each format string literal is known at compile time or use OpenCL constant address space literals for device-side printf calls.
14+
15+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
16+
target triple = "spir64-unknown-unknown"
17+
18+
%"class.cl::sycl::id" = type { %"class.cl::sycl::detail::array" }
19+
%"class.cl::sycl::detail::array" = type { [1 x i64] }
20+
21+
$_ZTSZZ3fooiENKUlRN2cl4sycl7handlerEE_clES2_EUlvE_ = comdat any
22+
23+
@.str = private unnamed_addr addrspace(1) constant [10 x i8] c"String 0\0A\00", align 1
24+
@.str.1 = private unnamed_addr addrspace(1) constant [10 x i8] c"String 1\0A\00", align 1
25+
26+
; Function Attrs: convergent norecurse
27+
define weak_odr dso_local spir_kernel void @_ZTSZZ3fooiENKUlRN2cl4sycl7handlerEE_clES2_EUlvE_(i32 addrspace(1)* %_arg_, %"class.cl::sycl::id"* byval(%"class.cl::sycl::id") align 8 %_arg_3) local_unnamed_addr #0 comdat !kernel_arg_buffer_location !5 !sycl_kernel_omit_args !6 {
28+
entry:
29+
%0 = getelementptr inbounds %"class.cl::sycl::id", %"class.cl::sycl::id"* %_arg_3, i64 0, i32 0, i32 0, i64 0
30+
%1 = addrspacecast i64* %0 to i64 addrspace(4)*
31+
%2 = load i64, i64 addrspace(4)* %1, align 8
32+
%add.ptr.i = getelementptr inbounds i32, i32 addrspace(1)* %_arg_, i64 %2
33+
%arrayidx.ascast.i.i = addrspacecast i32 addrspace(1)* %add.ptr.i to i32 addrspace(4)*
34+
%3 = load i32, i32 addrspace(4)* %arrayidx.ascast.i.i, align 4, !tbaa !7
35+
%cmp.i = icmp eq i32 %3, 0
36+
%..i = select i1 %cmp.i, i8 addrspace(4)* getelementptr inbounds ([10 x i8], [10 x i8] addrspace(4)* addrspacecast ([10 x i8] addrspace(1)* @.str to [10 x i8] addrspace(4)*), i64 0, i64 0), i8 addrspace(4)* getelementptr inbounds ([10 x i8], [10 x i8] addrspace(4)* addrspacecast ([10 x i8] addrspace(1)* @.str.1 to [10 x i8] addrspace(4)*), i64 0, i64 0)
37+
%call.i.i = tail call spir_func i32 @_Z18__spirv_ocl_printfIJEEiPKcDpT_(i8 addrspace(4)* %..i) #2
38+
ret void
39+
}
40+
41+
; Function Attrs: convergent
42+
declare dso_local spir_func i32 @_Z18__spirv_ocl_printfIJEEiPKcDpT_(i8 addrspace(4)*) local_unnamed_addr #1
43+
44+
attributes #0 = { convergent norecurse "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="experimental-printf.cpp" "uniform-work-group-size"="true" }
45+
attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
46+
attributes #2 = { convergent }
47+
48+
!llvm.module.flags = !{!0, !1}
49+
!opencl.spir.version = !{!2}
50+
!spirv.Source = !{!3}
51+
!llvm.ident = !{!4}
52+
53+
!0 = !{i32 1, !"wchar_size", i32 4}
54+
!1 = !{i32 7, !"frame-pointer", i32 2}
55+
!2 = !{i32 1, i32 2}
56+
!3 = !{i32 4, i32 100000}
57+
!4 = !{!"clang version 14.0.0"}
58+
!5 = !{i32 -1, i32 -1, i32 -1, i32 -1}
59+
!6 = !{i1 false, i1 true, i1 true, i1 false}
60+
!7 = !{!8, !8, i64 0}
61+
!8 = !{!"int", !9, i64 0}
62+
!9 = !{!"omnipotent char", !10, i64 0}
63+
!10 = !{!"Simple C++ TBAA"}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
;; This tests diagnostic emission whenever printf's format string argument
2+
;; is taken from the argument list of a user wrapper function and no
3+
;; inlining is performed prior to the address space mutation pass.
4+
5+
;; The IR for test purposes is based on the following source/compilation (custom
6+
;; build of SYCL Clang with SYCLMutatePrintfAddrspacePass turned off):
7+
;; clang++ -fsycl -fsycl-device-only Inputs/experimental-printf-bad-inline-test.cpp -S -D__SYCL_USE_NON_VARIADIC_SPIRV_OCL_PRINTF__ -O0
8+
9+
; RUN: not opt < %s --SYCLMutatePrintfAddrspace -S --enable-new-pm=0 2>&1 | FileCheck %s
10+
; RUN: not opt < %s --passes=SYCLMutatePrintfAddrspace -S 2>&1 | FileCheck %s
11+
; CHECK: error: experimental::printf requires format string to reside in constant address space. The compiler wasn't able to automatically convert your format string into constant address space when processing builtin _ZN2cl4sycl3ext6oneapi12experimental6printf{{.*}} called in function {{.*}}custom_wrapper{{.*}}.
12+
; CHECK-NEXT: Consider simplifying the code by passing format strings directly into experimental::printf calls, avoiding indirection via wrapper function arguments.
13+
14+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
15+
target triple = "spir64-unknown-unknown"
16+
17+
%"class.cl::sycl::range" = type { %"class.cl::sycl::detail::array" }
18+
%"class.cl::sycl::detail::array" = type { [1 x i64] }
19+
%"class.cl::sycl::id" = type { %"class.cl::sycl::detail::array" }
20+
%class.anon = type { %"class.cl::sycl::accessor" }
21+
%"class.cl::sycl::accessor" = type { %"class.cl::sycl::detail::AccessorImplDevice" }
22+
%"class.cl::sycl::detail::AccessorImplDevice" = type { %"class.cl::sycl::id", %"class.cl::sycl::range", %"class.cl::sycl::range" }
23+
%"class.cl::sycl::detail::accessor_common" = type { i8 }
24+
25+
$_ZN2cl4sycl3ext6oneapi12experimental6printfIcJEEEiPKT_DpT0_ = comdat any
26+
27+
; Function Attrs: convergent mustprogress noinline norecurse optnone
28+
define dso_local spir_func void @_Z14custom_wrapperPKc(i8 addrspace(4)* %S) #0 {
29+
entry:
30+
%S.addr = alloca i8 addrspace(4)*, align 8
31+
%S.addr.ascast = addrspacecast i8 addrspace(4)** %S.addr to i8 addrspace(4)* addrspace(4)*
32+
store i8 addrspace(4)* %S, i8 addrspace(4)* addrspace(4)* %S.addr.ascast, align 8
33+
%0 = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %S.addr.ascast, align 8
34+
%call = call spir_func i32 @_ZN2cl4sycl3ext6oneapi12experimental6printfIcJEEEiPKT_DpT0_(i8 addrspace(4)* %0) #9
35+
ret void
36+
}
37+
38+
; Function Attrs: convergent mustprogress noinline norecurse optnone
39+
define linkonce_odr dso_local spir_func i32 @_ZN2cl4sycl3ext6oneapi12experimental6printfIcJEEEiPKT_DpT0_(i8 addrspace(4)* %__format) #1 comdat {
40+
entry:
41+
%retval = alloca i32, align 4
42+
%__format.addr = alloca i8 addrspace(4)*, align 8
43+
%retval.ascast = addrspacecast i32* %retval to i32 addrspace(4)*
44+
%__format.addr.ascast = addrspacecast i8 addrspace(4)** %__format.addr to i8 addrspace(4)* addrspace(4)*
45+
store i8 addrspace(4)* %__format, i8 addrspace(4)* addrspace(4)* %__format.addr.ascast, align 8
46+
%0 = load i8 addrspace(4)*, i8 addrspace(4)* addrspace(4)* %__format.addr.ascast, align 8
47+
%call = call spir_func i32 @_Z18__spirv_ocl_printfIJEEiPKcDpT_(i8 addrspace(4)* %0) #9
48+
ret i32 %call
49+
}
50+
51+
; Function Attrs: convergent
52+
declare dso_local spir_func i32 @_Z18__spirv_ocl_printfIJEEiPKcDpT_(i8 addrspace(4)*) #2
53+
54+
attributes #0 = { convergent mustprogress noinline norecurse optnone "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="experimental-printf-bad-inline-test.cpp" }
55+
attributes #1 = { convergent mustprogress noinline norecurse optnone "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
56+
attributes #2 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
57+
attributes #3 = { convergent mustprogress noinline norecurse optnone "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "sycl-module-id"="experimental-printf-bad-inline-test.cpp" "uniform-work-group-size"="true" }
58+
attributes #4 = { convergent noinline norecurse optnone "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
59+
attributes #5 = { argmemonly nofree nounwind willreturn }
60+
attributes #6 = { argmemonly nofree nounwind willreturn writeonly }
61+
attributes #7 = { convergent noinline norecurse nounwind optnone "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
62+
attributes #8 = { convergent mustprogress noinline norecurse nounwind optnone "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
63+
attributes #9 = { convergent }
64+
65+
!llvm.module.flags = !{!0, !1}
66+
!opencl.spir.version = !{!2}
67+
!spirv.Source = !{!3}
68+
!llvm.ident = !{!4}
69+
70+
!0 = !{i32 1, !"wchar_size", i32 4}
71+
!1 = !{i32 7, !"frame-pointer", i32 2}
72+
!2 = !{i32 1, i32 2}
73+
!3 = !{i32 4, i32 100000}
74+
!4 = !{!"clang version 14.0.0"}
75+
!5 = !{i32 -1, i32 -1, i32 -1, i32 -1}
76+
!6 = distinct !{!6, !7, !8}
77+
!7 = !{!"llvm.loop.mustprogress"}
78+
!8 = !{!"llvm.loop.unroll.enable"}

0 commit comments

Comments
 (0)