; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumb-macho | FileCheck %s --check-prefix=ENABLE-V4T ; RUN: llc %s -o - -enable-shrink-wrap=true -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumbv5-macho | FileCheck %s --check-prefix=ENABLE-V5T ; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumb-macho | FileCheck %s --check-prefix=DISABLE-V4T ; RUN: llc %s -o - -enable-shrink-wrap=false -ifcvt-fn-start=1 -ifcvt-fn-stop=0 -tail-dup-placement=0 -mtriple=thumbv5-macho | FileCheck %s --check-prefix=DISABLE-V5T ; ; Note: Lots of tests use inline asm instead of regular calls. ; This allows to have a better control on what the allocation will do. ; Otherwise, we may have spill right in the entry block, defeating ; shrink-wrapping. Moreover, some of the inline asm statements (nop) ; are here to ensure that the related paths do not end up as critical ; edges. ; Also disable the late if-converter as it makes harder to reason on ; the diffs. ; Disable tail-duplication during placement, as v4t vs v5t get different ; results due to branches not being analyzable under v5 ; Initial motivating example: Simple diamond with a call just on one side. define i32 @foo(i32 %a, i32 %b) { ; ENABLE-V4T-LABEL: foo: ; ENABLE-V4T: @ %bb.0: ; ENABLE-V4T-NEXT: cmp r0, r1 ; ENABLE-V4T-NEXT: bge LBB0_2 ; ENABLE-V4T-NEXT: @ %bb.1: @ %true ; ENABLE-V4T-NEXT: push {r7, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r7, -8 ; ENABLE-V4T-NEXT: sub sp, #8 ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 16 ; ENABLE-V4T-NEXT: str r0, [sp, #4] ; ENABLE-V4T-NEXT: ldr r0, LCPI0_0 ; ENABLE-V4T-NEXT: LPC0_0: ; ENABLE-V4T-NEXT: add r0, pc ; ENABLE-V4T-NEXT: ldr r2, [r0] ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: add r1, sp, #4 ; ENABLE-V4T-NEXT: bl Ltmp0 ; ENABLE-V4T-NEXT: add sp, #8 ; ENABLE-V4T-NEXT: pop {r7} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: mov lr, r1 ; ENABLE-V4T-NEXT: LBB0_2: @ %false ; ENABLE-V4T-NEXT: bx lr ; ENABLE-V4T-NEXT: .p2align 2 ; ENABLE-V4T-NEXT: @ %bb.3: ; ENABLE-V4T-NEXT: .data_region ; ENABLE-V4T-NEXT: LCPI0_0: ; ENABLE-V4T-NEXT: .long L_doSomething$non_lazy_ptr-(LPC0_0+4) ; ENABLE-V4T-NEXT: .end_data_region ; ; ENABLE-V5T-LABEL: foo: ; ENABLE-V5T: @ %bb.0: ; ENABLE-V5T-NEXT: cmp r0, r1 ; ENABLE-V5T-NEXT: bge LBB0_2 ; ENABLE-V5T-NEXT: @ %bb.1: @ %true ; ENABLE-V5T-NEXT: push {r7, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r7, -8 ; ENABLE-V5T-NEXT: sub sp, #8 ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 16 ; ENABLE-V5T-NEXT: str r0, [sp, #4] ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: add r1, sp, #4 ; ENABLE-V5T-NEXT: bl _doSomething ; ENABLE-V5T-NEXT: add sp, #8 ; ENABLE-V5T-NEXT: pop {r7, pc} ; ENABLE-V5T-NEXT: LBB0_2: @ %false ; ENABLE-V5T-NEXT: bx lr ; ; DISABLE-V4T-LABEL: foo: ; DISABLE-V4T: @ %bb.0: ; DISABLE-V4T-NEXT: push {r7, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r7, -8 ; DISABLE-V4T-NEXT: sub sp, #8 ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 16 ; DISABLE-V4T-NEXT: cmp r0, r1 ; DISABLE-V4T-NEXT: bge LBB0_2 ; DISABLE-V4T-NEXT: @ %bb.1: @ %true ; DISABLE-V4T-NEXT: str r0, [sp, #4] ; DISABLE-V4T-NEXT: ldr r0, LCPI0_0 ; DISABLE-V4T-NEXT: LPC0_0: ; DISABLE-V4T-NEXT: add r0, pc ; DISABLE-V4T-NEXT: ldr r2, [r0] ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: add r1, sp, #4 ; DISABLE-V4T-NEXT: bl Ltmp0 ; DISABLE-V4T-NEXT: LBB0_2: @ %false ; DISABLE-V4T-NEXT: add sp, #8 ; DISABLE-V4T-NEXT: pop {r7} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; DISABLE-V4T-NEXT: .p2align 2 ; DISABLE-V4T-NEXT: @ %bb.3: ; DISABLE-V4T-NEXT: .data_region ; DISABLE-V4T-NEXT: LCPI0_0: ; DISABLE-V4T-NEXT: .long L_doSomething$non_lazy_ptr-(LPC0_0+4) ; DISABLE-V4T-NEXT: .end_data_region ; ; DISABLE-V5T-LABEL: foo: ; DISABLE-V5T: @ %bb.0: ; DISABLE-V5T-NEXT: push {r7, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r7, -8 ; DISABLE-V5T-NEXT: sub sp, #8 ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 16 ; DISABLE-V5T-NEXT: cmp r0, r1 ; DISABLE-V5T-NEXT: bge LBB0_2 ; DISABLE-V5T-NEXT: @ %bb.1: @ %true ; DISABLE-V5T-NEXT: str r0, [sp, #4] ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: add r1, sp, #4 ; DISABLE-V5T-NEXT: bl _doSomething ; DISABLE-V5T-NEXT: LBB0_2: @ %false ; DISABLE-V5T-NEXT: add sp, #8 ; DISABLE-V5T-NEXT: pop {r7, pc} %tmp = alloca i32, align 4 %tmp2 = icmp slt i32 %a, %b br i1 %tmp2, label %true, label %false true: store i32 %a, i32* %tmp, align 4 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) br label %false false: %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] ret i32 %tmp.0 } ; Same, but the final BB is non-trivial, so we don't duplicate the return inst. define i32 @bar(i32 %a, i32 %b) { ; ENABLE-V4T-LABEL: bar: ; ENABLE-V4T: @ %bb.0: ; ENABLE-V4T-NEXT: cmp r0, r1 ; ENABLE-V4T-NEXT: bge LBB1_2 ; ENABLE-V4T-NEXT: @ %bb.1: @ %true ; ENABLE-V4T-NEXT: push {r7, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r7, -8 ; ENABLE-V4T-NEXT: sub sp, #8 ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 16 ; ENABLE-V4T-NEXT: str r0, [sp, #4] ; ENABLE-V4T-NEXT: ldr r0, LCPI1_0 ; ENABLE-V4T-NEXT: LPC1_0: ; ENABLE-V4T-NEXT: add r0, pc ; ENABLE-V4T-NEXT: ldr r2, [r0] ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: add r1, sp, #4 ; ENABLE-V4T-NEXT: bl Ltmp1 ; ENABLE-V4T-NEXT: add sp, #8 ; ENABLE-V4T-NEXT: pop {r7} ; ENABLE-V4T-NEXT: pop {r0} ; ENABLE-V4T-NEXT: mov lr, r0 ; ENABLE-V4T-NEXT: LBB1_2: @ %false ; ENABLE-V4T-NEXT: movs r0, #42 ; ENABLE-V4T-NEXT: bx lr ; ENABLE-V4T-NEXT: .p2align 2 ; ENABLE-V4T-NEXT: @ %bb.3: ; ENABLE-V4T-NEXT: .data_region ; ENABLE-V4T-NEXT: LCPI1_0: ; ENABLE-V4T-NEXT: .long L_doSomething$non_lazy_ptr-(LPC1_0+4) ; ENABLE-V4T-NEXT: .end_data_region ; ; ENABLE-V5T-LABEL: bar: ; ENABLE-V5T: @ %bb.0: ; ENABLE-V5T-NEXT: cmp r0, r1 ; ENABLE-V5T-NEXT: bge LBB1_2 ; ENABLE-V5T-NEXT: @ %bb.1: @ %true ; ENABLE-V5T-NEXT: push {r7, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r7, -8 ; ENABLE-V5T-NEXT: sub sp, #8 ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 16 ; ENABLE-V5T-NEXT: str r0, [sp, #4] ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: add r1, sp, #4 ; ENABLE-V5T-NEXT: bl _doSomething ; ENABLE-V5T-NEXT: add sp, #8 ; ENABLE-V5T-NEXT: pop {r7} ; ENABLE-V5T-NEXT: pop {r0} ; ENABLE-V5T-NEXT: mov lr, r0 ; ENABLE-V5T-NEXT: LBB1_2: @ %false ; ENABLE-V5T-NEXT: movs r0, #42 ; ENABLE-V5T-NEXT: bx lr ; ; DISABLE-V4T-LABEL: bar: ; DISABLE-V4T: @ %bb.0: ; DISABLE-V4T-NEXT: push {r7, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r7, -8 ; DISABLE-V4T-NEXT: sub sp, #8 ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 16 ; DISABLE-V4T-NEXT: cmp r0, r1 ; DISABLE-V4T-NEXT: bge LBB1_2 ; DISABLE-V4T-NEXT: @ %bb.1: @ %true ; DISABLE-V4T-NEXT: str r0, [sp, #4] ; DISABLE-V4T-NEXT: ldr r0, LCPI1_0 ; DISABLE-V4T-NEXT: LPC1_0: ; DISABLE-V4T-NEXT: add r0, pc ; DISABLE-V4T-NEXT: ldr r2, [r0] ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: add r1, sp, #4 ; DISABLE-V4T-NEXT: bl Ltmp1 ; DISABLE-V4T-NEXT: LBB1_2: @ %false ; DISABLE-V4T-NEXT: movs r0, #42 ; DISABLE-V4T-NEXT: add sp, #8 ; DISABLE-V4T-NEXT: pop {r7} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; DISABLE-V4T-NEXT: .p2align 2 ; DISABLE-V4T-NEXT: @ %bb.3: ; DISABLE-V4T-NEXT: .data_region ; DISABLE-V4T-NEXT: LCPI1_0: ; DISABLE-V4T-NEXT: .long L_doSomething$non_lazy_ptr-(LPC1_0+4) ; DISABLE-V4T-NEXT: .end_data_region ; ; DISABLE-V5T-LABEL: bar: ; DISABLE-V5T: @ %bb.0: ; DISABLE-V5T-NEXT: push {r7, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r7, -8 ; DISABLE-V5T-NEXT: sub sp, #8 ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 16 ; DISABLE-V5T-NEXT: cmp r0, r1 ; DISABLE-V5T-NEXT: bge LBB1_2 ; DISABLE-V5T-NEXT: @ %bb.1: @ %true ; DISABLE-V5T-NEXT: str r0, [sp, #4] ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: add r1, sp, #4 ; DISABLE-V5T-NEXT: bl _doSomething ; DISABLE-V5T-NEXT: LBB1_2: @ %false ; DISABLE-V5T-NEXT: movs r0, #42 ; DISABLE-V5T-NEXT: add sp, #8 ; DISABLE-V5T-NEXT: pop {r7, pc} %tmp = alloca i32, align 4 %tmp2 = icmp slt i32 %a, %b br i1 %tmp2, label %true, label %false true: store i32 %a, i32* %tmp, align 4 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) br label %false false: ret i32 42 } ; Function Attrs: optsize declare i32 @doSomething(i32, i32*) ; Check that we do not perform the restore inside the loop whereas the save ; is outside. define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) { ; ENABLE-V4T-LABEL: freqSaveAndRestoreOutsideLoop: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: cmp r0, #0 ; ENABLE-V4T-NEXT: beq LBB2_4 ; ENABLE-V4T-NEXT: @ %bb.1: @ %for.preheader ; ENABLE-V4T-NEXT: push {r4, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r4, -8 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: mov r8, r8 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: movs r1, #10 ; ENABLE-V4T-NEXT: LBB2_2: @ %for.body ; ENABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: movs r2, #1 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: adds r0, r2, r0 ; ENABLE-V4T-NEXT: subs r1, r1, #1 ; ENABLE-V4T-NEXT: bne LBB2_2 ; ENABLE-V4T-NEXT: @ %bb.3: @ %for.end ; ENABLE-V4T-NEXT: lsls r0, r0, #3 ; ENABLE-V4T-NEXT: pop {r4} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: bx r1 ; ENABLE-V4T-NEXT: LBB2_4: @ %if.else ; ENABLE-V4T-NEXT: lsls r0, r1, #1 ; ENABLE-V4T-NEXT: bx lr ; ; ENABLE-V5T-LABEL: freqSaveAndRestoreOutsideLoop: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: cmp r0, #0 ; ENABLE-V5T-NEXT: beq LBB2_4 ; ENABLE-V5T-NEXT: @ %bb.1: @ %for.preheader ; ENABLE-V5T-NEXT: push {r4, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r4, -8 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: mov r8, r8 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: movs r1, #10 ; ENABLE-V5T-NEXT: LBB2_2: @ %for.body ; ENABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: movs r2, #1 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: adds r0, r2, r0 ; ENABLE-V5T-NEXT: subs r1, r1, #1 ; ENABLE-V5T-NEXT: bne LBB2_2 ; ENABLE-V5T-NEXT: @ %bb.3: @ %for.end ; ENABLE-V5T-NEXT: lsls r0, r0, #3 ; ENABLE-V5T-NEXT: pop {r4, pc} ; ENABLE-V5T-NEXT: LBB2_4: @ %if.else ; ENABLE-V5T-NEXT: lsls r0, r1, #1 ; ENABLE-V5T-NEXT: LBB2_5: @ %if.end ; ENABLE-V5T-NEXT: bx lr ; ; DISABLE-V4T-LABEL: freqSaveAndRestoreOutsideLoop: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r4, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r4, -8 ; DISABLE-V4T-NEXT: cmp r0, #0 ; DISABLE-V4T-NEXT: beq LBB2_4 ; DISABLE-V4T-NEXT: @ %bb.1: @ %for.preheader ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: mov r8, r8 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: movs r1, #10 ; DISABLE-V4T-NEXT: LBB2_2: @ %for.body ; DISABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: movs r2, #1 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: adds r0, r2, r0 ; DISABLE-V4T-NEXT: subs r1, r1, #1 ; DISABLE-V4T-NEXT: bne LBB2_2 ; DISABLE-V4T-NEXT: @ %bb.3: @ %for.end ; DISABLE-V4T-NEXT: lsls r0, r0, #3 ; DISABLE-V4T-NEXT: b LBB2_5 ; DISABLE-V4T-NEXT: LBB2_4: @ %if.else ; DISABLE-V4T-NEXT: lsls r0, r1, #1 ; DISABLE-V4T-NEXT: LBB2_5: @ %if.end ; DISABLE-V4T-NEXT: pop {r4} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; ; DISABLE-V5T-LABEL: freqSaveAndRestoreOutsideLoop: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r4, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r4, -8 ; DISABLE-V5T-NEXT: cmp r0, #0 ; DISABLE-V5T-NEXT: beq LBB2_4 ; DISABLE-V5T-NEXT: @ %bb.1: @ %for.preheader ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: mov r8, r8 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: movs r1, #10 ; DISABLE-V5T-NEXT: LBB2_2: @ %for.body ; DISABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: movs r2, #1 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: adds r0, r2, r0 ; DISABLE-V5T-NEXT: subs r1, r1, #1 ; DISABLE-V5T-NEXT: bne LBB2_2 ; DISABLE-V5T-NEXT: @ %bb.3: @ %for.end ; DISABLE-V5T-NEXT: lsls r0, r0, #3 ; DISABLE-V5T-NEXT: pop {r4, pc} ; DISABLE-V5T-NEXT: LBB2_4: @ %if.else ; DISABLE-V5T-NEXT: lsls r0, r1, #1 ; DISABLE-V5T-NEXT: pop {r4, pc} entry: %tobool = icmp eq i32 %cond, 0 br i1 %tobool, label %if.else, label %for.preheader for.preheader: tail call void asm "nop", ""() br label %for.body for.body: ; preds = %entry, %for.body %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() %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-V4T-LABEL: freqSaveAndRestoreOutsideLoop2: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: push {r4, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r4, -8 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: mov r8, r8 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: movs r1, #10 ; ENABLE-V4T-NEXT: LBB3_1: @ %for.body ; ENABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: movs r2, #1 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: adds r0, r2, r0 ; ENABLE-V4T-NEXT: subs r1, r1, #1 ; ENABLE-V4T-NEXT: bne LBB3_1 ; ENABLE-V4T-NEXT: @ %bb.2: @ %for.exit ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: mov r8, r8 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: pop {r4} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: bx r1 ; ; ENABLE-V5T-LABEL: freqSaveAndRestoreOutsideLoop2: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: push {r4, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r4, -8 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: mov r8, r8 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: movs r1, #10 ; ENABLE-V5T-NEXT: LBB3_1: @ %for.body ; ENABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: movs r2, #1 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: adds r0, r2, r0 ; ENABLE-V5T-NEXT: subs r1, r1, #1 ; ENABLE-V5T-NEXT: bne LBB3_1 ; ENABLE-V5T-NEXT: @ %bb.2: @ %for.exit ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: mov r8, r8 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: pop {r4, pc} ; ENABLE-V5T-NEXT: LBB3_3: @ %for.end ; ENABLE-V5T-NEXT: bx lr ; ; DISABLE-V4T-LABEL: freqSaveAndRestoreOutsideLoop2: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r4, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r4, -8 ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: mov r8, r8 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: movs r1, #10 ; DISABLE-V4T-NEXT: LBB3_1: @ %for.body ; DISABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: movs r2, #1 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: adds r0, r2, r0 ; DISABLE-V4T-NEXT: subs r1, r1, #1 ; DISABLE-V4T-NEXT: bne LBB3_1 ; DISABLE-V4T-NEXT: @ %bb.2: @ %for.exit ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: mov r8, r8 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: pop {r4} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; ; DISABLE-V5T-LABEL: freqSaveAndRestoreOutsideLoop2: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r4, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r4, -8 ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: mov r8, r8 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: movs r1, #10 ; DISABLE-V5T-NEXT: LBB3_1: @ %for.body ; DISABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: movs r2, #1 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: adds r0, r2, r0 ; DISABLE-V5T-NEXT: subs r1, r1, #1 ; DISABLE-V5T-NEXT: bne LBB3_1 ; DISABLE-V5T-NEXT: @ %bb.2: @ %for.exit ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: mov r8, r8 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: pop {r4, pc} entry: br label %for.preheader for.preheader: tail call void asm "nop", ""() br label %for.body for.body: ; preds = %for.body, %entry %i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ] %sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ] %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() %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.exit, label %for.body for.exit: tail call void asm "nop", ""() br label %for.end 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-V4T-LABEL: loopInfoSaveOutsideLoop: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: cmp r0, #0 ; ENABLE-V4T-NEXT: beq LBB4_4 ; ENABLE-V4T-NEXT: @ %bb.1: @ %for.preheader ; ENABLE-V4T-NEXT: push {r4, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r4, -8 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: mov r8, r8 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: movs r1, #10 ; ENABLE-V4T-NEXT: LBB4_2: @ %for.body ; ENABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: movs r2, #1 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: adds r0, r2, r0 ; ENABLE-V4T-NEXT: subs r1, r1, #1 ; ENABLE-V4T-NEXT: bne LBB4_2 ; ENABLE-V4T-NEXT: @ %bb.3: @ %for.end ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: mov r8, r8 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: lsls r0, r0, #3 ; ENABLE-V4T-NEXT: pop {r4} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: bx r1 ; ENABLE-V4T-NEXT: LBB4_4: @ %if.else ; ENABLE-V4T-NEXT: lsls r0, r1, #1 ; ENABLE-V4T-NEXT: bx lr ; ; ENABLE-V5T-LABEL: loopInfoSaveOutsideLoop: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: cmp r0, #0 ; ENABLE-V5T-NEXT: beq LBB4_4 ; ENABLE-V5T-NEXT: @ %bb.1: @ %for.preheader ; ENABLE-V5T-NEXT: push {r4, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r4, -8 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: mov r8, r8 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: movs r1, #10 ; ENABLE-V5T-NEXT: LBB4_2: @ %for.body ; ENABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: movs r2, #1 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: adds r0, r2, r0 ; ENABLE-V5T-NEXT: subs r1, r1, #1 ; ENABLE-V5T-NEXT: bne LBB4_2 ; ENABLE-V5T-NEXT: @ %bb.3: @ %for.end ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: mov r8, r8 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: lsls r0, r0, #3 ; ENABLE-V5T-NEXT: pop {r4, pc} ; ENABLE-V5T-NEXT: LBB4_4: @ %if.else ; ENABLE-V5T-NEXT: lsls r0, r1, #1 ; ENABLE-V5T-NEXT: LBB4_5: @ %if.end ; ENABLE-V5T-NEXT: bx lr ; ; DISABLE-V4T-LABEL: loopInfoSaveOutsideLoop: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r4, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r4, -8 ; DISABLE-V4T-NEXT: cmp r0, #0 ; DISABLE-V4T-NEXT: beq LBB4_4 ; DISABLE-V4T-NEXT: @ %bb.1: @ %for.preheader ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: mov r8, r8 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: movs r1, #10 ; DISABLE-V4T-NEXT: LBB4_2: @ %for.body ; DISABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: movs r2, #1 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: adds r0, r2, r0 ; DISABLE-V4T-NEXT: subs r1, r1, #1 ; DISABLE-V4T-NEXT: bne LBB4_2 ; DISABLE-V4T-NEXT: @ %bb.3: @ %for.end ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: mov r8, r8 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: lsls r0, r0, #3 ; DISABLE-V4T-NEXT: b LBB4_5 ; DISABLE-V4T-NEXT: LBB4_4: @ %if.else ; DISABLE-V4T-NEXT: lsls r0, r1, #1 ; DISABLE-V4T-NEXT: LBB4_5: @ %if.end ; DISABLE-V4T-NEXT: pop {r4} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; ; DISABLE-V5T-LABEL: loopInfoSaveOutsideLoop: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r4, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r4, -8 ; DISABLE-V5T-NEXT: cmp r0, #0 ; DISABLE-V5T-NEXT: beq LBB4_4 ; DISABLE-V5T-NEXT: @ %bb.1: @ %for.preheader ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: mov r8, r8 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: movs r1, #10 ; DISABLE-V5T-NEXT: LBB4_2: @ %for.body ; DISABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: movs r2, #1 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: adds r0, r2, r0 ; DISABLE-V5T-NEXT: subs r1, r1, #1 ; DISABLE-V5T-NEXT: bne LBB4_2 ; DISABLE-V5T-NEXT: @ %bb.3: @ %for.end ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: mov r8, r8 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: lsls r0, r0, #3 ; DISABLE-V5T-NEXT: pop {r4, pc} ; DISABLE-V5T-NEXT: LBB4_4: @ %if.else ; DISABLE-V5T-NEXT: lsls r0, r1, #1 ; DISABLE-V5T-NEXT: pop {r4, pc} entry: %tobool = icmp eq i32 %cond, 0 br i1 %tobool, label %if.else, label %for.preheader for.preheader: tail call void asm "nop", ""() br label %for.body for.body: ; preds = %entry, %for.body %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() %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 asm "nop", "~{r4}"() %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 { ; ENABLE-V4T-LABEL: loopInfoRestoreOutsideLoop: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: cmp r0, #0 ; ENABLE-V4T-NEXT: beq LBB5_4 ; ENABLE-V4T-NEXT: @ %bb.1: @ %if.then ; ENABLE-V4T-NEXT: push {r4, lr} ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: mov r8, r8 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: movs r1, #10 ; ENABLE-V4T-NEXT: LBB5_2: @ %for.body ; ENABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: movs r2, #1 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: adds r0, r2, r0 ; ENABLE-V4T-NEXT: subs r1, r1, #1 ; ENABLE-V4T-NEXT: bne LBB5_2 ; ENABLE-V4T-NEXT: @ %bb.3: @ %for.end ; ENABLE-V4T-NEXT: lsls r0, r0, #3 ; ENABLE-V4T-NEXT: pop {r4} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: bx r1 ; ENABLE-V4T-NEXT: LBB5_4: @ %if.else ; ENABLE-V4T-NEXT: lsls r0, r1, #1 ; ENABLE-V4T-NEXT: bx lr ; ENABLE-V4T-NEXT: @ -- End function ; ENABLE-V4T-NEXT: .globl _emptyFrame @ -- Begin function emptyFrame ; ENABLE-V4T-NEXT: .p2align 1 ; ENABLE-V4T-NEXT: .code 16 @ @emptyFrame ; ENABLE-V4T-NEXT: .thumb_func _emptyFrame ; ENABLE-V4T-NEXT: _emptyFrame: ; ENABLE-V4T-NEXT: .cfi_startproc ; ENABLE-V4T-NEXT: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: bx lr ; ; ENABLE-V5T-LABEL: loopInfoRestoreOutsideLoop: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: cmp r0, #0 ; ENABLE-V5T-NEXT: beq LBB5_4 ; ENABLE-V5T-NEXT: @ %bb.1: @ %if.then ; ENABLE-V5T-NEXT: push {r4, lr} ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: mov r8, r8 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: movs r1, #10 ; ENABLE-V5T-NEXT: LBB5_2: @ %for.body ; ENABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: movs r2, #1 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: adds r0, r2, r0 ; ENABLE-V5T-NEXT: subs r1, r1, #1 ; ENABLE-V5T-NEXT: bne LBB5_2 ; ENABLE-V5T-NEXT: @ %bb.3: @ %for.end ; ENABLE-V5T-NEXT: lsls r0, r0, #3 ; ENABLE-V5T-NEXT: pop {r4, pc} ; ENABLE-V5T-NEXT: LBB5_4: @ %if.else ; ENABLE-V5T-NEXT: lsls r0, r1, #1 ; ENABLE-V5T-NEXT: LBB5_5: @ %if.end ; ENABLE-V5T-NEXT: bx lr ; ENABLE-V5T-NEXT: @ -- End function ; ENABLE-V5T-NEXT: .globl _emptyFrame @ -- Begin function emptyFrame ; ENABLE-V5T-NEXT: .p2align 1 ; ENABLE-V5T-NEXT: .code 16 @ @emptyFrame ; ENABLE-V5T-NEXT: .thumb_func _emptyFrame ; ENABLE-V5T-NEXT: _emptyFrame: ; ENABLE-V5T-NEXT: .cfi_startproc ; ENABLE-V5T-NEXT: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: bx lr ; ; DISABLE-V4T-LABEL: loopInfoRestoreOutsideLoop: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r4, lr} ; DISABLE-V4T-NEXT: cmp r0, #0 ; DISABLE-V4T-NEXT: beq LBB5_4 ; DISABLE-V4T-NEXT: @ %bb.1: @ %if.then ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: mov r8, r8 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: movs r1, #10 ; DISABLE-V4T-NEXT: LBB5_2: @ %for.body ; DISABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: movs r2, #1 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: adds r0, r2, r0 ; DISABLE-V4T-NEXT: subs r1, r1, #1 ; DISABLE-V4T-NEXT: bne LBB5_2 ; DISABLE-V4T-NEXT: @ %bb.3: @ %for.end ; DISABLE-V4T-NEXT: lsls r0, r0, #3 ; DISABLE-V4T-NEXT: b LBB5_5 ; DISABLE-V4T-NEXT: LBB5_4: @ %if.else ; DISABLE-V4T-NEXT: lsls r0, r1, #1 ; DISABLE-V4T-NEXT: LBB5_5: @ %if.end ; DISABLE-V4T-NEXT: pop {r4} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; DISABLE-V4T-NEXT: @ -- End function ; DISABLE-V4T-NEXT: .globl _emptyFrame @ -- Begin function emptyFrame ; DISABLE-V4T-NEXT: .p2align 1 ; DISABLE-V4T-NEXT: .code 16 @ @emptyFrame ; DISABLE-V4T-NEXT: .thumb_func _emptyFrame ; DISABLE-V4T-NEXT: _emptyFrame: ; DISABLE-V4T-NEXT: .cfi_startproc ; DISABLE-V4T-NEXT: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: bx lr ; ; DISABLE-V5T-LABEL: loopInfoRestoreOutsideLoop: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r4, lr} ; DISABLE-V5T-NEXT: cmp r0, #0 ; DISABLE-V5T-NEXT: beq LBB5_4 ; DISABLE-V5T-NEXT: @ %bb.1: @ %if.then ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: mov r8, r8 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: movs r1, #10 ; DISABLE-V5T-NEXT: LBB5_2: @ %for.body ; DISABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: movs r2, #1 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: adds r0, r2, r0 ; DISABLE-V5T-NEXT: subs r1, r1, #1 ; DISABLE-V5T-NEXT: bne LBB5_2 ; DISABLE-V5T-NEXT: @ %bb.3: @ %for.end ; DISABLE-V5T-NEXT: lsls r0, r0, #3 ; DISABLE-V5T-NEXT: pop {r4, pc} ; DISABLE-V5T-NEXT: LBB5_4: @ %if.else ; DISABLE-V5T-NEXT: lsls r0, r1, #1 ; DISABLE-V5T-NEXT: pop {r4, pc} ; DISABLE-V5T-NEXT: @ -- End function ; DISABLE-V5T-NEXT: .globl _emptyFrame @ -- Begin function emptyFrame ; DISABLE-V5T-NEXT: .p2align 1 ; DISABLE-V5T-NEXT: .code 16 @ @emptyFrame ; DISABLE-V5T-NEXT: .thumb_func _emptyFrame ; DISABLE-V5T-NEXT: _emptyFrame: ; DISABLE-V5T-NEXT: .cfi_startproc ; DISABLE-V5T-NEXT: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: bx lr entry: %tobool = icmp eq i32 %cond, 0 br i1 %tobool, label %if.else, label %if.then if.then: ; preds = %entry tail call void asm "nop", "~{r4}"() 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 asm sideeffect "movs $0, #1", "=r,~{r4}"() %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() { entry: ret i32 0 } ; Check that we handle inline asm correctly. define i32 @inlineAsm(i32 %cond, i32 %N) { ; ENABLE-V4T-LABEL: inlineAsm: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: cmp r0, #0 ; ENABLE-V4T-NEXT: beq LBB7_4 ; ENABLE-V4T-NEXT: @ %bb.1: @ %for.preheader ; ENABLE-V4T-NEXT: push {r4, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r4, -8 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: mov r8, r8 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: movs r0, #10 ; ENABLE-V4T-NEXT: LBB7_2: @ %for.body ; ENABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: movs r4, #1 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: subs r0, r0, #1 ; ENABLE-V4T-NEXT: bne LBB7_2 ; ENABLE-V4T-NEXT: @ %bb.3: @ %for.exit ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: mov r8, r8 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: pop {r4} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: bx r1 ; ENABLE-V4T-NEXT: LBB7_4: @ %if.else ; ENABLE-V4T-NEXT: lsls r0, r1, #1 ; ENABLE-V4T-NEXT: bx lr ; ; ENABLE-V5T-LABEL: inlineAsm: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: cmp r0, #0 ; ENABLE-V5T-NEXT: beq LBB7_4 ; ENABLE-V5T-NEXT: @ %bb.1: @ %for.preheader ; ENABLE-V5T-NEXT: push {r4, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r4, -8 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: mov r8, r8 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: movs r0, #10 ; ENABLE-V5T-NEXT: LBB7_2: @ %for.body ; ENABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: movs r4, #1 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: subs r0, r0, #1 ; ENABLE-V5T-NEXT: bne LBB7_2 ; ENABLE-V5T-NEXT: @ %bb.3: @ %for.exit ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: mov r8, r8 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: pop {r4, pc} ; ENABLE-V5T-NEXT: LBB7_4: @ %if.else ; ENABLE-V5T-NEXT: lsls r0, r1, #1 ; ENABLE-V5T-NEXT: LBB7_5: @ %if.end ; ENABLE-V5T-NEXT: bx lr ; ; DISABLE-V4T-LABEL: inlineAsm: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r4, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r4, -8 ; DISABLE-V4T-NEXT: cmp r0, #0 ; DISABLE-V4T-NEXT: beq LBB7_4 ; DISABLE-V4T-NEXT: @ %bb.1: @ %for.preheader ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: mov r8, r8 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: movs r0, #10 ; DISABLE-V4T-NEXT: LBB7_2: @ %for.body ; DISABLE-V4T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: movs r4, #1 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: subs r0, r0, #1 ; DISABLE-V4T-NEXT: bne LBB7_2 ; DISABLE-V4T-NEXT: @ %bb.3: @ %for.exit ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: mov r8, r8 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: b LBB7_5 ; DISABLE-V4T-NEXT: LBB7_4: @ %if.else ; DISABLE-V4T-NEXT: lsls r0, r1, #1 ; DISABLE-V4T-NEXT: LBB7_5: @ %if.end ; DISABLE-V4T-NEXT: pop {r4} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; ; DISABLE-V5T-LABEL: inlineAsm: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r4, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r4, -8 ; DISABLE-V5T-NEXT: cmp r0, #0 ; DISABLE-V5T-NEXT: beq LBB7_4 ; DISABLE-V5T-NEXT: @ %bb.1: @ %for.preheader ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: mov r8, r8 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: movs r0, #10 ; DISABLE-V5T-NEXT: LBB7_2: @ %for.body ; DISABLE-V5T-NEXT: @ =>This Inner Loop Header: Depth=1 ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: movs r4, #1 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: subs r0, r0, #1 ; DISABLE-V5T-NEXT: bne LBB7_2 ; DISABLE-V5T-NEXT: @ %bb.3: @ %for.exit ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: mov r8, r8 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: pop {r4, pc} ; DISABLE-V5T-NEXT: LBB7_4: @ %if.else ; DISABLE-V5T-NEXT: lsls r0, r1, #1 ; DISABLE-V5T-NEXT: pop {r4, pc} entry: %tobool = icmp eq i32 %cond, 0 br i1 %tobool, label %if.else, label %for.preheader for.preheader: tail call void asm "nop", ""() br label %for.body for.body: ; preds = %entry, %for.body %i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] tail call void asm sideeffect "movs r4, #1", "~{r4}"() %inc = add nuw nsw i32 %i.03, 1 %exitcond = icmp eq i32 %inc, 10 br i1 %exitcond, label %for.exit, label %for.body for.exit: tail call void asm "nop", ""() br label %if.end 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.exit ] ret i32 %sum.0 } ; Check that we handle calls to variadic functions correctly. define i32 @callVariadicFunc(i32 %cond, i32 %N) { ; ENABLE-V4T-LABEL: callVariadicFunc: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: cmp r0, #0 ; ENABLE-V4T-NEXT: beq LBB8_2 ; ENABLE-V4T-NEXT: @ %bb.1: @ %if.then ; ENABLE-V4T-NEXT: push {r4, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r4, -8 ; ENABLE-V4T-NEXT: sub sp, #16 ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 24 ; ENABLE-V4T-NEXT: str r1, [sp] ; ENABLE-V4T-NEXT: str r1, [sp, #4] ; ENABLE-V4T-NEXT: str r1, [sp, #8] ; ENABLE-V4T-NEXT: ldr r0, LCPI8_0 ; ENABLE-V4T-NEXT: LPC8_0: ; ENABLE-V4T-NEXT: add r0, pc ; ENABLE-V4T-NEXT: ldr r4, [r0] ; ENABLE-V4T-NEXT: movs r0, r1 ; ENABLE-V4T-NEXT: movs r2, r1 ; ENABLE-V4T-NEXT: movs r3, r1 ; ENABLE-V4T-NEXT: bl Ltmp2 ; ENABLE-V4T-NEXT: lsls r0, r0, #3 ; ENABLE-V4T-NEXT: add sp, #16 ; ENABLE-V4T-NEXT: pop {r4} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: bx r1 ; ENABLE-V4T-NEXT: LBB8_2: @ %if.else ; ENABLE-V4T-NEXT: lsls r0, r1, #1 ; ENABLE-V4T-NEXT: bx lr ; ENABLE-V4T-NEXT: .p2align 2 ; ENABLE-V4T-NEXT: @ %bb.3: ; ENABLE-V4T-NEXT: .data_region ; ENABLE-V4T-NEXT: LCPI8_0: ; ENABLE-V4T-NEXT: .long L_someVariadicFunc$non_lazy_ptr-(LPC8_0+4) ; ENABLE-V4T-NEXT: .end_data_region ; ; ENABLE-V5T-LABEL: callVariadicFunc: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: cmp r0, #0 ; ENABLE-V5T-NEXT: beq LBB8_2 ; ENABLE-V5T-NEXT: @ %bb.1: @ %if.then ; ENABLE-V5T-NEXT: push {r7, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r7, -8 ; ENABLE-V5T-NEXT: sub sp, #16 ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 24 ; ENABLE-V5T-NEXT: str r1, [sp] ; ENABLE-V5T-NEXT: str r1, [sp, #4] ; ENABLE-V5T-NEXT: str r1, [sp, #8] ; ENABLE-V5T-NEXT: movs r0, r1 ; ENABLE-V5T-NEXT: movs r2, r1 ; ENABLE-V5T-NEXT: movs r3, r1 ; ENABLE-V5T-NEXT: bl _someVariadicFunc ; ENABLE-V5T-NEXT: lsls r0, r0, #3 ; ENABLE-V5T-NEXT: add sp, #16 ; ENABLE-V5T-NEXT: pop {r7, pc} ; ENABLE-V5T-NEXT: LBB8_2: @ %if.else ; ENABLE-V5T-NEXT: lsls r0, r1, #1 ; ENABLE-V5T-NEXT: LBB8_3: @ %if.end ; ENABLE-V5T-NEXT: bx lr ; ; DISABLE-V4T-LABEL: callVariadicFunc: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r4, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r4, -8 ; DISABLE-V4T-NEXT: sub sp, #16 ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 24 ; DISABLE-V4T-NEXT: cmp r0, #0 ; DISABLE-V4T-NEXT: beq LBB8_2 ; DISABLE-V4T-NEXT: @ %bb.1: @ %if.then ; DISABLE-V4T-NEXT: str r1, [sp] ; DISABLE-V4T-NEXT: str r1, [sp, #4] ; DISABLE-V4T-NEXT: str r1, [sp, #8] ; DISABLE-V4T-NEXT: ldr r0, LCPI8_0 ; DISABLE-V4T-NEXT: LPC8_0: ; DISABLE-V4T-NEXT: add r0, pc ; DISABLE-V4T-NEXT: ldr r4, [r0] ; DISABLE-V4T-NEXT: movs r0, r1 ; DISABLE-V4T-NEXT: movs r2, r1 ; DISABLE-V4T-NEXT: movs r3, r1 ; DISABLE-V4T-NEXT: bl Ltmp2 ; DISABLE-V4T-NEXT: lsls r0, r0, #3 ; DISABLE-V4T-NEXT: b LBB8_3 ; DISABLE-V4T-NEXT: LBB8_2: @ %if.else ; DISABLE-V4T-NEXT: lsls r0, r1, #1 ; DISABLE-V4T-NEXT: LBB8_3: @ %if.end ; DISABLE-V4T-NEXT: add sp, #16 ; DISABLE-V4T-NEXT: pop {r4} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; DISABLE-V4T-NEXT: .p2align 2 ; DISABLE-V4T-NEXT: @ %bb.4: ; DISABLE-V4T-NEXT: .data_region ; DISABLE-V4T-NEXT: LCPI8_0: ; DISABLE-V4T-NEXT: .long L_someVariadicFunc$non_lazy_ptr-(LPC8_0+4) ; DISABLE-V4T-NEXT: .end_data_region ; ; DISABLE-V5T-LABEL: callVariadicFunc: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r7, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r7, -8 ; DISABLE-V5T-NEXT: sub sp, #16 ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 24 ; DISABLE-V5T-NEXT: cmp r0, #0 ; DISABLE-V5T-NEXT: beq LBB8_2 ; DISABLE-V5T-NEXT: @ %bb.1: @ %if.then ; DISABLE-V5T-NEXT: str r1, [sp] ; DISABLE-V5T-NEXT: str r1, [sp, #4] ; DISABLE-V5T-NEXT: str r1, [sp, #8] ; DISABLE-V5T-NEXT: movs r0, r1 ; DISABLE-V5T-NEXT: movs r2, r1 ; DISABLE-V5T-NEXT: movs r3, r1 ; DISABLE-V5T-NEXT: bl _someVariadicFunc ; DISABLE-V5T-NEXT: lsls r0, r0, #3 ; DISABLE-V5T-NEXT: add sp, #16 ; DISABLE-V5T-NEXT: pop {r7, pc} ; DISABLE-V5T-NEXT: LBB8_2: @ %if.else ; DISABLE-V5T-NEXT: lsls r0, r1, #1 ; DISABLE-V5T-NEXT: add sp, #16 ; DISABLE-V5T-NEXT: pop {r7, pc} 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-V4T-LABEL: noreturn: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: cmp r0, #0 ; ENABLE-V4T-NEXT: bne LBB9_2 ; ENABLE-V4T-NEXT: @ %bb.1: @ %if.end ; ENABLE-V4T-NEXT: movs r0, #42 ; ENABLE-V4T-NEXT: bx lr ; ENABLE-V4T-NEXT: LBB9_2: @ %if.abort ; ENABLE-V4T-NEXT: push {r4, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r4, -8 ; ENABLE-V4T-NEXT: ldr r0, LCPI9_0 ; ENABLE-V4T-NEXT: LPC9_0: ; ENABLE-V4T-NEXT: add r0, pc ; ENABLE-V4T-NEXT: ldr r0, [r0] ; ENABLE-V4T-NEXT: @ InlineAsm Start ; ENABLE-V4T-NEXT: movs r1, #1 ; ENABLE-V4T-NEXT: @ InlineAsm End ; ENABLE-V4T-NEXT: bl Ltmp3 ; ENABLE-V4T-NEXT: .p2align 2 ; ENABLE-V4T-NEXT: @ %bb.3: ; ENABLE-V4T-NEXT: .data_region ; ENABLE-V4T-NEXT: LCPI9_0: ; ENABLE-V4T-NEXT: .long L_abort$non_lazy_ptr-(LPC9_0+4) ; ENABLE-V4T-NEXT: .end_data_region ; ; ENABLE-V5T-LABEL: noreturn: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: cmp r0, #0 ; ENABLE-V5T-NEXT: bne LBB9_2 ; ENABLE-V5T-NEXT: @ %bb.1: @ %if.end ; ENABLE-V5T-NEXT: movs r0, #42 ; ENABLE-V5T-NEXT: bx lr ; ENABLE-V5T-NEXT: LBB9_2: @ %if.abort ; ENABLE-V5T-NEXT: push {r4, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r4, -8 ; ENABLE-V5T-NEXT: @ InlineAsm Start ; ENABLE-V5T-NEXT: movs r0, #1 ; ENABLE-V5T-NEXT: @ InlineAsm End ; ENABLE-V5T-NEXT: bl _abort ; ; DISABLE-V4T-LABEL: noreturn: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r4, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r4, -8 ; DISABLE-V4T-NEXT: cmp r0, #0 ; DISABLE-V4T-NEXT: bne LBB9_2 ; DISABLE-V4T-NEXT: @ %bb.1: @ %if.end ; DISABLE-V4T-NEXT: movs r0, #42 ; DISABLE-V4T-NEXT: pop {r4} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; DISABLE-V4T-NEXT: LBB9_2: @ %if.abort ; DISABLE-V4T-NEXT: ldr r0, LCPI9_0 ; DISABLE-V4T-NEXT: LPC9_0: ; DISABLE-V4T-NEXT: add r0, pc ; DISABLE-V4T-NEXT: ldr r0, [r0] ; DISABLE-V4T-NEXT: @ InlineAsm Start ; DISABLE-V4T-NEXT: movs r1, #1 ; DISABLE-V4T-NEXT: @ InlineAsm End ; DISABLE-V4T-NEXT: bl Ltmp3 ; DISABLE-V4T-NEXT: .p2align 2 ; DISABLE-V4T-NEXT: @ %bb.3: ; DISABLE-V4T-NEXT: .data_region ; DISABLE-V4T-NEXT: LCPI9_0: ; DISABLE-V4T-NEXT: .long L_abort$non_lazy_ptr-(LPC9_0+4) ; DISABLE-V4T-NEXT: .end_data_region ; ; DISABLE-V5T-LABEL: noreturn: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r4, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r4, -8 ; DISABLE-V5T-NEXT: cmp r0, #0 ; DISABLE-V5T-NEXT: bne LBB9_2 ; DISABLE-V5T-NEXT: @ %bb.1: @ %if.end ; DISABLE-V5T-NEXT: movs r0, #42 ; DISABLE-V5T-NEXT: pop {r4, pc} ; DISABLE-V5T-NEXT: LBB9_2: @ %if.abort ; DISABLE-V5T-NEXT: @ InlineAsm Start ; DISABLE-V5T-NEXT: movs r0, #1 ; DISABLE-V5T-NEXT: @ InlineAsm End ; DISABLE-V5T-NEXT: bl _abort entry: %tobool = icmp eq i8 %bad_thing, 0 br i1 %tobool, label %if.end, label %if.abort if.abort: %call = tail call i32 asm sideeffect "movs $0, #1", "=r,~{r4}"() tail call void @abort() #0 unreachable if.end: ret i32 42 } declare void @abort() #0 define i32 @b_to_bx(i32 %value) { ; ENABLE-V4T-LABEL: b_to_bx: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: movs r1, r0 ; ENABLE-V4T-NEXT: cmp r0, #49 ; ENABLE-V4T-NEXT: bgt LBB10_2 ; ENABLE-V4T-NEXT: @ %bb.1: @ %if.then ; ENABLE-V4T-NEXT: push {r7, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r7, -8 ; ENABLE-V4T-NEXT: ldr r0, LCPI10_0 ; ENABLE-V4T-NEXT: ldr r2, LCPI10_1 ; ENABLE-V4T-NEXT: LPC10_0: ; ENABLE-V4T-NEXT: add r2, pc ; ENABLE-V4T-NEXT: bl Ltmp4 ; ENABLE-V4T-NEXT: pop {r7} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: bx r1 ; ENABLE-V4T-NEXT: LBB10_2: @ %if.else ; ENABLE-V4T-NEXT: lsls r0, r1, #1 ; ENABLE-V4T-NEXT: bx lr ; ENABLE-V4T-NEXT: .p2align 2 ; ENABLE-V4T-NEXT: @ %bb.3: ; ENABLE-V4T-NEXT: .data_region ; ENABLE-V4T-NEXT: LCPI10_0: ; ENABLE-V4T-NEXT: .long 5000 @ 0x1388 ; ENABLE-V4T-NEXT: LCPI10_1: ; ENABLE-V4T-NEXT: .long ___divsi3-(LPC10_0+4) ; ENABLE-V4T-NEXT: .end_data_region ; ; ENABLE-V5T-LABEL: b_to_bx: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: movs r1, r0 ; ENABLE-V5T-NEXT: cmp r0, #49 ; ENABLE-V5T-NEXT: bgt LBB10_2 ; ENABLE-V5T-NEXT: @ %bb.1: @ %if.then ; ENABLE-V5T-NEXT: push {r7, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r7, -8 ; ENABLE-V5T-NEXT: ldr r0, LCPI10_0 ; ENABLE-V5T-NEXT: bl ___divsi3 ; ENABLE-V5T-NEXT: pop {r7, pc} ; ENABLE-V5T-NEXT: LBB10_2: @ %if.else ; ENABLE-V5T-NEXT: lsls r0, r1, #1 ; ENABLE-V5T-NEXT: LBB10_3: @ %if.end ; ENABLE-V5T-NEXT: bx lr ; ENABLE-V5T-NEXT: .p2align 2 ; ENABLE-V5T-NEXT: @ %bb.4: ; ENABLE-V5T-NEXT: .data_region ; ENABLE-V5T-NEXT: LCPI10_0: ; ENABLE-V5T-NEXT: .long 5000 @ 0x1388 ; ENABLE-V5T-NEXT: .end_data_region ; ; DISABLE-V4T-LABEL: b_to_bx: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r7, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r7, -8 ; DISABLE-V4T-NEXT: movs r1, r0 ; DISABLE-V4T-NEXT: cmp r0, #49 ; DISABLE-V4T-NEXT: bgt LBB10_2 ; DISABLE-V4T-NEXT: @ %bb.1: @ %if.then ; DISABLE-V4T-NEXT: ldr r0, LCPI10_0 ; DISABLE-V4T-NEXT: ldr r2, LCPI10_1 ; DISABLE-V4T-NEXT: LPC10_0: ; DISABLE-V4T-NEXT: add r2, pc ; DISABLE-V4T-NEXT: bl Ltmp4 ; DISABLE-V4T-NEXT: b LBB10_3 ; DISABLE-V4T-NEXT: LBB10_2: @ %if.else ; DISABLE-V4T-NEXT: lsls r0, r1, #1 ; DISABLE-V4T-NEXT: LBB10_3: @ %if.end ; DISABLE-V4T-NEXT: pop {r7} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; DISABLE-V4T-NEXT: .p2align 2 ; DISABLE-V4T-NEXT: @ %bb.4: ; DISABLE-V4T-NEXT: .data_region ; DISABLE-V4T-NEXT: LCPI10_0: ; DISABLE-V4T-NEXT: .long 5000 @ 0x1388 ; DISABLE-V4T-NEXT: LCPI10_1: ; DISABLE-V4T-NEXT: .long ___divsi3-(LPC10_0+4) ; DISABLE-V4T-NEXT: .end_data_region ; ; DISABLE-V5T-LABEL: b_to_bx: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r7, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r7, -8 ; DISABLE-V5T-NEXT: movs r1, r0 ; DISABLE-V5T-NEXT: cmp r0, #49 ; DISABLE-V5T-NEXT: bgt LBB10_2 ; DISABLE-V5T-NEXT: @ %bb.1: @ %if.then ; DISABLE-V5T-NEXT: ldr r0, LCPI10_0 ; DISABLE-V5T-NEXT: bl ___divsi3 ; DISABLE-V5T-NEXT: pop {r7, pc} ; DISABLE-V5T-NEXT: LBB10_2: @ %if.else ; DISABLE-V5T-NEXT: lsls r0, r1, #1 ; DISABLE-V5T-NEXT: pop {r7, pc} ; DISABLE-V5T-NEXT: .p2align 2 ; DISABLE-V5T-NEXT: @ %bb.3: ; DISABLE-V5T-NEXT: .data_region ; DISABLE-V5T-NEXT: LCPI10_0: ; DISABLE-V5T-NEXT: .long 5000 @ 0x1388 ; DISABLE-V5T-NEXT: .end_data_region entry: %cmp = icmp slt i32 %value, 50 br i1 %cmp, label %if.then, label %if.else if.then: %div = sdiv i32 5000, %value br label %if.end if.else: %mul = shl nsw i32 %value, 1 br label %if.end if.end: %value.addr.0 = phi i32 [ %div, %if.then ], [ %mul, %if.else ] ret i32 %value.addr.0 } define i1 @beq_to_bx(i32* %y, i32 %head) { ; ENABLE-V4T-LABEL: beq_to_bx: ; ENABLE-V4T: @ %bb.0: @ %entry ; ENABLE-V4T-NEXT: push {r4, lr} ; ENABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V4T-NEXT: .cfi_offset lr, -4 ; ENABLE-V4T-NEXT: .cfi_offset r4, -8 ; ENABLE-V4T-NEXT: movs r2, r0 ; ENABLE-V4T-NEXT: movs r0, #1 ; ENABLE-V4T-NEXT: cmp r2, #0 ; ENABLE-V4T-NEXT: beq LBB11_3 ; ENABLE-V4T-NEXT: @ %bb.1: @ %if.end ; ENABLE-V4T-NEXT: ldr r3, [r2] ; ENABLE-V4T-NEXT: lsls r4, r3, #30 ; ENABLE-V4T-NEXT: bpl LBB11_3 ; ENABLE-V4T-NEXT: @ %bb.2: @ %if.end4 ; ENABLE-V4T-NEXT: str r1, [r2] ; ENABLE-V4T-NEXT: str r3, [r2] ; ENABLE-V4T-NEXT: movs r0, #0 ; ENABLE-V4T-NEXT: LBB11_3: @ %cleanup ; ENABLE-V4T-NEXT: pop {r4} ; ENABLE-V4T-NEXT: pop {r1} ; ENABLE-V4T-NEXT: bx r1 ; ; ENABLE-V5T-LABEL: beq_to_bx: ; ENABLE-V5T: @ %bb.0: @ %entry ; ENABLE-V5T-NEXT: push {r4, lr} ; ENABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; ENABLE-V5T-NEXT: .cfi_offset lr, -4 ; ENABLE-V5T-NEXT: .cfi_offset r4, -8 ; ENABLE-V5T-NEXT: movs r2, r0 ; ENABLE-V5T-NEXT: movs r0, #1 ; ENABLE-V5T-NEXT: cmp r2, #0 ; ENABLE-V5T-NEXT: beq LBB11_3 ; ENABLE-V5T-NEXT: @ %bb.1: @ %if.end ; ENABLE-V5T-NEXT: ldr r3, [r2] ; ENABLE-V5T-NEXT: lsls r4, r3, #30 ; ENABLE-V5T-NEXT: bpl LBB11_3 ; ENABLE-V5T-NEXT: @ %bb.2: @ %if.end4 ; ENABLE-V5T-NEXT: str r1, [r2] ; ENABLE-V5T-NEXT: str r3, [r2] ; ENABLE-V5T-NEXT: movs r0, #0 ; ENABLE-V5T-NEXT: LBB11_3: @ %cleanup ; ENABLE-V5T-NEXT: pop {r4, pc} ; ; DISABLE-V4T-LABEL: beq_to_bx: ; DISABLE-V4T: @ %bb.0: @ %entry ; DISABLE-V4T-NEXT: push {r4, lr} ; DISABLE-V4T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V4T-NEXT: .cfi_offset lr, -4 ; DISABLE-V4T-NEXT: .cfi_offset r4, -8 ; DISABLE-V4T-NEXT: movs r2, r0 ; DISABLE-V4T-NEXT: movs r0, #1 ; DISABLE-V4T-NEXT: cmp r2, #0 ; DISABLE-V4T-NEXT: beq LBB11_3 ; DISABLE-V4T-NEXT: @ %bb.1: @ %if.end ; DISABLE-V4T-NEXT: ldr r3, [r2] ; DISABLE-V4T-NEXT: lsls r4, r3, #30 ; DISABLE-V4T-NEXT: bpl LBB11_3 ; DISABLE-V4T-NEXT: @ %bb.2: @ %if.end4 ; DISABLE-V4T-NEXT: str r1, [r2] ; DISABLE-V4T-NEXT: str r3, [r2] ; DISABLE-V4T-NEXT: movs r0, #0 ; DISABLE-V4T-NEXT: LBB11_3: @ %cleanup ; DISABLE-V4T-NEXT: pop {r4} ; DISABLE-V4T-NEXT: pop {r1} ; DISABLE-V4T-NEXT: bx r1 ; ; DISABLE-V5T-LABEL: beq_to_bx: ; DISABLE-V5T: @ %bb.0: @ %entry ; DISABLE-V5T-NEXT: push {r4, lr} ; DISABLE-V5T-NEXT: .cfi_def_cfa_offset 8 ; DISABLE-V5T-NEXT: .cfi_offset lr, -4 ; DISABLE-V5T-NEXT: .cfi_offset r4, -8 ; DISABLE-V5T-NEXT: movs r2, r0 ; DISABLE-V5T-NEXT: movs r0, #1 ; DISABLE-V5T-NEXT: cmp r2, #0 ; DISABLE-V5T-NEXT: beq LBB11_3 ; DISABLE-V5T-NEXT: @ %bb.1: @ %if.end ; DISABLE-V5T-NEXT: ldr r3, [r2] ; DISABLE-V5T-NEXT: lsls r4, r3, #30 ; DISABLE-V5T-NEXT: bpl LBB11_3 ; DISABLE-V5T-NEXT: @ %bb.2: @ %if.end4 ; DISABLE-V5T-NEXT: str r1, [r2] ; DISABLE-V5T-NEXT: str r3, [r2] ; DISABLE-V5T-NEXT: movs r0, #0 ; DISABLE-V5T-NEXT: LBB11_3: @ %cleanup ; DISABLE-V5T-NEXT: pop {r4, pc} entry: %cmp = icmp eq i32* %y, null br i1 %cmp, label %cleanup, label %if.end if.end: %z = load i32, i32* %y, align 4 %and = and i32 %z, 2 %cmp2 = icmp eq i32 %and, 0 br i1 %cmp2, label %cleanup, label %if.end4 if.end4: store i32 %head, i32* %y, align 4 store volatile i32 %z, i32* %y, align 4 br label %cleanup cleanup: %retval.0 = phi i1 [ 0, %if.end4 ], [ 1, %entry ], [ 1, %if.end ] ret i1 %retval.0 } attributes #0 = { noreturn nounwind }