Andrew Trick | dba9573 | 2012-03-22 17:09:04 +0000 | [diff] [blame] | 1 | ; RUN: opt < %s -indvars -S | FileCheck %s |
Andrew Trick | fc933c0 | 2011-07-18 20:32:31 +0000 | [diff] [blame] | 2 | ; |
| 3 | ; Make sure that indvars can perform LFTR without a canonical IV. |
| 4 | |
| 5 | 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" |
| 6 | |
| 7 | ; Perform LFTR using the original pointer-type IV. |
| 8 | |
| 9 | ; for(char* p = base; p < base + n; ++p) { |
| 10 | ; *p = p-base; |
| 11 | ; } |
| 12 | define void @ptriv(i8* %base, i32 %n) nounwind { |
| 13 | entry: |
| 14 | %idx.ext = sext i32 %n to i64 |
| 15 | %add.ptr = getelementptr inbounds i8* %base, i64 %idx.ext |
| 16 | %cmp1 = icmp ult i8* %base, %add.ptr |
| 17 | br i1 %cmp1, label %for.body, label %for.end |
| 18 | |
| 19 | ; CHECK: for.body: |
| 20 | ; CHECK: phi i8* |
| 21 | ; CHECK-NOT: phi |
| 22 | ; CHECK-NOT: add |
| 23 | ; CHECK: icmp ne i8* |
| 24 | ; CHECK: br i1 |
| 25 | for.body: |
| 26 | %p.02 = phi i8* [ %base, %entry ], [ %incdec.ptr, %for.body ] |
| 27 | ; cruft to make the IV useful |
| 28 | %sub.ptr.lhs.cast = ptrtoint i8* %p.02 to i64 |
| 29 | %sub.ptr.rhs.cast = ptrtoint i8* %base to i64 |
| 30 | %sub.ptr.sub = sub i64 %sub.ptr.lhs.cast, %sub.ptr.rhs.cast |
| 31 | %conv = trunc i64 %sub.ptr.sub to i8 |
| 32 | store i8 %conv, i8* %p.02 |
| 33 | %incdec.ptr = getelementptr inbounds i8* %p.02, i32 1 |
| 34 | %cmp = icmp ult i8* %incdec.ptr, %add.ptr |
| 35 | br i1 %cmp, label %for.body, label %for.end |
| 36 | |
| 37 | for.end: |
| 38 | ret void |
| 39 | } |
| 40 | |
| 41 | ; It would be nice if SCEV and any loop analysis could assume that |
| 42 | ; preheaders exist. Unfortunately it is not always the case. This test |
| 43 | ; checks that SCEVExpander can handle an outer loop that has not yet |
| 44 | ; been simplified. As a result, the inner loop's exit test will not be |
| 45 | ; rewritten. |
| 46 | define void @expandOuterRecurrence(i32 %arg) nounwind { |
| 47 | entry: |
| 48 | %sub1 = sub nsw i32 %arg, 1 |
| 49 | %cmp1 = icmp slt i32 0, %sub1 |
| 50 | br i1 %cmp1, label %outer, label %exit |
| 51 | |
| 52 | outer: |
| 53 | %i = phi i32 [ 0, %entry ], [ %i.inc, %outer.inc ] |
| 54 | %sub2 = sub nsw i32 %arg, %i |
| 55 | %sub3 = sub nsw i32 %sub2, 1 |
| 56 | %cmp2 = icmp slt i32 0, %sub3 |
| 57 | br i1 %cmp2, label %inner.ph, label %outer.inc |
| 58 | |
| 59 | inner.ph: |
| 60 | br label %inner |
| 61 | |
| 62 | ; CHECK: inner: |
| 63 | ; CHECK: icmp slt |
| 64 | ; CHECK: br i1 |
| 65 | inner: |
| 66 | %j = phi i32 [ 0, %inner.ph ], [ %j.inc, %inner ] |
| 67 | %j.inc = add nsw i32 %j, 1 |
| 68 | %cmp3 = icmp slt i32 %j.inc, %sub3 |
| 69 | br i1 %cmp3, label %inner, label %outer.inc |
| 70 | |
| 71 | ; CHECK: outer.inc: |
| 72 | ; CHECK: icmp ne |
| 73 | ; CHECK: br i1 |
| 74 | outer.inc: |
| 75 | %i.inc = add nsw i32 %i, 1 |
| 76 | %cmp4 = icmp slt i32 %i.inc, %sub1 |
| 77 | br i1 %cmp4, label %outer, label %exit |
| 78 | |
| 79 | exit: |
| 80 | ret void |
| 81 | } |
| 82 | |
| 83 | ; Force SCEVExpander to look for an existing well-formed phi. |
| 84 | ; Perform LFTR without generating extra preheader code. |
| 85 | define void @guardedloop([0 x double]* %matrix, [0 x double]* %vector, |
| 86 | i32 %irow, i32 %ilead) nounwind { |
| 87 | ; CHECK: entry: |
| 88 | ; CHECK-NOT: zext |
| 89 | ; CHECK-NOT: add |
| 90 | ; CHECK: loop: |
| 91 | ; CHECK: phi i64 |
| 92 | ; CHECK: phi i64 |
| 93 | ; CHECK-NOT: phi |
| 94 | ; CHECK: icmp ne |
| 95 | ; CHECK: br i1 |
| 96 | entry: |
| 97 | %cmp = icmp slt i32 1, %irow |
| 98 | br i1 %cmp, label %loop, label %return |
| 99 | |
| 100 | loop: |
| 101 | %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ] |
| 102 | %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ] |
| 103 | %diagidx = add nsw i32 %rowidx, %i |
| 104 | %diagidxw = sext i32 %diagidx to i64 |
| 105 | %matrixp = getelementptr inbounds [0 x double]* %matrix, i32 0, i64 %diagidxw |
| 106 | %v1 = load double* %matrixp |
| 107 | %iw = sext i32 %i to i64 |
| 108 | %vectorp = getelementptr inbounds [0 x double]* %vector, i32 0, i64 %iw |
| 109 | %v2 = load double* %vectorp |
| 110 | %row.inc = add nsw i32 %rowidx, %ilead |
| 111 | %i.inc = add nsw i32 %i, 1 |
| 112 | %cmp196 = icmp slt i32 %i.inc, %irow |
| 113 | br i1 %cmp196, label %loop, label %return |
| 114 | |
| 115 | return: |
| 116 | ret void |
| 117 | } |
| 118 | |
| 119 | ; Avoid generating extra code to materialize a trip count. Skip LFTR. |
| 120 | define void @unguardedloop([0 x double]* %matrix, [0 x double]* %vector, |
| 121 | i32 %irow, i32 %ilead) nounwind { |
| 122 | entry: |
| 123 | br label %loop |
| 124 | |
| 125 | ; CHECK: entry: |
| 126 | ; CHECK-NOT: zext |
| 127 | ; CHECK-NOT: add |
| 128 | ; CHECK: loop: |
| 129 | ; CHECK: phi i64 |
| 130 | ; CHECK: phi i64 |
| 131 | ; CHECK-NOT: phi |
| 132 | ; CHECK: icmp slt |
| 133 | ; CHECK: br i1 |
| 134 | loop: |
| 135 | %rowidx = phi i32 [ 0, %entry ], [ %row.inc, %loop ] |
| 136 | %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ] |
| 137 | %diagidx = add nsw i32 %rowidx, %i |
| 138 | %diagidxw = sext i32 %diagidx to i64 |
| 139 | %matrixp = getelementptr inbounds [0 x double]* %matrix, i32 0, i64 %diagidxw |
| 140 | %v1 = load double* %matrixp |
| 141 | %iw = sext i32 %i to i64 |
| 142 | %vectorp = getelementptr inbounds [0 x double]* %vector, i32 0, i64 %iw |
| 143 | %v2 = load double* %vectorp |
| 144 | %row.inc = add nsw i32 %rowidx, %ilead |
| 145 | %i.inc = add nsw i32 %i, 1 |
| 146 | %cmp196 = icmp slt i32 %i.inc, %irow |
| 147 | br i1 %cmp196, label %loop, label %return |
| 148 | |
| 149 | return: |
| 150 | ret void |
| 151 | } |
| 152 | |
| 153 | ; Remove %i which is only used by the exit test. |
| 154 | ; Verify that SCEV can still compute a backedge count from the sign |
| 155 | ; extended %n, used for pointer comparison by LFTR. |
Andrew Trick | 4781d8e | 2012-07-18 04:35:10 +0000 | [diff] [blame] | 156 | ; |
| 157 | ; TODO: Fix for PR13371 currently makes this impossible. See |
| 158 | ; IndVarSimplify.cpp hasConcreteDef(). We may want to change to undef rules. |
Andrew Trick | fc933c0 | 2011-07-18 20:32:31 +0000 | [diff] [blame] | 159 | define void @geplftr(i8* %base, i32 %x, i32 %y, i32 %n) nounwind { |
| 160 | entry: |
| 161 | %x.ext = sext i32 %x to i64 |
| 162 | %add.ptr = getelementptr inbounds i8* %base, i64 %x.ext |
| 163 | %y.ext = sext i32 %y to i64 |
| 164 | %add.ptr10 = getelementptr inbounds i8* %add.ptr, i64 %y.ext |
| 165 | %lim = add i32 %x, %n |
| 166 | %cmp.ph = icmp ult i32 %x, %lim |
| 167 | br i1 %cmp.ph, label %loop, label %exit |
Andrew Trick | 4781d8e | 2012-07-18 04:35:10 +0000 | [diff] [blame] | 168 | ; CHECK: @geplftr |
Andrew Trick | fc933c0 | 2011-07-18 20:32:31 +0000 | [diff] [blame] | 169 | ; CHECK: loop: |
| 170 | ; CHECK: phi i8* |
Andrew Trick | 4781d8e | 2012-07-18 04:35:10 +0000 | [diff] [blame] | 171 | ; DISABLE-NOT: phi // This check is currently disabled |
Andrew Trick | fc933c0 | 2011-07-18 20:32:31 +0000 | [diff] [blame] | 172 | ; CHECK: getelementptr |
| 173 | ; CHECK: store |
Andrew Trick | 4781d8e | 2012-07-18 04:35:10 +0000 | [diff] [blame] | 174 | ; DISABLE: icmp ne i8* // This check is currently disabled |
Andrew Trick | fc933c0 | 2011-07-18 20:32:31 +0000 | [diff] [blame] | 175 | ; CHECK: br i1 |
| 176 | loop: |
| 177 | %i = phi i32 [ %x, %entry ], [ %inc, %loop ] |
| 178 | %aptr = phi i8* [ %add.ptr10, %entry ], [ %incdec.ptr, %loop ] |
| 179 | %incdec.ptr = getelementptr inbounds i8* %aptr, i32 1 |
| 180 | store i8 3, i8* %aptr |
| 181 | %inc = add i32 %i, 1 |
| 182 | %cmp = icmp ult i32 %inc, %lim |
| 183 | br i1 %cmp, label %loop, label %exit |
| 184 | |
| 185 | exit: |
| 186 | ret void |
| 187 | } |
| 188 | |
| 189 | ; Exercise backedge taken count verification with a never-taken loop. |
| 190 | define void @nevertaken() nounwind uwtable ssp { |
| 191 | entry: |
| 192 | br label %loop |
Andrew Trick | 4781d8e | 2012-07-18 04:35:10 +0000 | [diff] [blame] | 193 | ; CHECK: @nevertaken |
Andrew Trick | fc933c0 | 2011-07-18 20:32:31 +0000 | [diff] [blame] | 194 | ; CHECK: loop: |
| 195 | ; CHECK-NOT: phi |
| 196 | ; CHECK-NOT: add |
| 197 | ; CHECK-NOT: icmp |
| 198 | ; CHECK: exit: |
| 199 | loop: |
| 200 | %i = phi i32 [ 0, %entry ], [ %inc, %loop ] |
| 201 | %inc = add nsw i32 %i, 1 |
| 202 | %cmp = icmp sle i32 %inc, 0 |
| 203 | br i1 %cmp, label %loop, label %exit |
| 204 | |
| 205 | exit: |
| 206 | ret void |
| 207 | } |
| 208 | |
| 209 | ; Test LFTR on an IV whose recurrence start is a non-unit pointer type. |
| 210 | define void @aryptriv([256 x i8]* %base, i32 %n) nounwind { |
| 211 | entry: |
| 212 | %ivstart = getelementptr inbounds [256 x i8]* %base, i32 0, i32 0 |
| 213 | %ivend = getelementptr inbounds [256 x i8]* %base, i32 0, i32 %n |
| 214 | %cmp.ph = icmp ult i8* %ivstart, %ivend |
| 215 | br i1 %cmp.ph, label %loop, label %exit |
| 216 | |
| 217 | ; CHECK: loop: |
| 218 | ; CHECK: phi i8* |
| 219 | ; CHECK-NOT: phi |
| 220 | ; CHECK: getelementptr |
| 221 | ; CHECK: store |
| 222 | ; CHECK: icmp ne i8* |
| 223 | ; CHECK: br i1 |
| 224 | loop: |
| 225 | %aptr = phi i8* [ %ivstart, %entry ], [ %incdec.ptr, %loop ] |
| 226 | %incdec.ptr = getelementptr inbounds i8* %aptr, i32 1 |
| 227 | store i8 3, i8* %aptr |
| 228 | %cmp = icmp ult i8* %incdec.ptr, %ivend |
| 229 | br i1 %cmp, label %loop, label %exit |
| 230 | |
| 231 | exit: |
| 232 | ret void |
| 233 | } |