[llvm] e7e0834 - [SCEV] Recognize binary `or` as bit-wise `umax`

Roman Lebedev via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 10 06:46:57 PST 2022


Author: Roman Lebedev
Date: 2022-02-10T17:42:54+03:00
New Revision: e7e0834f076afaf3cde2c6c7270821084389dff8

URL: https://github.com/llvm/llvm-project/commit/e7e0834f076afaf3cde2c6c7270821084389dff8
DIFF: https://github.com/llvm/llvm-project/commit/e7e0834f076afaf3cde2c6c7270821084389dff8.diff

LOG: [SCEV] Recognize binary `or` as bit-wise `umax`

https://alive2.llvm.org/ce/z/SMEaoc

We could transparently handle wider bitwidths,
by effectively casting iN to <N x i1> and performing the `umax`
bit/element -wise, the expression will be rather large,
so let's not do that for now.

Added: 
    

Modified: 
    llvm/lib/Analysis/ScalarEvolution.cpp
    llvm/test/Analysis/ScalarEvolution/exact-exit-count-more-precise.ll
    llvm/test/Analysis/ScalarEvolution/logical-operations.ll
    llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll
    llvm/test/Analysis/ScalarEvolution/pr48225.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 546268b4da20f..36fa16267c5c2 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -7199,6 +7199,9 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
                             (SCEV::NoWrapFlags)(SCEV::FlagNUW | SCEV::FlagNSW));
         }
       }
+      // Binary `or` is a bit-wise `umax`.
+      if (BO->LHS->getType()->isIntegerTy(1))
+        return getUMaxExpr(getSCEV(BO->LHS), getSCEV(BO->RHS));
       break;
 
     case Instruction::Xor:

diff  --git a/llvm/test/Analysis/ScalarEvolution/exact-exit-count-more-precise.ll b/llvm/test/Analysis/ScalarEvolution/exact-exit-count-more-precise.ll
index d57265bb94a3c..f33de3c7ec0f6 100644
--- a/llvm/test/Analysis/ScalarEvolution/exact-exit-count-more-precise.ll
+++ b/llvm/test/Analysis/ScalarEvolution/exact-exit-count-more-precise.ll
@@ -51,7 +51,7 @@ define void @test_or() {
 ; CHECK-NEXT:    %B3 = add i32 %1, %2
 ; CHECK-NEXT:    --> {(-2 + undef),+,-1}<%BB> U: full-set S: full-set Exits: -2 LoopDispositions: { %BB: Computable }
 ; CHECK-NEXT:    %B = or i1 %C5, %C11
-; CHECK-NEXT:    --> %B U: full-set S: full-set Exits: false LoopDispositions: { %BB: Variant }
+; CHECK-NEXT:    --> (%C11 umax %C5) U: full-set S: full-set Exits: false LoopDispositions: { %BB: Variant }
 ; CHECK-NEXT:  Determining loop execution counts for: @test_or
 ; CHECK-NEXT:  Loop %BB: backedge-taken count is undef
 ; CHECK-NEXT:  Loop %BB: max backedge-taken count is -1

diff  --git a/llvm/test/Analysis/ScalarEvolution/logical-operations.ll b/llvm/test/Analysis/ScalarEvolution/logical-operations.ll
index 187c5d5e75b93..1b7c554d995ee 100644
--- a/llvm/test/Analysis/ScalarEvolution/logical-operations.ll
+++ b/llvm/test/Analysis/ScalarEvolution/logical-operations.ll
@@ -8,7 +8,7 @@ define i1 @binary_or.i1(i1 %x, i1 %y) {
 ; CHECK-LABEL: 'binary_or.i1'
 ; CHECK-NEXT:  Classifying expressions for: @binary_or.i1
 ; CHECK-NEXT:    %r = or i1 %x, %y
-; CHECK-NEXT:    --> %r U: full-set S: full-set
+; CHECK-NEXT:    --> (%x umax %y) U: full-set S: full-set
 ; CHECK-NEXT:  Determining loop execution counts for: @binary_or.i1
 ;
   %r = or i1 %x, %y
@@ -30,11 +30,11 @@ define i1 @binary_or.4ops.i1(i1 %x, i1 %y, i1 %z, i1 %a) {
 ; CHECK-LABEL: 'binary_or.4ops.i1'
 ; CHECK-NEXT:  Classifying expressions for: @binary_or.4ops.i1
 ; CHECK-NEXT:    %t0 = or i1 %x, %y
-; CHECK-NEXT:    --> %t0 U: full-set S: full-set
+; CHECK-NEXT:    --> (%x umax %y) U: full-set S: full-set
 ; CHECK-NEXT:    %t1 = or i1 %z, %a
-; CHECK-NEXT:    --> %t1 U: full-set S: full-set
+; CHECK-NEXT:    --> (%z umax %a) U: full-set S: full-set
 ; CHECK-NEXT:    %r = or i1 %t0, %t1
-; CHECK-NEXT:    --> %r U: full-set S: full-set
+; CHECK-NEXT:    --> (%x umax %y umax %z umax %a) U: full-set S: full-set
 ; CHECK-NEXT:  Determining loop execution counts for: @binary_or.4ops.i1
 ;
   %t0 = or i1 %x, %y

diff  --git a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll
index 1a9dba0511cd2..54c5e79ef0b14 100644
--- a/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll
+++ b/llvm/test/Analysis/ScalarEvolution/max-backedge-taken-count-guard-info.ll
@@ -597,7 +597,7 @@ define void @test_guard_if_and_or(i32* nocapture readonly %data, i64 %count, i1
 ; 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:    --> %cmp.or U: full-set S: full-set
+; 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:    %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
@@ -636,7 +636,7 @@ 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.or U: full-set S: full-set
+; 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
@@ -672,7 +672,7 @@ 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.or U: full-set S: full-set
+; 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
@@ -708,9 +708,9 @@ define void @test_guard_if_or_or(i32* nocapture readonly %data, i64 %count, i1 %
 ; 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:    --> %cmp.or1 U: full-set S: full-set
+; CHECK-NEXT:    --> (%c umax %cmp.eq) U: full-set S: full-set
 ; CHECK-NEXT:    %cmp.or = or i1 %cmp.uge, %cmp.or1
-; CHECK-NEXT:    --> %cmp.or U: full-set S: full-set
+; 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
@@ -749,7 +749,7 @@ define void @test_guard_if_or_and(i32* nocapture readonly %data, i64 %count, i1
 ; CHECK-NEXT:    %cmp.and = and i1 %c, %cmp.eq
 ; CHECK-NEXT:    --> %cmp.and U: full-set S: full-set
 ; CHECK-NEXT:    %cmp.or = or i1 %cmp.uge, %cmp.and
-; CHECK-NEXT:    --> %cmp.or U: full-set S: full-set
+; CHECK-NEXT:    --> (%cmp.and 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

diff  --git a/llvm/test/Analysis/ScalarEvolution/pr48225.ll b/llvm/test/Analysis/ScalarEvolution/pr48225.ll
index 6e2de25a02bc3..38e0967b4caef 100644
--- a/llvm/test/Analysis/ScalarEvolution/pr48225.ll
+++ b/llvm/test/Analysis/ScalarEvolution/pr48225.ll
@@ -64,7 +64,7 @@ define void @test_or(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 = or i1 %cond.true.on.first.iter, %cond.true.on.second.iter
-; CHECK-NEXT:    --> %or.cond U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
+; CHECK-NEXT:    --> (%cond.true.on.first.iter umax %cond.true.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_or


        


More information about the llvm-commits mailing list