[BlockGenerator] Fix PHI merges for MK_Arrays.

Value merging is only necessary for scalars when they are used outside
of the scop. While an array's base pointer can be used after the scop,
it gets an extra ScopArrayInfo of type MK_Value. We used to generate
phi's for both of them, where one was assuming the reault of the other
phi would be the original value, because it has already been replaced by
the previous phi. This resulted in IR that the current IR verifier
allows, but is probably illegal.

This reduces the number of LNT test-suite fails with
-polly-position=before-vectorizer -polly-process-unprofitable
from 16 to 10.

Also see llvm.org/PR26718.

llvm-svn: 262629
This commit is contained in:
Michael Kruse 2016-03-03 17:20:43 +00:00
parent 0ce261d052
commit faedfcbf6d
3 changed files with 60 additions and 0 deletions

View File

@ -319,6 +319,9 @@ public:
/// @brief Return the isl id for the base pointer.
__isl_give isl_id *getBasePtrId() const;
/// @brief Is this array info modeling an llvm::Value?
bool isValueKind() const { return Kind == MK_Value; };
/// @brief Is this array info modeling special PHI node memory?
///
/// During code generation of PHI nodes, there is a need for two kinds of
@ -331,6 +334,9 @@ public:
/// normal scalar array modeling.
bool isPHIKind() const { return Kind == MK_PHI; };
/// @brief Is this array info modeling an MK_ExitPHI?
bool isExitPHIKind() const { return Kind == MK_ExitPHI; };
/// @brief Is this array info modeling an array?
bool isArrayKind() const { return Kind == MK_Array; };

View File

@ -601,6 +601,13 @@ void BlockGenerator::createExitPHINodeMerges(Scop &S) {
auto &SAI = Pair.second;
auto *Val = SAI->getBasePtr();
// Only Value-like scalars need a merge PHI. Exit block PHIs receive either
// the original PHI's value or the reloaded incoming values from the
// generated code. An llvm::Value is merged between the original code's
// value or the generated one.
if (!SAI->isValueKind() && !SAI->isExitPHIKind())
continue;
PHINode *PHI = dyn_cast<PHINode>(Val);
if (!PHI)
continue;
@ -613,6 +620,9 @@ void BlockGenerator::createExitPHINodeMerges(Scop &S) {
Value *Reload = Builder.CreateLoad(ScalarAddr, Name + ".ph.final_reload");
Reload = Builder.CreateBitOrPointerCast(Reload, PHI->getType());
Value *OriginalValue = PHI->getIncomingValueForBlock(MergeBB);
assert((!isa<Instruction>(OriginalValue) ||
cast<Instruction>(OriginalValue)->getParent() != MergeBB) &&
"Original value must no be one we just generated.");
auto *MergePHI = PHINode::Create(PHI->getType(), 2, Name + ".ph.merge");
MergePHI->insertBefore(&*MergeBB->getFirstInsertionPt());
MergePHI->addIncoming(Reload, OptExitBB);

View File

@ -0,0 +1,44 @@
; RUN: opt %loadPolly -polly-position=before-vectorizer -polly-scops -analyze < %s | FileCheck %s --check-prefix=SCOP
; RUN: opt %loadPolly -polly-position=before-vectorizer -polly-codegen -S < %s | FileCheck %s --check-prefix=IR
; The IR has two ScopArrayInfo for the value %next.0. This used to produce two
; phi nodes in polly.merge_new_and_old, one illegaly using the result of the
; other. There must be only one merge phi, no need to generate them for arrays
; of type MK_Array.
; Derived from test-suite/MultiSource/Applications/siod/slib.c
%struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962 = type { i16, i16, %union.anon.1.289.321.337.353.481.545.593.625.817.897.913.961 }
%union.anon.1.289.321.337.353.481.545.593.625.817.897.913.961 = type { %struct.anon.0.288.320.336.352.480.544.592.624.816.896.912.960 }
%struct.anon.0.288.320.336.352.480.544.592.624.816.896.912.960 = type { %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962*, %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962* }
define void @leval_or() {
entry:
br label %while.cond
while.cond: ; preds = %sw.bb1.i30, %cond.end.i28, %entry
%next.0 = phi %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962* [ null, %entry ], [ %1, %sw.bb1.i30 ], [ null, %cond.end.i28 ]
br i1 undef, label %cond.end.i28, label %if.then
if.then: ; preds = %while.cond
ret void
cond.end.i28: ; preds = %while.cond
%type.i24 = getelementptr inbounds %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962, %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962* %next.0, i64 0, i32 1
%0 = load i16, i16* %type.i24, align 2
br i1 false, label %sw.bb1.i30, label %while.cond
sw.bb1.i30: ; preds = %cond.end.i28
%cdr.i29 = getelementptr inbounds %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962, %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962* %next.0, i64 0, i32 2, i32 0, i32 1
%1 = load %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962*, %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962** %cdr.i29, align 8
br label %while.cond
}
; SCOP: Arrays {
; SCOP-NEXT: i16 MemRef_next_0[*];
; SCOP-NEXT: %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962* MemRef_next_0;
; SCOP-NEXT: }
; IR: polly.merge_new_and_old:
; IR-NEXT: %next.0.ph.merge = phi %struct.obj.2.290.322.338.354.482.546.594.626.818.898.914.962* [ %next.0.ph.final_reload, %polly.exiting ], [ %next.0.ph, %while.cond.region_exiting ]
; IR-NEXT: %indvar.next = add i64 %indvar, 1
; IR-NEXT: br label %while.cond