1 ; RUN: opt < %s -indvars -indvars-post-increment-ranges -S | FileCheck %s 2 3 target datalayout = "p:64:64:64-n32:64" 4 5 ; When the IV in this loop is widened we want to widen this use as well: 6 ; icmp slt i32 %i.inc, %limit 7 ; In order to do this indvars need to prove that the narrow IV def (%i.inc) 8 ; is not-negative from the range check inside of the loop. 9 define void @test(i32* %base, i32 %limit, i32 %start) { 10 ; CHECK-LABEL: @test( 11 ; CHECK-NOT: trunc 12 13 for.body.lr.ph: 14 br label %for.body 15 16 for.body: 17 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 18 %within_limits = icmp ult i32 %i, 64 19 br i1 %within_limits, label %continue, label %for.end 20 21 continue: 22 %i.i64 = zext i32 %i to i64 23 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 24 %val = load i32, i32* %arrayidx, align 4 25 br label %for.inc 26 27 for.inc: 28 %i.inc = add nsw nuw i32 %i, 1 29 %cmp = icmp slt i32 %i.inc, %limit 30 br i1 %cmp, label %for.body, label %for.end 31 32 for.end: 33 br label %exit 34 35 exit: 36 ret void 37 } 38 39 define void @test_false_edge(i32* %base, i32 %limit, i32 %start) { 40 ; CHECK-LABEL: @test_false_edge( 41 ; CHECK-NOT: trunc 42 43 for.body.lr.ph: 44 br label %for.body 45 46 for.body: 47 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 48 %out_of_bounds = icmp ugt i32 %i, 64 49 br i1 %out_of_bounds, label %for.end, label %continue 50 51 continue: 52 %i.i64 = zext i32 %i to i64 53 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 54 %val = load i32, i32* %arrayidx, align 4 55 br label %for.inc 56 57 for.inc: 58 %i.inc = add nsw nuw i32 %i, 1 59 %cmp = icmp slt i32 %i.inc, %limit 60 br i1 %cmp, label %for.body, label %for.end 61 62 for.end: 63 br label %exit 64 65 exit: 66 ret void 67 } 68 69 define void @test_range_metadata(i32* %array_length_ptr, i32* %base, 70 i32 %limit, i32 %start) { 71 ; CHECK-LABEL: @test_range_metadata( 72 ; CHECK-NOT: trunc 73 74 for.body.lr.ph: 75 br label %for.body 76 77 for.body: 78 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 79 %array_length = load i32, i32* %array_length_ptr, !range !{i32 0, i32 64 } 80 %within_limits = icmp ult i32 %i, %array_length 81 br i1 %within_limits, label %continue, label %for.end 82 83 continue: 84 %i.i64 = zext i32 %i to i64 85 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 86 %val = load i32, i32* %arrayidx, align 4 87 br label %for.inc 88 89 for.inc: 90 %i.inc = add nsw nuw i32 %i, 1 91 %cmp = icmp slt i32 %i.inc, %limit 92 br i1 %cmp, label %for.body, label %for.end 93 94 for.end: 95 br label %exit 96 97 exit: 98 ret void 99 } 100 101 ; Negative version of the test above, we don't know anything about 102 ; array_length_ptr range. 103 define void @test_neg(i32* %array_length_ptr, i32* %base, 104 i32 %limit, i32 %start) { 105 ; CHECK-LABEL: @test_neg( 106 ; CHECK: trunc i64 107 108 for.body.lr.ph: 109 br label %for.body 110 111 for.body: 112 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 113 %array_length = load i32, i32* %array_length_ptr 114 %within_limits = icmp ult i32 %i, %array_length 115 br i1 %within_limits, label %continue, label %for.end 116 117 continue: 118 %i.i64 = zext i32 %i to i64 119 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 120 %val = load i32, i32* %arrayidx, align 4 121 br label %for.inc 122 123 for.inc: 124 %i.inc = add nsw nuw i32 %i, 1 125 %cmp = icmp slt i32 %i.inc, %limit 126 br i1 %cmp, label %for.body, label %for.end 127 128 for.end: 129 br label %exit 130 131 exit: 132 ret void 133 } 134 135 define void @test_transitive_use(i32* %base, i32 %limit, i32 %start) { 136 ; CHECK-LABEL: @test_transitive_use( 137 ; CHECK-NOT: trunc 138 ; CHECK: %result = icmp slt i64 139 140 for.body.lr.ph: 141 br label %for.body 142 143 for.body: 144 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 145 %within_limits = icmp ult i32 %i, 64 146 br i1 %within_limits, label %continue, label %for.end 147 148 continue: 149 %i.mul.3 = mul nsw nuw i32 %i, 3 150 %mul_within = icmp ult i32 %i.mul.3, 64 151 br i1 %mul_within, label %guarded, label %continue.2 152 153 guarded: 154 %i.mul.3.inc = add nsw nuw i32 %i.mul.3, 1 155 %result = icmp slt i32 %i.mul.3.inc, %limit 156 br i1 %result, label %continue.2, label %for.end 157 158 continue.2: 159 %i.i64 = zext i32 %i to i64 160 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 161 %val = load i32, i32* %arrayidx, align 4 162 br label %for.inc 163 164 for.inc: 165 %i.inc = add nsw nuw i32 %i, 1 166 %cmp = icmp slt i32 %i.inc, %limit 167 br i1 %cmp, label %for.body, label %for.end 168 169 170 for.end: 171 br label %exit 172 173 exit: 174 ret void 175 } 176 177 declare void @llvm.experimental.guard(i1, ...) 178 179 define void @test_guard_one_bb(i32* %base, i32 %limit, i32 %start) { 180 ; CHECK-LABEL: @test_guard_one_bb( 181 ; CHECK-NOT: trunc 182 ; CHECK-NOT: icmp slt i32 183 184 for.body.lr.ph: 185 br label %for.body 186 187 for.body: 188 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ] 189 %within_limits = icmp ult i32 %i, 64 190 %i.i64 = zext i32 %i to i64 191 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 192 %val = load i32, i32* %arrayidx, align 4 193 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ] 194 %i.inc = add nsw nuw i32 %i, 1 195 %cmp = icmp slt i32 %i.inc, %limit 196 br i1 %cmp, label %for.body, label %for.end 197 198 for.end: 199 br label %exit 200 201 exit: 202 ret void 203 } 204 205 define void @test_guard_in_the_same_bb(i32* %base, i32 %limit, i32 %start) { 206 ; CHECK-LABEL: @test_guard_in_the_same_bb( 207 ; CHECK-NOT: trunc 208 ; CHECK-NOT: icmp slt i32 209 210 for.body.lr.ph: 211 br label %for.body 212 213 for.body: 214 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 215 %within_limits = icmp ult i32 %i, 64 216 %i.i64 = zext i32 %i to i64 217 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 218 %val = load i32, i32* %arrayidx, align 4 219 br label %for.inc 220 221 for.inc: 222 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ] 223 %i.inc = add nsw nuw i32 %i, 1 224 %cmp = icmp slt i32 %i.inc, %limit 225 br i1 %cmp, label %for.body, label %for.end 226 227 for.end: 228 br label %exit 229 230 exit: 231 ret void 232 } 233 234 define void @test_guard_in_idom(i32* %base, i32 %limit, i32 %start) { 235 ; CHECK-LABEL: @test_guard_in_idom( 236 ; CHECK-NOT: trunc 237 ; CHECK-NOT: icmp slt i32 238 239 for.body.lr.ph: 240 br label %for.body 241 242 for.body: 243 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.inc ] 244 %within_limits = icmp ult i32 %i, 64 245 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits) [ "deopt"() ] 246 %i.i64 = zext i32 %i to i64 247 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 248 %val = load i32, i32* %arrayidx, align 4 249 br label %for.inc 250 251 for.inc: 252 %i.inc = add nsw nuw i32 %i, 1 253 %cmp = icmp slt i32 %i.inc, %limit 254 br i1 %cmp, label %for.body, label %for.end 255 256 for.end: 257 br label %exit 258 259 exit: 260 ret void 261 } 262 263 define void @test_guard_merge_ranges(i32* %base, i32 %limit, i32 %start) { 264 ; CHECK-LABEL: @test_guard_merge_ranges( 265 ; CHECK-NOT: trunc 266 ; CHECK-NOT: icmp slt i32 267 268 for.body.lr.ph: 269 br label %for.body 270 271 for.body: 272 %i = phi i32 [ %start, %for.body.lr.ph ], [ %i.inc, %for.body ] 273 %within_limits.1 = icmp ult i32 %i, 64 274 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.1) [ "deopt"() ] 275 %within_limits.2 = icmp ult i32 %i, 2147483647 276 call void(i1, ...) @llvm.experimental.guard(i1 %within_limits.2) [ "deopt"() ] 277 %i.i64 = zext i32 %i to i64 278 %arrayidx = getelementptr inbounds i32, i32* %base, i64 %i.i64 279 %val = load i32, i32* %arrayidx, align 4 280 %i.inc = add nsw nuw i32 %i, 1 281 %cmp = icmp slt i32 %i.inc, %limit 282 br i1 %cmp, label %for.body, label %for.end 283 284 for.end: 285 br label %exit 286 287 exit: 288 ret void 289 } 290