Andrew Trick | 03d3d3b | 2011-05-25 04:42:22 +0000 | [diff] [blame] | 1 | ; RUN: opt < %s -indvars -disable-iv-rewrite -S | FileCheck %s |
| 2 | ; |
| 3 | ; Make sure that indvars isn't inserting canonical IVs. |
| 4 | ; This is kinda hard to do until linear function test replacement is removed. |
| 5 | |
| 6 | target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" |
| 7 | |
| 8 | define i32 @sum(i32* %arr, i32 %n) nounwind { |
| 9 | entry: |
| 10 | %precond = icmp slt i32 0, %n |
| 11 | br i1 %precond, label %ph, label %return |
| 12 | |
| 13 | ph: |
| 14 | br label %loop |
| 15 | |
| 16 | ; CHECK: loop: |
| 17 | ; |
| 18 | ; We should only have 2 IVs. |
| 19 | ; CHECK: phi |
| 20 | ; CHECK: phi |
| 21 | ; CHECK-NOT: phi |
| 22 | ; |
| 23 | ; sext should be eliminated while preserving gep inboundsness. |
| 24 | ; CHECK-NOT: sext |
| 25 | ; CHECK: getelementptr inbounds |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 26 | ; CHECK: exit: |
Andrew Trick | 03d3d3b | 2011-05-25 04:42:22 +0000 | [diff] [blame] | 27 | loop: |
| 28 | %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] |
| 29 | %s.01 = phi i32 [ 0, %ph ], [ %sinc, %loop ] |
| 30 | %ofs = sext i32 %i.02 to i64 |
| 31 | %adr = getelementptr inbounds i32* %arr, i64 %ofs |
| 32 | %val = load i32* %adr |
| 33 | %sinc = add nsw i32 %s.01, %val |
| 34 | %iinc = add nsw i32 %i.02, 1 |
| 35 | %cond = icmp slt i32 %iinc, %n |
| 36 | br i1 %cond, label %loop, label %exit |
| 37 | |
| 38 | exit: |
| 39 | %s.lcssa = phi i32 [ %sinc, %loop ] |
| 40 | br label %return |
| 41 | |
| 42 | return: |
| 43 | %s.0.lcssa = phi i32 [ %s.lcssa, %exit ], [ 0, %entry ] |
| 44 | ret i32 %s.0.lcssa |
| 45 | } |
| 46 | |
| 47 | define i64 @suml(i32* %arr, i32 %n) nounwind { |
| 48 | entry: |
| 49 | %precond = icmp slt i32 0, %n |
| 50 | br i1 %precond, label %ph, label %return |
| 51 | |
| 52 | ph: |
| 53 | br label %loop |
| 54 | |
| 55 | ; CHECK: loop: |
| 56 | ; |
| 57 | ; We should only have 2 IVs. |
| 58 | ; CHECK: phi |
| 59 | ; CHECK: phi |
| 60 | ; CHECK-NOT: phi |
| 61 | ; |
| 62 | ; %ofs sext should be eliminated while preserving gep inboundsness. |
| 63 | ; CHECK-NOT: sext |
| 64 | ; CHECK: getelementptr inbounds |
| 65 | ; %vall sext should obviously not be eliminated |
| 66 | ; CHECK: sext |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 67 | ; CHECK: exit: |
Andrew Trick | 03d3d3b | 2011-05-25 04:42:22 +0000 | [diff] [blame] | 68 | loop: |
| 69 | %i.02 = phi i32 [ 0, %ph ], [ %iinc, %loop ] |
| 70 | %s.01 = phi i64 [ 0, %ph ], [ %sinc, %loop ] |
| 71 | %ofs = sext i32 %i.02 to i64 |
| 72 | %adr = getelementptr inbounds i32* %arr, i64 %ofs |
| 73 | %val = load i32* %adr |
| 74 | %vall = sext i32 %val to i64 |
| 75 | %sinc = add nsw i64 %s.01, %vall |
| 76 | %iinc = add nsw i32 %i.02, 1 |
| 77 | %cond = icmp slt i32 %iinc, %n |
| 78 | br i1 %cond, label %loop, label %exit |
| 79 | |
| 80 | exit: |
| 81 | %s.lcssa = phi i64 [ %sinc, %loop ] |
| 82 | br label %return |
| 83 | |
| 84 | return: |
| 85 | %s.0.lcssa = phi i64 [ %s.lcssa, %exit ], [ 0, %entry ] |
| 86 | ret i64 %s.0.lcssa |
| 87 | } |
| 88 | |
| 89 | define void @outofbounds(i32* %first, i32* %last, i32 %idx) nounwind { |
| 90 | %precond = icmp ne i32* %first, %last |
| 91 | br i1 %precond, label %ph, label %return |
| 92 | |
| 93 | ; CHECK: ph: |
| 94 | ; It's not indvars' job to perform LICM on %ofs |
| 95 | ; CHECK-NOT: sext |
| 96 | ph: |
| 97 | br label %loop |
| 98 | |
| 99 | ; CHECK: loop: |
| 100 | ; |
| 101 | ; Preserve exactly one pointer type IV. |
| 102 | ; CHECK: phi i32* |
| 103 | ; CHECK-NOT: phi |
| 104 | ; |
| 105 | ; Don't create any extra adds. |
| 106 | ; CHECK-NOT: add |
| 107 | ; |
| 108 | ; Preserve gep inboundsness, and don't factor it. |
| 109 | ; CHECK: getelementptr inbounds i32* %ptriv, i32 1 |
| 110 | ; CHECK-NOT: add |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 111 | ; CHECK: exit: |
Andrew Trick | 03d3d3b | 2011-05-25 04:42:22 +0000 | [diff] [blame] | 112 | loop: |
| 113 | %ptriv = phi i32* [ %first, %ph ], [ %ptrpost, %loop ] |
| 114 | %ofs = sext i32 %idx to i64 |
| 115 | %adr = getelementptr inbounds i32* %ptriv, i64 %ofs |
| 116 | store i32 3, i32* %adr |
| 117 | %ptrpost = getelementptr inbounds i32* %ptriv, i32 1 |
| 118 | %cond = icmp ne i32* %ptrpost, %last |
| 119 | br i1 %cond, label %loop, label %exit |
| 120 | |
| 121 | exit: |
| 122 | br label %return |
| 123 | |
| 124 | return: |
| 125 | ret void |
| 126 | } |
Andrew Trick | 11745d4 | 2011-06-29 03:13:40 +0000 | [diff] [blame] | 127 | |
| 128 | %struct = type { i32 } |
| 129 | |
| 130 | define void @bitcastiv(i32 %start, i32 %limit, i32 %step, %struct* %base) |
| 131 | nounwind |
| 132 | { |
| 133 | entry: |
| 134 | br label %loop |
| 135 | |
| 136 | ; CHECK: loop: |
| 137 | ; |
| 138 | ; Preserve casts |
| 139 | ; CHECK: phi i32 |
| 140 | ; CHECK: bitcast |
| 141 | ; CHECK: getelementptr |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 142 | ; CHECK: exit: |
Andrew Trick | 11745d4 | 2011-06-29 03:13:40 +0000 | [diff] [blame] | 143 | loop: |
| 144 | %iv = phi i32 [%start, %entry], [%next, %loop] |
| 145 | %p = phi %struct* [%base, %entry], [%pinc, %loop] |
| 146 | %adr = getelementptr %struct* %p, i32 0, i32 0 |
| 147 | store i32 3, i32* %adr |
| 148 | %pp = bitcast %struct* %p to i32* |
| 149 | store i32 4, i32* %pp |
| 150 | %pinc = getelementptr %struct* %p, i32 1 |
| 151 | %next = add i32 %iv, 1 |
| 152 | %cond = icmp ne i32 %next, %limit |
| 153 | br i1 %cond, label %loop, label %exit |
| 154 | |
| 155 | exit: |
Andrew Trick | cc359d9 | 2011-06-29 23:03:57 +0000 | [diff] [blame] | 156 | ret void |
| 157 | } |
Andrew Trick | 11745d4 | 2011-06-29 03:13:40 +0000 | [diff] [blame] | 158 | |
Andrew Trick | cc359d9 | 2011-06-29 23:03:57 +0000 | [diff] [blame] | 159 | define void @maxvisitor(i32 %limit, i32* %base) nounwind { |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 160 | entry: |
| 161 | br label %loop |
Andrew Trick | cc359d9 | 2011-06-29 23:03:57 +0000 | [diff] [blame] | 162 | |
Andrew Trick | 6e0ce24 | 2011-06-30 19:02:17 +0000 | [diff] [blame] | 163 | ; Test inserting a truncate at a phi use. |
| 164 | ; |
Andrew Trick | cc359d9 | 2011-06-29 23:03:57 +0000 | [diff] [blame] | 165 | ; CHECK: loop: |
| 166 | ; CHECK: phi i64 |
| 167 | ; CHECK: trunc |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 168 | ; CHECK: exit: |
Andrew Trick | cc359d9 | 2011-06-29 23:03:57 +0000 | [diff] [blame] | 169 | loop: |
| 170 | %idx = phi i32 [ 0, %entry ], [ %idx.next, %loop.inc ] |
| 171 | %max = phi i32 [ 0, %entry ], [ %max.next, %loop.inc ] |
| 172 | %idxprom = sext i32 %idx to i64 |
| 173 | %adr = getelementptr inbounds i32* %base, i64 %idxprom |
| 174 | %val = load i32* %adr |
| 175 | %cmp19 = icmp sgt i32 %val, %max |
| 176 | br i1 %cmp19, label %if.then, label %if.else |
| 177 | |
| 178 | if.then: |
| 179 | br label %loop.inc |
| 180 | |
| 181 | if.else: |
| 182 | br label %loop.inc |
| 183 | |
| 184 | loop.inc: |
| 185 | %max.next = phi i32 [ %idx, %if.then ], [ %max, %if.else ] |
| 186 | %idx.next = add nsw i32 %idx, 1 |
| 187 | %cmp = icmp slt i32 %idx.next, %limit |
| 188 | br i1 %cmp, label %loop, label %exit |
| 189 | |
| 190 | exit: |
Andrew Trick | 11745d4 | 2011-06-29 03:13:40 +0000 | [diff] [blame] | 191 | ret void |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 192 | } |
| 193 | |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 194 | define void @identityphi(i32 %limit) nounwind { |
| 195 | entry: |
| 196 | br label %loop |
| 197 | |
Andrew Trick | 6e0ce24 | 2011-06-30 19:02:17 +0000 | [diff] [blame] | 198 | ; Test an edge case of removing an identity phi that directly feeds |
| 199 | ; back to the loop iv. |
| 200 | ; |
| 201 | ; CHECK: loop: |
| 202 | ; CHECK: phi i32 |
| 203 | ; CHECK-NOT: phi |
| 204 | ; CHECK: exit: |
Andrew Trick | 60ac719 | 2011-06-30 01:27:23 +0000 | [diff] [blame] | 205 | loop: |
| 206 | %iv = phi i32 [ 0, %entry], [ %iv.next, %control ] |
| 207 | br i1 undef, label %if.then, label %control |
| 208 | |
| 209 | if.then: |
| 210 | br label %control |
| 211 | |
| 212 | control: |
| 213 | %iv.next = phi i32 [ %iv, %loop ], [ undef, %if.then ] |
| 214 | %cmp = icmp slt i32 %iv.next, %limit |
| 215 | br i1 %cmp, label %loop, label %exit |
| 216 | |
| 217 | exit: |
| 218 | ret void |
| 219 | } |
Andrew Trick | 6e0ce24 | 2011-06-30 19:02:17 +0000 | [diff] [blame] | 220 | |
| 221 | define i64 @cloneOr(i32 %limit, i64* %base) nounwind { |
| 222 | entry: |
| 223 | ; ensure that the loop can't overflow |
| 224 | %halfLim = ashr i32 %limit, 2 |
| 225 | br label %loop |
| 226 | |
| 227 | ; Test cloning an or, which is not an OverflowBinaryOperator. |
| 228 | ; |
| 229 | ; CHECK: loop: |
| 230 | ; CHECK: phi i64 |
| 231 | ; CHECK-NOT: sext |
| 232 | ; CHECK: or i64 |
| 233 | ; CHECK: exit: |
| 234 | loop: |
| 235 | %iv = phi i32 [ 0, %entry], [ %iv.next, %loop ] |
| 236 | %t1 = sext i32 %iv to i64 |
| 237 | %adr = getelementptr i64* %base, i64 %t1 |
| 238 | %val = load i64* %adr |
| 239 | %t2 = or i32 %iv, 1 |
| 240 | %t3 = sext i32 %t2 to i64 |
| 241 | %iv.next = add i32 %iv, 2 |
| 242 | %cmp = icmp slt i32 %iv.next, %halfLim |
| 243 | br i1 %cmp, label %loop, label %exit |
| 244 | |
| 245 | exit: |
| 246 | %result = and i64 %val, %t3 |
| 247 | ret i64 %result |
| 248 | } |
Andrew Trick | 4b02915 | 2011-07-02 02:34:25 +0000 | [diff] [blame] | 249 | |
| 250 | ; The i induction variable looks like a wrap-around, but it really is just |
| 251 | ; a simple affine IV. Make sure that indvars simplifies through. |
| 252 | define i32 @indirectRecurrence() nounwind { |
| 253 | entry: |
| 254 | br label %loop |
| 255 | |
| 256 | ; ReplaceLoopExitValue should fold the return value to constant 9. |
| 257 | ; CHECK: loop: |
| 258 | ; CHECK: phi i32 |
| 259 | ; CHECK: ret i32 9 |
| 260 | loop: |
| 261 | %j.0 = phi i32 [ 1, %entry ], [ %j.next, %cond_true ] |
| 262 | %i.0 = phi i32 [ 0, %entry ], [ %j.0, %cond_true ] |
| 263 | %tmp = icmp ne i32 %j.0, 10 |
| 264 | br i1 %tmp, label %cond_true, label %return |
| 265 | |
| 266 | cond_true: |
| 267 | %j.next = add i32 %j.0, 1 |
| 268 | br label %loop |
| 269 | |
| 270 | return: |
| 271 | ret i32 %i.0 |
| 272 | } |
Andrew Trick | 037d1c0 | 2011-07-06 20:50:43 +0000 | [diff] [blame^] | 273 | |
| 274 | ; Eliminate the congruent phis j, k, and l. |
| 275 | ; Eliminate the redundant IV increments k.next and l.next. |
| 276 | ; Two phis should remain, one starting at %init, and one at %init1. |
| 277 | ; Two increments should remain, one by %step and one by %step1. |
| 278 | ; CHECK: loop: |
| 279 | ; CHECK: phi i32 |
| 280 | ; CHECK: phi i32 |
| 281 | ; CHECK-NOT: phi |
| 282 | ; CHECK: add i32 |
| 283 | ; CHECK: add i32 |
| 284 | ; CHECK-NOT: add |
| 285 | ; CHECK: return: |
| 286 | ; |
| 287 | ; Five live-outs should remain. |
| 288 | ; CHECK: lcssa = phi |
| 289 | ; CHECK: lcssa = phi |
| 290 | ; CHECK: lcssa = phi |
| 291 | ; CHECK: lcssa = phi |
| 292 | ; CHECK: lcssa = phi |
| 293 | ; CHECK-NOT: phi |
| 294 | ; CHECK: ret |
| 295 | define i32 @isomorphic(i32 %init, i32 %step, i32 %lim) nounwind { |
| 296 | entry: |
| 297 | %step1 = add i32 %step, 1 |
| 298 | %init1 = add i32 %init, %step1 |
| 299 | %l.0 = sub i32 %init1, %step1 |
| 300 | br label %loop |
| 301 | |
| 302 | loop: |
| 303 | %ii = phi i32 [ %init1, %entry ], [ %ii.next, %loop ] |
| 304 | %i = phi i32 [ %init, %entry ], [ %ii, %loop ] |
| 305 | %j = phi i32 [ %init, %entry ], [ %j.next, %loop ] |
| 306 | %k = phi i32 [ %init1, %entry ], [ %k.next, %loop ] |
| 307 | %l = phi i32 [ %l.0, %entry ], [ %l.next, %loop ] |
| 308 | %ii.next = add i32 %ii, %step1 |
| 309 | %j.next = add i32 %j, %step1 |
| 310 | %k.next = add i32 %k, %step1 |
| 311 | %l.step = add i32 %l, %step |
| 312 | %l.next = add i32 %l.step, 1 |
| 313 | %cmp = icmp ne i32 %ii.next, %lim |
| 314 | br i1 %cmp, label %loop, label %return |
| 315 | |
| 316 | return: |
| 317 | %sum1 = add i32 %i, %j.next |
| 318 | %sum2 = add i32 %sum1, %k.next |
| 319 | %sum3 = add i32 %sum1, %l.step |
| 320 | %sum4 = add i32 %sum1, %l.next |
| 321 | ret i32 %sum4 |
| 322 | } |