; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py ; RUN: opt -passes='print<scalar-evolution>' -disable-output %s 2>&1 | FileCheck %s ; Test case for PR40961. The loop guard limit the max backedge-taken count. define void @test_guard_less_than_16(i32* nocapture %a, i64 %i) { ; CHECK-LABEL: 'test_guard_less_than_16' ; CHECK-NEXT: Classifying expressions for: @test_guard_less_than_16 ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] ; CHECK-NEXT: --> {%i,+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 15 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {((4 * %i) + %a),+,4}<nw><%loop> U: full-set S: full-set Exits: (60 + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {(1 + %i),+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 16 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_less_than_16 ; CHECK-NEXT: Loop %loop: backedge-taken count is (15 + (-1 * %i)) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 15 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (15 + (-1 * %i)) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp3 = icmp ult i64 %i, 16 br i1 %cmp3, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv.next, 16 br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_less_than_16_operands_swapped(i32* nocapture %a, i64 %i) { ; CHECK-LABEL: 'test_guard_less_than_16_operands_swapped' ; CHECK-NEXT: Classifying expressions for: @test_guard_less_than_16_operands_swapped ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] ; CHECK-NEXT: --> {%i,+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 15 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {((4 * %i) + %a),+,4}<nw><%loop> U: full-set S: full-set Exits: (60 + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {(1 + %i),+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 16 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_less_than_16_operands_swapped ; CHECK-NEXT: Loop %loop: backedge-taken count is (15 + (-1 * %i)) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 15 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (15 + (-1 * %i)) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp3 = icmp ugt i64 16, %i br i1 %cmp3, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv.next, 16 br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_less_than_16_branches_flipped(i32* nocapture %a, i64 %i) { ; CHECK-LABEL: 'test_guard_less_than_16_branches_flipped' ; CHECK-NEXT: Classifying expressions for: @test_guard_less_than_16_branches_flipped ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] ; CHECK-NEXT: --> {%i,+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 15 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {((4 * %i) + %a),+,4}<nw><%loop> U: full-set S: full-set Exits: (60 + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {(1 + %i),+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 16 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_less_than_16_branches_flipped ; CHECK-NEXT: Loop %loop: backedge-taken count is (15 + (-1 * %i)) ; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (15 + (-1 * %i)) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp3 = icmp ult i64 %i, 16 br i1 %cmp3, label %exit, label %loop loop: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv.next, 16 br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_uge_16_branches_flipped(i32* nocapture %a, i64 %i) { ; CHECK-LABEL: 'test_guard_uge_16_branches_flipped' ; CHECK-NEXT: Classifying expressions for: @test_guard_uge_16_branches_flipped ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] ; CHECK-NEXT: --> {%i,+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 15 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {((4 * %i) + %a),+,4}<nw><%loop> U: full-set S: full-set Exits: (60 + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {(1 + %i),+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 16 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_uge_16_branches_flipped ; CHECK-NEXT: Loop %loop: backedge-taken count is (15 + (-1 * %i)) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 15 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (15 + (-1 * %i)) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp3 = icmp uge i64 %i, 16 br i1 %cmp3, label %exit, label %loop loop: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv.next, 16 br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_eq_12(i32* nocapture %a, i64 %N) { ; CHECK-LABEL: 'test_guard_eq_12' ; CHECK-NEXT: Classifying expressions for: @test_guard_eq_12 ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,14) S: [1,14) Exits: (1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_eq_12 ; CHECK-NEXT: Loop %loop: backedge-taken count is %N ; CHECK-NEXT: Loop %loop: max backedge-taken count is 12 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is %N ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.1 = icmp eq i64 %N, 12 br i1 %c.1, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv, %N br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_ule_12(i32* nocapture %a, i64 %N) { ; CHECK-LABEL: 'test_guard_ule_12' ; CHECK-NEXT: Classifying expressions for: @test_guard_ule_12 ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,14) S: [1,14) Exits: (1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_ule_12 ; CHECK-NEXT: Loop %loop: backedge-taken count is %N ; CHECK-NEXT: Loop %loop: max backedge-taken count is 12 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is %N ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.1 = icmp ule i64 %N, 12 br i1 %c.1, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv, %N br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_ule_12_step2(i32* nocapture %a, i64 %N) { ; CHECK-LABEL: 'test_guard_ule_12_step2' ; CHECK-NEXT: Classifying expressions for: @test_guard_ule_12_step2 ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,2}<nuw><nsw><%loop> U: [0,13) S: [0,13) Exits: (2 * (%N /u 2))<nuw> LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,8}<nuw><%loop> U: full-set S: full-set Exits: ((8 * (%N /u 2)) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 2 ; CHECK-NEXT: --> {2,+,2}<nuw><nsw><%loop> U: [2,15) S: [2,15) Exits: (2 + (2 * (%N /u 2))<nuw>) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_ule_12_step2 ; CHECK-NEXT: Loop %loop: backedge-taken count is (%N /u 2) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 6 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%N /u 2) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.1 = icmp ule i64 %N, 12 br i1 %c.1, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 2 %exitcond = icmp eq i64 %iv, %N br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_multiple_const_guards_order1(i32* nocapture %a, i64 %i) { ; CHECK-LABEL: 'test_multiple_const_guards_order1' ; CHECK-NEXT: Classifying expressions for: @test_multiple_const_guards_order1 ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,10) S: [0,10) Exits: %i LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,11) S: [1,11) Exits: (1 + %i) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_multiple_const_guards_order1 ; CHECK-NEXT: Loop %loop: backedge-taken count is %i ; CHECK-NEXT: Loop %loop: max backedge-taken count is 9 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is %i ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.1 = icmp ult i64 %i, 16 br i1 %c.1, label %guardbb, label %exit guardbb: %c.2 = icmp ult i64 %i, 10 br i1 %c.2, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv, %i br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_multiple_const_guards_order2(i32* nocapture %a, i64 %i) { ; CHECK-LABEL: 'test_multiple_const_guards_order2' ; CHECK-NEXT: Classifying expressions for: @test_multiple_const_guards_order2 ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,10) S: [0,10) Exits: %i LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,11) S: [1,11) Exits: (1 + %i) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_multiple_const_guards_order2 ; CHECK-NEXT: Loop %loop: backedge-taken count is %i ; CHECK-NEXT: Loop %loop: max backedge-taken count is 9 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is %i ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.1 = icmp ult i64 %i, 10 br i1 %c.1, label %guardbb, label %exit guardbb: %c.2 = icmp ult i64 %i, 16 br i1 %c.2, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv, %i br i1 %exitcond, label %exit, label %loop exit: ret void } ; TODO: Currently we miss getting the tightest max backedge-taken count (11). define void @test_multiple_var_guards_order1(i32* nocapture %a, i64 %i, i64 %N) { ; CHECK-LABEL: 'test_multiple_var_guards_order1' ; CHECK-NEXT: Classifying expressions for: @test_multiple_var_guards_order1 ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-9223372036854775808) S: [0,-9223372036854775808) Exits: %i LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: (1 + %i) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_multiple_var_guards_order1 ; CHECK-NEXT: Loop %loop: backedge-taken count is %i ; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is %i ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.1 = icmp ult i64 %N, 12 br i1 %c.1, label %guardbb, label %exit guardbb: %c.2 = icmp ult i64 %i, %N br i1 %c.2, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv, %i br i1 %exitcond, label %exit, label %loop exit: ret void } ; TODO: Currently we miss getting the tightest max backedge-taken count (11). define void @test_multiple_var_guards_order2(i32* nocapture %a, i64 %i, i64 %N) { ; CHECK-LABEL: 'test_multiple_var_guards_order2' ; CHECK-NEXT: Classifying expressions for: @test_multiple_var_guards_order2 ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-9223372036854775808) S: [0,-9223372036854775808) Exits: %i LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %i) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: (1 + %i) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_multiple_var_guards_order2 ; CHECK-NEXT: Loop %loop: backedge-taken count is %i ; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is %i ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.1 = icmp ult i64 %i, %N br i1 %c.1, label %guardbb, label %exit guardbb: %c.2 = icmp ult i64 %N, 12 br i1 %c.2, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv, %i br i1 %exitcond, label %exit, label %loop exit: ret void } ; The guards here reference each other in a cycle. define void @test_multiple_var_guards_cycle(i32* nocapture %a, i64 %i, i64 %N) { ; CHECK-LABEL: 'test_multiple_var_guards_cycle' ; CHECK-NEXT: Classifying expressions for: @test_multiple_var_guards_cycle ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-9223372036854775808) S: [0,-9223372036854775808) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: ((4 * %N) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: (1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_multiple_var_guards_cycle ; CHECK-NEXT: Loop %loop: backedge-taken count is %N ; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is %N ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.1 = icmp ult i64 %N, %i br i1 %c.1, label %guardbb, label %exit guardbb: %c.2 = icmp ult i64 %i, %N br i1 %c.2, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv, %N br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_ult_ne(i32* nocapture readonly %data, i64 %count) { ; CHECK-LABEL: 'test_guard_ult_ne' ; CHECK-NEXT: Classifying expressions for: @test_guard_ult_ne ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: [0,4) S: [0,4) Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,5) S: [1,5) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_ult_ne ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.ult = icmp ult i64 %count, 5 br i1 %cmp.ult, label %guardbb, label %exit guardbb: %cmp.ne = icmp ne i64 %count, 0 br i1 %cmp.ne, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_ne_ult(i32* nocapture readonly %data, i64 %count) { ; CHECK-LABEL: 'test_guard_ne_ult' ; CHECK-NEXT: Classifying expressions for: @test_guard_ne_ult ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: [0,4) S: [0,4) Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,5) S: [1,5) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_ne_ult ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.ne = icmp ne i64 %count, 0 br i1 %cmp.ne, label %guardbb, label %exit guardbb: %cmp.ult = icmp ult i64 %count, 5 br i1 %cmp.ult, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %guardbb ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_if_and_enter(i32* nocapture readonly %data, i64 %count) { ; CHECK-LABEL: 'test_guard_if_and_enter' ; CHECK-NEXT: Classifying expressions for: @test_guard_if_and_enter ; CHECK-NEXT: %cmp.and = and i1 %cmp.ult, %cmp.ne ; CHECK-NEXT: --> (%cmp.ult umin %cmp.ne) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: [0,4) S: [0,4) Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,5) S: [1,5) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_if_and_enter ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.ult = icmp ult i64 %count, 5 %cmp.ne = icmp ne i64 %count, 0 %cmp.and = and i1 %cmp.ult, %cmp.ne br i1 %cmp.and, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_if_and_skip(i32* nocapture readonly %data, i64 %count) { ; CHECK-LABEL: 'test_guard_if_and_skip' ; CHECK-NEXT: Classifying expressions for: @test_guard_if_and_skip ; CHECK-NEXT: %cmp.and = and i1 %cmp.ult, %cmp.ne ; CHECK-NEXT: --> (%cmp.ult umin %cmp.ne) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_if_and_skip ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.ult = icmp ult i64 %count, 5 %cmp.ne = icmp ne i64 %count, 0 %cmp.and = and i1 %cmp.ult, %cmp.ne br i1 %cmp.and, label %exit, label %loop loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_if_and_and(i32* nocapture readonly %data, i64 %count, i1 %c) { ; CHECK-LABEL: 'test_guard_if_and_and' ; CHECK-NEXT: Classifying expressions for: @test_guard_if_and_and ; CHECK-NEXT: %cmp.and1 = and i1 %c, %cmp.ne ; CHECK-NEXT: --> (%c umin %cmp.ne) U: full-set S: full-set ; CHECK-NEXT: %cmp.and = and i1 %cmp.ult, %cmp.and1 ; CHECK-NEXT: --> (%c umin %cmp.ult umin %cmp.ne) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: [0,4) S: [0,4) Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,5) S: [1,5) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_if_and_and ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.ult = icmp ult i64 %count, 5 %cmp.ne = icmp ne i64 %count, 0 %cmp.and1 = and i1 %c, %cmp.ne %cmp.and = and i1 %cmp.ult, %cmp.and1 br i1 %cmp.and, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_if_and_or(i32* nocapture readonly %data, i64 %count, i1 %c) { ; CHECK-LABEL: 'test_guard_if_and_or' ; CHECK-NEXT: Classifying expressions for: @test_guard_if_and_or ; CHECK-NEXT: %cmp.or = or i1 %c, %cmp.ne ; CHECK-NEXT: --> (%c umax %cmp.ne) U: full-set S: full-set ; CHECK-NEXT: %cmp.and = and i1 %cmp.ult, %cmp.or ; CHECK-NEXT: --> ((%c umax %cmp.ne) umin %cmp.ult) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_if_and_or ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.ult = icmp ult i64 %count, 5 %cmp.ne = icmp ne i64 %count, 0 %cmp.or = or i1 %c, %cmp.ne %cmp.and = and i1 %cmp.ult, %cmp.or br i1 %cmp.and, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_if_or_skip(i32* nocapture readonly %data, i64 %count) { ; CHECK-LABEL: 'test_guard_if_or_skip' ; CHECK-NEXT: Classifying expressions for: @test_guard_if_or_skip ; CHECK-NEXT: %cmp.or = or i1 %cmp.uge, %cmp.eq ; CHECK-NEXT: --> (%cmp.uge umax %cmp.eq) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: [0,4) S: [0,4) Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,5) S: [1,5) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_if_or_skip ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.uge = icmp uge i64 %count, 5 %cmp.eq = icmp eq i64 %count, 0 %cmp.or = or i1 %cmp.uge, %cmp.eq br i1 %cmp.or, label %exit, label %loop loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_if_or_enter(i32* nocapture readonly %data, i64 %count) { ; CHECK-LABEL: 'test_guard_if_or_enter' ; CHECK-NEXT: Classifying expressions for: @test_guard_if_or_enter ; CHECK-NEXT: %cmp.or = or i1 %cmp.uge, %cmp.eq ; CHECK-NEXT: --> (%cmp.uge umax %cmp.eq) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_if_or_enter ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.uge = icmp uge i64 %count, 5 %cmp.eq = icmp eq i64 %count, 0 %cmp.or = or i1 %cmp.uge, %cmp.eq br i1 %cmp.or, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_if_or_or(i32* nocapture readonly %data, i64 %count, i1 %c) { ; CHECK-LABEL: 'test_guard_if_or_or' ; CHECK-NEXT: Classifying expressions for: @test_guard_if_or_or ; CHECK-NEXT: %cmp.or1 = or i1 %c, %cmp.eq ; CHECK-NEXT: --> (%c umax %cmp.eq) U: full-set S: full-set ; CHECK-NEXT: %cmp.or = or i1 %cmp.uge, %cmp.or1 ; CHECK-NEXT: --> (%c umax %cmp.uge umax %cmp.eq) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: [0,4) S: [0,4) Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,5) S: [1,5) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_if_or_or ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.uge = icmp uge i64 %count, 5 %cmp.eq = icmp eq i64 %count, 0 %cmp.or1 = or i1 %c, %cmp.eq %cmp.or = or i1 %cmp.uge, %cmp.or1 br i1 %cmp.or, label %exit, label %loop loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_if_or_and(i32* nocapture readonly %data, i64 %count, i1 %c) { ; CHECK-LABEL: 'test_guard_if_or_and' ; CHECK-NEXT: Classifying expressions for: @test_guard_if_or_and ; CHECK-NEXT: %cmp.and = and i1 %c, %cmp.eq ; CHECK-NEXT: --> (%c umin %cmp.eq) U: full-set S: full-set ; CHECK-NEXT: %cmp.or = or i1 %cmp.uge, %cmp.and ; CHECK-NEXT: --> ((%c umin %cmp.eq) umax %cmp.uge) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: full-set S: full-set Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_if_or_and ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is -1 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.uge = icmp uge i64 %count, 5 %cmp.eq = icmp eq i64 %count, 0 %cmp.and = and i1 %c, %cmp.eq %cmp.or = or i1 %cmp.uge, %cmp.and br i1 %cmp.or, label %exit, label %loop loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } ; Test case for PR47247. Both the guard condition and the assume limit the ; max backedge-taken count. define void @test_guard_and_assume(i32* nocapture readonly %data, i64 %count) { ; CHECK-LABEL: 'test_guard_and_assume' ; CHECK-NEXT: Classifying expressions for: @test_guard_and_assume ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: [0,4) S: [0,4) Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,5) S: [1,5) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_and_assume ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp = icmp ult i64 %count, 5 tail call void @llvm.assume(i1 %cmp) %cmp18.not = icmp eq i64 %count, 0 br i1 %cmp18.not, label %exit, label %loop loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } define void @test_guard_assume_and(i32* nocapture readonly %data, i64 %count) { ; CHECK-LABEL: 'test_guard_assume_and' ; CHECK-NEXT: Classifying expressions for: @test_guard_assume_and ; CHECK-NEXT: %cmp.and = and i1 %cmp.ult, %cmp.ne ; CHECK-NEXT: --> (%cmp.ult umin %cmp.ne) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] ; CHECK-NEXT: --> {0,+,1}<nuw><%loop> U: [0,4) S: [0,4) Exits: (-1 + %count) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %data, i64 %iv ; CHECK-NEXT: --> {%data,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %count) + %data) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,5) S: [1,5) Exits: %count LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_assume_and ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %count) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %count) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %cmp.ult = icmp ult i64 %count, 5 %cmp.ne = icmp ne i64 %count, 0 %cmp.and = and i1 %cmp.ult, %cmp.ne call void @llvm.assume(i1 %cmp.and) br label %loop loop: %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] %idx = getelementptr inbounds i32, i32* %data, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw i64 %iv, 1 %exitcond.not = icmp eq i64 %iv.next, %count br i1 %exitcond.not, label %exit, label %loop exit: ret void } ; Function Attrs: nounwind willreturn declare void @llvm.assume(i1 noundef) define void @guard_pessimizes_analysis_step1(i1 %c, i32 %N) { ; CHECK-LABEL: 'guard_pessimizes_analysis_step1' ; CHECK-NEXT: Classifying expressions for: @guard_pessimizes_analysis_step1 ; CHECK-NEXT: %init = phi i32 [ 2, %entry ], [ 3, %bb1 ] ; CHECK-NEXT: --> %init U: [2,4) S: [2,4) ; CHECK-NEXT: %iv = phi i32 [ %iv.next, %loop ], [ %init, %loop.ph ] ; CHECK-NEXT: --> {%init,+,1}<%loop> U: [2,11) S: [2,11) Exits: 9 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add i32 %iv, 1 ; CHECK-NEXT: --> {(1 + %init)<nuw><nsw>,+,1}<%loop> U: [3,12) S: [3,12) Exits: 10 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @guard_pessimizes_analysis_step1 ; CHECK-NEXT: Loop %loop: backedge-taken count is (9 + (-1 * %init)<nsw>)<nsw> ; CHECK-NEXT: Loop %loop: max backedge-taken count is 7 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (9 + (-1 * %init)<nsw>)<nsw> ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: br i1 %c, label %bb1, label %guard bb1: br label %guard guard: %init = phi i32 [ 2, %entry ], [ 3, %bb1 ] %c.1 = icmp ult i32 %init, %N br i1 %c.1, label %loop.ph, label %exit loop.ph: br label %loop loop: %iv = phi i32 [ %iv.next, %loop ], [ %init, %loop.ph ] %iv.next = add i32 %iv, 1 %exitcond = icmp eq i32 %iv.next, 10 br i1 %exitcond, label %exit, label %loop exit: ret void } define void @guard_pessimizes_analysis_step2(i1 %c, i32 %N) { ; CHECK-LABEL: 'guard_pessimizes_analysis_step2' ; CHECK-NEXT: Classifying expressions for: @guard_pessimizes_analysis_step2 ; CHECK-NEXT: %init = phi i32 [ 2, %entry ], [ 3, %bb1 ] ; CHECK-NEXT: --> %init U: [2,4) S: [2,4) ; CHECK-NEXT: %iv = phi i32 [ %iv.next, %loop ], [ %init, %loop.ph ] ; CHECK-NEXT: --> {%init,+,2}<nuw><nsw><%loop> U: [2,10) S: [2,10) Exits: ((2 * ((8 + (-1 * %init)<nsw>)<nsw> /u 2))<nuw><nsw> + %init) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 2 ; CHECK-NEXT: --> {(2 + %init)<nuw><nsw>,+,2}<nuw><nsw><%loop> U: [4,12) S: [4,12) Exits: (2 + (2 * ((8 + (-1 * %init)<nsw>)<nsw> /u 2))<nuw><nsw> + %init) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @guard_pessimizes_analysis_step2 ; CHECK-NEXT: Loop %loop: backedge-taken count is ((8 + (-1 * %init)<nsw>)<nsw> /u 2) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 3 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((8 + (-1 * %init)<nsw>)<nsw> /u 2) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: br i1 %c, label %bb1, label %guard bb1: br label %guard guard: %init = phi i32 [ 2, %entry ], [ 3, %bb1 ] %c.1 = icmp ult i32 %init, %N br i1 %c.1, label %loop.ph, label %exit loop.ph: br label %loop loop: %iv = phi i32 [ %iv.next, %loop ], [ %init, %loop.ph ] %iv.next = add nuw nsw i32 %iv, 2 %exitcond = icmp eq i32 %iv.next, 10 br i1 %exitcond, label %exit, label %loop exit: ret void } define void @crash(i8* %ptr) { ; CHECK-LABEL: 'crash' ; CHECK-NEXT: Classifying expressions for: @crash ; CHECK-NEXT: %text.addr.5 = phi i8* [ %incdec.ptr112, %while.cond111 ], [ null, %while.body ] ; CHECK-NEXT: --> {null,+,-1}<nw><%while.cond111> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %while.cond111: Computable, %while.body: Variant } ; CHECK-NEXT: %incdec.ptr112 = getelementptr inbounds i8, i8* %text.addr.5, i64 -1 ; CHECK-NEXT: --> {(-1 + null)<nuw><nsw>,+,-1}<nw><%while.cond111> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %while.cond111: Computable, %while.body: Variant } ; CHECK-NEXT: %lastout.2271 = phi i8* [ %incdec.ptr126, %while.body125 ], [ %ptr, %while.end117 ] ; CHECK-NEXT: --> {%ptr,+,1}<nuw><%while.body125> U: full-set S: full-set Exits: {(-2 + (-1 * (ptrtoint i8* %ptr to i64)) + %ptr),+,-1}<nw><%while.cond111> LoopDispositions: { %while.body125: Computable } ; CHECK-NEXT: %incdec.ptr126 = getelementptr inbounds i8, i8* %lastout.2271, i64 1 ; CHECK-NEXT: --> {(1 + %ptr),+,1}<nuw><%while.body125> U: full-set S: full-set Exits: {(-1 + (-1 * (ptrtoint i8* %ptr to i64)) + %ptr),+,-1}<nw><%while.cond111> LoopDispositions: { %while.body125: Computable } ; CHECK-NEXT: Determining loop execution counts for: @crash ; CHECK-NEXT: Loop %while.body125: backedge-taken count is {(-2 + (-1 * (ptrtoint i8* %ptr to i64))),+,-1}<nw><%while.cond111> ; CHECK-NEXT: Loop %while.body125: max backedge-taken count is -2 ; CHECK-NEXT: Loop %while.body125: Predicated backedge-taken count is {(-2 + (-1 * (ptrtoint i8* %ptr to i64))),+,-1}<nw><%while.cond111> ; CHECK-NEXT: Predicates: ; CHECK: Loop %while.body125: Trip multiple is 1 ; CHECK-NEXT: Loop %while.cond111: Unpredictable backedge-taken count. ; CHECK-NEXT: Loop %while.cond111: Unpredictable max backedge-taken count. ; CHECK-NEXT: Loop %while.cond111: Unpredictable predicated backedge-taken count. ; CHECK-NEXT: Loop %while.body: Unpredictable backedge-taken count. ; CHECK-NEXT: Loop %while.body: Unpredictable max backedge-taken count. ; CHECK-NEXT: Loop %while.body: Unpredictable predicated backedge-taken count. ; entry: br label %while.body while.body: br label %while.cond111 while.cond111: %text.addr.5 = phi i8* [ %incdec.ptr112, %while.cond111 ], [ null, %while.body ] %incdec.ptr112 = getelementptr inbounds i8, i8* %text.addr.5, i64 -1 br i1 false, label %while.end117, label %while.cond111 while.end117: %cmp118 = icmp ult i8* %ptr, %incdec.ptr112 br i1 %cmp118, label %while.body125, label %while.cond134.preheader while.cond134.preheader: br label %while.body while.body125: %lastout.2271 = phi i8* [ %incdec.ptr126, %while.body125 ], [ %ptr, %while.end117 ] %incdec.ptr126 = getelementptr inbounds i8, i8* %lastout.2271, i64 1 %exitcond.not = icmp eq i8* %incdec.ptr126, %incdec.ptr112 br i1 %exitcond.not, label %while.end129, label %while.body125 while.end129: ; preds = %while.body125 ret void } define void @test_guard_uge(i32 %blockSize) { ; CHECK-LABEL: 'test_guard_uge' ; CHECK-NEXT: Classifying expressions for: @test_guard_uge ; CHECK-NEXT: %shr = lshr i32 %blockSize, 2 ; CHECK-NEXT: --> (%blockSize /u 4) U: [0,1073741824) S: [0,1073741824) ; CHECK-NEXT: %iv = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ] ; CHECK-NEXT: --> {(%blockSize /u 4),+,-1}<%while.body> U: [-1073741822,1073741824) S: [-1073741822,1073741824) Exits: 1 LoopDispositions: { %while.body: Computable } ; CHECK-NEXT: %dec = add i32 %iv, -1 ; CHECK-NEXT: --> {(-1 + (%blockSize /u 4))<nsw>,+,-1}<%while.body> U: [-1073741823,1073741823) S: [-1073741823,1073741823) Exits: 0 LoopDispositions: { %while.body: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_uge ; CHECK-NEXT: Loop %while.body: backedge-taken count is (-1 + (%blockSize /u 4))<nsw> ; CHECK-NEXT: Loop %while.body: max backedge-taken count is 1073741822 ; CHECK-NEXT: Loop %while.body: Predicated backedge-taken count is (-1 + (%blockSize /u 4))<nsw> ; CHECK-NEXT: Predicates: ; CHECK: Loop %while.body: Trip multiple is 1 ; %shr = lshr i32 %blockSize, 2 %guard = icmp uge i32 %blockSize, 4 br i1 %guard, label %while.body.preheader, label %while.end while.body.preheader: br label %while.body while.body: %iv = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ] %dec = add i32 %iv, -1 %cmp.not = icmp eq i32 %dec, 0 br i1 %cmp.not, label %while.end.loopexit, label %while.body while.end.loopexit: br label %while.end while.end: ret void } define void @test_guard_ugt(i32 %blockSize) { ; CHECK-LABEL: 'test_guard_ugt' ; CHECK-NEXT: Classifying expressions for: @test_guard_ugt ; CHECK-NEXT: %shr = lshr i32 %blockSize, 2 ; CHECK-NEXT: --> (%blockSize /u 4) U: [0,1073741824) S: [0,1073741824) ; CHECK-NEXT: %iv = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ] ; CHECK-NEXT: --> {(%blockSize /u 4),+,-1}<%while.body> U: [-1073741822,1073741824) S: [-1073741822,1073741824) Exits: 1 LoopDispositions: { %while.body: Computable } ; CHECK-NEXT: %dec = add i32 %iv, -1 ; CHECK-NEXT: --> {(-1 + (%blockSize /u 4))<nsw>,+,-1}<%while.body> U: [-1073741823,1073741823) S: [-1073741823,1073741823) Exits: 0 LoopDispositions: { %while.body: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_ugt ; CHECK-NEXT: Loop %while.body: backedge-taken count is (-1 + (%blockSize /u 4))<nsw> ; CHECK-NEXT: Loop %while.body: max backedge-taken count is 1073741822 ; CHECK-NEXT: Loop %while.body: Predicated backedge-taken count is (-1 + (%blockSize /u 4))<nsw> ; CHECK-NEXT: Predicates: ; CHECK: Loop %while.body: Trip multiple is 1 ; %shr = lshr i32 %blockSize, 2 %guard = icmp ugt i32 %blockSize, 3 br i1 %guard, label %while.body.preheader, label %while.end while.body.preheader: br label %while.body while.body: %iv = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ] %dec = add i32 %iv, -1 %cmp.not = icmp eq i32 %dec, 0 br i1 %cmp.not, label %while.end.loopexit, label %while.body while.end.loopexit: br label %while.end while.end: ret void } define void @test_guard_uge_and_ule(i32 %blockSize) { ; CHECK-LABEL: 'test_guard_uge_and_ule' ; CHECK-NEXT: Classifying expressions for: @test_guard_uge_and_ule ; CHECK-NEXT: %shr = lshr i32 %blockSize, 2 ; CHECK-NEXT: --> (%blockSize /u 4) U: [0,1073741824) S: [0,1073741824) ; CHECK-NEXT: %iv = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ] ; CHECK-NEXT: --> {(%blockSize /u 4),+,-1}<%while.body> U: [-255,1073741824) S: [-255,1073741824) Exits: 1 LoopDispositions: { %while.body: Computable } ; CHECK-NEXT: %dec = add i32 %iv, -1 ; CHECK-NEXT: --> {(-1 + (%blockSize /u 4))<nsw>,+,-1}<%while.body> U: [-256,1073741823) S: [-256,1073741823) Exits: 0 LoopDispositions: { %while.body: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_uge_and_ule ; CHECK-NEXT: Loop %while.body: backedge-taken count is (-1 + (%blockSize /u 4))<nsw> ; CHECK-NEXT: Loop %while.body: max backedge-taken count is 255 ; CHECK-NEXT: Loop %while.body: Predicated backedge-taken count is (-1 + (%blockSize /u 4))<nsw> ; CHECK-NEXT: Predicates: ; CHECK: Loop %while.body: Trip multiple is 1 ; %shr = lshr i32 %blockSize, 2 %guard1 = icmp uge i32 %blockSize, 4 br i1 %guard1, label %while.guard, label %while.end while.guard: %guard2 = icmp ule i32 %blockSize, 1024 br i1 %guard2, label %while.body.preheader, label %while.end while.body.preheader: br label %while.body while.body: %iv = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ] %dec = add i32 %iv, -1 %cmp.not = icmp eq i32 %dec, 0 br i1 %cmp.not, label %while.end.loopexit, label %while.body while.end.loopexit: br label %while.end while.end: ret void } define void @test_guard_ugt_and_ult(i32 %blockSize) { ; CHECK-LABEL: 'test_guard_ugt_and_ult' ; CHECK-NEXT: Classifying expressions for: @test_guard_ugt_and_ult ; CHECK-NEXT: %shr = lshr i32 %blockSize, 2 ; CHECK-NEXT: --> (%blockSize /u 4) U: [0,1073741824) S: [0,1073741824) ; CHECK-NEXT: %iv = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ] ; CHECK-NEXT: --> {(%blockSize /u 4),+,-1}<%while.body> U: [-255,1073741824) S: [-255,1073741824) Exits: 1 LoopDispositions: { %while.body: Computable } ; CHECK-NEXT: %dec = add i32 %iv, -1 ; CHECK-NEXT: --> {(-1 + (%blockSize /u 4))<nsw>,+,-1}<%while.body> U: [-256,1073741823) S: [-256,1073741823) Exits: 0 LoopDispositions: { %while.body: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_ugt_and_ult ; CHECK-NEXT: Loop %while.body: backedge-taken count is (-1 + (%blockSize /u 4))<nsw> ; CHECK-NEXT: Loop %while.body: max backedge-taken count is 255 ; CHECK-NEXT: Loop %while.body: Predicated backedge-taken count is (-1 + (%blockSize /u 4))<nsw> ; CHECK-NEXT: Predicates: ; CHECK: Loop %while.body: Trip multiple is 1 ; %shr = lshr i32 %blockSize, 2 %guard1 = icmp ugt i32 %blockSize, 3 br i1 %guard1, label %while.guard, label %while.end while.guard: %guard2 = icmp ult i32 %blockSize, 1025 br i1 %guard2, label %while.body.preheader, label %while.end while.body.preheader: br label %while.body while.body: %iv = phi i32 [ %dec, %while.body ], [ %shr, %while.body.preheader ] %dec = add i32 %iv, -1 %cmp.not = icmp eq i32 %dec, 0 br i1 %cmp.not, label %while.end.loopexit, label %while.body while.end.loopexit: br label %while.end while.end: ret void } define void @test_guard_slt_sgt_1(i32* nocapture %a, i64 %N) { ; CHECK-LABEL: 'test_guard_slt_sgt_1' ; CHECK-NEXT: Classifying expressions for: @test_guard_slt_sgt_1 ; CHECK-NEXT: %and = and i1 %c.0, %c.1 ; CHECK-NEXT: --> (%c.0 umin %c.1) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,11) S: [0,11) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %N) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,12) S: [1,12) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_slt_sgt_1 ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 10 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.0 = icmp slt i64 %N, 12 %c.1 = icmp sgt i64 %N, 0 %and = and i1 %c.0, %c.1 br i1 %and, label %loop, label %exit loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv.next, %N br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_slt_sgt_2(i32* nocapture %a, i64 %i) { ; CHECK-LABEL: 'test_guard_slt_sgt_2' ; CHECK-NEXT: Classifying expressions for: @test_guard_slt_sgt_2 ; CHECK-NEXT: %and = and i1 %c.0, %c.1 ; CHECK-NEXT: --> (%c.0 umin %c.1) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] ; CHECK-NEXT: --> {%i,+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 17 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {((4 * %i) + %a),+,4}<nw><%loop> U: full-set S: full-set Exits: (68 + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {(1 + %i),+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 18 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_slt_sgt_2 ; CHECK-NEXT: Loop %loop: backedge-taken count is (17 + (-1 * %i)) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 12 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (17 + (-1 * %i)) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.0 = icmp slt i64 %i, 16 %c.1 = icmp sgt i64 %i, 4 %and = and i1 %c.0, %c.1 br i1 %and, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv.next, 18 br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_sle_sge_1(i32* nocapture %a, i64 %N) { ; CHECK-LABEL: 'test_guard_sle_sge_1' ; CHECK-NEXT: Classifying expressions for: @test_guard_sle_sge_1 ; CHECK-NEXT: %and = and i1 %c.0, %c.1 ; CHECK-NEXT: --> (%c.0 umin %c.1) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,12) S: [0,12) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {%a,+,4}<nuw><%loop> U: full-set S: full-set Exits: (-4 + (4 * %N) + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,13) S: [1,13) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_sle_sge_1 ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 11 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.0 = icmp sle i64 %N, 12 %c.1 = icmp sge i64 %N, 1 %and = and i1 %c.0, %c.1 br i1 %and, label %loop, label %exit loop: %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv.next, %N br i1 %exitcond, label %exit, label %loop exit: ret void } define void @test_guard_sle_sge_2(i32* nocapture %a, i64 %i) { ; CHECK-LABEL: 'test_guard_sle_sge_2' ; CHECK-NEXT: Classifying expressions for: @test_guard_sle_sge_2 ; CHECK-NEXT: %and = and i1 %c.0, %c.1 ; CHECK-NEXT: --> (%c.0 umin %c.1) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] ; CHECK-NEXT: --> {%i,+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 17 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %idx = getelementptr inbounds i32, i32* %a, i64 %iv ; CHECK-NEXT: --> {((4 * %i) + %a),+,4}<nw><%loop> U: full-set S: full-set Exits: (68 + %a) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i64 %iv, 1 ; CHECK-NEXT: --> {(1 + %i),+,1}<nuw><nsw><%loop> U: full-set S: full-set Exits: 18 LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_guard_sle_sge_2 ; CHECK-NEXT: Loop %loop: backedge-taken count is (17 + (-1 * %i)) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 13 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (17 + (-1 * %i)) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %c.0 = icmp sle i64 %i, 16 %c.1 = icmp sge i64 %i, 4 %and = and i1 %c.0, %c.1 br i1 %and, label %loop, label %exit loop: %iv = phi i64 [ %iv.next, %loop ], [ %i, %entry ] %idx = getelementptr inbounds i32, i32* %a, i64 %iv store i32 1, i32* %idx, align 4 %iv.next = add nuw nsw i64 %iv, 1 %exitcond = icmp eq i64 %iv.next, 18 br i1 %exitcond, label %exit, label %loop exit: ret void } ; The function below uses a single condition to ensure %N > 0 && %N < 8. ; InstCombine transforms such checks with 2 conditions to a single check as in ; the test function. define void @optimized_range_check_unsigned(i16* %pred, i32 %N) { ; CHECK-LABEL: 'optimized_range_check_unsigned' ; CHECK-NEXT: Classifying expressions for: @optimized_range_check_unsigned ; CHECK-NEXT: %N.off = add i32 %N, -1 ; CHECK-NEXT: --> (-1 + %N) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,7) S: [0,7) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %gep = getelementptr inbounds i16, i16* %pred, i32 %iv ; CHECK-NEXT: --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,8) S: [1,8) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @optimized_range_check_unsigned ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 6 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %N.off = add i32 %N, -1 %cmp = icmp ult i32 %N.off, 7 br i1 %cmp, label %loop, label %exit loop: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] %gep = getelementptr inbounds i16, i16* %pred, i32 %iv store i16 0, i16* %gep, align 2 %iv.next = add nuw nsw i32 %iv, 1 %ec = icmp eq i32 %iv.next, %N br i1 %ec, label %exit, label %loop exit: ret void } ; Same as @optimized_range_check_unsigned, but with the icmp operands swapped. define void @optimized_range_check_unsigned_icmp_ops_swapped(i16* %pred, i32 %N) { ; CHECK-LABEL: 'optimized_range_check_unsigned_icmp_ops_swapped' ; CHECK-NEXT: Classifying expressions for: @optimized_range_check_unsigned_icmp_ops_swapped ; CHECK-NEXT: %N.off = add i32 %N, -1 ; CHECK-NEXT: --> (-1 + %N) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,7) S: [0,7) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %gep = getelementptr inbounds i16, i16* %pred, i32 %iv ; CHECK-NEXT: --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,8) S: [1,8) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @optimized_range_check_unsigned_icmp_ops_swapped ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 6 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %N.off = add i32 %N, -1 %cmp = icmp ugt i32 7, %N.off br i1 %cmp, label %loop, label %exit loop: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] %gep = getelementptr inbounds i16, i16* %pred, i32 %iv store i16 0, i16* %gep, align 2 %iv.next = add nuw nsw i32 %iv, 1 %ec = icmp eq i32 %iv.next, %N br i1 %ec, label %exit, label %loop exit: ret void } ; The function below uses a single condition to ensure %N > 2 && %N < 22. ; InstCombine transforms such checks with 2 conditions to a single check as in ; the test function. define void @optimized_range_check_unsigned2(i16* %pred, i32 %N) { ; CHECK-LABEL: 'optimized_range_check_unsigned2' ; CHECK-NEXT: Classifying expressions for: @optimized_range_check_unsigned2 ; CHECK-NEXT: %N.off = add i32 %N, -2 ; CHECK-NEXT: --> (-2 + %N) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,21) S: [0,21) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %gep = getelementptr inbounds i16, i16* %pred, i32 %iv ; CHECK-NEXT: --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,22) S: [1,22) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @optimized_range_check_unsigned2 ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 20 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %N.off = add i32 %N, -2 %cmp = icmp ult i32 %N.off, 20 br i1 %cmp, label %loop, label %exit loop: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] %gep = getelementptr inbounds i16, i16* %pred, i32 %iv store i16 0, i16* %gep, align 2 %iv.next = add nuw nsw i32 %iv, 1 %ec = icmp eq i32 %iv.next, %N br i1 %ec, label %exit, label %loop exit: ret void } ; Same as @optimized_range_check_unsigned, but %N already has a range limited ; to [2,4) beforehand. define void @optimized_range_check_unsigned3(i16* %pred, i1 %c) { ; CHECK-LABEL: 'optimized_range_check_unsigned3' ; CHECK-NEXT: Classifying expressions for: @optimized_range_check_unsigned3 ; CHECK-NEXT: %N = select i1 %c, i32 2, i32 3 ; CHECK-NEXT: --> %N U: [2,4) S: [2,4) ; CHECK-NEXT: %N.off = add i32 %N, -1 ; CHECK-NEXT: --> (-1 + %N)<nsw> U: [1,3) S: [1,3) ; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,3) S: [0,3) Exits: (-1 + %N)<nsw> LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %gep = getelementptr inbounds i16, i16* %pred, i32 %iv ; CHECK-NEXT: --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N)<nsw> to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,4) S: [1,4) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @optimized_range_check_unsigned3 ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N)<nsw> ; CHECK-NEXT: Loop %loop: max backedge-taken count is 2 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N)<nsw> ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %N = select i1 %c, i32 2, i32 3 %N.off = add i32 %N, -1 %cmp = icmp ult i32 %N.off, 7 br i1 %cmp, label %loop, label %exit loop: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] %gep = getelementptr inbounds i16, i16* %pred, i32 %iv store i16 0, i16* %gep, align 2 %iv.next = add nuw nsw i32 %iv, 1 %ec = icmp eq i32 %iv.next, %N br i1 %ec, label %exit, label %loop exit: ret void } ; Similar to @optimized_range_check_unsigned, but the initial compare checks ; against unsigned max (-1), which breaks the range check idiom. define void @not_optimized_range_check_unsigned1(i16* %pred, i32 %N) { ; CHECK-LABEL: 'not_optimized_range_check_unsigned1' ; CHECK-NEXT: Classifying expressions for: @not_optimized_range_check_unsigned1 ; CHECK-NEXT: %N.off = add i32 %N, -1 ; CHECK-NEXT: --> (-1 + %N) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %gep = getelementptr inbounds i16, i16* %pred, i32 %iv ; CHECK-NEXT: --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @not_optimized_range_check_unsigned1 ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N) ; CHECK-NEXT: Loop %loop: max backedge-taken count is -2 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %N.off = add i32 %N, -1 %cmp = icmp ult i32 %N.off, -1 br i1 %cmp, label %loop, label %exit loop: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] %gep = getelementptr inbounds i16, i16* %pred, i32 %iv store i16 0, i16* %gep, align 2 %iv.next = add nuw nsw i32 %iv, 1 %ec = icmp eq i32 %iv.next, %N br i1 %ec, label %exit, label %loop exit: ret void } ; Similar to @optimized_range_check_unsigned, but the initial compare checks ; against 0, which breaks the range check idiom. define void @not_optimized_range_check_unsigned2(i16* %pred, i32 %N) { ; CHECK-LABEL: 'not_optimized_range_check_unsigned2' ; CHECK-NEXT: Classifying expressions for: @not_optimized_range_check_unsigned2 ; CHECK-NEXT: %N.off = add i32 %N, -1 ; CHECK-NEXT: --> (-1 + %N) U: full-set S: full-set ; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: (-1 + %N) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %gep = getelementptr inbounds i16, i16* %pred, i32 %iv ; CHECK-NEXT: --> {%pred,+,2}<nuw><%loop> U: full-set S: full-set Exits: ((2 * (zext i32 (-1 + %N) to i64))<nuw><nsw> + %pred) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw nsw i32 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %N LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @not_optimized_range_check_unsigned2 ; CHECK-NEXT: Loop %loop: backedge-taken count is (-1 + %N) ; CHECK-NEXT: Loop %loop: max backedge-taken count is -2 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (-1 + %N) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; entry: %N.off = add i32 %N, -1 %cmp = icmp ult i32 %N.off, 0 br i1 %cmp, label %loop, label %exit loop: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] %gep = getelementptr inbounds i16, i16* %pred, i32 %iv store i16 0, i16* %gep, align 2 %iv.next = add nuw nsw i32 %iv, 1 %ec = icmp eq i32 %iv.next, %N br i1 %ec, label %exit, label %loop exit: ret void } define i32 @sle_sgt_ult_umax_to_smax(i32 %num) { ; CHECK-LABEL: 'sle_sgt_ult_umax_to_smax' ; CHECK-NEXT: Classifying expressions for: @sle_sgt_ult_umax_to_smax ; CHECK-NEXT: %iv = phi i32 [ 0, %guard.3 ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,25) S: [0,25) Exits: (4 * ((-4 + %num) /u 4))<nuw> LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i32 %iv, 4 ; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,29) S: [4,29) Exits: (4 + (4 * ((-4 + %num) /u 4))<nuw>) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @sle_sgt_ult_umax_to_smax ; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + %num) /u 4) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 6 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + %num) /u 4) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; guard.1: %cmp.1 = icmp sle i32 %num, 0 br i1 %cmp.1, label %exit, label %guard.2 guard.2: %cmp.2 = icmp sgt i32 %num, 28 br i1 %cmp.2, label %exit, label %guard.3 guard.3: %cmp.3 = icmp ult i32 %num, 4 br i1 %cmp.3, label %exit, label %loop loop: %iv = phi i32 [ 0, %guard.3 ], [ %iv.next, %loop ] %iv.next = add nuw i32 %iv, 4 %ec = icmp eq i32 %iv.next, %num br i1 %ec, label %exit, label %loop exit: ret i32 0 } ; Similar to @sle_sgt_ult_umax_to_smax but with different predicate order. define i32 @ult_sle_sgt_umax_to_smax(i32 %num) { ; CHECK-LABEL: 'ult_sle_sgt_umax_to_smax' ; CHECK-NEXT: Classifying expressions for: @ult_sle_sgt_umax_to_smax ; CHECK-NEXT: %iv = phi i32 [ 0, %guard.3 ], [ %iv.next, %loop ] ; CHECK-NEXT: --> {0,+,4}<nuw><%loop> U: [0,-3) S: [-2147483648,2147483645) Exits: (4 * ((-4 + %num) /u 4))<nuw> LoopDispositions: { %loop: Computable } ; CHECK-NEXT: %iv.next = add nuw i32 %iv, 4 ; CHECK-NEXT: --> {4,+,4}<nuw><%loop> U: [4,-3) S: [-2147483648,2147483645) Exits: (4 + (4 * ((-4 + %num) /u 4))<nuw>) LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @ult_sle_sgt_umax_to_smax ; CHECK-NEXT: Loop %loop: backedge-taken count is ((-4 + %num) /u 4) ; CHECK-NEXT: Loop %loop: max backedge-taken count is 1073741823 ; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is ((-4 + %num) /u 4) ; CHECK-NEXT: Predicates: ; CHECK: Loop %loop: Trip multiple is 1 ; guard.1: %cmp.1 = icmp ult i32 %num, 4 br i1 %cmp.1, label %exit, label %guard.2 guard.2: %cmp.2 = icmp sgt i32 %num, 28 br i1 %cmp.2, label %exit, label %guard.3 guard.3: %cmp.3 = icmp sle i32 %num, 0 br i1 %cmp.3, label %exit, label %loop loop: %iv = phi i32 [ 0, %guard.3 ], [ %iv.next, %loop ] %iv.next = add nuw i32 %iv, 4 %ec = icmp eq i32 %iv.next, %num br i1 %ec, label %exit, label %loop exit: ret i32 0 }