Model scalar writes with uses outside the SCoP
authorJohannes Doerfert <doerfert@cs.uni-saarland.de>
Wed, 11 Feb 2015 17:02:52 +0000 (17:02 +0000)
committerJohannes Doerfert <doerfert@cs.uni-saarland.de>
Wed, 11 Feb 2015 17:02:52 +0000 (17:02 +0000)
  These write are important as they will force the scheduling and code
  generation of an otherwise trivial statement and also impose an order of
  execution needed to guarantee the correct final value for a scalar in a loop.

  Added test case modeled after ClamAV/clamscan.

llvm-svn: 228847

polly/lib/Analysis/TempScopInfo.cpp
polly/test/ScopInfo/escaping_empty_scop.ll [new file with mode: 0644]

index b357e6e..bde536a 100644 (file)
@@ -141,10 +141,7 @@ void TempScopInfo::buildPHIAccesses(PHINode *PHI, Region &R,
 }
 
 bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R) {
-  // No need to translate these scalar dependences into polyhedral form, because
-  // synthesizable scalars can be generated by the code generator.
-  if (canSynthesize(Inst, LI, SE, R))
-    return false;
+  bool canSynthesizeInst = canSynthesize(Inst, LI, SE, R);
   if (isIgnoredIntrinsic(Inst))
     return false;
 
@@ -170,12 +167,23 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R) {
     if (UseParent == ParentBB)
       continue;
 
+    // Check whether or not the use is in the SCoP.
+    if (!R->contains(UseParent)) {
+      AnyCrossStmtUse = true;
+      continue;
+    }
+
+    // If the instruction can be synthesized and the user is in the region
+    // we do not need to add scalar dependences.
+    if (canSynthesizeInst)
+      continue;
+
     // No need to translate these scalar dependences into polyhedral form,
     // because synthesizable scalars can be generated by the code generator.
     if (canSynthesize(UI, LI, SE, R))
       continue;
 
-    // Skip PHI nodes as they handle their operands on their own.
+    // Skip PHI nodes in the region as they handle their operands on their own.
     if (isa<PHINode>(UI))
       continue;
 
@@ -183,9 +191,6 @@ bool TempScopInfo::buildScalarDependences(Instruction *Inst, Region *R) {
     AnyCrossStmtUse = true;
 
     // Do not build a read access that is not in the current SCoP
-    if (!R->contains(UseParent))
-      continue;
-
     // Use the def instruction as base address of the IRAccess, so that it will
     // become the name of the scalar access in the polyhedral form.
     IRAccess ScalarAccess(IRAccess::READ, Inst, ZeroOffset, 1, true);
diff --git a/polly/test/ScopInfo/escaping_empty_scop.ll b/polly/test/ScopInfo/escaping_empty_scop.ll
new file mode 100644 (file)
index 0000000..7e0c512
--- /dev/null
@@ -0,0 +1,58 @@
+; RUN: opt %loadPolly -polly-scops -disable-polly-intra-scop-scalar-to-array -polly-model-phi-nodes -analyze < %s | FileCheck %s
+;
+;    void g();
+;    int f(int *A) {
+;      int a0 = 0, a1 = 0, a2 = 0;
+;      for (int i = 0; i < 1000; i++) {
+;        a0 = 2 * i;
+;        // split
+;        A[0] = i;
+;        a1 = 2 * i;
+;        // split
+;        a2 = 2 * i;
+;      }
+;      g();
+;      return a1 + a2;
+;    }
+;
+; CHECK:      Stmt_bb1
+; CHECK:            MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
+; CHECK:                { Stmt_bb1[i0] -> MemRef_a_0[] };
+; CHECK:      Stmt_bb2
+; CHECK:            MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
+; CHECK:                { Stmt_bb2[i0] -> MemRef_a_1[] };
+; CHECK:      Stmt_bb3
+; CHECK:            MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 1]
+; CHECK:                { Stmt_bb3[i0] -> MemRef_a_2[] };
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define i32 @f(i32* %A) {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb3, %bb
+  %i.0 = phi i32 [ 0, %bb ], [ %tmp4, %bb3 ]
+  %a.0 = mul i32 %i.0, 2
+  br label %bb2
+
+bb2:                                              ; preds = %bb1
+  %a.1 = mul i32 %i.0, 2
+  store i32 %i.0, i32 *%A, align 4
+  br label %bb3
+
+bb3:                                              ; preds = %bb2
+  %tmp = shl nsw i32 %i.0, 1
+  %tmp4 = add nuw nsw i32 %i.0, 1
+  %a.2 = mul i32 %i.0, 2
+  %exitcond = icmp ne i32 %i.0, 1000
+  br i1 %exitcond, label %bb1, label %bb5
+
+bb5:                                              ; preds = %bb1
+  call void (...)* @g() #2
+  %add = add i32 %a.0, %a.1
+  %add2 = add i32 %add, %a.2
+  ret i32 %add2
+}
+
+declare void @g(...) #1