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