[llvm] 7c73c2e - [LoopDeletion] Benefit from branches by undef conditions when symbolically executing 1st iteration

Max Kazantsev via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 27 21:40:48 PDT 2021


Author: Max Kazantsev
Date: 2021-06-28T11:39:46+07:00
New Revision: 7c73c2ede8088802adb8191d05cad09e3ad88539

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

LOG: [LoopDeletion] Benefit from branches by undef conditions when symbolically executing 1st iteration

We can exploit branches by `undef` condition. Frankly, the LangRef says that
such branches are UB, so we can assume that all outgoing edges of such blocks
are dead.

However, from practical perspective, we know that this is not supported correctly
in some other places. So we are being conservative about it.

Branch by undef is treated in the following way:
- If it is a loop-exiting branch, we always assume it exits the loop;
- If not, we arbitrarily assume it takes `true` value.

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

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/LoopDeletion.cpp
    llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 0831977f53dc2..eee97a54057de 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -333,13 +333,35 @@ static bool canProveExitOnFirstIteration(Loop *L, DominatorTree &DT,
     // Can we prove constant true or false for this condition?
     LHS = getValueOnFirstIteration(LHS, FirstIterValue, SQ);
     RHS = getValueOnFirstIteration(RHS, FirstIterValue, SQ);
-    auto *KnownCondition =
-        dyn_cast_or_null<ConstantInt>(SimplifyICmpInst(Pred, LHS, RHS, SQ));
+    auto *KnownCondition = SimplifyICmpInst(Pred, LHS, RHS, SQ);
     if (!KnownCondition) {
+      // Failed to simplify.
       MarkAllSuccessorsLive(BB);
       continue;
     }
-    if (KnownCondition->isAllOnesValue())
+    if (isa<UndefValue>(KnownCondition)) {
+      // TODO: According to langref, branching by undef is undefined behavior.
+      // It means that, theoretically, we should be able to just continue
+      // without marking any successors as live. However, we are not certain
+      // how correct our compiler is at handling such cases. So we are being
+      // very conservative here.
+      //
+      // If there is a non-loop successor, always assume this branch leaves the
+      // loop. Otherwise, arbitrarily take IfTrue.
+      //
+      // Once we are certain that branching by undef is handled correctly by
+      // other transforms, we should not mark any successors live here.
+      if (L->contains(IfTrue) && L->contains(IfFalse))
+        MarkLiveEdge(BB, IfTrue);
+      continue;
+    }
+    auto *ConstCondition = dyn_cast<ConstantInt>(KnownCondition);
+    if (!ConstCondition) {
+      // Non-constant condition, cannot analyze any further.
+      MarkAllSuccessorsLive(BB);
+      continue;
+    }
+    if (ConstCondition->isAllOnesValue())
       MarkLiveEdge(BB, IfTrue);
     else
       MarkLiveEdge(BB, IfFalse);

diff  --git a/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll b/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll
index 0e7e63f22a7d7..468382db00b46 100644
--- a/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll
+++ b/llvm/test/Transforms/LoopDeletion/eval_first_iteration.ll
@@ -881,20 +881,19 @@ failure:
   unreachable
 }
 
-; TODO: We can break the backedge here by exploiting undef.
 define i32 @test_multiple_pred_undef_3(i1 %cond, i1 %cond2) {
 ; CHECK-LABEL: @test_multiple_pred_undef_3(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[LOOP:%.*]]
 ; CHECK:       loop:
-; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[BACKEDGE:%.*]] ]
+; CHECK-NEXT:    [[SUM:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
 ; CHECK-NEXT:    [[SUB:%.*]] = sub i32 4, [[SUM]]
 ; CHECK-NEXT:    [[IS_POSITIVE:%.*]] = icmp sgt i32 [[SUB]], 0
 ; CHECK-NEXT:    br i1 [[IS_POSITIVE]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
 ; CHECK:       if.true:
 ; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_TRUE_1:%.*]], label [[IF_TRUE_2:%.*]]
 ; CHECK:       if.true.1:
-; CHECK-NEXT:    br label [[BACKEDGE]]
+; CHECK-NEXT:    br label [[BACKEDGE:%.*]]
 ; CHECK:       if.true.2:
 ; CHECK-NEXT:    br label [[BACKEDGE]]
 ; CHECK:       if.false:
@@ -905,9 +904,11 @@ define i32 @test_multiple_pred_undef_3(i1 %cond, i1 %cond2) {
 ; CHECK-NEXT:    br label [[BACKEDGE]]
 ; CHECK:       backedge:
 ; CHECK-NEXT:    [[MERGE_PHI:%.*]] = phi i32 [ 0, [[IF_FALSE_1]] ], [ 0, [[IF_FALSE_2]] ], [ undef, [[IF_TRUE_1]] ], [ undef, [[IF_TRUE_2]] ]
-; CHECK-NEXT:    [[SUM_NEXT]] = add i32 [[SUM]], [[MERGE_PHI]]
+; CHECK-NEXT:    [[SUM_NEXT:%.*]] = add i32 [[SUM]], [[MERGE_PHI]]
 ; CHECK-NEXT:    [[LOOP_COND:%.*]] = icmp ne i32 [[SUM_NEXT]], 4
-; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[LOOP]], label [[DONE:%.*]]
+; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[BACKEDGE_LOOP_CRIT_EDGE:%.*]], label [[DONE:%.*]]
+; CHECK:       backedge.loop_crit_edge:
+; CHECK-NEXT:    unreachable
 ; CHECK:       done:
 ; CHECK-NEXT:    [[SUM_NEXT_LCSSA:%.*]] = phi i32 [ [[SUM_NEXT]], [[BACKEDGE]] ]
 ; CHECK-NEXT:    ret i32 [[SUM_NEXT_LCSSA]]


        


More information about the llvm-commits mailing list