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