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