Index: llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -1300,6 +1300,12 @@ if (Instruction *Result = foldPHIArgZextsIntoPHI(PN)) return Result; + // Replace values from unreachable incoming blocks with undef. + for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) { + if (!DT.isReachableFromEntry(PN.getIncomingBlock(i))) + PN.setIncomingValue(i, UndefValue::get(PN.getType())); + } + // If all PHI operands are the same operation, pull them through the PHI, // reducing code size. if (isa(PN.getIncomingValue(0)) && Index: llvm/test/Transforms/InstCombine/phi.ll =================================================================== --- llvm/test/Transforms/InstCombine/phi.ll +++ llvm/test/Transforms/InstCombine/phi.ll @@ -1181,3 +1181,39 @@ %cmp1 = icmp ne i32 %a.0, 0 ret i1 %cmp1 } + +; This would crash trying to delete an instruction (conv) +; that still had uses because the user (the phi) was not +; updated to remove a use from an unreachable block (g.exit). + +define void @main(i16 %x) { +; CHECK-LABEL: @main( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: br i1 undef, label [[FOR_END:%.*]], label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: unreachable +; CHECK: g.exit: +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; +entry: + br label %for.cond + +for.cond: + %p = phi double [ %conv, %g.exit ], [ undef, %entry ] + br i1 undef, label %for.end, label %for.body + +for.body: + %conv = sitofp i16 %x to double + unreachable + +g.exit: + br label %for.cond + +for.end: + store double %p, double* undef + ret void +} Index: llvm/test/Transforms/InstCombine/zext-or-icmp.ll =================================================================== --- llvm/test/Transforms/InstCombine/zext-or-icmp.ll +++ llvm/test/Transforms/InstCombine/zext-or-icmp.ll @@ -31,14 +31,7 @@ ; CHECK: block1: ; CHECK-NEXT: br label [[BLOCK2]] ; CHECK: block2: -; CHECK-NEXT: [[CMP_I:%.*]] = phi i1 [ false, [[BLOCK1:%.*]] ], [ true, [[ENTRY:%.*]] ] -; CHECK-NEXT: [[M_011:%.*]] = phi i32 [ 0, [[BLOCK1]] ], [ 33, [[ENTRY]] ] -; CHECK-NEXT: [[M_1_OP:%.*]] = lshr i32 1, [[M_011]] -; CHECK-NEXT: [[SEXT_MASK:%.*]] = and i32 [[M_1_OP]], 65535 -; CHECK-NEXT: [[CMP115:%.*]] = icmp ne i32 [[SEXT_MASK]], 0 -; CHECK-NEXT: [[CMP1:%.*]] = or i1 [[CMP_I]], [[CMP115]] -; CHECK-NEXT: [[CONV2:%.*]] = zext i1 [[CMP1]] to i32 -; CHECK-NEXT: ret i32 [[CONV2]] +; CHECK-NEXT: ret i32 1 ; entry: br label %block2