// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple i386-unknown-unknown -Wno-error=return-type -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple i386-unknown-unknown -Wno-error=return-type -emit-llvm -fcxx-exceptions -fexceptions -disable-llvm-passes -std=c++03 -o - %s | FileCheck --check-prefixes=CHECK-EH-03 %s
// RUN: %clang_cc1 -triple i386-unknown-unknown -Wno-error=return-type -emit-llvm -fcxx-exceptions -fexceptions -disable-llvm-passes -std=c++11 -DCXX11 -o - %s | FileCheck --check-prefixes=CHECK-EH-11 %s

// Test code generation for the named return value optimization.
class X {
public:
  X();
  X(const X&);
  X(const volatile X &);
  ~X();
};

template<typename T> struct Y {
  Y();
  static Y f() {
    Y y;
    return y;
  }
};

void ConsumeX(X x);
extern X OuterX;

// CHECK-LABEL: @_Z5test0v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4:[0-9]+]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z5test0v(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    ret void
//
// CHECK-EH-11-LABEL: @_Z5test0v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6:[0-9]+]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    ret void
//
X test0() { // http://wg21.link/p2025r2#ex-2
  X x;
  return x; // NRVO happens
}

// CHECK-LABEL: @_Z5test1b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z5test1b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    ret void
//
// CHECK-EH-11-LABEL: @_Z5test1b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    ret void
//
X test1(bool B) {
  X x;
  if (B)
    return (x); // NRVO happens
  return x;     // NRVO happens
}

// CHECK-LABEL: @_Z5test2b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR4]]
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]]
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z5test2b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-03-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]]
// CHECK-EH-03:       invoke.cont2:
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[EHCLEANUP:%.*]]
// CHECK-EH-03:       lpad1:
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP5]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP6:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP6]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT5:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD1]]
// CHECK-EH-03:       invoke.cont3:
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD]]
// CHECK-EH-03:       invoke.cont4:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       invoke.cont5:
// CHECK-EH-03-NEXT:    br label [[EHCLEANUP]]
// CHECK-EH-03:       ehcleanup:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT7:%.*]] unwind label [[TERMINATE_LPAD]]
// CHECK-EH-03:       invoke.cont7:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL8:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL8]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP7:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP8]]) #[[ATTR6:[0-9]+]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z5test2b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]]
// CHECK-EH-11:       invoke.cont2:
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[EHCLEANUP:%.*]]
// CHECK-EH-11:       lpad1:
// CHECK-EH-11-NEXT:    [[TMP4:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP5]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP6:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP6]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EHCLEANUP]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD1]]
// CHECK-EH-11:       invoke.cont3:
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       ehcleanup:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL5:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL5]]
//
X test2(bool B) {
  X x;
  X y;
  if (B)
    return y; // NRVO is impossible
  return x;   // NRVO is impossible
}

// CHECK-LABEL: @_Z5test3b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    br label [[RETURN:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-NEXT:    [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]]
// CHECK:       nrvo.unused3:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR4]]
// CHECK:       nrvo.skipdtor4:
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z5test3b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]]
// CHECK-EH-03:       nrvo.unused3:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR4]]
// CHECK-EH-03:       nrvo.skipdtor4:
// CHECK-EH-03-NEXT:    br label [[RETURN]]
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
//
// CHECK-EH-11-LABEL: @_Z5test3b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]]
// CHECK-EH-11:       nrvo.unused3:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR4]]
// CHECK-EH-11:       nrvo.skipdtor4:
// CHECK-EH-11-NEXT:    br label [[RETURN]]
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
//
X test3(bool B) { // http://wg21.link/p2025r2#ex-4
  if (B) {
    X y;
    return y; // NRVO happens
  }
  X x;
  return x; // FIXME: NRVO could happen, but doesn't
}

extern "C" void exit(int) throw();

// CHECK-LABEL: @_Z5test4b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-NEXT:    ]
// CHECK:       cleanup.cont:
// CHECK-NEXT:    call void @exit(i32 noundef 1) #[[ATTR4]]
// CHECK-NEXT:    call void @llvm.trap()
// CHECK-NEXT:    unreachable
// CHECK:       return:
// CHECK-NEXT:    ret void
// CHECK:       unreachable:
// CHECK-NEXT:    unreachable
//
// CHECK-EH-03-LABEL: @_Z5test4b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-EH-03-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-EH-03-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-EH-03-NEXT:    ]
// CHECK-EH-03:       cleanup.cont:
// CHECK-EH-03-NEXT:    call void @exit(i32 noundef 1) #[[ATTR7:[0-9]+]]
// CHECK-EH-03-NEXT:    call void @llvm.trap()
// CHECK-EH-03-NEXT:    unreachable
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       unreachable:
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z5test4b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-EH-11-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-EH-11-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-EH-11-NEXT:    ]
// CHECK-EH-11:       cleanup.cont:
// CHECK-EH-11-NEXT:    call void @exit(i32 noundef 1) #[[ATTR6]]
// CHECK-EH-11-NEXT:    call void @llvm.trap()
// CHECK-EH-11-NEXT:    unreachable
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       unreachable:
// CHECK-EH-11-NEXT:    unreachable
//
X test4(bool B) {
  {
    X x;
    if (B)
      return x; // NRVO happens
  }
  exit(1);
}

#ifdef __EXCEPTIONS
void may_throw();
// CHECK-EH-03-LABEL: @_Z5test5v(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    invoke void @_Z9may_throwv()
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    br label [[TRY_CONT:%.*]]
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr @_ZTI1X
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CATCH_DISPATCH:%.*]]
// CHECK-EH-03:       catch.dispatch:
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTI1X) #[[ATTR7]]
// CHECK-EH-03-NEXT:    [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
// CHECK-EH-03-NEXT:    br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]]
// CHECK-EH-03:       catch:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = call ptr @__cxa_get_exception_ptr(ptr [[EXN]]) #[[ATTR7]]
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[X]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP4]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       invoke.cont1:
// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR7]]
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD2:%.*]]
// CHECK-EH-03:       invoke.cont3:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT5:%.*]] unwind label [[LPAD4:%.*]]
// CHECK-EH-03:       lpad2:
// CHECK-EH-03-NEXT:    [[TMP6:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP7:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP7]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP8]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT6:%.*]] unwind label [[TERMINATE_LPAD]]
// CHECK-EH-03:       invoke.cont5:
// CHECK-EH-03-NEXT:    call void @__cxa_end_catch()
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       lpad4:
// CHECK-EH-03-NEXT:    [[TMP9:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP10:%.*]] = extractvalue { ptr, i32 } [[TMP9]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP10]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP11:%.*]] = extractvalue { ptr, i32 } [[TMP9]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP11]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[EHCLEANUP:%.*]]
// CHECK-EH-03:       invoke.cont6:
// CHECK-EH-03-NEXT:    br label [[EHCLEANUP]]
// CHECK-EH-03:       ehcleanup:
// CHECK-EH-03-NEXT:    invoke void @__cxa_end_catch()
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT7:%.*]] unwind label [[TERMINATE_LPAD]]
// CHECK-EH-03:       invoke.cont7:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME]]
// CHECK-EH-03:       try.cont:
// CHECK-EH-03-NEXT:    call void @llvm.trap()
// CHECK-EH-03-NEXT:    unreachable
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN8:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL9:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN8]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL10:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL9]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL10]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP12:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP13:%.*]] = extractvalue { ptr, i32 } [[TMP12]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP13]]) #[[ATTR6]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z5test5v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    invoke void @_Z9may_throwv()
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    br label [[TRY_CONT:%.*]]
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            catch ptr @_ZTI1X
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CATCH_DISPATCH:%.*]]
// CHECK-EH-11:       catch.dispatch:
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTI1X) #[[ATTR6]]
// CHECK-EH-11-NEXT:    [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]]
// CHECK-EH-11-NEXT:    br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]]
// CHECK-EH-11:       catch:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP4:%.*]] = call ptr @__cxa_get_exception_ptr(ptr [[EXN]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[X]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP4]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-11:       invoke.cont1:
// CHECK-EH-11-NEXT:    [[TMP5:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD2:%.*]]
// CHECK-EH-11:       invoke.cont3:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    call void @__cxa_end_catch()
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       lpad2:
// CHECK-EH-11-NEXT:    [[TMP6:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP7:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP7]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP8]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    invoke void @__cxa_end_catch()
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT4:%.*]] unwind label [[TERMINATE_LPAD]]
// CHECK-EH-11:       invoke.cont4:
// CHECK-EH-11-NEXT:    br label [[EH_RESUME]]
// CHECK-EH-11:       try.cont:
// CHECK-EH-11-NEXT:    call void @llvm.trap()
// CHECK-EH-11-NEXT:    unreachable
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN5:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL6:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN5]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL7:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL6]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL7]]
// CHECK-EH-11:       terminate.lpad:
// CHECK-EH-11-NEXT:    [[TMP9:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            catch ptr null
// CHECK-EH-11-NEXT:    [[TMP10:%.*]] = extractvalue { ptr, i32 } [[TMP9]], 0
// CHECK-EH-11-NEXT:    call void @__clang_call_terminate(ptr [[TMP10]]) #[[ATTR7:[0-9]+]]
// CHECK-EH-11-NEXT:    unreachable
//
X test5() { // http://wg21.link/p2025r2#ex-14
  try {
    may_throw();
  } catch (X x) {
    return x; // FIXME: NRVO could happen, but doesn't
  }
}
#endif

// CHECK-LABEL: @_Z5test6v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[A:%.*]] = alloca [[CLASS_X:%.*]], align 8
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]])
// CHECK-NEXT:    call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[A]])
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR4]]
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z5test6v(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[A:%.*]] = alloca [[CLASS_X:%.*]], align 8
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]])
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[A]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]])
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       invoke.cont1:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL2]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP4]]) #[[ATTR6]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z5test6v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[A:%.*]] = alloca [[CLASS_X:%.*]], align 8
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]])
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[A]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL1:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL1]]
//
X test6() {
  X a __attribute__((aligned(8)));
  return a; // NRVO is impossible
}

// CHECK-LABEL: @_Z5test7b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    br label [[RETURN:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z5test7b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[RETURN]]
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
//
// CHECK-EH-11-LABEL: @_Z5test7b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    br label [[RETURN]]
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
//
X test7(bool b) {
  if (b) {
    X x;
    return x; // NRVO happens
  }
  return X();
}

// CHECK-LABEL: @_Z5test8b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    br label [[RETURN:%.*]]
// CHECK:       if.else:
// CHECK-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-NEXT:    [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]]
// CHECK:       nrvo.unused3:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR4]]
// CHECK:       nrvo.skipdtor4:
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z5test8b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-03:       if.else:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]]
// CHECK-EH-03:       nrvo.unused3:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR4]]
// CHECK-EH-03:       nrvo.skipdtor4:
// CHECK-EH-03-NEXT:    br label [[RETURN]]
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
//
// CHECK-EH-11-LABEL: @_Z5test8b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-11:       if.else:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]]
// CHECK-EH-11:       nrvo.unused3:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR4]]
// CHECK-EH-11:       nrvo.skipdtor4:
// CHECK-EH-11-NEXT:    br label [[RETURN]]
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
//
X test8(bool b) {
  if (b) {
    X x;
    return x; // NRVO happens
  } else {
    X y;
    return y; // NRVO happens
  }
}

// CHECK-LABEL: @_Z5test9v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]])
// CHECK-NEXT:    call void @llvm.trap()
// CHECK-NEXT:    unreachable
//
// CHECK-EH-03-LABEL: @_Z5test9v(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]])
// CHECK-EH-03-NEXT:    call void @llvm.trap()
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z5test9v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]])
// CHECK-EH-11-NEXT:    call void @llvm.trap()
// CHECK-EH-11-NEXT:    unreachable
//
Y<int> test9() {
  Y<int>::f();
}

// CHECK-LABEL: @_Z6test10b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.else:
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]]
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z6test10b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT2:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       if.else:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]]
// CHECK-EH-03:       invoke.cont1:
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       invoke.cont2:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL3:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL3]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test10b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       if.else:
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]]
// CHECK-EH-11:       invoke.cont1:
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL2]]
//
X test10(bool b) { // http://wg21.link/p2025r2#ex-3
  X x;
  if (b)
    return x; // NRVO is impossible
  else
    return X();
}

// CHECK-LABEL: @_Z6test11b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]]
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z6test11b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT2:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]]
// CHECK-EH-03:       invoke.cont1:
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       invoke.cont2:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL3:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL3]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test11b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]]
// CHECK-EH-11:       invoke.cont1:
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL2]]
//
X test11(bool b) { // http://wg21.link/p2025r2#ex-5
  X x;
  if (b)
    return X();
  return x; // NRVO is impossible
}

// CHECK-LABEL: @_Z6test12b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    br label [[DO_BODY:%.*]]
// CHECK:       do.body:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-NEXT:      i32 2, label [[DO_END:%.*]]
// CHECK-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-NEXT:    ]
// CHECK:       do.end:
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    ret void
// CHECK:       unreachable:
// CHECK-NEXT:    unreachable
//
// CHECK-EH-03-LABEL: @_Z6test12b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    br label [[DO_BODY:%.*]]
// CHECK-EH-03:       do.body:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-EH-03-NEXT:      i32 2, label [[DO_END:%.*]]
// CHECK-EH-03-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-EH-03-NEXT:    ]
// CHECK-EH-03:       do.end:
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[RETURN]]
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       unreachable:
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test12b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    br label [[DO_BODY:%.*]]
// CHECK-EH-11:       do.body:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-EH-11-NEXT:      i32 2, label [[DO_END:%.*]]
// CHECK-EH-11-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-EH-11-NEXT:    ]
// CHECK-EH-11:       do.end:
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    br label [[RETURN]]
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       unreachable:
// CHECK-EH-11-NEXT:    unreachable
//
X test12(bool b) { // http://wg21.link/p2025r2#ex-6
  do {
    X x;
    if (b)
      break;
    return x; // NRVO happens
  } while (false);
  return X();
}

// CHECK-LABEL: @_Z6test13b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    br label [[RETURN:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z6test13b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    br label [[RETURN]]
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
//
// CHECK-EH-11-LABEL: @_Z6test13b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    br label [[RETURN]]
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
//
X test13(bool b) { // http://wg21.link/p2025r2#ex-7
  if (b)
    return X();
  X x;
  return x; // FIXME: NRVO could happen, but doesn't
}

// CHECK-LABEL: @_Z6test14b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]]
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z6test14b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]]
// CHECK-EH-03:       invoke.cont1:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
// CHECK-EH-03:       invoke.cont2:
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       invoke.cont3:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL4]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test14b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]]
// CHECK-EH-11:       invoke.cont1:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL2]]
//
X test14(bool b) { // http://wg21.link/p2025r2#ex-8
  X x;
  if (b)
    return x;
  X y;
  return y; // FIXME: NRVO could happen, but doesn't
}

// CHECK-LABEL: @_Z6test15b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]]
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z6test15b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]]
// CHECK-EH-03:       invoke.cont1:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]]
// CHECK-EH-03:       invoke.cont2:
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       invoke.cont3:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL4]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test15b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]]
// CHECK-EH-11:       invoke.cont1:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL2]]
//
X test15(bool b) { // http://wg21.link/p2025r2#ex-15
  X x;
  if (b)
    return (x);
  X y;
  return ((y)); // FIXME: NRVO could happen, but doesn't
}

#ifdef CXX11
// CHECK-EH-11-LABEL: @_Z6test16v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[AGG_TMP:%.*]] = alloca [[CLASS_X]], align 1
// CHECK-EH-11-NEXT:    [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 4
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0
// CHECK-EH-11-NEXT:    store ptr [[X]], ptr [[TMP0]], align 4
// CHECK-EH-11-NEXT:    invoke void @"_ZZ6test16vENK3$_0clEv"(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP]], ptr noundef nonnull align 4 dereferenceable(4) [[REF_TMP]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    invoke void @_Z8ConsumeX1X(ptr noundef [[AGG_TMP]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]]
// CHECK-EH-11:       invoke.cont2:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[EHCLEANUP:%.*]]
// CHECK-EH-11:       lpad1:
// CHECK-EH-11-NEXT:    [[TMP4:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP5]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP6:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP6]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EHCLEANUP]]
// CHECK-EH-11:       ehcleanup:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL3:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL3]]
//
void test16() { // http://wg21.link/p2025r2#ex-9
  X x;
  ConsumeX([&] {
    X y(x);
    return y; // NRVO happens
  }());
}
#endif

// CHECK-LABEL: @_Z6test17i(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[I_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    store i32 [[I:%.*]], ptr [[I_ADDR]], align 4
// CHECK-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_END2:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    br label [[IMPOSSIBLE:%.*]]
// CHECK:       impossible:
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 3
// CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then1:
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    br label [[RETURN:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    br label [[IF_END2]]
// CHECK:       if.end2:
// CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
// CHECK:       while.body:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[TMP1]], 0
// CHECK-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END5:%.*]]
// CHECK:       if.then4:
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end5:
// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP6:%.*]] = icmp eq i32 [[TMP2]], 1
// CHECK-NEXT:    br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_END8:%.*]]
// CHECK:       if.then7:
// CHECK-NEXT:    store i32 4, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       if.end8:
// CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[TMP3]], 2
// CHECK-NEXT:    br i1 [[CMP9]], label [[IF_THEN10:%.*]], label [[IF_END11:%.*]]
// CHECK:       if.then10:
// CHECK-NEXT:    store i32 3, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]], !llvm.loop [[LOOP3:![0-9]+]]
// CHECK:       if.end11:
// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP12:%.*]] = icmp eq i32 [[TMP4]], 3
// CHECK-NEXT:    br i1 [[CMP12]], label [[IF_THEN13:%.*]], label [[IF_END14:%.*]]
// CHECK:       if.then13:
// CHECK-NEXT:    store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       if.end14:
// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP15:%.*]] = icmp eq i32 [[TMP5]], 4
// CHECK-NEXT:    br i1 [[CMP15]], label [[IF_THEN16:%.*]], label [[IF_END17:%.*]]
// CHECK:       if.then16:
// CHECK-NEXT:    call void @exit(i32 noundef 1) #[[ATTR4]]
// CHECK-NEXT:    br label [[IF_END17]]
// CHECK:       if.end17:
// CHECK-NEXT:    [[TMP6:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP18:%.*]] = icmp eq i32 [[TMP6]], 5
// CHECK-NEXT:    br i1 [[CMP18]], label [[IF_THEN19:%.*]], label [[IF_END20:%.*]]
// CHECK:       if.then19:
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       if.end20:
// CHECK-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-NEXT:      i32 1, label [[RETURN]]
// CHECK-NEXT:      i32 4, label [[WHILE_END:%.*]]
// CHECK-NEXT:      i32 3, label [[WHILE_BODY]]
// CHECK-NEXT:      i32 2, label [[IMPOSSIBLE]]
// CHECK-NEXT:    ]
// CHECK:       cleanup.cont:
// CHECK-NEXT:    br label [[WHILE_BODY]], !llvm.loop [[LOOP3]]
// CHECK:       while.end:
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    ret void
// CHECK:       unreachable:
// CHECK-NEXT:    unreachable
//
// CHECK-EH-03-LABEL: @_Z6test17i(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[I_ADDR:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    store i32 [[I:%.*]], ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_END2:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    br label [[IMPOSSIBLE:%.*]]
// CHECK-EH-03:       impossible:
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 3
// CHECK-EH-03-NEXT:    br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then1:
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    br label [[IF_END2]]
// CHECK-EH-03:       if.end2:
// CHECK-EH-03-NEXT:    br label [[WHILE_BODY:%.*]]
// CHECK-EH-03:       while.body:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[TMP1]], 0
// CHECK-EH-03-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END5:%.*]]
// CHECK-EH-03:       if.then4:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       if.end5:
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP6:%.*]] = icmp eq i32 [[TMP2]], 1
// CHECK-EH-03-NEXT:    br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_END8:%.*]]
// CHECK-EH-03:       if.then7:
// CHECK-EH-03-NEXT:    store i32 4, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       if.end8:
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[TMP3]], 2
// CHECK-EH-03-NEXT:    br i1 [[CMP9]], label [[IF_THEN10:%.*]], label [[IF_END11:%.*]]
// CHECK-EH-03:       if.then10:
// CHECK-EH-03-NEXT:    store i32 3, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       if.end11:
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP12:%.*]] = icmp eq i32 [[TMP4]], 3
// CHECK-EH-03-NEXT:    br i1 [[CMP12]], label [[IF_THEN13:%.*]], label [[IF_END14:%.*]]
// CHECK-EH-03:       if.then13:
// CHECK-EH-03-NEXT:    store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       if.end14:
// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP15:%.*]] = icmp eq i32 [[TMP5]], 4
// CHECK-EH-03-NEXT:    br i1 [[CMP15]], label [[IF_THEN16:%.*]], label [[IF_END17:%.*]]
// CHECK-EH-03:       if.then16:
// CHECK-EH-03-NEXT:    call void @exit(i32 noundef 1) #[[ATTR7]]
// CHECK-EH-03-NEXT:    br label [[IF_END17]]
// CHECK-EH-03:       if.end17:
// CHECK-EH-03-NEXT:    [[TMP6:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP18:%.*]] = icmp eq i32 [[TMP6]], 5
// CHECK-EH-03-NEXT:    br i1 [[CMP18]], label [[IF_THEN19:%.*]], label [[IF_END20:%.*]]
// CHECK-EH-03:       if.then19:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       if.end20:
// CHECK-EH-03-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-EH-03-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-EH-03-NEXT:      i32 1, label [[RETURN]]
// CHECK-EH-03-NEXT:      i32 4, label [[WHILE_END:%.*]]
// CHECK-EH-03-NEXT:      i32 3, label [[WHILE_BODY]]
// CHECK-EH-03-NEXT:      i32 2, label [[IMPOSSIBLE]]
// CHECK-EH-03-NEXT:    ]
// CHECK-EH-03:       cleanup.cont:
// CHECK-EH-03-NEXT:    br label [[WHILE_BODY]]
// CHECK-EH-03:       while.end:
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[RETURN]]
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       unreachable:
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test17i(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[I_ADDR:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    store i32 [[I:%.*]], ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    br i1 false, label [[IF_THEN:%.*]], label [[IF_END2:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    br label [[IMPOSSIBLE:%.*]]
// CHECK-EH-11:       impossible:
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 3
// CHECK-EH-11-NEXT:    br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then1:
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    br label [[IF_END2]]
// CHECK-EH-11:       if.end2:
// CHECK-EH-11-NEXT:    br label [[WHILE_BODY:%.*]]
// CHECK-EH-11:       while.body:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP3:%.*]] = icmp eq i32 [[TMP1]], 0
// CHECK-EH-11-NEXT:    br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END5:%.*]]
// CHECK-EH-11:       if.then4:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       if.end5:
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP6:%.*]] = icmp eq i32 [[TMP2]], 1
// CHECK-EH-11-NEXT:    br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_END8:%.*]]
// CHECK-EH-11:       if.then7:
// CHECK-EH-11-NEXT:    store i32 4, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       if.end8:
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP9:%.*]] = icmp eq i32 [[TMP3]], 2
// CHECK-EH-11-NEXT:    br i1 [[CMP9]], label [[IF_THEN10:%.*]], label [[IF_END11:%.*]]
// CHECK-EH-11:       if.then10:
// CHECK-EH-11-NEXT:    store i32 3, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]], !llvm.loop [[LOOP3:![0-9]+]]
// CHECK-EH-11:       if.end11:
// CHECK-EH-11-NEXT:    [[TMP4:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP12:%.*]] = icmp eq i32 [[TMP4]], 3
// CHECK-EH-11-NEXT:    br i1 [[CMP12]], label [[IF_THEN13:%.*]], label [[IF_END14:%.*]]
// CHECK-EH-11:       if.then13:
// CHECK-EH-11-NEXT:    store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       if.end14:
// CHECK-EH-11-NEXT:    [[TMP5:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP15:%.*]] = icmp eq i32 [[TMP5]], 4
// CHECK-EH-11-NEXT:    br i1 [[CMP15]], label [[IF_THEN16:%.*]], label [[IF_END17:%.*]]
// CHECK-EH-11:       if.then16:
// CHECK-EH-11-NEXT:    call void @exit(i32 noundef 1) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[IF_END17]]
// CHECK-EH-11:       if.end17:
// CHECK-EH-11-NEXT:    [[TMP6:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP18:%.*]] = icmp eq i32 [[TMP6]], 5
// CHECK-EH-11-NEXT:    br i1 [[CMP18]], label [[IF_THEN19:%.*]], label [[IF_END20:%.*]]
// CHECK-EH-11:       if.then19:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       if.end20:
// CHECK-EH-11-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-EH-11-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-EH-11-NEXT:      i32 1, label [[RETURN]]
// CHECK-EH-11-NEXT:      i32 4, label [[WHILE_END:%.*]]
// CHECK-EH-11-NEXT:      i32 3, label [[WHILE_BODY]]
// CHECK-EH-11-NEXT:      i32 2, label [[IMPOSSIBLE]]
// CHECK-EH-11-NEXT:    ]
// CHECK-EH-11:       cleanup.cont:
// CHECK-EH-11-NEXT:    br label [[WHILE_BODY]], !llvm.loop [[LOOP3]]
// CHECK-EH-11:       while.end:
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    br label [[RETURN]]
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       unreachable:
// CHECK-EH-11-NEXT:    unreachable
//
X test17(int i) { // http://wg21.link/p2025r2#ex-10
  if (false) {
  impossible:
    if (i == 3)
      return X();
  }

  while (true) {
    X x;
    if (i == 0)
      return x; // NRVO happens
    if (i == 1)
      break;
    if (i == 2)
      continue;
    if (i == 3)
      goto impossible;
    if (i == 4)
      exit(1);
    if (i == 5)
      return x; // NRVO happens
  }
  return X();
}

// CHECK-LABEL: @_Z6test18i(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[I_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[NRVO11:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    store i32 [[I:%.*]], ptr [[I_ADDR]], align 4
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
// CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP]]
// CHECK:       cleanup:
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-NEXT:    ]
// CHECK:       cleanup.cont:
// CHECK-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[TMP1]], 1
// CHECK-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]]
// CHECK:       if.then3:
// CHECK-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP5:%.*]]
// CHECK:       if.end4:
// CHECK-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    br label [[CLEANUP5]]
// CHECK:       cleanup5:
// CHECK-NEXT:    [[NRVO_VAL6:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL6]], label [[NRVO_SKIPDTOR8:%.*]], label [[NRVO_UNUSED7:%.*]]
// CHECK:       nrvo.unused7:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR8]]
// CHECK:       nrvo.skipdtor8:
// CHECK-NEXT:    [[CLEANUP_DEST9:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    switch i32 [[CLEANUP_DEST9]], label [[UNREACHABLE]] [
// CHECK-NEXT:      i32 0, label [[CLEANUP_CONT10:%.*]]
// CHECK-NEXT:      i32 1, label [[RETURN]]
// CHECK-NEXT:    ]
// CHECK:       cleanup.cont10:
// CHECK-NEXT:    store i1 false, ptr [[NRVO11]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO11]], align 1
// CHECK-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-NEXT:    [[NRVO_VAL13:%.*]] = load i1, ptr [[NRVO11]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL13]], label [[NRVO_SKIPDTOR15:%.*]], label [[NRVO_UNUSED14:%.*]]
// CHECK:       nrvo.unused14:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR15]]
// CHECK:       nrvo.skipdtor15:
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    ret void
// CHECK:       unreachable:
// CHECK-NEXT:    unreachable
//
// CHECK-EH-03-LABEL: @_Z6test18i(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[I_ADDR:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[NRVO11:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    store i32 [[I:%.*]], ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
// CHECK-EH-03-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
// CHECK-EH-03:       cleanup:
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-EH-03-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-EH-03-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-EH-03-NEXT:    ]
// CHECK-EH-03:       cleanup.cont:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-03-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[TMP1]], 1
// CHECK-EH-03-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]]
// CHECK-EH-03:       if.then3:
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP5:%.*]]
// CHECK-EH-03:       if.end4:
// CHECK-EH-03-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    br label [[CLEANUP5]]
// CHECK-EH-03:       cleanup5:
// CHECK-EH-03-NEXT:    [[NRVO_VAL6:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL6]], label [[NRVO_SKIPDTOR8:%.*]], label [[NRVO_UNUSED7:%.*]]
// CHECK-EH-03:       nrvo.unused7:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR8]]
// CHECK-EH-03:       nrvo.skipdtor8:
// CHECK-EH-03-NEXT:    [[CLEANUP_DEST9:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    switch i32 [[CLEANUP_DEST9]], label [[UNREACHABLE]] [
// CHECK-EH-03-NEXT:      i32 0, label [[CLEANUP_CONT10:%.*]]
// CHECK-EH-03-NEXT:      i32 1, label [[RETURN]]
// CHECK-EH-03-NEXT:    ]
// CHECK-EH-03:       cleanup.cont10:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO11]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO11]], align 1
// CHECK-EH-03-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[NRVO_VAL13:%.*]] = load i1, ptr [[NRVO11]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL13]], label [[NRVO_SKIPDTOR15:%.*]], label [[NRVO_UNUSED14:%.*]]
// CHECK-EH-03:       nrvo.unused14:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR15]]
// CHECK-EH-03:       nrvo.skipdtor15:
// CHECK-EH-03-NEXT:    br label [[RETURN]]
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       unreachable:
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test18i(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[I_ADDR:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    [[NRVO1:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[NRVO11:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    store i32 [[I:%.*]], ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
// CHECK-EH-11-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
// CHECK-EH-11:       cleanup:
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [
// CHECK-EH-11-NEXT:      i32 0, label [[CLEANUP_CONT:%.*]]
// CHECK-EH-11-NEXT:      i32 1, label [[RETURN:%.*]]
// CHECK-EH-11-NEXT:    ]
// CHECK-EH-11:       cleanup.cont:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4
// CHECK-EH-11-NEXT:    [[CMP2:%.*]] = icmp eq i32 [[TMP1]], 1
// CHECK-EH-11-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]]
// CHECK-EH-11:       if.then3:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP5:%.*]]
// CHECK-EH-11:       if.end4:
// CHECK-EH-11-NEXT:    store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    br label [[CLEANUP5]]
// CHECK-EH-11:       cleanup5:
// CHECK-EH-11-NEXT:    [[NRVO_VAL6:%.*]] = load i1, ptr [[NRVO1]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL6]], label [[NRVO_SKIPDTOR8:%.*]], label [[NRVO_UNUSED7:%.*]]
// CHECK-EH-11:       nrvo.unused7:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR8]]
// CHECK-EH-11:       nrvo.skipdtor8:
// CHECK-EH-11-NEXT:    [[CLEANUP_DEST9:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    switch i32 [[CLEANUP_DEST9]], label [[UNREACHABLE]] [
// CHECK-EH-11-NEXT:      i32 0, label [[CLEANUP_CONT10:%.*]]
// CHECK-EH-11-NEXT:      i32 1, label [[RETURN]]
// CHECK-EH-11-NEXT:    ]
// CHECK-EH-11:       cleanup.cont10:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO11]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO11]], align 1
// CHECK-EH-11-NEXT:    store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[NRVO_VAL13:%.*]] = load i1, ptr [[NRVO11]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL13]], label [[NRVO_SKIPDTOR15:%.*]], label [[NRVO_UNUSED14:%.*]]
// CHECK-EH-11:       nrvo.unused14:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR15]]
// CHECK-EH-11:       nrvo.skipdtor15:
// CHECK-EH-11-NEXT:    br label [[RETURN]]
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       unreachable:
// CHECK-EH-11-NEXT:    unreachable
//
X test18(int i) { // http://wg21.link/p2025r2#ex-11
  {
    {
      X x;
      if (i == 0)
        return x; // NRVO happens
    }
    X y;
    if (i == 1)
      return y; // FIXME: NRVO could happen, but doesn't
  }
  X z;
  return z; // FIXME: NRVO could happen, but doesn't
}

#ifdef CXX11
// CHECK-EH-11-LABEL: @_Z6test19v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[L:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[REF_TMP:%.*]] = alloca [[CLASS_ANON_0:%.*]], align 4
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT]], ptr [[TMP0]], align 4
// CHECK-EH-11-NEXT:    invoke void @"_ZZ6test19vENK3$_0clEv"(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[L]], ptr noundef nonnull align 4 dereferenceable(4) [[REF_TMP]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[L]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL1:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL1]]
//
X test19() { // http://wg21.link/p2025r2#ex-12
  X x;
  struct S {
    X f() { return X(); }
  };
  auto L = [&x]() { return X(); }();
  if constexpr (false) {
    return X();
  }
  return x; // NRVO happens
}

template <bool B>
X test20() { // http://wg21.link/p2025r2#ex-18
  X x;
  if constexpr (B) {
    if (false)
      return X();
  }
  return x; // FIXME: NRVO could happen when B == false, but doesn't
}

// CHECK-EH-11-LABEL: @_Z17test20instantiatev(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[AGG_TMP_ENSURED:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[AGG_TMP_ENSURED1:%.*]] = alloca [[CLASS_X]], align 1
// CHECK-EH-11-NEXT:    call void @_Z6test20ILb1EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED]])
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    call void @_Z6test20ILb0EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED1]])
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED1]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
//
void test20instantiate() {
  test20<true>();
  test20<false>();
}
#endif

// CHECK-LABEL: @_Z6test21v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z6test21v(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    ret void
//
// CHECK-EH-11-LABEL: @_Z6test21v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    ret void
//
const volatile X test21() { // http://wg21.link/p2025r2#ex-19
  X x;
  return x; // NRVO happens
}

// CHECK-LABEL: @_Z6test22v(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    call void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]]
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z6test22v(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       invoke.cont1:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL2]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP4]]) #[[ATTR6]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test22v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL1:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL1]]
//
X test22() { // http://wg21.link/p2025r2#ex-19
  volatile X x;
  return x; // NRVO is impossible
}

// CHECK-LABEL: @_Z6test23b(
// CHECK-NEXT:  entry:
// CHECK-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK:       if.then:
// CHECK-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK:       nrvo.unused:
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK:       nrvo.skipdtor:
// CHECK-NEXT:    br label [[RETURN:%.*]]
// CHECK:       if.end:
// CHECK-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-NEXT:    call void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR4]]
// CHECK-NEXT:    br label [[RETURN]]
// CHECK:       return:
// CHECK-NEXT:    ret void
//
// CHECK-EH-03-LABEL: @_Z6test23b(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-03-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-03-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-03-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-03-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-03:       if.then:
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-03:       if.end:
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-03:       invoke.cont:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-03-NEXT:    br label [[RETURN]]
// CHECK-EH-03:       lpad:
// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            cleanup
// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-03-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-03-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-03-NEXT:            to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
// CHECK-EH-03:       invoke.cont1:
// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-03:       return:
// CHECK-EH-03-NEXT:    ret void
// CHECK-EH-03:       eh.resume:
// CHECK-EH-03-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-03-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-03-NEXT:    [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-03-NEXT:    resume { ptr, i32 } [[LPAD_VAL2]]
// CHECK-EH-03:       terminate.lpad:
// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-03-NEXT:            catch ptr null
// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0
// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]]
// CHECK-EH-03-NEXT:    unreachable
//
// CHECK-EH-11-LABEL: @_Z6test23b(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8
// CHECK-EH-11-NEXT:    store i8 [[STOREDV]], ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-EH-11-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1
// CHECK-EH-11-NEXT:    br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
// CHECK-EH-11:       if.then:
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
// CHECK-EH-11:       if.end:
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]])
// CHECK-EH-11-NEXT:            to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
// CHECK-EH-11:       invoke.cont:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[RETURN]]
// CHECK-EH-11:       lpad:
// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { ptr, i32 }
// CHECK-EH-11-NEXT:            cleanup
// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0
// CHECK-EH-11-NEXT:    store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1
// CHECK-EH-11-NEXT:    store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
// CHECK-EH-11:       return:
// CHECK-EH-11-NEXT:    ret void
// CHECK-EH-11:       eh.resume:
// CHECK-EH-11-NEXT:    [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4
// CHECK-EH-11-NEXT:    [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0
// CHECK-EH-11-NEXT:    [[LPAD_VAL1:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1
// CHECK-EH-11-NEXT:    resume { ptr, i32 } [[LPAD_VAL1]]
//
X test23(bool b) { // http://wg21.link/p2025r2#ex-19
  if (b) {
    const X x;
    return x; // NRVO happens
  }
  volatile X y;
  return y; // NRVO is impossible
}

#ifdef __EXCEPTIONS
// CHECK-EH-03-LABEL: @_Z6test24v(
// CHECK-EH-03-NEXT:  entry:
// CHECK-EH-03-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-03-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-03-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-03-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-03-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-03:       nrvo.unused:
// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-03-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-03:       nrvo.skipdtor:
// CHECK-EH-03-NEXT:    ret void
//
// CHECK-EH-11-LABEL: @_Z6test24v(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[RESULT_PTR:%.*]] = alloca ptr, align 4
// CHECK-EH-11-NEXT:    [[NRVO:%.*]] = alloca i1, align 1
// CHECK-EH-11-NEXT:    store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
// CHECK-EH-11-NEXT:    store i1 false, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
// CHECK-EH-11-NEXT:    store i1 true, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1
// CHECK-EH-11-NEXT:    br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
// CHECK-EH-11:       nrvo.unused:
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
// CHECK-EH-11:       nrvo.skipdtor:
// CHECK-EH-11-NEXT:    ret void
//
X test24() { // http://wg21.link/p2025r2#ex-20
  X x;
  if (&x == &OuterX)
    throw 0;
  return x; // NRVO happens
}
#endif

#ifdef CXX11
template <bool B>
X test25() {
  X x;
  if constexpr (B) {
    return x; // FIXME: NRVO could happen when B == true, but doesn't
  } else {
    return X();
  }
}

// CHECK-EH-11-LABEL: @_Z17test25instantiatev(
// CHECK-EH-11-NEXT:  entry:
// CHECK-EH-11-NEXT:    [[AGG_TMP_ENSURED:%.*]] = alloca [[CLASS_X:%.*]], align 1
// CHECK-EH-11-NEXT:    [[AGG_TMP_ENSURED1:%.*]] = alloca [[CLASS_X]], align 1
// CHECK-EH-11-NEXT:    call void @_Z6test25ILb1EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED]])
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    call void @_Z6test25ILb0EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED1]])
// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED1]]) #[[ATTR6]]
// CHECK-EH-11-NEXT:    ret void
//
void test25instantiate() {
  test25<true>();
  test25<false>();
}
#endif
