1; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -mtriple=armv7-apple-ios \ 2; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=ARM --check-prefix=ENABLE --check-prefix=ARM-ENABLE 3; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -mtriple=armv7-apple-ios \ 4; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=ARM --check-prefix=DISABLE --check-prefix=ARM-DISABLE 5; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -mtriple=thumbv7-apple-ios \ 6; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB --check-prefix=ENABLE --check-prefix=THUMB-ENABLE 7; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -mtriple=thumbv7-apple-ios \ 8; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=THUMB --check-prefix=DISABLE --check-prefix=THUMB-DISABLE 9 10; 11; Note: Lots of tests use inline asm instead of regular calls. 12; This allows to have a better control on what the allocation will do. 13; Otherwise, we may have spill right in the entry block, defeating 14; shrink-wrapping. Moreover, some of the inline asm statements (nop) 15; are here to ensure that the related paths do not end up as critical 16; edges. 17; Also disable the late if-converter as it makes harder to reason on 18; the diffs. 19 20; Initial motivating example: Simple diamond with a call just on one side. 21; CHECK-LABEL: foo: 22; 23; Compare the arguments and jump to exit. 24; No prologue needed. 25; ENABLE: cmp r0, r1 26; ENABLE-NEXT: bge [[EXIT_LABEL:LBB[0-9_]+]] 27; 28; Prologue code. 29; CHECK: push {r7, lr} 30; CHECK-NEXT: mov r7, sp 31;; 32; Compare the arguments and jump to exit. 33; After the prologue is set. 34; DISABLE: sub sp 35; DISABLE: cmp r0, r1 36; DISABLE-NEXT: bge [[EXIT_LABEL:LBB[0-9_]+]] 37; 38; Store %a in the alloca. 39; ARM-ENABLE: push {r0} 40; THUMB-ENABLE: str r0, [sp, #-4] 41; DISABLE: str r0, [sp] 42; Set the alloca address in the second argument. 43; CHECK-NEXT: mov r1, sp 44; Set the first argument to zero. 45; CHECK-NEXT: mov{{s?}} r0, #0 46; CHECK-NEXT: bl{{x?}} _doSomething 47; 48; With shrink-wrapping, epilogue is just after the call. 49; ARM-ENABLE-NEXT: mov sp, r7 50; THUMB-ENABLE-NEXT: add sp, #4 51; ENABLE-NEXT: pop{{(\.w)?}} {r7, lr} 52; 53; CHECK: [[EXIT_LABEL]]: 54; 55; Without shrink-wrapping, epilogue is in the exit block. 56; Epilogue code. (What we pop does not matter.) 57; ARM-DISABLE: mov sp, r7 58; THUMB-DISABLE: add sp, 59; DISABLE-NEXT: pop {r7, pc} 60; 61; ENABLE-NEXT: bx lr 62define i32 @foo(i32 %a, i32 %b) { 63 %tmp = alloca i32, align 4 64 %tmp2 = icmp slt i32 %a, %b 65 br i1 %tmp2, label %true, label %false 66 67true: 68 store i32 %a, i32* %tmp, align 4 69 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) 70 br label %false 71 72false: 73 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 74 ret i32 %tmp.0 75} 76 77; Function Attrs: optsize 78declare i32 @doSomething(i32, i32*) 79 80 81; Check that we do not perform the restore inside the loop whereas the save 82; is outside. 83; CHECK-LABEL: freqSaveAndRestoreOutsideLoop: 84; 85; Shrink-wrapping allows to skip the prologue in the else case. 86; ARM-ENABLE: cmp r0, #0 87; ARM-ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 88; THUMB-ENABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 89; 90; Prologue code. 91; Make sure we save the CSR used in the inline asm: r4. 92; CHECK: push {r4, r7, lr} 93; CHECK-NEXT: add r7, sp, #4 94; 95; ARM-DISABLE: cmp r0, #0 96; ARM-DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 97; THUMB-DISABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 98; 99; SUM is in r0 because it is coalesced with the second 100; argument on the else path. 101; CHECK: mov{{s?}} [[SUM:r0]], #0 102; CHECK-NEXT: mov{{s?}} [[IV:r[0-9]+]], #10 103; 104; Next BB. 105; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body 106; CHECK: mov{{(\.w)?}} [[TMP:r[0-9]+]], #1 107; ARM: subs [[IV]], [[IV]], #1 108; THUMB: subs [[IV]], #1 109; ARM-NEXT: add [[SUM]], [[TMP]], [[SUM]] 110; THUMB-NEXT: add [[SUM]], [[TMP]] 111; CHECK-NEXT: bne [[LOOP]] 112; 113; Next BB. 114; SUM << 3. 115; CHECK: lsl{{s?}} [[SUM]], [[SUM]], #3 116; ENABLE-NEXT: pop {r4, r7, pc} 117; 118; Duplicated epilogue. 119; DISABLE: pop {r4, r7, pc} 120; 121; CHECK: [[ELSE_LABEL]]: @ %if.else 122; Shift second argument by one and store into returned register. 123; CHECK: lsl{{s?}} r0, r1, #1 124; DISABLE-NEXT: pop {r4, r7, pc} 125; 126; ENABLE-NEXT: bx lr 127define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) { 128entry: 129 %tobool = icmp eq i32 %cond, 0 130 br i1 %tobool, label %if.else, label %for.preheader 131 132for.preheader: 133 tail call void asm "nop", ""() 134 br label %for.body 135 136for.body: ; preds = %entry, %for.body 137 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 138 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] 139 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 140 %add = add nsw i32 %call, %sum.04 141 %inc = add nuw nsw i32 %i.05, 1 142 %exitcond = icmp eq i32 %inc, 10 143 br i1 %exitcond, label %for.end, label %for.body 144 145for.end: ; preds = %for.body 146 %shl = shl i32 %add, 3 147 br label %if.end 148 149if.else: ; preds = %entry 150 %mul = shl nsw i32 %N, 1 151 br label %if.end 152 153if.end: ; preds = %if.else, %for.end 154 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 155 ret i32 %sum.1 156} 157 158declare i32 @something(...) 159 160; Check that we do not perform the shrink-wrapping inside the loop even 161; though that would be legal. The cost model must prevent that. 162; CHECK-LABEL: freqSaveAndRestoreOutsideLoop2: 163; Prologue code. 164; Make sure we save the CSR used in the inline asm: r4. 165; CHECK: push {r4 166; CHECK: mov{{s?}} [[SUM:r0]], #0 167; CHECK-NEXT: mov{{s?}} [[IV:r[0-9]+]], #10 168; CHECK: nop 169; Next BB. 170; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: @ %for.body 171; CHECK: mov{{(\.w)?}} [[TMP:r[0-9]+]], #1 172; ARM: subs [[IV]], [[IV]], #1 173; THUMB: subs [[IV]], #1 174; ARM: add [[SUM]], [[TMP]], [[SUM]] 175; THUMB: add [[SUM]], [[TMP]] 176; CHECK-NEXT: bne [[LOOP_LABEL]] 177; Next BB. 178; CHECK: @ %for.exit 179; CHECK: nop 180; CHECK: pop {r4 181define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) { 182entry: 183 br label %for.preheader 184 185for.preheader: 186 tail call void asm "nop", ""() 187 br label %for.body 188 189for.body: ; preds = %for.body, %entry 190 %i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ] 191 %sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ] 192 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 193 %add = add nsw i32 %call, %sum.03 194 %inc = add nuw nsw i32 %i.04, 1 195 %exitcond = icmp eq i32 %inc, 10 196 br i1 %exitcond, label %for.exit, label %for.body 197 198for.exit: 199 tail call void asm "nop", ""() 200 br label %for.end 201 202for.end: ; preds = %for.body 203 ret i32 %add 204} 205 206; Check with a more complex case that we do not have save within the loop and 207; restore outside. 208; CHECK-LABEL: loopInfoSaveOutsideLoop: 209; 210; ARM-ENABLE: cmp r0, #0 211; ARM-ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 212; THUMB-ENABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 213; 214; Prologue code. 215; Make sure we save the CSR used in the inline asm: r4. 216; CHECK: push {r4, r7, lr} 217; CHECK-NEXT: add r7, sp, #4 218; 219; ARM-DISABLE: cmp r0, #0 220; ARM-DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 221; THUMB-DISABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 222; 223; SUM is in r0 because it is coalesced with the second 224; argument on the else path. 225; CHECK: mov{{s?}} [[SUM:r0]], #0 226; CHECK-NEXT: mov{{s?}} [[IV:r[0-9]+]], #10 227; 228; Next BB. 229; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body 230; CHECK: mov{{(\.w)?}} [[TMP:r[0-9]+]], #1 231; ARM: subs [[IV]], [[IV]], #1 232; THUMB: subs [[IV]], #1 233; ARM-NEXT: add [[SUM]], [[TMP]], [[SUM]] 234; THUMB-NEXT: add [[SUM]], [[TMP]] 235; CHECK-NEXT: bne [[LOOP]] 236; 237; Next BB. 238; SUM << 3. 239; CHECK: lsl{{s?}} [[SUM]], [[SUM]], #3 240; ENABLE: pop {r4, r7, pc} 241; 242; Duplicated epilogue. 243; DISABLE: pop {r4, r7, pc} 244; 245; CHECK: [[ELSE_LABEL]]: @ %if.else 246; Shift second argument by one and store into returned register. 247; CHECK: lsl{{s?}} r0, r1, #1 248; DISABLE-NEXT: pop {r4, r7, pc} 249; 250; ENABLE-NEXT: bx lr 251define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) { 252entry: 253 %tobool = icmp eq i32 %cond, 0 254 br i1 %tobool, label %if.else, label %for.preheader 255 256for.preheader: 257 tail call void asm "nop", ""() 258 br label %for.body 259 260for.body: ; preds = %entry, %for.body 261 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 262 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] 263 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 264 %add = add nsw i32 %call, %sum.04 265 %inc = add nuw nsw i32 %i.05, 1 266 %exitcond = icmp eq i32 %inc, 10 267 br i1 %exitcond, label %for.end, label %for.body 268 269for.end: ; preds = %for.body 270 tail call void asm "nop", "~{r4}"() 271 %shl = shl i32 %add, 3 272 br label %if.end 273 274if.else: ; preds = %entry 275 %mul = shl nsw i32 %N, 1 276 br label %if.end 277 278if.end: ; preds = %if.else, %for.end 279 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 280 ret i32 %sum.1 281} 282 283declare void @somethingElse(...) 284 285; Check with a more complex case that we do not have restore within the loop and 286; save outside. 287; CHECK-LABEL: loopInfoRestoreOutsideLoop: 288; 289; ARM-ENABLE: cmp r0, #0 290; ARM-ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 291; THUMB-ENABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 292; 293; Prologue code. 294; Make sure we save the CSR used in the inline asm: r4. 295; CHECK: push {r4, r7, lr} 296; CHECK-NEXT: add r7, sp, #4 297; 298; ARM-DISABLE: cmp r0, #0 299; ARM-DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 300; THUMB-DISABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 301; 302; SUM is in r0 because it is coalesced with the second 303; argument on the else path. 304; CHECK: mov{{s?}} [[SUM:r0]], #0 305; CHECK-NEXT: mov{{s?}} [[IV:r[0-9]+]], #10 306; 307; Next BB. 308; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body 309; CHECK: mov{{(\.w)?}} [[TMP:r[0-9]+]], #1 310; ARM: subs [[IV]], [[IV]], #1 311; THUMB: subs [[IV]], #1 312; ARM-NEXT: add [[SUM]], [[TMP]], [[SUM]] 313; THUMB-NEXT: add [[SUM]], [[TMP]] 314; CHECK-NEXT: bne [[LOOP]] 315; 316; Next BB. 317; SUM << 3. 318; CHECK: lsl{{s?}} [[SUM]], [[SUM]], #3 319; ENABLE-NEXT: pop {r4, r7, pc} 320; 321; Duplicated epilogue. 322; DISABLE: pop {r4, r7, pc} 323; 324; CHECK: [[ELSE_LABEL]]: @ %if.else 325; Shift second argument by one and store into returned register. 326; CHECK: lsl{{s?}} r0, r1, #1 327; DISABLE-NEXT: pop {r4, r7, pc} 328; 329; ENABLE-NEXT: bx lr 330define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 { 331entry: 332 %tobool = icmp eq i32 %cond, 0 333 br i1 %tobool, label %if.else, label %if.then 334 335if.then: ; preds = %entry 336 tail call void asm "nop", "~{r4}"() 337 br label %for.body 338 339for.body: ; preds = %for.body, %if.then 340 %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ] 341 %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 342 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 343 %add = add nsw i32 %call, %sum.04 344 %inc = add nuw nsw i32 %i.05, 1 345 %exitcond = icmp eq i32 %inc, 10 346 br i1 %exitcond, label %for.end, label %for.body 347 348for.end: ; preds = %for.body 349 %shl = shl i32 %add, 3 350 br label %if.end 351 352if.else: ; preds = %entry 353 %mul = shl nsw i32 %N, 1 354 br label %if.end 355 356if.end: ; preds = %if.else, %for.end 357 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 358 ret i32 %sum.1 359} 360 361; Check that we handle function with no frame information correctly. 362; CHECK-LABEL: emptyFrame: 363; CHECK: @ %entry 364; CHECK-NEXT: mov{{s?}} r0, #0 365; CHECK-NEXT: bx lr 366define i32 @emptyFrame() { 367entry: 368 ret i32 0 369} 370 371; Check that we handle inline asm correctly. 372; CHECK-LABEL: inlineAsm: 373; 374; ARM-ENABLE: cmp r0, #0 375; ARM-ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 376; THUMB-ENABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 377; 378; Prologue code. 379; Make sure we save the CSR used in the inline asm: r4. 380; CHECK: push {r4, r7, lr} 381; CHECK-NEXT: add r7, sp, #4 382; 383; ARM-DISABLE: cmp r0, #0 384; ARM-DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 385; THUMB-DISABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 386; 387; CHECK: mov{{s?}} [[IV:r[0-9]+]], #10 388; 389; Next BB. 390; CHECK: [[LOOP:LBB[0-9_]+]]: @ %for.body 391; ARM: subs [[IV]], [[IV]], #1 392; THUMB: subs [[IV]], #1 393; CHECK: add{{(\.w)?}} r4, r4, #1 394; CHECK: bne [[LOOP]] 395; 396; Next BB. 397; CHECK: mov{{s?}} r0, #0 398; 399; Duplicated epilogue. 400; DISABLE: pop {r4, r7, pc} 401; 402; CHECK: [[ELSE_LABEL]]: @ %if.else 403; Shift second argument by one and store into returned register. 404; CHECK: lsl{{s?}} r0, r1, #1 405; DISABLE-NEXT: pop {r4, r7, pc} 406; 407; ENABLE-NEXT: bx lr 408define i32 @inlineAsm(i32 %cond, i32 %N) { 409entry: 410 %tobool = icmp eq i32 %cond, 0 411 br i1 %tobool, label %if.else, label %for.preheader 412 413for.preheader: 414 tail call void asm "nop", ""() 415 br label %for.body 416 417for.body: ; preds = %entry, %for.body 418 %i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 419 tail call void asm sideeffect "add r4, #1", "~{r4}"() 420 %inc = add nuw nsw i32 %i.03, 1 421 %exitcond = icmp eq i32 %inc, 10 422 br i1 %exitcond, label %for.exit, label %for.body 423 424for.exit: 425 tail call void asm "nop", ""() 426 br label %if.end 427 428if.else: ; preds = %entry 429 %mul = shl nsw i32 %N, 1 430 br label %if.end 431 432if.end: ; preds = %for.body, %if.else 433 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.exit ] 434 ret i32 %sum.0 435} 436 437; Check that we handle calls to variadic functions correctly. 438; CHECK-LABEL: callVariadicFunc: 439; 440; ARM-ENABLE: cmp r0, #0 441; ARM-ENABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 442; THUMB-ENABLE: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 443; 444; Prologue code. 445; CHECK: push {r7, lr} 446; CHECK-NEXT: mov r7, sp 447; CHECK-NEXT: sub sp, {{(sp, )?}}#12 448; 449; ARM-DISABLE: cmp r0, #0 450; ARM-DISABLE-NEXT: beq [[ELSE_LABEL:LBB[0-9_]+]] 451; THUMB-DISABLE-NEXT: cbz r0, [[ELSE_LABEL:LBB[0-9_]+]] 452; 453; Setup of the varags. 454; CHECK: mov r0, r1 455; CHECK-NEXT: mov r2, r1 456; CHECK-NEXT: mov r3, r1 457; ARM-NEXT: str r1, [sp] 458; ARM-NEXT: str r1, [sp, #4] 459; THUMB-NEXT: strd r1, r1, [sp] 460; CHECK-NEXT: str r1, [sp, #8] 461; CHECK-NEXT: bl{{x?}} _someVariadicFunc 462; CHECK-NEXT: lsl{{s?}} r0, r0, #3 463; ARM-NEXT: mov sp, r7 464; THUMB-NEXT: add sp, #12 465; CHECK-NEXT: pop {r7, pc} 466; 467; CHECK: [[ELSE_LABEL]]: @ %if.else 468; Shift second argument by one and store into returned register. 469; CHECK: lsl{{s?}} r0, r1, #1 470; 471; Epilogue code. 472; ENABLE-NEXT: bx lr 473; 474; ARM-DISABLE-NEXT: mov sp, r7 475; THUMB-DISABLE-NEXT: add sp, #12 476; DISABLE-NEXT: pop {r7, pc} 477define i32 @callVariadicFunc(i32 %cond, i32 %N) { 478entry: 479 %tobool = icmp eq i32 %cond, 0 480 br i1 %tobool, label %if.else, label %if.then 481 482if.then: ; preds = %entry 483 %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N) 484 %shl = shl i32 %call, 3 485 br label %if.end 486 487if.else: ; preds = %entry 488 %mul = shl nsw i32 %N, 1 489 br label %if.end 490 491if.end: ; preds = %if.else, %if.then 492 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ] 493 ret i32 %sum.0 494} 495 496declare i32 @someVariadicFunc(i32, ...) 497 498; Make sure we do not insert unreachable code after noreturn function. 499; Although this is not incorrect to insert such code, it is useless 500; and it hurts the binary size. 501; 502; CHECK-LABEL: noreturn: 503; DISABLE: push 504; 505; CHECK: tst{{(\.w)?}} r0, #255 506; CHECK-NEXT: bne [[ABORT:LBB[0-9_]+]] 507; 508; CHECK: mov{{s?}} r0, #42 509; 510; ENABLE-NEXT: bx lr 511; 512; DISABLE-NEXT: pop 513;; 514; CHECK: [[ABORT]]: @ %if.abort 515; 516; ENABLE: push 517; 518; CHECK: bl{{x?}} _abort 519; ENABLE-NOT: pop 520define i32 @noreturn(i8 signext %bad_thing) { 521entry: 522 %tobool = icmp eq i8 %bad_thing, 0 523 br i1 %tobool, label %if.end, label %if.abort 524 525if.abort: 526 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 527 tail call void @abort() #0 528 unreachable 529 530if.end: 531 ret i32 42 532} 533 534declare void @abort() #0 535 536attributes #0 = { noreturn nounwind } 537 538; Make sure that we handle infinite loops properly When checking that the Save 539; and Restore blocks are control flow equivalent, the loop searches for the 540; immediate (post) dominator for the (restore) save blocks. When either the Save 541; or Restore block is located in an infinite loop the only immediate (post) 542; dominator is itself. In this case, we cannot perform shrink wrapping, but we 543; should return gracefully and continue compilation. 544; The only condition for this test is the compilation finishes correctly. 545; CHECK-LABEL: infiniteloop 546; CHECK: pop 547define void @infiniteloop() { 548entry: 549 br i1 undef, label %if.then, label %if.end 550 551if.then: 552 %ptr = alloca i32, i32 4 553 br label %for.body 554 555for.body: ; preds = %for.body, %entry 556 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 557 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 558 %add = add nsw i32 %call, %sum.03 559 store i32 %add, i32* %ptr 560 br label %for.body 561 562if.end: 563 ret void 564} 565 566; Another infinite loop test this time with a body bigger than just one block. 567; CHECK-LABEL: infiniteloop2 568; CHECK: pop 569define void @infiniteloop2() { 570entry: 571 br i1 undef, label %if.then, label %if.end 572 573if.then: 574 %ptr = alloca i32, i32 4 575 br label %for.body 576 577for.body: ; preds = %for.body, %entry 578 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2] 579 %call = tail call i32 asm "mov $0, #0", "=r,~{r4}"() 580 %add = add nsw i32 %call, %sum.03 581 store i32 %add, i32* %ptr 582 br i1 undef, label %body1, label %body2 583 584body1: 585 tail call void asm sideeffect "nop", "~{r4}"() 586 br label %for.body 587 588body2: 589 tail call void asm sideeffect "nop", "~{r4}"() 590 br label %for.body 591 592if.end: 593 ret void 594} 595 596; Another infinite loop test this time with two nested infinite loop. 597; CHECK-LABEL: infiniteloop3 598; CHECK: bx lr 599define void @infiniteloop3() { 600entry: 601 br i1 undef, label %loop2a, label %body 602 603body: ; preds = %entry 604 br i1 undef, label %loop2a, label %end 605 606loop1: ; preds = %loop2a, %loop2b 607 %var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ] 608 %next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ] 609 %0 = icmp eq i32* %var, null 610 %next.load = load i32*, i32** undef 611 br i1 %0, label %loop2a, label %loop2b 612 613loop2a: ; preds = %loop1, %body, %entry 614 %var = phi i32* [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ] 615 %next.var = phi i32* [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ] 616 br label %loop1 617 618loop2b: ; preds = %loop1 619 %gep1 = bitcast i32* %var.phi to i32* 620 %next.ptr = bitcast i32* %gep1 to i32** 621 store i32* %next.phi, i32** %next.ptr 622 br label %loop1 623 624end: 625 ret void 626} 627 628; Function Attrs: nounwind readnone 629declare double @llvm.pow.f64(double, double) 630 631; This function needs to spill floating point registers to 632; exercise the path where we were dereferencing the end iterator 633; to access debug info location while inserting the spill code 634; during PEI with shrink-wrapping enable. 635; CHECK-LABEL: debug_info: 636; 637; ENABLE: tst{{(\.w)?}} r2, #1 638; ENABLE-NEXT: beq [[BB13:LBB[0-9_]+]] 639; 640; CHECK: push 641; 642; DISABLE: tst{{(\.w)?}} r2, #1 643; DISABLE-NEXT: beq [[BB13:LBB[0-9_]+]] 644; 645; CHECK: bl{{x?}} _pow 646; 647; 648; ENABLE: pop 649; 650; CHECK: [[BB13]]: 651; CHECK: vldr 652; 653; DISABLE: pop 654; 655; CHECK: bl 656define float @debug_info(float %gamma, float %slopeLimit, i1 %or.cond, double %tmp) { 657bb: 658 br i1 %or.cond, label %bb3, label %bb13 659 660bb3: ; preds = %bb 661 %tmp4 = fcmp ogt float %gamma, 1.000000e+00 662 %tmp5 = fadd double 1.000000e+00, %tmp 663 %tmp6 = select i1 %tmp4, double %tmp5, double %tmp 664 %tmp10 = tail call double @llvm.pow.f64(double %tmp, double %tmp) 665 %tmp11 = fcmp une double %tmp6, %tmp 666 %tmp12 = fadd double %tmp10, %tmp10 667 %cutoff.0 = select i1 %tmp11, double %tmp12, double %tmp 668 %phitmp = fptrunc double %cutoff.0 to float 669 br label %bb13 670 671bb13: ; preds = %bb3, %bb 672 %cutoff.1 = phi float [ 0.000000e+00, %bb ], [ %phitmp, %bb3 ] 673 ret float %cutoff.1 674} 675 676 677!llvm.dbg.cu = !{!0} 678!llvm.module.flags = !{!3} 679 680!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "LLVM", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2) 681!1 = !DIFile(filename: "a.cpp", directory: "b") 682!2 = !{} 683!3 = !{i32 2, !"Debug Info Version", i32 3} 684