[IR][LoopRotate] avoid leaving phi with no operands (PR48296)

https://llvm.org/PR48296 shows an example where we delete all of the operands
of a phi without actually deleting the phi, and that is currently considered
invalid IR. The reduced test included here would crash for that reason.

A suggested follow-up is to loosen the assert to allow 0-operand phis
in unreachable blocks.

Differential Revision: https://reviews.llvm.org/D92247
This commit is contained in:
Sanjay Patel 2020-11-30 08:59:40 -05:00
parent 234a5297aa
commit bfd2c216ea
3 changed files with 38 additions and 4 deletions

View File

@ -387,9 +387,9 @@ public:
/// Update PHI nodes in this BasicBlock before removal of predecessor \p Pred.
/// Note that this function does not actually remove the predecessor.
///
/// If \p KeepOneInputPHIs is true then don't remove PHIs that are left with
/// zero or one incoming values, and don't simplify PHIs with all incoming
/// values the same.
/// If \p KeepOneInputPHIs is true, then don't remove PHIs that are left with
/// one incoming value and don't simplify PHIs with all incoming values the
/// same.
void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs = false);
bool canSplitPredecessors() const;

View File

@ -330,7 +330,7 @@ void BasicBlock::removePredecessor(BasicBlock *Pred,
unsigned NumPreds = cast<PHINode>(front()).getNumIncomingValues();
for (PHINode &Phi : make_early_inc_range(phis())) {
Phi.removeIncomingValue(Pred, !KeepOneInputPHIs);
Phi.removeIncomingValue(Pred);
if (KeepOneInputPHIs)
continue;
// If we have a single predecessor, removeIncomingValue erased the PHI

View File

@ -0,0 +1,34 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -lcssa -loop-rotate < %s | FileCheck %s
define void @PR48296(i1 %cond) {
; CHECK-LABEL: @PR48296(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: br i1 [[COND:%.*]], label [[INC:%.*]], label [[LOOP_BACKEDGE:%.*]]
; CHECK: loop.backedge:
; CHECK-NEXT: br label [[LOOP]]
; CHECK: dead:
; CHECK-NEXT: unreachable
; CHECK: inc:
; CHECK-NEXT: br label [[LOOP_BACKEDGE]]
; CHECK: return:
; CHECK-NEXT: ret void
;
entry:
br label %loop
loop:
br i1 %cond, label %inc, label %loop
dead: ; No predecessors!
br i1 %cond, label %inc, label %return
inc:
br label %loop
return:
%r = phi i32 [ undef, %dead ]
ret void
}