[llvm] [SimplifyCFG] Removed the conditional branch (PR #146445)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 30 19:22:48 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: David Zheng (davidzhengyes)
<details>
<summary>Changes</summary>
This pull request responds to my issue #<!-- -->146442. I track StronglyKnownValues in an unordered_set, meaning that we can determine the value on the edge, and also that value is an instruction that belongs to the `From` basic block.
---
Full diff: https://github.com/llvm/llvm-project/pull/146445.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Utils/SimplifyCFG.cpp (+34-6)
- (added) llvm/test/Transforms/SimplifyCFG/EliminateDeadPhi.ll (+74)
``````````diff
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 147d2060e8509..fb54b854c6da5 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -87,6 +87,7 @@
#include <optional>
#include <set>
#include <tuple>
+#include <unordered_set>
#include <utility>
#include <vector>
@@ -3436,7 +3437,7 @@ static bool blockIsSimpleEnoughToThreadThrough(BasicBlock *BB) {
}
static ConstantInt *getKnownValueOnEdge(Value *V, BasicBlock *From,
- BasicBlock *To) {
+ BasicBlock *To, bool Strong = false) {
// Don't look past the block defining the value, we might get the value from
// a previous loop iteration.
auto *I = dyn_cast<Instruction>(V);
@@ -3446,10 +3447,18 @@ static ConstantInt *getKnownValueOnEdge(Value *V, BasicBlock *From,
// We know the value if the From block branches on it.
auto *BI = dyn_cast<BranchInst>(From->getTerminator());
if (BI && BI->isConditional() && BI->getCondition() == V &&
- BI->getSuccessor(0) != BI->getSuccessor(1))
- return BI->getSuccessor(0) == To ? ConstantInt::getTrue(BI->getContext())
- : ConstantInt::getFalse(BI->getContext());
-
+ BI->getSuccessor(0) != BI->getSuccessor(1)) {
+ ConstantInt *KnownValue =
+ BI->getSuccessor(0) == To ? ConstantInt::getTrue(BI->getContext())
+ : ConstantInt::getFalse(BI->getContext());
+ if (Strong) {
+ Value *Cond = BI->getCondition();
+ Instruction *CondInst = dyn_cast<Instruction>(Cond);
+ return (CondInst && CondInst->getParent() == From) ? KnownValue : nullptr;
+ } else {
+ return KnownValue;
+ }
+ }
return nullptr;
}
@@ -3461,6 +3470,7 @@ foldCondBranchOnValueKnownInPredecessorImpl(BranchInst *BI, DomTreeUpdater *DTU,
const DataLayout &DL,
AssumptionCache *AC) {
SmallMapVector<ConstantInt *, SmallSetVector<BasicBlock *, 2>, 2> KnownValues;
+ std::unordered_set<ConstantInt *> StronglyKnownValues;
BasicBlock *BB = BI->getParent();
Value *Cond = BI->getCondition();
PHINode *PN = dyn_cast<PHINode>(Cond);
@@ -3476,8 +3486,12 @@ foldCondBranchOnValueKnownInPredecessorImpl(BranchInst *BI, DomTreeUpdater *DTU,
KnownValues[CB].insert(PN->getIncomingBlock(U));
} else {
for (BasicBlock *Pred : predecessors(BB)) {
- if (ConstantInt *CB = getKnownValueOnEdge(Cond, Pred, BB))
+ if (ConstantInt *CB = getKnownValueOnEdge(Cond, Pred, BB)) {
KnownValues[CB].insert(Pred);
+ if (getKnownValueOnEdge(Cond, Pred, BB, true)) {
+ StronglyKnownValues.insert(CB);
+ }
+ }
}
}
@@ -3593,11 +3607,20 @@ foldCondBranchOnValueKnownInPredecessorImpl(BranchInst *BI, DomTreeUpdater *DTU,
BranchInst *EdgeBI = cast<BranchInst>(EdgeBB->getTerminator());
EdgeBI->setSuccessor(0, RealDest);
EdgeBI->setDebugLoc(BI->getDebugLoc());
+
+ bool RemoveCondBr = StronglyKnownValues.count(CB);
+ if (RemoveCondBr) {
+ RealDest->removePredecessor(BB);
+ ReplaceInstWithInst(BI, BranchInst::Create(BI->getSuccessor(CB->getZExtValue())));
+ }
if (DTU) {
SmallVector<DominatorTree::UpdateType, 2> Updates;
Updates.push_back({DominatorTree::Delete, EdgeBB, BB});
Updates.push_back({DominatorTree::Insert, EdgeBB, RealDest});
+ if (RemoveCondBr) {
+ Updates.push_back({DominatorTree::Delete, BB, RealDest});
+ }
DTU->applyUpdates(Updates);
}
@@ -3607,6 +3630,11 @@ foldCondBranchOnValueKnownInPredecessorImpl(BranchInst *BI, DomTreeUpdater *DTU,
// bypass the check for trivial cycles above.
MergeBlockIntoPredecessor(EdgeBB, DTU);
+ // If we remove the conditional branch, cannot keep simplifying.
+ if (RemoveCondBr) {
+ return true;
+ }
+
// Signal repeat, simplifying any other constants.
return std::nullopt;
}
diff --git a/llvm/test/Transforms/SimplifyCFG/EliminateDeadPhi.ll b/llvm/test/Transforms/SimplifyCFG/EliminateDeadPhi.ll
new file mode 100644
index 0000000000000..2877d759b4940
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/EliminateDeadPhi.ll
@@ -0,0 +1,74 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=simplifycfg -S | FileCheck %s
+
+
+define void @mainfunc(i16 %0) {
+; CHECK-LABEL: define void @mainfunc(
+; CHECK-SAME: i16 [[TMP0:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i16 [[TMP0]], 10
+; CHECK-NEXT: br i1 [[TMP1]], label %[[OTHERLOOPEND:.*]], label %[[FOR_BODY_CRITEDGE:.*]]
+; CHECK: [[OTHERLOOPEND]]:
+; CHECK-NEXT: [[OTHERLOOPIV:%.*]] = call i16 @ivfunc()
+; CHECK-NEXT: [[OTHERLOOPPRED:%.*]] = icmp slt i16 [[OTHERLOOPIV]], 100
+; CHECK-NEXT: br i1 [[OTHERLOOPPRED]], label %[[OTHERLOOPEND]], label %[[VADDEXIT:.*]]
+; CHECK: [[VADDEXIT]]:
+; CHECK-NEXT: call void @voidfunc()
+; CHECK-NEXT: br label %[[END:.*]]
+; CHECK: [[FOR_BODY_CRITEDGE]]:
+; CHECK-NEXT: call void @voidfunc()
+; CHECK-NEXT: br label %[[FOR_BODY:.*]]
+; CHECK: [[FOR_BODY]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i16 [ [[IV_NEXT:%.*]], %[[FOR_BODY]] ], [ 0, %[[FOR_BODY_CRITEDGE]] ]
+; CHECK-NEXT: [[VAL:%.*]] = tail call <256 x i1> @helperfunc()
+; CHECK-NEXT: [[VAL2:%.*]] = tail call <1 x i32> @helperfunc2()
+; CHECK-NEXT: [[IV_NEXT]] = add i16 [[IV]], 1
+; CHECK-NEXT: [[PRED:%.*]] = icmp slt i16 [[IV_NEXT]], 100
+; CHECK-NEXT: br i1 [[PRED]], label %[[FOR_BODY]], label %[[END]]
+; CHECK: [[END]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %otherlooppreheader
+
+otherlooppreheader:
+ %1 = icmp ugt i16 %0, 10
+ br i1 %1, label %otherloopend, label %VAddExit
+
+otherloopend:
+ %otherloopiv = call i16 @ivfunc()
+ %otherLoopPred = icmp slt i16 %otherloopiv, 100
+ br i1 %otherLoopPred, label %otherloopend, label %VAddExit
+
+
+VAddExit:
+ call void @voidfunc()
+ br i1 %1, label %end, label %for.body
+
+for.body:
+ %iv = phi i16 [ %iv.next, %VMulExit ], [ 0, %VAddExit ]
+ %val = tail call <256 x i1> @helperfunc()
+ br label %for.body.inner
+
+for.body.inner:
+ %val2 = tail call <1 x i32> @helperfunc2()
+ br label %VMulExit
+
+VMulExit:
+ %iv.next = add i16 %iv, 1
+ %pred = icmp slt i16 %iv.next, 100
+ br i1 %pred, label %for.body, label %end
+
+end:
+ ret void
+
+}
+
+
+declare i16 @ivfunc()
+
+declare <256 x i1> @helperfunc()
+
+declare <1 x i32> @helperfunc2()
+
+declare void @voidfunc()
``````````
</details>
https://github.com/llvm/llvm-project/pull/146445
More information about the llvm-commits
mailing list