[llvm] 3adcf96 - [JumpThreading] Let ProcessImpliedCondition look into freeze instructions

Juneyoung Lee via llvm-commits llvm-commits at lists.llvm.org
Tue May 17 18:51:29 PDT 2022


Author: Juneyoung Lee
Date: 2022-05-18T10:41:31+09:00
New Revision: 3adcf96b4faa06ff6d82a8bdf92d2a3f4917c433

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

LOG: [JumpThreading] Let ProcessImpliedCondition look into freeze instructions

This patch makes JumpThreading's ProcessImpliedCondition deal with frozen
conditions.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D84941

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/JumpThreading.cpp
    llvm/test/Transforms/JumpThreading/freeze-impliescond.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index 4a64ada1b538..fc7bcbae21a3 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -1251,6 +1251,17 @@ bool JumpThreadingPass::processImpliedCondition(BasicBlock *BB) {
     return false;
 
   Value *Cond = BI->getCondition();
+  // Assuming that predecessor's branch was taken, if pred's branch condition
+  // (V) implies Cond, Cond can be either true, undef, or poison. In this case,
+  // freeze(Cond) is either true or a nondeterministic value.
+  // If freeze(Cond) has only one use, we can freely fold freeze(Cond) to true
+  // without affecting other instructions.
+  auto *FICond = dyn_cast<FreezeInst>(Cond);
+  if (FICond && FICond->hasOneUse())
+    Cond = FICond->getOperand(0);
+  else
+    FICond = nullptr;
+
   BasicBlock *CurrentBB = BB;
   BasicBlock *CurrentPred = BB->getSinglePredecessor();
   unsigned Iter = 0;
@@ -1267,6 +1278,15 @@ bool JumpThreadingPass::processImpliedCondition(BasicBlock *BB) {
     bool CondIsTrue = PBI->getSuccessor(0) == CurrentBB;
     Optional<bool> Implication =
         isImpliedCondition(PBI->getCondition(), Cond, DL, CondIsTrue);
+
+    // If the branch condition of BB (which is Cond) and CurrentPred are
+    // exactly the same freeze instruction, Cond can be folded into CondIsTrue.
+    if (!Implication && FICond && isa<FreezeInst>(PBI->getCondition())) {
+      if (cast<FreezeInst>(PBI->getCondition())->getOperand(0) ==
+          FICond->getOperand(0))
+        Implication = CondIsTrue;
+    }
+
     if (Implication) {
       BasicBlock *KeepSucc = BI->getSuccessor(*Implication ? 0 : 1);
       BasicBlock *RemoveSucc = BI->getSuccessor(*Implication ? 1 : 0);
@@ -1275,6 +1295,9 @@ bool JumpThreadingPass::processImpliedCondition(BasicBlock *BB) {
       UncondBI->setDebugLoc(BI->getDebugLoc());
       ++NumFolds;
       BI->eraseFromParent();
+      if (FICond)
+        FICond->eraseFromParent();
+
       DTU->applyUpdatesPermissive({{DominatorTree::Delete, BB, RemoveSucc}});
       if (HasProfileData)
         BPI->eraseBlock(BB);

diff  --git a/llvm/test/Transforms/JumpThreading/freeze-impliescond.ll b/llvm/test/Transforms/JumpThreading/freeze-impliescond.ll
index 470782dab7c1..0962e0e88495 100644
--- a/llvm/test/Transforms/JumpThreading/freeze-impliescond.ll
+++ b/llvm/test/Transforms/JumpThreading/freeze-impliescond.ll
@@ -42,20 +42,12 @@ define void @test2(i1 %cond, i1 %dummycond) {
 ; CHECK-NEXT:    [[COND_FR0:%.*]] = freeze i1 [[COND:%.*]]
 ; CHECK-NEXT:    br i1 [[COND_FR0]], label [[A:%.*]], label [[B:%.*]]
 ; CHECK:       A:
-; CHECK-NEXT:    br i1 [[DUMMYCOND:%.*]], label [[A2:%.*]], label [[DUMMY:%.*]]
-; CHECK:       A2:
-; CHECK-NEXT:    [[COND_FR:%.*]] = freeze i1 [[COND]]
-; CHECK-NEXT:    br i1 [[COND_FR]], label [[REACHABLE:%.*]], label [[UNREACHABLE:%.*]]
+; CHECK-NEXT:    br i1 [[DUMMYCOND:%.*]], label [[REACHABLE:%.*]], label [[DUMMY:%.*]]
 ; CHECK:       B:
-; CHECK-NEXT:    br i1 [[DUMMYCOND]], label [[B2:%.*]], label [[DUMMY]]
-; CHECK:       B2:
-; CHECK-NEXT:    [[COND_FR2:%.*]] = freeze i1 [[COND]]
-; CHECK-NEXT:    br i1 [[COND_FR2]], label [[UNREACHABLE]], label [[REACHABLE]]
+; CHECK-NEXT:    br i1 [[DUMMYCOND]], label [[REACHABLE]], label [[DUMMY]]
 ; CHECK:       REACHABLE:
 ; CHECK-NEXT:    call void @f()
 ; CHECK-NEXT:    ret void
-; CHECK:       UNREACHABLE:
-; CHECK-NEXT:    ret void
 ; CHECK:       DUMMY:
 ; CHECK-NEXT:    ret void
 ;
@@ -81,6 +73,14 @@ DUMMY:
   ret void
 }
 
+; In this specific example, it is still correct to fold %cond.fr into true.
+; This case is unsupported because it is unclear what is the result of
+; isImpliedCondition if LHS is poison or undef.
+; If isImpliedCondition(poison, any value) is true,
+; isImpliedCondition(and true, poison, false) is also true because 'and' propagates poison.
+; However, freeze(and true, poison) does not imply false because the former can
+; be frozen to true. Therefore, we cannot look through the argument of freeze (%cond.fr0)
+; in general under this isImpliedCondition definition.
 define void @and_noopt(i32 %x, i1 %cond2, i1 %dummycond) {
 ; CHECK-LABEL: @and_noopt(
 ; CHECK-NEXT:    [[COND1:%.*]] = icmp slt i32 0, [[X:%.*]]
@@ -135,10 +135,7 @@ define void @and(i32 %x, i1 %cond2, i1 %dummycond) {
 ; CHECK-NEXT:    [[COND:%.*]] = and i1 [[COND1]], [[COND2:%.*]]
 ; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
 ; CHECK:       A:
-; CHECK-NEXT:    br i1 [[DUMMYCOND:%.*]], label [[A2:%.*]], label [[DUMMY:%.*]]
-; CHECK:       A2:
-; CHECK-NEXT:    [[COND_FR:%.*]] = freeze i1 [[COND1]]
-; CHECK-NEXT:    br i1 [[COND_FR]], label [[REACHABLE:%.*]], label [[UNREACHABLE:%.*]]
+; CHECK-NEXT:    br i1 [[DUMMYCOND:%.*]], label [[REACHABLE:%.*]], label [[DUMMY:%.*]]
 ; CHECK:       B:
 ; CHECK-NEXT:    br i1 [[DUMMYCOND]], label [[B2:%.*]], label [[DUMMY]]
 ; CHECK:       B2:
@@ -150,8 +147,6 @@ define void @and(i32 %x, i1 %cond2, i1 %dummycond) {
 ; CHECK:       REACHABLE2:
 ; CHECK-NEXT:    call void @f()
 ; CHECK-NEXT:    ret void
-; CHECK:       UNREACHABLE:
-; CHECK-NEXT:    ret void
 ; CHECK:       DUMMY:
 ; CHECK-NEXT:    ret void
 ;


        


More information about the llvm-commits mailing list