[llvm] [InstCombine] Push freeze through non-recurrence PHIs (PR #157678)

David Sherwood via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 23 05:36:43 PDT 2025


================
@@ -5042,10 +5042,33 @@ InstCombinerImpl::pushFreezeToPreventPoisonFromPropagating(FreezeInst &OrigFI) {
   //   Op1.fr = Freeze(Op1)
   //   ... = Inst(Op1.fr, NonPoisonOps...)
 
-  auto CanPushFreeze = [](Value *V) {
-    if (!isa<Instruction>(V) || isa<PHINode>(V))
+  auto CanPushFreeze = [this](Value *V) {
+    if (!isa<Instruction>(V))
       return false;
 
+    if (auto *PN = dyn_cast<PHINode>(V)) {
+      BasicBlock *BB = PN->getParent();
+      SmallPtrSet<BasicBlock *, 8> VisitedBBs;
+      for (Use &U : PN->incoming_values()) {
+        BasicBlock *InBB = PN->getIncomingBlock(U);
+        // We can't move freeze if the start value is the result of a
+        // terminator (e.g. an invoke).
+        if (auto *OpI = dyn_cast<Instruction>(U)) {
+          if (OpI->isTerminator())
+            return false;
+        }
+
+        // If there's multiple incoming edges from the same predecessor we must
+        // ensure the freeze isn't pushed to a single one of the uses,
+        // invalidating the iterator. We simply don't support this case, but it
+        // could be handled if there's a use case.
+        if (isBackEdge(InBB, BB) || !VisitedBBs.insert(InBB).second ||
+            match(U.get(), m_Undef()))
----------------
david-arm wrote:

I guess in theory we could push the freeze to an undef argument, right? I noticed that this IR:

```
define i64 @foo() {
entry:
  %res = freeze i64 undef
  ret i64 %res
}
```

gets optimised by instcombine to just

```
define i64 @foo() {
entry:
  ret i64 0
}
```

but this could be done in a later patch if we see a need for it.

https://github.com/llvm/llvm-project/pull/157678


More information about the llvm-commits mailing list