[llvm] [Transforms] Add DeadBranchElimination pass (PR #211176)
Yoni Peleg via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 06:58:41 PDT 2026
================
@@ -0,0 +1,408 @@
+//===- DeadBranchElimination.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass eliminates conditional branches that are unreachable but that
+// cannot be proven unreachable directly, because the branch body modifies the
+// very values its condition depends on. The motivating example:
+//
+// int a = 0, b = 0, limit = 100;
+// while (a < limit) {
+// if (b == limit) // Unreachable: a == b always, and a < limit here.
+// limit += 1; // ...but it modifies limit (circular dependency).
+// a++; b++;
+// }
+//
+// Proving the branch dead requires knowing limit is loop-invariant, which
+// requires knowing the branch is dead.
+//
+// The algorithm is an optimistic fixed point over the two bodies (true side,
+// false side) of every conditional branch. Each body starts as Unknown
+// ("assumed dead") and can only be promoted to ProvenReachable:
+//
+// 1. Materialize the assumption set in place (no cloning): PHI slots fed
+// by assumed-dead edges or assumed-unreachable regions are temporarily
+// overwritten with the surviving values (see AssumedDeadEdges), so the
+// assumed-dead bodies' effects vanish from the analysis.
+// 2. Run ScalarEvolution on the function in this state.
+// 3. For each Unknown body, check whether the analysis proves its branch
+// edge is never taken (context-sensitive SCEV proof, or the branch
+// sits in an assumed-dead region). If the edge cannot be proven dead,
+// mark it ProvenReachable; its body is restored for the next
+// iteration.
+// 4. Undo the PHI rewrites exactly and repeat until no status changes.
+// Statuses move in one direction only, so this terminates.
+//
+// At convergence the remaining Unknown set is self-consistent: assuming
+// those bodies never run, the analysis proves they indeed never run
+// (consider the first time one would run -- up to that point the rewritten
+// values match the real execution, and the analysis proves the edge is not
+// taken). Those branches are then folded.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Scalar/DeadBranchElimination.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassInstrumentation.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Transforms/Utils/Local.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "dead-branch-elim"
+
+STATISTIC(NumBranchesFolded, "Number of provably dead branch edges folded");
+
+static cl::opt<unsigned> MaxRefineIterations(
+ "dbe-max-iterations", cl::init(8), cl::Hidden,
----------------
yonipeleg33 wrote:
How was 8 chosen? Can you share the justification behind this number?
I (unfortunately) witnessed function bodies with dozens to hundreds of scopes in them. Now, it doesn't mean that _necessarily_ 8 iterations won't be enough (e.g. if all are reachable 1 iteration will already reach the fixed point), but I can imagine cases where it won't be sufficient.
Are you intentionally leaving those cases on the table? Why?
https://github.com/llvm/llvm-project/pull/211176
More information about the llvm-commits
mailing list