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