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

Thanks! Yes I should've write comments that are understandable not only for me 
=)
I added comments to the existing tests as well.
Though NRVO attribute is bound to the variable, I'm also more comfortable to 
place comments in the "return" lines, as it is looks somewhat more clear.


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]+]]
@@ -32,7 +36,7 @@
 X test0() {
   X x;
 
-  return x;
+  return x; // NRVO happens
 }
 
 // CHECK-LABEL: @_Z5test1b(
@@ -48,8 +52,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 +159,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(
@@ -245,11 +247,10 @@
 X test3(bool B) {
   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 +292,7 @@
   {
     X x;
     if (B)
-      return x;
+      return x; // NRVO happens
   }
   exit(1);
 }
@@ -411,7 +412,7 @@
   try {
     may_throw();
   } catch (X x) {
-    return x;
+    return x; // FIXME: NRVO could happen, but doesn't
   }
 }
 #endif
@@ -476,7 +477,7 @@
 //
 X test6() {
   X a __attribute__((aligned(8)));
-  return a;
+  return a; // NRVO is impossible
 }
 
 // CHECK-LABEL: @_Z5test7b(
@@ -492,7 +493,7 @@
 X test7(bool b) {
   if (b) {
     X x;
-    return x;
+    return x; // NRVO happens
   }
   return X();
 }
@@ -510,10 +511,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 +537,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) {
+  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) {
+  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) {
+  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) {
+  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) {
+  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) {
+  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() {
+  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) {
+  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) {
+  {
+    {
+      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() {
+  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() {
+  X x;
+  if constexpr (B) {
+    if (false)
+      return X();
+  }
+  return x; // FIXME: NRVO could happen if 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() {
+  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() {
+  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) {
+  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() {
+  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