Skip to content

Commit 09dc08b

Browse files
committed
[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: llvm#151115 (comment)
1 parent bcbbb2c commit 09dc08b

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,12 +2011,17 @@ Instruction *InstCombinerImpl::foldOpIntoPhi(Instruction &I, PHINode *PN,
20112011
NewPN->addIncoming(NewPhiValues[i], PN->getIncomingBlock(i));
20122012

20132013
if (IdenticalUsers) {
2014-
for (User *U : make_early_inc_range(PN->users())) {
2014+
// Collect and deduplicate users up-front to avoid iterator invalidation.
2015+
SmallSetVector<Instruction *, 4> ToReplace;
2016+
for (User *U : PN->users()) {
20152017
Instruction *User = cast<Instruction>(U);
20162018
if (User == &I)
20172019
continue;
2018-
replaceInstUsesWith(*User, NewPN);
2019-
eraseInstFromFunction(*User);
2020+
ToReplace.insert(User);
2021+
}
2022+
for (Instruction *I : ToReplace) {
2023+
replaceInstUsesWith(*I, NewPN);
2024+
eraseInstFromFunction(*I);
20202025
}
20212026
OneUse = true;
20222027
}

llvm/test/Transforms/InstCombine/phi.ll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3025,3 +3025,31 @@ join:
30253025
%umax = call noundef i32 @llvm.umax(i32 noundef %phi, i32 1)
30263026
ret i32 %umax
30273027
}
3028+
3029+
define i32 @multiple_intrinsics_with_multiple_phi_uses(i1 %c, i32 %arg) {
3030+
; CHECK-LABEL: @multiple_intrinsics_with_multiple_phi_uses(
3031+
; CHECK-NEXT: entry:
3032+
; CHECK-NEXT: br i1 [[C:%.*]], label [[IF:%.*]], label [[IF_END:%.*]]
3033+
; CHECK: if:
3034+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ARG:%.*]], -8
3035+
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.fshl.i32(i32 [[ADD]], i32 [[ADD]], i32 29)
3036+
; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[TMP0]], 1
3037+
; CHECK-NEXT: br label [[IF_END]]
3038+
; CHECK: if.end:
3039+
; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[TMP1]], [[IF]] ], [ 0, [[ENTRY:%.*]] ]
3040+
; CHECK-NEXT: ret i32 [[PHI]]
3041+
;
3042+
entry:
3043+
br i1 %c, label %if, label %if.end
3044+
3045+
if:
3046+
%add = add i32 %arg, -8
3047+
br label %if.end
3048+
3049+
if.end:
3050+
%phi = phi i32 [ %add, %if ], [ 0, %entry ]
3051+
%fshl1 = call i32 @llvm.fshl.i32(i32 %phi, i32 %phi, i32 29)
3052+
%fshl2 = call i32 @llvm.fshl.i32(i32 %phi, i32 %phi, i32 29)
3053+
%add2 = add i32 %fshl1, %fshl2
3054+
ret i32 %add2
3055+
}

0 commit comments

Comments
 (0)