[llvm] 40a4078 - [BasicBlockUtils] Allow splitting predecessors with callbr terminators

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 7 00:18:14 PDT 2022


Author: Nikita Popov
Date: 2022-07-07T09:13:25+02:00
New Revision: 40a4078e14c2c6c5e2d0a1776285aa7491e791b3

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

LOG: [BasicBlockUtils] Allow splitting predecessors with callbr terminators

SplitBlockPredecessors currently asserts if one of the predecessor
terminators is a callbr. This limitation was originally necessary,
because just like with indirectbr, it was not possible to replace
successors of a callbr. However, this is no longer the case since
D67252. As the requirement nowadays is that callbr must reference
all blockaddrs directly in the call arguments, and these get
automatically updated when setSuccessor() is called, we no longer
need this limitation.

The only thing we need to do here is use replaceSuccessorWith()
instead of replaceUsesOfWith(), because only the former does the
necessary blockaddr updating magic.

I believe there's other similar limitations that can be removed,
e.g. related to critical edge splitting.

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

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/JumpThreading.cpp
    llvm/lib/Transforms/Scalar/LICM.cpp
    llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
    llvm/lib/Transforms/Utils/LoopUtils.cpp
    llvm/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/test/Transforms/JumpThreading/callbr-edge-split.ll
    llvm/test/Transforms/JumpThreading/pr46857-callbr.ll
    llvm/test/Transforms/LICM/callbr-crash.ll
    llvm/test/Transforms/SimplifyCFG/jump-threading.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
index 5caefc4229210..c441cf2799c23 100644
--- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp
@@ -1459,9 +1459,7 @@ bool JumpThreadingPass::simplifyPartiallyRedundantLoad(LoadInst *LoadI) {
     // Add all the unavailable predecessors to the PredsToSplit list.
     for (BasicBlock *P : predecessors(LoadBB)) {
       // If the predecessor is an indirect goto, we can't split the edge.
-      // Same for CallBr.
-      if (isa<IndirectBrInst>(P->getTerminator()) ||
-          isa<CallBrInst>(P->getTerminator()))
+      if (isa<IndirectBrInst>(P->getTerminator()))
         return false;
 
       if (!AvailablePredSet.count(P))
@@ -1685,9 +1683,8 @@ bool JumpThreadingPass::processThreadableEdges(Value *Cond, BasicBlock *BB,
     }
 
     // If the predecessor ends with an indirect goto, we can't change its
-    // destination. Same for CallBr.
-    if (isa<IndirectBrInst>(Pred->getTerminator()) ||
-        isa<CallBrInst>(Pred->getTerminator()))
+    // destination.
+    if (isa<IndirectBrInst>(Pred->getTerminator()))
       continue;
 
     PredToDestList.emplace_back(Pred, DestBB);
@@ -1924,10 +1921,9 @@ bool JumpThreadingPass::processBranchOnXOR(BinaryOperator *BO) {
   }
 
   // If any of predecessors end with an indirect goto, we can't change its
-  // destination. Same for CallBr.
+  // destination.
   if (any_of(BlocksToFoldInto, [](BasicBlock *Pred) {
-        return isa<IndirectBrInst>(Pred->getTerminator()) ||
-               isa<CallBrInst>(Pred->getTerminator());
+        return isa<IndirectBrInst>(Pred->getTerminator());
       }))
     return false;
 

diff  --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp
index 492f4e40395a1..f54264b1dca6c 100644
--- a/llvm/lib/Transforms/Scalar/LICM.cpp
+++ b/llvm/lib/Transforms/Scalar/LICM.cpp
@@ -1508,8 +1508,7 @@ static bool canSplitPredecessors(PHINode *PN, LoopSafetyInfo *SafetyInfo) {
   if (!SafetyInfo->getBlockColors().empty() && BB->getFirstNonPHI()->isEHPad())
     return false;
   for (BasicBlock *BBPred : predecessors(BB)) {
-    if (isa<IndirectBrInst>(BBPred->getTerminator()) ||
-        isa<CallBrInst>(BBPred->getTerminator()))
+    if (isa<IndirectBrInst>(BBPred->getTerminator()))
       return false;
   }
   return true;

diff  --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
index e9983ff821761..56bb405339fe6 100644
--- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -1132,9 +1132,7 @@ SplitBlockPredecessorsImpl(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
     // all BlockAddress uses would need to be updated.
     assert(!isa<IndirectBrInst>(Preds[i]->getTerminator()) &&
            "Cannot split an edge from an IndirectBrInst");
-    assert(!isa<CallBrInst>(Preds[i]->getTerminator()) &&
-           "Cannot split an edge from a CallBrInst");
-    Preds[i]->getTerminator()->replaceUsesOfWith(BB, NewBB);
+    Preds[i]->getTerminator()->replaceSuccessorWith(BB, NewBB);
   }
 
   // Insert a new PHI node into NewBB for every PHI node in BB and that new PHI

diff  --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index e088cf829ae20..afc7c61a56218 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -75,9 +75,6 @@ bool llvm::formDedicatedExitBlocks(Loop *L, DominatorTree *DT, LoopInfo *LI,
         if (isa<IndirectBrInst>(PredBB->getTerminator()))
           // We cannot rewrite exiting edges from an indirectbr.
           return false;
-        if (isa<CallBrInst>(PredBB->getTerminator()))
-          // We cannot rewrite exiting edges from a callbr.
-          return false;
 
         InLoopPredecessors.push_back(PredBB);
       } else {

diff  --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 7d76a6b68d0a8..86b2128a19374 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3033,8 +3033,7 @@ FoldCondBranchOnValueKnownInPredecessorImpl(BranchInst *BI, DomTreeUpdater *DTU,
 
     // Skip if the predecessor's terminator is an indirect branch.
     if (any_of(PredBBs, [](BasicBlock *PredBB) {
-          return isa<IndirectBrInst>(PredBB->getTerminator()) ||
-                 isa<CallBrInst>(PredBB->getTerminator());
+          return isa<IndirectBrInst>(PredBB->getTerminator());
         }))
       continue;
 

diff  --git a/llvm/test/Transforms/JumpThreading/callbr-edge-split.ll b/llvm/test/Transforms/JumpThreading/callbr-edge-split.ll
index 182bc1ea2ef19..44befe9751ed7 100644
--- a/llvm/test/Transforms/JumpThreading/callbr-edge-split.ll
+++ b/llvm/test/Transforms/JumpThreading/callbr-edge-split.ll
@@ -8,18 +8,18 @@
 define i32 @c() {
 ; CHECK-LABEL: @c(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a
+; CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
 ; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
-; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
-; CHECK:       if.then:
-; CHECK-NEXT:    [[CALL:%.*]] = call i32 @b()
-; CHECK-NEXT:    [[PHITMP:%.*]] = icmp ne i32 [[CALL]], 0
-; CHECK-NEXT:    br i1 [[PHITMP]], label [[IF_THEN2:%.*]], label [[IF_END4:%.*]]
+; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.else:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i"(i8* blockaddress(@c, [[IF_THEN2]]))
-; CHECK-NEXT:    to label [[IF_END_THREAD:%.*]] [label %if.then2]
-; CHECK:       if.end.thread:
+; CHECK-NEXT:    callbr void asm sideeffect "", "i"(i8* blockaddress(@c, [[IF_THEN2:%.*]]))
+; CHECK-NEXT:    to label [[NORMAL:%.*]] [label %if.then2]
+; CHECK:       normal:
 ; CHECK-NEXT:    br label [[IF_THEN2]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[CALL:%.*]] = call i32 @b()
+; CHECK-NEXT:    [[PHITMP:%.*]] = icmp ne i32 [[CALL]], 0
+; CHECK-NEXT:    br i1 [[PHITMP]], label [[IF_THEN2]], label [[IF_END4:%.*]]
 ; CHECK:       if.then2:
 ; CHECK-NEXT:    [[CALL3:%.*]] = call i32 @b()
 ; CHECK-NEXT:    br label [[IF_END4]]

diff  --git a/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll b/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll
index 605e4a0ed2612..882a6ea705636 100644
--- a/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll
+++ b/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll
@@ -6,21 +6,22 @@
 define i1 @func(i1 %arg, i32 %arg1, i1 %arg2) {
 ; CHECK-LABEL: @func(
 ; CHECK-NEXT:  bb:
-; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]
-; CHECK:       bb3:
-; CHECK-NEXT:    [[I:%.*]] = icmp eq i32 [[ARG1:%.*]], 0
-; CHECK-NEXT:    br label [[BB7:%.*]]
+; CHECK-NEXT:    br i1 [[ARG:%.*]], label [[BB7:%.*]], label [[BB4:%.*]]
 ; CHECK:       bb4:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i"(i8* blockaddress(@func, [[BB7]]))
-; CHECK-NEXT:    to label [[BB5:%.*]] [label %bb7]
+; CHECK-NEXT:    callbr void asm sideeffect "", "i"(i8* blockaddress(@func, [[BB7_THR_COMM:%.*]]))
+; CHECK-NEXT:    to label [[BB5:%.*]] [label %bb7.thr_comm]
 ; CHECK:       bb5:
-; CHECK-NEXT:    br label [[BB7]]
+; CHECK-NEXT:    br label [[BB7_THR_COMM]]
+; CHECK:       bb7.thr_comm:
+; CHECK-NEXT:    [[I91:%.*]] = xor i1 [[ARG2:%.*]], [[ARG]]
+; CHECK-NEXT:    br i1 [[I91]], label [[BB11:%.*]], label [[BB11]]
 ; CHECK:       bb7:
-; CHECK-NEXT:    [[I8:%.*]] = phi i1 [ [[I]], [[BB3]] ], [ [[ARG2:%.*]], [[BB5]] ], [ [[ARG2]], [[BB4]] ]
-; CHECK-NEXT:    [[I9:%.*]] = xor i1 [[I8]], [[ARG]]
-; CHECK-NEXT:    br i1 [[I9]], label [[BB11:%.*]], label [[BB11]]
+; CHECK-NEXT:    [[I:%.*]] = icmp eq i32 [[ARG1:%.*]], 0
+; CHECK-NEXT:    [[I9:%.*]] = xor i1 [[I]], [[ARG]]
+; CHECK-NEXT:    br i1 [[I9]], label [[BB11]], label [[BB11]]
 ; CHECK:       bb11:
-; CHECK-NEXT:    ret i1 [[I9]]
+; CHECK-NEXT:    [[I93:%.*]] = phi i1 [ [[I91]], [[BB7_THR_COMM]] ], [ [[I9]], [[BB7]] ], [ [[I91]], [[BB7_THR_COMM]] ], [ [[I9]], [[BB7]] ]
+; CHECK-NEXT:    ret i1 [[I93]]
 ;
 bb:
   br i1 %arg, label %bb3, label %bb4

diff  --git a/llvm/test/Transforms/LICM/callbr-crash.ll b/llvm/test/Transforms/LICM/callbr-crash.ll
index c9a3136e76124..b69ffc76b79fa 100644
--- a/llvm/test/Transforms/LICM/callbr-crash.ll
+++ b/llvm/test/Transforms/LICM/callbr-crash.ll
@@ -6,12 +6,18 @@ define i32 @j() {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
 ; CHECK:       for.cond:
-; CHECK-NEXT:    callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@j, [[FOR_END:%.*]]))
-; CHECK-NEXT:    to label [[COND_TRUE_I:%.*]] [label %for.end]
+; CHECK-NEXT:    callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@j, [[FOR_END_SPLIT_LOOP_EXIT1:%.*]]))
+; CHECK-NEXT:    to label [[COND_TRUE_I:%.*]] [label %for.end.split.loop.exit1]
 ; CHECK:       cond.true.i:
-; CHECK-NEXT:    br i1 true, label [[FOR_END]], label [[FOR_COND]]
+; CHECK-NEXT:    br i1 true, label [[FOR_END_SPLIT_LOOP_EXIT:%.*]], label [[FOR_COND]]
+; CHECK:       for.end.split.loop.exit:
+; CHECK-NEXT:    [[ASMRESULT1_I_I_LE:%.*]] = extractvalue { i8, i32 } zeroinitializer, 1
+; CHECK-NEXT:    br label [[FOR_END:%.*]]
+; CHECK:       for.end.split.loop.exit1:
+; CHECK-NEXT:    [[PHI_PH2:%.*]] = phi i32 [ undef, [[FOR_COND]] ]
+; CHECK-NEXT:    br label [[FOR_END]]
 ; CHECK:       for.end:
-; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ 0, [[COND_TRUE_I]] ], [ undef, [[FOR_COND]] ]
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[ASMRESULT1_I_I_LE]], [[FOR_END_SPLIT_LOOP_EXIT]] ], [ [[PHI_PH2]], [[FOR_END_SPLIT_LOOP_EXIT1]] ]
 ; CHECK-NEXT:    ret i32 [[PHI]]
 ;
 entry:

diff  --git a/llvm/test/Transforms/SimplifyCFG/jump-threading.ll b/llvm/test/Transforms/SimplifyCFG/jump-threading.ll
index 113ea6a01423f..c340fa0880b85 100644
--- a/llvm/test/Transforms/SimplifyCFG/jump-threading.ll
+++ b/llvm/test/Transforms/SimplifyCFG/jump-threading.ll
@@ -425,14 +425,8 @@ define void @callbr() {
 ; CHECK-LABEL: @callbr(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    callbr void asm sideeffect "", "i,~{dirflag},~{fpsr},~{flags}"(ptr blockaddress(@callbr, [[TARGET:%.*]]))
-; CHECK-NEXT:    to label [[JOIN:%.*]] [label %target]
+; CHECK-NEXT:    to label [[IF_END:%.*]] [label %target]
 ; CHECK:       target:
-; CHECK-NEXT:    br label [[JOIN]]
-; CHECK:       join:
-; CHECK-NEXT:    [[PHI:%.*]] = phi i1 [ false, [[TARGET]] ], [ false, [[ENTRY:%.*]] ]
-; CHECK-NEXT:    br i1 [[PHI]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
-; CHECK:       if.then:
-; CHECK-NEXT:    call void @foo()
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    ret void


        


More information about the llvm-commits mailing list