llvm/llvm/test/CodeGen/AArch64/arm64-shrink-wrapping.ll

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -debugify-and-strip-all-safe %s -o - -mtriple=arm64-apple-ios -enable-shrink-wrap=true -disable-post-ra -frame-pointer=non-leaf | FileCheck %s --check-prefix=ENABLE
; RUN: llc -debugify-and-strip-all-safe %s -o - -enable-shrink-wrap=false -disable-post-ra -frame-pointer=non-leaf | FileCheck %s --check-prefix=DISABLE
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-ios"


; Initial motivating example: Simple diamond with a call just on one side.
define i32 @foo(i32 %a, i32 %b) {
; ENABLE-LABEL: foo:
; ENABLE:       ; %bb.0:
; ENABLE-NEXT:    cmp w0, w1
; ENABLE-NEXT:    b.ge LBB0_2
; ENABLE-NEXT:  ; %bb.1: ; %true
; ENABLE-NEXT:    sub sp, sp, #32
; ENABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    stur w0, [x29, #-4]
; ENABLE-NEXT:    sub x1, x29, #4
; ENABLE-NEXT:    mov w0, wzr
; ENABLE-NEXT:    bl _doSomething
; ENABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; ENABLE-NEXT:    add sp, sp, #32
; ENABLE-NEXT:  LBB0_2: ; %false
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: foo:
; DISABLE:       ; %bb.0:
; DISABLE-NEXT:    sub sp, sp, #32
; DISABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    cmp w0, w1
; DISABLE-NEXT:    b.ge LBB0_2
; DISABLE-NEXT:  ; %bb.1: ; %true
; DISABLE-NEXT:    stur w0, [x29, #-4]
; DISABLE-NEXT:    sub x1, x29, #4
; DISABLE-NEXT:    mov w0, wzr
; DISABLE-NEXT:    bl _doSomething
; DISABLE-NEXT:  LBB0_2: ; %false
; DISABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; DISABLE-NEXT:    add sp, sp, #32
; DISABLE-NEXT:    ret
  %tmp = alloca i32, align 4
  %tmp2 = icmp slt i32 %a, %b
  br i1 %tmp2, label %true, label %false

true:
  store i32 %a, ptr %tmp, align 4
  %tmp4 = call i32 @doSomething(i32 0, ptr %tmp)
  br label %false

false:
  %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
  ret i32 %tmp.0
}

; Function Attrs: optsize
declare i32 @doSomething(i32, ptr)


; Check that we do not perform the restore inside the loop whereas the save
; is outside.
define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) {
; ENABLE-LABEL: freqSaveAndRestoreOutsideLoop:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    cbz w0, LBB1_4
; ENABLE-NEXT:  ; %bb.1: ; %for.body.preheader
; ENABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    .cfi_offset w19, -24
; ENABLE-NEXT:    .cfi_offset w20, -32
; ENABLE-NEXT:    mov w19, wzr
; ENABLE-NEXT:    mov w20, #10 ; =0xa
; ENABLE-NEXT:  LBB1_2: ; %for.body
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    bl _something
; ENABLE-NEXT:    subs w20, w20, #1
; ENABLE-NEXT:    add w19, w0, w19
; ENABLE-NEXT:    b.ne LBB1_2
; ENABLE-NEXT:  ; %bb.3: ; %for.end
; ENABLE-NEXT:    lsl w0, w19, #3
; ENABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; ENABLE-NEXT:    ret
; ENABLE-NEXT:  LBB1_4: ; %if.else
; ENABLE-NEXT:    lsl w0, w1, #1
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: freqSaveAndRestoreOutsideLoop:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    .cfi_offset w19, -24
; DISABLE-NEXT:    .cfi_offset w20, -32
; DISABLE-NEXT:    cbz w0, LBB1_4
; DISABLE-NEXT:  ; %bb.1: ; %for.body.preheader
; DISABLE-NEXT:    mov w19, wzr
; DISABLE-NEXT:    mov w20, #10 ; =0xa
; DISABLE-NEXT:  LBB1_2: ; %for.body
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    bl _something
; DISABLE-NEXT:    subs w20, w20, #1
; DISABLE-NEXT:    add w19, w0, w19
; DISABLE-NEXT:    b.ne LBB1_2
; DISABLE-NEXT:  ; %bb.3: ; %for.end
; DISABLE-NEXT:    lsl w0, w19, #3
; DISABLE-NEXT:    b LBB1_5
; DISABLE-NEXT:  LBB1_4: ; %if.else
; DISABLE-NEXT:    lsl w0, w1, #1
; DISABLE-NEXT:  LBB1_5: ; %if.end
; DISABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
entry:
  %tobool = icmp eq i32 %cond, 0
  br i1 %tobool, label %if.else, label %for.body

for.body:                                         ; preds = %entry, %for.body
  %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
  %sum.04 = phi i32 [ %add, %for.body ], [ 0, %entry ]
  %call = tail call i32 @something()
  %add = add nsw i32 %call, %sum.04
  %inc = add nuw nsw i32 %i.05, 1
  %exitcond = icmp eq i32 %inc, 10
  br i1 %exitcond, label %for.end, label %for.body

for.end:                                          ; preds = %for.body
  %shl = shl i32 %add, 3
  br label %if.end

if.else:                                          ; preds = %entry
  %mul = shl nsw i32 %N, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %for.end
  %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
  ret i32 %sum.1
}

declare i32 @something(...)

; Check that we do not perform the shrink-wrapping inside the loop even
; though that would be legal. The cost model must prevent that.
define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) {
; ENABLE-LABEL: freqSaveAndRestoreOutsideLoop2:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    .cfi_offset w19, -24
; ENABLE-NEXT:    .cfi_offset w20, -32
; ENABLE-NEXT:    mov w19, wzr
; ENABLE-NEXT:    mov w20, #10 ; =0xa
; ENABLE-NEXT:  LBB2_1: ; %for.body
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    bl _something
; ENABLE-NEXT:    subs w20, w20, #1
; ENABLE-NEXT:    add w19, w0, w19
; ENABLE-NEXT:    b.ne LBB2_1
; ENABLE-NEXT:  ; %bb.2: ; %for.end
; ENABLE-NEXT:    mov w0, w19
; ENABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: freqSaveAndRestoreOutsideLoop2:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    .cfi_offset w19, -24
; DISABLE-NEXT:    .cfi_offset w20, -32
; DISABLE-NEXT:    mov w19, wzr
; DISABLE-NEXT:    mov w20, #10 ; =0xa
; DISABLE-NEXT:  LBB2_1: ; %for.body
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    bl _something
; DISABLE-NEXT:    subs w20, w20, #1
; DISABLE-NEXT:    add w19, w0, w19
; DISABLE-NEXT:    b.ne LBB2_1
; DISABLE-NEXT:  ; %bb.2: ; %for.end
; DISABLE-NEXT:    mov w0, w19
; DISABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
entry:
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %i.04 = phi i32 [ 0, %entry ], [ %inc, %for.body ]
  %sum.03 = phi i32 [ 0, %entry ], [ %add, %for.body ]
  %call = tail call i32 @something()
  %add = add nsw i32 %call, %sum.03
  %inc = add nuw nsw i32 %i.04, 1
  %exitcond = icmp eq i32 %inc, 10
  br i1 %exitcond, label %for.end, label %for.body

for.end:                                          ; preds = %for.body
  ret i32 %add
}

; Check with a more complex case that we do not have save within the loop and
; restore outside.
define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) {
; ENABLE-LABEL: loopInfoSaveOutsideLoop:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    cbz w0, LBB3_4
; ENABLE-NEXT:  ; %bb.1: ; %for.body.preheader
; ENABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    .cfi_offset w19, -24
; ENABLE-NEXT:    .cfi_offset w20, -32
; ENABLE-NEXT:    mov w19, wzr
; ENABLE-NEXT:    mov w20, #10 ; =0xa
; ENABLE-NEXT:  LBB3_2: ; %for.body
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    bl _something
; ENABLE-NEXT:    subs w20, w20, #1
; ENABLE-NEXT:    add w19, w0, w19
; ENABLE-NEXT:    b.ne LBB3_2
; ENABLE-NEXT:  ; %bb.3: ; %for.end
; ENABLE-NEXT:    bl _somethingElse
; ENABLE-NEXT:    lsl w0, w19, #3
; ENABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; ENABLE-NEXT:    ret
; ENABLE-NEXT:  LBB3_4: ; %if.else
; ENABLE-NEXT:    lsl w0, w1, #1
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: loopInfoSaveOutsideLoop:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    .cfi_offset w19, -24
; DISABLE-NEXT:    .cfi_offset w20, -32
; DISABLE-NEXT:    cbz w0, LBB3_4
; DISABLE-NEXT:  ; %bb.1: ; %for.body.preheader
; DISABLE-NEXT:    mov w19, wzr
; DISABLE-NEXT:    mov w20, #10 ; =0xa
; DISABLE-NEXT:  LBB3_2: ; %for.body
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    bl _something
; DISABLE-NEXT:    subs w20, w20, #1
; DISABLE-NEXT:    add w19, w0, w19
; DISABLE-NEXT:    b.ne LBB3_2
; DISABLE-NEXT:  ; %bb.3: ; %for.end
; DISABLE-NEXT:    bl _somethingElse
; DISABLE-NEXT:    lsl w0, w19, #3
; DISABLE-NEXT:    b LBB3_5
; DISABLE-NEXT:  LBB3_4: ; %if.else
; DISABLE-NEXT:    lsl w0, w1, #1
; DISABLE-NEXT:  LBB3_5: ; %if.end
; DISABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
entry:
  %tobool = icmp eq i32 %cond, 0
  br i1 %tobool, label %if.else, label %for.body

for.body:                                         ; preds = %entry, %for.body
  %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
  %sum.04 = phi i32 [ %add, %for.body ], [ 0, %entry ]
  %call = tail call i32 @something()
  %add = add nsw i32 %call, %sum.04
  %inc = add nuw nsw i32 %i.05, 1
  %exitcond = icmp eq i32 %inc, 10
  br i1 %exitcond, label %for.end, label %for.body

for.end:                                          ; preds = %for.body
  tail call void @somethingElse()
  %shl = shl i32 %add, 3
  br label %if.end

if.else:                                          ; preds = %entry
  %mul = shl nsw i32 %N, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %for.end
  %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
  ret i32 %sum.1
}

declare void @somethingElse(...)

; Check with a more complex case that we do not have restore within the loop and
; save outside.
define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind uwtable {
; ENABLE-LABEL: loopInfoRestoreOutsideLoop:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    cbz w0, LBB4_4
; ENABLE-NEXT:  ; %bb.1: ; %if.then
; ENABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; ENABLE-NEXT:    .cfi_def_cfa_offset 32
; ENABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    .cfi_offset w19, -24
; ENABLE-NEXT:    .cfi_offset w20, -32
; ENABLE-NEXT:    bl _somethingElse
; ENABLE-NEXT:    mov w19, wzr
; ENABLE-NEXT:    mov w20, #10 ; =0xa
; ENABLE-NEXT:  LBB4_2: ; %for.body
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    bl _something
; ENABLE-NEXT:    subs w20, w20, #1
; ENABLE-NEXT:    add w19, w0, w19
; ENABLE-NEXT:    b.ne LBB4_2
; ENABLE-NEXT:  ; %bb.3: ; %for.end
; ENABLE-NEXT:    lsl w0, w19, #3
; ENABLE-NEXT:    .cfi_def_cfa wsp, 32
; ENABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; ENABLE-NEXT:    .cfi_def_cfa_offset 0
; ENABLE-NEXT:    .cfi_restore w30
; ENABLE-NEXT:    .cfi_restore w29
; ENABLE-NEXT:    .cfi_restore w19
; ENABLE-NEXT:    .cfi_restore w20
; ENABLE-NEXT:    ret
; ENABLE-NEXT:  LBB4_4: ; %if.else
; ENABLE-NEXT:    lsl w0, w1, #1
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: loopInfoRestoreOutsideLoop:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; DISABLE-NEXT:    .cfi_def_cfa_offset 32
; DISABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    .cfi_offset w19, -24
; DISABLE-NEXT:    .cfi_offset w20, -32
; DISABLE-NEXT:    cbz w0, LBB4_4
; DISABLE-NEXT:  ; %bb.1: ; %if.then
; DISABLE-NEXT:    bl _somethingElse
; DISABLE-NEXT:    mov w19, wzr
; DISABLE-NEXT:    mov w20, #10 ; =0xa
; DISABLE-NEXT:  LBB4_2: ; %for.body
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    bl _something
; DISABLE-NEXT:    subs w20, w20, #1
; DISABLE-NEXT:    add w19, w0, w19
; DISABLE-NEXT:    b.ne LBB4_2
; DISABLE-NEXT:  ; %bb.3: ; %for.end
; DISABLE-NEXT:    lsl w0, w19, #3
; DISABLE-NEXT:    b LBB4_5
; DISABLE-NEXT:  LBB4_4: ; %if.else
; DISABLE-NEXT:    lsl w0, w1, #1
; DISABLE-NEXT:  LBB4_5: ; %if.end
; DISABLE-NEXT:    .cfi_def_cfa wsp, 32
; DISABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; DISABLE-NEXT:    .cfi_def_cfa_offset 0
; DISABLE-NEXT:    .cfi_restore w30
; DISABLE-NEXT:    .cfi_restore w29
; DISABLE-NEXT:    .cfi_restore w19
; DISABLE-NEXT:    .cfi_restore w20
; DISABLE-NEXT:    ret
entry:
  %tobool = icmp eq i32 %cond, 0
  br i1 %tobool, label %if.else, label %if.then

if.then:                                          ; preds = %entry
  tail call void @somethingElse()
  br label %for.body

for.body:                                         ; preds = %for.body, %if.then
  %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ]
  %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
  %call = tail call i32 @something()
  %add = add nsw i32 %call, %sum.04
  %inc = add nuw nsw i32 %i.05, 1
  %exitcond = icmp eq i32 %inc, 10
  br i1 %exitcond, label %for.end, label %for.body

for.end:                                          ; preds = %for.body
  %shl = shl i32 %add, 3
  br label %if.end

if.else:                                          ; preds = %entry
  %mul = shl nsw i32 %N, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %for.end
  %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ]
  ret i32 %sum.1
}

; Check that we handle function with no frame information correctly.
define i32 @emptyFrame() {
; ENABLE-LABEL: emptyFrame:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    mov w0, wzr
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: emptyFrame:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    mov w0, wzr
; DISABLE-NEXT:    ret
entry:
  ret i32 0
}

; Check that we handle variadic function correctly.
define i32 @variadicFunc(i32 %cond, i32 %count, ...) nounwind uwtable {
; ENABLE-LABEL: variadicFunc:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    cbz w0, LBB6_4
; ENABLE-NEXT:  ; %bb.1: ; %if.then
; ENABLE-NEXT:    sub sp, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa_offset 16
; ENABLE-NEXT:    add x8, sp, #16
; ENABLE-NEXT:    cmp w1, #1
; ENABLE-NEXT:    str x8, [sp, #8]
; ENABLE-NEXT:    mov w0, wzr
; ENABLE-NEXT:    b.lt LBB6_3
; ENABLE-NEXT:  LBB6_2: ; %for.body
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    ldr x8, [sp, #8]
; ENABLE-NEXT:    add x9, x8, #8
; ENABLE-NEXT:    str x9, [sp, #8]
; ENABLE-NEXT:    ldr w8, [x8]
; ENABLE-NEXT:    subs w1, w1, #1
; ENABLE-NEXT:    add w0, w0, w8
; ENABLE-NEXT:    b.ne LBB6_2
; ENABLE-NEXT:  LBB6_3: ; %for.end
; ENABLE-NEXT:    add sp, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa_offset 0
; ENABLE-NEXT:    ret
; ENABLE-NEXT:  LBB6_4: ; %if.else
; ENABLE-NEXT:    lsl w0, w1, #1
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: variadicFunc:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    sub sp, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa_offset 16
; DISABLE-NEXT:    cbz w0, LBB6_3
; DISABLE-NEXT:  ; %bb.1: ; %if.then
; DISABLE-NEXT:    add x8, sp, #16
; DISABLE-NEXT:    cmp w1, #1
; DISABLE-NEXT:    str x8, [sp, #8]
; DISABLE-NEXT:    mov w0, wzr
; DISABLE-NEXT:    b.lt LBB6_4
; DISABLE-NEXT:  LBB6_2: ; %for.body
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    ldr x8, [sp, #8]
; DISABLE-NEXT:    add x9, x8, #8
; DISABLE-NEXT:    str x9, [sp, #8]
; DISABLE-NEXT:    ldr w8, [x8]
; DISABLE-NEXT:    subs w1, w1, #1
; DISABLE-NEXT:    add w0, w0, w8
; DISABLE-NEXT:    b.ne LBB6_2
; DISABLE-NEXT:    b LBB6_4
; DISABLE-NEXT:  LBB6_3: ; %if.else
; DISABLE-NEXT:    lsl w0, w1, #1
; DISABLE-NEXT:  LBB6_4: ; %if.end
; DISABLE-NEXT:    add sp, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa_offset 0
; DISABLE-NEXT:    ret
entry:
  %ap = alloca ptr, align 8
  %tobool = icmp eq i32 %cond, 0
  br i1 %tobool, label %if.else, label %if.then

if.then:                                          ; preds = %entry
  call void @llvm.va_start(ptr %ap)
  %cmp6 = icmp sgt i32 %count, 0
  br i1 %cmp6, label %for.body, label %for.end

for.body:                                         ; preds = %if.then, %for.body
  %i.08 = phi i32 [ %inc, %for.body ], [ 0, %if.then ]
  %sum.07 = phi i32 [ %add, %for.body ], [ 0, %if.then ]
  %0 = va_arg ptr %ap, i32
  %add = add nsw i32 %sum.07, %0
  %inc = add nuw nsw i32 %i.08, 1
  %exitcond = icmp eq i32 %inc, %count
  br i1 %exitcond, label %for.end, label %for.body

for.end:                                          ; preds = %for.body, %if.then
  %sum.0.lcssa = phi i32 [ 0, %if.then ], [ %add, %for.body ]
  call void @llvm.va_end(ptr %ap)
  br label %if.end

if.else:                                          ; preds = %entry
  %mul = shl nsw i32 %count, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %for.end
  %sum.1 = phi i32 [ %sum.0.lcssa, %for.end ], [ %mul, %if.else ]
  ret i32 %sum.1
}

declare void @llvm.va_start(ptr)

declare void @llvm.va_end(ptr)

; Check that we handle inline asm correctly.
define i32 @inlineAsm(i32 %cond, i32 %N) {
; ENABLE-LABEL: inlineAsm:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    cbz w0, LBB7_4
; ENABLE-NEXT:  ; %bb.1: ; %for.body.preheader
; ENABLE-NEXT:    stp x20, x19, [sp, #-16]! ; 16-byte Folded Spill
; ENABLE-NEXT:    .cfi_def_cfa_offset 16
; ENABLE-NEXT:    .cfi_offset w19, -8
; ENABLE-NEXT:    .cfi_offset w20, -16
; ENABLE-NEXT:    mov w8, #10 ; =0xa
; ENABLE-NEXT:  LBB7_2: ; %for.body
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    subs w8, w8, #1
; ENABLE-NEXT:    ; InlineAsm Start
; ENABLE-NEXT:    add x19, x19, #1
; ENABLE-NEXT:    ; InlineAsm End
; ENABLE-NEXT:    b.ne LBB7_2
; ENABLE-NEXT:  ; %bb.3:
; ENABLE-NEXT:    mov w0, wzr
; ENABLE-NEXT:    ldp x20, x19, [sp], #16 ; 16-byte Folded Reload
; ENABLE-NEXT:    ret
; ENABLE-NEXT:  LBB7_4: ; %if.else
; ENABLE-NEXT:    lsl w0, w1, #1
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: inlineAsm:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    stp x20, x19, [sp, #-16]! ; 16-byte Folded Spill
; DISABLE-NEXT:    .cfi_def_cfa_offset 16
; DISABLE-NEXT:    .cfi_offset w19, -8
; DISABLE-NEXT:    .cfi_offset w20, -16
; DISABLE-NEXT:    cbz w0, LBB7_4
; DISABLE-NEXT:  ; %bb.1: ; %for.body.preheader
; DISABLE-NEXT:    mov w8, #10 ; =0xa
; DISABLE-NEXT:  LBB7_2: ; %for.body
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    subs w8, w8, #1
; DISABLE-NEXT:    ; InlineAsm Start
; DISABLE-NEXT:    add x19, x19, #1
; DISABLE-NEXT:    ; InlineAsm End
; DISABLE-NEXT:    b.ne LBB7_2
; DISABLE-NEXT:  ; %bb.3:
; DISABLE-NEXT:    mov w0, wzr
; DISABLE-NEXT:    ldp x20, x19, [sp], #16 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
; DISABLE-NEXT:  LBB7_4: ; %if.else
; DISABLE-NEXT:    lsl w0, w1, #1
; DISABLE-NEXT:    ldp x20, x19, [sp], #16 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
entry:
  %tobool = icmp eq i32 %cond, 0
  br i1 %tobool, label %if.else, label %for.body

for.body:                                         ; preds = %entry, %for.body
  %i.03 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
  tail call void asm sideeffect "add x19, x19, #1", "~{x19}"()
  %inc = add nuw nsw i32 %i.03, 1
  %exitcond = icmp eq i32 %inc, 10
  br i1 %exitcond, label %if.end, label %for.body

if.else:                                          ; preds = %entry
  %mul = shl nsw i32 %N, 1
  br label %if.end

if.end:                                           ; preds = %for.body, %if.else
  %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.body ]
  ret i32 %sum.0
}

; Check that we handle calls to variadic functions correctly.
define i32 @callVariadicFunc(i32 %cond, i32 %N) {
; ENABLE-LABEL: callVariadicFunc:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    ; kill: def $w1 killed $w1 def $x1
; ENABLE-NEXT:    cbz w0, LBB8_2
; ENABLE-NEXT:  ; %bb.1: ; %if.then
; ENABLE-NEXT:    sub sp, sp, #64
; ENABLE-NEXT:    stp x29, x30, [sp, #48] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #48
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    stp x1, x1, [sp, #32]
; ENABLE-NEXT:    stp x1, x1, [sp, #16]
; ENABLE-NEXT:    stp x1, x1, [sp]
; ENABLE-NEXT:    mov w0, w1
; ENABLE-NEXT:    bl _someVariadicFunc
; ENABLE-NEXT:    lsl w0, w0, #3
; ENABLE-NEXT:    ldp x29, x30, [sp, #48] ; 16-byte Folded Reload
; ENABLE-NEXT:    add sp, sp, #64
; ENABLE-NEXT:    ret
; ENABLE-NEXT:  LBB8_2: ; %if.else
; ENABLE-NEXT:    lsl w0, w1, #1
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: callVariadicFunc:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    sub sp, sp, #64
; DISABLE-NEXT:    stp x29, x30, [sp, #48] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #48
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    ; kill: def $w1 killed $w1 def $x1
; DISABLE-NEXT:    cbz w0, LBB8_2
; DISABLE-NEXT:  ; %bb.1: ; %if.then
; DISABLE-NEXT:    stp x1, x1, [sp, #32]
; DISABLE-NEXT:    stp x1, x1, [sp, #16]
; DISABLE-NEXT:    stp x1, x1, [sp]
; DISABLE-NEXT:    mov w0, w1
; DISABLE-NEXT:    bl _someVariadicFunc
; DISABLE-NEXT:    lsl w0, w0, #3
; DISABLE-NEXT:    b LBB8_3
; DISABLE-NEXT:  LBB8_2: ; %if.else
; DISABLE-NEXT:    lsl w0, w1, #1
; DISABLE-NEXT:  LBB8_3: ; %if.end
; DISABLE-NEXT:    ldp x29, x30, [sp, #48] ; 16-byte Folded Reload
; DISABLE-NEXT:    add sp, sp, #64
; DISABLE-NEXT:    ret
entry:
  %tobool = icmp eq i32 %cond, 0
  br i1 %tobool, label %if.else, label %if.then

if.then:                                          ; preds = %entry
  %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N)
  %shl = shl i32 %call, 3
  br label %if.end

if.else:                                          ; preds = %entry
  %mul = shl nsw i32 %N, 1
  br label %if.end

if.end:                                           ; preds = %if.else, %if.then
  %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ]
  ret i32 %sum.0
}

declare i32 @someVariadicFunc(i32, ...)

; Make sure we do not insert unreachable code after noreturn function.
; Although this is not incorrect to insert such code, it is useless
; and it hurts the binary size.
;
define i32 @noreturn(i8 signext %bad_thing) {
; ENABLE-LABEL: noreturn:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    cbnz w0, LBB9_2
; ENABLE-NEXT:  ; %bb.1: ; %if.end
; ENABLE-NEXT:    mov w0, #42 ; =0x2a
; ENABLE-NEXT:    ret
; ENABLE-NEXT:  LBB9_2: ; %if.abort
; ENABLE-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
; ENABLE-NEXT:    mov x29, sp
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    bl _abort
;
; DISABLE-LABEL: noreturn:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
; DISABLE-NEXT:    mov x29, sp
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    cbnz w0, LBB9_2
; DISABLE-NEXT:  ; %bb.1: ; %if.end
; DISABLE-NEXT:    mov w0, #42 ; =0x2a
; DISABLE-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
; DISABLE-NEXT:  LBB9_2: ; %if.abort
; DISABLE-NEXT:    bl _abort
entry:
  %tobool = icmp eq i8 %bad_thing, 0
  br i1 %tobool, label %if.end, label %if.abort

if.abort:
  tail call void @abort() #0
  unreachable

if.end:
  ret i32 42
}

declare void @abort() #0

attributes #0 = { noreturn nounwind }

; Make sure that we handle infinite loops properly When checking that the Save
; and Restore blocks are control flow equivalent, the loop searches for the
; immediate (post) dominator for the (restore) save blocks. When either the Save
; or Restore block is located in an infinite loop the only immediate (post)
; dominator is itself. In this case, we cannot perform shrink wrapping, but we
; should return gracefully and continue compilation.
; The only condition for this test is the compilation finishes correctly.
;
define void @infiniteloop() {
; ENABLE-LABEL: infiniteloop:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    .cfi_offset w19, -24
; ENABLE-NEXT:    .cfi_offset w20, -32
; ENABLE-NEXT:    cbnz wzr, LBB10_3
; ENABLE-NEXT:  ; %bb.1: ; %if.then
; ENABLE-NEXT:    sub x19, sp, #16
; ENABLE-NEXT:    mov sp, x19
; ENABLE-NEXT:    mov w20, wzr
; ENABLE-NEXT:  LBB10_2: ; %for.body
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    bl _something
; ENABLE-NEXT:    add w20, w0, w20
; ENABLE-NEXT:    str w20, [x19]
; ENABLE-NEXT:    b LBB10_2
; ENABLE-NEXT:  LBB10_3: ; %if.end
; ENABLE-NEXT:    sub sp, x29, #16
; ENABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: infiniteloop:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    .cfi_offset w19, -24
; DISABLE-NEXT:    .cfi_offset w20, -32
; DISABLE-NEXT:    cbnz wzr, LBB10_3
; DISABLE-NEXT:  ; %bb.1: ; %if.then
; DISABLE-NEXT:    sub x19, sp, #16
; DISABLE-NEXT:    mov sp, x19
; DISABLE-NEXT:    mov w20, wzr
; DISABLE-NEXT:  LBB10_2: ; %for.body
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    bl _something
; DISABLE-NEXT:    add w20, w0, w20
; DISABLE-NEXT:    str w20, [x19]
; DISABLE-NEXT:    b LBB10_2
; DISABLE-NEXT:  LBB10_3: ; %if.end
; DISABLE-NEXT:    sub sp, x29, #16
; DISABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
entry:
  br i1 undef, label %if.then, label %if.end

if.then:
  %ptr = alloca i32, i32 4
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ]
  %call = tail call i32 @something()
  %add = add nsw i32 %call, %sum.03
  store i32 %add, ptr %ptr
  br label %for.body

if.end:
  ret void
}

; Another infinite loop test this time with a body bigger than just one block.
define void @infiniteloop2() {
; ENABLE-LABEL: infiniteloop2:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #16
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    .cfi_offset w19, -24
; ENABLE-NEXT:    .cfi_offset w20, -32
; ENABLE-NEXT:    cbnz wzr, LBB11_3
; ENABLE-NEXT:  ; %bb.1: ; %if.then
; ENABLE-NEXT:    sub x8, sp, #16
; ENABLE-NEXT:    mov sp, x8
; ENABLE-NEXT:    mov w9, wzr
; ENABLE-NEXT:  LBB11_2: ; %for.body
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    ; InlineAsm Start
; ENABLE-NEXT:    mov x10, #0 ; =0x0
; ENABLE-NEXT:    ; InlineAsm End
; ENABLE-NEXT:    add w10, w10, w9
; ENABLE-NEXT:    mov w9, #1 ; =0x1
; ENABLE-NEXT:    str w10, [x8]
; ENABLE-NEXT:    ; InlineAsm Start
; ENABLE-NEXT:    nop
; ENABLE-NEXT:    ; InlineAsm End
; ENABLE-NEXT:    b LBB11_2
; ENABLE-NEXT:  LBB11_3: ; %if.end
; ENABLE-NEXT:    sub sp, x29, #16
; ENABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: infiniteloop2:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #16
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    .cfi_offset w19, -24
; DISABLE-NEXT:    .cfi_offset w20, -32
; DISABLE-NEXT:    cbnz wzr, LBB11_3
; DISABLE-NEXT:  ; %bb.1: ; %if.then
; DISABLE-NEXT:    sub x8, sp, #16
; DISABLE-NEXT:    mov sp, x8
; DISABLE-NEXT:    mov w9, wzr
; DISABLE-NEXT:  LBB11_2: ; %for.body
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    ; InlineAsm Start
; DISABLE-NEXT:    mov x10, #0 ; =0x0
; DISABLE-NEXT:    ; InlineAsm End
; DISABLE-NEXT:    add w10, w10, w9
; DISABLE-NEXT:    mov w9, #1 ; =0x1
; DISABLE-NEXT:    str w10, [x8]
; DISABLE-NEXT:    ; InlineAsm Start
; DISABLE-NEXT:    nop
; DISABLE-NEXT:    ; InlineAsm End
; DISABLE-NEXT:    b LBB11_2
; DISABLE-NEXT:  LBB11_3: ; %if.end
; DISABLE-NEXT:    sub sp, x29, #16
; DISABLE-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
entry:
  br i1 undef, label %if.then, label %if.end

if.then:
  %ptr = alloca i32, i32 4
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2]
  %call = tail call i32 asm "mov $0, #0", "=r,~{x19}"()
  %add = add nsw i32 %call, %sum.03
  store i32 %add, ptr %ptr
  br i1 undef, label %body1, label %body2

body1:
  tail call void asm sideeffect "nop", "~{x19}"()
  br label %for.body

body2:
  tail call void asm sideeffect "nop", "~{x19}"()
  br label %for.body

if.end:
  ret void
}

; Another infinite loop test this time with two nested infinite loop.
define void @infiniteloop3() {
; ENABLE-LABEL: infiniteloop3:
; ENABLE:       ; %bb.0: ; %entry
; ENABLE-NEXT:    cbnz wzr, LBB12_5
; ENABLE-NEXT:  ; %bb.1: ; %loop2a.preheader
; ENABLE-NEXT:    mov x8, xzr
; ENABLE-NEXT:    mov x9, xzr
; ENABLE-NEXT:    mov x11, xzr
; ENABLE-NEXT:    b LBB12_3
; ENABLE-NEXT:  LBB12_2: ; %loop2b
; ENABLE-NEXT:    ; in Loop: Header=BB12_3 Depth=1
; ENABLE-NEXT:    str x10, [x11]
; ENABLE-NEXT:    mov x11, x10
; ENABLE-NEXT:  LBB12_3: ; %loop1
; ENABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; ENABLE-NEXT:    mov x10, x9
; ENABLE-NEXT:    ldr x9, [x8]
; ENABLE-NEXT:    cbnz x8, LBB12_2
; ENABLE-NEXT:  ; %bb.4: ; in Loop: Header=BB12_3 Depth=1
; ENABLE-NEXT:    mov x8, x10
; ENABLE-NEXT:    mov x11, x10
; ENABLE-NEXT:    b LBB12_3
; ENABLE-NEXT:  LBB12_5: ; %end
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: infiniteloop3:
; DISABLE:       ; %bb.0: ; %entry
; DISABLE-NEXT:    cbnz wzr, LBB12_5
; DISABLE-NEXT:  ; %bb.1: ; %loop2a.preheader
; DISABLE-NEXT:    mov x8, xzr
; DISABLE-NEXT:    mov x9, xzr
; DISABLE-NEXT:    mov x11, xzr
; DISABLE-NEXT:    b LBB12_3
; DISABLE-NEXT:  LBB12_2: ; %loop2b
; DISABLE-NEXT:    ; in Loop: Header=BB12_3 Depth=1
; DISABLE-NEXT:    str x10, [x11]
; DISABLE-NEXT:    mov x11, x10
; DISABLE-NEXT:  LBB12_3: ; %loop1
; DISABLE-NEXT:    ; =>This Inner Loop Header: Depth=1
; DISABLE-NEXT:    mov x10, x9
; DISABLE-NEXT:    ldr x9, [x8]
; DISABLE-NEXT:    cbnz x8, LBB12_2
; DISABLE-NEXT:  ; %bb.4: ; in Loop: Header=BB12_3 Depth=1
; DISABLE-NEXT:    mov x8, x10
; DISABLE-NEXT:    mov x11, x10
; DISABLE-NEXT:    b LBB12_3
; DISABLE-NEXT:  LBB12_5: ; %end
; DISABLE-NEXT:    ret
entry:
  br i1 undef, label %loop2a, label %body

body:                                             ; preds = %entry
  br i1 undef, label %loop2a, label %end

loop1:                                            ; preds = %loop2a, %loop2b
  %var.phi = phi ptr [ %next.phi, %loop2b ], [ %var, %loop2a ]
  %next.phi = phi ptr [ %next.load, %loop2b ], [ %next.var, %loop2a ]
  %0 = icmp eq ptr %var, null
  %next.load = load ptr, ptr undef
  br i1 %0, label %loop2a, label %loop2b

loop2a:                                           ; preds = %loop1, %body, %entry
  %var = phi ptr [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ]
  %next.var = phi ptr [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ]
  br label %loop1

loop2b:                                           ; preds = %loop1
  store ptr %next.phi, ptr %var.phi
  br label %loop1

end:
  ret void
}

; Re-aligned stack pointer.  See bug 26642.  Avoid clobbering live
; values in the prologue when re-aligning the stack pointer.
define i32 @stack_realign(i32 %a, i32 %b, ptr %ptr1, ptr %ptr2) {
; ENABLE-LABEL: stack_realign:
; ENABLE:       ; %bb.0:
; ENABLE-NEXT:    lsl w9, w0, w1
; ENABLE-NEXT:    lsl w8, w1, w0
; ENABLE-NEXT:    cmp w0, w1
; ENABLE-NEXT:    b.ge LBB13_2
; ENABLE-NEXT:  ; %bb.1: ; %true
; ENABLE-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
; ENABLE-NEXT:    mov x29, sp
; ENABLE-NEXT:    sub x1, sp, #16
; ENABLE-NEXT:    and sp, x1, #0xffffffffffffffe0
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    str w0, [sp]
; ENABLE-NEXT:    mov sp, x29
; ENABLE-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
; ENABLE-NEXT:  LBB13_2: ; %false
; ENABLE-NEXT:    str w9, [x2]
; ENABLE-NEXT:    str w8, [x3]
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: stack_realign:
; DISABLE:       ; %bb.0:
; DISABLE-NEXT:    stp x29, x30, [sp, #-16]! ; 16-byte Folded Spill
; DISABLE-NEXT:    mov x29, sp
; DISABLE-NEXT:    sub x9, sp, #16
; DISABLE-NEXT:    and sp, x9, #0xffffffffffffffe0
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    lsl w9, w0, w1
; DISABLE-NEXT:    lsl w8, w1, w0
; DISABLE-NEXT:    cmp w0, w1
; DISABLE-NEXT:    b.ge LBB13_2
; DISABLE-NEXT:  ; %bb.1: ; %true
; DISABLE-NEXT:    str w0, [sp]
; DISABLE-NEXT:  LBB13_2: ; %false
; DISABLE-NEXT:    str w9, [x2]
; DISABLE-NEXT:    str w8, [x3]
; DISABLE-NEXT:    mov sp, x29
; DISABLE-NEXT:    ldp x29, x30, [sp], #16 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
  %tmp = alloca i32, align 32
  %shl1 = shl i32 %a, %b
  %shl2 = shl i32 %b, %a
  %tmp2 = icmp slt i32 %a, %b
  br i1 %tmp2, label %true, label %false

true:
  store i32 %a, ptr %tmp, align 4
  %tmp4 = load i32, ptr %tmp
  br label %false

false:
  %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
  store i32 %shl1, ptr %ptr1
  store i32 %shl2, ptr %ptr2
  ret i32 %tmp.0
}

; Re-aligned stack pointer with all caller-save regs live.  See bug
; 26642.  In this case we currently avoid shrink wrapping because
; ensuring we have a scratch register to re-align the stack pointer is
; too complicated.  Output should be the same for both enabled and
; disabled shrink wrapping.
define void @stack_realign2(i32 %a, i32 %b, ptr %ptr1, ptr %ptr2, ptr %ptr3, ptr %ptr4, ptr %ptr5, ptr %ptr6) {
; ENABLE-LABEL: stack_realign2:
; ENABLE:       ; %bb.0:
; ENABLE-NEXT:    stp x28, x27, [sp, #-96]! ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x26, x25, [sp, #16] ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x24, x23, [sp, #32] ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x22, x21, [sp, #48] ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x20, x19, [sp, #64] ; 16-byte Folded Spill
; ENABLE-NEXT:    stp x29, x30, [sp, #80] ; 16-byte Folded Spill
; ENABLE-NEXT:    add x29, sp, #80
; ENABLE-NEXT:    sub x9, sp, #32
; ENABLE-NEXT:    and sp, x9, #0xffffffffffffffe0
; ENABLE-NEXT:    .cfi_def_cfa w29, 16
; ENABLE-NEXT:    .cfi_offset w30, -8
; ENABLE-NEXT:    .cfi_offset w29, -16
; ENABLE-NEXT:    .cfi_offset w19, -24
; ENABLE-NEXT:    .cfi_offset w20, -32
; ENABLE-NEXT:    .cfi_offset w21, -40
; ENABLE-NEXT:    .cfi_offset w22, -48
; ENABLE-NEXT:    .cfi_offset w23, -56
; ENABLE-NEXT:    .cfi_offset w24, -64
; ENABLE-NEXT:    .cfi_offset w25, -72
; ENABLE-NEXT:    .cfi_offset w26, -80
; ENABLE-NEXT:    .cfi_offset w27, -88
; ENABLE-NEXT:    .cfi_offset w28, -96
; ENABLE-NEXT:    lsl w8, w1, w0
; ENABLE-NEXT:    lsr w9, w0, w1
; ENABLE-NEXT:    lsl w14, w0, w1
; ENABLE-NEXT:    lsr w11, w1, w0
; ENABLE-NEXT:    add w15, w1, w0
; ENABLE-NEXT:    sub w10, w8, w9
; ENABLE-NEXT:    subs w17, w1, w0
; ENABLE-NEXT:    add w16, w14, w8
; ENABLE-NEXT:    add w12, w9, w11
; ENABLE-NEXT:    add w13, w11, w15
; ENABLE-NEXT:    b.le LBB14_2
; ENABLE-NEXT:  ; %bb.1: ; %true
; ENABLE-NEXT:    str w0, [sp]
; ENABLE-NEXT:    ; InlineAsm Start
; ENABLE-NEXT:    nop
; ENABLE-NEXT:    ; InlineAsm End
; ENABLE-NEXT:  LBB14_2: ; %false
; ENABLE-NEXT:    str w14, [x2]
; ENABLE-NEXT:    str w8, [x3]
; ENABLE-NEXT:    str w9, [x4]
; ENABLE-NEXT:    str w11, [x5]
; ENABLE-NEXT:    str w15, [x6]
; ENABLE-NEXT:    str w17, [x7]
; ENABLE-NEXT:    stp w0, w1, [x2, #4]
; ENABLE-NEXT:    stp w16, w10, [x2, #12]
; ENABLE-NEXT:    stp w12, w13, [x2, #20]
; ENABLE-NEXT:    sub sp, x29, #80
; ENABLE-NEXT:    ldp x29, x30, [sp, #80] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x20, x19, [sp, #64] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x22, x21, [sp, #48] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x24, x23, [sp, #32] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x26, x25, [sp, #16] ; 16-byte Folded Reload
; ENABLE-NEXT:    ldp x28, x27, [sp], #96 ; 16-byte Folded Reload
; ENABLE-NEXT:    ret
;
; DISABLE-LABEL: stack_realign2:
; DISABLE:       ; %bb.0:
; DISABLE-NEXT:    stp x28, x27, [sp, #-96]! ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x26, x25, [sp, #16] ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x24, x23, [sp, #32] ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x22, x21, [sp, #48] ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x20, x19, [sp, #64] ; 16-byte Folded Spill
; DISABLE-NEXT:    stp x29, x30, [sp, #80] ; 16-byte Folded Spill
; DISABLE-NEXT:    add x29, sp, #80
; DISABLE-NEXT:    sub x9, sp, #32
; DISABLE-NEXT:    and sp, x9, #0xffffffffffffffe0
; DISABLE-NEXT:    .cfi_def_cfa w29, 16
; DISABLE-NEXT:    .cfi_offset w30, -8
; DISABLE-NEXT:    .cfi_offset w29, -16
; DISABLE-NEXT:    .cfi_offset w19, -24
; DISABLE-NEXT:    .cfi_offset w20, -32
; DISABLE-NEXT:    .cfi_offset w21, -40
; DISABLE-NEXT:    .cfi_offset w22, -48
; DISABLE-NEXT:    .cfi_offset w23, -56
; DISABLE-NEXT:    .cfi_offset w24, -64
; DISABLE-NEXT:    .cfi_offset w25, -72
; DISABLE-NEXT:    .cfi_offset w26, -80
; DISABLE-NEXT:    .cfi_offset w27, -88
; DISABLE-NEXT:    .cfi_offset w28, -96
; DISABLE-NEXT:    lsl w8, w1, w0
; DISABLE-NEXT:    lsr w9, w0, w1
; DISABLE-NEXT:    lsl w14, w0, w1
; DISABLE-NEXT:    lsr w11, w1, w0
; DISABLE-NEXT:    add w15, w1, w0
; DISABLE-NEXT:    sub w10, w8, w9
; DISABLE-NEXT:    subs w17, w1, w0
; DISABLE-NEXT:    add w16, w14, w8
; DISABLE-NEXT:    add w12, w9, w11
; DISABLE-NEXT:    add w13, w11, w15
; DISABLE-NEXT:    b.le LBB14_2
; DISABLE-NEXT:  ; %bb.1: ; %true
; DISABLE-NEXT:    str w0, [sp]
; DISABLE-NEXT:    ; InlineAsm Start
; DISABLE-NEXT:    nop
; DISABLE-NEXT:    ; InlineAsm End
; DISABLE-NEXT:  LBB14_2: ; %false
; DISABLE-NEXT:    str w14, [x2]
; DISABLE-NEXT:    str w8, [x3]
; DISABLE-NEXT:    str w9, [x4]
; DISABLE-NEXT:    str w11, [x5]
; DISABLE-NEXT:    str w15, [x6]
; DISABLE-NEXT:    str w17, [x7]
; DISABLE-NEXT:    stp w0, w1, [x2, #4]
; DISABLE-NEXT:    stp w16, w10, [x2, #12]
; DISABLE-NEXT:    stp w12, w13, [x2, #20]
; DISABLE-NEXT:    sub sp, x29, #80
; DISABLE-NEXT:    ldp x29, x30, [sp, #80] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x20, x19, [sp, #64] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x22, x21, [sp, #48] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x24, x23, [sp, #32] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x26, x25, [sp, #16] ; 16-byte Folded Reload
; DISABLE-NEXT:    ldp x28, x27, [sp], #96 ; 16-byte Folded Reload
; DISABLE-NEXT:    ret
  %tmp = alloca i32, align 32
  %tmp1 = shl i32 %a, %b
  %tmp2 = shl i32 %b, %a
  %tmp3 = lshr i32 %a, %b
  %tmp4 = lshr i32 %b, %a
  %tmp5 = add i32 %b, %a
  %tmp6 = sub i32 %b, %a
  %tmp7 = add i32 %tmp1, %tmp2
  %tmp8 = sub i32 %tmp2, %tmp3
  %tmp9 = add i32 %tmp3, %tmp4
  %tmp10 = add i32 %tmp4, %tmp5
  %cmp = icmp slt i32 %a, %b
  br i1 %cmp, label %true, label %false

true:
  store i32 %a, ptr %tmp, align 4
  call void asm sideeffect "nop", "~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28}"() nounwind
  br label %false

false:
  store i32 %tmp1, ptr %ptr1, align 4
  store i32 %tmp2, ptr %ptr2, align 4
  store i32 %tmp3, ptr %ptr3, align 4
  store i32 %tmp4, ptr %ptr4, align 4
  store i32 %tmp5, ptr %ptr5, align 4
  store i32 %tmp6, ptr %ptr6, align 4
  %idx1 = getelementptr inbounds i32, ptr %ptr1, i64 1
  store i32 %a, ptr %idx1, align 4
  %idx2 = getelementptr inbounds i32, ptr %ptr1, i64 2
  store i32 %b, ptr %idx2, align 4
  %idx3 = getelementptr inbounds i32, ptr %ptr1, i64 3
  store i32 %tmp7, ptr %idx3, align 4
  %idx4 = getelementptr inbounds i32, ptr %ptr1, i64 4
  store i32 %tmp8, ptr %idx4, align 4
  %idx5 = getelementptr inbounds i32, ptr %ptr1, i64 5
  store i32 %tmp9, ptr %idx5, align 4
  %idx6 = getelementptr inbounds i32, ptr %ptr1, i64 6
  store i32 %tmp10, ptr %idx6, align 4

  ret void
}