[llvm] [CloneFunction] Fix non-deterministic PHI cleanup using PHINode::removeIncomingValueIf() (PR #173975)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 30 03:45:04 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Mingjie Xu (Enna1)
<details>
<summary>Changes</summary>
Previously, we use `std::map<BasicBlock *, unsigned> PredCount` to track excess incoming blocks and removed them one by one using `removeIncomingValue`. then we remove the excess incoming blocks one by one.
Since `PredCount` use `BasicBlock *` as key, the iteration order depends on the memory addresses of the blocks. With `PHINode::removeIncomingValue()` changed to use the swapping strategy, the order in which operands are removed affects the final order of the remaining operands in the PHI node. This will cause non-determinism in compiles.
This patch uses `PHINode::removeIncomingValueIf()` to remove invalid incoming blocks that no longer go to `NewBB` block, fixes the non-determinism.
---
Full diff: https://github.com/llvm/llvm-project/pull/173975.diff
1 Files Affected:
- (modified) llvm/lib/Transforms/Utils/CloneFunction.cpp (+9-16)
``````````diff
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index 1d0244c54a282..8ccbc33915d06 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -810,24 +810,17 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
NumPreds = pred_size(NewBB);
if (NumPreds != PN->getNumIncomingValues()) {
assert(NumPreds < PN->getNumIncomingValues());
- // Count how many times each predecessor comes to this block.
- std::map<BasicBlock *, unsigned> PredCount;
- for (BasicBlock *Pred : predecessors(NewBB))
- --PredCount[Pred];
-
- // Figure out how many entries to remove from each PHI.
- for (BasicBlock *Pred : PN->blocks())
- ++PredCount[Pred];
-
- // At this point, the excess predecessor entries are positive in the
- // map. Loop over all of the PHIs and remove excess predecessor
- // entries.
+ SmallPtrSet<BasicBlock *, 4> NewBBPreds(llvm::from_range,
+ predecessors(NewBB));
+
BasicBlock::iterator I = NewBB->begin();
for (; (PN = dyn_cast<PHINode>(I)); ++I) {
- for (const auto &[Pred, Count] : PredCount) {
- for ([[maybe_unused]] unsigned _ : llvm::seq<unsigned>(Count))
- PN->removeIncomingValue(Pred, false);
- }
+ PN->removeIncomingValueIf(
+ [&](unsigned Idx) {
+ BasicBlock *IncomingBlock = PN->getIncomingBlock(Idx);
+ return !NewBBPreds.contains(IncomingBlock);
+ },
+ false);
}
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/173975
More information about the llvm-commits
mailing list