1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 2 // RUN: %clang_cc1 -triple i386-unknown-unknown -Wno-error=return-type -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s 3 // RUN: %clang_cc1 -triple i386-unknown-unknown -Wno-error=return-type -emit-llvm -fcxx-exceptions -fexceptions -disable-llvm-passes -std=c++03 -o - %s | FileCheck --check-prefixes=CHECK-EH-03 %s 4 // RUN: %clang_cc1 -triple i386-unknown-unknown -Wno-error=return-type -emit-llvm -fcxx-exceptions -fexceptions -disable-llvm-passes -std=c++11 -DCXX11 -o - %s | FileCheck --check-prefixes=CHECK-EH-11 %s 5 6 // Test code generation for the named return value optimization. 7 class X { 8 public: 9 X(); 10 X(const X&); 11 X(const volatile X &); 12 ~X(); 13 }; 14 15 template<typename T> struct Y { 16 Y(); 17 static Y f() { 18 Y y; 19 return y; 20 } 21 }; 22 23 void ConsumeX(X x); 24 extern X OuterX; 25 26 // CHECK-LABEL: @_Z5test0v( 27 // CHECK-NEXT: entry: 28 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 29 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 30 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 31 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 32 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 33 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 34 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 35 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 36 // CHECK: nrvo.unused: 37 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4:[0-9]+]] 38 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 39 // CHECK: nrvo.skipdtor: 40 // CHECK-NEXT: ret void 41 // 42 // CHECK-EH-03-LABEL: @_Z5test0v( 43 // CHECK-EH-03-NEXT: entry: 44 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 45 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 46 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 47 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 48 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 49 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 50 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 51 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 52 // CHECK-EH-03: nrvo.unused: 53 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 54 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 55 // CHECK-EH-03: nrvo.skipdtor: 56 // CHECK-EH-03-NEXT: ret void 57 // 58 // CHECK-EH-11-LABEL: @_Z5test0v( 59 // CHECK-EH-11-NEXT: entry: 60 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 61 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 62 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 63 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 64 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 65 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 66 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 67 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 68 // CHECK-EH-11: nrvo.unused: 69 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6:[0-9]+]] 70 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 71 // CHECK-EH-11: nrvo.skipdtor: 72 // CHECK-EH-11-NEXT: ret void 73 // 74 X test0() { // http://wg21.link/p2025r2#ex-2 75 X x; 76 return x; // NRVO happens 77 } 78 79 // CHECK-LABEL: @_Z5test1b( 80 // CHECK-NEXT: entry: 81 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 82 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 83 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 84 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 85 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 86 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 87 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 88 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 89 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 90 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 91 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 92 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 93 // CHECK: if.then: 94 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 95 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 96 // CHECK-NEXT: br label [[CLEANUP:%.*]] 97 // CHECK: if.end: 98 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 99 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 100 // CHECK-NEXT: br label [[CLEANUP]] 101 // CHECK: cleanup: 102 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 103 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 104 // CHECK: nrvo.unused: 105 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 106 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 107 // CHECK: nrvo.skipdtor: 108 // CHECK-NEXT: ret void 109 // 110 // CHECK-EH-03-LABEL: @_Z5test1b( 111 // CHECK-EH-03-NEXT: entry: 112 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 113 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 114 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 115 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 116 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 117 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 118 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 119 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 120 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 121 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 122 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 123 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 124 // CHECK-EH-03: if.then: 125 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 126 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 127 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 128 // CHECK-EH-03: if.end: 129 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 130 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 131 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 132 // CHECK-EH-03: cleanup: 133 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 134 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 135 // CHECK-EH-03: nrvo.unused: 136 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 137 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 138 // CHECK-EH-03: nrvo.skipdtor: 139 // CHECK-EH-03-NEXT: ret void 140 // 141 // CHECK-EH-11-LABEL: @_Z5test1b( 142 // CHECK-EH-11-NEXT: entry: 143 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 144 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 145 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 146 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 147 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 148 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 149 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 150 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 151 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 152 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 153 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 154 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 155 // CHECK-EH-11: if.then: 156 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 157 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 158 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 159 // CHECK-EH-11: if.end: 160 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 161 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 162 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 163 // CHECK-EH-11: cleanup: 164 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 165 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 166 // CHECK-EH-11: nrvo.unused: 167 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 168 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 169 // CHECK-EH-11: nrvo.skipdtor: 170 // CHECK-EH-11-NEXT: ret void 171 // 172 X test1(bool B) { 173 X x; 174 if (B) 175 return (x); // NRVO happens 176 return x; // NRVO happens 177 } 178 179 // CHECK-LABEL: @_Z5test2b( 180 // CHECK-NEXT: entry: 181 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 182 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 183 // CHECK-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 184 // CHECK-NEXT: [[Y:%.*]] = alloca [[CLASS_X]], align 1 185 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 186 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 187 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 188 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 189 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 190 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 191 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 192 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 193 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 194 // CHECK: if.then: 195 // CHECK-NEXT: call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 196 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 197 // CHECK-NEXT: br label [[CLEANUP:%.*]] 198 // CHECK: if.end: 199 // CHECK-NEXT: call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 200 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 201 // CHECK-NEXT: br label [[CLEANUP]] 202 // CHECK: cleanup: 203 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR4]] 204 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]] 205 // CHECK-NEXT: ret void 206 // 207 // CHECK-EH-03-LABEL: @_Z5test2b( 208 // CHECK-EH-03-NEXT: entry: 209 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 210 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 211 // CHECK-EH-03-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 212 // CHECK-EH-03-NEXT: [[Y:%.*]] = alloca [[CLASS_X]], align 1 213 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 214 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 215 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 216 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 217 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 218 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 219 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 220 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 221 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 222 // CHECK-EH-03: invoke.cont: 223 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 224 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 225 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 226 // CHECK-EH-03: if.then: 227 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 228 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]] 229 // CHECK-EH-03: invoke.cont2: 230 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 231 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 232 // CHECK-EH-03: lpad: 233 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 234 // CHECK-EH-03-NEXT: cleanup 235 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 236 // CHECK-EH-03-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 237 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 238 // CHECK-EH-03-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 239 // CHECK-EH-03-NEXT: br label [[EHCLEANUP:%.*]] 240 // CHECK-EH-03: lpad1: 241 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 } 242 // CHECK-EH-03-NEXT: cleanup 243 // CHECK-EH-03-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0 244 // CHECK-EH-03-NEXT: store ptr [[TMP5]], ptr [[EXN_SLOT]], align 4 245 // CHECK-EH-03-NEXT: [[TMP6:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 1 246 // CHECK-EH-03-NEXT: store i32 [[TMP6]], ptr [[EHSELECTOR_SLOT]], align 4 247 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 248 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT5:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 249 // CHECK-EH-03: if.end: 250 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 251 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD1]] 252 // CHECK-EH-03: invoke.cont3: 253 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 254 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 255 // CHECK-EH-03: cleanup: 256 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 257 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT4:%.*]] unwind label [[LPAD]] 258 // CHECK-EH-03: invoke.cont4: 259 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 260 // CHECK-EH-03-NEXT: ret void 261 // CHECK-EH-03: invoke.cont5: 262 // CHECK-EH-03-NEXT: br label [[EHCLEANUP]] 263 // CHECK-EH-03: ehcleanup: 264 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 265 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[TERMINATE_LPAD]] 266 // CHECK-EH-03: invoke.cont7: 267 // CHECK-EH-03-NEXT: br label [[EH_RESUME:%.*]] 268 // CHECK-EH-03: eh.resume: 269 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 270 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 271 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 272 // CHECK-EH-03-NEXT: [[LPAD_VAL8:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 273 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL8]] 274 // CHECK-EH-03: terminate.lpad: 275 // CHECK-EH-03-NEXT: [[TMP7:%.*]] = landingpad { ptr, i32 } 276 // CHECK-EH-03-NEXT: catch ptr null 277 // CHECK-EH-03-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP7]], 0 278 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP8]]) #[[ATTR6:[0-9]+]] 279 // CHECK-EH-03-NEXT: unreachable 280 // 281 // CHECK-EH-11-LABEL: @_Z5test2b( 282 // CHECK-EH-11-NEXT: entry: 283 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 284 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 285 // CHECK-EH-11-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 286 // CHECK-EH-11-NEXT: [[Y:%.*]] = alloca [[CLASS_X]], align 1 287 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 288 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 289 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 290 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 291 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 292 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 293 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 294 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 295 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 296 // CHECK-EH-11: invoke.cont: 297 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 298 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 299 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 300 // CHECK-EH-11: if.then: 301 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 302 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]] 303 // CHECK-EH-11: invoke.cont2: 304 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 305 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 306 // CHECK-EH-11: lpad: 307 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 308 // CHECK-EH-11-NEXT: cleanup 309 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 310 // CHECK-EH-11-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 311 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 312 // CHECK-EH-11-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 313 // CHECK-EH-11-NEXT: br label [[EHCLEANUP:%.*]] 314 // CHECK-EH-11: lpad1: 315 // CHECK-EH-11-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 } 316 // CHECK-EH-11-NEXT: cleanup 317 // CHECK-EH-11-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0 318 // CHECK-EH-11-NEXT: store ptr [[TMP5]], ptr [[EXN_SLOT]], align 4 319 // CHECK-EH-11-NEXT: [[TMP6:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 1 320 // CHECK-EH-11-NEXT: store i32 [[TMP6]], ptr [[EHSELECTOR_SLOT]], align 4 321 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR6]] 322 // CHECK-EH-11-NEXT: br label [[EHCLEANUP]] 323 // CHECK-EH-11: if.end: 324 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 325 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD1]] 326 // CHECK-EH-11: invoke.cont3: 327 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 328 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 329 // CHECK-EH-11: cleanup: 330 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR6]] 331 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 332 // CHECK-EH-11-NEXT: ret void 333 // CHECK-EH-11: ehcleanup: 334 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 335 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 336 // CHECK-EH-11: eh.resume: 337 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 338 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 339 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 340 // CHECK-EH-11-NEXT: [[LPAD_VAL5:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 341 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL5]] 342 // 343 X test2(bool B) { 344 X x; 345 X y; 346 if (B) 347 return y; // NRVO is impossible 348 return x; // NRVO is impossible 349 } 350 351 // CHECK-LABEL: @_Z5test3b( 352 // CHECK-NEXT: entry: 353 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 354 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 355 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 356 // CHECK-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 357 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 358 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 359 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 360 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 361 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 362 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 363 // CHECK: if.then: 364 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 365 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 366 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 367 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 368 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 369 // CHECK: nrvo.unused: 370 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 371 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 372 // CHECK: nrvo.skipdtor: 373 // CHECK-NEXT: br label [[RETURN:%.*]] 374 // CHECK: if.end: 375 // CHECK-NEXT: store i1 false, ptr [[NRVO1]], align 1 376 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 377 // CHECK-NEXT: store i1 true, ptr [[NRVO1]], align 1 378 // CHECK-NEXT: [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1 379 // CHECK-NEXT: br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]] 380 // CHECK: nrvo.unused3: 381 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 382 // CHECK-NEXT: br label [[NRVO_SKIPDTOR4]] 383 // CHECK: nrvo.skipdtor4: 384 // CHECK-NEXT: br label [[RETURN]] 385 // CHECK: return: 386 // CHECK-NEXT: ret void 387 // 388 // CHECK-EH-03-LABEL: @_Z5test3b( 389 // CHECK-EH-03-NEXT: entry: 390 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 391 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 392 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 393 // CHECK-EH-03-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 394 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 395 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 396 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 397 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 398 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 399 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 400 // CHECK-EH-03: if.then: 401 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 402 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 403 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 404 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 405 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 406 // CHECK-EH-03: nrvo.unused: 407 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 408 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 409 // CHECK-EH-03: nrvo.skipdtor: 410 // CHECK-EH-03-NEXT: br label [[RETURN:%.*]] 411 // CHECK-EH-03: if.end: 412 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO1]], align 1 413 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 414 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO1]], align 1 415 // CHECK-EH-03-NEXT: [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1 416 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]] 417 // CHECK-EH-03: nrvo.unused3: 418 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 419 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR4]] 420 // CHECK-EH-03: nrvo.skipdtor4: 421 // CHECK-EH-03-NEXT: br label [[RETURN]] 422 // CHECK-EH-03: return: 423 // CHECK-EH-03-NEXT: ret void 424 // 425 // CHECK-EH-11-LABEL: @_Z5test3b( 426 // CHECK-EH-11-NEXT: entry: 427 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 428 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 429 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 430 // CHECK-EH-11-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 431 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 432 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 433 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 434 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 435 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 436 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 437 // CHECK-EH-11: if.then: 438 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 439 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 440 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 441 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 442 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 443 // CHECK-EH-11: nrvo.unused: 444 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 445 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 446 // CHECK-EH-11: nrvo.skipdtor: 447 // CHECK-EH-11-NEXT: br label [[RETURN:%.*]] 448 // CHECK-EH-11: if.end: 449 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO1]], align 1 450 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 451 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO1]], align 1 452 // CHECK-EH-11-NEXT: [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1 453 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]] 454 // CHECK-EH-11: nrvo.unused3: 455 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 456 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR4]] 457 // CHECK-EH-11: nrvo.skipdtor4: 458 // CHECK-EH-11-NEXT: br label [[RETURN]] 459 // CHECK-EH-11: return: 460 // CHECK-EH-11-NEXT: ret void 461 // 462 X test3(bool B) { // http://wg21.link/p2025r2#ex-4 463 if (B) { 464 X y; 465 return y; // NRVO happens 466 } 467 X x; 468 return x; // FIXME: NRVO could happen, but doesn't 469 } 470 471 extern "C" void exit(int) throw(); 472 473 // CHECK-LABEL: @_Z5test4b( 474 // CHECK-NEXT: entry: 475 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 476 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 477 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 478 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 479 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 480 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 481 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 482 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 483 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 484 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 485 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 486 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 487 // CHECK: if.then: 488 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 489 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 490 // CHECK-NEXT: br label [[CLEANUP:%.*]] 491 // CHECK: if.end: 492 // CHECK-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 493 // CHECK-NEXT: br label [[CLEANUP]] 494 // CHECK: cleanup: 495 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 496 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 497 // CHECK: nrvo.unused: 498 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 499 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 500 // CHECK: nrvo.skipdtor: 501 // CHECK-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 502 // CHECK-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 503 // CHECK-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 504 // CHECK-NEXT: i32 1, label [[RETURN:%.*]] 505 // CHECK-NEXT: ] 506 // CHECK: cleanup.cont: 507 // CHECK-NEXT: call void @exit(i32 noundef 1) #[[ATTR4]] 508 // CHECK-NEXT: call void @llvm.trap() 509 // CHECK-NEXT: unreachable 510 // CHECK: return: 511 // CHECK-NEXT: ret void 512 // CHECK: unreachable: 513 // CHECK-NEXT: unreachable 514 // 515 // CHECK-EH-03-LABEL: @_Z5test4b( 516 // CHECK-EH-03-NEXT: entry: 517 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 518 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 519 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 520 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 521 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 522 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 523 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 524 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 525 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 526 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 527 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 528 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 529 // CHECK-EH-03: if.then: 530 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 531 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 532 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 533 // CHECK-EH-03: if.end: 534 // CHECK-EH-03-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 535 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 536 // CHECK-EH-03: cleanup: 537 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 538 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 539 // CHECK-EH-03: nrvo.unused: 540 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 541 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 542 // CHECK-EH-03: nrvo.skipdtor: 543 // CHECK-EH-03-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 544 // CHECK-EH-03-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 545 // CHECK-EH-03-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 546 // CHECK-EH-03-NEXT: i32 1, label [[RETURN:%.*]] 547 // CHECK-EH-03-NEXT: ] 548 // CHECK-EH-03: cleanup.cont: 549 // CHECK-EH-03-NEXT: call void @exit(i32 noundef 1) #[[ATTR7:[0-9]+]] 550 // CHECK-EH-03-NEXT: call void @llvm.trap() 551 // CHECK-EH-03-NEXT: unreachable 552 // CHECK-EH-03: return: 553 // CHECK-EH-03-NEXT: ret void 554 // CHECK-EH-03: unreachable: 555 // CHECK-EH-03-NEXT: unreachable 556 // 557 // CHECK-EH-11-LABEL: @_Z5test4b( 558 // CHECK-EH-11-NEXT: entry: 559 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 560 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 561 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 562 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 563 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 564 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 565 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 566 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 567 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 568 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 569 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 570 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 571 // CHECK-EH-11: if.then: 572 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 573 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 574 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 575 // CHECK-EH-11: if.end: 576 // CHECK-EH-11-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 577 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 578 // CHECK-EH-11: cleanup: 579 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 580 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 581 // CHECK-EH-11: nrvo.unused: 582 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 583 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 584 // CHECK-EH-11: nrvo.skipdtor: 585 // CHECK-EH-11-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 586 // CHECK-EH-11-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 587 // CHECK-EH-11-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 588 // CHECK-EH-11-NEXT: i32 1, label [[RETURN:%.*]] 589 // CHECK-EH-11-NEXT: ] 590 // CHECK-EH-11: cleanup.cont: 591 // CHECK-EH-11-NEXT: call void @exit(i32 noundef 1) #[[ATTR6]] 592 // CHECK-EH-11-NEXT: call void @llvm.trap() 593 // CHECK-EH-11-NEXT: unreachable 594 // CHECK-EH-11: return: 595 // CHECK-EH-11-NEXT: ret void 596 // CHECK-EH-11: unreachable: 597 // CHECK-EH-11-NEXT: unreachable 598 // 599 X test4(bool B) { 600 { 601 X x; 602 if (B) 603 return x; // NRVO happens 604 } 605 exit(1); 606 } 607 608 #ifdef __EXCEPTIONS 609 void may_throw(); 610 // CHECK-EH-03-LABEL: @_Z5test5v( 611 // CHECK-EH-03-NEXT: entry: 612 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 613 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 614 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 615 // CHECK-EH-03-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 616 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 617 // CHECK-EH-03-NEXT: invoke void @_Z9may_throwv() 618 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 619 // CHECK-EH-03: invoke.cont: 620 // CHECK-EH-03-NEXT: br label [[TRY_CONT:%.*]] 621 // CHECK-EH-03: lpad: 622 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 623 // CHECK-EH-03-NEXT: catch ptr @_ZTI1X 624 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 625 // CHECK-EH-03-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4 626 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 627 // CHECK-EH-03-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4 628 // CHECK-EH-03-NEXT: br label [[CATCH_DISPATCH:%.*]] 629 // CHECK-EH-03: catch.dispatch: 630 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 631 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTI1X) #[[ATTR7]] 632 // CHECK-EH-03-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]] 633 // CHECK-EH-03-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] 634 // CHECK-EH-03: catch: 635 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 636 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = call ptr @__cxa_get_exception_ptr(ptr [[EXN]]) #[[ATTR7]] 637 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[X]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP4]]) 638 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 639 // CHECK-EH-03: invoke.cont1: 640 // CHECK-EH-03-NEXT: [[TMP5:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR7]] 641 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 642 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD2:%.*]] 643 // CHECK-EH-03: invoke.cont3: 644 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 645 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT5:%.*]] unwind label [[LPAD4:%.*]] 646 // CHECK-EH-03: lpad2: 647 // CHECK-EH-03-NEXT: [[TMP6:%.*]] = landingpad { ptr, i32 } 648 // CHECK-EH-03-NEXT: cleanup 649 // CHECK-EH-03-NEXT: [[TMP7:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 0 650 // CHECK-EH-03-NEXT: store ptr [[TMP7]], ptr [[EXN_SLOT]], align 4 651 // CHECK-EH-03-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 1 652 // CHECK-EH-03-NEXT: store i32 [[TMP8]], ptr [[EHSELECTOR_SLOT]], align 4 653 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 654 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT6:%.*]] unwind label [[TERMINATE_LPAD]] 655 // CHECK-EH-03: invoke.cont5: 656 // CHECK-EH-03-NEXT: call void @__cxa_end_catch() 657 // CHECK-EH-03-NEXT: ret void 658 // CHECK-EH-03: lpad4: 659 // CHECK-EH-03-NEXT: [[TMP9:%.*]] = landingpad { ptr, i32 } 660 // CHECK-EH-03-NEXT: cleanup 661 // CHECK-EH-03-NEXT: [[TMP10:%.*]] = extractvalue { ptr, i32 } [[TMP9]], 0 662 // CHECK-EH-03-NEXT: store ptr [[TMP10]], ptr [[EXN_SLOT]], align 4 663 // CHECK-EH-03-NEXT: [[TMP11:%.*]] = extractvalue { ptr, i32 } [[TMP9]], 1 664 // CHECK-EH-03-NEXT: store i32 [[TMP11]], ptr [[EHSELECTOR_SLOT]], align 4 665 // CHECK-EH-03-NEXT: br label [[EHCLEANUP:%.*]] 666 // CHECK-EH-03: invoke.cont6: 667 // CHECK-EH-03-NEXT: br label [[EHCLEANUP]] 668 // CHECK-EH-03: ehcleanup: 669 // CHECK-EH-03-NEXT: invoke void @__cxa_end_catch() 670 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[TERMINATE_LPAD]] 671 // CHECK-EH-03: invoke.cont7: 672 // CHECK-EH-03-NEXT: br label [[EH_RESUME]] 673 // CHECK-EH-03: try.cont: 674 // CHECK-EH-03-NEXT: call void @llvm.trap() 675 // CHECK-EH-03-NEXT: unreachable 676 // CHECK-EH-03: eh.resume: 677 // CHECK-EH-03-NEXT: [[EXN8:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 678 // CHECK-EH-03-NEXT: [[SEL9:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 679 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN8]], 0 680 // CHECK-EH-03-NEXT: [[LPAD_VAL10:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL9]], 1 681 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL10]] 682 // CHECK-EH-03: terminate.lpad: 683 // CHECK-EH-03-NEXT: [[TMP12:%.*]] = landingpad { ptr, i32 } 684 // CHECK-EH-03-NEXT: catch ptr null 685 // CHECK-EH-03-NEXT: [[TMP13:%.*]] = extractvalue { ptr, i32 } [[TMP12]], 0 686 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP13]]) #[[ATTR6]] 687 // CHECK-EH-03-NEXT: unreachable 688 // 689 // CHECK-EH-11-LABEL: @_Z5test5v( 690 // CHECK-EH-11-NEXT: entry: 691 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 692 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 693 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 694 // CHECK-EH-11-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 695 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 696 // CHECK-EH-11-NEXT: invoke void @_Z9may_throwv() 697 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 698 // CHECK-EH-11: invoke.cont: 699 // CHECK-EH-11-NEXT: br label [[TRY_CONT:%.*]] 700 // CHECK-EH-11: lpad: 701 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 702 // CHECK-EH-11-NEXT: catch ptr @_ZTI1X 703 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 704 // CHECK-EH-11-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4 705 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 706 // CHECK-EH-11-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4 707 // CHECK-EH-11-NEXT: br label [[CATCH_DISPATCH:%.*]] 708 // CHECK-EH-11: catch.dispatch: 709 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 710 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTI1X) #[[ATTR6]] 711 // CHECK-EH-11-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[SEL]], [[TMP3]] 712 // CHECK-EH-11-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] 713 // CHECK-EH-11: catch: 714 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 715 // CHECK-EH-11-NEXT: [[TMP4:%.*]] = call ptr @__cxa_get_exception_ptr(ptr [[EXN]]) #[[ATTR6]] 716 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[X]], ptr noundef nonnull align 1 dereferenceable(1) [[TMP4]]) 717 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 718 // CHECK-EH-11: invoke.cont1: 719 // CHECK-EH-11-NEXT: [[TMP5:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]]) #[[ATTR6]] 720 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 721 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[LPAD2:%.*]] 722 // CHECK-EH-11: invoke.cont3: 723 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 724 // CHECK-EH-11-NEXT: call void @__cxa_end_catch() 725 // CHECK-EH-11-NEXT: ret void 726 // CHECK-EH-11: lpad2: 727 // CHECK-EH-11-NEXT: [[TMP6:%.*]] = landingpad { ptr, i32 } 728 // CHECK-EH-11-NEXT: cleanup 729 // CHECK-EH-11-NEXT: [[TMP7:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 0 730 // CHECK-EH-11-NEXT: store ptr [[TMP7]], ptr [[EXN_SLOT]], align 4 731 // CHECK-EH-11-NEXT: [[TMP8:%.*]] = extractvalue { ptr, i32 } [[TMP6]], 1 732 // CHECK-EH-11-NEXT: store i32 [[TMP8]], ptr [[EHSELECTOR_SLOT]], align 4 733 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 734 // CHECK-EH-11-NEXT: invoke void @__cxa_end_catch() 735 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT4:%.*]] unwind label [[TERMINATE_LPAD]] 736 // CHECK-EH-11: invoke.cont4: 737 // CHECK-EH-11-NEXT: br label [[EH_RESUME]] 738 // CHECK-EH-11: try.cont: 739 // CHECK-EH-11-NEXT: call void @llvm.trap() 740 // CHECK-EH-11-NEXT: unreachable 741 // CHECK-EH-11: eh.resume: 742 // CHECK-EH-11-NEXT: [[EXN5:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 743 // CHECK-EH-11-NEXT: [[SEL6:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 744 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN5]], 0 745 // CHECK-EH-11-NEXT: [[LPAD_VAL7:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL6]], 1 746 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL7]] 747 // CHECK-EH-11: terminate.lpad: 748 // CHECK-EH-11-NEXT: [[TMP9:%.*]] = landingpad { ptr, i32 } 749 // CHECK-EH-11-NEXT: catch ptr null 750 // CHECK-EH-11-NEXT: [[TMP10:%.*]] = extractvalue { ptr, i32 } [[TMP9]], 0 751 // CHECK-EH-11-NEXT: call void @__clang_call_terminate(ptr [[TMP10]]) #[[ATTR7:[0-9]+]] 752 // CHECK-EH-11-NEXT: unreachable 753 // 754 X test5() { // http://wg21.link/p2025r2#ex-14 755 try { 756 may_throw(); 757 } catch (X x) { 758 return x; // FIXME: NRVO could happen, but doesn't 759 } 760 } 761 #endif 762 763 // CHECK-LABEL: @_Z5test6v( 764 // CHECK-NEXT: entry: 765 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 766 // CHECK-NEXT: [[A:%.*]] = alloca [[CLASS_X:%.*]], align 8 767 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 768 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) 769 // CHECK-NEXT: call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[A]]) 770 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR4]] 771 // CHECK-NEXT: ret void 772 // 773 // CHECK-EH-03-LABEL: @_Z5test6v( 774 // CHECK-EH-03-NEXT: entry: 775 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 776 // CHECK-EH-03-NEXT: [[A:%.*]] = alloca [[CLASS_X:%.*]], align 8 777 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 778 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 779 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 780 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) 781 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[A]]) 782 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 783 // CHECK-EH-03: invoke.cont: 784 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) 785 // CHECK-EH-03-NEXT: ret void 786 // CHECK-EH-03: lpad: 787 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 788 // CHECK-EH-03-NEXT: cleanup 789 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 790 // CHECK-EH-03-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4 791 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 792 // CHECK-EH-03-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4 793 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) 794 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 795 // CHECK-EH-03: invoke.cont1: 796 // CHECK-EH-03-NEXT: br label [[EH_RESUME:%.*]] 797 // CHECK-EH-03: eh.resume: 798 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 799 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 800 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 801 // CHECK-EH-03-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 802 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL2]] 803 // CHECK-EH-03: terminate.lpad: 804 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = landingpad { ptr, i32 } 805 // CHECK-EH-03-NEXT: catch ptr null 806 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0 807 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP4]]) #[[ATTR6]] 808 // CHECK-EH-03-NEXT: unreachable 809 // 810 // CHECK-EH-11-LABEL: @_Z5test6v( 811 // CHECK-EH-11-NEXT: entry: 812 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 813 // CHECK-EH-11-NEXT: [[A:%.*]] = alloca [[CLASS_X:%.*]], align 8 814 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 815 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 816 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 817 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) 818 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[A]]) 819 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 820 // CHECK-EH-11: invoke.cont: 821 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR6]] 822 // CHECK-EH-11-NEXT: ret void 823 // CHECK-EH-11: lpad: 824 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 825 // CHECK-EH-11-NEXT: cleanup 826 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 827 // CHECK-EH-11-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4 828 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 829 // CHECK-EH-11-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4 830 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[A]]) #[[ATTR6]] 831 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 832 // CHECK-EH-11: eh.resume: 833 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 834 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 835 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 836 // CHECK-EH-11-NEXT: [[LPAD_VAL1:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 837 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL1]] 838 // 839 X test6() { 840 X a __attribute__((aligned(8))); 841 return a; // NRVO is impossible 842 } 843 844 // CHECK-LABEL: @_Z5test7b( 845 // CHECK-NEXT: entry: 846 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 847 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 848 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 849 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 850 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 851 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 852 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 853 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 854 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 855 // CHECK: if.then: 856 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 857 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 858 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 859 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 860 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 861 // CHECK: nrvo.unused: 862 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 863 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 864 // CHECK: nrvo.skipdtor: 865 // CHECK-NEXT: br label [[RETURN:%.*]] 866 // CHECK: if.end: 867 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 868 // CHECK-NEXT: br label [[RETURN]] 869 // CHECK: return: 870 // CHECK-NEXT: ret void 871 // 872 // CHECK-EH-03-LABEL: @_Z5test7b( 873 // CHECK-EH-03-NEXT: entry: 874 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 875 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 876 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 877 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 878 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 879 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 880 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 881 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 882 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 883 // CHECK-EH-03: if.then: 884 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 885 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 886 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 887 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 888 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 889 // CHECK-EH-03: nrvo.unused: 890 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 891 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 892 // CHECK-EH-03: nrvo.skipdtor: 893 // CHECK-EH-03-NEXT: br label [[RETURN:%.*]] 894 // CHECK-EH-03: if.end: 895 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 896 // CHECK-EH-03-NEXT: br label [[RETURN]] 897 // CHECK-EH-03: return: 898 // CHECK-EH-03-NEXT: ret void 899 // 900 // CHECK-EH-11-LABEL: @_Z5test7b( 901 // CHECK-EH-11-NEXT: entry: 902 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 903 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 904 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 905 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 906 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 907 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 908 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 909 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 910 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 911 // CHECK-EH-11: if.then: 912 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 913 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 914 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 915 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 916 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 917 // CHECK-EH-11: nrvo.unused: 918 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 919 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 920 // CHECK-EH-11: nrvo.skipdtor: 921 // CHECK-EH-11-NEXT: br label [[RETURN:%.*]] 922 // CHECK-EH-11: if.end: 923 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 924 // CHECK-EH-11-NEXT: br label [[RETURN]] 925 // CHECK-EH-11: return: 926 // CHECK-EH-11-NEXT: ret void 927 // 928 X test7(bool b) { 929 if (b) { 930 X x; 931 return x; // NRVO happens 932 } 933 return X(); 934 } 935 936 // CHECK-LABEL: @_Z5test8b( 937 // CHECK-NEXT: entry: 938 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 939 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 940 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 941 // CHECK-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 942 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 943 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 944 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 945 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 946 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 947 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 948 // CHECK: if.then: 949 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 950 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 951 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 952 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 953 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 954 // CHECK: nrvo.unused: 955 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 956 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 957 // CHECK: nrvo.skipdtor: 958 // CHECK-NEXT: br label [[RETURN:%.*]] 959 // CHECK: if.else: 960 // CHECK-NEXT: store i1 false, ptr [[NRVO1]], align 1 961 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 962 // CHECK-NEXT: store i1 true, ptr [[NRVO1]], align 1 963 // CHECK-NEXT: [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1 964 // CHECK-NEXT: br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]] 965 // CHECK: nrvo.unused3: 966 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 967 // CHECK-NEXT: br label [[NRVO_SKIPDTOR4]] 968 // CHECK: nrvo.skipdtor4: 969 // CHECK-NEXT: br label [[RETURN]] 970 // CHECK: return: 971 // CHECK-NEXT: ret void 972 // 973 // CHECK-EH-03-LABEL: @_Z5test8b( 974 // CHECK-EH-03-NEXT: entry: 975 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 976 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 977 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 978 // CHECK-EH-03-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 979 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 980 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 981 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 982 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 983 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 984 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 985 // CHECK-EH-03: if.then: 986 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 987 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 988 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 989 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 990 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 991 // CHECK-EH-03: nrvo.unused: 992 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 993 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 994 // CHECK-EH-03: nrvo.skipdtor: 995 // CHECK-EH-03-NEXT: br label [[RETURN:%.*]] 996 // CHECK-EH-03: if.else: 997 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO1]], align 1 998 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 999 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO1]], align 1 1000 // CHECK-EH-03-NEXT: [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1 1001 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]] 1002 // CHECK-EH-03: nrvo.unused3: 1003 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1004 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR4]] 1005 // CHECK-EH-03: nrvo.skipdtor4: 1006 // CHECK-EH-03-NEXT: br label [[RETURN]] 1007 // CHECK-EH-03: return: 1008 // CHECK-EH-03-NEXT: ret void 1009 // 1010 // CHECK-EH-11-LABEL: @_Z5test8b( 1011 // CHECK-EH-11-NEXT: entry: 1012 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1013 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1014 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1015 // CHECK-EH-11-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 1016 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1017 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1018 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1019 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1020 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1021 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1022 // CHECK-EH-11: if.then: 1023 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 1024 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1025 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 1026 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1027 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1028 // CHECK-EH-11: nrvo.unused: 1029 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 1030 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 1031 // CHECK-EH-11: nrvo.skipdtor: 1032 // CHECK-EH-11-NEXT: br label [[RETURN:%.*]] 1033 // CHECK-EH-11: if.else: 1034 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO1]], align 1 1035 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1036 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO1]], align 1 1037 // CHECK-EH-11-NEXT: [[NRVO_VAL2:%.*]] = load i1, ptr [[NRVO1]], align 1 1038 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL2]], label [[NRVO_SKIPDTOR4:%.*]], label [[NRVO_UNUSED3:%.*]] 1039 // CHECK-EH-11: nrvo.unused3: 1040 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 1041 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR4]] 1042 // CHECK-EH-11: nrvo.skipdtor4: 1043 // CHECK-EH-11-NEXT: br label [[RETURN]] 1044 // CHECK-EH-11: return: 1045 // CHECK-EH-11-NEXT: ret void 1046 // 1047 X test8(bool b) { 1048 if (b) { 1049 X x; 1050 return x; // NRVO happens 1051 } else { 1052 X y; 1053 return y; // NRVO happens 1054 } 1055 } 1056 1057 // CHECK-LABEL: @_Z5test9v( 1058 // CHECK-NEXT: entry: 1059 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1060 // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1 1061 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1062 // CHECK-NEXT: call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]]) 1063 // CHECK-NEXT: call void @llvm.trap() 1064 // CHECK-NEXT: unreachable 1065 // 1066 // CHECK-EH-03-LABEL: @_Z5test9v( 1067 // CHECK-EH-03-NEXT: entry: 1068 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1069 // CHECK-EH-03-NEXT: [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1 1070 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1071 // CHECK-EH-03-NEXT: call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]]) 1072 // CHECK-EH-03-NEXT: call void @llvm.trap() 1073 // CHECK-EH-03-NEXT: unreachable 1074 // 1075 // CHECK-EH-11-LABEL: @_Z5test9v( 1076 // CHECK-EH-11-NEXT: entry: 1077 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1078 // CHECK-EH-11-NEXT: [[TMP:%.*]] = alloca [[STRUCT_Y:%.*]], align 1 1079 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1080 // CHECK-EH-11-NEXT: call void @_ZN1YIiE1fEv(ptr dead_on_unwind writable sret([[STRUCT_Y]]) align 1 [[TMP]]) 1081 // CHECK-EH-11-NEXT: call void @llvm.trap() 1082 // CHECK-EH-11-NEXT: unreachable 1083 // 1084 Y<int> test9() { 1085 Y<int>::f(); 1086 } 1087 1088 // CHECK-LABEL: @_Z6test10b( 1089 // CHECK-NEXT: entry: 1090 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1091 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1092 // CHECK-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1093 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1094 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1095 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1096 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1097 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1098 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1099 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1100 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1101 // CHECK: if.then: 1102 // CHECK-NEXT: call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1103 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1104 // CHECK-NEXT: br label [[CLEANUP:%.*]] 1105 // CHECK: if.else: 1106 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1107 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1108 // CHECK-NEXT: br label [[CLEANUP]] 1109 // CHECK: cleanup: 1110 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]] 1111 // CHECK-NEXT: ret void 1112 // 1113 // CHECK-EH-03-LABEL: @_Z6test10b( 1114 // CHECK-EH-03-NEXT: entry: 1115 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1116 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1117 // CHECK-EH-03-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1118 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1119 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1120 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1121 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1122 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1123 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1124 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1125 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1126 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1127 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1128 // CHECK-EH-03: if.then: 1129 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1130 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1131 // CHECK-EH-03: invoke.cont: 1132 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1133 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 1134 // CHECK-EH-03: lpad: 1135 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1136 // CHECK-EH-03-NEXT: cleanup 1137 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1138 // CHECK-EH-03-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1139 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1140 // CHECK-EH-03-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1141 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1142 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 1143 // CHECK-EH-03: if.else: 1144 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1145 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]] 1146 // CHECK-EH-03: invoke.cont1: 1147 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1148 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 1149 // CHECK-EH-03: cleanup: 1150 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1151 // CHECK-EH-03-NEXT: ret void 1152 // CHECK-EH-03: invoke.cont2: 1153 // CHECK-EH-03-NEXT: br label [[EH_RESUME:%.*]] 1154 // CHECK-EH-03: eh.resume: 1155 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1156 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1157 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1158 // CHECK-EH-03-NEXT: [[LPAD_VAL3:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1159 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL3]] 1160 // CHECK-EH-03: terminate.lpad: 1161 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 } 1162 // CHECK-EH-03-NEXT: catch ptr null 1163 // CHECK-EH-03-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0 1164 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]] 1165 // CHECK-EH-03-NEXT: unreachable 1166 // 1167 // CHECK-EH-11-LABEL: @_Z6test10b( 1168 // CHECK-EH-11-NEXT: entry: 1169 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1170 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1171 // CHECK-EH-11-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1172 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1173 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1174 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1175 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1176 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1177 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1178 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1179 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1180 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1181 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 1182 // CHECK-EH-11: if.then: 1183 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1184 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1185 // CHECK-EH-11: invoke.cont: 1186 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1187 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 1188 // CHECK-EH-11: lpad: 1189 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1190 // CHECK-EH-11-NEXT: cleanup 1191 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1192 // CHECK-EH-11-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1193 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1194 // CHECK-EH-11-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1195 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1196 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 1197 // CHECK-EH-11: if.else: 1198 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1199 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]] 1200 // CHECK-EH-11: invoke.cont1: 1201 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1202 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 1203 // CHECK-EH-11: cleanup: 1204 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1205 // CHECK-EH-11-NEXT: ret void 1206 // CHECK-EH-11: eh.resume: 1207 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1208 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1209 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1210 // CHECK-EH-11-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1211 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL2]] 1212 // 1213 X test10(bool b) { // http://wg21.link/p2025r2#ex-3 1214 X x; 1215 if (b) 1216 return x; // NRVO is impossible 1217 else 1218 return X(); 1219 } 1220 1221 // CHECK-LABEL: @_Z6test11b( 1222 // CHECK-NEXT: entry: 1223 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1224 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1225 // CHECK-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1226 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1227 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1228 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1229 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1230 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1231 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1232 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1233 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1234 // CHECK: if.then: 1235 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1236 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1237 // CHECK-NEXT: br label [[CLEANUP:%.*]] 1238 // CHECK: if.end: 1239 // CHECK-NEXT: call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1240 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1241 // CHECK-NEXT: br label [[CLEANUP]] 1242 // CHECK: cleanup: 1243 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]] 1244 // CHECK-NEXT: ret void 1245 // 1246 // CHECK-EH-03-LABEL: @_Z6test11b( 1247 // CHECK-EH-03-NEXT: entry: 1248 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1249 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1250 // CHECK-EH-03-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1251 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1252 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1253 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1254 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1255 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1256 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1257 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1258 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1259 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1260 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1261 // CHECK-EH-03: if.then: 1262 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1263 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1264 // CHECK-EH-03: invoke.cont: 1265 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1266 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 1267 // CHECK-EH-03: lpad: 1268 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1269 // CHECK-EH-03-NEXT: cleanup 1270 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1271 // CHECK-EH-03-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1272 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1273 // CHECK-EH-03-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1274 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1275 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 1276 // CHECK-EH-03: if.end: 1277 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1278 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]] 1279 // CHECK-EH-03: invoke.cont1: 1280 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1281 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 1282 // CHECK-EH-03: cleanup: 1283 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1284 // CHECK-EH-03-NEXT: ret void 1285 // CHECK-EH-03: invoke.cont2: 1286 // CHECK-EH-03-NEXT: br label [[EH_RESUME:%.*]] 1287 // CHECK-EH-03: eh.resume: 1288 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1289 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1290 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1291 // CHECK-EH-03-NEXT: [[LPAD_VAL3:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1292 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL3]] 1293 // CHECK-EH-03: terminate.lpad: 1294 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 } 1295 // CHECK-EH-03-NEXT: catch ptr null 1296 // CHECK-EH-03-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0 1297 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]] 1298 // CHECK-EH-03-NEXT: unreachable 1299 // 1300 // CHECK-EH-11-LABEL: @_Z6test11b( 1301 // CHECK-EH-11-NEXT: entry: 1302 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1303 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1304 // CHECK-EH-11-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1305 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1306 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1307 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1308 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1309 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1310 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1311 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1312 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1313 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1314 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1315 // CHECK-EH-11: if.then: 1316 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1317 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1318 // CHECK-EH-11: invoke.cont: 1319 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1320 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 1321 // CHECK-EH-11: lpad: 1322 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1323 // CHECK-EH-11-NEXT: cleanup 1324 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1325 // CHECK-EH-11-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1326 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1327 // CHECK-EH-11-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1328 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1329 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 1330 // CHECK-EH-11: if.end: 1331 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1332 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]] 1333 // CHECK-EH-11: invoke.cont1: 1334 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1335 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 1336 // CHECK-EH-11: cleanup: 1337 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1338 // CHECK-EH-11-NEXT: ret void 1339 // CHECK-EH-11: eh.resume: 1340 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1341 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1342 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1343 // CHECK-EH-11-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1344 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL2]] 1345 // 1346 X test11(bool b) { // http://wg21.link/p2025r2#ex-5 1347 X x; 1348 if (b) 1349 return X(); 1350 return x; // NRVO is impossible 1351 } 1352 1353 // CHECK-LABEL: @_Z6test12b( 1354 // CHECK-NEXT: entry: 1355 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1356 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1357 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1358 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1359 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1360 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1361 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1362 // CHECK-NEXT: br label [[DO_BODY:%.*]] 1363 // CHECK: do.body: 1364 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 1365 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1366 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1367 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1368 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1369 // CHECK: if.then: 1370 // CHECK-NEXT: store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4 1371 // CHECK-NEXT: br label [[CLEANUP:%.*]] 1372 // CHECK: if.end: 1373 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 1374 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1375 // CHECK-NEXT: br label [[CLEANUP]] 1376 // CHECK: cleanup: 1377 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1378 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1379 // CHECK: nrvo.unused: 1380 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 1381 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 1382 // CHECK: nrvo.skipdtor: 1383 // CHECK-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 1384 // CHECK-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 1385 // CHECK-NEXT: i32 2, label [[DO_END:%.*]] 1386 // CHECK-NEXT: i32 1, label [[RETURN:%.*]] 1387 // CHECK-NEXT: ] 1388 // CHECK: do.end: 1389 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1390 // CHECK-NEXT: br label [[RETURN]] 1391 // CHECK: return: 1392 // CHECK-NEXT: ret void 1393 // CHECK: unreachable: 1394 // CHECK-NEXT: unreachable 1395 // 1396 // CHECK-EH-03-LABEL: @_Z6test12b( 1397 // CHECK-EH-03-NEXT: entry: 1398 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1399 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1400 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1401 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1402 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1403 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1404 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1405 // CHECK-EH-03-NEXT: br label [[DO_BODY:%.*]] 1406 // CHECK-EH-03: do.body: 1407 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 1408 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1409 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1410 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1411 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1412 // CHECK-EH-03: if.then: 1413 // CHECK-EH-03-NEXT: store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4 1414 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 1415 // CHECK-EH-03: if.end: 1416 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 1417 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1418 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 1419 // CHECK-EH-03: cleanup: 1420 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1421 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1422 // CHECK-EH-03: nrvo.unused: 1423 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1424 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 1425 // CHECK-EH-03: nrvo.skipdtor: 1426 // CHECK-EH-03-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 1427 // CHECK-EH-03-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 1428 // CHECK-EH-03-NEXT: i32 2, label [[DO_END:%.*]] 1429 // CHECK-EH-03-NEXT: i32 1, label [[RETURN:%.*]] 1430 // CHECK-EH-03-NEXT: ] 1431 // CHECK-EH-03: do.end: 1432 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1433 // CHECK-EH-03-NEXT: br label [[RETURN]] 1434 // CHECK-EH-03: return: 1435 // CHECK-EH-03-NEXT: ret void 1436 // CHECK-EH-03: unreachable: 1437 // CHECK-EH-03-NEXT: unreachable 1438 // 1439 // CHECK-EH-11-LABEL: @_Z6test12b( 1440 // CHECK-EH-11-NEXT: entry: 1441 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1442 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1443 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1444 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1445 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1446 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1447 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1448 // CHECK-EH-11-NEXT: br label [[DO_BODY:%.*]] 1449 // CHECK-EH-11: do.body: 1450 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 1451 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1452 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1453 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1454 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1455 // CHECK-EH-11: if.then: 1456 // CHECK-EH-11-NEXT: store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4 1457 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 1458 // CHECK-EH-11: if.end: 1459 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 1460 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1461 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 1462 // CHECK-EH-11: cleanup: 1463 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1464 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1465 // CHECK-EH-11: nrvo.unused: 1466 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 1467 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 1468 // CHECK-EH-11: nrvo.skipdtor: 1469 // CHECK-EH-11-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 1470 // CHECK-EH-11-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 1471 // CHECK-EH-11-NEXT: i32 2, label [[DO_END:%.*]] 1472 // CHECK-EH-11-NEXT: i32 1, label [[RETURN:%.*]] 1473 // CHECK-EH-11-NEXT: ] 1474 // CHECK-EH-11: do.end: 1475 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1476 // CHECK-EH-11-NEXT: br label [[RETURN]] 1477 // CHECK-EH-11: return: 1478 // CHECK-EH-11-NEXT: ret void 1479 // CHECK-EH-11: unreachable: 1480 // CHECK-EH-11-NEXT: unreachable 1481 // 1482 X test12(bool b) { // http://wg21.link/p2025r2#ex-6 1483 do { 1484 X x; 1485 if (b) 1486 break; 1487 return x; // NRVO happens 1488 } while (false); 1489 return X(); 1490 } 1491 1492 // CHECK-LABEL: @_Z6test13b( 1493 // CHECK-NEXT: entry: 1494 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1495 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1496 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1497 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1498 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1499 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1500 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1501 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1502 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1503 // CHECK: if.then: 1504 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1505 // CHECK-NEXT: br label [[RETURN:%.*]] 1506 // CHECK: if.end: 1507 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 1508 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1509 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 1510 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1511 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1512 // CHECK: nrvo.unused: 1513 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 1514 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 1515 // CHECK: nrvo.skipdtor: 1516 // CHECK-NEXT: br label [[RETURN]] 1517 // CHECK: return: 1518 // CHECK-NEXT: ret void 1519 // 1520 // CHECK-EH-03-LABEL: @_Z6test13b( 1521 // CHECK-EH-03-NEXT: entry: 1522 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1523 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1524 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1525 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1526 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1527 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1528 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1529 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1530 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1531 // CHECK-EH-03: if.then: 1532 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1533 // CHECK-EH-03-NEXT: br label [[RETURN:%.*]] 1534 // CHECK-EH-03: if.end: 1535 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 1536 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1537 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 1538 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1539 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1540 // CHECK-EH-03: nrvo.unused: 1541 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1542 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 1543 // CHECK-EH-03: nrvo.skipdtor: 1544 // CHECK-EH-03-NEXT: br label [[RETURN]] 1545 // CHECK-EH-03: return: 1546 // CHECK-EH-03-NEXT: ret void 1547 // 1548 // CHECK-EH-11-LABEL: @_Z6test13b( 1549 // CHECK-EH-11-NEXT: entry: 1550 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1551 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1552 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1553 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1554 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1555 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1556 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1557 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1558 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1559 // CHECK-EH-11: if.then: 1560 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1561 // CHECK-EH-11-NEXT: br label [[RETURN:%.*]] 1562 // CHECK-EH-11: if.end: 1563 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 1564 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1565 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 1566 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1567 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1568 // CHECK-EH-11: nrvo.unused: 1569 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 1570 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 1571 // CHECK-EH-11: nrvo.skipdtor: 1572 // CHECK-EH-11-NEXT: br label [[RETURN]] 1573 // CHECK-EH-11: return: 1574 // CHECK-EH-11-NEXT: ret void 1575 // 1576 X test13(bool b) { // http://wg21.link/p2025r2#ex-7 1577 if (b) 1578 return X(); 1579 X x; 1580 return x; // FIXME: NRVO could happen, but doesn't 1581 } 1582 1583 // CHECK-LABEL: @_Z6test14b( 1584 // CHECK-NEXT: entry: 1585 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1586 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1587 // CHECK-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1588 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1589 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1590 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1591 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1592 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1593 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1594 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1595 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1596 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1597 // CHECK: if.then: 1598 // CHECK-NEXT: call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1599 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1600 // CHECK-NEXT: br label [[CLEANUP:%.*]] 1601 // CHECK: if.end: 1602 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 1603 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1604 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 1605 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1606 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1607 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1608 // CHECK: nrvo.unused: 1609 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 1610 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 1611 // CHECK: nrvo.skipdtor: 1612 // CHECK-NEXT: br label [[CLEANUP]] 1613 // CHECK: cleanup: 1614 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]] 1615 // CHECK-NEXT: ret void 1616 // 1617 // CHECK-EH-03-LABEL: @_Z6test14b( 1618 // CHECK-EH-03-NEXT: entry: 1619 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1620 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1621 // CHECK-EH-03-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1622 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1623 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1624 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1625 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1626 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1627 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1628 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1629 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1630 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1631 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1632 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1633 // CHECK-EH-03: if.then: 1634 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1635 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1636 // CHECK-EH-03: invoke.cont: 1637 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1638 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 1639 // CHECK-EH-03: lpad: 1640 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1641 // CHECK-EH-03-NEXT: cleanup 1642 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1643 // CHECK-EH-03-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1644 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1645 // CHECK-EH-03-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1646 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1647 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 1648 // CHECK-EH-03: if.end: 1649 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 1650 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1651 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]] 1652 // CHECK-EH-03: invoke.cont1: 1653 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 1654 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1655 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1656 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1657 // CHECK-EH-03: nrvo.unused: 1658 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1659 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]] 1660 // CHECK-EH-03: invoke.cont2: 1661 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 1662 // CHECK-EH-03: nrvo.skipdtor: 1663 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 1664 // CHECK-EH-03: cleanup: 1665 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1666 // CHECK-EH-03-NEXT: ret void 1667 // CHECK-EH-03: invoke.cont3: 1668 // CHECK-EH-03-NEXT: br label [[EH_RESUME:%.*]] 1669 // CHECK-EH-03: eh.resume: 1670 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1671 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1672 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1673 // CHECK-EH-03-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1674 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL4]] 1675 // CHECK-EH-03: terminate.lpad: 1676 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 } 1677 // CHECK-EH-03-NEXT: catch ptr null 1678 // CHECK-EH-03-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0 1679 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]] 1680 // CHECK-EH-03-NEXT: unreachable 1681 // 1682 // CHECK-EH-11-LABEL: @_Z6test14b( 1683 // CHECK-EH-11-NEXT: entry: 1684 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1685 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1686 // CHECK-EH-11-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1687 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1688 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1689 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1690 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1691 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1692 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1693 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1694 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1695 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1696 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1697 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1698 // CHECK-EH-11: if.then: 1699 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1700 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1701 // CHECK-EH-11: invoke.cont: 1702 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1703 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 1704 // CHECK-EH-11: lpad: 1705 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1706 // CHECK-EH-11-NEXT: cleanup 1707 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1708 // CHECK-EH-11-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1709 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1710 // CHECK-EH-11-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1711 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1712 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 1713 // CHECK-EH-11: if.end: 1714 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 1715 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1716 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]] 1717 // CHECK-EH-11: invoke.cont1: 1718 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 1719 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1720 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1721 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1722 // CHECK-EH-11: nrvo.unused: 1723 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 1724 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 1725 // CHECK-EH-11: nrvo.skipdtor: 1726 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 1727 // CHECK-EH-11: cleanup: 1728 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1729 // CHECK-EH-11-NEXT: ret void 1730 // CHECK-EH-11: eh.resume: 1731 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1732 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1733 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1734 // CHECK-EH-11-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1735 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL2]] 1736 // 1737 X test14(bool b) { // http://wg21.link/p2025r2#ex-8 1738 X x; 1739 if (b) 1740 return x; 1741 X y; 1742 return y; // FIXME: NRVO could happen, but doesn't 1743 } 1744 1745 // CHECK-LABEL: @_Z6test15b( 1746 // CHECK-NEXT: entry: 1747 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1748 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1749 // CHECK-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1750 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1751 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1752 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1753 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1754 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1755 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1756 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1757 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1758 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1759 // CHECK: if.then: 1760 // CHECK-NEXT: call void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1761 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1762 // CHECK-NEXT: br label [[CLEANUP:%.*]] 1763 // CHECK: if.end: 1764 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 1765 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1766 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 1767 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1768 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1769 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1770 // CHECK: nrvo.unused: 1771 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 1772 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 1773 // CHECK: nrvo.skipdtor: 1774 // CHECK-NEXT: br label [[CLEANUP]] 1775 // CHECK: cleanup: 1776 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]] 1777 // CHECK-NEXT: ret void 1778 // 1779 // CHECK-EH-03-LABEL: @_Z6test15b( 1780 // CHECK-EH-03-NEXT: entry: 1781 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1782 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1783 // CHECK-EH-03-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1784 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1785 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1786 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1787 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1788 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1789 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1790 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1791 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1792 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1793 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1794 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1795 // CHECK-EH-03: if.then: 1796 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1797 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1798 // CHECK-EH-03: invoke.cont: 1799 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1800 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 1801 // CHECK-EH-03: lpad: 1802 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1803 // CHECK-EH-03-NEXT: cleanup 1804 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1805 // CHECK-EH-03-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1806 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1807 // CHECK-EH-03-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1808 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1809 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT3:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 1810 // CHECK-EH-03: if.end: 1811 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 1812 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1813 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]] 1814 // CHECK-EH-03: invoke.cont1: 1815 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 1816 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1817 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1818 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1819 // CHECK-EH-03: nrvo.unused: 1820 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1821 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD]] 1822 // CHECK-EH-03: invoke.cont2: 1823 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 1824 // CHECK-EH-03: nrvo.skipdtor: 1825 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 1826 // CHECK-EH-03: cleanup: 1827 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1828 // CHECK-EH-03-NEXT: ret void 1829 // CHECK-EH-03: invoke.cont3: 1830 // CHECK-EH-03-NEXT: br label [[EH_RESUME:%.*]] 1831 // CHECK-EH-03: eh.resume: 1832 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1833 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1834 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1835 // CHECK-EH-03-NEXT: [[LPAD_VAL4:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1836 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL4]] 1837 // CHECK-EH-03: terminate.lpad: 1838 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 } 1839 // CHECK-EH-03-NEXT: catch ptr null 1840 // CHECK-EH-03-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0 1841 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]] 1842 // CHECK-EH-03-NEXT: unreachable 1843 // 1844 // CHECK-EH-11-LABEL: @_Z6test15b( 1845 // CHECK-EH-11-NEXT: entry: 1846 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1847 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 1848 // CHECK-EH-11-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1849 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1850 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1851 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1852 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1853 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1854 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 1855 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 1856 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1857 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 1858 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 1859 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 1860 // CHECK-EH-11: if.then: 1861 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1862 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1863 // CHECK-EH-11: invoke.cont: 1864 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1865 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 1866 // CHECK-EH-11: lpad: 1867 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1868 // CHECK-EH-11-NEXT: cleanup 1869 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1870 // CHECK-EH-11-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1871 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1872 // CHECK-EH-11-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1873 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1874 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 1875 // CHECK-EH-11: if.end: 1876 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 1877 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1878 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[LPAD]] 1879 // CHECK-EH-11: invoke.cont1: 1880 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 1881 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1882 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 1883 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 1884 // CHECK-EH-11: nrvo.unused: 1885 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 1886 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 1887 // CHECK-EH-11: nrvo.skipdtor: 1888 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 1889 // CHECK-EH-11: cleanup: 1890 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1891 // CHECK-EH-11-NEXT: ret void 1892 // CHECK-EH-11: eh.resume: 1893 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1894 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1895 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1896 // CHECK-EH-11-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1897 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL2]] 1898 // 1899 X test15(bool b) { // http://wg21.link/p2025r2#ex-15 1900 X x; 1901 if (b) 1902 return (x); 1903 X y; 1904 return ((y)); // FIXME: NRVO could happen, but doesn't 1905 } 1906 1907 #ifdef CXX11 1908 // CHECK-EH-11-LABEL: @_Z6test16v( 1909 // CHECK-EH-11-NEXT: entry: 1910 // CHECK-EH-11-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 1911 // CHECK-EH-11-NEXT: [[AGG_TMP:%.*]] = alloca [[CLASS_X]], align 1 1912 // CHECK-EH-11-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON:%.*]], align 4 1913 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 1914 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 1915 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 1916 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON]], ptr [[REF_TMP]], i32 0, i32 0 1917 // CHECK-EH-11-NEXT: store ptr [[X]], ptr [[TMP0]], align 4 1918 // CHECK-EH-11-NEXT: invoke void @"_ZZ6test16vENK3$_0clEv"(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP]], ptr noundef nonnull align 4 dereferenceable(4) [[REF_TMP]]) 1919 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 1920 // CHECK-EH-11: invoke.cont: 1921 // CHECK-EH-11-NEXT: invoke void @_Z8ConsumeX1X(ptr noundef [[AGG_TMP]]) 1922 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT2:%.*]] unwind label [[LPAD1:%.*]] 1923 // CHECK-EH-11: invoke.cont2: 1924 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP]]) #[[ATTR6]] 1925 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1926 // CHECK-EH-11-NEXT: ret void 1927 // CHECK-EH-11: lpad: 1928 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 1929 // CHECK-EH-11-NEXT: cleanup 1930 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 1931 // CHECK-EH-11-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 1932 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 1933 // CHECK-EH-11-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 1934 // CHECK-EH-11-NEXT: br label [[EHCLEANUP:%.*]] 1935 // CHECK-EH-11: lpad1: 1936 // CHECK-EH-11-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 } 1937 // CHECK-EH-11-NEXT: cleanup 1938 // CHECK-EH-11-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0 1939 // CHECK-EH-11-NEXT: store ptr [[TMP5]], ptr [[EXN_SLOT]], align 4 1940 // CHECK-EH-11-NEXT: [[TMP6:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 1 1941 // CHECK-EH-11-NEXT: store i32 [[TMP6]], ptr [[EHSELECTOR_SLOT]], align 4 1942 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP]]) #[[ATTR6]] 1943 // CHECK-EH-11-NEXT: br label [[EHCLEANUP]] 1944 // CHECK-EH-11: ehcleanup: 1945 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 1946 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 1947 // CHECK-EH-11: eh.resume: 1948 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 1949 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 1950 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 1951 // CHECK-EH-11-NEXT: [[LPAD_VAL3:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 1952 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL3]] 1953 // 1954 void test16() { // http://wg21.link/p2025r2#ex-9 1955 X x; 1956 ConsumeX([&] { 1957 X y(x); 1958 return y; // NRVO happens 1959 }()); 1960 } 1961 #endif 1962 1963 // CHECK-LABEL: @_Z6test17i( 1964 // CHECK-NEXT: entry: 1965 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 1966 // CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 1967 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 1968 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 1969 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 1970 // CHECK-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 1971 // CHECK-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_END2:%.*]] 1972 // CHECK: if.then: 1973 // CHECK-NEXT: br label [[IMPOSSIBLE:%.*]] 1974 // CHECK: impossible: 1975 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 1976 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 3 1977 // CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]] 1978 // CHECK: if.then1: 1979 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1980 // CHECK-NEXT: br label [[RETURN:%.*]] 1981 // CHECK: if.end: 1982 // CHECK-NEXT: br label [[IF_END2]] 1983 // CHECK: if.end2: 1984 // CHECK-NEXT: br label [[WHILE_BODY:%.*]] 1985 // CHECK: while.body: 1986 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 1987 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 1988 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4 1989 // CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP1]], 0 1990 // CHECK-NEXT: br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END5:%.*]] 1991 // CHECK: if.then4: 1992 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 1993 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 1994 // CHECK-NEXT: br label [[CLEANUP:%.*]] 1995 // CHECK: if.end5: 1996 // CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I_ADDR]], align 4 1997 // CHECK-NEXT: [[CMP6:%.*]] = icmp eq i32 [[TMP2]], 1 1998 // CHECK-NEXT: br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_END8:%.*]] 1999 // CHECK: if.then7: 2000 // CHECK-NEXT: store i32 4, ptr [[CLEANUP_DEST_SLOT]], align 4 2001 // CHECK-NEXT: br label [[CLEANUP]] 2002 // CHECK: if.end8: 2003 // CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4 2004 // CHECK-NEXT: [[CMP9:%.*]] = icmp eq i32 [[TMP3]], 2 2005 // CHECK-NEXT: br i1 [[CMP9]], label [[IF_THEN10:%.*]], label [[IF_END11:%.*]] 2006 // CHECK: if.then10: 2007 // CHECK-NEXT: store i32 3, ptr [[CLEANUP_DEST_SLOT]], align 4 2008 // CHECK-NEXT: br label [[CLEANUP]], !llvm.loop [[LOOP3:![0-9]+]] 2009 // CHECK: if.end11: 2010 // CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[I_ADDR]], align 4 2011 // CHECK-NEXT: [[CMP12:%.*]] = icmp eq i32 [[TMP4]], 3 2012 // CHECK-NEXT: br i1 [[CMP12]], label [[IF_THEN13:%.*]], label [[IF_END14:%.*]] 2013 // CHECK: if.then13: 2014 // CHECK-NEXT: store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4 2015 // CHECK-NEXT: br label [[CLEANUP]] 2016 // CHECK: if.end14: 2017 // CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[I_ADDR]], align 4 2018 // CHECK-NEXT: [[CMP15:%.*]] = icmp eq i32 [[TMP5]], 4 2019 // CHECK-NEXT: br i1 [[CMP15]], label [[IF_THEN16:%.*]], label [[IF_END17:%.*]] 2020 // CHECK: if.then16: 2021 // CHECK-NEXT: call void @exit(i32 noundef 1) #[[ATTR4]] 2022 // CHECK-NEXT: br label [[IF_END17]] 2023 // CHECK: if.end17: 2024 // CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[I_ADDR]], align 4 2025 // CHECK-NEXT: [[CMP18:%.*]] = icmp eq i32 [[TMP6]], 5 2026 // CHECK-NEXT: br i1 [[CMP18]], label [[IF_THEN19:%.*]], label [[IF_END20:%.*]] 2027 // CHECK: if.then19: 2028 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 2029 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2030 // CHECK-NEXT: br label [[CLEANUP]] 2031 // CHECK: if.end20: 2032 // CHECK-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2033 // CHECK-NEXT: br label [[CLEANUP]] 2034 // CHECK: cleanup: 2035 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2036 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2037 // CHECK: nrvo.unused: 2038 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 2039 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 2040 // CHECK: nrvo.skipdtor: 2041 // CHECK-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2042 // CHECK-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 2043 // CHECK-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 2044 // CHECK-NEXT: i32 1, label [[RETURN]] 2045 // CHECK-NEXT: i32 4, label [[WHILE_END:%.*]] 2046 // CHECK-NEXT: i32 3, label [[WHILE_BODY]] 2047 // CHECK-NEXT: i32 2, label [[IMPOSSIBLE]] 2048 // CHECK-NEXT: ] 2049 // CHECK: cleanup.cont: 2050 // CHECK-NEXT: br label [[WHILE_BODY]], !llvm.loop [[LOOP3]] 2051 // CHECK: while.end: 2052 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2053 // CHECK-NEXT: br label [[RETURN]] 2054 // CHECK: return: 2055 // CHECK-NEXT: ret void 2056 // CHECK: unreachable: 2057 // CHECK-NEXT: unreachable 2058 // 2059 // CHECK-EH-03-LABEL: @_Z6test17i( 2060 // CHECK-EH-03-NEXT: entry: 2061 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2062 // CHECK-EH-03-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 2063 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2064 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 2065 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2066 // CHECK-EH-03-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 2067 // CHECK-EH-03-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_END2:%.*]] 2068 // CHECK-EH-03: if.then: 2069 // CHECK-EH-03-NEXT: br label [[IMPOSSIBLE:%.*]] 2070 // CHECK-EH-03: impossible: 2071 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 2072 // CHECK-EH-03-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 3 2073 // CHECK-EH-03-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]] 2074 // CHECK-EH-03: if.then1: 2075 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2076 // CHECK-EH-03-NEXT: br label [[RETURN:%.*]] 2077 // CHECK-EH-03: if.end: 2078 // CHECK-EH-03-NEXT: br label [[IF_END2]] 2079 // CHECK-EH-03: if.end2: 2080 // CHECK-EH-03-NEXT: br label [[WHILE_BODY:%.*]] 2081 // CHECK-EH-03: while.body: 2082 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 2083 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2084 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4 2085 // CHECK-EH-03-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP1]], 0 2086 // CHECK-EH-03-NEXT: br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END5:%.*]] 2087 // CHECK-EH-03: if.then4: 2088 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 2089 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2090 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 2091 // CHECK-EH-03: if.end5: 2092 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = load i32, ptr [[I_ADDR]], align 4 2093 // CHECK-EH-03-NEXT: [[CMP6:%.*]] = icmp eq i32 [[TMP2]], 1 2094 // CHECK-EH-03-NEXT: br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_END8:%.*]] 2095 // CHECK-EH-03: if.then7: 2096 // CHECK-EH-03-NEXT: store i32 4, ptr [[CLEANUP_DEST_SLOT]], align 4 2097 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 2098 // CHECK-EH-03: if.end8: 2099 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4 2100 // CHECK-EH-03-NEXT: [[CMP9:%.*]] = icmp eq i32 [[TMP3]], 2 2101 // CHECK-EH-03-NEXT: br i1 [[CMP9]], label [[IF_THEN10:%.*]], label [[IF_END11:%.*]] 2102 // CHECK-EH-03: if.then10: 2103 // CHECK-EH-03-NEXT: store i32 3, ptr [[CLEANUP_DEST_SLOT]], align 4 2104 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 2105 // CHECK-EH-03: if.end11: 2106 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = load i32, ptr [[I_ADDR]], align 4 2107 // CHECK-EH-03-NEXT: [[CMP12:%.*]] = icmp eq i32 [[TMP4]], 3 2108 // CHECK-EH-03-NEXT: br i1 [[CMP12]], label [[IF_THEN13:%.*]], label [[IF_END14:%.*]] 2109 // CHECK-EH-03: if.then13: 2110 // CHECK-EH-03-NEXT: store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4 2111 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 2112 // CHECK-EH-03: if.end14: 2113 // CHECK-EH-03-NEXT: [[TMP5:%.*]] = load i32, ptr [[I_ADDR]], align 4 2114 // CHECK-EH-03-NEXT: [[CMP15:%.*]] = icmp eq i32 [[TMP5]], 4 2115 // CHECK-EH-03-NEXT: br i1 [[CMP15]], label [[IF_THEN16:%.*]], label [[IF_END17:%.*]] 2116 // CHECK-EH-03: if.then16: 2117 // CHECK-EH-03-NEXT: call void @exit(i32 noundef 1) #[[ATTR7]] 2118 // CHECK-EH-03-NEXT: br label [[IF_END17]] 2119 // CHECK-EH-03: if.end17: 2120 // CHECK-EH-03-NEXT: [[TMP6:%.*]] = load i32, ptr [[I_ADDR]], align 4 2121 // CHECK-EH-03-NEXT: [[CMP18:%.*]] = icmp eq i32 [[TMP6]], 5 2122 // CHECK-EH-03-NEXT: br i1 [[CMP18]], label [[IF_THEN19:%.*]], label [[IF_END20:%.*]] 2123 // CHECK-EH-03: if.then19: 2124 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 2125 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2126 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 2127 // CHECK-EH-03: if.end20: 2128 // CHECK-EH-03-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2129 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 2130 // CHECK-EH-03: cleanup: 2131 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2132 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2133 // CHECK-EH-03: nrvo.unused: 2134 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2135 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 2136 // CHECK-EH-03: nrvo.skipdtor: 2137 // CHECK-EH-03-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2138 // CHECK-EH-03-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 2139 // CHECK-EH-03-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 2140 // CHECK-EH-03-NEXT: i32 1, label [[RETURN]] 2141 // CHECK-EH-03-NEXT: i32 4, label [[WHILE_END:%.*]] 2142 // CHECK-EH-03-NEXT: i32 3, label [[WHILE_BODY]] 2143 // CHECK-EH-03-NEXT: i32 2, label [[IMPOSSIBLE]] 2144 // CHECK-EH-03-NEXT: ] 2145 // CHECK-EH-03: cleanup.cont: 2146 // CHECK-EH-03-NEXT: br label [[WHILE_BODY]] 2147 // CHECK-EH-03: while.end: 2148 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2149 // CHECK-EH-03-NEXT: br label [[RETURN]] 2150 // CHECK-EH-03: return: 2151 // CHECK-EH-03-NEXT: ret void 2152 // CHECK-EH-03: unreachable: 2153 // CHECK-EH-03-NEXT: unreachable 2154 // 2155 // CHECK-EH-11-LABEL: @_Z6test17i( 2156 // CHECK-EH-11-NEXT: entry: 2157 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2158 // CHECK-EH-11-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 2159 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2160 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 2161 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2162 // CHECK-EH-11-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 2163 // CHECK-EH-11-NEXT: br i1 false, label [[IF_THEN:%.*]], label [[IF_END2:%.*]] 2164 // CHECK-EH-11: if.then: 2165 // CHECK-EH-11-NEXT: br label [[IMPOSSIBLE:%.*]] 2166 // CHECK-EH-11: impossible: 2167 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 2168 // CHECK-EH-11-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 3 2169 // CHECK-EH-11-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END:%.*]] 2170 // CHECK-EH-11: if.then1: 2171 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2172 // CHECK-EH-11-NEXT: br label [[RETURN:%.*]] 2173 // CHECK-EH-11: if.end: 2174 // CHECK-EH-11-NEXT: br label [[IF_END2]] 2175 // CHECK-EH-11: if.end2: 2176 // CHECK-EH-11-NEXT: br label [[WHILE_BODY:%.*]] 2177 // CHECK-EH-11: while.body: 2178 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 2179 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2180 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4 2181 // CHECK-EH-11-NEXT: [[CMP3:%.*]] = icmp eq i32 [[TMP1]], 0 2182 // CHECK-EH-11-NEXT: br i1 [[CMP3]], label [[IF_THEN4:%.*]], label [[IF_END5:%.*]] 2183 // CHECK-EH-11: if.then4: 2184 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 2185 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2186 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 2187 // CHECK-EH-11: if.end5: 2188 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = load i32, ptr [[I_ADDR]], align 4 2189 // CHECK-EH-11-NEXT: [[CMP6:%.*]] = icmp eq i32 [[TMP2]], 1 2190 // CHECK-EH-11-NEXT: br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_END8:%.*]] 2191 // CHECK-EH-11: if.then7: 2192 // CHECK-EH-11-NEXT: store i32 4, ptr [[CLEANUP_DEST_SLOT]], align 4 2193 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 2194 // CHECK-EH-11: if.end8: 2195 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = load i32, ptr [[I_ADDR]], align 4 2196 // CHECK-EH-11-NEXT: [[CMP9:%.*]] = icmp eq i32 [[TMP3]], 2 2197 // CHECK-EH-11-NEXT: br i1 [[CMP9]], label [[IF_THEN10:%.*]], label [[IF_END11:%.*]] 2198 // CHECK-EH-11: if.then10: 2199 // CHECK-EH-11-NEXT: store i32 3, ptr [[CLEANUP_DEST_SLOT]], align 4 2200 // CHECK-EH-11-NEXT: br label [[CLEANUP]], !llvm.loop [[LOOP3:![0-9]+]] 2201 // CHECK-EH-11: if.end11: 2202 // CHECK-EH-11-NEXT: [[TMP4:%.*]] = load i32, ptr [[I_ADDR]], align 4 2203 // CHECK-EH-11-NEXT: [[CMP12:%.*]] = icmp eq i32 [[TMP4]], 3 2204 // CHECK-EH-11-NEXT: br i1 [[CMP12]], label [[IF_THEN13:%.*]], label [[IF_END14:%.*]] 2205 // CHECK-EH-11: if.then13: 2206 // CHECK-EH-11-NEXT: store i32 2, ptr [[CLEANUP_DEST_SLOT]], align 4 2207 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 2208 // CHECK-EH-11: if.end14: 2209 // CHECK-EH-11-NEXT: [[TMP5:%.*]] = load i32, ptr [[I_ADDR]], align 4 2210 // CHECK-EH-11-NEXT: [[CMP15:%.*]] = icmp eq i32 [[TMP5]], 4 2211 // CHECK-EH-11-NEXT: br i1 [[CMP15]], label [[IF_THEN16:%.*]], label [[IF_END17:%.*]] 2212 // CHECK-EH-11: if.then16: 2213 // CHECK-EH-11-NEXT: call void @exit(i32 noundef 1) #[[ATTR6]] 2214 // CHECK-EH-11-NEXT: br label [[IF_END17]] 2215 // CHECK-EH-11: if.end17: 2216 // CHECK-EH-11-NEXT: [[TMP6:%.*]] = load i32, ptr [[I_ADDR]], align 4 2217 // CHECK-EH-11-NEXT: [[CMP18:%.*]] = icmp eq i32 [[TMP6]], 5 2218 // CHECK-EH-11-NEXT: br i1 [[CMP18]], label [[IF_THEN19:%.*]], label [[IF_END20:%.*]] 2219 // CHECK-EH-11: if.then19: 2220 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 2221 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2222 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 2223 // CHECK-EH-11: if.end20: 2224 // CHECK-EH-11-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2225 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 2226 // CHECK-EH-11: cleanup: 2227 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2228 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2229 // CHECK-EH-11: nrvo.unused: 2230 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2231 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 2232 // CHECK-EH-11: nrvo.skipdtor: 2233 // CHECK-EH-11-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2234 // CHECK-EH-11-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 2235 // CHECK-EH-11-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 2236 // CHECK-EH-11-NEXT: i32 1, label [[RETURN]] 2237 // CHECK-EH-11-NEXT: i32 4, label [[WHILE_END:%.*]] 2238 // CHECK-EH-11-NEXT: i32 3, label [[WHILE_BODY]] 2239 // CHECK-EH-11-NEXT: i32 2, label [[IMPOSSIBLE]] 2240 // CHECK-EH-11-NEXT: ] 2241 // CHECK-EH-11: cleanup.cont: 2242 // CHECK-EH-11-NEXT: br label [[WHILE_BODY]], !llvm.loop [[LOOP3]] 2243 // CHECK-EH-11: while.end: 2244 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2245 // CHECK-EH-11-NEXT: br label [[RETURN]] 2246 // CHECK-EH-11: return: 2247 // CHECK-EH-11-NEXT: ret void 2248 // CHECK-EH-11: unreachable: 2249 // CHECK-EH-11-NEXT: unreachable 2250 // 2251 X test17(int i) { // http://wg21.link/p2025r2#ex-10 2252 if (false) { 2253 impossible: 2254 if (i == 3) 2255 return X(); 2256 } 2257 2258 while (true) { 2259 X x; 2260 if (i == 0) 2261 return x; // NRVO happens 2262 if (i == 1) 2263 break; 2264 if (i == 2) 2265 continue; 2266 if (i == 3) 2267 goto impossible; 2268 if (i == 4) 2269 exit(1); 2270 if (i == 5) 2271 return x; // NRVO happens 2272 } 2273 return X(); 2274 } 2275 2276 // CHECK-LABEL: @_Z6test18i( 2277 // CHECK-NEXT: entry: 2278 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2279 // CHECK-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 2280 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2281 // CHECK-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 2282 // CHECK-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 2283 // CHECK-NEXT: [[NRVO11:%.*]] = alloca i1, align 1 2284 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2285 // CHECK-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 2286 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 2287 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2288 // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 2289 // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 2290 // CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 2291 // CHECK: if.then: 2292 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 2293 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2294 // CHECK-NEXT: br label [[CLEANUP:%.*]] 2295 // CHECK: if.end: 2296 // CHECK-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2297 // CHECK-NEXT: br label [[CLEANUP]] 2298 // CHECK: cleanup: 2299 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2300 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2301 // CHECK: nrvo.unused: 2302 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 2303 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 2304 // CHECK: nrvo.skipdtor: 2305 // CHECK-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2306 // CHECK-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 2307 // CHECK-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 2308 // CHECK-NEXT: i32 1, label [[RETURN:%.*]] 2309 // CHECK-NEXT: ] 2310 // CHECK: cleanup.cont: 2311 // CHECK-NEXT: store i1 false, ptr [[NRVO1]], align 1 2312 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2313 // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4 2314 // CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP1]], 1 2315 // CHECK-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]] 2316 // CHECK: if.then3: 2317 // CHECK-NEXT: store i1 true, ptr [[NRVO1]], align 1 2318 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2319 // CHECK-NEXT: br label [[CLEANUP5:%.*]] 2320 // CHECK: if.end4: 2321 // CHECK-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2322 // CHECK-NEXT: br label [[CLEANUP5]] 2323 // CHECK: cleanup5: 2324 // CHECK-NEXT: [[NRVO_VAL6:%.*]] = load i1, ptr [[NRVO1]], align 1 2325 // CHECK-NEXT: br i1 [[NRVO_VAL6]], label [[NRVO_SKIPDTOR8:%.*]], label [[NRVO_UNUSED7:%.*]] 2326 // CHECK: nrvo.unused7: 2327 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 2328 // CHECK-NEXT: br label [[NRVO_SKIPDTOR8]] 2329 // CHECK: nrvo.skipdtor8: 2330 // CHECK-NEXT: [[CLEANUP_DEST9:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2331 // CHECK-NEXT: switch i32 [[CLEANUP_DEST9]], label [[UNREACHABLE]] [ 2332 // CHECK-NEXT: i32 0, label [[CLEANUP_CONT10:%.*]] 2333 // CHECK-NEXT: i32 1, label [[RETURN]] 2334 // CHECK-NEXT: ] 2335 // CHECK: cleanup.cont10: 2336 // CHECK-NEXT: store i1 false, ptr [[NRVO11]], align 1 2337 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2338 // CHECK-NEXT: store i1 true, ptr [[NRVO11]], align 1 2339 // CHECK-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2340 // CHECK-NEXT: [[NRVO_VAL13:%.*]] = load i1, ptr [[NRVO11]], align 1 2341 // CHECK-NEXT: br i1 [[NRVO_VAL13]], label [[NRVO_SKIPDTOR15:%.*]], label [[NRVO_UNUSED14:%.*]] 2342 // CHECK: nrvo.unused14: 2343 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 2344 // CHECK-NEXT: br label [[NRVO_SKIPDTOR15]] 2345 // CHECK: nrvo.skipdtor15: 2346 // CHECK-NEXT: br label [[RETURN]] 2347 // CHECK: return: 2348 // CHECK-NEXT: ret void 2349 // CHECK: unreachable: 2350 // CHECK-NEXT: unreachable 2351 // 2352 // CHECK-EH-03-LABEL: @_Z6test18i( 2353 // CHECK-EH-03-NEXT: entry: 2354 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2355 // CHECK-EH-03-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 2356 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2357 // CHECK-EH-03-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 2358 // CHECK-EH-03-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 2359 // CHECK-EH-03-NEXT: [[NRVO11:%.*]] = alloca i1, align 1 2360 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2361 // CHECK-EH-03-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 2362 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 2363 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2364 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 2365 // CHECK-EH-03-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 2366 // CHECK-EH-03-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 2367 // CHECK-EH-03: if.then: 2368 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 2369 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2370 // CHECK-EH-03-NEXT: br label [[CLEANUP:%.*]] 2371 // CHECK-EH-03: if.end: 2372 // CHECK-EH-03-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2373 // CHECK-EH-03-NEXT: br label [[CLEANUP]] 2374 // CHECK-EH-03: cleanup: 2375 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2376 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2377 // CHECK-EH-03: nrvo.unused: 2378 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2379 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 2380 // CHECK-EH-03: nrvo.skipdtor: 2381 // CHECK-EH-03-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2382 // CHECK-EH-03-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 2383 // CHECK-EH-03-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 2384 // CHECK-EH-03-NEXT: i32 1, label [[RETURN:%.*]] 2385 // CHECK-EH-03-NEXT: ] 2386 // CHECK-EH-03: cleanup.cont: 2387 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO1]], align 1 2388 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2389 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4 2390 // CHECK-EH-03-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP1]], 1 2391 // CHECK-EH-03-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]] 2392 // CHECK-EH-03: if.then3: 2393 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO1]], align 1 2394 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2395 // CHECK-EH-03-NEXT: br label [[CLEANUP5:%.*]] 2396 // CHECK-EH-03: if.end4: 2397 // CHECK-EH-03-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2398 // CHECK-EH-03-NEXT: br label [[CLEANUP5]] 2399 // CHECK-EH-03: cleanup5: 2400 // CHECK-EH-03-NEXT: [[NRVO_VAL6:%.*]] = load i1, ptr [[NRVO1]], align 1 2401 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL6]], label [[NRVO_SKIPDTOR8:%.*]], label [[NRVO_UNUSED7:%.*]] 2402 // CHECK-EH-03: nrvo.unused7: 2403 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2404 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR8]] 2405 // CHECK-EH-03: nrvo.skipdtor8: 2406 // CHECK-EH-03-NEXT: [[CLEANUP_DEST9:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2407 // CHECK-EH-03-NEXT: switch i32 [[CLEANUP_DEST9]], label [[UNREACHABLE]] [ 2408 // CHECK-EH-03-NEXT: i32 0, label [[CLEANUP_CONT10:%.*]] 2409 // CHECK-EH-03-NEXT: i32 1, label [[RETURN]] 2410 // CHECK-EH-03-NEXT: ] 2411 // CHECK-EH-03: cleanup.cont10: 2412 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO11]], align 1 2413 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2414 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO11]], align 1 2415 // CHECK-EH-03-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2416 // CHECK-EH-03-NEXT: [[NRVO_VAL13:%.*]] = load i1, ptr [[NRVO11]], align 1 2417 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL13]], label [[NRVO_SKIPDTOR15:%.*]], label [[NRVO_UNUSED14:%.*]] 2418 // CHECK-EH-03: nrvo.unused14: 2419 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2420 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR15]] 2421 // CHECK-EH-03: nrvo.skipdtor15: 2422 // CHECK-EH-03-NEXT: br label [[RETURN]] 2423 // CHECK-EH-03: return: 2424 // CHECK-EH-03-NEXT: ret void 2425 // CHECK-EH-03: unreachable: 2426 // CHECK-EH-03-NEXT: unreachable 2427 // 2428 // CHECK-EH-11-LABEL: @_Z6test18i( 2429 // CHECK-EH-11-NEXT: entry: 2430 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2431 // CHECK-EH-11-NEXT: [[I_ADDR:%.*]] = alloca i32, align 4 2432 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2433 // CHECK-EH-11-NEXT: [[CLEANUP_DEST_SLOT:%.*]] = alloca i32, align 4 2434 // CHECK-EH-11-NEXT: [[NRVO1:%.*]] = alloca i1, align 1 2435 // CHECK-EH-11-NEXT: [[NRVO11:%.*]] = alloca i1, align 1 2436 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2437 // CHECK-EH-11-NEXT: store i32 [[I:%.*]], ptr [[I_ADDR]], align 4 2438 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 2439 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2440 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i32, ptr [[I_ADDR]], align 4 2441 // CHECK-EH-11-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0 2442 // CHECK-EH-11-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 2443 // CHECK-EH-11: if.then: 2444 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 2445 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2446 // CHECK-EH-11-NEXT: br label [[CLEANUP:%.*]] 2447 // CHECK-EH-11: if.end: 2448 // CHECK-EH-11-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2449 // CHECK-EH-11-NEXT: br label [[CLEANUP]] 2450 // CHECK-EH-11: cleanup: 2451 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2452 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2453 // CHECK-EH-11: nrvo.unused: 2454 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2455 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 2456 // CHECK-EH-11: nrvo.skipdtor: 2457 // CHECK-EH-11-NEXT: [[CLEANUP_DEST:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2458 // CHECK-EH-11-NEXT: switch i32 [[CLEANUP_DEST]], label [[UNREACHABLE:%.*]] [ 2459 // CHECK-EH-11-NEXT: i32 0, label [[CLEANUP_CONT:%.*]] 2460 // CHECK-EH-11-NEXT: i32 1, label [[RETURN:%.*]] 2461 // CHECK-EH-11-NEXT: ] 2462 // CHECK-EH-11: cleanup.cont: 2463 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO1]], align 1 2464 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2465 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = load i32, ptr [[I_ADDR]], align 4 2466 // CHECK-EH-11-NEXT: [[CMP2:%.*]] = icmp eq i32 [[TMP1]], 1 2467 // CHECK-EH-11-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END4:%.*]] 2468 // CHECK-EH-11: if.then3: 2469 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO1]], align 1 2470 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2471 // CHECK-EH-11-NEXT: br label [[CLEANUP5:%.*]] 2472 // CHECK-EH-11: if.end4: 2473 // CHECK-EH-11-NEXT: store i32 0, ptr [[CLEANUP_DEST_SLOT]], align 4 2474 // CHECK-EH-11-NEXT: br label [[CLEANUP5]] 2475 // CHECK-EH-11: cleanup5: 2476 // CHECK-EH-11-NEXT: [[NRVO_VAL6:%.*]] = load i1, ptr [[NRVO1]], align 1 2477 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL6]], label [[NRVO_SKIPDTOR8:%.*]], label [[NRVO_UNUSED7:%.*]] 2478 // CHECK-EH-11: nrvo.unused7: 2479 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2480 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR8]] 2481 // CHECK-EH-11: nrvo.skipdtor8: 2482 // CHECK-EH-11-NEXT: [[CLEANUP_DEST9:%.*]] = load i32, ptr [[CLEANUP_DEST_SLOT]], align 4 2483 // CHECK-EH-11-NEXT: switch i32 [[CLEANUP_DEST9]], label [[UNREACHABLE]] [ 2484 // CHECK-EH-11-NEXT: i32 0, label [[CLEANUP_CONT10:%.*]] 2485 // CHECK-EH-11-NEXT: i32 1, label [[RETURN]] 2486 // CHECK-EH-11-NEXT: ] 2487 // CHECK-EH-11: cleanup.cont10: 2488 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO11]], align 1 2489 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2490 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO11]], align 1 2491 // CHECK-EH-11-NEXT: store i32 1, ptr [[CLEANUP_DEST_SLOT]], align 4 2492 // CHECK-EH-11-NEXT: [[NRVO_VAL13:%.*]] = load i1, ptr [[NRVO11]], align 1 2493 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL13]], label [[NRVO_SKIPDTOR15:%.*]], label [[NRVO_UNUSED14:%.*]] 2494 // CHECK-EH-11: nrvo.unused14: 2495 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2496 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR15]] 2497 // CHECK-EH-11: nrvo.skipdtor15: 2498 // CHECK-EH-11-NEXT: br label [[RETURN]] 2499 // CHECK-EH-11: return: 2500 // CHECK-EH-11-NEXT: ret void 2501 // CHECK-EH-11: unreachable: 2502 // CHECK-EH-11-NEXT: unreachable 2503 // 2504 X test18(int i) { // http://wg21.link/p2025r2#ex-11 2505 { 2506 { 2507 X x; 2508 if (i == 0) 2509 return x; // NRVO happens 2510 } 2511 X y; 2512 if (i == 1) 2513 return y; // FIXME: NRVO could happen, but doesn't 2514 } 2515 X z; 2516 return z; // FIXME: NRVO could happen, but doesn't 2517 } 2518 2519 #ifdef CXX11 2520 // CHECK-EH-11-LABEL: @_Z6test19v( 2521 // CHECK-EH-11-NEXT: entry: 2522 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2523 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2524 // CHECK-EH-11-NEXT: [[L:%.*]] = alloca [[CLASS_X:%.*]], align 1 2525 // CHECK-EH-11-NEXT: [[REF_TMP:%.*]] = alloca [[CLASS_ANON_0:%.*]], align 4 2526 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 2527 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 2528 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2529 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 2530 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2531 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[CLASS_ANON_0]], ptr [[REF_TMP]], i32 0, i32 0 2532 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT]], ptr [[TMP0]], align 4 2533 // CHECK-EH-11-NEXT: invoke void @"_ZZ6test19vENK3$_0clEv"(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[L]], ptr noundef nonnull align 4 dereferenceable(4) [[REF_TMP]]) 2534 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 2535 // CHECK-EH-11: invoke.cont: 2536 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 2537 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[L]]) #[[ATTR6]] 2538 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2539 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2540 // CHECK-EH-11: lpad: 2541 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 2542 // CHECK-EH-11-NEXT: cleanup 2543 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 2544 // CHECK-EH-11-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 2545 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 2546 // CHECK-EH-11-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 2547 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2548 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 2549 // CHECK-EH-11: nrvo.unused: 2550 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2551 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 2552 // CHECK-EH-11: nrvo.skipdtor: 2553 // CHECK-EH-11-NEXT: ret void 2554 // CHECK-EH-11: eh.resume: 2555 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 2556 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 2557 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 2558 // CHECK-EH-11-NEXT: [[LPAD_VAL1:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 2559 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL1]] 2560 // 2561 X test19() { // http://wg21.link/p2025r2#ex-12 2562 X x; 2563 struct S { 2564 X f() { return X(); } 2565 }; 2566 auto L = [&x]() { return X(); }(); 2567 if constexpr (false) { 2568 return X(); 2569 } 2570 return x; // NRVO happens 2571 } 2572 2573 template <bool B> 2574 X test20() { // http://wg21.link/p2025r2#ex-18 2575 X x; 2576 if constexpr (B) { 2577 if (false) 2578 return X(); 2579 } 2580 return x; // FIXME: NRVO could happen when B == false, but doesn't 2581 } 2582 2583 // CHECK-EH-11-LABEL: @_Z17test20instantiatev( 2584 // CHECK-EH-11-NEXT: entry: 2585 // CHECK-EH-11-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[CLASS_X:%.*]], align 1 2586 // CHECK-EH-11-NEXT: [[AGG_TMP_ENSURED1:%.*]] = alloca [[CLASS_X]], align 1 2587 // CHECK-EH-11-NEXT: call void @_Z6test20ILb1EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED]]) 2588 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]) #[[ATTR6]] 2589 // CHECK-EH-11-NEXT: call void @_Z6test20ILb0EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED1]]) 2590 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED1]]) #[[ATTR6]] 2591 // CHECK-EH-11-NEXT: ret void 2592 // 2593 void test20instantiate() { 2594 test20<true>(); 2595 test20<false>(); 2596 } 2597 #endif 2598 2599 // CHECK-LABEL: @_Z6test21v( 2600 // CHECK-NEXT: entry: 2601 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2602 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2603 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2604 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 2605 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2606 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 2607 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2608 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2609 // CHECK: nrvo.unused: 2610 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 2611 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 2612 // CHECK: nrvo.skipdtor: 2613 // CHECK-NEXT: ret void 2614 // 2615 // CHECK-EH-03-LABEL: @_Z6test21v( 2616 // CHECK-EH-03-NEXT: entry: 2617 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2618 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2619 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2620 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 2621 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2622 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 2623 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2624 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2625 // CHECK-EH-03: nrvo.unused: 2626 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2627 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 2628 // CHECK-EH-03: nrvo.skipdtor: 2629 // CHECK-EH-03-NEXT: ret void 2630 // 2631 // CHECK-EH-11-LABEL: @_Z6test21v( 2632 // CHECK-EH-11-NEXT: entry: 2633 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2634 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2635 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2636 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 2637 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2638 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 2639 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2640 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2641 // CHECK-EH-11: nrvo.unused: 2642 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2643 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 2644 // CHECK-EH-11: nrvo.skipdtor: 2645 // CHECK-EH-11-NEXT: ret void 2646 // 2647 const volatile X test21() { // http://wg21.link/p2025r2#ex-19 2648 X x; 2649 return x; // NRVO happens 2650 } 2651 2652 // CHECK-LABEL: @_Z6test22v( 2653 // CHECK-NEXT: entry: 2654 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2655 // CHECK-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 2656 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2657 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 2658 // CHECK-NEXT: call void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 2659 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR4]] 2660 // CHECK-NEXT: ret void 2661 // 2662 // CHECK-EH-03-LABEL: @_Z6test22v( 2663 // CHECK-EH-03-NEXT: entry: 2664 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2665 // CHECK-EH-03-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 2666 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 2667 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 2668 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2669 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 2670 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 2671 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 2672 // CHECK-EH-03: invoke.cont: 2673 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 2674 // CHECK-EH-03-NEXT: ret void 2675 // CHECK-EH-03: lpad: 2676 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 2677 // CHECK-EH-03-NEXT: cleanup 2678 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 2679 // CHECK-EH-03-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4 2680 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 2681 // CHECK-EH-03-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4 2682 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 2683 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 2684 // CHECK-EH-03: invoke.cont1: 2685 // CHECK-EH-03-NEXT: br label [[EH_RESUME:%.*]] 2686 // CHECK-EH-03: eh.resume: 2687 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 2688 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 2689 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 2690 // CHECK-EH-03-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 2691 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL2]] 2692 // CHECK-EH-03: terminate.lpad: 2693 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = landingpad { ptr, i32 } 2694 // CHECK-EH-03-NEXT: catch ptr null 2695 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0 2696 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP4]]) #[[ATTR6]] 2697 // CHECK-EH-03-NEXT: unreachable 2698 // 2699 // CHECK-EH-11-LABEL: @_Z6test22v( 2700 // CHECK-EH-11-NEXT: entry: 2701 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2702 // CHECK-EH-11-NEXT: [[X:%.*]] = alloca [[CLASS_X:%.*]], align 1 2703 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 2704 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 2705 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2706 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 2707 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[X]]) 2708 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 2709 // CHECK-EH-11: invoke.cont: 2710 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 2711 // CHECK-EH-11-NEXT: ret void 2712 // CHECK-EH-11: lpad: 2713 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 2714 // CHECK-EH-11-NEXT: cleanup 2715 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 2716 // CHECK-EH-11-NEXT: store ptr [[TMP1]], ptr [[EXN_SLOT]], align 4 2717 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 2718 // CHECK-EH-11-NEXT: store i32 [[TMP2]], ptr [[EHSELECTOR_SLOT]], align 4 2719 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[X]]) #[[ATTR6]] 2720 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 2721 // CHECK-EH-11: eh.resume: 2722 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 2723 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 2724 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 2725 // CHECK-EH-11-NEXT: [[LPAD_VAL1:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 2726 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL1]] 2727 // 2728 X test22() { // http://wg21.link/p2025r2#ex-19 2729 volatile X x; 2730 return x; // NRVO is impossible 2731 } 2732 2733 // CHECK-LABEL: @_Z6test23b( 2734 // CHECK-NEXT: entry: 2735 // CHECK-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2736 // CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 2737 // CHECK-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2738 // CHECK-NEXT: [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1 2739 // CHECK-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2740 // CHECK-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 2741 // CHECK-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 2742 // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 2743 // CHECK-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 2744 // CHECK-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 2745 // CHECK: if.then: 2746 // CHECK-NEXT: store i1 false, ptr [[NRVO]], align 1 2747 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2748 // CHECK-NEXT: store i1 true, ptr [[NRVO]], align 1 2749 // CHECK-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2750 // CHECK-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2751 // CHECK: nrvo.unused: 2752 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR4]] 2753 // CHECK-NEXT: br label [[NRVO_SKIPDTOR]] 2754 // CHECK: nrvo.skipdtor: 2755 // CHECK-NEXT: br label [[RETURN:%.*]] 2756 // CHECK: if.end: 2757 // CHECK-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 2758 // CHECK-NEXT: call void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 2759 // CHECK-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR4]] 2760 // CHECK-NEXT: br label [[RETURN]] 2761 // CHECK: return: 2762 // CHECK-NEXT: ret void 2763 // 2764 // CHECK-EH-03-LABEL: @_Z6test23b( 2765 // CHECK-EH-03-NEXT: entry: 2766 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2767 // CHECK-EH-03-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 2768 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2769 // CHECK-EH-03-NEXT: [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1 2770 // CHECK-EH-03-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 2771 // CHECK-EH-03-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 2772 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2773 // CHECK-EH-03-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 2774 // CHECK-EH-03-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 2775 // CHECK-EH-03-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 2776 // CHECK-EH-03-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 2777 // CHECK-EH-03-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 2778 // CHECK-EH-03: if.then: 2779 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 2780 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2781 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 2782 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2783 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2784 // CHECK-EH-03: nrvo.unused: 2785 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2786 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 2787 // CHECK-EH-03: nrvo.skipdtor: 2788 // CHECK-EH-03-NEXT: br label [[RETURN:%.*]] 2789 // CHECK-EH-03: if.end: 2790 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 2791 // CHECK-EH-03-NEXT: invoke void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 2792 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 2793 // CHECK-EH-03: invoke.cont: 2794 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 2795 // CHECK-EH-03-NEXT: br label [[RETURN]] 2796 // CHECK-EH-03: lpad: 2797 // CHECK-EH-03-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 2798 // CHECK-EH-03-NEXT: cleanup 2799 // CHECK-EH-03-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 2800 // CHECK-EH-03-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 2801 // CHECK-EH-03-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 2802 // CHECK-EH-03-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 2803 // CHECK-EH-03-NEXT: invoke void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 2804 // CHECK-EH-03-NEXT: to label [[INVOKE_CONT1:%.*]] unwind label [[TERMINATE_LPAD:%.*]] 2805 // CHECK-EH-03: invoke.cont1: 2806 // CHECK-EH-03-NEXT: br label [[EH_RESUME:%.*]] 2807 // CHECK-EH-03: return: 2808 // CHECK-EH-03-NEXT: ret void 2809 // CHECK-EH-03: eh.resume: 2810 // CHECK-EH-03-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 2811 // CHECK-EH-03-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 2812 // CHECK-EH-03-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 2813 // CHECK-EH-03-NEXT: [[LPAD_VAL2:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 2814 // CHECK-EH-03-NEXT: resume { ptr, i32 } [[LPAD_VAL2]] 2815 // CHECK-EH-03: terminate.lpad: 2816 // CHECK-EH-03-NEXT: [[TMP4:%.*]] = landingpad { ptr, i32 } 2817 // CHECK-EH-03-NEXT: catch ptr null 2818 // CHECK-EH-03-NEXT: [[TMP5:%.*]] = extractvalue { ptr, i32 } [[TMP4]], 0 2819 // CHECK-EH-03-NEXT: call void @__clang_call_terminate(ptr [[TMP5]]) #[[ATTR6]] 2820 // CHECK-EH-03-NEXT: unreachable 2821 // 2822 // CHECK-EH-11-LABEL: @_Z6test23b( 2823 // CHECK-EH-11-NEXT: entry: 2824 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2825 // CHECK-EH-11-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1 2826 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2827 // CHECK-EH-11-NEXT: [[Y:%.*]] = alloca [[CLASS_X:%.*]], align 1 2828 // CHECK-EH-11-NEXT: [[EXN_SLOT:%.*]] = alloca ptr, align 4 2829 // CHECK-EH-11-NEXT: [[EHSELECTOR_SLOT:%.*]] = alloca i32, align 4 2830 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2831 // CHECK-EH-11-NEXT: [[STOREDV:%.*]] = zext i1 [[B:%.*]] to i8 2832 // CHECK-EH-11-NEXT: store i8 [[STOREDV]], ptr [[B_ADDR]], align 1 2833 // CHECK-EH-11-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1 2834 // CHECK-EH-11-NEXT: [[LOADEDV:%.*]] = trunc i8 [[TMP0]] to i1 2835 // CHECK-EH-11-NEXT: br i1 [[LOADEDV]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 2836 // CHECK-EH-11: if.then: 2837 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 2838 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2839 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 2840 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2841 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2842 // CHECK-EH-11: nrvo.unused: 2843 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2844 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 2845 // CHECK-EH-11: nrvo.skipdtor: 2846 // CHECK-EH-11-NEXT: br label [[RETURN:%.*]] 2847 // CHECK-EH-11: if.end: 2848 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 2849 // CHECK-EH-11-NEXT: invoke void @_ZN1XC1ERVKS_(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]], ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) 2850 // CHECK-EH-11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 2851 // CHECK-EH-11: invoke.cont: 2852 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR6]] 2853 // CHECK-EH-11-NEXT: br label [[RETURN]] 2854 // CHECK-EH-11: lpad: 2855 // CHECK-EH-11-NEXT: [[TMP1:%.*]] = landingpad { ptr, i32 } 2856 // CHECK-EH-11-NEXT: cleanup 2857 // CHECK-EH-11-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 0 2858 // CHECK-EH-11-NEXT: store ptr [[TMP2]], ptr [[EXN_SLOT]], align 4 2859 // CHECK-EH-11-NEXT: [[TMP3:%.*]] = extractvalue { ptr, i32 } [[TMP1]], 1 2860 // CHECK-EH-11-NEXT: store i32 [[TMP3]], ptr [[EHSELECTOR_SLOT]], align 4 2861 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[Y]]) #[[ATTR6]] 2862 // CHECK-EH-11-NEXT: br label [[EH_RESUME:%.*]] 2863 // CHECK-EH-11: return: 2864 // CHECK-EH-11-NEXT: ret void 2865 // CHECK-EH-11: eh.resume: 2866 // CHECK-EH-11-NEXT: [[EXN:%.*]] = load ptr, ptr [[EXN_SLOT]], align 4 2867 // CHECK-EH-11-NEXT: [[SEL:%.*]] = load i32, ptr [[EHSELECTOR_SLOT]], align 4 2868 // CHECK-EH-11-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } poison, ptr [[EXN]], 0 2869 // CHECK-EH-11-NEXT: [[LPAD_VAL1:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[SEL]], 1 2870 // CHECK-EH-11-NEXT: resume { ptr, i32 } [[LPAD_VAL1]] 2871 // 2872 X test23(bool b) { // http://wg21.link/p2025r2#ex-19 2873 if (b) { 2874 const X x; 2875 return x; // NRVO happens 2876 } 2877 volatile X y; 2878 return y; // NRVO is impossible 2879 } 2880 2881 #ifdef __EXCEPTIONS 2882 // CHECK-EH-03-LABEL: @_Z6test24v( 2883 // CHECK-EH-03-NEXT: entry: 2884 // CHECK-EH-03-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2885 // CHECK-EH-03-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2886 // CHECK-EH-03-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2887 // CHECK-EH-03-NEXT: store i1 false, ptr [[NRVO]], align 1 2888 // CHECK-EH-03-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2889 // CHECK-EH-03-NEXT: store i1 true, ptr [[NRVO]], align 1 2890 // CHECK-EH-03-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2891 // CHECK-EH-03-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2892 // CHECK-EH-03: nrvo.unused: 2893 // CHECK-EH-03-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2894 // CHECK-EH-03-NEXT: br label [[NRVO_SKIPDTOR]] 2895 // CHECK-EH-03: nrvo.skipdtor: 2896 // CHECK-EH-03-NEXT: ret void 2897 // 2898 // CHECK-EH-11-LABEL: @_Z6test24v( 2899 // CHECK-EH-11-NEXT: entry: 2900 // CHECK-EH-11-NEXT: [[RESULT_PTR:%.*]] = alloca ptr, align 4 2901 // CHECK-EH-11-NEXT: [[NRVO:%.*]] = alloca i1, align 1 2902 // CHECK-EH-11-NEXT: store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4 2903 // CHECK-EH-11-NEXT: store i1 false, ptr [[NRVO]], align 1 2904 // CHECK-EH-11-NEXT: call void @_ZN1XC1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) 2905 // CHECK-EH-11-NEXT: store i1 true, ptr [[NRVO]], align 1 2906 // CHECK-EH-11-NEXT: [[NRVO_VAL:%.*]] = load i1, ptr [[NRVO]], align 1 2907 // CHECK-EH-11-NEXT: br i1 [[NRVO_VAL]], label [[NRVO_SKIPDTOR:%.*]], label [[NRVO_UNUSED:%.*]] 2908 // CHECK-EH-11: nrvo.unused: 2909 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_RESULT]]) #[[ATTR6]] 2910 // CHECK-EH-11-NEXT: br label [[NRVO_SKIPDTOR]] 2911 // CHECK-EH-11: nrvo.skipdtor: 2912 // CHECK-EH-11-NEXT: ret void 2913 // 2914 X test24() { // http://wg21.link/p2025r2#ex-20 2915 X x; 2916 if (&x == &OuterX) 2917 throw 0; 2918 return x; // NRVO happens 2919 } 2920 #endif 2921 2922 #ifdef CXX11 2923 template <bool B> 2924 X test25() { 2925 X x; 2926 if constexpr (B) { 2927 return x; // FIXME: NRVO could happen when B == true, but doesn't 2928 } else { 2929 return X(); 2930 } 2931 } 2932 2933 // CHECK-EH-11-LABEL: @_Z17test25instantiatev( 2934 // CHECK-EH-11-NEXT: entry: 2935 // CHECK-EH-11-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[CLASS_X:%.*]], align 1 2936 // CHECK-EH-11-NEXT: [[AGG_TMP_ENSURED1:%.*]] = alloca [[CLASS_X]], align 1 2937 // CHECK-EH-11-NEXT: call void @_Z6test25ILb1EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED]]) 2938 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED]]) #[[ATTR6]] 2939 // CHECK-EH-11-NEXT: call void @_Z6test25ILb0EE1Xv(ptr dead_on_unwind writable sret([[CLASS_X]]) align 1 [[AGG_TMP_ENSURED1]]) 2940 // CHECK-EH-11-NEXT: call void @_ZN1XD1Ev(ptr noundef nonnull align 1 dereferenceable(1) [[AGG_TMP_ENSURED1]]) #[[ATTR6]] 2941 // CHECK-EH-11-NEXT: ret void 2942 // 2943 void test25instantiate() { 2944 test25<true>(); 2945 test25<false>(); 2946 } 2947 #endif 2948