const SmallVectorImpl<Instruction *> &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<Instruction>(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<PHINode>(I)); ++I) {
if (PN->getIncomingValue(0) == Inst) {
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<PHINode>(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());
}
}
--- /dev/null
+; 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
+}