[polly] r310311 - [ZoneAlgo] Allow two writes that write identical values into same array slot

Tobias Grosser via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 7 15:01:29 PDT 2017


Author: grosser
Date: Mon Aug  7 15:01:29 2017
New Revision: 310311

URL: http://llvm.org/viewvc/llvm-project?rev=310311&view=rev
Log:
[ZoneAlgo] Allow two writes that write identical values into same array slot

Two write statements which write into the very same array slot generally are
conflicting. However, in case the value that is written is identical, this
does not cause any problem. Hence, allow such write pairs in this specific
situation.

Added:
    polly/trunk/test/ForwardOpTree/forward_load_double_write.ll
Modified:
    polly/trunk/lib/Transform/ZoneAlgo.cpp

Modified: polly/trunk/lib/Transform/ZoneAlgo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Transform/ZoneAlgo.cpp?rev=310311&r1=310310&r2=310311&view=diff
==============================================================================
--- polly/trunk/lib/Transform/ZoneAlgo.cpp (original)
+++ polly/trunk/lib/Transform/ZoneAlgo.cpp Mon Aug  7 15:01:29 2017
@@ -284,6 +284,29 @@ ZoneAlgorithm::ZoneAlgorithm(const char
   ScatterSpace = getScatterSpace(Schedule);
 }
 
+/// Check if all stores in @p Stmt store the very same value.
+///
+/// TODO: In the future we may want to extent this to make the checks
+///       specific to different memory locations.
+static bool onlySameValueWrites(ScopStmt *Stmt) {
+  Value *V = nullptr;
+
+  for (auto *MA : *Stmt) {
+    if (!MA->isLatestArrayKind() || !MA->isMustWrite() ||
+        !MA->isOriginalArrayKind())
+      continue;
+
+    if (!V) {
+      V = MA->getAccessValue();
+      continue;
+    }
+
+    if (V != MA->getAccessValue())
+      return false;
+  }
+  return true;
+}
+
 bool ZoneAlgorithm::isCompatibleStmt(ScopStmt *Stmt) {
   auto Stores = makeEmptyUnionMap();
   auto Loads = makeEmptyUnionMap();
@@ -338,11 +361,13 @@ bool ZoneAlgorithm::isCompatibleStmt(Sco
     if (!isl_union_map_is_disjoint(Stores.keep(), AccRel.keep())) {
       OptimizationRemarkMissed R(PassName, "StoreAfterStore",
                                  MA->getAccessInstruction());
-      R << "store after store of same element in same statement";
-      R << " (previous stores: " << Stores;
-      R << ", storing: " << AccRel << ")";
-      S->getFunction().getContext().diagnose(R);
-      return false;
+      if (!onlySameValueWrites(Stmt)) {
+        R << "store after store of same element in same statement";
+        R << " (previous stores: " << Stores;
+        R << ", storing: " << AccRel << ")";
+        S->getFunction().getContext().diagnose(R);
+        return false;
+      }
     }
 
     Stores = give(isl_union_map_union(Stores.take(), AccRel.take()));

Added: polly/trunk/test/ForwardOpTree/forward_load_double_write.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ForwardOpTree/forward_load_double_write.ll?rev=310311&view=auto
==============================================================================
--- polly/trunk/test/ForwardOpTree/forward_load_double_write.ll (added)
+++ polly/trunk/test/ForwardOpTree/forward_load_double_write.ll Mon Aug  7 15:01:29 2017
@@ -0,0 +1,56 @@
+; RUN: opt %loadPolly -polly-optree -analyze < %s | FileCheck %s -match-full-lines
+;
+; Rematerialize a load even in case two writes of identical values are in
+; one scop statement.
+;
+define void @func(i32 %n, double* noalias nonnull %A, double* noalias nonnull %B) {
+entry:
+  br label %for
+
+for:
+  %j = phi i32 [0, %entry], [%j.inc, %inc]
+  %j.cmp = icmp slt i32 %j, %n
+  br i1 %j.cmp, label %bodyA, label %exit
+
+    bodyA:
+      %B_idx = getelementptr inbounds double, double* %B, i32 %j
+      %val = load double, double* %B_idx
+      br label %bodyB
+
+    bodyB:
+      %A_idx = getelementptr inbounds double, double* %A, i32 %j
+      store double %val, double* %A_idx
+      store double %val, double* %A_idx
+      br label %inc
+
+inc:
+  %j.inc = add nuw nsw i32 %j, 1
+  br label %for
+
+exit:
+  br label %return
+
+return:
+  ret void
+}
+
+
+; CHECK: Statistics {
+; CHECK:     Known loads forwarded: 1
+; CHECK:     Operand trees forwarded: 1
+; CHECK:     Statements with forwarded operand trees: 1
+; CHECK: }
+
+; CHECK:      Stmt_bodyB
+; CHECK-NEXT:         ReadAccess :=       [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:             null;
+; CHECK-NEXT:        new: [n] -> { Stmt_bodyB[i0] -> MemRef_B[i0] };
+; CHECK-NEXT:         MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:             [n] -> { Stmt_bodyB[i0] -> MemRef_A[i0] };
+; CHECK-NEXT:         MustWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:             [n] -> { Stmt_bodyB[i0] -> MemRef_A[i0] };
+; CHECK-NEXT:         Instructions {
+; CHECK-NEXT:               %val = load double, double* %B_idx
+; CHECK-NEXT:               store double %val, double* %A_idx
+; CHECK-NEXT:               store double %val, double* %A_idx
+; CHECK-NEXT:         }




More information about the llvm-commits mailing list