1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=licm -S | FileCheck %s 3; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<target-ir>,require<scalar-evolution>,require<opt-remark-emit>,loop-mssa(licm)' -S %s | FileCheck %s 4 5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 6target triple = "x86_64-unknown-linux-gnu" 7 8; Make sure we don't hoist the store out of the loop; %a would 9; have the wrong value if f() unwinds 10define void @test1(ptr nocapture noalias %a, i1 zeroext %y) uwtable { 11; CHECK-LABEL: @test1( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: [[A_PROMOTED:%.*]] = load i32, ptr [[A:%.*]], align 4 14; CHECK-NEXT: br label [[FOR_BODY:%.*]] 15; CHECK: for.body: 16; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[A_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_INC:%.*]] ] 17; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_INC]] ] 18; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 19; CHECK-NEXT: store i32 [[ADD]], ptr [[A]], align 4 20; CHECK-NEXT: br i1 [[Y:%.*]], label [[IF_THEN:%.*]], label [[FOR_INC]] 21; CHECK: if.then: 22; CHECK-NEXT: tail call void @f() 23; CHECK-NEXT: br label [[FOR_INC]] 24; CHECK: for.inc: 25; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_03]], 1 26; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 10000 27; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 28; CHECK: for.cond.cleanup: 29; CHECK-NEXT: ret void 30; 31entry: 32 br label %for.body 33 34for.body: 35 %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 36 %0 = load i32, ptr %a, align 4 37 %add = add nsw i32 %0, 1 38 store i32 %add, ptr %a, align 4 39 br i1 %y, label %if.then, label %for.inc 40 41 42if.then: 43 tail call void @f() 44 br label %for.inc 45 46for.inc: 47 %inc = add nuw nsw i32 %i.03, 1 48 %exitcond = icmp eq i32 %inc, 10000 49 br i1 %exitcond, label %for.cond.cleanup, label %for.body 50 51for.cond.cleanup: 52 ret void 53} 54 55; We can hoist the store out of the loop here; if f() unwinds, 56; the lifetime of %a ends. 57define void @test_alloca(i1 zeroext %y) uwtable { 58; CHECK-LABEL: @test_alloca( 59; CHECK-NEXT: entry: 60; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 61; CHECK-NEXT: [[A_PROMOTED:%.*]] = load i32, ptr [[A]], align 4 62; CHECK-NEXT: br label [[FOR_BODY:%.*]] 63; CHECK: for.body: 64; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[A_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_INC:%.*]] ] 65; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_INC]] ] 66; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 67; CHECK-NEXT: br i1 [[Y:%.*]], label [[IF_THEN:%.*]], label [[FOR_INC]] 68; CHECK: if.then: 69; CHECK-NEXT: tail call void @f() 70; CHECK-NEXT: br label [[FOR_INC]] 71; CHECK: for.inc: 72; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_03]], 1 73; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 10000 74; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 75; CHECK: for.cond.cleanup: 76; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_INC]] ] 77; CHECK-NEXT: store i32 [[ADD_LCSSA]], ptr [[A]], align 4 78; CHECK-NEXT: ret void 79; 80entry: 81 %a = alloca i32 82 br label %for.body 83 84for.body: 85 %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 86 %0 = load i32, ptr %a, align 4 87 %add = add nsw i32 %0, 1 88 store i32 %add, ptr %a, align 4 89 br i1 %y, label %if.then, label %for.inc 90 91if.then: 92 tail call void @f() 93 br label %for.inc 94 95for.inc: 96 %inc = add nuw nsw i32 %i.03, 1 97 %exitcond = icmp eq i32 %inc, 10000 98 br i1 %exitcond, label %for.cond.cleanup, label %for.body 99 100for.cond.cleanup: 101 ret void 102} 103 104; byval memory cannot be accessed on unwind either. 105define void @test_byval(ptr byval(i32) %a, i1 zeroext %y) uwtable { 106; CHECK-LABEL: @test_byval( 107; CHECK-NEXT: entry: 108; CHECK-NEXT: [[A_PROMOTED:%.*]] = load i32, ptr [[A:%.*]], align 4 109; CHECK-NEXT: br label [[FOR_BODY:%.*]] 110; CHECK: for.body: 111; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[A_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_INC:%.*]] ] 112; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_INC]] ] 113; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 114; CHECK-NEXT: br i1 [[Y:%.*]], label [[IF_THEN:%.*]], label [[FOR_INC]] 115; CHECK: if.then: 116; CHECK-NEXT: tail call void @f() 117; CHECK-NEXT: br label [[FOR_INC]] 118; CHECK: for.inc: 119; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_03]], 1 120; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 10000 121; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 122; CHECK: for.cond.cleanup: 123; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_INC]] ] 124; CHECK-NEXT: store i32 [[ADD_LCSSA]], ptr [[A]], align 4 125; CHECK-NEXT: ret void 126; 127entry: 128 br label %for.body 129 130for.body: 131 %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 132 %0 = load i32, ptr %a, align 4 133 %add = add nsw i32 %0, 1 134 store i32 %add, ptr %a, align 4 135 br i1 %y, label %if.then, label %for.inc 136 137if.then: 138 tail call void @f() 139 br label %for.inc 140 141for.inc: 142 %inc = add nuw nsw i32 %i.03, 1 143 %exitcond = icmp eq i32 %inc, 10000 144 br i1 %exitcond, label %for.cond.cleanup, label %for.body 145 146for.cond.cleanup: 147 ret void 148} 149 150define void @test_dead_on_unwind(ptr noalias dead_on_unwind %a, i1 zeroext %y) uwtable { 151; CHECK-LABEL: @test_dead_on_unwind( 152; CHECK-NEXT: entry: 153; CHECK-NEXT: [[A_PROMOTED:%.*]] = load i32, ptr [[A:%.*]], align 4 154; CHECK-NEXT: br label [[FOR_BODY:%.*]] 155; CHECK: for.body: 156; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[A_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_INC:%.*]] ] 157; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_INC]] ] 158; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 159; CHECK-NEXT: br i1 [[Y:%.*]], label [[IF_THEN:%.*]], label [[FOR_INC]] 160; CHECK: if.then: 161; CHECK-NEXT: tail call void @f() 162; CHECK-NEXT: br label [[FOR_INC]] 163; CHECK: for.inc: 164; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_03]], 1 165; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 10000 166; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 167; CHECK: for.cond.cleanup: 168; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_INC]] ] 169; CHECK-NEXT: store i32 [[ADD_LCSSA]], ptr [[A]], align 4 170; CHECK-NEXT: ret void 171; 172entry: 173 br label %for.body 174 175for.body: 176 %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 177 %0 = load i32, ptr %a, align 4 178 %add = add nsw i32 %0, 1 179 store i32 %add, ptr %a, align 4 180 br i1 %y, label %if.then, label %for.inc 181 182if.then: 183 tail call void @f() 184 br label %for.inc 185 186for.inc: 187 %inc = add nuw nsw i32 %i.03, 1 188 %exitcond = icmp eq i32 %inc, 10000 189 br i1 %exitcond, label %for.cond.cleanup, label %for.body 190 191for.cond.cleanup: 192 ret void 193} 194 195;; We can promote if the load can be proven safe to speculate, and the 196;; store safe to sink, even if the the store *isn't* must execute. 197define void @test3(i1 zeroext %y) uwtable { 198; CHECK-LABEL: @test3( 199; CHECK-NEXT: entry: 200; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 201; CHECK-NEXT: [[A_PROMOTED:%.*]] = load i32, ptr [[A]], align 4 202; CHECK-NEXT: br label [[FOR_BODY:%.*]] 203; CHECK: for.body: 204; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[A_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 205; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 206; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 207; CHECK-NEXT: tail call void @f() 208; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_03]], 1 209; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 10000 210; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 211; CHECK: for.cond.cleanup: 212; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ] 213; CHECK-NEXT: store i32 [[ADD_LCSSA]], ptr [[A]], align 4 214; CHECK-NEXT: ret void 215; 216entry: 217 %a = alloca i32 218 br label %for.body 219 220for.body: 221 %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 222 %0 = load i32, ptr %a, align 4 223 %add = add nsw i32 %0, 1 224 tail call void @f() 225 store i32 %add, ptr %a, align 4 226 %inc = add nuw nsw i32 %i.03, 1 227 %exitcond = icmp eq i32 %inc, 10000 228 br i1 %exitcond, label %for.cond.cleanup, label %for.body 229 230for.cond.cleanup: 231 ret void 232} 233 234;; Same as test3, but with unordered atomics 235define void @test3b(i1 zeroext %y) uwtable { 236; CHECK-LABEL: @test3b( 237; CHECK-NEXT: entry: 238; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 239; CHECK-NEXT: [[A_PROMOTED:%.*]] = load atomic i32, ptr [[A]] unordered, align 4 240; CHECK-NEXT: br label [[FOR_BODY:%.*]] 241; CHECK: for.body: 242; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[A_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 243; CHECK-NEXT: [[I_03:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 244; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 245; CHECK-NEXT: tail call void @f() 246; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_03]], 1 247; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 10000 248; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 249; CHECK: for.cond.cleanup: 250; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ] 251; CHECK-NEXT: store atomic i32 [[ADD_LCSSA]], ptr [[A]] unordered, align 4 252; CHECK-NEXT: ret void 253; 254entry: 255 %a = alloca i32 256 br label %for.body 257 258for.body: 259 %i.03 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 260 %0 = load atomic i32, ptr %a unordered, align 4 261 %add = add nsw i32 %0, 1 262 tail call void @f() 263 store atomic i32 %add, ptr %a unordered, align 4 264 %inc = add nuw nsw i32 %i.03, 1 265 %exitcond = icmp eq i32 %inc, 10000 266 br i1 %exitcond, label %for.cond.cleanup, label %for.body 267 268for.cond.cleanup: 269 ret void 270} 271 272@_ZTIi = external constant ptr 273 274; In this test, the loop is within a try block. There is an explicit unwind edge out of the loop. 275; Make sure this edge is treated as a loop exit, and that the loads and stores are promoted as 276; expected 277define void @loop_within_tryblock() personality ptr @__gxx_personality_v0 { 278; CHECK-LABEL: @loop_within_tryblock( 279; CHECK-NEXT: entry: 280; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 281; CHECK-NEXT: store i32 0, ptr [[A]], align 4 282; CHECK-NEXT: [[A_PROMOTED:%.*]] = load i32, ptr [[A]], align 4 283; CHECK-NEXT: br label [[FOR_COND:%.*]] 284; CHECK: for.cond: 285; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[A_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_INC:%.*]] ] 286; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_INC]] ] 287; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 1024 288; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 289; CHECK: for.body: 290; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 291; CHECK-NEXT: invoke void @boo() 292; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 293; CHECK: invoke.cont: 294; CHECK-NEXT: br label [[FOR_INC]] 295; CHECK: for.inc: 296; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 1 297; CHECK-NEXT: br label [[FOR_COND]] 298; CHECK: lpad: 299; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ] 300; CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 301; CHECK-NEXT: catch ptr @_ZTIi 302; CHECK-NEXT: store i32 [[ADD_LCSSA]], ptr [[A]], align 4 303; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 304; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 305; CHECK-NEXT: br label [[CATCH_DISPATCH:%.*]] 306; CHECK: catch.dispatch: 307; CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) 308; CHECK-NEXT: [[MATCHES:%.*]] = icmp eq i32 [[TMP2]], [[TMP3]] 309; CHECK-NEXT: br i1 [[MATCHES]], label [[CATCH:%.*]], label [[EH_RESUME:%.*]] 310; CHECK: catch: 311; CHECK-NEXT: [[TMP4:%.*]] = call ptr @__cxa_begin_catch(ptr [[TMP1]]) 312; CHECK-NEXT: [[TMP5:%.*]] = load i32, ptr [[TMP4]], align 4 313; CHECK-NEXT: call void @__cxa_end_catch() 314; CHECK-NEXT: br label [[TRY_CONT:%.*]] 315; CHECK: try.cont: 316; CHECK-NEXT: ret void 317; CHECK: for.end: 318; CHECK-NEXT: [[ADD1_LCSSA:%.*]] = phi i32 [ [[ADD1]], [[FOR_COND]] ] 319; CHECK-NEXT: store i32 [[ADD1_LCSSA]], ptr [[A]], align 4 320; CHECK-NEXT: br label [[TRY_CONT]] 321; CHECK: eh.resume: 322; CHECK-NEXT: [[LPAD_VAL:%.*]] = insertvalue { ptr, i32 } undef, ptr [[TMP1]], 0 323; CHECK-NEXT: [[LPAD_VAL3:%.*]] = insertvalue { ptr, i32 } [[LPAD_VAL]], i32 [[TMP2]], 1 324; CHECK-NEXT: resume { ptr, i32 } [[LPAD_VAL3]] 325; 326entry: 327 %a = alloca i32, align 4 328 store i32 0, ptr %a, align 4 329 br label %for.cond 330 331for.cond: 332 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] 333 %cmp = icmp slt i32 %i.0, 1024 334 br i1 %cmp, label %for.body, label %for.end 335 336for.body: 337 %0 = load i32, ptr %a, align 4 338 %add = add nsw i32 %0, 1 339 store i32 %add, ptr %a, align 4 340 invoke void @boo() 341 to label %invoke.cont unwind label %lpad 342 343invoke.cont: 344 br label %for.inc 345 346for.inc: 347 %inc = add nsw i32 %i.0, 1 348 br label %for.cond 349 350lpad: 351 %1 = landingpad { ptr, i32 } 352 catch ptr @_ZTIi 353 %2 = extractvalue { ptr, i32 } %1, 0 354 %3 = extractvalue { ptr, i32 } %1, 1 355 br label %catch.dispatch 356 357catch.dispatch: 358 %4 = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi) #3 359 %matches = icmp eq i32 %3, %4 360 br i1 %matches, label %catch, label %eh.resume 361 362catch: 363 %5 = call ptr @__cxa_begin_catch(ptr %2) #3 364 %6 = load i32, ptr %5, align 4 365 call void @__cxa_end_catch() #3 366 br label %try.cont 367 368try.cont: 369 ret void 370 371for.end: 372 br label %try.cont 373 374eh.resume: 375 %lpad.val = insertvalue { ptr, i32 } undef, ptr %2, 0 376 %lpad.val3 = insertvalue { ptr, i32 } %lpad.val, i32 %3, 1 377 resume { ptr, i32 } %lpad.val3 378} 379 380 381; The malloc'ed memory is not capture and therefore promoted. 382define void @malloc_no_capture() #0 personality ptr @__gxx_personality_v0 { 383; CHECK-LABEL: @malloc_no_capture( 384; CHECK-NEXT: entry: 385; CHECK-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 4) 386; CHECK-NEXT: [[CALL_PROMOTED:%.*]] = load i32, ptr [[CALL]], align 4 387; CHECK-NEXT: br label [[FOR_BODY:%.*]] 388; CHECK: for.body: 389; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[CALL_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_LATCH:%.*]] ] 390; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_LATCH]] ] 391; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 392; CHECK-NEXT: br label [[FOR_CALL:%.*]] 393; CHECK: for.call: 394; CHECK-NEXT: invoke void @boo() 395; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 396; CHECK: invoke.cont: 397; CHECK-NEXT: br label [[FOR_LATCH]] 398; CHECK: for.latch: 399; CHECK-NEXT: [[INC]] = add i32 [[I_0]], 1 400; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 1024 401; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 402; CHECK: for.end: 403; CHECK-NEXT: [[ADD_LCSSA2:%.*]] = phi i32 [ [[ADD]], [[FOR_LATCH]] ] 404; CHECK-NEXT: store i32 [[ADD_LCSSA2]], ptr [[CALL]], align 4 405; CHECK-NEXT: br label [[FUN_RET:%.*]] 406; CHECK: lpad: 407; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_CALL]] ] 408; CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 409; CHECK-NEXT: catch ptr null 410; CHECK-NEXT: store i32 [[ADD_LCSSA]], ptr [[CALL]], align 4 411; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 412; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 413; CHECK-NEXT: br label [[CATCH:%.*]] 414; CHECK: catch: 415; CHECK-NEXT: [[TMP3:%.*]] = call ptr @__cxa_begin_catch(ptr [[TMP1]]) 416; CHECK-NEXT: call void @free(ptr [[CALL]]) 417; CHECK-NEXT: call void @__cxa_end_catch() 418; CHECK-NEXT: br label [[FUN_RET]] 419; CHECK: fun.ret: 420; CHECK-NEXT: ret void 421; 422entry: 423 %call = call ptr @malloc(i64 4) 424 br label %for.body 425 426for.body: 427 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.latch ] 428 %0 = load i32, ptr %call, align 4 429 %add = add nsw i32 %0, 1 430 store i32 %add, ptr %call, align 4 431 br label %for.call 432 433for.call: 434 invoke void @boo() 435 to label %invoke.cont unwind label %lpad 436 437invoke.cont: 438 br label %for.latch 439 440for.latch: 441 %inc = add i32 %i.0, 1 442 %cmp = icmp slt i32 %i.0, 1024 443 br i1 %cmp, label %for.body, label %for.end 444 445for.end: 446 br label %fun.ret 447 448lpad: 449 %1 = landingpad { ptr, i32 } 450 catch ptr null 451 %2 = extractvalue { ptr, i32 } %1, 0 452 %3 = extractvalue { ptr, i32 } %1, 1 453 br label %catch 454 455catch: 456 %4 = call ptr @__cxa_begin_catch(ptr %2) #4 457 call void @free(ptr %call) 458 call void @__cxa_end_catch() 459 br label %fun.ret 460 461fun.ret: 462 ret void 463} 464 465; The malloc'ed memory can be captured and therefore only loads can be promoted. 466define void @malloc_capture(ptr noalias %A) personality ptr @__gxx_personality_v0 { 467; CHECK-LABEL: @malloc_capture( 468; CHECK-NEXT: entry: 469; CHECK-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 4) 470; CHECK-NEXT: [[CALL_PROMOTED:%.*]] = load i32, ptr [[CALL]], align 4 471; CHECK-NEXT: br label [[FOR_BODY:%.*]] 472; CHECK: for.body: 473; CHECK-NEXT: [[ADD1:%.*]] = phi i32 [ [[CALL_PROMOTED]], [[ENTRY:%.*]] ], [ [[ADD:%.*]], [[FOR_LATCH:%.*]] ] 474; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[INC:%.*]], [[FOR_LATCH]] ] 475; CHECK-NEXT: [[ADD]] = add nsw i32 [[ADD1]], 1 476; CHECK-NEXT: store i32 [[ADD]], ptr [[CALL]], align 4 477; CHECK-NEXT: br label [[FOR_CALL:%.*]] 478; CHECK: for.call: 479; CHECK-NEXT: invoke void @boo_readnone() 480; CHECK-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]] 481; CHECK: invoke.cont: 482; CHECK-NEXT: br label [[FOR_LATCH]] 483; CHECK: for.latch: 484; CHECK-NEXT: store ptr [[CALL]], ptr [[A:%.*]], align 8 485; CHECK-NEXT: [[INC]] = add i32 [[I_0]], 1 486; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 1024 487; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 488; CHECK: for.end: 489; CHECK-NEXT: br label [[FUN_RET:%.*]] 490; CHECK: lpad: 491; CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } 492; CHECK-NEXT: catch ptr null 493; CHECK-NEXT: [[TMP1:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 0 494; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { ptr, i32 } [[TMP0]], 1 495; CHECK-NEXT: br label [[CATCH:%.*]] 496; CHECK: catch: 497; CHECK-NEXT: [[TMP3:%.*]] = call ptr @__cxa_begin_catch(ptr [[TMP1]]) 498; CHECK-NEXT: call void @free(ptr [[CALL]]) 499; CHECK-NEXT: call void @__cxa_end_catch() 500; CHECK-NEXT: br label [[FUN_RET]] 501; CHECK: fun.ret: 502; CHECK-NEXT: ret void 503; 504entry: 505 %call = call ptr @malloc(i64 4) 506 br label %for.body 507 508for.body: 509 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.latch ] 510 %0 = load i32, ptr %call, align 4 511 %add = add nsw i32 %0, 1 512 store i32 %add, ptr %call, align 4 513 br label %for.call 514 515for.call: 516 invoke void @boo_readnone() 517 to label %invoke.cont unwind label %lpad 518 519invoke.cont: 520 br label %for.latch 521 522for.latch: 523 store ptr %call, ptr %A 524 %inc = add i32 %i.0, 1 525 %cmp = icmp slt i32 %i.0, 1024 526 br i1 %cmp, label %for.body, label %for.end 527 528for.end: 529 br label %fun.ret 530 531lpad: 532 %1 = landingpad { ptr, i32 } 533 catch ptr null 534 %2 = extractvalue { ptr, i32 } %1, 0 535 %3 = extractvalue { ptr, i32 } %1, 1 536 br label %catch 537 538catch: 539 %4 = call ptr @__cxa_begin_catch(ptr %2) #4 540 call void @free(ptr %call) 541 call void @__cxa_end_catch() 542 br label %fun.ret 543 544fun.ret: 545 ret void 546} 547 548; Function Attrs: nounwind 549declare noalias ptr @malloc(i64) 550 551; Function Attrs: nounwind 552declare void @free(ptr nocapture) 553 554declare void @boo() 555 556; This is an artifical example, readnone functions by definition cannot unwind 557; exceptions by calling the C++ exception throwing methods 558; This function should only be used to test malloc_capture. 559declare void @boo_readnone() readnone 560 561declare i32 @__gxx_personality_v0(...) 562 563declare ptr @__cxa_begin_catch(ptr) 564 565declare void @__cxa_end_catch() 566 567declare i32 @llvm.eh.typeid.for.p0(ptr) 568 569declare void @f() uwtable 570