1; RUN: llc -mtriple=x86_64-windows-gnu %s -o - | FileCheck %s
2
3; Based on this C++ code:
4; struct as {
5;     as() { at = static_cast<int *>(operator new(sizeof(int))); }
6;     ~as() { operator delete(at); }
7;     int *at;
8; };
9; void am(int) {
10;     static as au;
11;     as av;
12;     throw 0;
13; }
14
15; optnone was added to ensure that branch folding and block layout are not
16; disturbed. The key thing about this test is that it ends in an empty
17; unreachable block, which forces us to scan back across blocks.
18
19; CHECK: _Z2ami:
20; CHECK: callq   __cxa_throw
21; CHECK: # %eh.resume
22; CHECK: callq _Unwind_Resume
23; CHECK-NEXT: # %unreachable
24; CHECK-NEXT: int3
25; CHECK-NEXT: .Lfunc_end0:
26
27%struct.as = type { i32* }
28
29@_ZZ2amiE2au = internal unnamed_addr global %struct.as zeroinitializer, align 8
30@_ZGVZ2amiE2au = internal global i64 0, align 8
31@_ZTIi = external constant i8*
32
33define dso_local void @_Z2ami(i32 %0) noinline optnone personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*) {
34entry:
35  %1 = load atomic i8, i8* bitcast (i64* @_ZGVZ2amiE2au to i8*) acquire, align 8
36  %guard.uninitialized = icmp eq i8 %1, 0
37  br i1 %guard.uninitialized, label %init.check, label %init.end
38
39init.check:                                       ; preds = %entry
40  %2 = tail call i32 @__cxa_guard_acquire(i64* nonnull @_ZGVZ2amiE2au)
41  %tobool = icmp eq i32 %2, 0
42  br i1 %tobool, label %init.end, label %init
43
44init:                                             ; preds = %init.check
45  %call.i3 = invoke i8* @_Znwy(i64 4)
46          to label %invoke.cont unwind label %lpad
47
48invoke.cont:                                      ; preds = %init
49  store i8* %call.i3, i8** bitcast (%struct.as* @_ZZ2amiE2au to i8**), align 8
50  %3 = tail call i32 @atexit(void ()* nonnull @__dtor__ZZ2amiE2au)
51  tail call void @__cxa_guard_release(i64* nonnull @_ZGVZ2amiE2au)
52  br label %init.end
53
54init.end:                                         ; preds = %init.check, %invoke.cont, %entry
55  %call.i = tail call i8* @_Znwy(i64 4)
56  %exception = tail call i8* @__cxa_allocate_exception(i64 4)
57  %4 = bitcast i8* %exception to i32*
58  store i32 0, i32* %4, align 16
59  invoke void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
60          to label %unreachable unwind label %lpad1
61
62lpad:                                             ; preds = %init
63  %5 = landingpad { i8*, i32 }
64          cleanup
65  %6 = extractvalue { i8*, i32 } %5, 0
66  %7 = extractvalue { i8*, i32 } %5, 1
67  tail call void @__cxa_guard_abort(i64* nonnull @_ZGVZ2amiE2au)
68  br label %eh.resume
69
70lpad1:                                            ; preds = %init.end
71  %8 = landingpad { i8*, i32 }
72          cleanup
73  %9 = extractvalue { i8*, i32 } %8, 0
74  %10 = extractvalue { i8*, i32 } %8, 1
75  tail call void @_ZdlPv(i8* %call.i)
76  br label %eh.resume
77
78eh.resume:                                        ; preds = %lpad1, %lpad
79  %exn.slot.0 = phi i8* [ %9, %lpad1 ], [ %6, %lpad ]
80  %ehselector.slot.0 = phi i32 [ %10, %lpad1 ], [ %7, %lpad ]
81  %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn.slot.0, 0
82  %lpad.val2 = insertvalue { i8*, i32 } %lpad.val, i32 %ehselector.slot.0, 1
83  resume { i8*, i32 } %lpad.val2
84
85unreachable:                                      ; preds = %init.end
86  unreachable
87}
88
89declare dso_local i32 @__cxa_guard_acquire(i64*)
90
91declare dso_local i32 @__gxx_personality_seh0(...)
92
93declare dso_local void @__dtor__ZZ2amiE2au()
94
95declare dso_local i32 @atexit(void ()*)
96
97declare dso_local void @__cxa_guard_abort(i64*)
98
99declare dso_local void @__cxa_guard_release(i64*)
100
101declare dso_local i8* @__cxa_allocate_exception(i64)
102
103declare dso_local void @__cxa_throw(i8*, i8*, i8*)
104
105declare dso_local noalias i8* @_Znwy(i64)
106
107declare dso_local void @_ZdlPv(i8*)
108