[llvm] [InstCombine] Allow freezing multiple out-of-loop values (PR #155638)

Cullen Rhodes via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 27 08:27:31 PDT 2025


https://github.com/c-rhodes created https://github.com/llvm/llvm-project/pull/155638

Extend foldFreezeIntoRecurrence to allow freezing multiple out-of-loop values. This is following on from #154336, which recently made the same change for a wider set of ops.

>From f330a2889f2b82bb2d1e267a86c820da8537dbca Mon Sep 17 00:00:00 2001
From: Cullen Rhodes <cullen.rhodes at arm.com>
Date: Wed, 27 Aug 2025 10:46:37 +0000
Subject: [PATCH] [InstCombine] Allow freezing multiple out-of-loop values

Extend foldFreezeIntoRecurrence to allow freezing multiple out-of-loop
values. This is following on from #154336, which recently made the same
change for a wider set of ops.
---
 .../InstCombine/InstructionCombining.cpp      | 30 +++++++++----------
 llvm/test/Transforms/InstCombine/freeze.ll    |  7 +++--
 2 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 1c512ec1e21bb..e524839e2876e 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -5032,32 +5032,28 @@ Instruction *InstCombinerImpl::foldFreezeIntoRecurrence(FreezeInst &FI,
   // backedge values (possibly dropping poison flags along the way) until we
   // reach the phi again. In that case, we can move the freeze to the start
   // value.
-  Use *StartU = nullptr;
+  SmallVector<Use *> StartUses;
   SmallVector<Value *> Worklist;
   for (Use &U : PN->incoming_values()) {
-    if (DT.dominates(PN->getParent(), PN->getIncomingBlock(U))) {
+    BasicBlock *StartBB = PN->getIncomingBlock(U);
+    Value *StartV = U.get();
+    if (DT.dominates(PN->getParent(), StartBB)) {
       // Add backedge value to worklist.
-      Worklist.push_back(U.get());
+      Worklist.push_back(StartV);
       continue;
     }
 
-    // Don't bother handling multiple start values.
-    if (StartU)
+    bool StartNeedsFreeze = !isGuaranteedNotToBeUndefOrPoison(StartV);
+    // We can't insert freeze if a start value is the result of the
+    // terminator (e.g. an invoke).
+    if (StartNeedsFreeze && StartBB->getTerminator() == StartV)
       return nullptr;
-    StartU = &U;
+    StartUses.push_back(&U);
   }
 
-  if (!StartU || Worklist.empty())
+  if (StartUses.empty() || Worklist.empty())
     return nullptr; // Not a recurrence.
 
-  Value *StartV = StartU->get();
-  BasicBlock *StartBB = PN->getIncomingBlock(*StartU);
-  bool StartNeedsFreeze = !isGuaranteedNotToBeUndefOrPoison(StartV);
-  // We can't insert freeze if the start value is the result of the
-  // terminator (e.g. an invoke).
-  if (StartNeedsFreeze && StartBB->getTerminator() == StartV)
-    return nullptr;
-
   SmallPtrSet<Value *, 32> Visited;
   SmallVector<Instruction *> DropFlags;
   while (!Worklist.empty()) {
@@ -5084,7 +5080,9 @@ Instruction *InstCombinerImpl::foldFreezeIntoRecurrence(FreezeInst &FI,
   for (Instruction *I : DropFlags)
     I->dropPoisonGeneratingAnnotations();
 
-  if (StartNeedsFreeze) {
+  for (Use *StartU : StartUses) {
+    Value *StartV = StartU->get();
+    BasicBlock *StartBB = PN->getIncomingBlock(*StartU);
     Builder.SetInsertPoint(StartBB->getTerminator());
     Value *FrozenStartV = Builder.CreateFreeze(StartV,
                                                StartV->getName() + ".fr");
diff --git a/llvm/test/Transforms/InstCombine/freeze.ll b/llvm/test/Transforms/InstCombine/freeze.ll
index b29421a655fa8..09fb2dc19912c 100644
--- a/llvm/test/Transforms/InstCombine/freeze.ll
+++ b/llvm/test/Transforms/InstCombine/freeze.ll
@@ -1106,13 +1106,14 @@ define void @fold_phi_multiple_start_values(i1 %c, i32 %init, i32 %init2, i32 %n
 ; CHECK-LABEL: define void @fold_phi_multiple_start_values(
 ; CHECK-SAME: i1 [[C:%.*]], i32 [[INIT:%.*]], i32 [[INIT2:%.*]], i32 [[N:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[INIT_FR:%.*]] = freeze i32 [[INIT]]
 ; CHECK-NEXT:    br i1 [[C]], label %[[IF:.*]], label %[[LOOP:.*]]
 ; CHECK:       [[IF]]:
+; CHECK-NEXT:    [[INIT2_FR:%.*]] = freeze i32 [[INIT2]]
 ; CHECK-NEXT:    br label %[[LOOP]]
 ; CHECK:       [[LOOP]]:
-; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT]], %[[ENTRY]] ], [ [[INIT2]], %[[IF]] ], [ [[I_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT:    [[I_FR:%.*]] = freeze i32 [[I]]
-; CHECK-NEXT:    [[I_NEXT]] = add nuw nsw i32 [[I_FR]], 1
+; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[INIT_FR]], %[[ENTRY]] ], [ [[INIT2_FR]], %[[IF]] ], [ [[I_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[I_NEXT]], [[N]]
 ; CHECK-NEXT:    br i1 [[COND]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:



More information about the llvm-commits mailing list