---
 gcc/testsuite/gcc.dg/tree-ssa/pr93334.c | 14 ++++++++
 gcc/tree-data-ref.c                     | 50 ++++++++++++++++++++++++++
 gcc/tree-data-ref.h                     |  1 +
 gcc/tree-loop-distribution.c            | 62 +--------------------------------
 gcc/tree.c                              | 61 ++++++++++++++++++++++++++++++++
 gcc/tree.h                              |  1 +
 6 files changed, 128 insertions(+), 61 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr93334.c

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr93334.c b/gcc/testsuite/gcc.dg/tree-ssa/pr93334.c
new file mode 100644
index 0000000..d321e03
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr93334.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-ldist-details" } */
+
+void test_crazy_code(long l, double* mem, long ofs2, long ofs3, long ofs4) {
+  for (long k=0; k<l; k++) {
+      mem[k] = 0.0;
+      mem[ofs2 +k] = 0.0;
+      mem[ofs3 +k] = 0.0;
+      mem[ofs4 +k] = 0.0;
+  }
+}
+
+/* { dg-final { scan-tree-dump-not "Version loop ... with runtime alias check" "ldist" } } */
+/* { dg-final { scan-tree-dump "Loop . distributed: split to 0 loops and 4 library" "ldist" } } */
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index e2ea5b8..a2887ac 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -5404,6 +5404,56 @@ compute_all_dependences (vec<data_reference_p> datarefs,
   return true;
 }
 
+/* Refine data dependence relation DDR under certain conditions.  For now the
+   only case handled is write-after-write dependence with two data references
+   storing the same constant with the same bytes.  */
+
+void
+refine_affine_dependence (struct data_dependence_relation *ddr)
+{
+  /* Refine data dependence relation which can't be analyzed.  */
+  if (DDR_ARE_DEPENDENT (ddr) != chrec_dont_know)
+    return;
+
+  struct data_reference *dra = DDR_A (ddr);
+  struct data_reference *drb = DDR_B (ddr);
+
+  if (DR_IS_READ (dra) || DR_IS_READ (drb))
+    return;
+
+  gimple *stmta = DR_STMT (dra), *stmtb = DR_STMT (drb);
+
+  if (!gimple_assign_single_p (stmta) || !gimple_assign_single_p (stmtb))
+    return;
+
+  if (gimple_bb (stmta)->loop_father != gimple_bb (stmtb)->loop_father)
+    return;
+
+  tree rhsa = gimple_assign_rhs1 (stmta);
+  tree rhsb = gimple_assign_rhs1 (stmtb);
+
+  if (!TREE_CONSTANT (rhsa) || !TREE_CONSTANT (rhsb))
+    return;
+
+  int byte = const_with_all_bytes_same (rhsa);
+  if (byte == -1)
+    return;
+  if (byte != const_with_all_bytes_same (rhsb))
+    return;
+
+  /* The two data references store the same constant with the same bytes,
+     the dependence can be ignored.  */
+  finalize_ddr_dependent (ddr, chrec_known);
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    {
+      fprintf (dump_file, "(refine_affine_dependence: no dependence\n");
+      fprintf (dump_file, "  stmt_a: ");
+      print_gimple_stmt (dump_file, DR_STMT (dra), 0, TDF_SLIM);
+      fprintf (dump_file, "  stmt_b: ");
+      print_gimple_stmt (dump_file, DR_STMT (drb), 0, TDF_SLIM);
+    }
+}
+
 /* Describes a location of a memory reference.  */
 
 struct data_ref_loc
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 771d20f..bc76d26 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -554,6 +554,7 @@ extern void compute_self_dependence (struct data_dependence_relation *);
 extern bool compute_all_dependences (vec<data_reference_p> ,
 				     vec<ddr_p> *,
 				     vec<loop_p>, bool);
+extern void refine_affine_dependence (struct data_dependence_relation *);
 extern tree find_data_references_in_bb (class loop *, basic_block,
                                         vec<data_reference_p> *);
 extern unsigned int dr_alignment (innermost_loop_behavior *);
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index a4f0b1e..7f91be8 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -1073,67 +1073,6 @@ generate_loops_for_partition (class loop *loop, partition *partition,
   free (bbs);
 }
 
-/* If VAL memory representation contains the same value in all bytes,
-   return that value, otherwise return -1.
-   E.g. for 0x24242424 return 0x24, for IEEE double
-   747708026454360457216.0 return 0x44, etc.  */
-
-static int
-const_with_all_bytes_same (tree val)
-{
-  unsigned char buf[64];
-  int i, len;
-
-  if (integer_zerop (val)
-      || (TREE_CODE (val) == CONSTRUCTOR
-          && !TREE_CLOBBER_P (val)
-          && CONSTRUCTOR_NELTS (val) == 0))
-    return 0;
-
-  if (real_zerop (val))
-    {
-      /* Only return 0 for +0.0, not for -0.0, which doesn't have
-	 an all bytes same memory representation.  Don't transform
-	 -0.0 stores into +0.0 even for !HONOR_SIGNED_ZEROS.  */
-      switch (TREE_CODE (val))
-	{
-	case REAL_CST:
-	  if (!real_isneg (TREE_REAL_CST_PTR (val)))
-	    return 0;
-	  break;
-	case COMPLEX_CST:
-	  if (!const_with_all_bytes_same (TREE_REALPART (val))
-	      && !const_with_all_bytes_same (TREE_IMAGPART (val)))
-	    return 0;
-	  break;
-	case VECTOR_CST:
-	  {
-	    unsigned int count = vector_cst_encoded_nelts (val);
-	    unsigned int j;
-	    for (j = 0; j < count; ++j)
-	      if (const_with_all_bytes_same (VECTOR_CST_ENCODED_ELT (val, j)))
-		break;
-	    if (j == count)
-	      return 0;
-	    break;
-	  }
-	default:
-	  break;
-	}
-    }
-
-  if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
-    return -1;
-
-  len = native_encode_expr (val, buf, sizeof (buf));
-  if (len == 0)
-    return -1;
-  for (i = 1; i < len; i++)
-    if (buf[i] != buf[0])
-      return -1;
-  return buf[0];
-}
-
 /* Generate a call to memset for PARTITION in LOOP.  */
 
 static void
@@ -1362,6 +1301,7 @@ loop_distribution::get_data_dependence (struct graph *rdg, data_reference_p a,
     {
       ddr = initialize_data_dependence_relation (a, b, loop_nest);
       compute_affine_dependence (ddr, loop_nest[0]);
+      refine_affine_dependence (ddr);
       *slot = ddr;
     }
 
diff --git a/gcc/tree.c b/gcc/tree.c
index 298499f..739fb59 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2939,6 +2939,67 @@ really_constant_p (const_tree exp)
   return TREE_CONSTANT (exp);
 }
 
+/* If VAL memory representation contains the same value in all bytes,
+   return that value, otherwise return -1.
+   E.g. for 0x24242424 return 0x24, for IEEE double
+   747708026454360457216.0 return 0x44, etc.  */
+
+int
+const_with_all_bytes_same (tree val)
+{
+  unsigned char buf[64];
+  int i, len;
+
+  if (integer_zerop (val)
+      || (TREE_CODE (val) == CONSTRUCTOR
+          && !TREE_CLOBBER_P (val)
+          && CONSTRUCTOR_NELTS (val) == 0))
+    return 0;
+
+  if (real_zerop (val))
+    {
+      /* Only return 0 for +0.0, not for -0.0, which doesn't have
+	 an all bytes same memory representation.  Don't transform
+	 -0.0 stores into +0.0 even for !HONOR_SIGNED_ZEROS.  */
+      switch (TREE_CODE (val))
+	{
+	case REAL_CST:
+	  if (!real_isneg (TREE_REAL_CST_PTR (val)))
+	    return 0;
+	  break;
+	case COMPLEX_CST:
+	  if (!const_with_all_bytes_same (TREE_REALPART (val))
+	      && !const_with_all_bytes_same (TREE_IMAGPART (val)))
+	    return 0;
+	  break;
+	case VECTOR_CST:
+	  {
+	    unsigned int count = vector_cst_encoded_nelts (val);
+	    unsigned int j;
+	    for (j = 0; j < count; ++j)
+	      if (const_with_all_bytes_same (VECTOR_CST_ENCODED_ELT (val, j)))
+		break;
+	    if (j == count)
+	      return 0;
+	    break;
+	  }
+	default:
+	  break;
+	}
+    }
+
+  if (CHAR_BIT != 8 || BITS_PER_UNIT != 8)
+    return -1;
+
+  len = native_encode_expr (val, buf, sizeof (buf));
+  if (len == 0)
+    return -1;
+  for (i = 1; i < len; i++)
+    if (buf[i] != buf[0])
+      return -1;
+  return buf[0];
+}
+
 /* Return true if T holds a polynomial pointer difference, storing it in
    *VALUE if so.  A true return means that T's precision is no greater
    than 64 bits, which is the largest address space we support, so *VALUE
diff --git a/gcc/tree.h b/gcc/tree.h
index 9342220..8b28c9c 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5161,6 +5161,7 @@ bit_field_offset (const_tree t)
 
 extern tree strip_float_extensions (tree);
 extern bool really_constant_p (const_tree);
+extern int const_with_all_bytes_same (tree);
 extern bool ptrdiff_tree_p (const_tree, poly_int64_pod *);
 extern bool decl_address_invariant_p (const_tree);
 extern bool decl_address_ip_invariant_p (const_tree);
-- 
1.8.3.1

