1; RUN: opt -S -loop-unroll < %s | FileCheck %s 2; RUN: opt -S -passes='require<opt-remark-emit>,loop(loop-unroll-full)' < %s | FileCheck %s 3 4; Unroll twice, with first loop exit kept 5; CHECK-LABEL: @s32_max1 6; CHECK: do.body: 7; CHECK: store 8; CHECK: br i1 %cmp, label %do.body.1, label %do.end 9; CHECK: do.end: 10; CHECK: ret void 11; CHECK: do.body.1: 12; CHECK: store 13; CHECK: br label %do.end 14define void @s32_max1(i32 %n, i32* %p) { 15entry: 16 %add = add i32 %n, 1 17 br label %do.body 18 19do.body: 20 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ] 21 %arrayidx = getelementptr i32, i32* %p, i32 %i.0 22 store i32 %i.0, i32* %arrayidx, align 4 23 %inc = add i32 %i.0, 1 24 %cmp = icmp slt i32 %i.0, %add 25 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 1 times 26 27do.end: 28 ret void 29} 30 31; Unroll thrice, with first loop exit kept 32; CHECK-LABEL: @s32_max2 33; CHECK: do.body: 34; CHECK: store 35; CHECK: br i1 %cmp, label %do.body.1, label %do.end 36; CHECK: do.end: 37; CHECK: ret void 38; CHECK: do.body.1: 39; CHECK: store 40; CHECK: store 41; CHECK: br label %do.end 42define void @s32_max2(i32 %n, i32* %p) { 43entry: 44 %add = add i32 %n, 2 45 br label %do.body 46 47do.body: 48 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ] 49 %arrayidx = getelementptr i32, i32* %p, i32 %i.0 50 store i32 %i.0, i32* %arrayidx, align 4 51 %inc = add i32 %i.0, 1 52 %cmp = icmp slt i32 %i.0, %add 53 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 2 times 54 55do.end: 56 ret void 57} 58 59; Should not be unrolled 60; CHECK-LABEL: @s32_maxx 61; CHECK: do.body: 62; CHECK: do.end: 63; CHECK-NOT: do.body.1: 64define void @s32_maxx(i32 %n, i32 %x, i32* %p) { 65entry: 66 %add = add i32 %x, %n 67 br label %do.body 68 69do.body: 70 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ] 71 %arrayidx = getelementptr i32, i32* %p, i32 %i.0 72 store i32 %i.0, i32* %arrayidx, align 4 73 %inc = add i32 %i.0, 1 74 %cmp = icmp slt i32 %i.0, %add 75 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or x times 76 77do.end: 78 ret void 79} 80 81; Should not be unrolled 82; CHECK-LABEL: @s32_max2_unpredictable_exit 83; CHECK: do.body: 84; CHECK: do.end: 85; CHECK-NOT: do.body.1: 86define void @s32_max2_unpredictable_exit(i32 %n, i32 %x, i32* %p) { 87entry: 88 %add = add i32 %n, 2 89 br label %do.body 90 91do.body: 92 %i.0 = phi i32 [ %n, %entry ], [ %inc, %if.end ] 93 %cmp = icmp eq i32 %i.0, %x 94 br i1 %cmp, label %do.end, label %if.end ; unpredictable 95 96if.end: 97 %arrayidx = getelementptr i32, i32* %p, i32 %i.0 98 store i32 %i.0, i32* %arrayidx, align 4 99 %inc = add i32 %i.0, 1 100 %cmp1 = icmp slt i32 %i.0, %add 101 br i1 %cmp1, label %do.body, label %do.end ; taken either 0 or 2 times 102 103do.end: 104 ret void 105} 106 107; Unroll twice, with first loop exit kept 108; CHECK-LABEL: @u32_max1 109; CHECK: do.body: 110; CHECK: store 111; CHECK: br i1 %cmp, label %do.body.1, label %do.end 112; CHECK: do.end: 113; CHECK: ret void 114; CHECK: do.body.1: 115; CHECK: store 116; CHECK: br label %do.end 117define void @u32_max1(i32 %n, i32* %p) { 118entry: 119 %add = add i32 %n, 1 120 br label %do.body 121 122do.body: 123 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ] 124 %arrayidx = getelementptr i32, i32* %p, i32 %i.0 125 store i32 %i.0, i32* %arrayidx, align 4 126 %inc = add i32 %i.0, 1 127 %cmp = icmp ult i32 %i.0, %add 128 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 1 times 129 130do.end: 131 ret void 132} 133 134; Unroll thrice, with first loop exit kept 135; CHECK-LABEL: @u32_max2 136; CHECK: do.body: 137; CHECK: store 138; CHECK: br i1 %cmp, label %do.body.1, label %do.end 139; CHECK: do.end: 140; CHECK: ret void 141; CHECK: do.body.1: 142; CHECK: store 143; CHECK: store 144; CHECK: br label %do.end 145define void @u32_max2(i32 %n, i32* %p) { 146entry: 147 %add = add i32 %n, 2 148 br label %do.body 149 150do.body: 151 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ] 152 %arrayidx = getelementptr i32, i32* %p, i32 %i.0 153 store i32 %i.0, i32* %arrayidx, align 4 154 %inc = add i32 %i.0, 1 155 %cmp = icmp ult i32 %i.0, %add 156 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or 2 times 157 158do.end: 159 ret void 160} 161 162; Should not be unrolled 163; CHECK-LABEL: @u32_maxx 164; CHECK: do.body: 165; CHECK: do.end: 166; CHECK-NOT: do.body.1: 167define void @u32_maxx(i32 %n, i32 %x, i32* %p) { 168entry: 169 %add = add i32 %x, %n 170 br label %do.body 171 172do.body: 173 %i.0 = phi i32 [ %n, %entry ], [ %inc, %do.body ] 174 %arrayidx = getelementptr i32, i32* %p, i32 %i.0 175 store i32 %i.0, i32* %arrayidx, align 4 176 %inc = add i32 %i.0, 1 177 %cmp = icmp ult i32 %i.0, %add 178 br i1 %cmp, label %do.body, label %do.end ; taken either 0 or x times 179 180do.end: 181 ret void 182} 183 184; Should not be unrolled 185; CHECK-LABEL: @u32_max2_unpredictable_exit 186; CHECK: do.body: 187; CHECK: do.end: 188; CHECK-NOT: do.body.1: 189define void @u32_max2_unpredictable_exit(i32 %n, i32 %x, i32* %p) { 190entry: 191 %add = add i32 %n, 2 192 br label %do.body 193 194do.body: 195 %i.0 = phi i32 [ %n, %entry ], [ %inc, %if.end ] 196 %cmp = icmp eq i32 %i.0, %x 197 br i1 %cmp, label %do.end, label %if.end ; unpredictable 198 199if.end: 200 %arrayidx = getelementptr i32, i32* %p, i32 %i.0 201 store i32 %i.0, i32* %arrayidx, align 4 202 %inc = add i32 %i.0, 1 203 %cmp1 = icmp ult i32 %i.0, %add 204 br i1 %cmp1, label %do.body, label %do.end ; taken either 0 or 2 times 205 206do.end: 207 ret void 208} 209