[llvm] [SimplifyCFG] Simplify conditional branches on const icmp eq's (PR #73334)

via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 24 06:44:17 PST 2023


https://github.com/yonillasky created https://github.com/llvm/llvm-project/pull/73334

The issue that is being addressed here is shown in the `@ intersection_block_with_dead_predecessor` test.

Before this fix, what happens there is that:
- SimplifyCFG converts the switch instruction into a conditional branch (on the PHI value)
- SimplifyCFG identifies the block `%a` is dead, and deletes it
- PHI decays into a constant
- The condition of the conditional branch is now a compile-time constant, so one of the outgoing edges is dead, but no further simplification is performed (though here, for instance, `%c` is a dead block)

I am fixing that, by explicitly doing the necessary constant-folding for this specific case.

>From b2af341f9e5bcb8c297595051e82437c572155c9 Mon Sep 17 00:00:00 2001
From: Yoni Lavi <yoni.lavi at nextsilicon.com>
Date: Fri, 24 Nov 2023 16:25:19 +0200
Subject: [PATCH] [SimplifyCFG] Simplify conditional branches on const icmp
 eq's

---
 llvm/lib/Transforms/Utils/SimplifyCFG.cpp     | 18 +++++++
 .../SimplifyCFG/constant-valued-cond-br.ll    | 47 +++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 llvm/test/Transforms/SimplifyCFG/constant-valued-cond-br.ll

diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 3bcd896639a8ec2..2fe0c281662aa36 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -3578,6 +3578,13 @@ static bool FoldTwoEntryPHINode(PHINode *PN, const TargetTransformInfo &TTI,
   return true;
 }
 
+static BranchInst *decayCondBranchToUncondBranch(IRBuilderBase &Builder, BranchInst *BI, bool Eval) {
+  unsigned SuccessorIdx = (Eval) ? 0 : 1;
+  auto *NewBI = Builder.CreateBr(BI->getSuccessor(SuccessorIdx));
+  BI->eraseFromParent();
+  return NewBI;
+}
+
 static Value *createLogicalOp(IRBuilderBase &Builder,
                               Instruction::BinaryOps Opc, Value *LHS,
                               Value *RHS, const Twine &Name = "") {
@@ -7325,6 +7332,17 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
           if (mergeConditionalStores(PBI, BI, DTU, DL, TTI))
             return requestResimplify();
 
+  // Check if the condition is an equality between two constants. This can form due to other
+  // CFGSimplify steps, and may prevent further simplification if we don't deal with it here.
+  if (auto ICmp = dyn_cast<ICmpInst>(BI->getCondition()))
+    if (ICmp->getPredicate() == CmpInst::ICMP_EQ)
+      if (auto *LHS = dyn_cast<ConstantInt>(ICmp->getOperand(0)))
+        if (auto *RHS = dyn_cast<ConstantInt>(ICmp->getOperand(1))) {
+          bool CondEval = LHS->getZExtValue() == RHS->getZExtValue();
+          decayCondBranchToUncondBranch(Builder, BI, CondEval);
+          return requestResimplify();
+        }
+
   return false;
 }
 
diff --git a/llvm/test/Transforms/SimplifyCFG/constant-valued-cond-br.ll b/llvm/test/Transforms/SimplifyCFG/constant-valued-cond-br.ll
new file mode 100644
index 000000000000000..51262dab3ab0436
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/constant-valued-cond-br.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
+; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
+
+define void @const_valued_cond_br(ptr %P) {
+; CHECK-LABEL: define void @const_valued_cond_br(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 42, 42
+; CHECK-NEXT:    store i32 123, ptr [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+entry:
+  %cond = icmp eq i32 42, 42
+  br i1 %cond, label %a, label %b
+a:
+  store i32 123, ptr %P
+  br label %b
+b:
+  ret void
+}
+
+
+
+define void @intersection_block_with_dead_predecessor(ptr %P) {
+; CHECK-LABEL: define void @intersection_block_with_dead_predecessor(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 1, 1
+; CHECK-NEXT:    store i32 321, ptr [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+entry:
+  br label %b
+b:
+  %x = phi i32 [1, %entry], [2, %a]
+  switch i32 %x, label %c [
+  i32 1, label %d
+  ]
+c:
+  store i32 123, ptr %P
+  ret void
+d:
+  store i32 321, ptr %P
+  ret void
+a: ; unreachable
+  br label %b
+}



More information about the llvm-commits mailing list