forked from OSchip/llvm-project
[LoopVer] Update all existing PHIs in the exit block
We only used to add the edge from the cloned loop to PHIs that corresponded to values defined by the loop. We need to do this for all PHIs obviously since we need a PHI operand for each incoming edge. This includes things like PHIs with a constant value or with values defined before the original loop (see the testcases). After the patch the PHIs are added to the exit block in two passes. In the first pass we ensure there is a single-operand (LCSSA) PHI for each value defined by the loop. In the second pass we loop through each (single-operand) PHI and add the value for the edge from the cloned loop. If the value is defined in the loop we'll use the cloned instruction from the cloned loop. Fixes PR28037 llvm-svn: 272649
This commit is contained in:
parent
e661e528db
commit
73a26957fc
|
@ -125,12 +125,12 @@ void LoopVersioning::addPHINodes(
|
|||
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) {
|
||||
|
@ -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<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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue