Izaron updated this revision to Diff 409389.
Izaron added a comment.

I placed links to corresponding p2025 examples.

Some of the examples are reasonably absent from the test, such as 1st (RVO, not 
NRVO), 13th (consteval methods are not getting to LLVM IR), 17th (there are no 
NRVOs for non-class types in Clang), etc.

The 19th example (about volatiles) is massive and has three corresponding 
functions in the test.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119927/new/

https://reviews.llvm.org/D119927

Files:
  clang/test/CodeGenCXX/nrvo.cpp

Index: clang/test/CodeGenCXX/nrvo.cpp
===================================================================
--- clang/test/CodeGenCXX/nrvo.cpp
+++ clang/test/CodeGenCXX/nrvo.cpp
@@ -1,13 +1,14 @@
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
 // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s
 // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++03 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-03 %s
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++11 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-11 %s
+// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++11 -DCXX11 -o - %s | FileCheck --check-prefixes=CHECK-EH,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();
 };
 
@@ -19,6 +20,9 @@
   }
 };
 
+void ConsumeX(X x);
+extern X OuterX;
+
 // CHECK-LABEL: @_Z5test0v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5:[0-9]+]]
@@ -29,10 +33,9 @@
 // CHECK-EH-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
 // CHECK-EH-NEXT:    ret void
 //
-X test0() {
+X test0() { // http://wg21.link/p2025r2#ex-2
   X x;
-
-  return x;
+  return x; // NRVO happens
 }
 
 // CHECK-LABEL: @_Z5test1b(
@@ -48,8 +51,8 @@
 X test1(bool B) {
   X x;
   if (B)
-    return (x);
-  return x;
+    return (x); // NRVO happens
+  return x;     // NRVO happens
 }
 
 // CHECK-LABEL: @_Z5test2b(
@@ -155,13 +158,11 @@
 // CHECK-EH-11-NEXT:    resume { i8*, i32 } [[DOTPN]]
 //
 X test2(bool B) {
-  // No NRVO.
-
   X x;
   X y;
   if (B)
-    return y;
-  return x;
+    return y; // NRVO is impossible
+  return x;   // NRVO is impossible
 }
 
 // CHECK-LABEL: @_Z5test3b(
@@ -242,14 +243,13 @@
 // CHECK-EH-11:       return:
 // CHECK-EH-11-NEXT:    ret void
 //
-X test3(bool B) {
+X test3(bool B) { // http://wg21.link/p2025r2#ex-4
   if (B) {
     X y;
-    return y;
+    return y; // NRVO happens
   }
-  // FIXME: we should NRVO this variable too.
   X x;
-  return x;
+  return x; // FIXME: NRVO could happen, but doesn't
 }
 
 extern "C" void exit(int) throw();
@@ -291,7 +291,7 @@
   {
     X x;
     if (B)
-      return x;
+      return x; // NRVO happens
   }
   exit(1);
 }
@@ -407,11 +407,11 @@
 // CHECK-EH-11-NEXT:    call void @__clang_call_terminate(i8* [[TMP10]]) #[[ATTR8:[0-9]+]]
 // CHECK-EH-11-NEXT:    unreachable
 //
-X test5() {
+X test5() { // http://wg21.link/p2025r2#ex-14
   try {
     may_throw();
   } catch (X x) {
-    return x;
+    return x; // FIXME: NRVO could happen, but doesn't
   }
 }
 #endif
@@ -476,7 +476,7 @@
 //
 X test6() {
   X a __attribute__((aligned(8)));
-  return a;
+  return a; // NRVO is impossible
 }
 
 // CHECK-LABEL: @_Z5test7b(
@@ -492,7 +492,7 @@
 X test7(bool b) {
   if (b) {
     X x;
-    return x;
+    return x; // NRVO happens
   }
   return X();
 }
@@ -510,10 +510,10 @@
 X test8(bool b) {
   if (b) {
     X x;
-    return x;
+    return x; // NRVO happens
   } else {
     X y;
-    return y;
+    return y; // NRVO happens
   }
 }
 
@@ -536,3 +536,1227 @@
 Y<int> test9() {
   Y<int>::f();
 }
+
+// CHECK-LABEL: @_Z6test10b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+// CHECK:       if.then:
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[CLEANUP:%.*]]
+// CHECK:       if.else:
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[CLEANUP]]
+// CHECK:       cleanup:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    ret void
+//
+// CHECK-EH-03-LABEL: @_Z6test10b(
+// CHECK-EH-03-NEXT:  entry:
+// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+// CHECK-EH-03:       if.then:
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-03:       lpad:
+// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* 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(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP]] unwind label [[LPAD]]
+// CHECK-EH-03:       cleanup:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    ret void
+// CHECK-EH-03:       invoke.cont2:
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
+// CHECK-EH-03:       terminate.lpad:
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    catch i8* null
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    unreachable
+//
+// CHECK-EH-11-LABEL: @_Z6test10b(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+// CHECK-EH-11:       if.then:
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
+// CHECK-EH-11:       if.else:
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP]] unwind label [[LPAD]]
+// CHECK-EH-11:       cleanup:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    ret void
+//
+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:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK:       if.then:
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[CLEANUP:%.*]]
+// CHECK:       if.end:
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[CLEANUP]]
+// CHECK:       cleanup:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    ret void
+//
+// CHECK-EH-03-LABEL: @_Z6test11b(
+// CHECK-EH-03-NEXT:  entry:
+// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-03:       if.then:
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-03:       lpad:
+// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* 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_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP]] unwind label [[LPAD]]
+// CHECK-EH-03:       cleanup:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    ret void
+// CHECK-EH-03:       invoke.cont2:
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
+// CHECK-EH-03:       terminate.lpad:
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    catch i8* null
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    unreachable
+//
+// CHECK-EH-11-LABEL: @_Z6test11b(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-11:       if.then:
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
+// CHECK-EH-11:       if.end:
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP]] unwind label [[LPAD]]
+// CHECK-EH-11:       cleanup:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    ret void
+//
+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:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
+// CHECK-NEXT:    br i1 [[B:%.*]], label [[NRVO_UNUSED:%.*]], label [[RETURN:%.*]]
+// CHECK:       nrvo.unused:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[RETURN]]
+// CHECK:       return:
+// CHECK-NEXT:    ret void
+//
+// CHECK-EH-03-LABEL: @_Z6test12b(
+// CHECK-EH-03-NEXT:  entry:
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[NRVO_UNUSED:%.*]], label [[RETURN:%.*]]
+// CHECK-EH-03:       nrvo.unused:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* 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: @_Z6test12b(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[NRVO_UNUSED:%.*]], label [[RETURN:%.*]]
+// CHECK-EH-11:       nrvo.unused:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* 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 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:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK:       if.then:
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[RETURN:%.*]]
+// CHECK:       if.end:
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// 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:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-03:       if.then:
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
+// CHECK-EH-03:       if.end:
+// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* 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(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[RETURN]]
+// CHECK-EH-03:       lpad:
+// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* 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:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
+// CHECK-EH-03:       return:
+// CHECK-EH-03-NEXT:    ret void
+// CHECK-EH-03:       terminate.lpad:
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    catch i8* null
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    unreachable
+//
+// CHECK-EH-11-LABEL: @_Z6test13b(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-11:       if.then:
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
+// CHECK-EH-11:       if.end:
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* 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(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[RETURN]]
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
+// 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:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK:       if.then:
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[CLEANUP:%.*]]
+// CHECK:       if.end:
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[CLEANUP]]
+// CHECK:       cleanup:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    ret void
+//
+// CHECK-EH-03-LABEL: @_Z6test14b(
+// CHECK-EH-03-NEXT:  entry:
+// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-03-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-03:       if.then:
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-03:       lpad:
+// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    br label [[EHCLEANUP7:%.*]]
+// CHECK-EH-03:       if.end:
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(%class.X* 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:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD3:%.*]]
+// CHECK-EH-03:       invoke.cont4:
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT5:%.*]] unwind label [[LPAD1]]
+// CHECK-EH-03:       lpad1:
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    br label [[EHCLEANUP:%.*]]
+// CHECK-EH-03:       lpad3:
+// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    to label [[EHCLEANUP]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK-EH-03:       invoke.cont5:
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-03:       ehcleanup:
+// CHECK-EH-03-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP3]], [[LPAD1]] ], [ [[TMP4]], [[LPAD3]] ]
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[EHCLEANUP7]]
+// CHECK-EH-03:       cleanup:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    ret void
+// CHECK-EH-03:       ehcleanup7:
+// CHECK-EH-03-NEXT:    [[DOTPN13:%.*]] = phi { i8*, i32 } [ [[TMP1]], [[LPAD]] ], [ [[DOTPN]], [[EHCLEANUP]] ]
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT8:%.*]] unwind label [[TERMINATE_LPAD]]
+// CHECK-EH-03:       invoke.cont8:
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[DOTPN13]]
+// CHECK-EH-03:       terminate.lpad:
+// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    catch i8* null
+// CHECK-EH-03-NEXT:    [[TMP6:%.*]] = extractvalue { i8*, i32 } [[TMP5]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP6]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    unreachable
+//
+// CHECK-EH-11-LABEL: @_Z6test14b(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-11:       if.then:
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP5:%.*]]
+// CHECK-EH-11:       if.end:
+// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* 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:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD3:%.*]]
+// CHECK-EH-11:       invoke.cont4:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-11:       lpad1:
+// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP:%.*]]
+// CHECK-EH-11:       lpad3:
+// CHECK-EH-11-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP]]
+// CHECK-EH-11:       ehcleanup:
+// CHECK-EH-11-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP4]], [[LPAD3]] ], [ [[TMP3]], [[LPAD1]] ]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP5]]
+// CHECK-EH-11:       cleanup:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    ret void
+// CHECK-EH-11:       ehcleanup5:
+// CHECK-EH-11-NEXT:    [[DOTPN10:%.*]] = phi { i8*, i32 } [ [[TMP1]], [[LPAD]] ], [ [[DOTPN]], [[EHCLEANUP]] ]
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[DOTPN10]]
+//
+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:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK:       if.then:
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[CLEANUP:%.*]]
+// CHECK:       if.end:
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[CLEANUP]]
+// CHECK:       cleanup:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    ret void
+//
+// CHECK-EH-03-LABEL: @_Z6test15b(
+// CHECK-EH-03-NEXT:  entry:
+// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-03-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-03:       if.then:
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-03:       lpad:
+// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    br label [[EHCLEANUP7:%.*]]
+// CHECK-EH-03:       if.end:
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1Ev(%class.X* 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:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD3:%.*]]
+// CHECK-EH-03:       invoke.cont4:
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT5:%.*]] unwind label [[LPAD1]]
+// CHECK-EH-03:       lpad1:
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    br label [[EHCLEANUP:%.*]]
+// CHECK-EH-03:       lpad3:
+// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    to label [[EHCLEANUP]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK-EH-03:       invoke.cont5:
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-03:       ehcleanup:
+// CHECK-EH-03-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP3]], [[LPAD1]] ], [ [[TMP4]], [[LPAD3]] ]
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[EHCLEANUP7]]
+// CHECK-EH-03:       cleanup:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    ret void
+// CHECK-EH-03:       ehcleanup7:
+// CHECK-EH-03-NEXT:    [[DOTPN13:%.*]] = phi { i8*, i32 } [ [[TMP1]], [[LPAD]] ], [ [[DOTPN]], [[EHCLEANUP]] ]
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT8:%.*]] unwind label [[TERMINATE_LPAD]]
+// CHECK-EH-03:       invoke.cont8:
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[DOTPN13]]
+// CHECK-EH-03:       terminate.lpad:
+// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    catch i8* null
+// CHECK-EH-03-NEXT:    [[TMP6:%.*]] = extractvalue { i8*, i32 } [[TMP5]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP6]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    unreachable
+//
+// CHECK-EH-11-LABEL: @_Z6test15b(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-11:       if.then:
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP5:%.*]]
+// CHECK-EH-11:       if.end:
+// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* 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:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD3:%.*]]
+// CHECK-EH-11:       invoke.cont4:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-11:       lpad1:
+// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP:%.*]]
+// CHECK-EH-11:       lpad3:
+// CHECK-EH-11-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP]]
+// CHECK-EH-11:       ehcleanup:
+// CHECK-EH-11-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP4]], [[LPAD3]] ], [ [[TMP3]], [[LPAD1]] ]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP5]]
+// CHECK-EH-11:       cleanup:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    ret void
+// CHECK-EH-11:       ehcleanup5:
+// CHECK-EH-11-NEXT:    [[DOTPN10:%.*]] = phi { i8*, i32 } [ [[TMP1]], [[LPAD]] ], [ [[DOTPN]], [[EHCLEANUP]] ]
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[DOTPN10]]
+//
+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:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_TMP]], %class.X* 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:    invoke void @_Z8ConsumeX1X(%class.X* noundef nonnull [[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(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_TMP]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    ret void
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP:%.*]]
+// CHECK-EH-11:       lpad1:
+// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_TMP]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[EHCLEANUP]]
+// CHECK-EH-11:       ehcleanup:
+// CHECK-EH-11-NEXT:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP2]], [[LPAD1]] ], [ [[TMP1]], [[LPAD]] ]
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[DOTPN]]
+//
+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:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 3
+// CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
+// CHECK:       impossible:
+// CHECK-NEXT:    br i1 [[CMP]], label [[RETURN_SINK_SPLIT:%.*]], label [[WHILE_BODY_BACKEDGE:%.*]]
+// CHECK:       while.body.backedge:
+// CHECK-NEXT:    br label [[WHILE_BODY]], !llvm.loop [[LOOP3:![0-9]+]]
+// CHECK:       while.body:
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
+// CHECK-NEXT:    switch i32 [[I]], label [[IF_END20:%.*]] [
+// CHECK-NEXT:    i32 0, label [[CLEANUP:%.*]]
+// CHECK-NEXT:    i32 1, label [[IF_THEN7:%.*]]
+// CHECK-NEXT:    i32 2, label [[IF_THEN10:%.*]]
+// CHECK-NEXT:    i32 3, label [[IF_THEN13:%.*]]
+// CHECK-NEXT:    i32 4, label [[IF_THEN16:%.*]]
+// CHECK-NEXT:    i32 5, label [[CLEANUP]]
+// CHECK-NEXT:    ]
+// CHECK:       if.then7:
+// CHECK-NEXT:    br label [[CLEANUP]]
+// CHECK:       if.then10:
+// CHECK-NEXT:    br label [[CLEANUP]], !llvm.loop [[LOOP3]]
+// CHECK:       if.then13:
+// CHECK-NEXT:    br label [[CLEANUP]]
+// CHECK:       if.then16:
+// CHECK-NEXT:    call void @exit(i32 noundef 1) #[[ATTR5]]
+// CHECK-NEXT:    br label [[IF_END20]]
+// CHECK:       if.end20:
+// CHECK-NEXT:    br label [[CLEANUP]]
+// CHECK:       cleanup:
+// CHECK-NEXT:    [[NRVO_0:%.*]] = phi i1 [ false, [[IF_THEN7]] ], [ false, [[IF_THEN10]] ], [ false, [[IF_THEN13]] ], [ false, [[IF_END20]] ], [ true, [[WHILE_BODY]] ], [ true, [[WHILE_BODY]] ]
+// CHECK-NEXT:    [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ 4, [[IF_THEN7]] ], [ 3, [[IF_THEN10]] ], [ 2, [[IF_THEN13]] ], [ 0, [[IF_END20]] ], [ 1, [[WHILE_BODY]] ], [ 1, [[WHILE_BODY]] ]
+// CHECK-NEXT:    br i1 [[NRVO_0]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
+// CHECK:       nrvo.unused:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[NRVO_SKIPDTOR]]
+// CHECK:       nrvo.skipdtor:
+// CHECK-NEXT:    switch i32 [[CLEANUP_DEST_SLOT_0]], label [[UNREACHABLE:%.*]] [
+// CHECK-NEXT:    i32 0, label [[WHILE_BODY_BACKEDGE]]
+// CHECK-NEXT:    i32 1, label [[RETURN:%.*]]
+// CHECK-NEXT:    i32 4, label [[RETURN_SINK_SPLIT]]
+// CHECK-NEXT:    i32 3, label [[WHILE_BODY_BACKEDGE]]
+// CHECK-NEXT:    i32 2, label [[IMPOSSIBLE:%.*]]
+// CHECK-NEXT:    ]
+// CHECK:       return.sink.split:
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
+// 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:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 3
+// CHECK-EH-03-NEXT:    br label [[WHILE_BODY:%.*]]
+// CHECK-EH-03:       impossible:
+// CHECK-EH-03-NEXT:    br i1 [[CMP]], label [[RETURN_SINK_SPLIT:%.*]], label [[WHILE_BODY_BACKEDGE:%.*]]
+// CHECK-EH-03:       while.body.backedge:
+// CHECK-EH-03-NEXT:    br label [[WHILE_BODY]], !llvm.loop [[LOOP3:![0-9]+]]
+// CHECK-EH-03:       while.body:
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-03-NEXT:    switch i32 [[I]], label [[IF_END20:%.*]] [
+// CHECK-EH-03-NEXT:    i32 0, label [[CLEANUP:%.*]]
+// CHECK-EH-03-NEXT:    i32 1, label [[IF_THEN7:%.*]]
+// CHECK-EH-03-NEXT:    i32 2, label [[IF_THEN10:%.*]]
+// CHECK-EH-03-NEXT:    i32 3, label [[IF_THEN13:%.*]]
+// CHECK-EH-03-NEXT:    i32 4, label [[IF_THEN16:%.*]]
+// CHECK-EH-03-NEXT:    i32 5, label [[CLEANUP]]
+// CHECK-EH-03-NEXT:    ]
+// CHECK-EH-03:       if.then7:
+// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-03:       if.then10:
+// CHECK-EH-03-NEXT:    br label [[CLEANUP]], !llvm.loop [[LOOP3]]
+// CHECK-EH-03:       if.then13:
+// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-03:       if.then16:
+// CHECK-EH-03-NEXT:    call void @exit(i32 noundef 1) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[IF_END20]]
+// CHECK-EH-03:       if.end20:
+// CHECK-EH-03-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-03:       cleanup:
+// CHECK-EH-03-NEXT:    [[NRVO_0:%.*]] = phi i1 [ false, [[IF_THEN7]] ], [ false, [[IF_THEN10]] ], [ false, [[IF_THEN13]] ], [ false, [[IF_END20]] ], [ true, [[WHILE_BODY]] ], [ true, [[WHILE_BODY]] ]
+// CHECK-EH-03-NEXT:    [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ 4, [[IF_THEN7]] ], [ 3, [[IF_THEN10]] ], [ 2, [[IF_THEN13]] ], [ 0, [[IF_END20]] ], [ 1, [[WHILE_BODY]] ], [ 1, [[WHILE_BODY]] ]
+// CHECK-EH-03-NEXT:    br i1 [[NRVO_0]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
+// CHECK-EH-03:       nrvo.unused:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* 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:    switch i32 [[CLEANUP_DEST_SLOT_0]], label [[UNREACHABLE:%.*]] [
+// CHECK-EH-03-NEXT:    i32 0, label [[WHILE_BODY_BACKEDGE]]
+// CHECK-EH-03-NEXT:    i32 1, label [[RETURN:%.*]]
+// CHECK-EH-03-NEXT:    i32 4, label [[RETURN_SINK_SPLIT]]
+// CHECK-EH-03-NEXT:    i32 3, label [[WHILE_BODY_BACKEDGE]]
+// CHECK-EH-03-NEXT:    i32 2, label [[IMPOSSIBLE:%.*]]
+// CHECK-EH-03-NEXT:    ]
+// CHECK-EH-03:       return.sink.split:
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* 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:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 3
+// CHECK-EH-11-NEXT:    br label [[WHILE_BODY:%.*]]
+// CHECK-EH-11:       impossible:
+// CHECK-EH-11-NEXT:    br i1 [[CMP]], label [[RETURN_SINK_SPLIT:%.*]], label [[WHILE_BODY_BACKEDGE:%.*]]
+// CHECK-EH-11:       while.body.backedge:
+// CHECK-EH-11-NEXT:    br label [[WHILE_BODY]], !llvm.loop [[LOOP3:![0-9]+]]
+// CHECK-EH-11:       while.body:
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-11-NEXT:    switch i32 [[I]], label [[IF_END20:%.*]] [
+// CHECK-EH-11-NEXT:    i32 0, label [[CLEANUP:%.*]]
+// CHECK-EH-11-NEXT:    i32 1, label [[IF_THEN7:%.*]]
+// CHECK-EH-11-NEXT:    i32 2, label [[IF_THEN10:%.*]]
+// CHECK-EH-11-NEXT:    i32 3, label [[IF_THEN13:%.*]]
+// CHECK-EH-11-NEXT:    i32 4, label [[IF_THEN16:%.*]]
+// CHECK-EH-11-NEXT:    i32 5, label [[CLEANUP]]
+// CHECK-EH-11-NEXT:    ]
+// CHECK-EH-11:       if.then7:
+// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-11:       if.then10:
+// CHECK-EH-11-NEXT:    br label [[CLEANUP]], !llvm.loop [[LOOP3]]
+// CHECK-EH-11:       if.then13:
+// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-11:       if.then16:
+// CHECK-EH-11-NEXT:    call void @exit(i32 noundef 1) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[IF_END20]]
+// CHECK-EH-11:       if.end20:
+// CHECK-EH-11-NEXT:    br label [[CLEANUP]]
+// CHECK-EH-11:       cleanup:
+// CHECK-EH-11-NEXT:    [[NRVO_0:%.*]] = phi i1 [ false, [[IF_THEN7]] ], [ false, [[IF_THEN10]] ], [ false, [[IF_THEN13]] ], [ false, [[IF_END20]] ], [ true, [[WHILE_BODY]] ], [ true, [[WHILE_BODY]] ]
+// CHECK-EH-11-NEXT:    [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ 4, [[IF_THEN7]] ], [ 3, [[IF_THEN10]] ], [ 2, [[IF_THEN13]] ], [ 0, [[IF_END20]] ], [ 1, [[WHILE_BODY]] ], [ 1, [[WHILE_BODY]] ]
+// CHECK-EH-11-NEXT:    br i1 [[NRVO_0]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]]
+// CHECK-EH-11:       nrvo.unused:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[NRVO_SKIPDTOR]]
+// CHECK-EH-11:       nrvo.skipdtor:
+// CHECK-EH-11-NEXT:    switch i32 [[CLEANUP_DEST_SLOT_0]], label [[UNREACHABLE:%.*]] [
+// CHECK-EH-11-NEXT:    i32 0, label [[WHILE_BODY_BACKEDGE]]
+// CHECK-EH-11-NEXT:    i32 1, label [[RETURN:%.*]]
+// CHECK-EH-11-NEXT:    i32 4, label [[RETURN_SINK_SPLIT]]
+// CHECK-EH-11-NEXT:    i32 3, label [[WHILE_BODY_BACKEDGE]]
+// CHECK-EH-11-NEXT:    i32 2, label [[IMPOSSIBLE:%.*]]
+// CHECK-EH-11-NEXT:    ]
+// CHECK-EH-11:       return.sink.split:
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* 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:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-NEXT:    [[Z:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 0
+// CHECK-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[NRVO_UNUSED:%.*]]
+// CHECK:       nrvo.unused:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR5]]
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[I]], 1
+// CHECK-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[CLEANUP_CONT7_CRITEDGE:%.*]]
+// CHECK:       if.then2:
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[RETURN]]
+// CHECK:       cleanup.cont7.critedge:
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Z]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP1]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[RETURN]]
+// CHECK:       return:
+// CHECK-NEXT:    ret void
+//
+// CHECK-EH-03-LABEL: @_Z6test18i(
+// CHECK-EH-03-NEXT:  entry:
+// CHECK-EH-03-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-03-NEXT:    [[Z:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-03-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 0
+// CHECK-EH-03-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[NRVO_UNUSED:%.*]]
+// CHECK-EH-03:       nrvo.unused:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]])
+// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[I]], 1
+// CHECK-EH-03-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[CLEANUP_CONT8_CRITEDGE:%.*]]
+// CHECK-EH-03:       if.then2:
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    to label [[CLEANUP4:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-03:       lpad:
+// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT5:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK-EH-03:       cleanup4:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[RETURN]]
+// CHECK-EH-03:       cleanup.cont8.critedge:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Z]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT10:%.*]] unwind label [[LPAD9:%.*]]
+// CHECK-EH-03:       invoke.cont10:
+// CHECK-EH-03-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[RETURN]]
+// CHECK-EH-03:       invoke.cont5:
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[EH_RESUME:%.*]]
+// CHECK-EH-03:       lpad9:
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
+// CHECK-EH-03-NEXT:    to label [[INVOKE_CONT12:%.*]] unwind label [[TERMINATE_LPAD]]
+// CHECK-EH-03:       invoke.cont12:
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// 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:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP3]], [[INVOKE_CONT12]] ], [ [[TMP1]], [[INVOKE_CONT5]] ]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[DOTPN]]
+// CHECK-EH-03:       terminate.lpad:
+// CHECK-EH-03-NEXT:    [[TMP4:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    catch i8* null
+// CHECK-EH-03-NEXT:    [[TMP5:%.*]] = extractvalue { i8*, i32 } [[TMP4]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP5]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    unreachable
+//
+// CHECK-EH-11-LABEL: @_Z6test18i(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    [[Z:%.*]] = alloca [[CLASS_X]], align 1
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-11-NEXT:    [[CMP:%.*]] = icmp eq i32 [[I:%.*]], 0
+// CHECK-EH-11-NEXT:    br i1 [[CMP]], label [[RETURN:%.*]], label [[NRVO_UNUSED:%.*]]
+// CHECK-EH-11:       nrvo.unused:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-11-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[I]], 1
+// CHECK-EH-11-NEXT:    br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[CLEANUP_CONT7_CRITEDGE:%.*]]
+// CHECK-EH-11:       if.then2:
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-11-NEXT:    to label [[CLEANUP4:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[EH_RESUME:%.*]]
+// CHECK-EH-11:       cleanup4:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[RETURN]]
+// CHECK-EH-11:       cleanup.cont7.critedge:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Z]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Z]])
+// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT9:%.*]] unwind label [[LPAD8:%.*]]
+// CHECK-EH-11:       invoke.cont9:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[RETURN]]
+// CHECK-EH-11:       lpad8:
+// CHECK-EH-11-NEXT:    [[TMP3:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Z]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]]
+// 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:    [[DOTPN:%.*]] = phi { i8*, i32 } [ [[TMP3]], [[LPAD8]] ], [ [[TMP1]], [[LPAD]] ]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[DOTPN]]
+//
+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:    [[L:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[L]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[L]])
+// CHECK-EH-11-NEXT:    to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-EH-11:       invoke.cont:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[L]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    ret void
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
+//
+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:    [[X_I2:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    [[X_I:%.*]] = alloca [[CLASS_X]], align 1
+// 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:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X_I]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]], !noalias !6
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X_I]]), !noalias !6
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X_I]])
+// CHECK-EH-11-NEXT:    to label [[_Z6TEST20ILB1EE1XV_EXIT:%.*]] unwind label [[LPAD_I:%.*]]
+// CHECK-EH-11:       common.resume:
+// CHECK-EH-11-NEXT:    [[COMMON_RESUME_OP:%.*]] = phi { i8*, i32 } [ [[TMP1:%.*]], [[LPAD_I]] ], [ [[TMP3:%.*]], [[LPAD_I3:%.*]] ]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[COMMON_RESUME_OP]]
+// CHECK-EH-11:       lpad.i:
+// CHECK-EH-11-NEXT:    [[TMP1]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X_I]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]], !noalias !6
+// CHECK-EH-11-NEXT:    br label [[COMMON_RESUME:%.*]]
+// CHECK-EH-11:       _Z6test20ILb1EE1Xv.exit:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X_I]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]], !noalias !6
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X_I2]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]], !noalias !9
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X_I2]]), !noalias !9
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED1]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X_I2]])
+// CHECK-EH-11-NEXT:    to label [[_Z6TEST20ILB0EE1XV_EXIT:%.*]] unwind label [[LPAD_I3]]
+// CHECK-EH-11:       lpad.i3:
+// CHECK-EH-11-NEXT:    [[TMP3]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X_I2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]], !noalias !9
+// CHECK-EH-11-NEXT:    br label [[COMMON_RESUME]]
+// CHECK-EH-11:       _Z6test20ILb0EE1Xv.exit:
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X_I2]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP2]]) #[[ATTR7]], !noalias !9
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED1]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    ret void
+//
+void test20instantiate() {
+  test20<true>();
+  test20<false>();
+}
+#endif
+
+// CHECK-LABEL: @_Z6test21v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
+// CHECK-NEXT:    ret void
+//
+// CHECK-EH-LABEL: @_Z6test21v(
+// CHECK-EH-NEXT:  entry:
+// CHECK-EH-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-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:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1ERVKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    ret void
+//
+// CHECK-EH-03-LABEL: @_Z6test22v(
+// CHECK-EH-03-NEXT:  entry:
+// CHECK-EH-03-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERVKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* 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(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    ret void
+// CHECK-EH-03:       lpad:
+// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* 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:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
+// CHECK-EH-03:       terminate.lpad:
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    catch i8* null
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    unreachable
+//
+// CHECK-EH-11-LABEL: @_Z6test22v(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[X]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]])
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERVKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]], %class.X* 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(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    ret void
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
+//
+X test22() { // http://wg21.link/p2025r2#ex-19
+  volatile X x;
+  return x; // NRVO is impossible
+}
+
+// CHECK-LABEL: @_Z6test23b(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK:       if.then:
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]]) #[[ATTR5]]
+// CHECK-NEXT:    br label [[RETURN:%.*]]
+// CHECK:       if.end:
+// CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XC1ERVKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR5]]
+// CHECK-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR5]]
+// 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:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-03-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-03:       if.then:
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-03-NEXT:    br label [[RETURN:%.*]]
+// CHECK-EH-03:       if.end:
+// CHECK-EH-03-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XC1ERVKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* 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(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-03-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    br label [[RETURN]]
+// CHECK-EH-03:       lpad:
+// CHECK-EH-03-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    cleanup
+// CHECK-EH-03-NEXT:    invoke void @_ZN1XD1Ev(%class.X* 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:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-03-NEXT:    resume { i8*, i32 } [[TMP1]]
+// CHECK-EH-03:       return:
+// CHECK-EH-03-NEXT:    ret void
+// CHECK-EH-03:       terminate.lpad:
+// CHECK-EH-03-NEXT:    [[TMP2:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-03-NEXT:    catch i8* null
+// CHECK-EH-03-NEXT:    [[TMP3:%.*]] = extractvalue { i8*, i32 } [[TMP2]], 0
+// CHECK-EH-03-NEXT:    call void @__clang_call_terminate(i8* [[TMP3]]) #[[ATTR8]]
+// CHECK-EH-03-NEXT:    unreachable
+//
+// CHECK-EH-11-LABEL: @_Z6test23b(
+// CHECK-EH-11-NEXT:  entry:
+// CHECK-EH-11-NEXT:    [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1
+// CHECK-EH-11-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+// CHECK-EH-11:       if.then:
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-11-NEXT:    br label [[RETURN:%.*]]
+// CHECK-EH-11:       if.end:
+// CHECK-EH-11-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[CLASS_X]], %class.X* [[Y]], i32 0, i32 0
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]])
+// CHECK-EH-11-NEXT:    invoke void @_ZN1XC1ERVKS_(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], %class.X* 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(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    br label [[RETURN]]
+// CHECK-EH-11:       lpad:
+// CHECK-EH-11-NEXT:    [[TMP1:%.*]] = landingpad { i8*, i32 }
+// CHECK-EH-11-NEXT:    cleanup
+// CHECK-EH-11-NEXT:    call void @_ZN1XD1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[TMP0]]) #[[ATTR7]]
+// CHECK-EH-11-NEXT:    resume { i8*, i32 } [[TMP1]]
+// CHECK-EH-11:       return:
+// CHECK-EH-11-NEXT:    ret void
+//
+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-LABEL: @_Z6test24v(
+// CHECK-EH-NEXT:  entry:
+// CHECK-EH-NEXT:    call void @_ZN1XC1Ev(%class.X* noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT:%.*]])
+// CHECK-EH-NEXT:    ret void
+//
+X test24() { // http://wg21.link/p2025r2#ex-20
+  X x;
+  if (&x == &OuterX)
+    throw 0;
+  return x; // NRVO happens
+}
+#endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to