[llvm] [SimplifyCFG] Simplify nested branches (PR #97067)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 28 12:51:21 PDT 2024


================
@@ -7468,6 +7468,91 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
           if (mergeConditionalStores(PBI, BI, DTU, DL, TTI))
             return requestResimplify();
 
+  {
+    // Fold the following pattern:
+    // bb0:
+    //   br i1 %cond1, label %bb1, label %bb2
+    // bb1:
+    //   br i1 %cond2, label %bb3, label %bb4
+    // bb2:
+    //   br i1 %cond2, label %bb4, label %bb3
+    // bb3:
+    //   ...
+    // bb4:
+    //   ...
+    // into
+    // bb0:
+    //   %cond = xor i1 %cond1, %cond2
+    //   br i1 %cond, label %bb4, label %bb3
+    // bb3:
+    //   ...
+    // bb4:
+    //   ...
+    // NOTE: %cond2 always dominates the terminator of bb0.
+
+    BasicBlock *BB1 = BI->getSuccessor(0);
+    BasicBlock *BB2 = BI->getSuccessor(1);
+    auto IsSimpleSuccessor = [BB](BasicBlock *Succ, BranchInst *&SuccBI) {
+      if (Succ == BB)
+        return false;
+      if (&Succ->front() != Succ->getTerminator())
+        return false;
+      SuccBI = dyn_cast<BranchInst>(Succ->getTerminator());
+      if (!SuccBI || !SuccBI->isConditional())
+        return false;
+      BasicBlock *Succ1 = SuccBI->getSuccessor(0);
+      BasicBlock *Succ2 = SuccBI->getSuccessor(1);
+      return Succ1 != Succ && Succ2 != Succ && Succ1 != BB && Succ2 != BB &&
+             !isa<PHINode>(Succ1->front()) && !isa<PHINode>(Succ2->front());
+    };
+    BranchInst *BB1BI, *BB2BI;
+    if (IsSimpleSuccessor(BB1, BB1BI) && IsSimpleSuccessor(BB2, BB2BI) &&
+        BB1BI->getCondition() == BB2BI->getCondition() &&
+        BB1BI->getSuccessor(0) == BB2BI->getSuccessor(1) &&
+        BB1BI->getSuccessor(1) == BB2BI->getSuccessor(0)) {
+      BasicBlock *BB3 = BB1BI->getSuccessor(0);
+      BasicBlock *BB4 = BB1BI->getSuccessor(1);
+      IRBuilder<> Builder(BI);
+      BI->setCondition(
+          Builder.CreateXor(BI->getCondition(), BB1BI->getCondition()));
+      BB1->removePredecessor(BB);
+      BI->setSuccessor(0, BB4);
+      BB2->removePredecessor(BB);
+      BI->setSuccessor(1, BB3);
+      if (DTU) {
+        SmallVector<DominatorTree::UpdateType, 4> Updates;
+        Updates.push_back({DominatorTree::Delete, BB, BB1});
+        Updates.push_back({DominatorTree::Insert, BB, BB4});
+        Updates.push_back({DominatorTree::Delete, BB, BB2});
+        Updates.push_back({DominatorTree::Insert, BB, BB3});
+
+        DTU->applyUpdates(Updates);
+      }
+      bool HasWeight = false;
+      uint64_t BBTWeight, BBFWeight;
+      if (extractBranchWeights(*BI, BBTWeight, BBFWeight))
+        HasWeight = true;
+      else
+        BBTWeight = BBFWeight = 1;
+      uint64_t BB1TWeight, BB1FWeight;
+      if (extractBranchWeights(*BB1BI, BB1TWeight, BB1FWeight))
+        HasWeight = true;
+      else
+        BB1TWeight = BB1FWeight = 1;
+      uint64_t BB2TWeight, BB2FWeight;
+      if (extractBranchWeights(*BB2BI, BB2TWeight, BB2FWeight))
+        HasWeight = true;
+      else
+        BB2TWeight = BB2FWeight = 1;
+      uint64_t Weights[2] = {BBTWeight * BB1FWeight + BBFWeight * BB2TWeight,
+                             BBTWeight * BB1TWeight + BBFWeight * BB2FWeight};
----------------
nikic wrote:

Move Weights into branch?

https://github.com/llvm/llvm-project/pull/97067


More information about the llvm-commits mailing list