diff --git a/llvm/lib/Transforms/Utils/LoopVersioning.cpp b/llvm/lib/Transforms/Utils/LoopVersioning.cpp index 5b1fa8eec2f5..83af2d8ea33b 100644 --- a/llvm/lib/Transforms/Utils/LoopVersioning.cpp +++ b/llvm/lib/Transforms/Utils/LoopVersioning.cpp @@ -125,12 +125,12 @@ void LoopVersioning::addPHINodes( const SmallVectorImpl &DefsUsedOutside) { BasicBlock *PHIBlock = VersionedLoop->getExitBlock(); assert(PHIBlock && "No single successor to loop exit block"); + PHINode *PN; + // First add a single-operand PHI for each DefsUsedOutside if one does not + // exists yet. for (auto *Inst : DefsUsedOutside) { - auto *NonVersionedLoopInst = cast(VMap[Inst]); - PHINode *PN; - - // First see if we have a single-operand PHI with the value defined by the + // See if we have a single-operand PHI with the value defined by the // original loop. for (auto I = PHIBlock->begin(); (PN = dyn_cast(I)); ++I) { if (PN->getIncomingValue(0) == Inst) { @@ -148,8 +148,20 @@ void LoopVersioning::addPHINodes( User->replaceUsesOfWith(Inst, PN); PN->addIncoming(Inst, VersionedLoop->getExitingBlock()); } - // Add the new incoming value from the non-versioned loop. - PN->addIncoming(NonVersionedLoopInst, NonVersionedLoop->getExitingBlock()); + } + + // Then for each PHI add the operand for the edge from the cloned loop. + for (auto I = PHIBlock->begin(); (PN = dyn_cast(I)); ++I) { + assert(PN->getNumOperands() == 1 && + "Exit block should only have on predecessor"); + + // If the definition was cloned used that otherwise use the same value. + Value *ClonedValue = PN->getIncomingValue(0); + auto Mapped = VMap.find(ClonedValue); + if (Mapped != VMap.end()) + ClonedValue = Mapped->second; + + PN->addIncoming(ClonedValue, NonVersionedLoop->getExitingBlock()); } } diff --git a/llvm/test/Transforms/LoopVersioning/incorrect-phi.ll b/llvm/test/Transforms/LoopVersioning/incorrect-phi.ll new file mode 100644 index 000000000000..fcecdb349003 --- /dev/null +++ b/llvm/test/Transforms/LoopVersioning/incorrect-phi.ll @@ -0,0 +1,62 @@ +; RUN: opt -loop-versioning -S < %s | FileCheck %s + +; Make sure all PHIs are properly updated in the exit block. Based on +; PR28037. + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@x = external global [2 x [3 x [5 x i16]]] + +; CHECK-LABEL: @phi_with_undef +define void @phi_with_undef() { +bb6.lr.ph: ; preds = %bb5.preheader + br label %bb6 + +bb6: ; preds = %bb6.lr.ph, %bb6 + %_tmp1423 = phi i16 [ undef, %bb6.lr.ph ], [ %_tmp142, %bb6 ] + %_tmp123 = getelementptr [2 x [3 x [5 x i16]]], [2 x [3 x [5 x i16]]]* @x, i16 0, i64 undef + %_tmp125 = sext i16 %_tmp1423 to i64 + %_tmp126 = getelementptr [3 x [5 x i16]], [3 x [5 x i16]]* %_tmp123, i16 0, i64 %_tmp125 + %_tmp129 = getelementptr [5 x i16], [5 x i16]* %_tmp126, i16 0, i64 undef + %_tmp130 = load i16, i16* %_tmp129 + store i16 undef, i16* getelementptr ([2 x [3 x [5 x i16]]], [2 x [3 x [5 x i16]]]* @x, i64 0, i64 undef, i64 undef, i64 undef) + %_tmp142 = add i16 %_tmp1423, 1 + br i1 false, label %bb6, label %loop.exit + +loop.exit: ; preds = %bb6 + %_tmp142.lcssa = phi i16 [ %_tmp142, %bb6 ] + %split = phi i16 [ undef, %bb6 ] +; CHECK: %split = phi i16 [ undef, %bb6 ], [ undef, %bb6.lver.orig ] + br label %bb9 + +bb9: ; preds = %bb9.loopexit, %bb1 + ret void +} + +; CHECK-LABEL: @phi_with_non_loop_defined_value +define void @phi_with_non_loop_defined_value() { +bb6.lr.ph: ; preds = %bb5.preheader + %t = add i16 1, 1 + br label %bb6 + +bb6: ; preds = %bb6.lr.ph, %bb6 + %_tmp1423 = phi i16 [ undef, %bb6.lr.ph ], [ %_tmp142, %bb6 ] + %_tmp123 = getelementptr [2 x [3 x [5 x i16]]], [2 x [3 x [5 x i16]]]* @x, i16 0, i64 undef + %_tmp125 = sext i16 %_tmp1423 to i64 + %_tmp126 = getelementptr [3 x [5 x i16]], [3 x [5 x i16]]* %_tmp123, i16 0, i64 %_tmp125 + %_tmp129 = getelementptr [5 x i16], [5 x i16]* %_tmp126, i16 0, i64 undef + %_tmp130 = load i16, i16* %_tmp129 + store i16 undef, i16* getelementptr ([2 x [3 x [5 x i16]]], [2 x [3 x [5 x i16]]]* @x, i64 0, i64 undef, i64 undef, i64 undef) + %_tmp142 = add i16 %_tmp1423, 1 + br i1 false, label %bb6, label %loop.exit + +loop.exit: ; preds = %bb6 + %_tmp142.lcssa = phi i16 [ %_tmp142, %bb6 ] + %split = phi i16 [ %t, %bb6 ] +; CHECK: %split = phi i16 [ %t, %bb6 ], [ %t, %bb6.lver.orig ] + br label %bb9 + +bb9: ; preds = %bb9.loopexit, %bb1 + ret void +}