[llvm] [JumpThreading] Refractor redirectValuesFromPredecessorsToPhi: avoid unnecessary map resizing in gatherIncomingValuesToPhi (PR #173596)

via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 30 04:00:15 PST 2025


https://github.com/int-zjt updated https://github.com/llvm/llvm-project/pull/173596

>From 9958963e59d13b90179c87151d3ef23c3ab3a465 Mon Sep 17 00:00:00 2001
From: "zhangjiatong.0" <zhangjiatong.0 at bytedance.com>
Date: Thu, 11 Dec 2025 19:48:27 +0800
Subject: [PATCH 1/4] [JumpThreading] Add fast path for single-pred blocks in
 redirectValuesFromPredecessorsToPhi

---
 llvm/lib/Transforms/Utils/Local.cpp | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index f7842a235b20d..9e5115d0b0795 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -1077,6 +1077,19 @@ static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
   Value *OldVal = PN->removeIncomingValue(BB, false);
   assert(OldVal && "No entry in PHI for Pred BB!");
 
+  // Fast path: If BB has a single predecessor and the incoming value is not
+  // defined in BB itself, we can directly redirect the edge.
+  //
+  // Note: We rely on TryToSimplifyUncondBranchFromEmptyBlock (the caller) to
+  // have already verified via CanPropagatePredecessorsForPHIs that merging
+  // blocks won't introduce value conflicts for any common predecessors.
+  auto *BBSinglePred = BB->getSinglePredecessor();
+  Instruction *OldInst = dyn_cast<Instruction>(OldVal);
+  if (BBSinglePred && OldInst && OldInst->getParent() != BB) {
+    PN->addIncoming(OldVal, BBSinglePred);
+    return;
+  }
+
   IncomingValueMap IncomingValues;
 
   // We are merging two blocks - BB, and the block containing PN - and

>From efc76213c515606b1264094132eccb22694c9635 Mon Sep 17 00:00:00 2001
From: "zhangjiatong.0" <zhangjiatong.0bytedance.com>
Date: Mon, 29 Dec 2025 14:19:30 +0800
Subject: [PATCH 2/4] Replace IncomingValues by a known value

---
 llvm/lib/Transforms/Utils/Local.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 9e5115d0b0795..60e89932ae1a7 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -1087,6 +1087,14 @@ static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
   Instruction *OldInst = dyn_cast<Instruction>(OldVal);
   if (BBSinglePred && OldInst && OldInst->getParent() != BB) {
     PN->addIncoming(OldVal, BBSinglePred);
+    
+    auto *knownDefine = OldVal;
+    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
+      if (PN->getIncomingBlock(i) == BBSinglePred && !isa<UndefValue>(PN->getIncomingValue(i)))
+        knownDefine = PN->getIncomingValue(i);
+    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
+      if (PN->getIncomingBlock(i) == BBSinglePred)
+        PN->setIncomingValue(i, knownDefine);
     return;
   }
 

>From 68feda8189e5ff16db983efccb01090bc5ade172 Mon Sep 17 00:00:00 2001
From: "zhangjiatong.0" <zhangjiatong.0bytedance.com>
Date: Mon, 29 Dec 2025 14:20:28 +0800
Subject: [PATCH 3/4] Format

---
 llvm/lib/Transforms/Utils/Local.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 60e89932ae1a7..1a00f9fd91ae7 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -1087,10 +1087,11 @@ static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
   Instruction *OldInst = dyn_cast<Instruction>(OldVal);
   if (BBSinglePred && OldInst && OldInst->getParent() != BB) {
     PN->addIncoming(OldVal, BBSinglePred);
-    
+
     auto *knownDefine = OldVal;
     for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
-      if (PN->getIncomingBlock(i) == BBSinglePred && !isa<UndefValue>(PN->getIncomingValue(i)))
+      if (PN->getIncomingBlock(i) == BBSinglePred &&
+          !isa<UndefValue>(PN->getIncomingValue(i)))
         knownDefine = PN->getIncomingValue(i);
     for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
       if (PN->getIncomingBlock(i) == BBSinglePred)

>From 6f5040509262dbef3867e7aafb3f2faf238d1e4a Mon Sep 17 00:00:00 2001
From: "zhangjiatong.0" <zhangjiatong.0bytedance.com>
Date: Mon, 29 Dec 2025 17:13:18 +0800
Subject: [PATCH 4/4] Refractor redirectValuesFromPredecessorsToPhi

---
 llvm/lib/Transforms/Utils/Local.cpp | 67 +++++++++++++----------------
 1 file changed, 31 insertions(+), 36 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 1a00f9fd91ae7..d01944b5d2efa 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -926,16 +926,18 @@ using IncomingValueMap = SmallDenseMap<BasicBlock *, Value *, 16>;
 static Value *selectIncomingValueForBlock(Value *OldVal, BasicBlock *BB,
                                           IncomingValueMap &IncomingValues) {
   if (!isa<UndefValue>(OldVal)) {
-    assert((!IncomingValues.count(BB) ||
-            IncomingValues.find(BB)->second == OldVal) &&
+    assert((IncomingValues.count(BB) &&
+            (isa<UndefValue>(IncomingValues.find(BB)->second) ||
+             IncomingValues.find(BB)->second == OldVal)) &&
            "Expected OldVal to match incoming value from BB!");
 
-    IncomingValues.insert(std::make_pair(BB, OldVal));
+    IncomingValues.insert_or_assign(BB, OldVal);
     return OldVal;
   }
 
   IncomingValueMap::const_iterator It = IncomingValues.find(BB);
-  if (It != IncomingValues.end()) return It->second;
+  if (It != IncomingValues.end() && !isa<UndefValue>(It->second))
+    return It->second;
 
   return OldVal;
 }
@@ -943,19 +945,30 @@ static Value *selectIncomingValueForBlock(Value *OldVal, BasicBlock *BB,
 /// Create a map from block to value for the operands of a
 /// given phi.
 ///
-/// Create a map from block to value for each non-undef value flowing
-/// into \p PN.
+/// This function initializes the map with UndefValue for all predecessors
+/// in BBPreds, and then updates the map with concrete non-undef values
+/// found in the PHI node.
 ///
 /// \param PN The phi we are collecting the map for.
+/// \param BBPreds The list of all predecessor blocks to initialize with Undef.
 /// \param IncomingValues [out] The map from block to value for this phi.
-static void gatherIncomingValuesToPhi(PHINode *PN,
-                                      IncomingValueMap &IncomingValues) {
+static void gatherIncomingValuesToPhi(llvm::PHINode *PN,
+                                      IncomingValueMap &IncomingValues,
+                                      const PredBlockVector &BBPreds) {
+  llvm::Value *Undef = llvm::UndefValue::get(PN->getType());
+  for (llvm::BasicBlock *Pred : BBPreds) {
+    IncomingValues[Pred] = Undef;
+  }
+
   for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
-    BasicBlock *BB = PN->getIncomingBlock(i);
-    Value *V = PN->getIncomingValue(i);
+    llvm::Value *V = PN->getIncomingValue(i);
+    if (llvm::isa<llvm::UndefValue>(V))
+      continue;
 
-    if (!isa<UndefValue>(V))
-      IncomingValues.insert(std::make_pair(BB, V));
+    llvm::BasicBlock *BB = PN->getIncomingBlock(i);
+    if (IncomingValues.count(BB)) {
+      IncomingValues[BB] = V;
+    }
   }
 }
 
@@ -974,12 +987,15 @@ static void replaceUndefValuesInPhi(PHINode *PN,
 
     BasicBlock *BB = PN->getIncomingBlock(i);
     IncomingValueMap::const_iterator It = IncomingValues.find(BB);
+    if (It == IncomingValues.end()) {
+      continue;
+    }
 
     // Keep track of undef/poison incoming values. Those must match, so we fix
     // them up below if needed.
     // Note: this is conservatively correct, but we could try harder and group
     // the undef values per incoming basic block.
-    if (It == IncomingValues.end()) {
+    if (isa<UndefValue>(It->second)) {
       TrueUndefOps.push_back(i);
       continue;
     }
@@ -1077,28 +1093,7 @@ static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
   Value *OldVal = PN->removeIncomingValue(BB, false);
   assert(OldVal && "No entry in PHI for Pred BB!");
 
-  // Fast path: If BB has a single predecessor and the incoming value is not
-  // defined in BB itself, we can directly redirect the edge.
-  //
-  // Note: We rely on TryToSimplifyUncondBranchFromEmptyBlock (the caller) to
-  // have already verified via CanPropagatePredecessorsForPHIs that merging
-  // blocks won't introduce value conflicts for any common predecessors.
-  auto *BBSinglePred = BB->getSinglePredecessor();
-  Instruction *OldInst = dyn_cast<Instruction>(OldVal);
-  if (BBSinglePred && OldInst && OldInst->getParent() != BB) {
-    PN->addIncoming(OldVal, BBSinglePred);
-
-    auto *knownDefine = OldVal;
-    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
-      if (PN->getIncomingBlock(i) == BBSinglePred &&
-          !isa<UndefValue>(PN->getIncomingValue(i)))
-        knownDefine = PN->getIncomingValue(i);
-    for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
-      if (PN->getIncomingBlock(i) == BBSinglePred)
-        PN->setIncomingValue(i, knownDefine);
-    return;
-  }
-
+  // Map BBPreds to defined or undefined values in PN
   IncomingValueMap IncomingValues;
 
   // We are merging two blocks - BB, and the block containing PN - and
@@ -1110,7 +1105,7 @@ static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
   // values flowing into PN, we want to rewrite those values to be
   // consistent with the non-undef values.
 
-  gatherIncomingValuesToPhi(PN, IncomingValues);
+  gatherIncomingValuesToPhi(PN, IncomingValues, BBPreds);
 
   // If this incoming value is one of the PHI nodes in BB, the new entries
   // in the PHI node are the entries from the old PHI.



More information about the llvm-commits mailing list