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