1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=thumbv8.1m.main %s -o - | FileCheck %s 3 4define void @cbz_exit(i32* %in, i32* %res) { 5; CHECK-LABEL: cbz_exit: 6; CHECK: @ %bb.0: @ %entry 7; CHECK-NEXT: subs r2, r0, #4 8; CHECK-NEXT: mov.w r0, #-1 9; CHECK-NEXT: .LBB0_1: @ %loop 10; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 11; CHECK-NEXT: ldr r3, [r2, #4]! 12; CHECK-NEXT: adds r0, #1 13; CHECK-NEXT: cbz r3, .LBB0_2 14; CHECK-NEXT: le .LBB0_1 15; CHECK-NEXT: .LBB0_2: @ %exit 16; CHECK-NEXT: str r0, [r1] 17; CHECK-NEXT: bx lr 18entry: 19 br label %loop 20 21loop: 22 %offset = phi i32 [ 0, %entry ], [ %next, %loop ] 23 %ptr = getelementptr i32, i32* %in, i32 %offset 24 %val = load i32, i32* %ptr 25 %next = add i32 %offset, 1 26 %cmp = icmp eq i32 %val, 0 27 br i1 %cmp, label %exit, label %loop 28 29exit: 30 store i32 %offset, i32* %res 31 ret void 32} 33 34define void @cbnz_exit(i32* %in, i32* %res) { 35; CHECK-LABEL: cbnz_exit: 36; CHECK: @ %bb.0: @ %entry 37; CHECK-NEXT: subs r2, r0, #4 38; CHECK-NEXT: mov.w r0, #-1 39; CHECK-NEXT: .LBB1_1: @ %loop 40; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 41; CHECK-NEXT: ldr r3, [r2, #4]! 42; CHECK-NEXT: adds r0, #1 43; CHECK-NEXT: cbnz r3, .LBB1_2 44; CHECK-NEXT: le .LBB1_1 45; CHECK-NEXT: .LBB1_2: @ %exit 46; CHECK-NEXT: str r0, [r1] 47; CHECK-NEXT: bx lr 48entry: 49 br label %loop 50 51loop: 52 %offset = phi i32 [ 0, %entry ], [ %next, %loop ] 53 %ptr = getelementptr i32, i32* %in, i32 %offset 54 %val = load i32, i32* %ptr 55 %next = add i32 %offset, 1 56 %cmp = icmp ne i32 %val, 0 57 br i1 %cmp, label %exit, label %loop 58 59exit: 60 store i32 %offset, i32* %res 61 ret void 62} 63 64define void @cbnz_exit_too_large(i32* %in, i32* %res) { 65; CHECK-LABEL: cbnz_exit_too_large: 66; CHECK: @ %bb.0: @ %entry 67; CHECK-NEXT: subs r2, r0, #4 68; CHECK-NEXT: mov.w r0, #-1 69; CHECK-NEXT: .LBB2_1: @ %loop 70; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 71; CHECK-NEXT: ldr r12, [r2, #4]! 72; CHECK-NEXT: .zero 4090 73; CHECK-NEXT: adds r0, #1 74; CHECK-NEXT: cmp.w r12, #0 75; CHECK-NEXT: beq.w .LBB2_1 76; CHECK-NEXT: @ %bb.2: @ %exit 77; CHECK-NEXT: str r0, [r1] 78; CHECK-NEXT: bx lr 79entry: 80 br label %loop 81 82loop: 83 %offset = phi i32 [ 0, %entry ], [ %next, %loop ] 84 %ptr = getelementptr i32, i32* %in, i32 %offset 85 %val = load i32, i32* %ptr 86 %next = add i32 %offset, 1 87 %cmp = icmp ne i32 %val, 0 88 %size = call i32 @llvm.arm.space(i32 4090, i32 undef) 89 br i1 %cmp, label %exit, label %loop 90 91exit: 92 store i32 %offset, i32* %res 93 ret void 94} 95 96define void @cbz_exit_minsize(i32* %in, i32* %res) #0 { 97; CHECK-LABEL: cbz_exit_minsize: 98; CHECK: @ %bb.0: @ %entry 99; CHECK-NEXT: movs r2, #0 100; CHECK-NEXT: .LBB3_1: @ %loop 101; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 102; CHECK-NEXT: ldr.w r3, [r0, r2, lsl #2] 103; CHECK-NEXT: adds r2, #1 104; CHECK-NEXT: cmp r3, #0 105; CHECK-NEXT: bne .LBB3_1 106; CHECK-NEXT: @ %bb.2: @ %exit 107; CHECK-NEXT: subs r0, r2, #1 108; CHECK-NEXT: str r0, [r1] 109; CHECK-NEXT: bx lr 110entry: 111 br label %loop 112 113loop: 114 %offset = phi i32 [ 0, %entry ], [ %next, %loop ] 115 %ptr = getelementptr i32, i32* %in, i32 %offset 116 %val = load i32, i32* %ptr 117 %next = add i32 %offset, 1 118 %cmp = icmp eq i32 %val, 0 119 br i1 %cmp, label %exit, label %loop 120 121exit: 122 store i32 %offset, i32* %res 123 ret void 124} 125 126define void @cbnz_exit_minsize(i32* %in, i32* %res) #0 { 127; CHECK-LABEL: cbnz_exit_minsize: 128; CHECK: @ %bb.0: @ %entry 129; CHECK-NEXT: movs r2, #0 130; CHECK-NEXT: .LBB4_1: @ %loop 131; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 132; CHECK-NEXT: ldr.w r3, [r0, r2, lsl #2] 133; CHECK-NEXT: adds r2, #1 134; CHECK-NEXT: cmp r3, #0 135; CHECK-NEXT: beq .LBB4_1 136; CHECK-NEXT: @ %bb.2: @ %exit 137; CHECK-NEXT: subs r0, r2, #1 138; CHECK-NEXT: str r0, [r1] 139; CHECK-NEXT: bx lr 140entry: 141 br label %loop 142 143loop: 144 %offset = phi i32 [ 0, %entry ], [ %next, %loop ] 145 %ptr = getelementptr i32, i32* %in, i32 %offset 146 %val = load i32, i32* %ptr 147 %next = add i32 %offset, 1 148 %cmp = icmp ne i32 %val, 0 149 br i1 %cmp, label %exit, label %loop 150 151exit: 152 store i32 %offset, i32* %res 153 ret void 154} 155 156attributes #0 = { minsize optsize } 157 158declare i32 @llvm.arm.space(i32 immarg, i32); 159