1 ; RUN: opt < %s -bounds-checking -S | FileCheck %s 2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 3 4 ; CHECK-LABEL: @sumSize 5 define dso_local i32 @sumSize(i32 %n) { 6 entry: 7 %foo = alloca [1000 x i32], align 16 8 %0 = bitcast [1000 x i32]* %foo to i8* 9 call void @llvm.lifetime.start.p0i8(i64 4000, i8* nonnull %0) 10 %arraydecay = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 0 11 call void @fill(i32* nonnull %arraydecay, i32 %n) 12 br label %for.body.i 13 14 for.body.i: ; preds = %for.body.i, %entry 15 %indvars.iv.i = phi i64 [ 0, %entry ], [ %indvars.iv.next.i, %for.body.i ] 16 %sum.07.i = phi i32 [ 0, %entry ], [ %add.i, %for.body.i ] 17 %arrayidx.i = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 %indvars.iv.i 18 ; CHECK-NOT: trap 19 %1 = load i32, i32* %arrayidx.i, align 4 20 %add.i = add nsw i32 %1, %sum.07.i 21 %indvars.iv.next.i = add nuw nsw i64 %indvars.iv.i, 1 22 %exitcond.i = icmp eq i64 %indvars.iv.next.i, 1000 23 br i1 %exitcond.i, label %accumulate.exit, label %for.body.i 24 25 accumulate.exit: ; preds = %for.body.i 26 call void @llvm.lifetime.end.p0i8(i64 4000, i8* nonnull %0) 27 ret i32 %add.i 28 } 29 30 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) 31 32 declare dso_local void @fill(i32*, i32) 33 34 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) 35 36 ; CHECK-LABEL: @sumSizePlusOne 37 define dso_local i32 @sumSizePlusOne(i32 %n) { 38 entry: 39 %foo = alloca [1000 x i32], align 16 40 %0 = bitcast [1000 x i32]* %foo to i8* 41 call void @llvm.lifetime.start.p0i8(i64 4000, i8* nonnull %0) 42 %arraydecay = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 0 43 call void @fill(i32* nonnull %arraydecay, i32 %n) 44 br label %for.body.i 45 46 for.body.i: ; preds = %for.body.i, %entry 47 %indvars.iv.i = phi i64 [ 0, %entry ], [ %indvars.iv.next.i, %for.body.i ] 48 %sum.01.i = phi i32 [ 0, %entry ], [ %add.i, %for.body.i ] 49 %arrayidx.i = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 %indvars.iv.i 50 ; CHECK: mul i64 {{.*}}, 4 51 ; CHECK: sub i64 4000, % 52 ; CHECK-NEXT: icmp ult i64 {{.*}}, 4 53 ; CHECK-NEXT: or i1 54 ; CHECK: trap 55 %1 = load i32, i32* %arrayidx.i, align 4 56 %add.i = add nsw i32 %1, %sum.01.i 57 %indvars.iv.next.i = add nuw nsw i64 %indvars.iv.i, 1 58 %exitcond.i = icmp eq i64 %indvars.iv.next.i, 1001 59 br i1 %exitcond.i, label %accumulate.exit, label %for.body.i 60 61 accumulate.exit: ; preds = %for.body.i 62 call void @llvm.lifetime.end.p0i8(i64 4000, i8* nonnull %0) 63 ret i32 %add.i 64 } 65 66 ; CHECK-LABEL: @sumLarger 67 define dso_local i32 @sumLarger(i32 %n) { 68 entry: 69 %foo = alloca [1000 x i32], align 16 70 %0 = bitcast [1000 x i32]* %foo to i8* 71 call void @llvm.lifetime.start.p0i8(i64 4000, i8* nonnull %0) 72 %arraydecay = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 0 73 call void @fill(i32* nonnull %arraydecay, i32 %n) 74 br label %for.body.i 75 76 for.body.i: ; preds = %for.body.i, %entry 77 %indvars.iv.i = phi i64 [ 0, %entry ], [ %indvars.iv.next.i, %for.body.i ] 78 %sum.07.i = phi i32 [ 0, %entry ], [ %add.i, %for.body.i ] 79 %arrayidx.i = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 %indvars.iv.i 80 ; CHECK: mul i64 {{.*}}, 4 81 ; CHECK: sub i64 4000, % 82 ; CHECK-NEXT: icmp ult i64 4000, % 83 ; CHECK-NEXT: icmp ult i64 {{.*}}, 4 84 ; CHECK-NEXT: or i1 85 ; CHECK: trap 86 %1 = load i32, i32* %arrayidx.i, align 4 87 %add.i = add nsw i32 %1, %sum.07.i 88 %indvars.iv.next.i = add nuw nsw i64 %indvars.iv.i, 1 89 %exitcond.i = icmp eq i64 %indvars.iv.next.i, 2000 90 br i1 %exitcond.i, label %accumulate.exit, label %for.body.i 91 92 accumulate.exit: ; preds = %for.body.i 93 call void @llvm.lifetime.end.p0i8(i64 4000, i8* nonnull %0) 94 ret i32 %add.i 95 } 96 97 ; CHECK-LABEL: @sumUnknown 98 define dso_local i32 @sumUnknown(i32 %n) { 99 entry: 100 %foo = alloca [1000 x i32], align 16 101 %0 = bitcast [1000 x i32]* %foo to i8* 102 call void @llvm.lifetime.start.p0i8(i64 4000, i8* nonnull %0) 103 %arraydecay = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 0 104 call void @fill(i32* nonnull %arraydecay, i32 %n) 105 %cmp6.i = icmp eq i32 %n, 0 106 br i1 %cmp6.i, label %accumulate.exit, label %for.body.preheader.i 107 108 for.body.preheader.i: ; preds = %entry 109 %wide.trip.count.i = zext i32 %n to i64 110 br label %for.body.i 111 112 for.body.i: ; preds = %for.body.i, %for.body.preheader.i 113 %indvars.iv.i = phi i64 [ 0, %for.body.preheader.i ], [ %indvars.iv.next.i, %for.body.i ] 114 %sum.07.i = phi i32 [ 0, %for.body.preheader.i ], [ %add.i, %for.body.i ] 115 %arrayidx.i = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 %indvars.iv.i 116 ; CHECK: mul i64 {{.*}}, 4 117 ; CHECK: sub i64 4000, % 118 ; CHECK-NEXT: icmp ult i64 4000, % 119 ; CHECK-NEXT: icmp ult i64 {{.*}}, 4 120 ; CHECK-NEXT: or i1 121 ; CHECK: trap 122 %1 = load i32, i32* %arrayidx.i, align 4 123 %add.i = add nsw i32 %1, %sum.07.i 124 %indvars.iv.next.i = add nuw nsw i64 %indvars.iv.i, 1 125 %exitcond.i = icmp eq i64 %indvars.iv.next.i, %wide.trip.count.i 126 br i1 %exitcond.i, label %accumulate.exit, label %for.body.i 127 128 accumulate.exit: ; preds = %for.body.i, %entry 129 %sum.0.lcssa.i = phi i32 [ 0, %entry ], [ %add.i, %for.body.i ] 130 call void @llvm.lifetime.end.p0i8(i64 4000, i8* nonnull %0) 131 ret i32 %sum.0.lcssa.i 132 } 133 134 ; CHECK-LABEL: @twoDimSize 135 define dso_local i32 @twoDimSize(i32 %n) { 136 entry: 137 %foo = alloca [2 x [2 x i32]], align 16 138 %0 = bitcast [2 x [2 x i32]]* %foo to i8* 139 call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %0) 140 %arraydecay = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %foo, i64 0, i64 0, i64 0 141 call void @fill(i32* nonnull %arraydecay, i32 %n) 142 br label %for.cond1.preheader 143 144 for.cond1.preheader: ; preds = %for.cond.cleanup3, %entry 145 %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for.cond.cleanup3 ] 146 %sum.021 = phi i32 [ 0, %entry ], [ %add, %for.cond.cleanup3 ] 147 br label %for.body4 148 149 for.cond.cleanup: ; preds = %for.cond.cleanup3 150 call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %0) 151 ret i32 %add 152 153 for.cond.cleanup3: ; preds = %for.body4 154 %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1 155 %exitcond25 = icmp eq i64 %indvars.iv.next24, 2 156 br i1 %exitcond25, label %for.cond.cleanup, label %for.cond1.preheader 157 158 for.body4: ; preds = %for.body4, %for.cond1.preheader 159 %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body4 ] 160 %sum.119 = phi i32 [ %sum.021, %for.cond1.preheader ], [ %add, %for.body4 ] 161 %arrayidx7 = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %foo, i64 0, i64 %indvars.iv23, i64 %indvars.iv 162 ; CHECK-NOT: trap 163 %1 = load i32, i32* %arrayidx7, align 4 164 %add = add nsw i32 %1, %sum.119 165 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 166 %exitcond = icmp eq i64 %indvars.iv.next, 2 167 br i1 %exitcond, label %for.cond.cleanup3, label %for.body4 168 } 169 170 ; CHECK-LABEL: @twoDimLarger1 171 define dso_local i32 @twoDimLarger1(i32 %n) { 172 entry: 173 %foo = alloca [2 x [2 x i32]], align 16 174 %0 = bitcast [2 x [2 x i32]]* %foo to i8* 175 call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %0) 176 %arraydecay = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %foo, i64 0, i64 0, i64 0 177 call void @fill(i32* nonnull %arraydecay, i32 %n) 178 br label %for.cond1.preheader 179 180 for.cond1.preheader: ; preds = %for.cond.cleanup3, %entry 181 %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for.cond.cleanup3 ] 182 %sum.021 = phi i32 [ 0, %entry ], [ %add, %for.cond.cleanup3 ] 183 br label %for.body4 184 185 for.cond.cleanup: ; preds = %for.cond.cleanup3 186 call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %0) 187 ret i32 %add 188 189 for.cond.cleanup3: ; preds = %for.body4 190 %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1 191 %exitcond25 = icmp eq i64 %indvars.iv.next24, 3 192 br i1 %exitcond25, label %for.cond.cleanup, label %for.cond1.preheader 193 194 for.body4: ; preds = %for.body4, %for.cond1.preheader 195 %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body4 ] 196 %sum.119 = phi i32 [ %sum.021, %for.cond1.preheader ], [ %add, %for.body4 ] 197 %arrayidx7 = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %foo, i64 0, i64 %indvars.iv23, i64 %indvars.iv 198 ; CHECK: mul i64 {{.*}}, 8 199 ; CHECK: mul i64 {{.*}}, 4 200 ; CHECK: add i64 201 ; CHECK: sub i64 16, % 202 ; CHECK-NEXT: icmp ult i64 16, % 203 ; CHECK-NEXT: icmp ult i64 {{.*}}, 4 204 ; CHECK-NEXT: or i1 205 ; CHECK: trap 206 %1 = load i32, i32* %arrayidx7, align 4 207 %add = add nsw i32 %1, %sum.119 208 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 209 %exitcond = icmp eq i64 %indvars.iv.next, 2 210 br i1 %exitcond, label %for.cond.cleanup3, label %for.body4 211 } 212 213 ; CHECK-LABEL: @twoDimLarger2 214 define dso_local i32 @twoDimLarger2(i32 %n) { 215 entry: 216 %foo = alloca [2 x [2 x i32]], align 16 217 %0 = bitcast [2 x [2 x i32]]* %foo to i8* 218 call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %0) 219 %arraydecay = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %foo, i64 0, i64 0, i64 0 220 call void @fill(i32* nonnull %arraydecay, i32 %n) 221 br label %for.cond1.preheader 222 223 for.cond1.preheader: ; preds = %for.cond.cleanup3, %entry 224 %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for.cond.cleanup3 ] 225 %sum.021 = phi i32 [ 0, %entry ], [ %add, %for.cond.cleanup3 ] 226 br label %for.body4 227 228 for.cond.cleanup: ; preds = %for.cond.cleanup3 229 call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %0) 230 ret i32 %add 231 232 for.cond.cleanup3: ; preds = %for.body4 233 %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1 234 %exitcond25 = icmp eq i64 %indvars.iv.next24, 2 235 br i1 %exitcond25, label %for.cond.cleanup, label %for.cond1.preheader 236 237 for.body4: ; preds = %for.body4, %for.cond1.preheader 238 %indvars.iv = phi i64 [ 0, %for.cond1.preheader ], [ %indvars.iv.next, %for.body4 ] 239 %sum.119 = phi i32 [ %sum.021, %for.cond1.preheader ], [ %add, %for.body4 ] 240 %arrayidx7 = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %foo, i64 0, i64 %indvars.iv23, i64 %indvars.iv 241 ; CHECK: mul i64 {{.*}}, 8 242 ; CHECK: mul i64 {{.*}}, 4 243 ; CHECK: add i64 244 ; CHECK: sub i64 16, % 245 ; CHECK-NEXT: icmp ult i64 {{.*}}, 4 246 ; CHECK-NEXT: or i1 247 ; CHECK: trap 248 %1 = load i32, i32* %arrayidx7, align 4 249 %add = add nsw i32 %1, %sum.119 250 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 251 %exitcond = icmp eq i64 %indvars.iv.next, 3 252 br i1 %exitcond, label %for.cond.cleanup3, label %for.body4 253 } 254 255 ; CHECK-LABEL: @twoDimUnknown 256 define dso_local i32 @twoDimUnknown(i32 %n) { 257 entry: 258 %foo = alloca [2 x [2 x i32]], align 16 259 %0 = bitcast [2 x [2 x i32]]* %foo to i8* 260 call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull %0) 261 %arraydecay = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %foo, i64 0, i64 0, i64 0 262 call void @fill(i32* nonnull %arraydecay, i32 %n) 263 %cmp24 = icmp eq i32 %n, 0 264 br i1 %cmp24, label %for.cond.cleanup, label %for.cond1.preheader.lr.ph 265 266 for.cond1.preheader.lr.ph: ; preds = %entry 267 %wide.trip.count = zext i32 %n to i64 268 %wide.trip.count.le = zext i32 %n to i64 269 br label %for.body4.lr.ph 270 271 for.body4.lr.ph: ; preds = %for.cond1.preheader.lr.ph, %for.cond.cleanup3 272 %indvars.iv28 = phi i64 [ 0, %for.cond1.preheader.lr.ph ], [ %indvars.iv.next29, %for.cond.cleanup3 ] 273 %sum.025 = phi i32 [ 0, %for.cond1.preheader.lr.ph ], [ %add, %for.cond.cleanup3 ] 274 br label %for.body4 275 276 for.cond.cleanup: ; preds = %for.cond.cleanup3, %entry 277 %sum.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.cond.cleanup3 ] 278 call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull %0) 279 ret i32 %sum.0.lcssa 280 281 for.cond.cleanup3: ; preds = %for.body4 282 %indvars.iv.next29 = add nuw nsw i64 %indvars.iv28, 1 283 %exitcond31 = icmp eq i64 %indvars.iv.next29, %wide.trip.count.le 284 br i1 %exitcond31, label %for.cond.cleanup, label %for.body4.lr.ph 285 286 for.body4: ; preds = %for.body4, %for.body4.lr.ph 287 %indvars.iv = phi i64 [ 0, %for.body4.lr.ph ], [ %indvars.iv.next, %for.body4 ] 288 %sum.122 = phi i32 [ %sum.025, %for.body4.lr.ph ], [ %add, %for.body4 ] 289 %arrayidx7 = getelementptr inbounds [2 x [2 x i32]], [2 x [2 x i32]]* %foo, i64 0, i64 %indvars.iv28, i64 %indvars.iv 290 ; CHECK: mul i64 {{.*}}, 8 291 ; CHECK: mul i64 {{.*}}, 4 292 ; CHECK: add i64 293 ; CHECK: sub i64 16, % 294 ; CHECK-NEXT: icmp ult i64 16, % 295 ; CHECK-NEXT: icmp ult i64 {{.*}}, 4 296 ; CHECK-NEXT: or i1 297 ; CHECK: trap 298 %1 = load i32, i32* %arrayidx7, align 4 299 %add = add nsw i32 %1, %sum.122 300 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 301 %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count 302 br i1 %exitcond, label %for.cond.cleanup3, label %for.body4 303 } 304 305 ; CHECK-LABEL: @countDownGood 306 define dso_local i32 @countDownGood(i32 %n) { 307 entry: 308 %foo = alloca [1000 x i32], align 16 309 %0 = bitcast [1000 x i32]* %foo to i8* 310 call void @llvm.lifetime.start.p0i8(i64 4000, i8* nonnull %0) 311 %arraydecay = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 0 312 call void @fill(i32* nonnull %arraydecay, i32 %n) 313 br label %for.body 314 315 for.cond.cleanup: ; preds = %for.body 316 call void @llvm.lifetime.end.p0i8(i64 4000, i8* nonnull %0) 317 ret i32 %add 318 319 for.body: ; preds = %for.body, %entry 320 %indvars.iv = phi i64 [ 999, %entry ], [ %indvars.iv.next, %for.body ] 321 %sum.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] 322 %arrayidx = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 %indvars.iv 323 ; CHECK-NOT: trap 324 %1 = load i32, i32* %arrayidx, align 4 325 %add = add nsw i32 %1, %sum.06 326 %indvars.iv.next = add nsw i64 %indvars.iv, -1 327 %cmp = icmp eq i64 %indvars.iv, 0 328 br i1 %cmp, label %for.cond.cleanup, label %for.body 329 } 330 331 ; CHECK-LABEL: @countDownBad 332 define dso_local i32 @countDownBad(i32 %n) { 333 entry: 334 %foo = alloca [1000 x i32], align 16 335 %0 = bitcast [1000 x i32]* %foo to i8* 336 call void @llvm.lifetime.start.p0i8(i64 4000, i8* nonnull %0) 337 %arraydecay = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 0 338 call void @fill(i32* nonnull %arraydecay, i32 %n) 339 br label %for.body 340 341 for.cond.cleanup: ; preds = %for.body 342 call void @llvm.lifetime.end.p0i8(i64 4000, i8* nonnull %0) 343 ret i32 %add 344 345 for.body: ; preds = %entry, %for.body 346 %indvars.iv = phi i64 [ 999, %entry ], [ %indvars.iv.next, %for.body ] 347 %sum.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] 348 %arrayidx = getelementptr inbounds [1000 x i32], [1000 x i32]* %foo, i64 0, i64 %indvars.iv 349 ; CHECK: mul i64 {{.*}}, 4 350 ; CHECK: sub i64 4000, % 351 ; CHECK-NEXT: icmp ult i64 4000, % 352 ; CHECK: trap 353 %1 = load i32, i32* %arrayidx, align 4 354 %add = add nsw i32 %1, %sum.06 355 %indvars.iv.next = add nsw i64 %indvars.iv, -1 356 %cmp = icmp sgt i64 %indvars.iv, -1 357 br i1 %cmp, label %for.body, label %for.cond.cleanup 358 } 359