forked from OSchip/llvm-project
[SCEV] Recognize binary `and` as bit-wise `umin`
https://alive2.llvm.org/ce/z/aKAr94 We could transparently handle wider bitwidths, by effectively casting iN to <N x i1> and performing the `umin` bit/element -wise, the expression will be rather large, so let's not do that for now.
This commit is contained in:
parent
e7e0834f07
commit
503541fa93
|
@ -7180,6 +7180,9 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
|
|||
MulCount);
|
||||
}
|
||||
}
|
||||
// Binary `and` is a bit-wise `umin`.
|
||||
if (BO->LHS->getType()->isIntegerTy(1))
|
||||
return getUMinExpr(getSCEV(BO->LHS), getSCEV(BO->RHS));
|
||||
break;
|
||||
|
||||
case Instruction::Or:
|
||||
|
|
|
@ -11,7 +11,7 @@ define void @test_and(i16 %in) {
|
|||
; CHECK-NEXT: %_tmp6.i = add nsw i16 %_tmp25.i, 1
|
||||
; CHECK-NEXT: --> {(1 + %in),+,1}<nsw><%bb1.i> U: full-set S: full-set Exits: 2 LoopDispositions: { %bb1.i: Computable, %bb2: Variant }
|
||||
; CHECK-NEXT: %or.cond = and i1 %_tmp10.i, %exitcond.i
|
||||
; CHECK-NEXT: --> %or.cond U: full-set S: full-set Exits: true LoopDispositions: { %bb1.i: Variant, %bb2: Variant }
|
||||
; CHECK-NEXT: --> (%_tmp10.i umin %exitcond.i) U: full-set S: full-set Exits: true LoopDispositions: { %bb1.i: Variant, %bb2: Variant }
|
||||
; CHECK-NEXT: Determining loop execution counts for: @test_and
|
||||
; CHECK-NEXT: Loop %bb1.i: backedge-taken count is (1 + (-1 * %in))
|
||||
; CHECK-NEXT: Loop %bb1.i: max backedge-taken count is -1
|
||||
|
|
|
@ -47,7 +47,7 @@ define i1 @binary_and.i1(i1 %x, i1 %y) {
|
|||
; CHECK-LABEL: 'binary_and.i1'
|
||||
; CHECK-NEXT: Classifying expressions for: @binary_and.i1
|
||||
; CHECK-NEXT: %r = and i1 %x, %y
|
||||
; CHECK-NEXT: --> %r U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (%x umin %y) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @binary_and.i1
|
||||
;
|
||||
%r = and i1 %x, %y
|
||||
|
@ -69,11 +69,11 @@ define i1 @binary_and.4ops.i1(i1 %x, i1 %y, i1 %z, i1 %a) {
|
|||
; CHECK-LABEL: 'binary_and.4ops.i1'
|
||||
; CHECK-NEXT: Classifying expressions for: @binary_and.4ops.i1
|
||||
; CHECK-NEXT: %t0 = and i1 %x, %y
|
||||
; CHECK-NEXT: --> %t0 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (%x umin %y) U: full-set S: full-set
|
||||
; CHECK-NEXT: %t1 = and i1 %z, %a
|
||||
; CHECK-NEXT: --> %t1 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (%z umin %a) U: full-set S: full-set
|
||||
; CHECK-NEXT: %r = and i1 %t0, %t1
|
||||
; CHECK-NEXT: --> %r U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (%x umin %y umin %z umin %a) U: full-set S: full-set
|
||||
; CHECK-NEXT: Determining loop execution counts for: @binary_and.4ops.i1
|
||||
;
|
||||
%t0 = and i1 %x, %y
|
||||
|
|
|
@ -486,7 +486,7 @@ 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.and U: full-set S: full-set
|
||||
; 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
|
||||
|
@ -522,7 +522,7 @@ 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.and U: full-set S: full-set
|
||||
; 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
|
||||
|
@ -558,9 +558,9 @@ define void @test_guard_if_and_and(i32* nocapture readonly %data, i64 %count, i1
|
|||
; 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: --> %cmp.and1 U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (%c umin %cmp.ne) U: full-set S: full-set
|
||||
; CHECK-NEXT: %cmp.and = and i1 %cmp.ult, %cmp.and1
|
||||
; CHECK-NEXT: --> %cmp.and U: full-set S: full-set
|
||||
; 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
|
||||
|
@ -599,7 +599,7 @@ define void @test_guard_if_and_or(i32* nocapture readonly %data, i64 %count, i1
|
|||
; 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: --> %cmp.and U: full-set S: full-set
|
||||
; 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
|
||||
|
@ -747,9 +747,9 @@ define void @test_guard_if_or_and(i32* nocapture readonly %data, i64 %count, i1
|
|||
; 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: --> %cmp.and U: full-set S: full-set
|
||||
; CHECK-NEXT: --> (%c umin %cmp.eq) U: full-set S: full-set
|
||||
; CHECK-NEXT: %cmp.or = or i1 %cmp.uge, %cmp.and
|
||||
; CHECK-NEXT: --> (%cmp.and umax %cmp.uge) U: full-set S: full-set
|
||||
; 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
|
||||
|
@ -1110,7 +1110,7 @@ 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: --> %and U: full-set S: full-set
|
||||
; 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
|
||||
|
@ -1146,7 +1146,7 @@ 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: --> %and U: full-set S: full-set
|
||||
; 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
|
||||
|
@ -1182,7 +1182,7 @@ 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: --> %and U: full-set S: full-set
|
||||
; 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
|
||||
|
@ -1218,7 +1218,7 @@ 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: --> %and U: full-set S: full-set
|
||||
; 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
|
||||
|
|
|
@ -17,7 +17,7 @@ define void @test_and(i1 %boolcond) {
|
|||
; CHECK-NEXT: %iv = phi i32 [ 0, %entry ], [ %inc, %backedge ]
|
||||
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,3) S: [0,3) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
||||
; CHECK-NEXT: %or.cond = and i1 %cond.false.on.first.iter, %cond.false.on.second.iter
|
||||
; CHECK-NEXT: --> %or.cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
||||
; CHECK-NEXT: --> (%cond.false.on.first.iter umin %cond.false.on.second.iter) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
||||
; CHECK-NEXT: %inc = add nuw nsw i32 %iv, 1
|
||||
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,4) S: [1,4) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
|
||||
; CHECK-NEXT: Determining loop execution counts for: @test_and
|
||||
|
|
|
@ -13,7 +13,7 @@ define void @umin_sext_x_zext_x(i32 %len) {
|
|||
; CHECK-NEXT: %iv.next = add i64 %iv, 1
|
||||
; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,4294967297) S: [1,4294967297) Exits: (1 + (zext i32 %len to i64))<nuw><nsw> LoopDispositions: { %loop: Computable }
|
||||
; CHECK-NEXT: %and = and i1 %cmp1, %cmp2
|
||||
; CHECK-NEXT: --> %and U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
||||
; CHECK-NEXT: --> (%cmp1 umin %cmp2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
||||
; CHECK-NEXT: Determining loop execution counts for: @umin_sext_x_zext_x
|
||||
; CHECK-NEXT: Loop %loop: backedge-taken count is (zext i32 %len to i64)
|
||||
; CHECK-NEXT: Loop %loop: max backedge-taken count is 4294967295
|
||||
|
|
|
@ -20,7 +20,7 @@ define i32 @wc_max() {
|
|||
; CHECK-NEXT: %widenable_cond3 = call i1 @llvm.experimental.widenable.condition()
|
||||
; CHECK-NEXT: --> %widenable_cond3 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
||||
; CHECK-NEXT: %exiplicit_guard_cond4 = and i1 %cond_1, %widenable_cond3
|
||||
; CHECK-NEXT: --> %exiplicit_guard_cond4 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
||||
; CHECK-NEXT: --> (%cond_1 umin %widenable_cond3) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
|
||||
; CHECK-NEXT: Determining loop execution counts for: @wc_max
|
||||
; CHECK-NEXT: Loop %loop: Unpredictable backedge-taken count.
|
||||
; CHECK-NEXT: Loop %loop: max backedge-taken count is 1999
|
||||
|
|
Loading…
Reference in New Issue