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) "no-frame-pointer-elim"="true" { 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) "no-frame-pointer-elim"="true" { 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) "no-frame-pointer-elim"="true" { 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) "no-frame-pointer-elim"="true" { 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) "no-frame-pointer-elim"="true" nounwind { 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) "no-frame-pointer-elim"="true" { 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) "no-frame-pointer-elim"="true" { 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; ARM-ENABLE: cmp r0, #0 505; ARM-DISABLE: cmp r0, #0 506; ARM-ENABLE: bne [[ABORT:LBB[0-9_]+]] 507; ARM-DISABLE: bne [[ABORT:LBB[0-9_]+]] 508; THUMB-ENABLE: cbnz r0, [[ABORT:LBB[0-9_]+]] 509; THUMB-DISABLE: cbnz r0, [[ABORT:LBB[0-9_]+]] 510 511; 512; CHECK: mov{{s?}} r0, #42 513; 514; ENABLE-NEXT: bx lr 515; 516; DISABLE-NEXT: pop 517;; 518; CHECK: [[ABORT]]: @ %if.abort 519; 520; ENABLE: push 521; 522; CHECK: bl{{x?}} _abort 523; ENABLE-NOT: pop 524define i32 @noreturn(i8 signext %bad_thing) "no-frame-pointer-elim"="true" { 525entry: 526 %tobool = icmp eq i8 %bad_thing, 0 527 br i1 %tobool, label %if.end, label %if.abort 528 529if.abort: 530 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 531 tail call void @abort() #0 532 unreachable 533 534if.end: 535 ret i32 42 536} 537 538declare void @abort() #0 539 540attributes #0 = { noreturn nounwind } 541 542; Make sure that we handle infinite loops properly When checking that the Save 543; and Restore blocks are control flow equivalent, the loop searches for the 544; immediate (post) dominator for the (restore) save blocks. When either the Save 545; or Restore block is located in an infinite loop the only immediate (post) 546; dominator is itself. In this case, we cannot perform shrink wrapping, but we 547; should return gracefully and continue compilation. 548; The only condition for this test is the compilation finishes correctly. 549; CHECK-LABEL: infiniteloop 550; CHECK: pop 551define void @infiniteloop() "no-frame-pointer-elim"="true" { 552entry: 553 br i1 undef, label %if.then, label %if.end 554 555if.then: 556 %ptr = alloca i32, i32 4 557 br label %for.body 558 559for.body: ; preds = %for.body, %entry 560 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 561 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 562 %add = add nsw i32 %call, %sum.03 563 store i32 %add, i32* %ptr 564 br label %for.body 565 566if.end: 567 ret void 568} 569 570; Another infinite loop test this time with a body bigger than just one block. 571; CHECK-LABEL: infiniteloop2 572; CHECK: pop 573define void @infiniteloop2() "no-frame-pointer-elim"="true" { 574entry: 575 br i1 undef, label %if.then, label %if.end 576 577if.then: 578 %ptr = alloca i32, i32 4 579 br label %for.body 580 581for.body: ; preds = %for.body, %entry 582 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2] 583 %call = tail call i32 asm "mov $0, #0", "=r,~{r4}"() 584 %add = add nsw i32 %call, %sum.03 585 store i32 %add, i32* %ptr 586 br i1 undef, label %body1, label %body2 587 588body1: 589 tail call void asm sideeffect "nop", "~{r4}"() 590 br label %for.body 591 592body2: 593 tail call void asm sideeffect "nop", "~{r4}"() 594 br label %for.body 595 596if.end: 597 ret void 598} 599 600; Another infinite loop test this time with two nested infinite loop. 601; CHECK-LABEL: infiniteloop3 602; CHECK: bx lr 603define void @infiniteloop3() "no-frame-pointer-elim"="true" { 604entry: 605 br i1 undef, label %loop2a, label %body 606 607body: ; preds = %entry 608 br i1 undef, label %loop2a, label %end 609 610loop1: ; preds = %loop2a, %loop2b 611 %var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ] 612 %next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ] 613 %0 = icmp eq i32* %var, null 614 %next.load = load i32*, i32** undef 615 br i1 %0, label %loop2a, label %loop2b 616 617loop2a: ; preds = %loop1, %body, %entry 618 %var = phi i32* [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ] 619 %next.var = phi i32* [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ] 620 br label %loop1 621 622loop2b: ; preds = %loop1 623 %gep1 = bitcast i32* %var.phi to i32* 624 %next.ptr = bitcast i32* %gep1 to i32** 625 store i32* %next.phi, i32** %next.ptr 626 br label %loop1 627 628end: 629 ret void 630} 631 632; Function Attrs: nounwind readnone 633declare double @llvm.pow.f64(double, double) 634 635; This function needs to spill floating point registers to 636; exercise the path where we were dereferencing the end iterator 637; to access debug info location while inserting the spill code 638; during PEI with shrink-wrapping enable. 639; CHECK-LABEL: debug_info: 640; 641; ENABLE: {{tst r2, #1|lsls r1, r2, #31}} 642; ENABLE-NEXT: beq [[BB13:LBB[0-9_]+]] 643; 644; CHECK: push 645; 646; DISABLE: {{tst r2, #1|lsls r1, r2, #31}} 647; DISABLE: beq [[BB13:LBB[0-9_]+]] 648; 649; CHECK: bl{{x?}} _pow 650; 651; 652; ENABLE: pop 653; 654; CHECK: [[BB13]]: 655; CHECK: vldr 656; 657; DISABLE: pop 658; 659; FIXME: This is flakey passing by finding 'bl' somewhere amongst the debug 660; info (like labels named 'line_table) not because it's found a bl instruction. 661; 662; CHECK: bl 663define float @debug_info(float %gamma, float %slopeLimit, i1 %or.cond, double %tmp) "no-frame-pointer-elim"="true" { 664bb: 665 br i1 %or.cond, label %bb3, label %bb13 666 667bb3: ; preds = %bb 668 %tmp4 = fcmp ogt float %gamma, 1.000000e+00 669 %tmp5 = fadd double 1.000000e+00, %tmp 670 %tmp6 = select i1 %tmp4, double %tmp5, double %tmp 671 %tmp10 = tail call double @llvm.pow.f64(double %tmp, double %tmp) 672 %tmp11 = fcmp une double %tmp6, %tmp 673 %tmp12 = fadd double %tmp10, %tmp10 674 %cutoff.0 = select i1 %tmp11, double %tmp12, double %tmp 675 %phitmp = fptrunc double %cutoff.0 to float 676 br label %bb13 677 678bb13: ; preds = %bb3, %bb 679 %cutoff.1 = phi float [ 0.000000e+00, %bb ], [ %phitmp, %bb3 ] 680 ret float %cutoff.1 681} 682 683 684!llvm.dbg.cu = !{!0} 685!llvm.module.flags = !{!3} 686 687!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "LLVM", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !4, globals: !2, imports: !2) 688!1 = !DIFile(filename: "a.cpp", directory: "b") 689!2 = !{} 690!3 = !{i32 2, !"Debug Info Version", i32 3} 691!4 = !{!5} 692!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) 693