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 62 define 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 67 true: 68 store i32 %a, i32* %tmp, align 4 69 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) 70 br label %false 71 72 false: 73 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 74 ret i32 %tmp.0 75 } 76 77 ; Function Attrs: optsize 78 declare 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 127 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) { 128 entry: 129 %tobool = icmp eq i32 %cond, 0 130 br i1 %tobool, label %if.else, label %for.preheader 131 132 for.preheader: 133 tail call void asm "nop", ""() 134 br label %for.body 135 136 for.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 145 for.end: ; preds = %for.body 146 %shl = shl i32 %add, 3 147 br label %if.end 148 149 if.else: ; preds = %entry 150 %mul = shl nsw i32 %N, 1 151 br label %if.end 152 153 if.end: ; preds = %if.else, %for.end 154 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 155 ret i32 %sum.1 156 } 157 158 declare 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 181 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) { 182 entry: 183 br label %for.preheader 184 185 for.preheader: 186 tail call void asm "nop", ""() 187 br label %for.body 188 189 for.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 198 for.exit: 199 tail call void asm "nop", ""() 200 br label %for.end 201 202 for.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 251 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) { 252 entry: 253 %tobool = icmp eq i32 %cond, 0 254 br i1 %tobool, label %if.else, label %for.preheader 255 256 for.preheader: 257 tail call void asm "nop", ""() 258 br label %for.body 259 260 for.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 269 for.end: ; preds = %for.body 270 tail call void asm "nop", "~{r4}"() 271 %shl = shl i32 %add, 3 272 br label %if.end 273 274 if.else: ; preds = %entry 275 %mul = shl nsw i32 %N, 1 276 br label %if.end 277 278 if.end: ; preds = %if.else, %for.end 279 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 280 ret i32 %sum.1 281 } 282 283 declare 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 330 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 { 331 entry: 332 %tobool = icmp eq i32 %cond, 0 333 br i1 %tobool, label %if.else, label %if.then 334 335 if.then: ; preds = %entry 336 tail call void asm "nop", "~{r4}"() 337 br label %for.body 338 339 for.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 348 for.end: ; preds = %for.body 349 %shl = shl i32 %add, 3 350 br label %if.end 351 352 if.else: ; preds = %entry 353 %mul = shl nsw i32 %N, 1 354 br label %if.end 355 356 if.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 366 define i32 @emptyFrame() { 367 entry: 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 408 define i32 @inlineAsm(i32 %cond, i32 %N) { 409 entry: 410 %tobool = icmp eq i32 %cond, 0 411 br i1 %tobool, label %if.else, label %for.preheader 412 413 for.preheader: 414 tail call void asm "nop", ""() 415 br label %for.body 416 417 for.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 424 for.exit: 425 tail call void asm "nop", ""() 426 br label %if.end 427 428 if.else: ; preds = %entry 429 %mul = shl nsw i32 %N, 1 430 br label %if.end 431 432 if.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} 477 define i32 @callVariadicFunc(i32 %cond, i32 %N) { 478 entry: 479 %tobool = icmp eq i32 %cond, 0 480 br i1 %tobool, label %if.else, label %if.then 481 482 if.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 487 if.else: ; preds = %entry 488 %mul = shl nsw i32 %N, 1 489 br label %if.end 490 491 if.end: ; preds = %if.else, %if.then 492 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ] 493 ret i32 %sum.0 494 } 495 496 declare 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 520 define i32 @noreturn(i8 signext %bad_thing) { 521 entry: 522 %tobool = icmp eq i8 %bad_thing, 0 523 br i1 %tobool, label %if.end, label %if.abort 524 525 if.abort: 526 %call = tail call i32 asm sideeffect "mov $0, #1", "=r,~{r4}"() 527 tail call void @abort() #0 528 unreachable 529 530 if.end: 531 ret i32 42 532 } 533 534 declare void @abort() #0 535 536 attributes #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 547 define void @infiniteloop() { 548 entry: 549 br i1 undef, label %if.then, label %if.end 550 551 if.then: 552 %ptr = alloca i32, i32 4 553 br label %for.body 554 555 for.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 562 if.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 569 define void @infiniteloop2() { 570 entry: 571 br i1 undef, label %if.then, label %if.end 572 573 if.then: 574 %ptr = alloca i32, i32 4 575 br label %for.body 576 577 for.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 584 body1: 585 tail call void asm sideeffect "nop", "~{r4}"() 586 br label %for.body 587 588 body2: 589 tail call void asm sideeffect "nop", "~{r4}"() 590 br label %for.body 591 592 if.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 599 define void @infiniteloop3() { 600 entry: 601 br i1 undef, label %loop2a, label %body 602 603 body: ; preds = %entry 604 br i1 undef, label %loop2a, label %end 605 606 loop1: ; 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 613 loop2a: ; 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 618 loop2b: ; 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 624 end: 625 ret void 626 } 627 628 ; Function Attrs: nounwind readnone 629 declare double @llvm.pow.f64(double, double) 630 631 ; This function needs to spill floating point registers to 632 ; exerce the path where we were deferencing 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 656 define float @debug_info(float %gamma, float %slopeLimit, i1 %or.cond, double %tmp) { 657 bb: 658 br i1 %or.cond, label %bb3, label %bb13 659 660 bb3: ; 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 671 bb13: ; 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: 1, enums: !2, retainedTypes: !2, subprograms: !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