Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc %s -o - -enable-shrink-wrap=true -disable-post-ra -disable-fp-elim | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE
      2 ; RUN: llc %s -o - -enable-shrink-wrap=false -disable-post-ra -disable-fp-elim | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE
      3 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
      4 target 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: sub sp, sp, #32
     17 ; CHECK-NEXT: stp [[SAVE_SP:x[0-9]+]], [[CSR:x[0-9]+]], [sp, #16]
     18 ; CHECK-NEXT: add [[SAVE_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: ldp x{{[0-9]+}}, [[CSR]], [sp, #16]
     37 ; CHECK-NEXT: add sp, sp, #32
     38 ;
     39 ; With shrink-wrapping, exit block is a simple return.
     40 ; ENABLE: [[EXIT_LABEL]]:
     41 ; CHECK-NEXT: ret
     42 define 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 
     47 true:
     48   store i32 %a, i32* %tmp, align 4
     49   %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
     50   br label %false
     51 
     52 false:
     53   %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
     54   ret i32 %tmp.0
     55 }
     56 
     57 ; Function Attrs: optsize
     58 declare 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: mov [[IV:w[0-9]+]], #10
     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
    106 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
    107 entry:
    108   %tobool = icmp eq i32 %cond, 0
    109   br i1 %tobool, label %if.else, label %for.body
    110 
    111 for.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 
    120 for.end:                                          ; preds = %for.body
    121   %shl = shl i32 %add, 3
    122   br label %if.end
    123 
    124 if.else:                                          ; preds = %entry
    125   %mul = shl nsw i32 %N, 1
    126   br label %if.end
    127 
    128 if.end:                                           ; preds = %if.else, %for.end
    129   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
    130   ret i32 %sum.1
    131 }
    132 
    133 declare 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: mov [[IV:w[0-9]+]], #10
    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
    156 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
    157 entry:
    158   br label %for.body
    159 
    160 for.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 
    169 for.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: mov [[IV:w[0-9]+]], #10
    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
    214 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
    215 entry:
    216   %tobool = icmp eq i32 %cond, 0
    217   br i1 %tobool, label %if.else, label %for.body
    218 
    219 for.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 
    228 for.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 
    233 if.else:                                          ; preds = %entry
    234   %mul = shl nsw i32 %N, 1
    235   br label %if.end
    236 
    237 if.end:                                           ; preds = %if.else, %for.end
    238   %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
    239   ret i32 %sum.1
    240 }
    241 
    242 declare 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: mov [[IV:w[0-9]+]], #10
    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
    284 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) #0 {
    285 entry:
    286   %tobool = icmp eq i32 %cond, 0
    287   br i1 %tobool, label %if.else, label %if.then
    288 
    289 if.then:                                          ; preds = %entry
    290   tail call void bitcast (void (...)* @somethingElse to void ()*)()
    291   br label %for.body
    292 
    293 for.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 
    302 for.end:                                          ; preds = %for.body
    303   %shl = shl i32 %add, 3
    304   br label %if.end
    305 
    306 if.else:                                          ; preds = %entry
    307   %mul = shl nsw i32 %N, 1
    308   br label %if.end
    309 
    310 if.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
    320 define i32 @emptyFrame() {
    321 entry:
    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: add [[VA_BASE:x[0-9]+]], sp, #16
    336 ; CHECK-NEXT: str [[VA_BASE]], [sp, #8]
    337 ; CHECK-NEXT: cmp w1, #1
    338 ; CHECK-NEXT: b.lt [[IFEND_LABEL:LBB[0-9_]+]]
    339 ; CHECK: mov [[SUM:w0]], wzr
    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
    351 ; DISABLE: [[ELSE_LABEL]]: ; %if.else
    352 ; DISABLE: lsl w0, w1, #1
    353 ;
    354 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
    355 ; ENABLE: lsl w0, w1, #1
    356 ; ENABLE-NEXT: ret
    357 ;
    358 ; CHECK: [[IFEND_LABEL]]:
    359 ; Epilogue code.
    360 ; CHECK: add sp, sp, #16
    361 ; CHECK-NEXT: ret
    362 define i32 @variadicFunc(i32 %cond, i32 %count, ...) #0 {
    363 entry:
    364   %ap = alloca i8*, align 8
    365   %tobool = icmp eq i32 %cond, 0
    366   br i1 %tobool, label %if.else, label %if.then
    367 
    368 if.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 
    374 for.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 
    383 for.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 
    388 if.else:                                          ; preds = %entry
    389   %mul = shl nsw i32 %count, 1
    390   br label %if.end
    391 
    392 if.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 
    397 declare void @llvm.va_start(i8*)
    398 
    399 declare 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: mov [[IV:w[0-9]+]], #10
    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
    430 define i32 @inlineAsm(i32 %cond, i32 %N) {
    431 entry:
    432   %tobool = icmp eq i32 %cond, 0
    433   br i1 %tobool, label %if.else, label %for.body
    434 
    435 for.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 
    442 if.else:                                          ; preds = %entry
    443   %mul = shl nsw i32 %N, 1
    444   br label %if.end
    445 
    446 if.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: sub sp, sp, #64
    458 ; CHECK-NEXT: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #48]
    459 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], 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: ldp [[CSR1]], [[CSR2]], [sp, #48]
    477 ; CHECK-NEXT: add sp, sp, #64
    478 ; CHECK-NEXT: ret
    479 ;
    480 ; ENABLE: [[ELSE_LABEL]]: ; %if.else
    481 ; ENABLE-NEXT: lsl w0, w1, #1
    482 ; ENABLE-NEXT: ret
    483 define i32 @callVariadicFunc(i32 %cond, i32 %N) {
    484 entry:
    485   %tobool = icmp eq i32 %cond, 0
    486   br i1 %tobool, label %if.else, label %if.then
    487 
    488 if.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 
    493 if.else:                                          ; preds = %entry
    494   %mul = shl nsw i32 %N, 1
    495   br label %if.end
    496 
    497 if.end:                                           ; preds = %if.else, %if.then
    498   %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
    499   ret i32 %sum.0
    500 }
    501 
    502 declare 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: mov w0, #42
    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
    526 define i32 @noreturn(i8 signext %bad_thing) {
    527 entry:
    528   %tobool = icmp eq i8 %bad_thing, 0
    529   br i1 %tobool, label %if.end, label %if.abort
    530 
    531 if.abort:
    532   tail call void @abort() #0
    533   unreachable
    534 
    535 if.end:
    536   ret i32 42
    537 }
    538 
    539 declare void @abort() #0
    540 
    541 attributes #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
    553 define void @infiniteloop() {
    554 entry:
    555   br i1 undef, label %if.then, label %if.end
    556 
    557 if.then:
    558   %ptr = alloca i32, i32 4
    559   br label %for.body
    560 
    561 for.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 
    568 if.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
    575 define void @infiniteloop2() {
    576 entry:
    577   br i1 undef, label %if.then, label %if.end
    578 
    579 if.then:
    580   %ptr = alloca i32, i32 4
    581   br label %for.body
    582 
    583 for.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 
    590 body1:
    591   tail call void asm sideeffect "nop", "~{x19}"()
    592   br label %for.body
    593 
    594 body2:
    595   tail call void asm sideeffect "nop", "~{x19}"()
    596   br label %for.body
    597 
    598 if.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
    605 define void @infiniteloop3() {
    606 entry:
    607   br i1 undef, label %loop2a, label %body
    608 
    609 body:                                             ; preds = %entry
    610   br i1 undef, label %loop2a, label %end
    611 
    612 loop1:                                            ; 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 
    619 loop2a:                                           ; 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 
    624 loop2b:                                           ; 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 
    630 end:
    631   ret void
    632 }
    633 
    634 ; Re-aligned stack pointer.  See bug 26642.  Avoid clobbering live
    635 ; values in the prologue when re-aligning the stack pointer.
    636 ; CHECK-LABEL: stack_realign:
    637 ; ENABLE-DAG: lsl w[[LSL1:[0-9]+]], w0, w1
    638 ; ENABLE-DAG: lsl w[[LSL2:[0-9]+]], w1, w0
    639 ; DISABLE-NOT: lsl w[[LSL1:[0-9]+]], w0, w1
    640 ; DISABLE-NOT: lsl w[[LSL2:[0-9]+]], w1, w0
    641 ; CHECK: stp x29, x30, [sp, #-16]!
    642 ; CHECK: mov x29, sp
    643 ; ENABLE-NOT: sub x[[LSL1]], sp, #16
    644 ; ENABLE-NOT: sub x[[LSL2]], sp, #16
    645 ; DISABLE: sub x{{[0-9]+}}, sp, #16
    646 ; DISABLE-DAG: lsl w[[LSL1:[0-9]+]], w0, w1
    647 ; DISABLE-DAG: lsl w[[LSL2:[0-9]+]], w1, w0
    648 ; CHECK-DAG: str w[[LSL1]],
    649 ; CHECK-DAG: str w[[LSL2]],
    650 
    651 define i32 @stack_realign(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2) {
    652   %tmp = alloca i32, align 32
    653   %shl1 = shl i32 %a, %b
    654   %shl2 = shl i32 %b, %a
    655   %tmp2 = icmp slt i32 %a, %b
    656   br i1 %tmp2, label %true, label %false
    657 
    658 true:
    659   store i32 %a, i32* %tmp, align 4
    660   %tmp4 = load i32, i32* %tmp
    661   br label %false
    662 
    663 false:
    664   %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
    665   store i32 %shl1, i32* %ptr1
    666   store i32 %shl2, i32* %ptr2
    667   ret i32 %tmp.0
    668 }
    669 
    670 ; Re-aligned stack pointer with all caller-save regs live.  See bug
    671 ; 26642.  In this case we currently avoid shrink wrapping because
    672 ; ensuring we have a scratch register to re-align the stack pointer is
    673 ; too complicated.  Output should be the same for both enabled and
    674 ; disabled shrink wrapping.
    675 ; CHECK-LABEL: stack_realign2:
    676 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #-{{[0-9]+}}]!
    677 ; CHECK: add x29, sp, #{{[0-9]+}}
    678 ; CHECK: lsl {{w[0-9]+}}, w0, w1
    679 
    680 define void @stack_realign2(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2, i32* %ptr3, i32* %ptr4, i32* %ptr5, i32* %ptr6) {
    681   %tmp = alloca i32, align 32
    682   %tmp1 = shl i32 %a, %b
    683   %tmp2 = shl i32 %b, %a
    684   %tmp3 = lshr i32 %a, %b
    685   %tmp4 = lshr i32 %b, %a
    686   %tmp5 = add i32 %b, %a
    687   %tmp6 = sub i32 %b, %a
    688   %tmp7 = add i32 %tmp1, %tmp2
    689   %tmp8 = sub i32 %tmp2, %tmp3
    690   %tmp9 = add i32 %tmp3, %tmp4
    691   %tmp10 = add i32 %tmp4, %tmp5
    692   %cmp = icmp slt i32 %a, %b
    693   br i1 %cmp, label %true, label %false
    694 
    695 true:
    696   store i32 %a, i32* %tmp, align 4
    697   call void asm sideeffect "nop", "~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28}"() nounwind
    698   br label %false
    699 
    700 false:
    701   store i32 %tmp1, i32* %ptr1, align 4
    702   store i32 %tmp2, i32* %ptr2, align 4
    703   store i32 %tmp3, i32* %ptr3, align 4
    704   store i32 %tmp4, i32* %ptr4, align 4
    705   store i32 %tmp5, i32* %ptr5, align 4
    706   store i32 %tmp6, i32* %ptr6, align 4
    707   %idx1 = getelementptr inbounds i32, i32* %ptr1, i64 1
    708   store i32 %a, i32* %idx1, align 4
    709   %idx2 = getelementptr inbounds i32, i32* %ptr1, i64 2
    710   store i32 %b, i32* %idx2, align 4
    711   %idx3 = getelementptr inbounds i32, i32* %ptr1, i64 3
    712   store i32 %tmp7, i32* %idx3, align 4
    713   %idx4 = getelementptr inbounds i32, i32* %ptr1, i64 4
    714   store i32 %tmp8, i32* %idx4, align 4
    715   %idx5 = getelementptr inbounds i32, i32* %ptr1, i64 5
    716   store i32 %tmp9, i32* %idx5, align 4
    717   %idx6 = getelementptr inbounds i32, i32* %ptr1, i64 6
    718   store i32 %tmp10, i32* %idx6, align 4
    719 
    720   ret void
    721 }
    722