Skip to content

Commit b1b2f0a

Browse files
committed
[IR] Avoid self-referencing values caused by PHI node removal
In case of an unreachable loop, for example, the JumpThreading pass might attempt to remove the PHI node in the loop entry and replace it with its constant value. However, this fails in case the value is an instruction using the PHI node. This LLVM defect was identified via the AMD Fuzzing project.
1 parent f745cb6 commit b1b2f0a

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

llvm/lib/IR/BasicBlock.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,14 @@ void BasicBlock::removePredecessor(BasicBlock *Pred,
556556
if (NumPreds == 1)
557557
continue;
558558

559-
// Try to replace the PHI node with a constant value.
560-
if (Value *PhiConstant = Phi.hasConstantValue()) {
559+
// Try to replace the PHI node with a constant value, but make sure that
560+
// this value isn't using the PHI node. (Except it's a PHI node itself. PHI
561+
// nodes are allowed to reference themselves.)
562+
if (Value *PhiConstant = Phi.hasConstantValue();
563+
PhiConstant &&
564+
(!isa<Instruction>(PhiConstant) || isa<PHINode>(PhiConstant) ||
565+
llvm::all_of(Phi.users(),
566+
[PhiConstant](User *U) { return U != PhiConstant; }))) {
561567
Phi.replaceAllUsesWith(PhiConstant);
562568
Phi.eraseFromParent();
563569
}

llvm/test/Transforms/JumpThreading/unreachable-loops.ll

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,64 @@ cleanup2343.loopexit4: ; preds = %cleanup1491
180180
unreachable
181181
}
182182

183+
; This segfaults due to recursion in %C4. Reason: %L6 is identified to be a
184+
; "partially redundant load" and is replaced by a PHI node. The PHI node is then
185+
; simplified to be constant and is removed. This leads to %L6 being replaced by
186+
; %C4, which makes %C4 invalid since it uses %L6.
187+
; The test case has been generated by the AMD Fuzzing project and simplified
188+
; manually and by llvm-reduce.
189+
190+
define i32 @constant_phi_leads_to_self_reference() {
191+
; CHECK-LABEL: @constant_phi_leads_to_self_reference(
192+
; CHECK-NEXT: [[A9:%.*]] = alloca i1, align 1
193+
; CHECK-NEXT: br label [[F6:%.*]]
194+
; CHECK: T3:
195+
; CHECK-NEXT: [[L6:%.*]] = phi i1 [ [[C4:%.*]], [[BB6:%.*]] ]
196+
; CHECK-NEXT: br label [[BB5:%.*]]
197+
; CHECK: BB5:
198+
; CHECK-NEXT: [[L10:%.*]] = load i1, ptr [[A9]], align 1
199+
; CHECK-NEXT: br i1 [[L10]], label [[BB6]], label [[F6]]
200+
; CHECK: BB6:
201+
; CHECK-NEXT: [[LGV3:%.*]] = load i1, ptr null, align 1
202+
; CHECK-NEXT: [[C4]] = icmp sle i1 [[L6]], true
203+
; CHECK-NEXT: store i1 [[C4]], ptr null, align 1
204+
; CHECK-NEXT: br i1 [[L6]], label [[F6]], label [[T3:%.*]]
205+
; CHECK: F6:
206+
; CHECK-NEXT: ret i32 0
207+
; CHECK: F7:
208+
; CHECK-NEXT: br label [[BB5]]
209+
;
210+
%A9 = alloca i1, align 1
211+
br i1 false, label %BB4, label %F6
212+
213+
BB4: ; preds = %0
214+
br i1 false, label %F6, label %F1
215+
216+
F1: ; preds = %BB4
217+
br i1 false, label %T4, label %T3
218+
219+
T3: ; preds = %T4, %BB6, %F1
220+
%L6 = load i1, ptr null, align 1
221+
br label %BB5
222+
223+
BB5: ; preds = %F7, %T3
224+
%L10 = load i1, ptr %A9, align 1
225+
br i1 %L10, label %BB6, label %F6
226+
227+
BB6: ; preds = %BB5
228+
%LGV3 = load i1, ptr null, align 1
229+
%C4 = icmp sle i1 %L6, true
230+
store i1 %C4, ptr null, align 1
231+
br i1 %L6, label %F6, label %T3
232+
233+
T4: ; preds = %F1
234+
br label %T3
235+
236+
F6: ; preds = %BB6, %BB5, %BB4, %0
237+
ret i32 0
238+
239+
F7: ; No predecessors!
240+
br label %BB5
241+
}
242+
183243
!0 = !{!"branch_weights", i32 2146410443, i32 1073205}

0 commit comments

Comments
 (0)