forked from OSchip/llvm-project
[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:
parent
0ce261d052
commit
faedfcbf6d
|
@ -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; };
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue