1 ; RUN: opt -S -loop-unroll < %s | FileCheck %s 2 ; RUN: opt -S -passes='require<opt-remark-emit>,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 14 define void @s32_max1(i32 %n, i32* %p) { 15 entry: 16 %add = add i32 %n, 1 17 br label %do.body 18 19 do.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 27 do.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 42 define void @s32_max2(i32 %n, i32* %p) { 43 entry: 44 %add = add i32 %n, 2 45 br label %do.body 46 47 do.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 55 do.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: 64 define void @s32_maxx(i32 %n, i32 %x, i32* %p) { 65 entry: 66 %add = add i32 %x, %n 67 br label %do.body 68 69 do.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 77 do.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: 86 define void @s32_max2_unpredictable_exit(i32 %n, i32 %x, i32* %p) { 87 entry: 88 %add = add i32 %n, 2 89 br label %do.body 90 91 do.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 96 if.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 103 do.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 117 define void @u32_max1(i32 %n, i32* %p) { 118 entry: 119 %add = add i32 %n, 1 120 br label %do.body 121 122 do.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 130 do.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 145 define void @u32_max2(i32 %n, i32* %p) { 146 entry: 147 %add = add i32 %n, 2 148 br label %do.body 149 150 do.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 158 do.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: 167 define void @u32_maxx(i32 %n, i32 %x, i32* %p) { 168 entry: 169 %add = add i32 %x, %n 170 br label %do.body 171 172 do.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 180 do.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: 189 define void @u32_max2_unpredictable_exit(i32 %n, i32 %x, i32* %p) { 190 entry: 191 %add = add i32 %n, 2 192 br label %do.body 193 194 do.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 199 if.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 206 do.end: 207 ret void 208 } 209