[polly] r212796 - DeadCodeElim: Compute correct liveout for non-affine accesses

Tobias Grosser tobias at grosser.es
Fri Jul 11 00:12:11 PDT 2014


Author: grosser
Date: Fri Jul 11 02:12:10 2014
New Revision: 212796

URL: http://llvm.org/viewvc/llvm-project?rev=212796&view=rev
Log:
DeadCodeElim: Compute correct liveout for non-affine accesses

Thanks to Johannes Doerfert for narrowing down the bug.

Reported-by: Chris Jenneisch <chrisj at codeaurora.org>

Added:
    polly/trunk/test/DeadCodeElimination/non-affine-affine-mix.ll
    polly/trunk/test/DeadCodeElimination/non-affine.ll
Modified:
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/Transform/DeadCodeElimination.cpp

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=212796&r1=212795&r2=212796&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Fri Jul 11 02:12:10 2014
@@ -702,6 +702,12 @@ public:
   /// @brief Get a union set containing the iteration domains of all statements.
   __isl_give isl_union_set *getDomains();
 
+  /// @brief Get a union map of all may-writes performed in the SCoP.
+  __isl_give isl_union_map *getMayWrites();
+
+  /// @brief Get a union map of all must-writes performed in the SCoP.
+  __isl_give isl_union_map *getMustWrites();
+
   /// @brief Get a union map of all writes performed in the SCoP.
   __isl_give isl_union_map *getWrites();
 

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=212796&r1=212795&r2=212796&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Fri Jul 11 02:12:10 2014
@@ -1269,6 +1269,40 @@ __isl_give isl_union_set *Scop::getDomai
   return Domain;
 }
 
+__isl_give isl_union_map *Scop::getMustWrites() {
+  isl_union_map *Write = isl_union_map_empty(this->getParamSpace());
+
+  for (ScopStmt *Stmt : *this) {
+    for (MemoryAccess *MA : *Stmt) {
+      if (!MA->isMustWrite())
+        continue;
+
+      isl_set *Domain = Stmt->getDomain();
+      isl_map *AccessDomain = MA->getAccessRelation();
+      AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
+      Write = isl_union_map_add_map(Write, AccessDomain);
+    }
+  }
+  return isl_union_map_coalesce(Write);
+}
+
+__isl_give isl_union_map *Scop::getMayWrites() {
+  isl_union_map *Write = isl_union_map_empty(this->getParamSpace());
+
+  for (ScopStmt *Stmt : *this) {
+    for (MemoryAccess *MA : *Stmt) {
+      if (!MA->isMayWrite())
+        continue;
+
+      isl_set *Domain = Stmt->getDomain();
+      isl_map *AccessDomain = MA->getAccessRelation();
+      AccessDomain = isl_map_intersect_domain(AccessDomain, Domain);
+      Write = isl_union_map_add_map(Write, AccessDomain);
+    }
+  }
+  return isl_union_map_coalesce(Write);
+}
+
 __isl_give isl_union_map *Scop::getWrites() {
   isl_union_map *Write = isl_union_map_empty(this->getParamSpace());
 

Modified: polly/trunk/lib/Transform/DeadCodeElimination.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Transform/DeadCodeElimination.cpp?rev=212796&r1=212795&r2=212796&view=diff
==============================================================================
--- polly/trunk/lib/Transform/DeadCodeElimination.cpp (original)
+++ polly/trunk/lib/Transform/DeadCodeElimination.cpp Fri Jul 11 02:12:10 2014
@@ -36,6 +36,7 @@
 #include "polly/LinkAllPasses.h"
 #include "polly/ScopInfo.h"
 #include "llvm/Support/CommandLine.h"
+#include "isl/flow.h"
 #include "isl/set.h"
 #include "isl/map.h"
 #include "isl/union_map.h"
@@ -63,26 +64,35 @@ public:
   void getAnalysisUsage(AnalysisUsage &AU) const;
 
 private:
-  isl_union_set *getLastWrites(isl_union_map *Writes, isl_union_map *Schedule);
+  /// @brief Return the set of live iterations.
+  ///
+  /// The set of live iterations are all iterations that write to memory and for
+  /// which we can not prove that there will be a later write that _must_
+  /// overwrite the same memory location and is consequently the only one that
+  /// is visible after the execution of the SCoP.
+  ///
+  isl_union_set *getLiveOut(Scop &S);
   bool eliminateDeadCode(Scop &S, int PreciseSteps);
 };
 }
 
 char DeadCodeElim::ID = 0;
 
-/// Return the set of iterations that contains the last write for each location.
-isl_union_set *DeadCodeElim::getLastWrites(__isl_take isl_union_map *Writes,
-                                           __isl_take isl_union_map *Schedule) {
-  isl_union_map *WriteIterations = isl_union_map_reverse(Writes);
-  isl_union_map *WriteTimes =
-      isl_union_map_apply_range(WriteIterations, isl_union_map_copy(Schedule));
-
-  isl_union_map *LastWriteTimes = isl_union_map_lexmax(WriteTimes);
-  isl_union_map *LastWriteIterations = isl_union_map_apply_range(
-      LastWriteTimes, isl_union_map_reverse(Schedule));
-
-  isl_union_set *Live = isl_union_map_range(LastWriteIterations);
-  return isl_union_set_coalesce(Live);
+// To compute the live outs, we first assume all must and may-writes are exposed
+// and then subtract the set of statements that are definitely overwritten.
+isl_union_set *DeadCodeElim::getLiveOut(Scop &S) {
+  __isl_take isl_union_map *Kills = S.getMustWrites();
+  __isl_take isl_union_map *Empty = isl_union_map_empty(S.getParamSpace());
+
+  isl_union_map *Covering;
+  isl_union_map *Writes = S.getWrites();
+  isl_union_map_compute_flow(Kills, Empty, isl_union_map_copy(Writes),
+                             S.getSchedule(), NULL, &Covering, NULL, NULL);
+
+  isl_union_map *Exposed = Writes;
+  Exposed =
+      isl_union_map_subtract_domain(Exposed, isl_union_map_domain(Covering));
+  return isl_union_map_domain(Exposed);
 }
 
 /// Performs polyhedral dead iteration elimination by:
@@ -99,7 +109,7 @@ bool DeadCodeElim::eliminateDeadCode(Sco
   if (!D->hasValidDependences())
     return false;
 
-  isl_union_set *Live = this->getLastWrites(S.getWrites(), S.getSchedule());
+  isl_union_set *Live = getLiveOut(S);
   isl_union_map *Dep =
       D->getDependences(Dependences::TYPE_RAW | Dependences::TYPE_RED);
   Dep = isl_union_map_reverse(Dep);

Added: polly/trunk/test/DeadCodeElimination/non-affine-affine-mix.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/DeadCodeElimination/non-affine-affine-mix.ll?rev=212796&view=auto
==============================================================================
--- polly/trunk/test/DeadCodeElimination/non-affine-affine-mix.ll (added)
+++ polly/trunk/test/DeadCodeElimination/non-affine-affine-mix.ll Fri Jul 11 02:12:10 2014
@@ -0,0 +1,53 @@
+; RUN: opt %loadPolly -polly-allow-nonaffine -polly-dce -polly-ast -analyze < %s | FileCheck %s
+;
+;    void f(int *A) {
+;      for (int i = 0; i < 1024; i++)
+; S1:    A[i % 2] = i;
+;      for (int i = 0; i < 1024; i++)
+; S2:    A[i2] = i;
+;    }
+
+; CHECK-NOT: Stmt_S1
+
+; CHECK: for (int c1 = 0; c1 <= 1023; c1 += 1)
+; CHECK:   Stmt_S2(c1);
+
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %S1, label %for.cond.2
+
+S1:
+  %rem = srem i32 %i.0, 2
+  %arrayidx = getelementptr inbounds i32* %A, i32 %rem
+  store i32 %i.0, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.cond.2:
+  %i.2 = phi i32 [ 0, %for.cond ], [ %inc.2, %for.inc.2 ]
+  %exitcond.2 = icmp ne i32 %i.2, 1024
+  br i1 %exitcond.2, label %S2, label %for.end
+
+S2:
+  %arrayidx.2 = getelementptr inbounds i32* %A, i32 %i.2
+  store i32 %i.2, i32* %arrayidx.2, align 4
+  br label %for.inc.2
+
+for.inc.2:
+  %inc.2 = add nsw i32 %i.2, 1
+  br label %for.cond.2
+
+for.end:
+  ret void
+}
+

Added: polly/trunk/test/DeadCodeElimination/non-affine.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/DeadCodeElimination/non-affine.ll?rev=212796&view=auto
==============================================================================
--- polly/trunk/test/DeadCodeElimination/non-affine.ll (added)
+++ polly/trunk/test/DeadCodeElimination/non-affine.ll Fri Jul 11 02:12:10 2014
@@ -0,0 +1,34 @@
+; RUN: opt %loadPolly -polly-allow-nonaffine -polly-dce -polly-ast -analyze < %s | FileCheck %s
+;
+; CHECK: for (int c1 = 0; c1 <= 1023; c1 += 1)
+;
+;    void f(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        A[i % 2] = i;
+;    }
+;
+target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64"
+
+define void @f(i32* %A) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %i.0, 1024
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %rem = srem i32 %i.0, 2
+  %arrayidx = getelementptr inbounds i32* %A, i32 %rem
+  store i32 %i.0, i32* %arrayidx, align 4
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body
+  %inc = add nsw i32 %i.0, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}
+





More information about the llvm-commits mailing list