summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr54132.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c11
-rw-r--r--gcc/tree-data-ref.c2
-rw-r--r--gcc/tree-data-ref.h2
-rw-r--r--gcc/tree-loop-distribution.c33
7 files changed, 79 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 936b7d0f588..fc193892471 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2012-09-19 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/54132
+ * tree-loop-distribution.c (classify_partition): Properly
+ check dependences for memmove.
+ * tree-data-ref.h (compute_affine_dependence): Declare.
+ * tree-data-ref.c (compute_affine_dependence): Export.
+
2012-09-19 Zhenqiang Chen <zhenqiang.chen@arm.com>
PR middle-end/54364
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index df70396f936..bf497ee1169 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2012-09-19 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/54132
+ * gcc.dg/tree-ssa/ldist-21.c: New testcase.
+ * gcc.dg/torture/pr54132.c: Likewise.
+
2012-09-19 Terry Guo <terry.guo@arm.com>
* lib/gcc-dg.exp (dg_runtest_extra_prunes): New variable to define
diff --git a/gcc/testsuite/gcc.dg/torture/pr54132.c b/gcc/testsuite/gcc.dg/torture/pr54132.c
new file mode 100644
index 00000000000..97bc01caf8d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr54132.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+
+extern void abort (void);
+void foo(char *p, int n)
+{
+ int i;
+ for (i = 1; i < n; i++)
+ p[i] = p[i - 1];
+}
+int main()
+{
+ char a[1024];
+ a[0] = 1;
+ foo (a, 1024);
+ if (a[1023] != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c
new file mode 100644
index 00000000000..35f01aba2a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-21.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-ldist-details" } */
+
+void bar(char *p, int n)
+{
+ int i;
+ for (i = 1; i < n; i++)
+ p[i-1] = p[i];
+}
+
+/* { dg-final { scan-tree-dump "generated memmove" "ldist" } } */
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 0f68fdf4020..4f6df91ec28 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -4130,7 +4130,7 @@ ddr_consistent_p (FILE *file,
relation the first time we detect a CHREC_KNOWN element for a given
subscript. */
-static void
+void
compute_affine_dependence (struct data_dependence_relation *ddr,
struct loop *loop_nest)
{
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index db33e328c3e..b00a4f752b0 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -396,6 +396,8 @@ struct data_reference *create_data_ref (loop_p, loop_p, tree, gimple, bool);
extern bool find_loop_nest (struct loop *, VEC (loop_p, heap) **);
extern struct data_dependence_relation *initialize_data_dependence_relation
(struct data_reference *, struct data_reference *, VEC (loop_p, heap) *);
+extern void compute_affine_dependence (struct data_dependence_relation *,
+ loop_p);
extern void compute_self_dependence (struct data_dependence_relation *);
extern bool compute_all_dependences (VEC (data_reference_p, heap) *,
VEC (ddr_p, heap) **, VEC (loop_p, heap) *,
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index f340eab2a0f..b24af33d7ab 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -1011,6 +1011,39 @@ classify_partition (loop_p loop, struct graph *rdg, partition_t partition)
|| !operand_equal_p (DR_STEP (single_store),
DR_STEP (single_load), 0))
return;
+ /* Now check that if there is a dependence this dependence is
+ of a suitable form for memmove. */
+ VEC(loop_p, heap) *loops = NULL;
+ ddr_p ddr;
+ VEC_safe_push (loop_p, heap, loops, loop);
+ ddr = initialize_data_dependence_relation (single_load, single_store,
+ loops);
+ compute_affine_dependence (ddr, loop);
+ VEC_free (loop_p, heap, loops);
+ if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
+ {
+ free_dependence_relation (ddr);
+ return;
+ }
+ if (DDR_ARE_DEPENDENT (ddr) != chrec_known)
+ {
+ if (DDR_NUM_DIST_VECTS (ddr) == 0)
+ {
+ free_dependence_relation (ddr);
+ return;
+ }
+ lambda_vector dist_v;
+ FOR_EACH_VEC_ELT (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v)
+ {
+ int dist = dist_v[index_in_loop_nest (loop->num,
+ DDR_LOOP_NEST (ddr))];
+ if (dist > 0 && !DDR_REVERSED_P (ddr))
+ {
+ free_dependence_relation (ddr);
+ return;
+ }
+ }
+ }
partition->kind = PKIND_MEMCPY;
partition->main_dr = single_store;
partition->secondary_dr = single_load;