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}<%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}<%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}<%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}<%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}<%loop> U: [0,3) S: [0,3) Exits: <> 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: <> LoopDispositions: { %loop: Variant } +; CHECK-NEXT: --> (%cond.true.on.first.iter umax %cond.true.on.second.iter) U: full-set S: full-set Exits: <> LoopDispositions: { %loop: Variant } ; CHECK-NEXT: %inc = add nuw nsw i32 %iv, 1 ; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,4) S: [1,4) Exits: <> LoopDispositions: { %loop: Computable } ; CHECK-NEXT: Determining loop execution counts for: @test_or