[llvm] [SimplifyCFG] Enable MergeBlockIntoPredecessor with two successors (PR #143766)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 13 16:32:41 PDT 2025


https://github.com/HighW4y2H3ll updated https://github.com/llvm/llvm-project/pull/143766

>From 7194cc0a4e20d1ad5f90c1faf70ad4beca49f05b Mon Sep 17 00:00:00 2001
From: h2h <h2h at meta.com>
Date: Fri, 13 Jun 2025 16:15:00 -0700
Subject: [PATCH] [FlattenCFG] Flatten CFG with Phi nodes

---
 llvm/lib/Transforms/Utils/FlattenCFG.cpp      | 51 ++++++++++++------
 .../SimplifyCFG/flatten-cfg-with-phi.ll       | 53 +++++++++++++++++++
 2 files changed, 89 insertions(+), 15 deletions(-)
 create mode 100644 llvm/test/Transforms/SimplifyCFG/flatten-cfg-with-phi.ll

diff --git a/llvm/lib/Transforms/Utils/FlattenCFG.cpp b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
index 1d9408d6db433..cde9b040224cc 100644
--- a/llvm/lib/Transforms/Utils/FlattenCFG.cpp
+++ b/llvm/lib/Transforms/Utils/FlattenCFG.cpp
@@ -134,10 +134,6 @@ class FlattenCFGOpt {
 ///  its predecessor.  In Case 2, BB (BB3) only has conditional branches
 ///  as its predecessors.
 bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
-  PHINode *PHI = dyn_cast<PHINode>(BB->begin());
-  if (PHI)
-    return false; // For simplicity, avoid cases containing PHI nodes.
-
   BasicBlock *LastCondBlock = nullptr;
   BasicBlock *FirstCondBlock = nullptr;
   BasicBlock *UnCondBlock = nullptr;
@@ -208,8 +204,10 @@ bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
 
     if (Idx == -1)
       Idx = CIdx;
-    else if (CIdx != Idx)
-      return false;
+    else if (CIdx != Idx) {
+      // Inverse Branch Condition
+      InvertBranch(PBI, Builder);
+    }
 
     // PS is the successor which is not BB. Check successors to identify
     // the last conditional branch.
@@ -269,11 +267,6 @@ bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
   if (!PBI1 || !PBI1->isUnconditional())
     return false;
 
-  // PS2 should not contain PHI node.
-  PHI = dyn_cast<PHINode>(PS2->begin());
-  if (PHI)
-    return false;
-
   // Do the transformation.
   BasicBlock *CB;
   BranchInst *PBI = cast<BranchInst>(FirstCondBlock->getTerminator());
@@ -291,17 +284,45 @@ bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder) {
     // Merge conditions.
     Builder.SetInsertPoint(PBI);
     Value *NC;
-    if (Idx == 0)
-      // Case 2, use parallel or.
-      NC = Builder.CreateOr(PC, CC);
-    else
+    if (UnCondBlock)
       // Case 1, use parallel and.
       NC = Builder.CreateAnd(PC, CC);
+    else
+      // Case 2, use parallel or.
+      NC = Builder.CreateOr(PC, CC);
+
+    // Fixup PHI node if needed
+    for (BasicBlock *CBS : successors(PBI)) {
+      for (PHINode &Phi : CBS->phis()) {
+        Value *origPhi0 = nullptr;
+        Value *newPhi = nullptr;
+        if (llvm::is_contained(Phi.blocks(), FirstCondBlock)) {
+          origPhi0 = Phi.removeIncomingValue(FirstCondBlock, false);
+          newPhi = origPhi0;
+        }
+        if (llvm::is_contained(Phi.blocks(), CB)) {
+          Value *origPhi1 = Phi.removeIncomingValue(CB, false);
+          newPhi = origPhi1;
+
+          if (origPhi0) {
+            // Swap branch given the conditions
+            if (PBI->getSuccessor(0) == CBS) {
+              newPhi = Builder.CreateSelect(PC, origPhi0, origPhi1);
+            } else {
+              newPhi = Builder.CreateSelect(PC, origPhi1, origPhi0);
+            }
+          }
+        }
+        if (newPhi)
+          Phi.addIncoming(newPhi, FirstCondBlock);
+      }
+    }
 
     PBI->replaceUsesOfWith(CC, NC);
     PC = NC;
     if (CB == LastCondBlock)
       Iteration = false;
+
     // Remove internal conditional branches.
     CB->dropAllReferences();
     // make CB unreachable and let downstream to delete the block.
diff --git a/llvm/test/Transforms/SimplifyCFG/flatten-cfg-with-phi.ll b/llvm/test/Transforms/SimplifyCFG/flatten-cfg-with-phi.ll
new file mode 100644
index 0000000000000..cf7c3f566e8df
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/flatten-cfg-with-phi.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool ./opt --version 5
+; RUN: opt < %s -passes=flatten-cfg -S | FileCheck %s
+
+define i1 @_Z7compareRK1SS1_(ptr %a, ptr %b) {
+; CHECK-LABEL: @_Z7compareRK1SS1_(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT: entry:
+; CHECK-NEXT:   %0 = load i32, ptr %a, align 4, !tbaa !3
+; CHECK-NEXT:   %1 = load i32, ptr %b, align 4, !tbaa !3
+; CHECK-NEXT:   %cmp.i = icmp sge i32 %0, %1
+; CHECK-NEXT:   %cmp.i19 = icmp eq i32 %0, %1
+; CHECK-NEXT:   %2 = and i1 %cmp.i, %cmp.i19
+; CHECK-NEXT:   %3 = select i1 %cmp.i, i1 false, i1 true
+; CHECK-NEXT:   br i1 %2, label %land.rhs, label %lor.end
+; CHECK-LABEL: lor.end:                                          ; preds = %land.rhs, %entry
+; CHECK-NEXT:   %6 = phi i1 [ %cmp, %land.rhs ], [ %3, %entry ]
+; CHECK-NEXT:   ret i1 %6
+entry:
+  %0 = load i32, ptr %a, align 4, !tbaa !3
+  %1 = load i32, ptr %b, align 4, !tbaa !3
+  %cmp.i = icmp slt i32 %0, %1
+  br i1 %cmp.i, label %lor.end, label %lor.rhs
+
+lor.rhs:                                          ; preds = %entry
+  %cmp.i19 = icmp eq i32 %0, %1
+  br i1 %cmp.i19, label %land.rhs, label %lor.end
+
+land.rhs:                                         ; preds = %lor.rhs
+  %y = getelementptr inbounds nuw i8, ptr %a, i64 4
+  %2 = load i32, ptr %y, align 4, !tbaa !8
+  %y14 = getelementptr inbounds nuw i8, ptr %b, i64 4
+  %3 = load i32, ptr %y14, align 4, !tbaa !8
+  %cmp = icmp slt i32 %2, %3
+  br label %lor.end
+
+lor.end:                                          ; preds = %lor.rhs, %land.rhs, %entry
+  %4 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ %cmp, %land.rhs ]
+  ret i1 %4
+}
+
+!llvm.module.flags = !{!0, !1}
+!llvm.ident = !{!2}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"uwtable", i32 2}
+!2 = !{!"clang"}
+!3 = !{!4, !5, i64 0}
+!4 = !{!"_ZTS1S", !5, i64 0, !5, i64 4}
+!5 = !{!"int", !6, i64 0}
+!6 = !{!"omnipotent char", !7, i64 0}
+!7 = !{!"Simple C++ TBAA"}
+!8 = !{!4, !5, i64 4}
+!9 = !{!5, !5, i64 0}



More information about the llvm-commits mailing list