10200626fSPhilip Reames; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
20200626fSPhilip Reames; RUN: opt < %s -indvars -indvars-predicate-loops=1 -S | FileCheck %s
30200626fSPhilip Reames
40200626fSPhilip Reamesdeclare void @prevent_merging()
50200626fSPhilip Reames
60200626fSPhilip Reames; Base case
70200626fSPhilip Reamesdefine i32 @test1(i32* %array, i32 %length, i32 %n) {
80200626fSPhilip Reames; CHECK-LABEL: @test1(
90200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
10b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
11b46c085dSRoman Lebedev; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
12*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
13*c8b675eaSNikita Popov; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]])
14*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
150200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
160200626fSPhilip Reames; CHECK:       loop:
170200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
180200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
19*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0:![0-9]+]]
200200626fSPhilip Reames; CHECK:       deopt:
210200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
220200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
230200626fSPhilip Reames; CHECK:       guarded:
240200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
250200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
260200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
270200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
280200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
290200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
300200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
310200626fSPhilip Reames; CHECK:       exit:
320200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
330200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
340200626fSPhilip Reames;
350200626fSPhilip Reamesloop.preheader:                                   ; preds = %entry
360200626fSPhilip Reames  br label %loop
370200626fSPhilip Reames
380200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
390200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
400200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
410200626fSPhilip Reames  %within.bounds = icmp ult i32 %i, %length
420200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
430200626fSPhilip Reames
440200626fSPhilip Reamesdeopt:                                            ; preds = %loop
450200626fSPhilip Reames  call void @prevent_merging()
460200626fSPhilip Reames  ret i32 -1
470200626fSPhilip Reames
480200626fSPhilip Reamesguarded:                                          ; preds = %loop
490200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
500200626fSPhilip Reames  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
510200626fSPhilip Reames  %array.i = load i32, i32* %array.i.ptr, align 4
520200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc, %array.i
530200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
540200626fSPhilip Reames  %continue = icmp ult i32 %i.next, %n
550200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
560200626fSPhilip Reames
570200626fSPhilip Reamesexit:                                             ; preds = %guarded, %entry
580200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ]
590200626fSPhilip Reames  ret i32 %result
600200626fSPhilip Reames}
610200626fSPhilip Reames
620200626fSPhilip Reames; Has side effect which must be reflected
630200626fSPhilip Reamesdefine i32 @neg_store(i32* %array, i32 %length, i32 %n) {
640200626fSPhilip Reames; CHECK-LABEL: @neg_store(
650200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
660200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
670200626fSPhilip Reames; CHECK:       loop:
680200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
690200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
700200626fSPhilip Reames; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
71*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
720200626fSPhilip Reames; CHECK:       deopt:
730200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
740200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
750200626fSPhilip Reames; CHECK:       guarded:
760200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
770200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
780200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
790200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
80b46c085dSRoman Lebedev; CHECK-NEXT:    store i32 0, i32* [[ARRAY_I_PTR]], align 4
810200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
820200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]]
830200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
840200626fSPhilip Reames; CHECK:       exit:
850200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
860200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
870200626fSPhilip Reames;
880200626fSPhilip Reamesloop.preheader:                                   ; preds = %entry
890200626fSPhilip Reames  br label %loop
900200626fSPhilip Reames
910200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
920200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
930200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
940200626fSPhilip Reames  %within.bounds = icmp ult i32 %i, %length
950200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
960200626fSPhilip Reames
970200626fSPhilip Reamesdeopt:                                            ; preds = %loop
980200626fSPhilip Reames  call void @prevent_merging()
990200626fSPhilip Reames  ret i32 -1
1000200626fSPhilip Reames
1010200626fSPhilip Reamesguarded:                                          ; preds = %loop
1020200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
1030200626fSPhilip Reames  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1040200626fSPhilip Reames  %array.i = load i32, i32* %array.i.ptr, align 4
1050200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc, %array.i
1060200626fSPhilip Reames  store i32 0, i32* %array.i.ptr
1070200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
1080200626fSPhilip Reames  %continue = icmp ult i32 %i.next, %n
1090200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
1100200626fSPhilip Reames
1110200626fSPhilip Reamesexit:                                             ; preds = %guarded, %entry
1120200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ]
1130200626fSPhilip Reames  ret i32 %result
1140200626fSPhilip Reames}
1150200626fSPhilip Reames
1160200626fSPhilip Reamesdeclare void @maythrow()
1170200626fSPhilip Reames
1180200626fSPhilip Reames; May exit through implicit exception edge
1190200626fSPhilip Reamesdefine i32 @neg_implicit_exit(i32* %array, i32 %length, i32 %n) {
1200200626fSPhilip Reames; CHECK-LABEL: @neg_implicit_exit(
1210200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
1220200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
1230200626fSPhilip Reames; CHECK:       loop:
1240200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1250200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
1260200626fSPhilip Reames; CHECK-NEXT:    call void @maythrow()
1270200626fSPhilip Reames; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
128*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1290200626fSPhilip Reames; CHECK:       deopt:
1300200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
1310200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
1320200626fSPhilip Reames; CHECK:       guarded:
1330200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1340200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1350200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1360200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1370200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1380200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]]
1390200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1400200626fSPhilip Reames; CHECK:       exit:
1410200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
1420200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
1430200626fSPhilip Reames;
1440200626fSPhilip Reamesloop.preheader:                                   ; preds = %entry
1450200626fSPhilip Reames  br label %loop
1460200626fSPhilip Reames
1470200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
1480200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
1490200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
1500200626fSPhilip Reames  call void @maythrow()
1510200626fSPhilip Reames  %within.bounds = icmp ult i32 %i, %length
1520200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
1530200626fSPhilip Reames
1540200626fSPhilip Reamesdeopt:                                            ; preds = %loop
1550200626fSPhilip Reames  call void @prevent_merging()
1560200626fSPhilip Reames  ret i32 -1
1570200626fSPhilip Reames
1580200626fSPhilip Reamesguarded:                                          ; preds = %loop
1590200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
1600200626fSPhilip Reames  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
1610200626fSPhilip Reames  %array.i = load i32, i32* %array.i.ptr, align 4
1620200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc, %array.i
1630200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
1640200626fSPhilip Reames  %continue = icmp ult i32 %i.next, %n
1650200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
1660200626fSPhilip Reames
1670200626fSPhilip Reamesexit:                                             ; preds = %guarded, %entry
1680200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ]
1690200626fSPhilip Reames  ret i32 %result
1700200626fSPhilip Reames}
1710200626fSPhilip Reames
1720200626fSPhilip Reames
1730200626fSPhilip Reames
1747f7dac71SZarko Todorovski; Base case, but in LFTR form (just for basic correctness checking)
1750200626fSPhilip Reamesdefine i32 @test2(i32* %array, i32 %length, i32 %n) {
1760200626fSPhilip Reames; CHECK-LABEL: @test2(
1770200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
1780200626fSPhilip Reames; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[N:%.*]], -1
179*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
180*c8b675eaSNikita Popov; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]])
181*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
1820200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
1830200626fSPhilip Reames; CHECK:       loop:
1840200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
1850200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
186*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
1870200626fSPhilip Reames; CHECK:       deopt:
1880200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
1890200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
1900200626fSPhilip Reames; CHECK:       guarded:
1910200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
1920200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
1930200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
1940200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
1950200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
1960200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ne i32 [[I_NEXT]], [[N]]
1970200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
1980200626fSPhilip Reames; CHECK:       exit:
1990200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
2000200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
2010200626fSPhilip Reames;
2020200626fSPhilip Reamesloop.preheader:                                   ; preds = %entry
2030200626fSPhilip Reames  br label %loop
2040200626fSPhilip Reames
2050200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
2060200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
2070200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
2080200626fSPhilip Reames  %within.bounds = icmp ne i32 %i, %length
2090200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
2100200626fSPhilip Reames
2110200626fSPhilip Reamesdeopt:                                            ; preds = %loop
2120200626fSPhilip Reames  call void @prevent_merging()
2130200626fSPhilip Reames  ret i32 -1
2140200626fSPhilip Reames
2150200626fSPhilip Reamesguarded:                                          ; preds = %loop
2160200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
2170200626fSPhilip Reames  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
2180200626fSPhilip Reames  %array.i = load i32, i32* %array.i.ptr, align 4
2190200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc, %array.i
2200200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
2210200626fSPhilip Reames  %continue = icmp ne i32 %i.next, %n
2220200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
2230200626fSPhilip Reames
2240200626fSPhilip Reamesexit:                                             ; preds = %guarded, %entry
2250200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ]
2260200626fSPhilip Reames  ret i32 %result
2270200626fSPhilip Reames}
2280200626fSPhilip Reames
2290200626fSPhilip Reames; br (and rcheck1, rcheck2)
2300200626fSPhilip Reamesdefine i32 @two_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32 %n) {
2310200626fSPhilip Reames; CHECK-LABEL: @two_range_checks(
2320200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
233b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_2:%.*]], i32 [[LENGTH_1:%.*]])
234b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
235b46c085dSRoman Lebedev; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
236*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
237*c8b675eaSNikita Popov; CHECK-NEXT:    [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN]])
238*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[UMIN]], [[UMIN1]]
2390200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
2400200626fSPhilip Reames; CHECK:       loop:
2410200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
2420200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
243*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
2440200626fSPhilip Reames; CHECK:       deopt:
2450200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
2460200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
2470200626fSPhilip Reames; CHECK:       guarded:
2480200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
2490200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
2500200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
2510200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
2520200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
2530200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
2540200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
2550200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
2560200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
2570200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
2580200626fSPhilip Reames; CHECK:       exit:
2590200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
2600200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
2610200626fSPhilip Reames;
2620200626fSPhilip Reamesloop.preheader:                                   ; preds = %entry
2630200626fSPhilip Reames  br label %loop
2640200626fSPhilip Reames
2650200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
2660200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
2670200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
2680200626fSPhilip Reames  %within.bounds.1 = icmp ult i32 %i, %length.1
2690200626fSPhilip Reames  %within.bounds.2 = icmp ult i32 %i, %length.2
2700200626fSPhilip Reames  %within.bounds = and i1 %within.bounds.1, %within.bounds.2
2710200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
2720200626fSPhilip Reames
2730200626fSPhilip Reamesdeopt:                                            ; preds = %loop
2740200626fSPhilip Reames  call void @prevent_merging()
2750200626fSPhilip Reames  ret i32 -1
2760200626fSPhilip Reames
2770200626fSPhilip Reamesguarded:                                          ; preds = %loop
2780200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
2790200626fSPhilip Reames  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
2800200626fSPhilip Reames  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
2810200626fSPhilip Reames  %loop.acc.1 = add i32 %loop.acc, %array.1.i
2820200626fSPhilip Reames  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
2830200626fSPhilip Reames  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
2840200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc.1, %array.2.i
2850200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
2860200626fSPhilip Reames  %continue = icmp ult i32 %i.next, %n
2870200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
2880200626fSPhilip Reames
2890200626fSPhilip Reamesexit:                                             ; preds = %guarded, %entry
2900200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ]
2910200626fSPhilip Reames  ret i32 %result
2920200626fSPhilip Reames}
2930200626fSPhilip Reames
2940200626fSPhilip Reamesdefine i32 @three_range_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32* %array.3, i32 %length.3, i32 %n) {
2950200626fSPhilip Reames; CHECK-LABEL: @three_range_checks(
2960200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
297b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[LENGTH_3:%.*]], i32 [[LENGTH_2:%.*]])
298b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[LENGTH_1:%.*]])
299b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
300b46c085dSRoman Lebedev; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
301*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
302*c8b675eaSNikita Popov; CHECK-NEXT:    [[UMIN2:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[UMIN1]])
303*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[UMIN1]], [[UMIN2]]
3040200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
3050200626fSPhilip Reames; CHECK:       loop:
3060200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
3070200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
308*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[TMP2]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
3090200626fSPhilip Reames; CHECK:       deopt:
3100200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
3110200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
3120200626fSPhilip Reames; CHECK:       guarded:
3130200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
3140200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
3150200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
3160200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
3170200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_2_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_2:%.*]], i64 [[I_I64]]
3180200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_2_I:%.*]] = load i32, i32* [[ARRAY_2_I_PTR]], align 4
3190200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_2:%.*]] = add i32 [[LOOP_ACC_1]], [[ARRAY_2_I]]
3200200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
3210200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
3220200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_2]], [[ARRAY_3_I]]
3230200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
3240200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
3250200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
3260200626fSPhilip Reames; CHECK:       exit:
3270200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
3280200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
3290200626fSPhilip Reames;
3300200626fSPhilip Reamesloop.preheader:                                   ; preds = %entry
3310200626fSPhilip Reames  br label %loop
3320200626fSPhilip Reames
3330200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
3340200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
3350200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
3360200626fSPhilip Reames  %within.bounds.1 = icmp ult i32 %i, %length.1
3370200626fSPhilip Reames  %within.bounds.2 = icmp ult i32 %i, %length.2
3380200626fSPhilip Reames  %within.bounds.3 = icmp ult i32 %i, %length.3
3390200626fSPhilip Reames  %within.bounds.1.and.2 = and i1 %within.bounds.1, %within.bounds.2
3400200626fSPhilip Reames  %within.bounds = and i1 %within.bounds.1.and.2, %within.bounds.3
3410200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
3420200626fSPhilip Reames
3430200626fSPhilip Reamesdeopt:                                            ; preds = %loop
3440200626fSPhilip Reames  call void @prevent_merging()
3450200626fSPhilip Reames  ret i32 -1
3460200626fSPhilip Reames
3470200626fSPhilip Reamesguarded:                                          ; preds = %loop
3480200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
3490200626fSPhilip Reames  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
3500200626fSPhilip Reames  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
3510200626fSPhilip Reames  %loop.acc.1 = add i32 %loop.acc, %array.1.i
3520200626fSPhilip Reames  %array.2.i.ptr = getelementptr inbounds i32, i32* %array.2, i64 %i.i64
3530200626fSPhilip Reames  %array.2.i = load i32, i32* %array.2.i.ptr, align 4
3540200626fSPhilip Reames  %loop.acc.2 = add i32 %loop.acc.1, %array.2.i
3550200626fSPhilip Reames  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
3560200626fSPhilip Reames  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
3570200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc.2, %array.3.i
3580200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
3590200626fSPhilip Reames  %continue = icmp ult i32 %i.next, %n
3600200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
3610200626fSPhilip Reames
3620200626fSPhilip Reamesexit:                                             ; preds = %guarded, %entry
3630200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ]
3640200626fSPhilip Reames  ret i32 %result
3650200626fSPhilip Reames}
3660200626fSPhilip Reames
3670200626fSPhilip Reames; Analogous to the above, but with two distinct branches (on different conditions)
3680200626fSPhilip Reamesdefine i32 @distinct_checks(i32* %array.1, i32 %length.1, i32* %array.2, i32 %length.2, i32* %array.3, i32 %length.3, i32 %n) {
3690200626fSPhilip Reames; CHECK-LABEL: @distinct_checks(
3700200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
371b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
372b46c085dSRoman Lebedev; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
373*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
374*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP2:%.*]] = freeze i32 [[LENGTH_2:%.*]]
375*c8b675eaSNikita Popov; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[TMP2]])
376*c8b675eaSNikita Popov; CHECK-NEXT:    [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[LENGTH_1:%.*]])
377*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[LENGTH_1]], [[UMIN1]]
378*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne i32 [[LENGTH_2]], [[UMIN1]]
3790200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
3800200626fSPhilip Reames; CHECK:       loop:
3810200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
3820200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ]
383*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[TMP3]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
3840200626fSPhilip Reames; CHECK:       deopt:
3850200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
3860200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
3870200626fSPhilip Reames; CHECK:       guarded:
3880200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
3890200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
3900200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
3910200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
392*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
3930200626fSPhilip Reames; CHECK:       deopt2:
3940200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
3950200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
3960200626fSPhilip Reames; CHECK:       guarded1:
3970200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
3980200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
3990200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]]
4000200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
4010200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
4020200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
4030200626fSPhilip Reames; CHECK:       exit:
4040200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ]
4050200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
4060200626fSPhilip Reames;
4070200626fSPhilip Reamesloop.preheader:                                   ; preds = %entry
4080200626fSPhilip Reames  br label %loop
4090200626fSPhilip Reames
4100200626fSPhilip Reamesloop:                                             ; preds = %guarded4, %loop.preheader
4110200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded1 ], [ 0, %loop.preheader ]
4120200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded1 ], [ 0, %loop.preheader ]
4130200626fSPhilip Reames  %within.bounds.1 = icmp ult i32 %i, %length.1
4140200626fSPhilip Reames  br i1 %within.bounds.1, label %guarded, label %deopt, !prof !0
4150200626fSPhilip Reames
4160200626fSPhilip Reamesdeopt:                                            ; preds = %loop
4170200626fSPhilip Reames  call void @prevent_merging()
4180200626fSPhilip Reames  ret i32 -1
4190200626fSPhilip Reames
4200200626fSPhilip Reamesguarded:                                          ; preds = %loop
4210200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
4220200626fSPhilip Reames  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
4230200626fSPhilip Reames  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
4240200626fSPhilip Reames  %loop.acc.1 = add i32 %loop.acc, %array.1.i
4250200626fSPhilip Reames  %within.bounds.2 = icmp ult i32 %i, %length.2
4260200626fSPhilip Reames  br i1 %within.bounds.2, label %guarded1, label %deopt2, !prof !0
4270200626fSPhilip Reames
4280200626fSPhilip Reamesdeopt2:                                           ; preds = %guarded
4290200626fSPhilip Reames  call void @prevent_merging()
4300200626fSPhilip Reames  ret i32 -1
4310200626fSPhilip Reames
4320200626fSPhilip Reamesguarded1:                                         ; preds = %guarded1
4330200626fSPhilip Reames  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
4340200626fSPhilip Reames  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
4350200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc.1, %array.3.i
4360200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
4370200626fSPhilip Reames  %continue = icmp ult i32 %i.next, %n
4380200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
4390200626fSPhilip Reames
4400200626fSPhilip Reamesexit:
4410200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded1 ]
4420200626fSPhilip Reames  ret i32 %result
4430200626fSPhilip Reames}
4440200626fSPhilip Reames
4450200626fSPhilip Reamesdefine i32 @duplicate_checks(i32* %array.1, i32* %array.2, i32* %array.3, i32 %length, i32 %n) {
4460200626fSPhilip Reames; CHECK-LABEL: @duplicate_checks(
4470200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
448b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMAX:%.*]] = call i32 @llvm.umax.i32(i32 [[N:%.*]], i32 1)
449b46c085dSRoman Lebedev; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[UMAX]], -1
450*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP1:%.*]] = freeze i32 [[TMP0]]
451*c8b675eaSNikita Popov; CHECK-NEXT:    [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[LENGTH:%.*]])
452*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[LENGTH]], [[UMIN]]
4530200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
4540200626fSPhilip Reames; CHECK:       loop:
4550200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED1:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
4560200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED1]] ], [ 0, [[LOOP_PREHEADER]] ]
457*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[TMP2]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
4580200626fSPhilip Reames; CHECK:       deopt:
4590200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
4600200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
4610200626fSPhilip Reames; CHECK:       guarded:
4620200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
4630200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_1_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_1:%.*]], i64 [[I_I64]]
4640200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_1_I:%.*]] = load i32, i32* [[ARRAY_1_I_PTR]], align 4
4650200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_1:%.*]] = add i32 [[LOOP_ACC]], [[ARRAY_1_I]]
466*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 true, label [[GUARDED1]], label [[DEOPT2:%.*]], !prof [[PROF0]]
4670200626fSPhilip Reames; CHECK:       deopt2:
4680200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
4690200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
4700200626fSPhilip Reames; CHECK:       guarded1:
4710200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_3_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY_3:%.*]], i64 [[I_I64]]
4720200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_3_I:%.*]] = load i32, i32* [[ARRAY_3_I_PTR]], align 4
4730200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC_1]], [[ARRAY_3_I]]
4740200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
4750200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N]]
4760200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
4770200626fSPhilip Reames; CHECK:       exit:
4780200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED1]] ]
4790200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
4800200626fSPhilip Reames;
4810200626fSPhilip Reamesloop.preheader:                                   ; preds = %entry
4820200626fSPhilip Reames  br label %loop
4830200626fSPhilip Reames
4840200626fSPhilip Reamesloop:                                             ; preds = %guarded4, %loop.preheader
4850200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded1 ], [ 0, %loop.preheader ]
4860200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded1 ], [ 0, %loop.preheader ]
4870200626fSPhilip Reames  %within.bounds.1 = icmp ult i32 %i, %length
4880200626fSPhilip Reames  br i1 %within.bounds.1, label %guarded, label %deopt, !prof !0
4890200626fSPhilip Reames
4900200626fSPhilip Reamesdeopt:                                            ; preds = %loop
4910200626fSPhilip Reames  call void @prevent_merging()
4920200626fSPhilip Reames  ret i32 -1
4930200626fSPhilip Reames
4940200626fSPhilip Reamesguarded:                                          ; preds = %loop
4950200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
4960200626fSPhilip Reames  %array.1.i.ptr = getelementptr inbounds i32, i32* %array.1, i64 %i.i64
4970200626fSPhilip Reames  %array.1.i = load i32, i32* %array.1.i.ptr, align 4
4980200626fSPhilip Reames  %loop.acc.1 = add i32 %loop.acc, %array.1.i
4990200626fSPhilip Reames  %within.bounds.2 = icmp ult i32 %i, %length
5000200626fSPhilip Reames  br i1 %within.bounds.2, label %guarded1, label %deopt2, !prof !0
5010200626fSPhilip Reames
5020200626fSPhilip Reamesdeopt2:                                           ; preds = %guarded
5030200626fSPhilip Reames  call void @prevent_merging()
5040200626fSPhilip Reames  ret i32 -1
5050200626fSPhilip Reames
5060200626fSPhilip Reamesguarded1:                                         ; preds = %guarded1
5070200626fSPhilip Reames  %array.3.i.ptr = getelementptr inbounds i32, i32* %array.3, i64 %i.i64
5080200626fSPhilip Reames  %array.3.i = load i32, i32* %array.3.i.ptr, align 4
5090200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc.1, %array.3.i
5100200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
5110200626fSPhilip Reames  %continue = icmp ult i32 %i.next, %n
5120200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
5130200626fSPhilip Reames
5140200626fSPhilip Reamesexit:
5150200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded1 ]
5160200626fSPhilip Reames  ret i32 %result
5170200626fSPhilip Reames}
5180200626fSPhilip Reames
5190200626fSPhilip Reames
5200200626fSPhilip Reamesdefine i32 @provably_taken(i32* %array, i32* %length.ptr) {
5210200626fSPhilip Reames; CHECK-LABEL: @provably_taken(
5220200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
5230200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
5240200626fSPhilip Reames; CHECK:       loop:
5250200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
5260200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
527*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 false, label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
5280200626fSPhilip Reames; CHECK:       deopt:
5290200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
5300200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
5310200626fSPhilip Reames; CHECK:       guarded:
5320200626fSPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
5330200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
5340200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
5350200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
5360200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I]], 1
5370200626fSPhilip Reames; CHECK-NEXT:    br i1 true, label [[LOOP]], label [[EXIT:%.*]]
5380200626fSPhilip Reames; CHECK:       exit:
5390200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
5400200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
5410200626fSPhilip Reames;
5420200626fSPhilip Reamesloop.preheader:
5430200626fSPhilip Reames  %length = load i32, i32* %length.ptr, !range !2
5440200626fSPhilip Reames  br label %loop
5450200626fSPhilip Reames
5460200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
5470200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
5480200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 0, %loop.preheader ]
5490200626fSPhilip Reames  %within.bounds = icmp ult i32 %i, %length
5500200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
5510200626fSPhilip Reames
5520200626fSPhilip Reamesdeopt:                                            ; preds = %loop
5530200626fSPhilip Reames  call void @prevent_merging()
5540200626fSPhilip Reames  ret i32 -1
5550200626fSPhilip Reames
5560200626fSPhilip Reamesguarded:                                          ; preds = %loop
5570200626fSPhilip Reames  %i.i64 = zext i32 %i to i64
5580200626fSPhilip Reames  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
5590200626fSPhilip Reames  %array.i = load i32, i32* %array.i.ptr, align 4
5600200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc, %array.i
5610200626fSPhilip Reames  %i.next = add nuw i32 %i, 1
5620200626fSPhilip Reames  %continue = icmp slt i32 %i.next, 200
5630200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
5640200626fSPhilip Reames
5650200626fSPhilip Reamesexit:                                             ; preds = %guarded
5660200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ]
5670200626fSPhilip Reames  ret i32 %result
5680200626fSPhilip Reames}
5690200626fSPhilip Reames
5700200626fSPhilip Reames; Non-latch exits can still be predicated
5710200626fSPhilip Reamesdefine i32 @unconditional_latch(i32* %a, i32 %length) {
5720200626fSPhilip Reames; CHECK-LABEL: @unconditional_latch(
5730200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
5740200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
5750200626fSPhilip Reames; CHECK:       loop:
576*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 false, label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
5770200626fSPhilip Reames; CHECK:       deopt:
5780200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
5790200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
5800200626fSPhilip Reames; CHECK:       guarded:
5810200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP]]
5820200626fSPhilip Reames;
5830200626fSPhilip Reamesloop.preheader:
5840200626fSPhilip Reames  br label %loop
5850200626fSPhilip Reames
5860200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
5870200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 400, %loop.preheader ]
5880200626fSPhilip Reames  %within.bounds = icmp ult i32 %i, %length
5890200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
5900200626fSPhilip Reames
5910200626fSPhilip Reamesdeopt:                                            ; preds = %loop
5920200626fSPhilip Reames  call void @prevent_merging()
5930200626fSPhilip Reames  ret i32 -1
5940200626fSPhilip Reames
5950200626fSPhilip Reamesguarded:                                          ; preds = %loop
5960200626fSPhilip Reames  %i.next = add i32 %i, 1
5970200626fSPhilip Reames  br label %loop
5980200626fSPhilip Reames}
5990200626fSPhilip Reames
6000200626fSPhilip Reames; Side effect in loop must run proper number of times
6010200626fSPhilip Reamesdefine i32 @unconditional_latch_with_side_effect(i32* %a, i32 %length) {
6020200626fSPhilip Reames; CHECK-LABEL: @unconditional_latch_with_side_effect(
6030200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
6040200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
6050200626fSPhilip Reames; CHECK:       loop:
6060200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED:%.*]] ], [ 400, [[LOOP_PREHEADER:%.*]] ]
6070200626fSPhilip Reames; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
608*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
6090200626fSPhilip Reames; CHECK:       deopt:
6100200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
6110200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
6120200626fSPhilip Reames; CHECK:       guarded:
613b46c085dSRoman Lebedev; CHECK-NEXT:    store volatile i32 0, i32* [[A:%.*]], align 4
6140200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
6150200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP]]
6160200626fSPhilip Reames;
6170200626fSPhilip Reamesloop.preheader:
6180200626fSPhilip Reames  br label %loop
6190200626fSPhilip Reames
6200200626fSPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
6210200626fSPhilip Reames  %i = phi i32 [ %i.next, %guarded ], [ 400, %loop.preheader ]
6220200626fSPhilip Reames  %within.bounds = icmp ult i32 %i, %length
6230200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
6240200626fSPhilip Reames
6250200626fSPhilip Reamesdeopt:                                            ; preds = %loop
6260200626fSPhilip Reames  call void @prevent_merging()
6270200626fSPhilip Reames  ret i32 -1
6280200626fSPhilip Reames
6290200626fSPhilip Reamesguarded:                                          ; preds = %loop
6300200626fSPhilip Reames  store volatile i32 0, i32* %a
6310200626fSPhilip Reames  %i.next = add i32 %i, 1
6320200626fSPhilip Reames  br label %loop
6330200626fSPhilip Reames}
6340200626fSPhilip Reames
6350200626fSPhilip Reames; Demonstrate that this approach works with IVs of different steps, and types
6360200626fSPhilip Reames; This version uses a manually lftred exit condition to work around an issue described
6370200626fSPhilip Reames; in detail on next test.
6380200626fSPhilip Reamesdefine i32 @different_ivs(i32* %array, i32 %length, i32 %n) {
6390200626fSPhilip Reames; CHECK-LABEL: @different_ivs(
6400200626fSPhilip Reames; CHECK-NEXT:  loop.preheader:
6410200626fSPhilip Reames; CHECK-NEXT:    [[N64:%.*]] = zext i32 [[N:%.*]] to i64
642b46c085dSRoman Lebedev; CHECK-NEXT:    [[UMAX:%.*]] = call i64 @llvm.umax.i64(i64 [[N64]], i64 1)
643b46c085dSRoman Lebedev; CHECK-NEXT:    [[TMP0:%.*]] = add nsw i64 [[UMAX]], -1
644*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP1:%.*]] = freeze i64 [[TMP0]]
645*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP2:%.*]] = zext i32 [[LENGTH:%.*]] to i64
646*c8b675eaSNikita Popov; CHECK-NEXT:    [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP1]], i64 [[TMP2]])
647*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP3:%.*]] = zext i32 [[LENGTH]] to i64
648*c8b675eaSNikita Popov; CHECK-NEXT:    [[TMP4:%.*]] = icmp ne i64 [[TMP3]], [[UMIN]]
6490200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
6500200626fSPhilip Reames; CHECK:       loop:
6510200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
6520200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
653*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[TMP4]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
6540200626fSPhilip Reames; CHECK:       deopt:
6550200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
6560200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
6570200626fSPhilip Reames; CHECK:       guarded:
6580200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I]]
6590200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
6600200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
6610200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i64 [[I]], 1
6620200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i64 [[I_NEXT]], [[N64]]
6630200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
6640200626fSPhilip Reames; CHECK:       exit:
6650200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
6660200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
6670200626fSPhilip Reames;
6680200626fSPhilip Reamesloop.preheader:
6690200626fSPhilip Reames  %j.start = sub nuw nsw i32 %length, 1
6700200626fSPhilip Reames  %n64 = zext i32 %n to i64
6710200626fSPhilip Reames  br label %loop
6720200626fSPhilip Reames
6730200626fSPhilip Reamesloop:
6740200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
6750200626fSPhilip Reames  %i = phi i64 [ %i.next, %guarded ], [ 0, %loop.preheader ]
6760200626fSPhilip Reames  %j = phi i32 [ %j.next, %guarded ], [ %j.start, %loop.preheader ]
6770200626fSPhilip Reames  %within.bounds = icmp ne i32 %j, -1
6780200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
6790200626fSPhilip Reames
6800200626fSPhilip Reamesdeopt:
6810200626fSPhilip Reames  call void @prevent_merging()
6820200626fSPhilip Reames  ret i32 -1
6830200626fSPhilip Reames
6840200626fSPhilip Reamesguarded:
6850200626fSPhilip Reames  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i
6860200626fSPhilip Reames  %array.i = load i32, i32* %array.i.ptr, align 4
6870200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc, %array.i
6880200626fSPhilip Reames  %i.next = add nuw i64 %i, 1
6890200626fSPhilip Reames  %j.next = sub nuw i32 %j, 1
6900200626fSPhilip Reames  %continue = icmp ult i64 %i.next, %n64
6910200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
6920200626fSPhilip Reames
6930200626fSPhilip Reamesexit:
6940200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ]
6950200626fSPhilip Reames  ret i32 %result
6960200626fSPhilip Reames}
6970200626fSPhilip Reames
6980200626fSPhilip Reames; TODO: We're failing to compute an exit count for the bounds check.
6990200626fSPhilip Reames; From some quick analysis, it looks like we don't handle -1 step
7000200626fSPhilip Reames; in howManyLessThans.  Should be a simple fix.
7010200626fSPhilip Reamesdefine i32 @different_ivs2(i32* %array, i32 %length, i32 %n) {
7020200626fSPhilip Reames; CHECK-LABEL: @different_ivs2(
7030200626fSPhilip Reames; CHECK-NEXT:  entry:
7040200626fSPhilip Reames; CHECK-NEXT:    [[POS_LENGTH:%.*]] = icmp sgt i32 [[LENGTH:%.*]], 0
7050200626fSPhilip Reames; CHECK-NEXT:    br i1 [[POS_LENGTH]], label [[LOOP_PREHEADER:%.*]], label [[EXIT:%.*]]
7060200626fSPhilip Reames; CHECK:       loop.preheader:
7070200626fSPhilip Reames; CHECK-NEXT:    [[J_START:%.*]] = sub nuw nsw i32 [[LENGTH]], 1
7080200626fSPhilip Reames; CHECK-NEXT:    [[N64:%.*]] = zext i32 [[N:%.*]] to i64
7090200626fSPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
7100200626fSPhilip Reames; CHECK:       loop:
7110200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED:%.*]] ], [ 0, [[LOOP_PREHEADER]] ]
7120200626fSPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[GUARDED]] ], [ 0, [[LOOP_PREHEADER]] ]
7130200626fSPhilip Reames; CHECK-NEXT:    [[J:%.*]] = phi i32 [ [[J_NEXT:%.*]], [[GUARDED]] ], [ [[J_START]], [[LOOP_PREHEADER]] ]
7140200626fSPhilip Reames; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[J]], [[LENGTH]]
715*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED]], label [[DEOPT:%.*]], !prof [[PROF0]]
7160200626fSPhilip Reames; CHECK:       deopt:
7170200626fSPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
7180200626fSPhilip Reames; CHECK-NEXT:    ret i32 -1
7190200626fSPhilip Reames; CHECK:       guarded:
7200200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I]]
7210200626fSPhilip Reames; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
7220200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
7230200626fSPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i64 [[I]], 1
7240200626fSPhilip Reames; CHECK-NEXT:    [[J_NEXT]] = sub nuw i32 [[J]], 1
7250200626fSPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i64 [[I_NEXT]], [[N64]]
7260200626fSPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
7270200626fSPhilip Reames; CHECK:       exit.loopexit:
7280200626fSPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT_LCSSA:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED]] ]
7290200626fSPhilip Reames; CHECK-NEXT:    br label [[EXIT]]
7300200626fSPhilip Reames; CHECK:       exit:
7310200626fSPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[LOOP_ACC_NEXT_LCSSA]], [[EXIT_LOOPEXIT]] ]
7320200626fSPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
7330200626fSPhilip Reames;
7340200626fSPhilip Reamesentry:
7350200626fSPhilip Reames  %pos_length = icmp sgt i32 %length, 0
7360200626fSPhilip Reames  br i1 %pos_length, label %loop.preheader, label %exit
7370200626fSPhilip Reames
7380200626fSPhilip Reamesloop.preheader:
7390200626fSPhilip Reames  %j.start = sub nuw nsw i32 %length, 1
7400200626fSPhilip Reames  %n64 = zext i32 %n to i64
7410200626fSPhilip Reames  br label %loop
7420200626fSPhilip Reames
7430200626fSPhilip Reamesloop:
7440200626fSPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded ], [ 0, %loop.preheader ]
7450200626fSPhilip Reames  %i = phi i64 [ %i.next, %guarded ], [ 0, %loop.preheader ]
7460200626fSPhilip Reames  %j = phi i32 [ %j.next, %guarded ], [ %j.start, %loop.preheader ]
7470200626fSPhilip Reames  %within.bounds = icmp ult i32 %j, %length
7480200626fSPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
7490200626fSPhilip Reames
7500200626fSPhilip Reamesdeopt:
7510200626fSPhilip Reames  call void @prevent_merging()
7520200626fSPhilip Reames  ret i32 -1
7530200626fSPhilip Reames
7540200626fSPhilip Reamesguarded:
7550200626fSPhilip Reames  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i
7560200626fSPhilip Reames  %array.i = load i32, i32* %array.i.ptr, align 4
7570200626fSPhilip Reames  %loop.acc.next = add i32 %loop.acc, %array.i
7580200626fSPhilip Reames  %i.next = add nuw i64 %i, 1
7590200626fSPhilip Reames  %j.next = sub nuw i32 %j, 1
7600200626fSPhilip Reames  %continue = icmp ult i64 %i.next, %n64
7610200626fSPhilip Reames  br i1 %continue, label %loop, label %exit
7620200626fSPhilip Reames
7630200626fSPhilip Reamesexit:
7640200626fSPhilip Reames  %result = phi i32 [ %loop.acc.next, %guarded ], [0, %entry]
7650200626fSPhilip Reames  ret i32 %result
7660200626fSPhilip Reames}
7670200626fSPhilip Reames
7682b161cd0SPhilip Reames; If we have a dominating exit (exit1) which can't be itself rewritten, we
7692b161cd0SPhilip Reames; can't rewrite a later exit (exit2).  Doing so would cause the loop to exit
7702b161cd0SPhilip Reames; from the exit2 when it should have exited from exit1.
7718cbcd2f4SPhilip Reamesdefine i32 @neg_dominating_exit(i32* %array, i32 %length, i32 %length2, i32 %n) {
7722b161cd0SPhilip Reames; CHECK-LABEL: @neg_dominating_exit(
7732b161cd0SPhilip Reames; CHECK-NEXT:  loop.preheader:
7742b161cd0SPhilip Reames; CHECK-NEXT:    br label [[LOOP:%.*]]
7752b161cd0SPhilip Reames; CHECK:       loop:
7762b161cd0SPhilip Reames; CHECK-NEXT:    [[LOOP_ACC:%.*]] = phi i32 [ [[LOOP_ACC_NEXT:%.*]], [[GUARDED2:%.*]] ], [ 0, [[LOOP_PREHEADER:%.*]] ]
7772b161cd0SPhilip Reames; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[I_NEXT:%.*]], [[GUARDED2]] ], [ 0, [[LOOP_PREHEADER]] ]
778d4346584SPhilip Reames; CHECK-NEXT:    [[WITHIN_BOUNDS:%.*]] = icmp ult i32 [[I]], [[LENGTH:%.*]]
779*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS]], label [[GUARDED:%.*]], label [[DEOPT:%.*]], !prof [[PROF0]]
7802b161cd0SPhilip Reames; CHECK:       deopt:
7812b161cd0SPhilip Reames; CHECK-NEXT:    [[RESULT:%.*]] = phi i32 [ [[LOOP_ACC]], [[LOOP]] ]
7822b161cd0SPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
7832b161cd0SPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT]]
7842b161cd0SPhilip Reames; CHECK:       guarded:
7858cbcd2f4SPhilip Reames; CHECK-NEXT:    [[WITHIN_BOUNDS2:%.*]] = icmp ult i32 [[I]], [[LENGTH2:%.*]]
786*c8b675eaSNikita Popov; CHECK-NEXT:    br i1 [[WITHIN_BOUNDS2]], label [[GUARDED2]], label [[DEOPT2:%.*]], !prof [[PROF0]]
7872b161cd0SPhilip Reames; CHECK:       deopt2:
7882b161cd0SPhilip Reames; CHECK-NEXT:    call void @prevent_merging()
7892b161cd0SPhilip Reames; CHECK-NEXT:    ret i32 -1
7902b161cd0SPhilip Reames; CHECK:       guarded2:
7912b161cd0SPhilip Reames; CHECK-NEXT:    [[I_I64:%.*]] = zext i32 [[I]] to i64
7922b161cd0SPhilip Reames; CHECK-NEXT:    [[ARRAY_I_PTR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[I_I64]]
7932b161cd0SPhilip Reames; CHECK-NEXT:    [[ARRAY_I:%.*]] = load i32, i32* [[ARRAY_I_PTR]], align 4
7942b161cd0SPhilip Reames; CHECK-NEXT:    [[LOOP_ACC_NEXT]] = add i32 [[LOOP_ACC]], [[ARRAY_I]]
7952b161cd0SPhilip Reames; CHECK-NEXT:    [[I_NEXT]] = add nuw i32 [[I]], 1
796d4346584SPhilip Reames; CHECK-NEXT:    [[CONTINUE:%.*]] = icmp ult i32 [[I_NEXT]], [[N:%.*]]
7972b161cd0SPhilip Reames; CHECK-NEXT:    br i1 [[CONTINUE]], label [[LOOP]], label [[EXIT:%.*]]
7982b161cd0SPhilip Reames; CHECK:       exit:
7992b161cd0SPhilip Reames; CHECK-NEXT:    [[RESULT2:%.*]] = phi i32 [ [[LOOP_ACC_NEXT]], [[GUARDED2]] ]
8002b161cd0SPhilip Reames; CHECK-NEXT:    ret i32 [[RESULT2]]
8012b161cd0SPhilip Reames;
8022b161cd0SPhilip Reamesloop.preheader:                                   ; preds = %entry
8032b161cd0SPhilip Reames  br label %loop
8042b161cd0SPhilip Reames
8052b161cd0SPhilip Reamesloop:                                             ; preds = %guarded, %loop.preheader
8062b161cd0SPhilip Reames  %loop.acc = phi i32 [ %loop.acc.next, %guarded2 ], [ 0, %loop.preheader ]
8072b161cd0SPhilip Reames  %i = phi i32 [ %i.next, %guarded2 ], [ 0, %loop.preheader ]
8082b161cd0SPhilip Reames  %within.bounds = icmp ult i32 %i, %length
8092b161cd0SPhilip Reames  br i1 %within.bounds, label %guarded, label %deopt, !prof !0
8102b161cd0SPhilip Reames
8112b161cd0SPhilip Reamesdeopt:                                            ; preds = %loop
8122b161cd0SPhilip Reames  %result = phi i32 [ %loop.acc, %loop ]
8132b161cd0SPhilip Reames  call void @prevent_merging()
8142b161cd0SPhilip Reames  ret i32 %result
8152b161cd0SPhilip Reames
8162b161cd0SPhilip Reamesguarded:                                          ; preds = %loop
8178cbcd2f4SPhilip Reames  %within.bounds2 = icmp ult i32 %i, %length2
8182b161cd0SPhilip Reames  br i1 %within.bounds2, label %guarded2, label %deopt2, !prof !0
8192b161cd0SPhilip Reames
8202b161cd0SPhilip Reamesdeopt2:                                            ; preds = %loop
8212b161cd0SPhilip Reames  call void @prevent_merging()
8222b161cd0SPhilip Reames  ret i32 -1
8232b161cd0SPhilip Reames
8242b161cd0SPhilip Reamesguarded2:                                          ; preds = %loop
8252b161cd0SPhilip Reames  %i.i64 = zext i32 %i to i64
8262b161cd0SPhilip Reames  %array.i.ptr = getelementptr inbounds i32, i32* %array, i64 %i.i64
8272b161cd0SPhilip Reames  %array.i = load i32, i32* %array.i.ptr, align 4
8282b161cd0SPhilip Reames  %loop.acc.next = add i32 %loop.acc, %array.i
8292b161cd0SPhilip Reames  %i.next = add nuw i32 %i, 1
8302b161cd0SPhilip Reames  %continue = icmp ult i32 %i.next, %n
8312b161cd0SPhilip Reames  br i1 %continue, label %loop, label %exit
8322b161cd0SPhilip Reames
8332b161cd0SPhilip Reamesexit:                                             ; preds = %guarded, %entry
8342b161cd0SPhilip Reames  %result2 = phi i32 [ %loop.acc.next, %guarded2 ]
8352b161cd0SPhilip Reames  ret i32 %result2
8362b161cd0SPhilip Reames}
8370200626fSPhilip Reames
8380200626fSPhilip Reames
8390200626fSPhilip Reamesdeclare i32 @llvm.experimental.deoptimize.i32(...)
8400200626fSPhilip Reames
8410200626fSPhilip Reames!0 = !{!"branch_weights", i32 1048576, i32 1}
8420200626fSPhilip Reames!1 = !{i32 1, i32 -2147483648}
8430200626fSPhilip Reames!2 = !{i32 0, i32 50}
844