Skip to content

Commit a4e255f

Browse files
committed
Skip exception cleanups when the innermost scope is EHTerminateScope.
EHTerminateScope is used to implement C++ noexcept semantics. Per C++ [except.terminate], it is implemented-defined whether no, some, or all cleanups are run prior to terminatation. Therefore, the code to run cleanups on the way towards termination is unnecessary, and may be omitted. After this change, we will still run some cleanups: any cleanups in a function called from the noexcept function will continue to run, while those in the noexcept function itself will not. Differential Revision: https://reviews.llvm.org/D113620
1 parent ca88bec commit a4e255f

11 files changed

+980
-1578
lines changed

clang/lib/CodeGen/CGCleanup.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ void *EHScopeStack::pushCleanup(CleanupKind Kind, size_t Size) {
180180
bool IsNormalCleanup = Kind & NormalCleanup;
181181
bool IsEHCleanup = Kind & EHCleanup;
182182
bool IsLifetimeMarker = Kind & LifetimeMarker;
183+
184+
// Per C++ [except.terminate], it is implementation-defined whether none,
185+
// some, or all cleanups are called before std::terminate. Thus, when
186+
// terminate is the current EH scope, we may skip adding any EH cleanup
187+
// scopes.
188+
if (find(InnermostEHScope)->getKind() == EHScope::Terminate)
189+
IsEHCleanup = false;
190+
183191
EHCleanupScope *Scope =
184192
new (Buffer) EHCleanupScope(IsNormalCleanup,
185193
IsEHCleanup,

clang/test/CodeGenCXX/noexcept.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,32 +16,23 @@ namespace test0 {
1616
foo();
1717
}
1818
}
19+
1920
// CHECK-LABEL: define{{.*}} void @_ZN5test04testEv()
20-
// CHECK: [[EXN:%.*]] = alloca i8*
2121
// This goes to the terminate lpad.
2222
// CHECK: invoke void @_ZN5test01AC1Ev(
23-
// This goes to the cleanup-and-then-terminate lpad.
23+
// CHECK-NEXT: unwind label %[[TERMINATE_LPAD:.*]]
24+
// This also goes to the terminate lpad (no cleanups!).
2425
// CHECK: invoke void @_ZN5test03fooEv()
26+
// CHECK-NEXT: unwind label %[[TERMINATE_LPAD]]
2527
// Destructors don't throw by default in C++11.
2628
// CHECK: call void @_ZN5test01AD1Ev(
2729
// Cleanup lpad.
28-
// CHECK: [[T0:%.*]] = landingpad
29-
// CHECK-NEXT: catch i8* null
30-
// CHECK-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
31-
// CHECK-NEXT: store i8* [[T1]], i8** [[EXN]]
32-
// (Calling this destructor is not technically required.)
33-
// CHECK: call void @_ZN5test01AD1Ev(
34-
// CHECK-NEXT: br label
35-
// The terminate landing pad jumps in here for some reason.
36-
// CHECK: [[T0:%.*]] = landingpad
30+
// CHECK: [[TERMINATE_LPAD]]:
31+
// CHECK-NEXT: [[T0:%.*]] = landingpad
3732
// CHECK-NEXT: catch i8* null
3833
// CHECK-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
3934
// CHECK-NEXT: call void @__clang_call_terminate(i8* [[T1]])
4035
// CHECK-NEXT: unreachable
41-
// The terminate handler chained to by the cleanup lpad.
42-
// CHECK: [[T0:%.*]] = load i8*, i8** [[EXN]]
43-
// CHECK-NEXT: call void @__clang_call_terminate(i8* [[T0]])
44-
// CHECK-NEXT: unreachable
4536

4637
// CHECK-LABEL: define linkonce_odr hidden void @__clang_call_terminate(
4738
// CHECK: call i8* @__cxa_begin_catch(

clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp

Lines changed: 32 additions & 153 deletions
Large diffs are not rendered by default.

clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp

Lines changed: 56 additions & 176 deletions
Large diffs are not rendered by default.

clang/test/OpenMP/openmp_win_codegen.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ int main() {
7373
// CHECK1-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
7474
// CHECK1-NEXT: call void @__kmpc_critical(%struct.ident_t* @[[GLOB1]], i32 [[TMP3]], [8 x i32]* @.gomp_critical_user_.var) [ "funclet"(token [[TMP1]]) ]
7575
// CHECK1-NEXT: invoke void @"?bar@@YAXXZ"() [ "funclet"(token [[TMP1]]) ]
76-
// CHECK1-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[EHCLEANUP:%.*]]
76+
// CHECK1-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE2:%.*]]
7777
// CHECK1: invoke.cont1:
7878
// CHECK1-NEXT: call void @__kmpc_end_critical(%struct.ident_t* @[[GLOB1]], i32 [[TMP3]], [8 x i32]* @.gomp_critical_user_.var) [ "funclet"(token [[TMP1]]) ]
7979
// CHECK1-NEXT: catchret from [[TMP1]] to label [[CATCHRET_DEST:%.*]]
@@ -83,17 +83,13 @@ int main() {
8383
// CHECK1-NEXT: ret void
8484
// CHECK1: invoke.cont:
8585
// CHECK1-NEXT: br label [[TRY_CONT]]
86-
// CHECK1: ehcleanup:
87-
// CHECK1-NEXT: [[TMP4:%.*]] = cleanuppad within [[TMP1]] []
88-
// CHECK1-NEXT: call void @__kmpc_end_critical(%struct.ident_t* @[[GLOB1]], i32 [[TMP3]], [8 x i32]* @.gomp_critical_user_.var) [ "funclet"(token [[TMP4]]) ]
89-
// CHECK1-NEXT: cleanupret from [[TMP4]] unwind label [[TERMINATE2:%.*]]
9086
// CHECK1: terminate:
91-
// CHECK1-NEXT: [[TMP5:%.*]] = cleanuppad within none []
92-
// CHECK1-NEXT: call void @"?terminate@@YAXXZ"() #[[ATTR7:[0-9]+]] [ "funclet"(token [[TMP5]]) ]
87+
// CHECK1-NEXT: [[TMP4:%.*]] = cleanuppad within none []
88+
// CHECK1-NEXT: call void @"?terminate@@YAXXZ"() #[[ATTR7:[0-9]+]] [ "funclet"(token [[TMP4]]) ]
9389
// CHECK1-NEXT: unreachable
9490
// CHECK1: terminate2:
95-
// CHECK1-NEXT: [[TMP6:%.*]] = cleanuppad within [[TMP1]] []
96-
// CHECK1-NEXT: call void @"?terminate@@YAXXZ"() #[[ATTR7]] [ "funclet"(token [[TMP6]]) ]
91+
// CHECK1-NEXT: [[TMP5:%.*]] = cleanuppad within [[TMP1]] []
92+
// CHECK1-NEXT: call void @"?terminate@@YAXXZ"() #[[ATTR7]] [ "funclet"(token [[TMP5]]) ]
9793
// CHECK1-NEXT: unreachable
9894
//
9995
//
@@ -155,4 +151,3 @@ int main() {
155151
// CHECK1-NEXT: store i32 [[TMP12]], i32* [[TMP8]], align 4
156152
// CHECK1-NEXT: ret void
157153
//
158-
//

clang/test/OpenMP/ordered_doacross_codegen.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,6 @@ int main() {
8888
#pragma omp ordered depend(sink : i - 2)
8989
d[i] = a[i - 2];
9090
}
91-
// CHECK: landingpad
92-
// CHECK-NORMAL: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
93-
// CHECK: br label %
9491

9592
// CHECK: call void @__kmpc_for_static_fini(
9693
// CHECK-NORMAL: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
@@ -150,10 +147,6 @@ int main1() {
150147
#pragma omp ordered depend(sink : i - 2)
151148
d[i] = a[i - 2];
152149
}
153-
// CHECK: landingpad
154-
// CHECK-NORMAL: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
155-
// CHECK: br label %
156-
157150
// CHECK: call void @__kmpc_for_static_fini(
158151
// CHECK-NORMAL: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
159152
// CHECK: ret i32 0
@@ -267,10 +260,6 @@ struct TestStruct {
267260
baz(a[i][j], b[i][j]);
268261
}
269262
}
270-
// CHECK: landingpad
271-
// CHECK-NORMAL: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
272-
// CHECK: br label %
273-
274263
// CHECK: call void @__kmpc_for_static_fini(
275264
// CHECK-NORMAL: call void @__kmpc_doacross_fini([[IDENT]], i32 [[GTID]])
276265
// CHECK: ret

clang/test/OpenMP/parallel_master_codegen.cpp

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,6 @@ void parallel_master_allocate() {
305305
// CHECK1-NEXT: entry:
306306
// CHECK1-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8
307307
// CHECK1-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8
308-
// CHECK1-NEXT: [[EXN_SLOT:%.*]] = alloca i8*, align 8
309-
// CHECK1-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
310308
// CHECK1-NEXT: store i32* [[DOTGLOBAL_TID_]], i32** [[DOTGLOBAL_TID__ADDR]], align 8
311309
// CHECK1-NEXT: store i32* [[DOTBOUND_TID_]], i32** [[DOTBOUND_TID__ADDR]], align 8
312310
// CHECK1-NEXT: [[TMP0:%.*]] = load i32*, i32** [[DOTGLOBAL_TID__ADDR]], align 8
@@ -316,24 +314,17 @@ void parallel_master_allocate() {
316314
// CHECK1-NEXT: br i1 [[TMP3]], label [[OMP_IF_THEN:%.*]], label [[OMP_IF_END:%.*]]
317315
// CHECK1: omp_if.then:
318316
// CHECK1-NEXT: invoke void @_Z3foov()
319-
// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
317+
// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
320318
// CHECK1: invoke.cont:
321319
// CHECK1-NEXT: call void @__kmpc_end_master(%struct.ident_t* @[[GLOB1]], i32 [[TMP1]])
322320
// CHECK1-NEXT: br label [[OMP_IF_END]]
323-
// CHECK1: lpad:
321+
// CHECK1: omp_if.end:
322+
// CHECK1-NEXT: ret void
323+
// CHECK1: terminate.lpad:
324324
// CHECK1-NEXT: [[TMP4:%.*]] = landingpad { i8*, i32 }
325325
// CHECK1-NEXT: catch i8* null
326326
// CHECK1-NEXT: [[TMP5:%.*]] = extractvalue { i8*, i32 } [[TMP4]], 0
327-
// CHECK1-NEXT: store i8* [[TMP5]], i8** [[EXN_SLOT]], align 8
328-
// CHECK1-NEXT: [[TMP6:%.*]] = extractvalue { i8*, i32 } [[TMP4]], 1
329-
// CHECK1-NEXT: store i32 [[TMP6]], i32* [[EHSELECTOR_SLOT]], align 4
330-
// CHECK1-NEXT: call void @__kmpc_end_master(%struct.ident_t* @[[GLOB1]], i32 [[TMP1]])
331-
// CHECK1-NEXT: br label [[TERMINATE_HANDLER:%.*]]
332-
// CHECK1: omp_if.end:
333-
// CHECK1-NEXT: ret void
334-
// CHECK1: terminate.handler:
335-
// CHECK1-NEXT: [[EXN:%.*]] = load i8*, i8** [[EXN_SLOT]], align 8
336-
// CHECK1-NEXT: call void @__clang_call_terminate(i8* [[EXN]]) #[[ATTR6:[0-9]+]]
327+
// CHECK1-NEXT: call void @__clang_call_terminate(i8* [[TMP5]]) #[[ATTR6:[0-9]+]]
337328
// CHECK1-NEXT: unreachable
338329
//
339330
//
@@ -363,8 +354,6 @@ void parallel_master_allocate() {
363354
// CHECK2-NEXT: entry:
364355
// CHECK2-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca i32*, align 8
365356
// CHECK2-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca i32*, align 8
366-
// CHECK2-NEXT: [[EXN_SLOT:%.*]] = alloca i8*, align 8
367-
// CHECK2-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
368357
// CHECK2-NEXT: store i32* [[DOTGLOBAL_TID_]], i32** [[DOTGLOBAL_TID__ADDR]], align 8
369358
// CHECK2-NEXT: store i32* [[DOTBOUND_TID_]], i32** [[DOTBOUND_TID__ADDR]], align 8
370359
// CHECK2-NEXT: [[TMP0:%.*]] = load i32*, i32** [[DOTGLOBAL_TID__ADDR]], align 8
@@ -374,24 +363,17 @@ void parallel_master_allocate() {
374363
// CHECK2-NEXT: br i1 [[TMP3]], label [[OMP_IF_THEN:%.*]], label [[OMP_IF_END:%.*]]
375364
// CHECK2: omp_if.then:
376365
// CHECK2-NEXT: invoke void @_Z3foov()
377-
// CHECK2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
366+
// CHECK2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
378367
// CHECK2: invoke.cont:
379368
// CHECK2-NEXT: call void @__kmpc_end_master(%struct.ident_t* @[[GLOB1]], i32 [[TMP1]])
380369
// CHECK2-NEXT: br label [[OMP_IF_END]]
381-
// CHECK2: lpad:
370+
// CHECK2: omp_if.end:
371+
// CHECK2-NEXT: ret void
372+
// CHECK2: terminate.lpad:
382373
// CHECK2-NEXT: [[TMP4:%.*]] = landingpad { i8*, i32 }
383374
// CHECK2-NEXT: catch i8* null
384375
// CHECK2-NEXT: [[TMP5:%.*]] = extractvalue { i8*, i32 } [[TMP4]], 0
385-
// CHECK2-NEXT: store i8* [[TMP5]], i8** [[EXN_SLOT]], align 8
386-
// CHECK2-NEXT: [[TMP6:%.*]] = extractvalue { i8*, i32 } [[TMP4]], 1
387-
// CHECK2-NEXT: store i32 [[TMP6]], i32* [[EHSELECTOR_SLOT]], align 4
388-
// CHECK2-NEXT: call void @__kmpc_end_master(%struct.ident_t* @[[GLOB1]], i32 [[TMP1]])
389-
// CHECK2-NEXT: br label [[TERMINATE_HANDLER:%.*]]
390-
// CHECK2: omp_if.end:
391-
// CHECK2-NEXT: ret void
392-
// CHECK2: terminate.handler:
393-
// CHECK2-NEXT: [[EXN:%.*]] = load i8*, i8** [[EXN_SLOT]], align 8
394-
// CHECK2-NEXT: call void @__clang_call_terminate(i8* [[EXN]]) #[[ATTR6:[0-9]+]]
376+
// CHECK2-NEXT: call void @__clang_call_terminate(i8* [[TMP5]]) #[[ATTR6:[0-9]+]]
395377
// CHECK2-NEXT: unreachable
396378
//
397379
//

0 commit comments

Comments
 (0)