[llvm] 0130d0e - [SCEV] Compute symbolic exit count for 'and' conditions

Max Kazantsev via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 8 01:05:08 PST 2022


Author: Max Kazantsev
Date: 2022-12-08T16:04:42+07:00
New Revision: 0130d0ed35e8788be502f14cdb8b5569a6db527a

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

LOG: [SCEV] Compute symbolic exit count for 'and' conditions

If loop exits by condition like `A < B && X < Y`, and at least one of symbolic max
exit counts for these conditions is known, it can be used as estimate of symbolic
max exit count for whole branch. If both are known, then we can use their umin
as the estimate.

Differential Revision: https://reviews.llvm.org/D139403
Reviewed By: nikic

Added: 
    

Modified: 
    llvm/lib/Analysis/ScalarEvolution.cpp
    llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 1a6a27e97549..61a4895c8341 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -8961,14 +8961,15 @@ ScalarEvolution::computeExitLimitFromCondFromBinOp(
 
   const SCEV *BECount = getCouldNotCompute();
   const SCEV *ConstantMaxBECount = getCouldNotCompute();
+  const SCEV *SymbolicMaxBECount = getCouldNotCompute();
   if (EitherMayExit) {
+    bool UseSequentialUMin = !isa<BinaryOperator>(ExitCond);
     // Both conditions must be same for the loop to continue executing.
     // Choose the less conservative count.
     if (EL0.ExactNotTaken != getCouldNotCompute() &&
         EL1.ExactNotTaken != getCouldNotCompute()) {
-      BECount = getUMinFromMismatchedTypes(
-          EL0.ExactNotTaken, EL1.ExactNotTaken,
-          /*Sequential=*/!isa<BinaryOperator>(ExitCond));
+      BECount = getUMinFromMismatchedTypes(EL0.ExactNotTaken, EL1.ExactNotTaken,
+                                           UseSequentialUMin);
     }
     if (EL0.ConstantMaxNotTaken == getCouldNotCompute())
       ConstantMaxBECount = EL1.ConstantMaxNotTaken;
@@ -8977,6 +8978,13 @@ ScalarEvolution::computeExitLimitFromCondFromBinOp(
     else
       ConstantMaxBECount = getUMinFromMismatchedTypes(EL0.ConstantMaxNotTaken,
                                                       EL1.ConstantMaxNotTaken);
+    if (EL0.SymbolicMaxNotTaken == getCouldNotCompute())
+      SymbolicMaxBECount = EL1.SymbolicMaxNotTaken;
+    else if (EL1.SymbolicMaxNotTaken == getCouldNotCompute())
+      SymbolicMaxBECount = EL0.SymbolicMaxNotTaken;
+    else
+      SymbolicMaxBECount = getUMinFromMismatchedTypes(
+          EL0.SymbolicMaxNotTaken, EL1.SymbolicMaxNotTaken, UseSequentialUMin);
   } else {
     // Both conditions must be same at the same time for the loop to exit.
     // For now, be conservative.
@@ -8993,8 +9001,9 @@ ScalarEvolution::computeExitLimitFromCondFromBinOp(
   if (isa<SCEVCouldNotCompute>(ConstantMaxBECount) &&
       !isa<SCEVCouldNotCompute>(BECount))
     ConstantMaxBECount = getConstant(getUnsignedRangeMax(BECount));
-  const SCEV *SymbolicMaxBECount =
-      isa<SCEVCouldNotCompute>(BECount) ? ConstantMaxBECount : BECount;
+  if (isa<SCEVCouldNotCompute>(SymbolicMaxBECount))
+    SymbolicMaxBECount =
+        isa<SCEVCouldNotCompute>(BECount) ? ConstantMaxBECount : BECount;
   return ExitLimit(BECount, ConstantMaxBECount, SymbolicMaxBECount, false,
                    { &EL0.Predicates, &EL1.Predicates });
 }

diff  --git a/llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll b/llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll
index c85582fb294b..d45cf2dd65fd 100644
--- a/llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll
+++ b/llvm/test/Analysis/ScalarEvolution/symbolic_max_exit_count.ll
@@ -54,7 +54,6 @@ failed_2:
   ret i32 -2
 }
 
-; TODO: Symbolic max can be %start
 define i32 @test_litter_conditions(i32 %start, i32 %len) {
 ; CHECK-LABEL: 'test_litter_conditions'
 ; CHECK-NEXT:  Classifying expressions for: @test_litter_conditions
@@ -80,8 +79,8 @@ define i32 @test_litter_conditions(i32 %start, i32 %len) {
 ; CHECK-NEXT:    exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is -1
-; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is -1
-; CHECK-NEXT:    symbolic max exit count for loop: -1
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is %start
+; CHECK-NEXT:    symbolic max exit count for loop: %start
 ; CHECK-NEXT:    symbolic max exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    symbolic max exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: Unpredictable predicated backedge-taken count.
@@ -118,7 +117,6 @@ failed_2:
   ret i32 -2
 }
 
-; TODO: Symbolic max can be %start
 define i32 @test_litter_conditions_bad_context(i32 %start, i32 %len) {
 ; CHECK-LABEL: 'test_litter_conditions_bad_context'
 ; CHECK-NEXT:  Classifying expressions for: @test_litter_conditions_bad_context
@@ -144,8 +142,8 @@ define i32 @test_litter_conditions_bad_context(i32 %start, i32 %len) {
 ; CHECK-NEXT:    exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is -1
-; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is -1
-; CHECK-NEXT:    symbolic max exit count for loop: -1
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is %start
+; CHECK-NEXT:    symbolic max exit count for loop: %start
 ; CHECK-NEXT:    symbolic max exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    symbolic max exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: Unpredictable predicated backedge-taken count.
@@ -182,7 +180,6 @@ failed_2:
   ret i32 -2
 }
 
-; TODO: Symbolic max can be %start
 define i32 @test_and_conditions(i32 %start, i32 %len) {
 ; CHECK-LABEL: 'test_and_conditions'
 ; CHECK-NEXT:  Classifying expressions for: @test_and_conditions
@@ -201,8 +198,8 @@ define i32 @test_and_conditions(i32 %start, i32 %len) {
 ; CHECK-NEXT:    exit count for loop: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is -1
-; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is -1
-; CHECK-NEXT:    symbolic max exit count for loop: -1
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is %start
+; CHECK-NEXT:    symbolic max exit count for loop: %start
 ; CHECK-NEXT:    symbolic max exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: Unpredictable predicated backedge-taken count.
 ;
@@ -320,7 +317,6 @@ failed_1:
   ret i32 -1
 }
 
-; TODO: Symbolic max can be start1 umin_seq start2
 define i32 @test_two_phis(i32 %start_1, i32 %start_2, i32 %len) {
 ; CHECK-LABEL: 'test_two_phis'
 ; CHECK-NEXT:  Classifying expressions for: @test_two_phis
@@ -351,9 +347,9 @@ define i32 @test_two_phis(i32 %start_1, i32 %start_2, i32 %len) {
 ; CHECK-NEXT:    exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is -1
-; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is -1
-; CHECK-NEXT:    symbolic max exit count for loop: -1
-; CHECK-NEXT:    symbolic max exit count for zero_check_block: -1
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is (%start_1 umin_seq %start_2)
+; CHECK-NEXT:    symbolic max exit count for loop: %start_1
+; CHECK-NEXT:    symbolic max exit count for zero_check_block: %start_2
 ; CHECK-NEXT:    symbolic max exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    symbolic max exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: Unpredictable predicated backedge-taken count.
@@ -438,7 +434,6 @@ exit:
   ret i32 0
 }
 
-; TODO: Symbolic max can be start1 umin start2
 define i32 @test_two_phis_arithmetic_and(i32 %start_1, i32 %start_2, i32 %len) {
 ; CHECK-LABEL: 'test_two_phis_arithmetic_and'
 ; CHECK-NEXT:  Classifying expressions for: @test_two_phis_arithmetic_and
@@ -470,8 +465,8 @@ define i32 @test_two_phis_arithmetic_and(i32 %start_1, i32 %start_2, i32 %len) {
 ; CHECK-NEXT:    exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is -1
-; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is -1
-; CHECK-NEXT:    symbolic max exit count for loop: -1
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is (%start_1 umin %start_2)
+; CHECK-NEXT:    symbolic max exit count for loop: (%start_1 umin %start_2)
 ; CHECK-NEXT:    symbolic max exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    symbolic max exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: Unpredictable predicated backedge-taken count.
@@ -586,7 +581,6 @@ failed_2:
   ret i32 -2
 }
 
-; TODO: Symbolic max can be start1 umin_seq start2
 define i32 @test_two_phis_logical_and(i32 %start_1, i32 %start_2, i32 %len) {
 ; CHECK-LABEL: 'test_two_phis_logical_and'
 ; CHECK-NEXT:  Classifying expressions for: @test_two_phis_logical_and
@@ -618,8 +612,8 @@ define i32 @test_two_phis_logical_and(i32 %start_1, i32 %start_2, i32 %len) {
 ; CHECK-NEXT:    exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: constant max backedge-taken count is -1
-; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is -1
-; CHECK-NEXT:    symbolic max exit count for loop: -1
+; CHECK-NEXT:  Loop %loop: symbolic max backedge-taken count is (%start_1 umin_seq %start_2)
+; CHECK-NEXT:    symbolic max exit count for loop: (%start_1 umin_seq %start_2)
 ; CHECK-NEXT:    symbolic max exit count for range_check_block: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:    symbolic max exit count for backedge: ***COULDNOTCOMPUTE***
 ; CHECK-NEXT:  Loop %loop: Unpredictable predicated backedge-taken count.


        


More information about the llvm-commits mailing list