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