[BlockGenerator] Fix PHI merges for MK_Arrays.
authorMichael Kruse <llvm@meinersbur.de>
Thu, 3 Mar 2016 17:20:43 +0000 (17:20 +0000)
committerMichael Kruse <llvm@meinersbur.de>
Thu, 3 Mar 2016 17:20:43 +0000 (17:20 +0000)
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

polly/include/polly/ScopInfo.h
polly/lib/CodeGen/BlockGenerators.cpp
polly/test/Isl/CodeGen/multiple_sai_fro_same_base_address.ll [new file with mode: 0644]

index 2d0b9e7..5c18971 100644 (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; };
 
index 4beb30a..e643ada 100644 (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);
diff --git a/polly/test/Isl/CodeGen/multiple_sai_fro_same_base_address.ll b/polly/test/Isl/CodeGen/multiple_sai_fro_same_base_address.ll
new file mode 100644 (file)
index 0000000..7fa431e
--- /dev/null
@@ -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