1; RUN: llc %s -o - -enable-shrink-wrap=true -disable-post-ra | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE 2; RUN: llc %s -o - -enable-shrink-wrap=false -disable-post-ra | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE 3target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 4target triple = "arm64-apple-ios" 5 6 7; Initial motivating example: Simple diamond with a call just on one side. 8; CHECK-LABEL: foo: 9; 10; Compare the arguments and jump to exit. 11; No prologue needed. 12; ENABLE: cmp w0, w1 13; ENABLE-NEXT: b.ge [[EXIT_LABEL:LBB[0-9_]+]] 14; 15; Prologue code. 16; CHECK: stp [[SAVE_SP:x[0-9]+]], [[CSR:x[0-9]+]], [sp, #-16]! 17; CHECK-NEXT: mov [[SAVE_SP]], sp 18; CHECK-NEXT: sub sp, sp, #16 19; 20; Compare the arguments and jump to exit. 21; After the prologue is set. 22; DISABLE: cmp w0, w1 23; DISABLE-NEXT: b.ge [[EXIT_LABEL:LBB[0-9_]+]] 24; 25; Store %a in the alloca. 26; CHECK: stur w0, {{\[}}[[SAVE_SP]], #-4] 27; Set the alloca address in the second argument. 28; CHECK-NEXT: sub x1, [[SAVE_SP]], #4 29; Set the first argument to zero. 30; CHECK-NEXT: mov w0, wzr 31; CHECK-NEXT: bl _doSomething 32; 33; Without shrink-wrapping, epilogue is in the exit block. 34; DISABLE: [[EXIT_LABEL]]: 35; Epilogue code. 36; CHECK-NEXT: mov sp, [[SAVE_SP]] 37; CHECK-NEXT: ldp [[SAVE_SP]], [[CSR]], [sp], #16 38; 39; With shrink-wrapping, exit block is a simple return. 40; ENABLE: [[EXIT_LABEL]]: 41; CHECK-NEXT: ret 42define i32 @foo(i32 %a, i32 %b) { 43 %tmp = alloca i32, align 4 44 %tmp2 = icmp slt i32 %a, %b 45 br i1 %tmp2, label %true, label %false 46 47true: 48 store i32 %a, i32* %tmp, align 4 49 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) 50 br label %false 51 52false: 53 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 54 ret i32 %tmp.0 55} 56 57; Function Attrs: optsize 58declare i32 @doSomething(i32, i32*) 59 60 61; Check that we do not perform the restore inside the loop whereas the save 62; is outside. 63; CHECK-LABEL: freqSaveAndRestoreOutsideLoop: 64; 65; Shrink-wrapping allows to skip the prologue in the else case. 66; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 67; 68; Prologue code. 69; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]! 70; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16] 71; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16 72; 73; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 74; 75; CHECK: mov [[SUM:w[0-9]+]], wzr 76; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa 77; 78; Next BB. 79; CHECK: [[LOOP:LBB[0-9_]+]]: ; %for.body 80; CHECK: bl _something 81; CHECK-NEXT: add [[SUM]], w0, [[SUM]] 82; CHECK-NEXT: sub [[IV]], [[IV]], #1 83; CHECK-NEXT: cbnz [[IV]], [[LOOP]] 84; 85; Next BB. 86; Copy SUM into the returned register + << 3. 87; CHECK: lsl w0, [[SUM]], #3 88; 89; Jump to epilogue. 90; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]] 91; 92; DISABLE: [[ELSE_LABEL]]: ; %if.else 93; Shift second argument by one and store into returned register. 94; DISABLE: lsl w0, w1, #1 95; DISABLE: [[EPILOG_BB]]: ; %if.end 96; 97; Epilogue code. 98; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16] 99; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32 100; CHECK-NEXT: ret 101; 102; ENABLE: [[ELSE_LABEL]]: ; %if.else 103; Shift second argument by one and store into returned register. 104; ENABLE: lsl w0, w1, #1 105; ENABLE: ret 106define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) { 107entry: 108 %tobool = icmp eq i32 %cond, 0 109 br i1 %tobool, label %if.else, label %for.body 110 111for.body: ; preds = %entry, %for.body 112 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 113 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %entry ] 114 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 115 %add = add nsw i32 %call, %sum.04 116 %inc = add nuw nsw i32 %i.05, 1 117 %exitcond = icmp eq i32 %inc, 10 118 br i1 %exitcond, label %for.end, label %for.body 119 120for.end: ; preds = %for.body 121 %shl = shl i32 %add, 3 122 br label %if.end 123 124if.else: ; preds = %entry 125 %mul = shl nsw i32 %N, 1 126 br label %if.end 127 128if.end: ; preds = %if.else, %for.end 129 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 130 ret i32 %sum.1 131} 132 133declare i32 @something(...) 134 135; Check that we do not perform the shrink-wrapping inside the loop even 136; though that would be legal. The cost model must prevent that. 137; CHECK-LABEL: freqSaveAndRestoreOutsideLoop2: 138; Prologue code. 139; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]! 140; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16] 141; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16 142; CHECK: mov [[SUM:w[0-9]+]], wzr 143; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa 144; Next BB. 145; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 146; CHECK: bl _something 147; CHECK-NEXT: add [[SUM]], w0, [[SUM]] 148; CHECK-NEXT: sub [[IV]], [[IV]], #1 149; CHECK-NEXT: cbnz [[IV]], [[LOOP_LABEL]] 150; Next BB. 151; CHECK: ; %for.end 152; CHECK: mov w0, [[SUM]] 153; CHECK-NEXT: ldp [[CSR3]], [[CSR4]], [sp, #16] 154; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32 155; CHECK-NEXT: ret 156define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) { 157entry: 158 br label %for.body 159 160for.body: ; preds = %for.body, %entry 161 %i.04 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 162 %sum.03 = phi i32 [ 0, %entry ], [ %add, %for.body ] 163 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 164 %add = add nsw i32 %call, %sum.03 165 %inc = add nuw nsw i32 %i.04, 1 166 %exitcond = icmp eq i32 %inc, 10 167 br i1 %exitcond, label %for.end, label %for.body 168 169for.end: ; preds = %for.body 170 ret i32 %add 171} 172 173; Check with a more complex case that we do not have save within the loop and 174; restore outside. 175; CHECK-LABEL: loopInfoSaveOutsideLoop: 176; 177; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 178; 179; Prologue code. 180; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]! 181; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16] 182; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16 183; 184; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 185; 186; CHECK: mov [[SUM:w[0-9]+]], wzr 187; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa 188; 189; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 190; CHECK: bl _something 191; CHECK-NEXT: add [[SUM]], w0, [[SUM]] 192; CHECK-NEXT: sub [[IV]], [[IV]], #1 193; CHECK-NEXT: cbnz [[IV]], [[LOOP_LABEL]] 194; Next BB. 195; CHECK: bl _somethingElse 196; CHECK-NEXT: lsl w0, [[SUM]], #3 197; 198; Jump to epilogue. 199; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]] 200; 201; DISABLE: [[ELSE_LABEL]]: ; %if.else 202; Shift second argument by one and store into returned register. 203; DISABLE: lsl w0, w1, #1 204; DISABLE: [[EPILOG_BB]]: ; %if.end 205; Epilogue code. 206; CHECK-NEXT: ldp [[CSR3]], [[CSR4]], [sp, #16] 207; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32 208; CHECK-NEXT: ret 209; 210; ENABLE: [[ELSE_LABEL]]: ; %if.else 211; Shift second argument by one and store into returned register. 212; ENABLE: lsl w0, w1, #1 213; ENABLE: ret 214define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) { 215entry: 216 %tobool = icmp eq i32 %cond, 0 217 br i1 %tobool, label %if.else, label %for.body 218 219for.body: ; preds = %entry, %for.body 220 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 221 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %entry ] 222 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 223 %add = add nsw i32 %call, %sum.04 224 %inc = add nuw nsw i32 %i.05, 1 225 %exitcond = icmp eq i32 %inc, 10 226 br i1 %exitcond, label %for.end, label %for.body 227 228for.end: ; preds = %for.body 229 tail call void bitcast (void (...)* @somethingElse to void ()*)() 230 %shl = shl i32 %add, 3 231 br label %if.end 232 233if.else: ; preds = %entry 234 %mul = shl nsw i32 %N, 1 235 br label %if.end 236 237if.end: ; preds = %if.else, %for.end 238 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 239 ret i32 %sum.1 240} 241 242declare void @somethingElse(...) 243 244; Check with a more complex case that we do not have restore within the loop and 245; save outside. 246; CHECK-LABEL: loopInfoRestoreOutsideLoop: 247; 248; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 249; 250; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]! 251; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16] 252; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16 253; 254; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 255; 256; CHECK: bl _somethingElse 257; CHECK-NEXT: mov [[SUM:w[0-9]+]], wzr 258; CHECK-NEXT: movz [[IV:w[0-9]+]], #0xa 259; 260; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 261; CHECK: bl _something 262; CHECK-NEXT: add [[SUM]], w0, [[SUM]] 263; CHECK-NEXT: sub [[IV]], [[IV]], #1 264; CHECK-NEXT: cbnz [[IV]], [[LOOP_LABEL]] 265; Next BB. 266; CHECK: lsl w0, [[SUM]], #3 267; 268; Jump to epilogue. 269; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]] 270; 271; DISABLE: [[ELSE_LABEL]]: ; %if.else 272; Shift second argument by one and store into returned register. 273; DISABLE: lsl w0, w1, #1 274; DISABLE: [[EPILOG_BB]]: ; %if.end 275; Epilogue code. 276; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16] 277; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32 278; CHECK-NEXT: ret 279; 280; ENABLE: [[ELSE_LABEL]]: ; %if.else 281; Shift second argument by one and store into returned register. 282; ENABLE: lsl w0, w1, #1 283; ENABLE: ret 284define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 { 285entry: 286 %tobool = icmp eq i32 %cond, 0 287 br i1 %tobool, label %if.else, label %if.then 288 289if.then: ; preds = %entry 290 tail call void bitcast (void (...)* @somethingElse to void ()*)() 291 br label %for.body 292 293for.body: ; preds = %for.body, %if.then 294 %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ] 295 %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 296 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 297 %add = add nsw i32 %call, %sum.04 298 %inc = add nuw nsw i32 %i.05, 1 299 %exitcond = icmp eq i32 %inc, 10 300 br i1 %exitcond, label %for.end, label %for.body 301 302for.end: ; preds = %for.body 303 %shl = shl i32 %add, 3 304 br label %if.end 305 306if.else: ; preds = %entry 307 %mul = shl nsw i32 %N, 1 308 br label %if.end 309 310if.end: ; preds = %if.else, %for.end 311 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 312 ret i32 %sum.1 313} 314 315; Check that we handle function with no frame information correctly. 316; CHECK-LABEL: emptyFrame: 317; CHECK: ; %entry 318; CHECK-NEXT: mov w0, wzr 319; CHECK-NEXT: ret 320define i32 @emptyFrame() { 321entry: 322 ret i32 0 323} 324 325; Check that we handle variadic function correctly. 326; CHECK-LABEL: variadicFunc: 327; 328; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 329; 330; Prologue code. 331; CHECK: sub sp, sp, #16 332; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 333; 334; Sum is merged with the returned register. 335; CHECK: mov [[SUM:w0]], wzr 336; CHECK-NEXT: add [[VA_BASE:x[0-9]+]], sp, #16 337; CHECK-NEXT: str [[VA_BASE]], [sp, #8] 338; CHECK-NEXT: cmp w1, #1 339; CHECK-NEXT: b.lt [[IFEND_LABEL:LBB[0-9_]+]] 340; 341; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 342; CHECK: ldr [[VA_ADDR:x[0-9]+]], [sp, #8] 343; CHECK-NEXT: add [[NEXT_VA_ADDR:x[0-9]+]], [[VA_ADDR]], #8 344; CHECK-NEXT: str [[NEXT_VA_ADDR]], [sp, #8] 345; CHECK-NEXT: ldr [[VA_VAL:w[0-9]+]], {{\[}}[[VA_ADDR]]] 346; CHECK-NEXT: add [[SUM]], [[SUM]], [[VA_VAL]] 347; CHECK-NEXT: sub w1, w1, #1 348; CHECK-NEXT: cbnz w1, [[LOOP_LABEL]] 349; 350; DISABLE-NEXT: b [[IFEND_LABEL]] 351; DISABLE: [[ELSE_LABEL]]: ; %if.else 352; DISABLE: lsl w0, w1, #1 353; 354; CHECK: [[IFEND_LABEL]]: 355; Epilogue code. 356; CHECK: add sp, sp, #16 357; CHECK-NEXT: ret 358; 359; ENABLE: [[ELSE_LABEL]]: ; %if.else 360; ENABLE: lsl w0, w1, #1 361; ENABLE-NEXT: ret 362define i32 @variadicFunc(i32 %cond, i32 %count, ...) #0 { 363entry: 364 %ap = alloca i8*, align 8 365 %tobool = icmp eq i32 %cond, 0 366 br i1 %tobool, label %if.else, label %if.then 367 368if.then: ; preds = %entry 369 %ap1 = bitcast i8** %ap to i8* 370 call void @llvm.va_start(i8* %ap1) 371 %cmp6 = icmp sgt i32 %count, 0 372 br i1 %cmp6, label %for.body, label %for.end 373 374for.body: ; preds = %if.then, %for.body 375 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %if.then ] 376 %sum.07 = phi i32 [ %add, %for.body ], [ 0, %if.then ] 377 %0 = va_arg i8** %ap, i32 378 %add = add nsw i32 %sum.07, %0 379 %inc = add nuw nsw i32 %i.08, 1 380 %exitcond = icmp eq i32 %inc, %count 381 br i1 %exitcond, label %for.end, label %for.body 382 383for.end: ; preds = %for.body, %if.then 384 %sum.0.lcssa = phi i32 [ 0, %if.then ], [ %add, %for.body ] 385 call void @llvm.va_end(i8* %ap1) 386 br label %if.end 387 388if.else: ; preds = %entry 389 %mul = shl nsw i32 %count, 1 390 br label %if.end 391 392if.end: ; preds = %if.else, %for.end 393 %sum.1 = phi i32 [ %sum.0.lcssa, %for.end ], [ %mul, %if.else ] 394 ret i32 %sum.1 395} 396 397declare void @llvm.va_start(i8*) 398 399declare void @llvm.va_end(i8*) 400 401; Check that we handle inline asm correctly. 402; CHECK-LABEL: inlineAsm: 403; 404; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 405; 406; Prologue code. 407; Make sure we save the CSR used in the inline asm: x19. 408; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x19]], [sp, #-16]! 409; 410; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 411; 412; CHECK: movz [[IV:w[0-9]+]], #0xa 413; 414; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 415; Inline asm statement. 416; CHECK: add x19, x19, #1 417; CHECK: sub [[IV]], [[IV]], #1 418; CHECK-NEXT: cbnz [[IV]], [[LOOP_LABEL]] 419; Next BB. 420; CHECK: mov w0, wzr 421; Epilogue code. 422; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16 423; CHECK-NEXT: ret 424; Next BB. 425; CHECK: [[ELSE_LABEL]]: ; %if.else 426; CHECK-NEXT: lsl w0, w1, #1 427; Epilogue code. 428; DISABLE-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16 429; CHECK-NEXT: ret 430define i32 @inlineAsm(i32 %cond, i32 %N) { 431entry: 432 %tobool = icmp eq i32 %cond, 0 433 br i1 %tobool, label %if.else, label %for.body 434 435for.body: ; preds = %entry, %for.body 436 %i.03 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 437 tail call void asm sideeffect "add x19, x19, #1", "~{x19}"() 438 %inc = add nuw nsw i32 %i.03, 1 439 %exitcond = icmp eq i32 %inc, 10 440 br i1 %exitcond, label %if.end, label %for.body 441 442if.else: ; preds = %entry 443 %mul = shl nsw i32 %N, 1 444 br label %if.end 445 446if.end: ; preds = %for.body, %if.else 447 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.body ] 448 ret i32 %sum.0 449} 450 451; Check that we handle calls to variadic functions correctly. 452; CHECK-LABEL: callVariadicFunc: 453; 454; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 455; 456; Prologue code. 457; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-16]! 458; CHECK-NEXT: mov [[NEW_SP:x[0-9]+]], sp 459; CHECK-NEXT: sub sp, sp, #48 460; 461; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 462; Setup of the varags. 463; CHECK: stp x1, x1, [sp, #32] 464; CHECK-NEXT: stp x1, x1, [sp, #16] 465; CHECK-NEXT: stp x1, x1, [sp] 466; CHECK-NEXT: mov w0, w1 467; CHECK-NEXT: bl _someVariadicFunc 468; CHECK-NEXT: lsl w0, w0, #3 469; 470; DISABLE: b [[IFEND_LABEL:LBB[0-9_]+]] 471; DISABLE: [[ELSE_LABEL]]: ; %if.else 472; DISABLE-NEXT: lsl w0, w1, #1 473; DISABLE: [[IFEND_LABEL]]: ; %if.end 474; 475; Epilogue code. 476; CHECK: mov sp, [[NEW_SP]] 477; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16 478; CHECK-NEXT: ret 479; 480; ENABLE: [[ELSE_LABEL]]: ; %if.else 481; ENABLE-NEXT: lsl w0, w1, #1 482; ENABLE-NEXT: ret 483define i32 @callVariadicFunc(i32 %cond, i32 %N) { 484entry: 485 %tobool = icmp eq i32 %cond, 0 486 br i1 %tobool, label %if.else, label %if.then 487 488if.then: ; preds = %entry 489 %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N) 490 %shl = shl i32 %call, 3 491 br label %if.end 492 493if.else: ; preds = %entry 494 %mul = shl nsw i32 %N, 1 495 br label %if.end 496 497if.end: ; preds = %if.else, %if.then 498 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ] 499 ret i32 %sum.0 500} 501 502declare i32 @someVariadicFunc(i32, ...) 503 504; Make sure we do not insert unreachable code after noreturn function. 505; Although this is not incorrect to insert such code, it is useless 506; and it hurts the binary size. 507; 508; CHECK-LABEL: noreturn: 509; DISABLE: stp 510; 511; CHECK: and [[TEST:w[0-9]+]], w0, #0xff 512; CHECK-NEXT: cbnz [[TEST]], [[ABORT:LBB[0-9_]+]] 513; 514; CHECK: movz w0, #0x2a 515; 516; DISABLE-NEXT: ldp 517; 518; CHECK-NEXT: ret 519; 520; CHECK: [[ABORT]]: ; %if.abort 521; 522; ENABLE: stp 523; 524; CHECK: bl _abort 525; ENABLE-NOT: ldp 526define i32 @noreturn(i8 signext %bad_thing) { 527entry: 528 %tobool = icmp eq i8 %bad_thing, 0 529 br i1 %tobool, label %if.end, label %if.abort 530 531if.abort: 532 tail call void @abort() #0 533 unreachable 534 535if.end: 536 ret i32 42 537} 538 539declare void @abort() #0 540 541attributes #0 = { noreturn nounwind } 542 543; Make sure that we handle infinite loops properly When checking that the Save 544; and Restore blocks are control flow equivalent, the loop searches for the 545; immediate (post) dominator for the (restore) save blocks. When either the Save 546; or Restore block is located in an infinite loop the only immediate (post) 547; dominator is itself. In this case, we cannot perform shrink wrapping, but we 548; should return gracefully and continue compilation. 549; The only condition for this test is the compilation finishes correctly. 550; 551; CHECK-LABEL: infiniteloop 552; CHECK: ret 553define void @infiniteloop() { 554entry: 555 br i1 undef, label %if.then, label %if.end 556 557if.then: 558 %ptr = alloca i32, i32 4 559 br label %for.body 560 561for.body: ; preds = %for.body, %entry 562 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 563 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 564 %add = add nsw i32 %call, %sum.03 565 store i32 %add, i32* %ptr 566 br label %for.body 567 568if.end: 569 ret void 570} 571 572; Another infinite loop test this time with a body bigger than just one block. 573; CHECK-LABEL: infiniteloop2 574; CHECK: ret 575define void @infiniteloop2() { 576entry: 577 br i1 undef, label %if.then, label %if.end 578 579if.then: 580 %ptr = alloca i32, i32 4 581 br label %for.body 582 583for.body: ; preds = %for.body, %entry 584 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2] 585 %call = tail call i32 asm "mov $0, #0", "=r,~{x19}"() 586 %add = add nsw i32 %call, %sum.03 587 store i32 %add, i32* %ptr 588 br i1 undef, label %body1, label %body2 589 590body1: 591 tail call void asm sideeffect "nop", "~{x19}"() 592 br label %for.body 593 594body2: 595 tail call void asm sideeffect "nop", "~{x19}"() 596 br label %for.body 597 598if.end: 599 ret void 600} 601 602; Another infinite loop test this time with two nested infinite loop. 603; CHECK-LABEL: infiniteloop3 604; CHECK: ret 605define void @infiniteloop3() { 606entry: 607 br i1 undef, label %loop2a, label %body 608 609body: ; preds = %entry 610 br i1 undef, label %loop2a, label %end 611 612loop1: ; preds = %loop2a, %loop2b 613 %var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ] 614 %next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ] 615 %0 = icmp eq i32* %var, null 616 %next.load = load i32*, i32** undef 617 br i1 %0, label %loop2a, label %loop2b 618 619loop2a: ; preds = %loop1, %body, %entry 620 %var = phi i32* [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ] 621 %next.var = phi i32* [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ] 622 br label %loop1 623 624loop2b: ; preds = %loop1 625 %gep1 = bitcast i32* %var.phi to i32* 626 %next.ptr = bitcast i32* %gep1 to i32** 627 store i32* %next.phi, i32** %next.ptr 628 br label %loop1 629 630end: 631 ret void 632} 633