aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorVenkataramanan Kumar <venkataramanan.kumar@amd.com>2012-10-09 15:48:45 +0000
committerVenkataramanan Kumar <vekumar@gcc.gnu.org>2012-10-09 15:48:45 +0000
commita5497b12385d3a21e336f068d5477574a78da94a (patch)
tree57e1fe2200c0ab02d5afebc842ab80d29b4aa98e /gcc
parenteeeef8f4f93036d2ea25325a3b681c338e7e143f (diff)
downloadgcc-a5497b12385d3a21e336f068d5477574a78da94a.zip
gcc-a5497b12385d3a21e336f068d5477574a78da94a.tar.gz
gcc-a5497b12385d3a21e336f068d5477574a78da94a.tar.bz2
Fix for PR53397 by making prefecthing less agressive
From-SVN: r192261
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/cfgloop.h14
-rw-r--r--gcc/testsuite/gcc.dg/pr53397-1.c28
-rw-r--r--gcc/testsuite/gcc.dg/pr53397-2.c28
-rw-r--r--gcc/tree-ssa-loop-prefetch.c77
5 files changed, 148 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 655f85f..6d24574 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,21 @@
+2012-10-09 Venkataramanan Kumar <venkataramanan.kumar@amd.com>
+
+ PR middle-end/53397
+ * tree-ssa-loop-prefetch.c (gather_memory_references_ref):
+ Perform non constant step prefetching in inner loop, only
+ when it is invariant in the entire loop nest.
+ * tree-ssa-loop-prefetch.c (dump_mem_details): New function to dump
+ base, step and delta values of memeory reference analysed for
+ prefetching.
+ * tree-ssa-loop-prefetch.c (dump_mem_ref): Call dump_mem_details
+ to print base, step and delta values of memory reference.
+ * cfgloop.h (loop_outermost): New function that returns outermost
+ loop for a given loop in a loop nest.
+ * testsuite/gcc.dg/pr53397-1.c: New test case
+ Checks we are prefecthing for loop invariant steps
+ * testsuite/gcc.dg/pr53397-2.c: New test case
+ Checks we are not prefecthing for loop variant steps
+
2012-10-09 Richard Guenther <rguenther@suse.de>
PR middle-end/54837
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index 9d7b784..80af7d8 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -712,4 +712,18 @@ extern void move_loop_invariants (void);
extern bool finite_loop_p (struct loop *);
extern void scale_loop_profile (struct loop *loop, int scale, int iteration_bound);
+/* Returns the outermost loop of the loop nest that contains LOOP.*/
+static inline struct loop *
+loop_outermost (struct loop *loop)
+{
+
+ unsigned n = VEC_length (loop_p, loop->superloops);
+
+ if (n <= 1)
+ return loop;
+
+ return VEC_index (loop_p, loop->superloops, 1);
+}
+
+
#endif /* GCC_CFGLOOP_H */
diff --git a/gcc/testsuite/gcc.dg/pr53397-1.c b/gcc/testsuite/gcc.dg/pr53397-1.c
new file mode 100644
index 0000000..abb83c6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr53397-1.c
@@ -0,0 +1,28 @@
+/* Prefetching when the step is loop invariant. */
+/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-options "-O3 -fprefetch-loop-arrays -fdump-tree-aprefetch-details --param min-insn-to-prefetch-ratio=3 --param simultaneous-prefetches=10 -fdump-tree-aprefetch-details" } */
+
+
+double data[16384];
+void prefetch_when_non_constant_step_is_invariant(int step, int n)
+{
+ int a;
+ int b;
+ for (a = 1; a < step; a++) {
+ for (b = 0; b < n; b += 2 * step) {
+
+ int i = 2*(b + a);
+ int j = 2*(b + a + step);
+
+
+ data[j] = data[i];
+ data[j+1] = data[i+1];
+ }
+ }
+}
+
+/* { dg-final { scan-tree-dump "Issued prefetch" "aprefetch" } } */
+/* { dg-final { scan-assembler "prefetcht0" } } */
+
+/* { dg-final { cleanup-tree-dump "aprefetch" } } */
diff --git a/gcc/testsuite/gcc.dg/pr53397-2.c b/gcc/testsuite/gcc.dg/pr53397-2.c
new file mode 100644
index 0000000..4793ae0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr53397-2.c
@@ -0,0 +1,28 @@
+/* Not prefetching when the step is loop variant. */
+/* { dg-do compile { target { i?86-*-* x86_64-*-* } } } */
+/* { dg-require-effective-target sse2 } */
+/* { dg-options "-O3 -fprefetch-loop-arrays -fdump-tree-aprefetch-details --param min-insn-to-prefetch-ratio=3 --param simultaneous-prefetches=10 -fdump-tree-aprefetch-details" } */
+
+double data[16384];
+void donot_prefetch_when_non_constant_step_is_variant(int step, int n)
+{
+ int a;
+ int b;
+ for (a = 1; a < step; a++,step*=2) {
+ for (b = 0; b < n; b += 2 * step) {
+
+ int i = 2*(b + a);
+ int j = 2*(b + a + step);
+
+
+ data[j] = data[i];
+ data[j+1] = data[i+1];
+ }
+ }
+}
+
+/* { dg-final { scan-tree-dump "Not prefetching" "aprefetch" } } */
+/* { dg-final { scan-tree-dump "loop variant step" "aprefetch" } } */
+
+/* { dg-final { cleanup-tree-dump "aprefetch" } } */
+
diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c
index fe4df9a..dcc65e1 100644
--- a/gcc/tree-ssa-loop-prefetch.c
+++ b/gcc/tree-ssa-loop-prefetch.c
@@ -278,29 +278,37 @@ struct mem_ref
nontemporal one. */
};
-/* Dumps information about reference REF to FILE. */
-
+/* Dumps information about memory reference */
static void
-dump_mem_ref (FILE *file, struct mem_ref *ref)
+dump_mem_details (FILE *file, tree base, tree step,
+ HOST_WIDE_INT delta, bool write_p)
{
- fprintf (file, "Reference %p:\n", (void *) ref);
-
- fprintf (file, " group %p (base ", (void *) ref->group);
- print_generic_expr (file, ref->group->base, TDF_SLIM);
+ fprintf (file, "(base ");
+ print_generic_expr (file, base, TDF_SLIM);
fprintf (file, ", step ");
- if (cst_and_fits_in_hwi (ref->group->step))
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, int_cst_value (ref->group->step));
+ if (cst_and_fits_in_hwi (step))
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, int_cst_value (step));
else
- print_generic_expr (file, ref->group->step, TDF_TREE);
+ print_generic_expr (file, step, TDF_TREE);
fprintf (file, ")\n");
-
fprintf (file, " delta ");
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, ref->delta);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, delta);
fprintf (file, "\n");
+ fprintf (file, " %s\n", write_p ? "write" : "read");
+ fprintf (file, "\n");
+}
- fprintf (file, " %s\n", ref->write_p ? "write" : "read");
+/* Dumps information about reference REF to FILE. */
- fprintf (file, "\n");
+static void
+dump_mem_ref (FILE *file, struct mem_ref *ref)
+{
+ fprintf (file, "Reference %p:\n", (void *) ref);
+
+ fprintf (file, " group %p ", (void *) ref->group);
+
+ dump_mem_details (file, ref->group->base, ref->group->step, ref->delta,
+ ref->write_p);
}
/* Finds a group with BASE and STEP in GROUPS, or creates one if it does not
@@ -537,9 +545,44 @@ gather_memory_references_ref (struct loop *loop, struct mem_ref_group **refs,
if (may_be_nonaddressable_p (base))
return false;
- /* Limit non-constant step prefetching only to the innermost loops. */
- if (!cst_and_fits_in_hwi (step) && loop->inner != NULL)
- return false;
+ /* Limit non-constant step prefetching only to the innermost loops and
+ only when the step is loop invariant in the entire loop nest. */
+ if (!cst_and_fits_in_hwi (step))
+ {
+ if (loop->inner != NULL)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Memory expression %p\n",(void *) ref );
+ print_generic_expr (dump_file, ref, TDF_TREE);
+ fprintf (dump_file,":");
+ dump_mem_details( dump_file, base, step, delta, write_p);
+ fprintf (dump_file,
+ "Ignoring %p, non-constant step prefetching is "
+ "limited to inner most loops \n",
+ (void *) ref);
+ }
+ return false;
+ }
+ else
+ {
+ if (!expr_invariant_in_loop_p (loop_outermost (loop), step))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Memory expression %p\n",(void *) ref );
+ print_generic_expr (dump_file, ref, TDF_TREE);
+ fprintf (dump_file,":");
+ dump_mem_details(dump_file, base, step, delta, write_p);
+ fprintf (dump_file,
+ "Not prefetching, ignoring %p due to "
+ "loop variant step\n",
+ (void *) ref);
+ }
+ return false;
+ }
+ }
+ }
/* Now we know that REF = &BASE + STEP * iter + DELTA, where DELTA and STEP
are integer constants. */