Skip to content

Commit ecedb43

Browse files
Ilya Stepykinbader
Ilya Stepykin
authored andcommitted
[SYCL] Don't emit exception handling code for device
In order to support exception handling, the compiler generates additional code inside functions to perform cleanup, catch unexpected exceptions. This is done by calling a function that may throw using "invoke" LLVM instruction with additional landing pad code instead of simple "call". Previously, when such code is generated, llvm-spirv would fail to translate it as it doesn't know how to handle "invoke" instruction. There is no support for exceptions on device side, so generation of such exception handling code (including "invoke" instruction) can be simply disabled. Signed-off-by: Ilya Stepykin <ilya.stepykin@intel.com>
1 parent ae4419f commit ecedb43

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

clang/lib/CodeGen/CGException.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -717,8 +717,8 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
717717
return nullptr;
718718
}
719719

720-
// CUDA device code doesn't have exceptions.
721-
if (LO.CUDA && LO.CUDAIsDevice)
720+
// CUDA and SYCL device code doesn't have exceptions.
721+
if (LO.CUDA && LO.CUDAIsDevice || LO.SYCLIsDevice)
722722
return nullptr;
723723

724724
// Check the innermost scope for a cached landing pad. If this is

clang/test/CodeGenSYCL/noexcept.cpp

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %clang_cc1 -triple spir64-unknown-linux-sycldevice -I%S -fsycl-is-device \
2+
// RUN: -std=c++11 -fcxx-exceptions -fexceptions -disable-llvm-passes -x c++ \
3+
// RUN: -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-DEVICE
4+
//
5+
// RUN: %clang_cc1 -I%S -std=c++11 -fcxx-exceptions -fexceptions -disable-llvm-passes \
6+
// RUN: -x c++ -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-HOST
7+
8+
// The test checks that exception handling code is generated only for host and not for device.
9+
10+
void f1() {}
11+
void f2() {}
12+
void f3() {}
13+
14+
void foo_noexcept() noexcept {
15+
// CHECK-DEVICE: call spir_func void @_Z2f1v()
16+
// CHECK-HOST: invoke void @_Z2f1v()
17+
f1();
18+
}
19+
20+
void foo_throw() throw() {
21+
// CHECK-DEVICE: call spir_func void @_Z2f2v()
22+
// CHECK-HOST: invoke void @_Z2f2v()
23+
f2();
24+
}
25+
26+
struct A {
27+
// Non-trivial destructor to force generation of cleanup code
28+
~A(){}
29+
};
30+
31+
void foo_cleanup() {
32+
A a;
33+
// CHECK-DEVICE: call spir_func void @_Z2f3v()
34+
// CHECK-HOST: invoke void @_Z2f3v()
35+
f3();
36+
// CHECK-DEVICE: call spir_func void @_ZN1AD1Ev
37+
// Regular + exception cleanup
38+
// CHECK-HOST: call void @_ZN1AD1Ev
39+
// CHECK-HOST: call void @_ZN1AD1Ev
40+
}
41+
42+
template <typename name, typename Func>
43+
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
44+
kernelFunc();
45+
}
46+
47+
int main() {
48+
kernel_single_task<class kernel>([=](){
49+
foo_noexcept();
50+
foo_throw();
51+
foo_cleanup();
52+
});
53+
}

0 commit comments

Comments
 (0)