[llvm] 09dc08b - [InstCombine] Handle repeated users in foldOpIntoPhi()

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 1 02:07:15 PDT 2025


Author: Nikita Popov
Date: 2025-08-01T11:07:06+02:00
New Revision: 09dc08b707cf70897a7cb47efba19a14798561b3

URL: https://github.com/llvm/llvm-project/commit/09dc08b707cf70897a7cb47efba19a14798561b3
DIFF: https://github.com/llvm/llvm-project/commit/09dc08b707cf70897a7cb47efba19a14798561b3.diff

LOG: [InstCombine] Handle repeated users in foldOpIntoPhi()

If the phi is used multiple times in the same user, it will appear
multiple times in users(), in which case make_early_inc_range()
is insufficient to prevent iterator invalidation.

Fixes the issue reported at:
https://github.com/llvm/llvm-project/pull/151115#issuecomment-3141542852

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
    llvm/test/Transforms/InstCombine/phi.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 79238e9fc7808..5ee3bb1abe86e 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2011,12 +2011,17 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN,
     NewPN->addIncoming(NewPhiValues[i], PN->getIncomingBlock(i));
 
   if (IdenticalUsers) {
-    for (User *U : make_early_inc_range(PN->users())) {
+    // Collect and deduplicate users up-front to avoid iterator invalidation.
+    SmallSetVector<Instruction *, 4> ToReplace;
+    for (User *U : PN->users()) {
       Instruction *User = cast<Instruction>(U);
       if (User == &I)
         continue;
-      replaceInstUsesWith(*User, NewPN);
-      eraseInstFromFunction(*User);
+      ToReplace.insert(User);
+    }
+    for (Instruction *I : ToReplace) {
+      replaceInstUsesWith(*I, NewPN);
+      eraseInstFromFunction(*I);
     }
     OneUse = true;
   }

diff  --git a/llvm/test/Transforms/InstCombine/phi.ll b/llvm/test/Transforms/InstCombine/phi.ll
index d9f729e69ad14..3454835d3ad65 100644
--- a/llvm/test/Transforms/InstCombine/phi.ll
+++ b/llvm/test/Transforms/InstCombine/phi.ll
@@ -3025,3 +3025,31 @@ join:
   %umax = call noundef i32 @llvm.umax(i32 noundef %phi, i32 1)
   ret i32 %umax
 }
+
+define i32 @multiple_intrinsics_with_multiple_phi_uses(i1 %c, i32 %arg) {
+; CHECK-LABEL: @multiple_intrinsics_with_multiple_phi_uses(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[IF_END:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[ARG:%.*]], -8
+; CHECK-NEXT:    [[TMP0:%.*]] = call i32 @llvm.fshl.i32(i32 [[ADD]], i32 [[ADD]], i32 29)
+; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[TMP0]], 1
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[TMP1]], [[IF]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[PHI]]
+;
+entry:
+  br i1 %c, label %if, label %if.end
+
+if:
+  %add = add i32 %arg, -8
+  br label %if.end
+
+if.end:
+  %phi = phi i32 [ %add, %if ], [ 0, %entry ]
+  %fshl1 = call i32 @llvm.fshl.i32(i32 %phi, i32 %phi, i32 29)
+  %fshl2 = call i32 @llvm.fshl.i32(i32 %phi, i32 %phi, i32 29)
+  %add2 = add i32 %fshl1, %fshl2
+  ret i32 %add2
+}


        


More information about the llvm-commits mailing list