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 | 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" |
| 4 | |
Andrew Trick | b1ce4c0 | 2011-05-31 21:17:47 +0000 | [diff] [blame] | 5 | ; IV with constant start, preinc and postinc sign extends, with and without NSW. |
| 6 | ; IV rewrite only removes one sext. WidenIVs removes all three. |
Andrew Trick | fcdc9a4 | 2011-05-26 00:46:11 +0000 | [diff] [blame] | 7 | define void @postincConstIV(i8* %base, i32 %limit) nounwind { |
| 8 | entry: |
| 9 | br label %loop |
| 10 | ; CHECK: loop: |
| 11 | ; CHECK-NOT: sext |
| 12 | ; CHECK: exit: |
| 13 | loop: |
| 14 | %iv = phi i32 [ %postiv, %loop ], [ 0, %entry ] |
| 15 | %ivnsw = phi i32 [ %postivnsw, %loop ], [ 0, %entry ] |
| 16 | %preofs = sext i32 %iv to i64 |
| 17 | %preadr = getelementptr i8* %base, i64 %preofs |
| 18 | store i8 0, i8* %preadr |
| 19 | %postiv = add i32 %iv, 1 |
| 20 | %postofs = sext i32 %postiv to i64 |
| 21 | %postadr = getelementptr i8* %base, i64 %postofs |
| 22 | store i8 0, i8* %postadr |
| 23 | %postivnsw = add nsw i32 %ivnsw, 1 |
| 24 | %postofsnsw = sext i32 %postivnsw to i64 |
| 25 | %postadrnsw = getelementptr i8* %base, i64 %postofsnsw |
| 26 | store i8 0, i8* %postadrnsw |
| 27 | %cond = icmp sgt i32 %limit, %iv |
| 28 | br i1 %cond, label %loop, label %exit |
| 29 | exit: |
| 30 | br label %return |
| 31 | return: |
| 32 | ret void |
| 33 | } |
| 34 | |
Andrew Trick | b1ce4c0 | 2011-05-31 21:17:47 +0000 | [diff] [blame] | 35 | ; IV with nonconstant start, preinc and postinc sign extends, |
Andrew Trick | fcdc9a4 | 2011-05-26 00:46:11 +0000 | [diff] [blame] | 36 | ; with and without NSW. |
Andrew Trick | b1ce4c0 | 2011-05-31 21:17:47 +0000 | [diff] [blame] | 37 | ; As with postincConstIV, WidenIVs removes all three sexts. |
Andrew Trick | fcdc9a4 | 2011-05-26 00:46:11 +0000 | [diff] [blame] | 38 | define void @postincVarIV(i8* %base, i32 %init, i32 %limit) nounwind { |
| 39 | entry: |
Andrew Trick | b1ce4c0 | 2011-05-31 21:17:47 +0000 | [diff] [blame] | 40 | %precond = icmp sgt i32 %limit, %init |
| 41 | br i1 %precond, label %loop, label %return |
Andrew Trick | fcdc9a4 | 2011-05-26 00:46:11 +0000 | [diff] [blame] | 42 | ; CHECK: loop: |
Andrew Trick | fcdc9a4 | 2011-05-26 00:46:11 +0000 | [diff] [blame] | 43 | ; CHECK-NOT: sext |
| 44 | ; CHECK: exit: |
| 45 | loop: |
| 46 | %iv = phi i32 [ %postiv, %loop ], [ %init, %entry ] |
Andrew Trick | b1ce4c0 | 2011-05-31 21:17:47 +0000 | [diff] [blame] | 47 | %ivnsw = phi i32 [ %postivnsw, %loop ], [ %init, %entry ] |
Andrew Trick | fcdc9a4 | 2011-05-26 00:46:11 +0000 | [diff] [blame] | 48 | %preofs = sext i32 %iv to i64 |
| 49 | %preadr = getelementptr i8* %base, i64 %preofs |
| 50 | store i8 0, i8* %preadr |
| 51 | %postiv = add i32 %iv, 1 |
| 52 | %postofs = sext i32 %postiv to i64 |
| 53 | %postadr = getelementptr i8* %base, i64 %postofs |
| 54 | store i8 0, i8* %postadr |
| 55 | %postivnsw = add nsw i32 %ivnsw, 1 |
| 56 | %postofsnsw = sext i32 %postivnsw to i64 |
| 57 | %postadrnsw = getelementptr i8* %base, i64 %postofsnsw |
| 58 | store i8 0, i8* %postadrnsw |
Andrew Trick | b1ce4c0 | 2011-05-31 21:17:47 +0000 | [diff] [blame] | 59 | %cond = icmp sgt i32 %limit, %postiv |
Andrew Trick | fcdc9a4 | 2011-05-26 00:46:11 +0000 | [diff] [blame] | 60 | br i1 %cond, label %loop, label %exit |
| 61 | exit: |
| 62 | br label %return |
| 63 | return: |
| 64 | ret void |
| 65 | } |
| 66 | |
| 67 | ; Test sign extend elimination in the inner and outer loop. |
Andrew Trick | 03d3d3b | 2011-05-25 04:42:22 +0000 | [diff] [blame] | 68 | ; %outercount is straightforward to widen, besides being in an outer loop. |
| 69 | ; %innercount is currently blocked by lcssa, so is not widened. |
| 70 | ; %inneriv can be widened only after proving it has no signed-overflow |
| 71 | ; based on the loop test. |
| 72 | define void @nestedIV(i8* %address, i32 %limit) nounwind { |
| 73 | entry: |
| 74 | %limitdec = add i32 %limit, -1 |
| 75 | br label %outerloop |
| 76 | |
| 77 | ; CHECK: outerloop: |
| 78 | ; |
| 79 | ; Eliminate %ofs1 after widening outercount. |
| 80 | ; CHECK-NOT: sext |
| 81 | ; CHECK: getelementptr |
| 82 | ; |
| 83 | ; IV rewriting hoists a gep into this block. We don't like that. |
| 84 | ; CHECK-NOT: getelementptr |
| 85 | outerloop: |
| 86 | %outercount = phi i32 [ %outerpostcount, %outermerge ], [ 0, %entry ] |
| 87 | %innercount = phi i32 [ %innercount.merge, %outermerge ], [ 0, %entry ] |
| 88 | |
| 89 | %outercountdec = add i32 %outercount, -1 |
| 90 | %ofs1 = sext i32 %outercountdec to i64 |
| 91 | %adr1 = getelementptr i8* %address, i64 %ofs1 |
| 92 | store i8 0, i8* %adr1 |
| 93 | |
| 94 | br label %innerpreheader |
| 95 | |
| 96 | innerpreheader: |
| 97 | %innerprecmp = icmp sgt i32 %limitdec, %innercount |
| 98 | br i1 %innerprecmp, label %innerloop, label %outermerge |
| 99 | |
| 100 | ; CHECK: innerloop: |
| 101 | ; |
| 102 | ; Eliminate %ofs2 after widening inneriv. |
Andrew Trick | b1ce4c0 | 2011-05-31 21:17:47 +0000 | [diff] [blame] | 103 | ; Eliminate %ofs3 after normalizing sext(innerpostiv) |
Andrew Trick | 03d3d3b | 2011-05-25 04:42:22 +0000 | [diff] [blame] | 104 | ; CHECK-NOT: sext |
| 105 | ; CHECK: getelementptr |
| 106 | ; |
Andrew Trick | b1ce4c0 | 2011-05-31 21:17:47 +0000 | [diff] [blame] | 107 | ; FIXME: We should check that indvars does not increase the number of |
| 108 | ; IVs in this loop. sext elimination plus LFTR currently results in 2 final |
| 109 | ; IVs. Waiting to remove LFTR. |
Andrew Trick | 03d3d3b | 2011-05-25 04:42:22 +0000 | [diff] [blame] | 110 | innerloop: |
| 111 | %inneriv = phi i32 [ %innerpostiv, %innerloop ], [ %innercount, %innerpreheader ] |
| 112 | %innerpostiv = add i32 %inneriv, 1 |
| 113 | |
| 114 | %ofs2 = sext i32 %inneriv to i64 |
| 115 | %adr2 = getelementptr i8* %address, i64 %ofs2 |
| 116 | store i8 0, i8* %adr2 |
| 117 | |
| 118 | %ofs3 = sext i32 %innerpostiv to i64 |
| 119 | %adr3 = getelementptr i8* %address, i64 %ofs3 |
| 120 | store i8 0, i8* %adr3 |
| 121 | |
| 122 | %innercmp = icmp sgt i32 %limitdec, %innerpostiv |
| 123 | br i1 %innercmp, label %innerloop, label %innerexit |
| 124 | |
| 125 | innerexit: |
| 126 | %innercount.lcssa = phi i32 [ %innerpostiv, %innerloop ] |
| 127 | br label %outermerge |
| 128 | |
| 129 | ; CHECK: outermerge: |
| 130 | ; |
| 131 | ; Eliminate %ofs4 after widening outercount |
| 132 | ; CHECK-NOT: sext |
| 133 | ; CHECK: getelementptr |
| 134 | ; |
| 135 | ; TODO: Eliminate %ofs5 after removing lcssa |
| 136 | outermerge: |
| 137 | %innercount.merge = phi i32 [ %innercount.lcssa, %innerexit ], [ %innercount, %innerpreheader ] |
| 138 | |
| 139 | %ofs4 = sext i32 %outercount to i64 |
| 140 | %adr4 = getelementptr i8* %address, i64 %ofs4 |
| 141 | store i8 0, i8* %adr3 |
| 142 | |
| 143 | %ofs5 = sext i32 %innercount.merge to i64 |
| 144 | %adr5 = getelementptr i8* %address, i64 %ofs5 |
| 145 | store i8 0, i8* %adr4 |
| 146 | |
| 147 | %outerpostcount = add i32 %outercount, 1 |
| 148 | %tmp47 = icmp slt i32 %outerpostcount, %limit |
| 149 | br i1 %tmp47, label %outerloop, label %return |
| 150 | |
| 151 | return: |
| 152 | ret void |
| 153 | } |