1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -basic-aa -loop-predication < %s 2>&1 | FileCheck %s 3; RUN: opt -S -aa-pipeline=basic-aa -passes='require<aa>,require<scalar-evolution>,loop(loop-predication)' < %s 2>&1 | FileCheck %s 4 5declare void @llvm.experimental.guard(i1, ...) 6 7@UNKNOWN = external global i1 8 9define i32 @neg_length_variant(i32* %array, i32* %length, i32 %n) { 10; CHECK-LABEL: @neg_length_variant( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 13; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 14; CHECK: loop.preheader: 15; CHECK-NEXT: br label [[LOOP:%.*]] 16; CHECK: loop: 17; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 18; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 19; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN 20; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] 21; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4 22; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]] 23; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 24; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 25; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 26; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 27; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 28; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 29; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 30; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 31; CHECK: exit.loopexit: 32; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 33; CHECK-NEXT: br label [[EXIT]] 34; CHECK: exit: 35; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 36; CHECK-NEXT: ret i32 [[RESULT]] 37; 38entry: 39 %tmp5 = icmp eq i32 %n, 0 40 br i1 %tmp5, label %exit, label %loop.preheader 41 42loop.preheader: 43 br label %loop 44 45loop: 46 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 47 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 48 %unknown = load volatile i1, i1* @UNKNOWN 49 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ] 50 %len = load i32, i32* %length, align 4 51 %within.bounds = icmp ult i32 %i, %len 52 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 53 54 %i.i64 = zext i32 %i to i64 55 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 56 %array.i = load i32, i32* %array.i.ptr, align 4 57 %loop.acc.next = add i32 %loop.acc, %array.i 58 59 %i.next = add nuw i32 %i, 1 60 %continue = icmp ult i32 %i.next, %n 61 br i1 %continue, label %loop, label %exit 62 63exit: 64 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 65 ret i32 %result 66} 67 68define i32 @invariant_load_guard_limit(i32* %array, i32* %length, i32 %n) { 69; CHECK-LABEL: @invariant_load_guard_limit( 70; CHECK-NEXT: entry: 71; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 72; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 73; CHECK: loop.preheader: 74; CHECK-NEXT: br label [[LOOP:%.*]] 75; CHECK: loop: 76; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 77; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 78; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN 79; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] 80; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0 81; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LEN]] 82; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LEN]] 83; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 84; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 85; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 86; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 87; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 88; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 89; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 90; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 91; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 92; CHECK: exit.loopexit: 93; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 94; CHECK-NEXT: br label [[EXIT]] 95; CHECK: exit: 96; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 97; CHECK-NEXT: ret i32 [[RESULT]] 98; 99entry: 100 %tmp5 = icmp eq i32 %n, 0 101 br i1 %tmp5, label %exit, label %loop.preheader 102 103loop.preheader: 104 br label %loop 105 106loop: 107 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 108 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 109 %unknown = load volatile i1, i1* @UNKNOWN 110 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ] 111 %len = load i32, i32* %length, align 4, !invariant.load !{} 112 %within.bounds = icmp ult i32 %i, %len 113 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 114 115 %i.i64 = zext i32 %i to i64 116 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 117 %array.i = load i32, i32* %array.i.ptr, align 4 118 %loop.acc.next = add i32 %loop.acc, %array.i 119 120 %i.next = add nuw i32 %i, 1 121 %continue = icmp ult i32 %i.next, %n 122 br i1 %continue, label %loop, label %exit 123 124exit: 125 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 126 ret i32 %result 127} 128 129; Case where we have an invariant load, but it's not loading from a loop 130; invariant location. 131define i32 @neg_varying_invariant_load_op(i32* %array, i32* %lengths, i32 %n) { 132; CHECK-LABEL: @neg_varying_invariant_load_op( 133; CHECK-NEXT: entry: 134; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 135; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 136; CHECK: loop.preheader: 137; CHECK-NEXT: br label [[LOOP:%.*]] 138; CHECK: loop: 139; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 140; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 141; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN 142; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] 143; CHECK-NEXT: [[LENGTH_ADDR:%.*]] = getelementptr i32, i32* [[LENGTHS:%.*]], i32 [[I]] 144; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LENGTH_ADDR]], align 4, !invariant.load !0 145; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LEN]] 146; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 147; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 148; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 149; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 150; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 151; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 152; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 153; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 154; CHECK: exit.loopexit: 155; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 156; CHECK-NEXT: br label [[EXIT]] 157; CHECK: exit: 158; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 159; CHECK-NEXT: ret i32 [[RESULT]] 160; 161entry: 162 %tmp5 = icmp eq i32 %n, 0 163 br i1 %tmp5, label %exit, label %loop.preheader 164 165loop.preheader: 166 br label %loop 167 168loop: 169 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 170 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 171 %unknown = load volatile i1, i1* @UNKNOWN 172 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ] 173 174 %length.addr = getelementptr i32, i32* %lengths, i32 %i 175 %len = load i32, i32* %length.addr, align 4, !invariant.load !{} 176 %within.bounds = icmp ult i32 %i, %len 177 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 178 179 %i.i64 = zext i32 %i to i64 180 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 181 %array.i = load i32, i32* %array.i.ptr, align 4 182 %loop.acc.next = add i32 %loop.acc, %array.i 183 184 %i.next = add nuw i32 %i, 1 185 %continue = icmp ult i32 %i.next, %n 186 br i1 %continue, label %loop, label %exit 187 188exit: 189 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 190 ret i32 %result 191} 192 193; This is a case where moving the load which provides the limit for the latch 194; would be invalid, so we can't preform the tempting transform. Loading the 195; latch limit may fault since we could always fail the guard. 196define i32 @neg_invariant_load_latch_limit(i32* %array, i32* %length, i32 %n) { 197; CHECK-LABEL: @neg_invariant_load_latch_limit( 198; CHECK-NEXT: entry: 199; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 200; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 201; CHECK: loop.preheader: 202; CHECK-NEXT: br label [[LOOP:%.*]] 203; CHECK: loop: 204; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 205; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 206; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN 207; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] 208; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[N]] 209; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 210; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 211; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 212; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 213; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 214; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 215; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0 216; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[LEN]] 217; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 218; CHECK: exit.loopexit: 219; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 220; CHECK-NEXT: br label [[EXIT]] 221; CHECK: exit: 222; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 223; CHECK-NEXT: ret i32 [[RESULT]] 224; 225entry: 226 %tmp5 = icmp eq i32 %n, 0 227 br i1 %tmp5, label %exit, label %loop.preheader 228 229loop.preheader: 230 br label %loop 231 232loop: 233 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 234 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 235 %unknown = load volatile i1, i1* @UNKNOWN 236 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ] 237 %within.bounds = icmp ult i32 %i, %n 238 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 239 240 %i.i64 = zext i32 %i to i64 241 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 242 %array.i = load i32, i32* %array.i.ptr, align 4 243 %loop.acc.next = add i32 %loop.acc, %array.i 244 245 %i.next = add nuw i32 %i, 1 246 %len = load i32, i32* %length, align 4, !invariant.load !{} 247 %continue = icmp ult i32 %i.next, %len 248 br i1 %continue, label %loop, label %exit 249 250exit: 251 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 252 ret i32 %result 253} 254 255define i32 @invariant_load_latch_limit(i32* %array, 256; CHECK-LABEL: @invariant_load_latch_limit( 257; CHECK-NEXT: entry: 258; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 259; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 260; CHECK: loop.preheader: 261; CHECK-NEXT: br label [[LOOP:%.*]] 262; CHECK: loop: 263; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 264; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 265; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN 266; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] 267; CHECK-NEXT: [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[N]] 268; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[WITHIN_BOUNDS]], i32 9) [ "deopt"() ] 269; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 270; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 271; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 272; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 273; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 274; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* [[LENGTH:%.*]], align 4, !invariant.load !0 275; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[LEN]] 276; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 277; CHECK: exit.loopexit: 278; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 279; CHECK-NEXT: br label [[EXIT]] 280; CHECK: exit: 281; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 282; CHECK-NEXT: ret i32 [[RESULT]] 283; 284 i32* dereferenceable(4) %length, 285 i32 %n) { 286entry: 287 %tmp5 = icmp eq i32 %n, 0 288 br i1 %tmp5, label %exit, label %loop.preheader 289 290loop.preheader: 291 br label %loop 292 293loop: 294 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 295 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 296 %unknown = load volatile i1, i1* @UNKNOWN 297 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ] 298 %within.bounds = icmp ult i32 %i, %n 299 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 300 301 %i.i64 = zext i32 %i to i64 302 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 303 %array.i = load i32, i32* %array.i.ptr, align 4 304 %loop.acc.next = add i32 %loop.acc, %array.i 305 306 %i.next = add nuw i32 %i, 1 307 %len = load i32, i32* %length, align 4, !invariant.load !{} 308 %continue = icmp ult i32 %i.next, %len 309 br i1 %continue, label %loop, label %exit 310 311exit: 312 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 313 ret i32 %result 314} 315 316 317 318@Length = external constant i32 319 320define i32 @constant_memory(i32* %array, i32 %n) { 321; CHECK-LABEL: @constant_memory( 322; CHECK-NEXT: entry: 323; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 324; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 325; CHECK: loop.preheader: 326; CHECK-NEXT: br label [[LOOP:%.*]] 327; CHECK: loop: 328; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 329; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 330; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN 331; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] 332; CHECK-NEXT: [[LEN:%.*]] = load i32, i32* @Length, align 4 333; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], [[LEN]] 334; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 0, [[LEN]] 335; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[TMP1]], [[TMP0]] 336; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP2]], i32 9) [ "deopt"() ] 337; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 338; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 339; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 340; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 341; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 342; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 343; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 344; CHECK: exit.loopexit: 345; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 346; CHECK-NEXT: br label [[EXIT]] 347; CHECK: exit: 348; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 349; CHECK-NEXT: ret i32 [[RESULT]] 350; 351entry: 352 %tmp5 = icmp eq i32 %n, 0 353 br i1 %tmp5, label %exit, label %loop.preheader 354 355loop.preheader: 356 br label %loop 357 358loop: 359 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 360 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 361 %unknown = load volatile i1, i1* @UNKNOWN 362 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ] 363 %len = load i32, i32* @Length, align 4 364 %within.bounds = icmp ult i32 %i, %len 365 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 366 367 %i.i64 = zext i32 %i to i64 368 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 369 %array.i = load i32, i32* %array.i.ptr, align 4 370 %loop.acc.next = add i32 %loop.acc, %array.i 371 372 %i.next = add nuw i32 %i, 1 373 %continue = icmp ult i32 %i.next, %n 374 br i1 %continue, label %loop, label %exit 375 376exit: 377 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 378 ret i32 %result 379} 380 381define i32 @constant_length(i32* %array, i32 %n) { 382; CHECK-LABEL: @constant_length( 383; CHECK-NEXT: entry: 384; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[N:%.*]], 0 385; CHECK-NEXT: br i1 [[TMP5]], label [[EXIT:%.*]], label [[LOOP_PREHEADER:%.*]] 386; CHECK: loop.preheader: 387; CHECK-NEXT: [[TMP0:%.*]] = icmp ule i32 [[N]], 20 388; CHECK-NEXT: [[TMP1:%.*]] = and i1 true, [[TMP0]] 389; CHECK-NEXT: br label [[LOOP:%.*]] 390; CHECK: loop: 391; CHECK-NEXT: [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 392; CHECK-NEXT: [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ] 393; CHECK-NEXT: [[UNKNOWN:%.*]] = load volatile i1, i1* @UNKNOWN 394; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[UNKNOWN]]) [ "deopt"() ] 395; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[TMP1]], i32 9) [ "deopt"() ] 396; CHECK-NEXT: [[I_I64:%.*]] = zext i32 [[I]] to i64 397; CHECK-NEXT: [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]] 398; CHECK-NEXT: [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4 399; CHECK-NEXT: [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]] 400; CHECK-NEXT: [[I_NEXT]] = add nuw i32 [[I]], 1 401; CHECK-NEXT: [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]] 402; CHECK-NEXT: br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]] 403; CHECK: exit.loopexit: 404; CHECK-NEXT: [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[LOOP]] ] 405; CHECK-NEXT: br label [[EXIT]] 406; CHECK: exit: 407; CHECK-NEXT: [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ] 408; CHECK-NEXT: ret i32 [[RESULT]] 409; 410entry: 411 %tmp5 = icmp eq i32 %n, 0 412 br i1 %tmp5, label %exit, label %loop.preheader 413 414loop.preheader: 415 br label %loop 416 417loop: 418 %loop.acc = phi i32 [ %loop.acc.next, %loop ], [ 0, %loop.preheader ] 419 %i = phi i32 [ %i.next, %loop ], [ 0, %loop.preheader ] 420 %unknown = load volatile i1, i1* @UNKNOWN 421 call void (i1, ...) @llvm.experimental.guard(i1 %unknown) [ "deopt"() ] 422 %within.bounds = icmp ult i32 %i, 20 423 call void (i1, ...) @llvm.experimental.guard(i1 %within.bounds, i32 9) [ "deopt"() ] 424 425 %i.i64 = zext i32 %i to i64 426 %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64 427 %array.i = load i32, i32* %array.i.ptr, align 4 428 %loop.acc.next = add i32 %loop.acc, %array.i 429 430 %i.next = add nuw i32 %i, 1 431 %continue = icmp ult i32 %i.next, %n 432 br i1 %continue, label %loop, label %exit 433 434exit: 435 %result = phi i32 [ 0, %entry ], [ %loop.acc.next, %loop ] 436 ret i32 %result 437} 438 439 440