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

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 30 09:30:35 PDT 2024


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

>From 4952a3a44adb3c5ea36885f5877a1109269f626c Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 29 Jun 2024 16:43:10 +0800
Subject: [PATCH 1/5] [SimplifyCFG] Add pre-commit tests from PR97022. NFC.

---
 .../Transforms/SimplifyCFG/branch-nested.ll   | 314 ++++++++++++++++++
 1 file changed, 314 insertions(+)
 create mode 100644 llvm/test/Transforms/SimplifyCFG/branch-nested.ll

diff --git a/llvm/test/Transforms/SimplifyCFG/branch-nested.ll b/llvm/test/Transforms/SimplifyCFG/branch-nested.ll
new file mode 100644
index 0000000000000..3f9b9ca14b6e2
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/branch-nested.ll
@@ -0,0 +1,314 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
+
+define void @fold_nested_branch(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: define void @fold_nested_branch(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4]], label %[[BB3]]
+; CHECK:       [[COMMON_RET:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+; Negative tests
+
+define void @fold_nested_branch_cfg_mismatch(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: define void @fold_nested_branch_cfg_mismatch(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[COMMON_RET:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4:.*]], label %[[BB3]]
+; CHECK:       [[COMMON_RET]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb5
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+
+bb5:
+  ret void
+}
+
+define void @fold_nested_branch_cond_mismatch(i1 %cond1, i1 %cond2, i1 %cond3) {
+; CHECK-LABEL: define void @fold_nested_branch_cond_mismatch(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], i1 [[COND3:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br i1 [[COND3]], label %[[BB4]], label %[[BB3]]
+; CHECK:       [[COMMON_RET:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond3, label %bb4, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+define void @fold_nested_branch_non_trivial_succ(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: define void @fold_nested_branch_non_trivial_succ(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4]], label %[[BB3]]
+; CHECK:       [[COMMON_RET:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  call void @sideeffect1()
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+define i32 @fold_nested_branch_with_phi(i1 %cond1, i1 %cond2, i32 %x) {
+; CHECK-LABEL: define i32 @fold_nested_branch_with_phi(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], i32 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[COMMON_RET:.*]], label %[[BB4:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4]], label %[[COMMON_RET]]
+; CHECK:       [[COMMON_RET]]:
+; CHECK-NEXT:    [[COMMON_RET_OP:%.*]] = phi i32 [ 0, %[[BB4]] ], [ 0, %[[BB1]] ], [ [[X]], %[[BB2]] ]
+; CHECK-NEXT:    ret i32 [[COMMON_RET_OP]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3
+
+bb3:
+  %ret = phi i32 [ 0, %bb1 ], [ %x, %bb2 ]
+  ret i32 %ret
+
+bb4:
+  call void @sideeffect2()
+  ret i32 0
+}
+
+define void @fold_nested_branch_loop1(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: define void @fold_nested_branch_loop1(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[COND1_NOT:%.*]] = xor i1 [[COND1]], true
+; CHECK-NEXT:    [[BRMERGE:%.*]] = select i1 [[COND1_NOT]], i1 true, i1 [[COND2]]
+; CHECK-NEXT:    br i1 [[BRMERGE]], label %[[BB3:.*]], label %[[BB4:.*]]
+; CHECK:       [[COMMON_RET:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb1, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+define void @fold_nested_branch_loop2(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: define void @fold_nested_branch_loop2(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[BB0:.*]]
+; CHECK:       [[BB0]]:
+; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB0]], label %[[BB3]]
+; CHECK:       [[COMMON_RET:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br label %bb0
+
+bb0:
+  br i1 %cond1, label %bb1, label %bb2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4
+
+bb2:
+  br i1 %cond2, label %bb0, label %bb3
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+; Make sure that branch weights are correctly preserved
+; freq(bb4) = 1 * 4 + 2 * 5 = 14
+; freq(bb3) = 1 * 3 + 2 * 6 = 15
+define void @fold_nested_branch_prof(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: define void @fold_nested_branch_prof(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]], !prof [[PROF0:![0-9]+]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1:![0-9]+]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4]], label %[[BB3]], !prof [[PROF2:![0-9]+]]
+; CHECK:       [[COMMON_RET:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br i1 %cond1, label %bb1, label %bb2, !prof !0 ; 1:2
+
+bb1:
+  br i1 %cond2, label %bb3, label %bb4, !prof !1 ; 3:4
+
+bb2:
+  br i1 %cond2, label %bb4, label %bb3, !prof !2 ; 5:6
+
+bb3:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
+!0 = !{!"branch_weights", i32 1, i32 2}
+!1 = !{!"branch_weights", i32 3, i32 4}
+!2 = !{!"branch_weights", i32 5, i32 6}
+
+
+declare void @sideeffect1()
+declare void @sideeffect2()
+;.
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 1, i32 2}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 3, i32 4}
+; CHECK: [[PROF2]] = !{!"branch_weights", i32 5, i32 6}
+;.

>From f9d7f5f29c012c0e7d904c679b42c24390c8dc62 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 29 Jun 2024 16:59:52 +0800
Subject: [PATCH 2/5] [SimplifyCFG] Simplify nested branches.

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     |  93 ++++++++++++++
 llvm/test/CodeGen/ARM/and-cmp0-sink.ll        | 115 +++++-------------
 .../Transforms/SimplifyCFG/branch-nested.ll   |  18 +--
 3 files changed, 127 insertions(+), 99 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 6847bb7502429..69daa6352f95e 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -7361,6 +7361,95 @@ static BasicBlock *allPredecessorsComeFromSameSource(BasicBlock *BB) {
   return PredPred;
 }
 
+/// 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.
+static bool mergeNestedCondBranch(BranchInst *BI, DomTreeUpdater *DTU) {
+  BasicBlock *BB = BI->getParent();
+  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))
+    return false;
+
+  if (BB1BI->getCondition() != BB2BI->getCondition() ||
+      BB1BI->getSuccessor(0) != BB2BI->getSuccessor(1) ||
+      BB1BI->getSuccessor(1) != BB2BI->getSuccessor(0))
+    return false;
+
+  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;
+  if (HasWeight) {
+    uint64_t Weights[2] = {BBTWeight * BB1FWeight + BBFWeight * BB2TWeight,
+                           BBTWeight * BB1TWeight + BBFWeight * BB2FWeight};
+    FitWeights(Weights);
+    setBranchWeights(BI, Weights[0], Weights[1], /*IsExpected=*/false);
+  }
+  return true;
+}
+
 bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
   assert(
       !isa<ConstantInt>(BI->getCondition()) &&
@@ -7468,6 +7557,10 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
           if (mergeConditionalStores(PBI, BI, DTU, DL, TTI))
             return requestResimplify();
 
+  // Look for nested conditional branches.
+  if (mergeNestedCondBranch(BI, DTU))
+    return requestResimplify();
+
   return false;
 }
 
diff --git a/llvm/test/CodeGen/ARM/and-cmp0-sink.ll b/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
index 27203e274a4aa..9c60f02dee881 100644
--- a/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
+++ b/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
@@ -189,60 +189,31 @@ exit:
 define i32 @f0(i1 %c0, i32 %v) {
 ; V7M-LABEL: f0:
 ; V7M:       @ %bb.0: @ %E
-; V7M-NEXT:    lsls r0, r0, #31
-; V7M-NEXT:    beq .LBB1_2
-; V7M-NEXT:  @ %bb.1: @ %A
-; V7M-NEXT:    tst.w r1, #16843009
-; V7M-NEXT:    itt eq
-; V7M-NEXT:    moveq r0, #0
-; V7M-NEXT:    bxeq lr
-; V7M-NEXT:    b .LBB1_3
-; V7M-NEXT:  .LBB1_2: @ %B
-; V7M-NEXT:    tst.w r1, #16843009
-; V7M-NEXT:    itt ne
-; V7M-NEXT:    movne r0, #0
-; V7M-NEXT:    bxne lr
-; V7M-NEXT:  .LBB1_3: @ %D
-; V7M-NEXT:    movs r0, #1
+; V7M-NEXT:    bic r1, r1, #-16843010
+; V7M-NEXT:    clz r1, r1
+; V7M-NEXT:    lsrs r1, r1, #5
+; V7M-NEXT:    eors r0, r1
+; V7M-NEXT:    and r0, r0, #1
 ; V7M-NEXT:    bx lr
 ;
 ; V7A-LABEL: f0:
 ; V7A:       @ %bb.0: @ %E
 ; V7A-NEXT:    movw r2, #257
-; V7A-NEXT:    tst r0, #1
 ; V7A-NEXT:    movt r2, #257
 ; V7A-NEXT:    and r1, r1, r2
-; V7A-NEXT:    beq .LBB1_3
-; V7A-NEXT:  @ %bb.1: @ %A
-; V7A-NEXT:    cmp r1, #0
-; V7A-NEXT:    moveq r0, #0
-; V7A-NEXT:    bxeq lr
-; V7A-NEXT:  .LBB1_2: @ %D
-; V7A-NEXT:    mov r0, #1
-; V7A-NEXT:    bx lr
-; V7A-NEXT:  .LBB1_3: @ %B
-; V7A-NEXT:    mov r0, #0
-; V7A-NEXT:    cmp r1, #0
-; V7A-NEXT:    moveq r0, #1
+; V7A-NEXT:    clz r1, r1
+; V7A-NEXT:    lsr r1, r1, #5
+; V7A-NEXT:    eor r0, r0, r1
+; V7A-NEXT:    and r0, r0, #1
 ; V7A-NEXT:    bx lr
 ;
 ; V7A-T-LABEL: f0:
 ; V7A-T:       @ %bb.0: @ %E
-; V7A-T-NEXT:    lsls r0, r0, #31
-; V7A-T-NEXT:    beq .LBB1_2
-; V7A-T-NEXT:  @ %bb.1: @ %A
-; V7A-T-NEXT:    tst.w r1, #16843009
-; V7A-T-NEXT:    itt eq
-; V7A-T-NEXT:    moveq r0, #0
-; V7A-T-NEXT:    bxeq lr
-; V7A-T-NEXT:    b .LBB1_3
-; V7A-T-NEXT:  .LBB1_2: @ %B
-; V7A-T-NEXT:    tst.w r1, #16843009
-; V7A-T-NEXT:    itt ne
-; V7A-T-NEXT:    movne r0, #0
-; V7A-T-NEXT:    bxne lr
-; V7A-T-NEXT:  .LBB1_3: @ %D
-; V7A-T-NEXT:    movs r0, #1
+; V7A-T-NEXT:    bic r1, r1, #-16843010
+; V7A-T-NEXT:    clz r1, r1
+; V7A-T-NEXT:    lsrs r1, r1, #5
+; V7A-T-NEXT:    eors r0, r1
+; V7A-T-NEXT:    and r0, r0, #1
 ; V7A-T-NEXT:    bx lr
 ;
 ; V6M-LABEL: f0:
@@ -297,57 +268,29 @@ X:
 define i32 @f1(i1 %c0, i32 %v) {
 ; V7M-LABEL: f1:
 ; V7M:       @ %bb.0: @ %E
-; V7M-NEXT:    lsls r0, r0, #31
-; V7M-NEXT:    beq .LBB2_2
-; V7M-NEXT:  @ %bb.1: @ %A
-; V7M-NEXT:    tst.w r1, #100663296
-; V7M-NEXT:    itt eq
-; V7M-NEXT:    moveq r0, #0
-; V7M-NEXT:    bxeq lr
-; V7M-NEXT:    b .LBB2_3
-; V7M-NEXT:  .LBB2_2: @ %B
-; V7M-NEXT:    tst.w r1, #100663296
-; V7M-NEXT:    itt ne
-; V7M-NEXT:    movne r0, #0
-; V7M-NEXT:    bxne lr
-; V7M-NEXT:  .LBB2_3: @ %D
-; V7M-NEXT:    movs r0, #1
+; V7M-NEXT:    and r1, r1, #100663296
+; V7M-NEXT:    clz r1, r1
+; V7M-NEXT:    lsrs r1, r1, #5
+; V7M-NEXT:    eors r0, r1
+; V7M-NEXT:    and r0, r0, #1
 ; V7M-NEXT:    bx lr
 ;
 ; V7A-LABEL: f1:
 ; V7A:       @ %bb.0: @ %E
-; V7A-NEXT:    tst r0, #1
-; V7A-NEXT:    beq .LBB2_3
-; V7A-NEXT:  @ %bb.1: @ %A
-; V7A-NEXT:    tst r1, #100663296
-; V7A-NEXT:    moveq r0, #0
-; V7A-NEXT:    bxeq lr
-; V7A-NEXT:  .LBB2_2: @ %D
-; V7A-NEXT:    mov r0, #1
-; V7A-NEXT:    bx lr
-; V7A-NEXT:  .LBB2_3: @ %B
-; V7A-NEXT:    mov r0, #0
-; V7A-NEXT:    tst r1, #100663296
-; V7A-NEXT:    moveq r0, #1
+; V7A-NEXT:    and r1, r1, #100663296
+; V7A-NEXT:    clz r1, r1
+; V7A-NEXT:    lsr r1, r1, #5
+; V7A-NEXT:    eor r0, r0, r1
+; V7A-NEXT:    and r0, r0, #1
 ; V7A-NEXT:    bx lr
 ;
 ; V7A-T-LABEL: f1:
 ; V7A-T:       @ %bb.0: @ %E
-; V7A-T-NEXT:    lsls r0, r0, #31
-; V7A-T-NEXT:    beq .LBB2_2
-; V7A-T-NEXT:  @ %bb.1: @ %A
-; V7A-T-NEXT:    tst.w r1, #100663296
-; V7A-T-NEXT:    itt eq
-; V7A-T-NEXT:    moveq r0, #0
-; V7A-T-NEXT:    bxeq lr
-; V7A-T-NEXT:    b .LBB2_3
-; V7A-T-NEXT:  .LBB2_2: @ %B
-; V7A-T-NEXT:    tst.w r1, #100663296
-; V7A-T-NEXT:    itt ne
-; V7A-T-NEXT:    movne r0, #0
-; V7A-T-NEXT:    bxne lr
-; V7A-T-NEXT:  .LBB2_3: @ %D
-; V7A-T-NEXT:    movs r0, #1
+; V7A-T-NEXT:    and r1, r1, #100663296
+; V7A-T-NEXT:    clz r1, r1
+; V7A-T-NEXT:    lsrs r1, r1, #5
+; V7A-T-NEXT:    eors r0, r1
+; V7A-T-NEXT:    and r0, r0, #1
 ; V7A-T-NEXT:    bx lr
 ;
 ; V6M-LABEL: f1:
diff --git a/llvm/test/Transforms/SimplifyCFG/branch-nested.ll b/llvm/test/Transforms/SimplifyCFG/branch-nested.ll
index 3f9b9ca14b6e2..e7192de91dcc4 100644
--- a/llvm/test/Transforms/SimplifyCFG/branch-nested.ll
+++ b/llvm/test/Transforms/SimplifyCFG/branch-nested.ll
@@ -5,11 +5,8 @@ define void @fold_nested_branch(i1 %cond1, i1 %cond2) {
 ; CHECK-LABEL: define void @fold_nested_branch(
 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]]
-; CHECK:       [[BB1]]:
-; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
-; CHECK:       [[BB2]]:
-; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4]], label %[[BB3]]
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[COND1]], [[COND2]]
+; CHECK-NEXT:    br i1 [[TMP0]], label %[[BB4:.*]], label %[[BB3:.*]]
 ; CHECK:       [[COMMON_RET:.*]]:
 ; CHECK-NEXT:    ret void
 ; CHECK:       [[BB3]]:
@@ -268,11 +265,8 @@ define void @fold_nested_branch_prof(i1 %cond1, i1 %cond2) {
 ; CHECK-LABEL: define void @fold_nested_branch_prof(
 ; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    br i1 [[COND1]], label %[[BB1:.*]], label %[[BB2:.*]], !prof [[PROF0:![0-9]+]]
-; CHECK:       [[BB1]]:
-; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1:![0-9]+]]
-; CHECK:       [[BB2]]:
-; CHECK-NEXT:    br i1 [[COND2]], label %[[BB4]], label %[[BB3]], !prof [[PROF2:![0-9]+]]
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[COND1]], [[COND2]]
+; CHECK-NEXT:    br i1 [[TMP0]], label %[[BB4:.*]], label %[[BB3:.*]], !prof [[PROF0:![0-9]+]]
 ; CHECK:       [[COMMON_RET:.*]]:
 ; CHECK-NEXT:    ret void
 ; CHECK:       [[BB3]]:
@@ -308,7 +302,5 @@ bb4:
 declare void @sideeffect1()
 declare void @sideeffect2()
 ;.
-; CHECK: [[PROF0]] = !{!"branch_weights", i32 1, i32 2}
-; CHECK: [[PROF1]] = !{!"branch_weights", i32 3, i32 4}
-; CHECK: [[PROF2]] = !{!"branch_weights", i32 5, i32 6}
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 14, i32 15}
 ;.

>From 16d017c4c8e44d6e9caec08b53bbda3b7c9567bf Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 30 Jun 2024 16:09:36 +0800
Subject: [PATCH 3/5] [SimplifyCFG] Fix ARM codegen tests. NFC.

---
 llvm/test/CodeGen/ARM/and-cmp0-sink.ll | 79 +++++++++++++++++++-------
 1 file changed, 58 insertions(+), 21 deletions(-)

diff --git a/llvm/test/CodeGen/ARM/and-cmp0-sink.ll b/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
index 9c60f02dee881..eb12cba52732c 100644
--- a/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
+++ b/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
@@ -265,49 +265,85 @@ X:
 }
 
 ; Test with a mask that can be encoded both with T32 and A32 instruction sets.
-define i32 @f1(i1 %c0, i32 %v) {
+define i32 @f1(i1 %c0, i32 %v, ptr %p) {
 ; V7M-LABEL: f1:
 ; V7M:       @ %bb.0: @ %E
-; V7M-NEXT:    and r1, r1, #100663296
-; V7M-NEXT:    clz r1, r1
-; V7M-NEXT:    lsrs r1, r1, #5
-; V7M-NEXT:    eors r0, r1
-; V7M-NEXT:    and r0, r0, #1
+; V7M-NEXT:    lsls r0, r0, #31
+; V7M-NEXT:    beq .LBB2_2
+; V7M-NEXT:  @ %bb.1: @ %A
+; V7M-NEXT:    tst.w r1, #100663296
+; V7M-NEXT:    itt eq
+; V7M-NEXT:    moveq r0, #0
+; V7M-NEXT:    bxeq lr
+; V7M-NEXT:    b .LBB2_3
+; V7M-NEXT:  .LBB2_2: @ %B
+; V7M-NEXT:    movs r0, #1
+; V7M-NEXT:    tst.w r1, #100663296
+; V7M-NEXT:    str r0, [r2]
+; V7M-NEXT:    itt ne
+; V7M-NEXT:    movne r0, #0
+; V7M-NEXT:    bxne lr
+; V7M-NEXT:  .LBB2_3: @ %D
+; V7M-NEXT:    movs r0, #1
 ; V7M-NEXT:    bx lr
 ;
 ; V7A-LABEL: f1:
 ; V7A:       @ %bb.0: @ %E
-; V7A-NEXT:    and r1, r1, #100663296
-; V7A-NEXT:    clz r1, r1
-; V7A-NEXT:    lsr r1, r1, #5
-; V7A-NEXT:    eor r0, r0, r1
-; V7A-NEXT:    and r0, r0, #1
+; V7A-NEXT:    tst r0, #1
+; V7A-NEXT:    beq .LBB2_3
+; V7A-NEXT:  @ %bb.1: @ %A
+; V7A-NEXT:    tst r1, #100663296
+; V7A-NEXT:    moveq r0, #0
+; V7A-NEXT:    bxeq lr
+; V7A-NEXT:  .LBB2_2: @ %D
+; V7A-NEXT:    mov r0, #1
+; V7A-NEXT:    bx lr
+; V7A-NEXT:  .LBB2_3: @ %B
+; V7A-NEXT:    mov r0, #1
+; V7A-NEXT:    tst r1, #100663296
+; V7A-NEXT:    str r0, [r2]
+; V7A-NEXT:    mov r0, #0
+; V7A-NEXT:    moveq r0, #1
 ; V7A-NEXT:    bx lr
 ;
 ; V7A-T-LABEL: f1:
 ; V7A-T:       @ %bb.0: @ %E
-; V7A-T-NEXT:    and r1, r1, #100663296
-; V7A-T-NEXT:    clz r1, r1
-; V7A-T-NEXT:    lsrs r1, r1, #5
-; V7A-T-NEXT:    eors r0, r1
-; V7A-T-NEXT:    and r0, r0, #1
+; V7A-T-NEXT:    lsls r0, r0, #31
+; V7A-T-NEXT:    beq .LBB2_2
+; V7A-T-NEXT:  @ %bb.1: @ %A
+; V7A-T-NEXT:    tst.w r1, #100663296
+; V7A-T-NEXT:    itt eq
+; V7A-T-NEXT:    moveq r0, #0
+; V7A-T-NEXT:    bxeq lr
+; V7A-T-NEXT:    b .LBB2_3
+; V7A-T-NEXT:  .LBB2_2: @ %B
+; V7A-T-NEXT:    movs r0, #1
+; V7A-T-NEXT:    tst.w r1, #100663296
+; V7A-T-NEXT:    str r0, [r2]
+; V7A-T-NEXT:    itt ne
+; V7A-T-NEXT:    movne r0, #0
+; V7A-T-NEXT:    bxne lr
+; V7A-T-NEXT:  .LBB2_3: @ %D
+; V7A-T-NEXT:    movs r0, #1
 ; V7A-T-NEXT:    bx lr
 ;
 ; V6M-LABEL: f1:
 ; V6M:       @ %bb.0: @ %E
-; V6M-NEXT:    movs r2, #3
-; V6M-NEXT:    lsls r2, r2, #25
-; V6M-NEXT:    ands r2, r1
+; V6M-NEXT:    movs r3, #3
+; V6M-NEXT:    lsls r3, r3, #25
+; V6M-NEXT:    ands r3, r1
 ; V6M-NEXT:    lsls r0, r0, #31
 ; V6M-NEXT:    beq .LBB2_3
 ; V6M-NEXT:  @ %bb.1: @ %A
-; V6M-NEXT:    cmp r2, #0
+; V6M-NEXT:    cmp r3, #0
 ; V6M-NEXT:    bne .LBB2_5
 ; V6M-NEXT:  @ %bb.2:
 ; V6M-NEXT:    movs r0, #0
 ; V6M-NEXT:    bx lr
 ; V6M-NEXT:  .LBB2_3: @ %B
-; V6M-NEXT:    cmp r2, #0
+; V6M-NEXT:    movs r0, #1
+; V6M-NEXT:    str r0, [r2]
+; V6M-NEXT:    cmp r3, #0
 ; V6M-NEXT:    beq .LBB2_5
 ; V6M-NEXT:  @ %bb.4:
 ; V6M-NEXT:    movs r0, #0
@@ -325,6 +361,7 @@ A:
 
 B:
   %c2 = icmp eq i32 %a, 0
+  store i32 1, ptr %p, align 4
   br i1 %c2, label %D, label %C
 
 C:

>From 72a27eabe3edf57cc0566413f2be57dbfa383a09 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 30 Jun 2024 16:19:38 +0800
Subject: [PATCH 4/5] [SimplifyCFG] Fix ARM codegen tests. NFC.

---
 llvm/test/CodeGen/ARM/and-cmp0-sink.ll | 82 +++++++++++++++++++-------
 1 file changed, 60 insertions(+), 22 deletions(-)

diff --git a/llvm/test/CodeGen/ARM/and-cmp0-sink.ll b/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
index eb12cba52732c..fb9139c0d1285 100644
--- a/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
+++ b/llvm/test/CodeGen/ARM/and-cmp0-sink.ll
@@ -186,50 +186,87 @@ exit:
 }
 
 ; Test with a mask that can be encoded with T32 instruction set, but not with A32.
-define i32 @f0(i1 %c0, i32 %v) {
+define i32 @f0(i1 %c0, i32 %v, ptr %p) {
 ; V7M-LABEL: f0:
 ; V7M:       @ %bb.0: @ %E
-; V7M-NEXT:    bic r1, r1, #-16843010
-; V7M-NEXT:    clz r1, r1
-; V7M-NEXT:    lsrs r1, r1, #5
-; V7M-NEXT:    eors r0, r1
-; V7M-NEXT:    and r0, r0, #1
+; V7M-NEXT:    lsls r0, r0, #31
+; V7M-NEXT:    beq .LBB1_2
+; V7M-NEXT:  @ %bb.1: @ %A
+; V7M-NEXT:    tst.w r1, #16843009
+; V7M-NEXT:    itt eq
+; V7M-NEXT:    moveq r0, #0
+; V7M-NEXT:    bxeq lr
+; V7M-NEXT:    b .LBB1_3
+; V7M-NEXT:  .LBB1_2: @ %B
+; V7M-NEXT:    movs r0, #1
+; V7M-NEXT:    tst.w r1, #16843009
+; V7M-NEXT:    str r0, [r2]
+; V7M-NEXT:    itt ne
+; V7M-NEXT:    movne r0, #0
+; V7M-NEXT:    bxne lr
+; V7M-NEXT:  .LBB1_3: @ %D
+; V7M-NEXT:    movs r0, #1
 ; V7M-NEXT:    bx lr
 ;
 ; V7A-LABEL: f0:
 ; V7A:       @ %bb.0: @ %E
-; V7A-NEXT:    movw r2, #257
-; V7A-NEXT:    movt r2, #257
-; V7A-NEXT:    and r1, r1, r2
-; V7A-NEXT:    clz r1, r1
-; V7A-NEXT:    lsr r1, r1, #5
-; V7A-NEXT:    eor r0, r0, r1
-; V7A-NEXT:    and r0, r0, #1
+; V7A-NEXT:    movw r3, #257
+; V7A-NEXT:    tst r0, #1
+; V7A-NEXT:    movt r3, #257
+; V7A-NEXT:    and r1, r1, r3
+; V7A-NEXT:    beq .LBB1_3
+; V7A-NEXT:  @ %bb.1: @ %A
+; V7A-NEXT:    cmp r1, #0
+; V7A-NEXT:    moveq r0, #0
+; V7A-NEXT:    bxeq lr
+; V7A-NEXT:  .LBB1_2: @ %D
+; V7A-NEXT:    mov r0, #1
+; V7A-NEXT:    bx lr
+; V7A-NEXT:  .LBB1_3: @ %B
+; V7A-NEXT:    mov r0, #1
+; V7A-NEXT:    cmp r1, #0
+; V7A-NEXT:    str r0, [r2]
+; V7A-NEXT:    mov r0, #0
+; V7A-NEXT:    moveq r0, #1
 ; V7A-NEXT:    bx lr
 ;
 ; V7A-T-LABEL: f0:
 ; V7A-T:       @ %bb.0: @ %E
-; V7A-T-NEXT:    bic r1, r1, #-16843010
-; V7A-T-NEXT:    clz r1, r1
-; V7A-T-NEXT:    lsrs r1, r1, #5
-; V7A-T-NEXT:    eors r0, r1
-; V7A-T-NEXT:    and r0, r0, #1
+; V7A-T-NEXT:    lsls r0, r0, #31
+; V7A-T-NEXT:    beq .LBB1_2
+; V7A-T-NEXT:  @ %bb.1: @ %A
+; V7A-T-NEXT:    tst.w r1, #16843009
+; V7A-T-NEXT:    itt eq
+; V7A-T-NEXT:    moveq r0, #0
+; V7A-T-NEXT:    bxeq lr
+; V7A-T-NEXT:    b .LBB1_3
+; V7A-T-NEXT:  .LBB1_2: @ %B
+; V7A-T-NEXT:    movs r0, #1
+; V7A-T-NEXT:    tst.w r1, #16843009
+; V7A-T-NEXT:    str r0, [r2]
+; V7A-T-NEXT:    itt ne
+; V7A-T-NEXT:    movne r0, #0
+; V7A-T-NEXT:    bxne lr
+; V7A-T-NEXT:  .LBB1_3: @ %D
+; V7A-T-NEXT:    movs r0, #1
 ; V7A-T-NEXT:    bx lr
 ;
 ; V6M-LABEL: f0:
 ; V6M:       @ %bb.0: @ %E
-; V6M-NEXT:    ldr r2, .LCPI1_0
-; V6M-NEXT:    ands r2, r1
+; V6M-NEXT:    ldr r3, .LCPI1_0
+; V6M-NEXT:    ands r3, r1
 ; V6M-NEXT:    lsls r0, r0, #31
 ; V6M-NEXT:    beq .LBB1_3
 ; V6M-NEXT:  @ %bb.1: @ %A
-; V6M-NEXT:    cmp r2, #0
+; V6M-NEXT:    cmp r3, #0
 ; V6M-NEXT:    bne .LBB1_5
 ; V6M-NEXT:  @ %bb.2:
 ; V6M-NEXT:    movs r0, #0
 ; V6M-NEXT:    bx lr
 ; V6M-NEXT:  .LBB1_3: @ %B
-; V6M-NEXT:    cmp r2, #0
+; V6M-NEXT:    movs r0, #1
+; V6M-NEXT:    str r0, [r2]
+; V6M-NEXT:    cmp r3, #0
 ; V6M-NEXT:    beq .LBB1_5
 ; V6M-NEXT:  @ %bb.4:
 ; V6M-NEXT:    movs r0, #0
@@ -251,6 +288,7 @@ A:
 
 B:
   %c2 = icmp eq i32 %a, 0
+  store i32 1, ptr %p, align 4
   br i1 %c2, label %D, label %C
 
 C:

>From f321880cadb102bf082077c81b7764d634335f70 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 1 Jul 2024 00:30:07 +0800
Subject: [PATCH 5/5] [SimplifyCFG] Add more tests. NFC.

---
 .../Transforms/SimplifyCFG/branch-nested.ll   | 45 +++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/llvm/test/Transforms/SimplifyCFG/branch-nested.ll b/llvm/test/Transforms/SimplifyCFG/branch-nested.ll
index e7192de91dcc4..13218e6d2049c 100644
--- a/llvm/test/Transforms/SimplifyCFG/branch-nested.ll
+++ b/llvm/test/Transforms/SimplifyCFG/branch-nested.ll
@@ -34,6 +34,51 @@ bb4:
   ret void
 }
 
+define void @fold_nested_branch_extra_predecessors(i1 %cond0, i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: define void @fold_nested_branch_extra_predecessors(
+; CHECK-SAME: i1 [[COND0:%.*]], i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[COND0]], label %[[BB0:.*]], label %[[BB1_PRED:.*]]
+; CHECK:       [[BB1_PRED]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BB3:.*]], label %[[BB4:.*]]
+; CHECK:       [[BB0]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = xor i1 [[COND1]], [[COND2]]
+; CHECK-NEXT:    br i1 [[TMP0]], label %[[BB4]], label %[[BB3]]
+; CHECK:       [[COMMON_RET:.*]]:
+; CHECK-NEXT:    ret void
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @sideeffect1()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+; CHECK:       [[BB4]]:
+; CHECK-NEXT:    call void @sideeffect2()
+; CHECK-NEXT:    br label %[[COMMON_RET]]
+;
+entry:
+  br i1 %cond0, label %bb0, label %bb1_pred
+
+bb1_pred:
+  call void @sideeffect1()
+  br label %bb1
+
+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:
+  call void @sideeffect1()
+  ret void
+
+bb4:
+  call void @sideeffect2()
+  ret void
+}
+
 ; Negative tests
 
 define void @fold_nested_branch_cfg_mismatch(i1 %cond1, i1 %cond2) {



More information about the llvm-commits mailing list