1; RUN: opt -mtriple=thumbv8.1m.main-none-none-eabi -passes=hardware-loops %s -S -o - | FileCheck %s 2; RUN: opt -mtriple=thumbv8.1m.main-none-none-eabi -passes=hardware-loops -disable-arm-loloops=true %s -S -o - | FileCheck %s --check-prefix=DISABLED 3; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi %s -o - | FileCheck %s --check-prefix=CHECK-LLC 4 5; DISABLED-NOT: llvm.{{.*}}.loop.iterations 6; DISABLED-NOT: llvm.loop.decrement 7 8@g = common local_unnamed_addr global ptr null, align 4 9 10; CHECK-LABEL: do_copy 11; CHECK: [[START:%[^ ]+]] = call i32 @llvm.start.loop.iterations.i32(i32 %n) 12; CHECK: br label %while.body 13 14; CHECK: [[REM:%[^ ]+]] = phi i32 [ [[START]], %entry ], [ [[LOOP_DEC:%[^ ]+]], %while.body ] 15; CHECK: [[LOOP_DEC]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[REM]], i32 1) 16; CHECK: [[CMP:%[^ ]+]] = icmp ne i32 [[LOOP_DEC]], 0 17; CHECK: br i1 [[CMP]], label %while.body, label %while.end 18 19; CHECK-LLC-LABEL:do_copy: 20; CHECK-LLC-NOT: mov lr, r0 21; CHECK-LLC: dls lr, r0 22; CHECK-LLC-NOT: mov lr, r0 23; CHECK-LLC: [[LOOP_HEADER:\.LBB[0-9_]+]]: 24; CHECK-LLC: le lr, [[LOOP_HEADER]] 25; CHECK-LLC-NOT: b [[LOOP_EXIT:\.LBB[0-9._]+]] 26; CHECK-LLC: @ %while.end 27define i32 @do_copy(i32 %n, ptr nocapture %p, ptr nocapture readonly %q) { 28entry: 29 br label %while.body 30 31while.body: 32 %q.addr.05 = phi ptr [ %incdec.ptr, %while.body ], [ %q, %entry ] 33 %p.addr.04 = phi ptr [ %incdec.ptr1, %while.body ], [ %p, %entry ] 34 %x.addr.03 = phi i32 [ %dec, %while.body ], [ %n, %entry ] 35 %dec = add nsw i32 %x.addr.03, -1 36 %incdec.ptr = getelementptr inbounds i32, ptr %q.addr.05, i32 1 37 %0 = load i32, ptr %q.addr.05, align 4 38 %incdec.ptr1 = getelementptr inbounds i32, ptr %p.addr.04, i32 1 39 store i32 %0, ptr %p.addr.04, align 4 40 %tobool = icmp eq i32 %dec, 0 41 br i1 %tobool, label %while.end, label %while.body 42 43while.end: 44 ret i32 0 45} 46 47; CHECK-LABEL: do_inc1 48; CHECK: entry: 49; CHECK: [[TEST:%[^ ]+]] = call { i32, i1 } @llvm.test.start.loop.iterations.i32(i32 %n) 50; CHECK: [[TEST1:%[^ ]+]] = extractvalue { i32, i1 } [[TEST]], 1 51; CHECK: [[TEST0:%[^ ]+]] = extractvalue { i32, i1 } [[TEST]], 0 52; CHECK: br i1 [[TEST1]], label %while.body.lr.ph, label %while.end 53 54; CHECK: while.body.lr.ph: 55; CHECK: br label %while.body 56 57; CHECK: [[REM:%[^ ]+]] = phi i32 [ [[TEST0]], %while.body.lr.ph ], [ [[LOOP_DEC:%[^ ]+]], %while.body ] 58; CHECK: [[LOOP_DEC]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[REM]], i32 1) 59; CHECK: [[CMP:%[^ ]+]] = icmp ne i32 [[LOOP_DEC]], 0 60; CHECK: br i1 [[CMP]], label %while.body, label %while.end.loopexit 61 62; CHECK-LLC-LABEL:do_inc1: 63; CHECK-LLC: wls lr, {{.*}}, [[LOOP_EXIT:.[LBB_0-3]+]] 64; CHECK-LLC-NOT: mov lr, 65; CHECK-LLC: [[LOOP_HEADER:\.LBB[0-9_]+]]: 66; CHECK-LLC: le lr, [[LOOP_HEADER]] 67; CHECK-LLC-NOT: b [[LOOP_EXIT:\.LBB[0-9_]+]] 68; CHECK-LLC: [[LOOP_EXIT]]: 69 70define i32 @do_inc1(i32 %n) { 71entry: 72 %cmp7 = icmp eq i32 %n, 0 73 br i1 %cmp7, label %while.end, label %while.body.lr.ph 74 75while.body.lr.ph: 76 %0 = load ptr, ptr @g, align 4 77 br label %while.body 78 79while.body: 80 %i.09 = phi i32 [ 0, %while.body.lr.ph ], [ %inc1, %while.body ] 81 %res.08 = phi i32 [ 0, %while.body.lr.ph ], [ %add, %while.body ] 82 %arrayidx = getelementptr inbounds i32, ptr %0, i32 %i.09 83 %1 = load i32, ptr %arrayidx, align 4 84 %add = add nsw i32 %1, %res.08 85 %inc1 = add nuw i32 %i.09, 1 86 %exitcond = icmp eq i32 %inc1, %n 87 br i1 %exitcond, label %while.end.loopexit, label %while.body 88 89while.end.loopexit: 90 br label %while.end 91 92while.end: 93 %res.0.lcssa = phi i32 [ 0, %entry ], [ %add, %while.end.loopexit ] 94 ret i32 %res.0.lcssa 95} 96 97; CHECK-LABEL: do_inc2 98; CHECK: entry: 99; CHECK: [[ROUND:%[^ ]+]] = add i32 %n, -1 100; CHECK: [[HALVE:%[^ ]+]] = lshr i32 [[ROUND]], 1 101; CHECK: [[COUNT:%[^ ]+]] = add nuw i32 [[HALVE]], 1 102 103; CHECK: while.body.lr.ph: 104; CHECK: [[START:%[^ ]+]] = call i32 @llvm.start.loop.iterations.i32(i32 [[COUNT]]) 105; CHECK: br label %while.body 106; CHECK: while.body: 107; CHECK: [[REM:%[^ ]+]] = phi i32 [ [[START]], %while.body.lr.ph ], [ [[LOOP_DEC:%[^ ]+]], %while.body ] 108; CHECK: [[LOOP_DEC]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[REM]], i32 1) 109; CHECK: [[CMP:%[^ ]+]] = icmp ne i32 [[LOOP_DEC]], 0 110; CHECK: br i1 [[CMP]], label %while.body, label %while.end.loopexit 111 112; CHECK-LLC: do_inc2: 113; CHECK-LLC-NOT: mov lr, 114; CHECK-LLC: add.w lr, 115; CHECK-LLC-NOT: dls lr, 116; CHECK-LLC-NOT: mov lr, 117; CHECK-LLC: [[LOOP_HEADER:\.LBB[0-9._]+]]: 118; CHECK-LLC: le lr, [[LOOP_HEADER]] 119 120define i32 @do_inc2(i32 %n) { 121entry: 122 %cmp7 = icmp sgt i32 %n, 0 123 br i1 %cmp7, label %while.body.lr.ph, label %while.end 124 125while.body.lr.ph: 126 %0 = load ptr, ptr @g, align 4 127 br label %while.body 128 129while.body: 130 %i.09 = phi i32 [ 0, %while.body.lr.ph ], [ %add1, %while.body ] 131 %res.08 = phi i32 [ 0, %while.body.lr.ph ], [ %add, %while.body ] 132 %arrayidx = getelementptr inbounds i32, ptr %0, i32 %i.09 133 %1 = load i32, ptr %arrayidx, align 4 134 %add = add nsw i32 %1, %res.08 135 %add1 = add nuw nsw i32 %i.09, 2 136 %cmp = icmp slt i32 %add1, %n 137 br i1 %cmp, label %while.body, label %while.end.loopexit 138 139while.end.loopexit: 140 br label %while.end 141 142while.end: 143 %res.0.lcssa = phi i32 [ 0, %entry ], [ %add, %while.end.loopexit ] 144 ret i32 %res.0.lcssa 145} 146 147; CHECK-LABEL: do_dec2 148 149; CHECK: entry: 150; CHECK: [[ROUND:%[^ ]+]] = add i32 %n, 1 151; CHECK: [[SMIN:%[^ ]+]] = call i32 @llvm.smin.i32(i32 %n, i32 2) 152; CHECK: [[SUB:%[^ ]+]] = sub i32 [[ROUND]], [[SMIN]] 153; CHECK: [[HALVE:%[^ ]+]] = lshr i32 [[SUB]], 1 154; CHECK: [[COUNT:%[^ ]+]] = add nuw i32 [[HALVE]], 1 155 156; CHECK: while.body.lr.ph: 157; CHECK: [[START:%[^ ]+]] = call i32 @llvm.start.loop.iterations.i32(i32 [[COUNT]]) 158; CHECK: br label %while.body 159 160; CHECK: [[REM:%[^ ]+]] = phi i32 [ [[START]], %while.body.lr.ph ], [ [[LOOP_DEC:%[^ ]+]], %while.body ] 161; CHECK: [[LOOP_DEC]] = call i32 @llvm.loop.decrement.reg.i32(i32 [[REM]], i32 1) 162; CHECK: [[CMP:%[^ ]+]] = icmp ne i32 [[LOOP_DEC]], 0 163; CHECK: br i1 [[CMP]], label %while.body, label %while.end.loopexit 164 165; CHECK-LLC: do_dec2 166; CHECK-LLC-NOT: mov lr, 167; CHECK-LLC: add.w lr, 168; CHECK-LLC-NOT: dls lr, 169; CHECK-LLC-NOT: mov lr, 170; CHECK-LLC: [[LOOP_HEADER:\.LBB[0-9_]+]]: 171; CHECK-LLC: le lr, [[LOOP_HEADER]] 172; CHECK-LLC-NOT: b . 173define i32 @do_dec2(i32 %n) { 174entry: 175 %cmp6 = icmp sgt i32 %n, 0 176 br i1 %cmp6, label %while.body.lr.ph, label %while.end 177 178while.body.lr.ph: 179 %0 = load ptr, ptr @g, align 4 180 br label %while.body 181 182while.body: 183 %i.08 = phi i32 [ %n, %while.body.lr.ph ], [ %sub, %while.body ] 184 %res.07 = phi i32 [ 0, %while.body.lr.ph ], [ %add, %while.body ] 185 %arrayidx = getelementptr inbounds i32, ptr %0, i32 %i.08 186 %1 = load i32, ptr %arrayidx, align 4 187 %add = add nsw i32 %1, %res.07 188 %sub = add nsw i32 %i.08, -2 189 %cmp = icmp sgt i32 %i.08, 2 190 br i1 %cmp, label %while.body, label %while.end.loopexit 191 192while.end.loopexit: 193 br label %while.end 194 195while.end: 196 %res.0.lcssa = phi i32 [ 0, %entry ], [ %add, %while.end.loopexit ] 197 ret i32 %res.0.lcssa 198} 199