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