]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix for PR53397 by making prefecthing less agressive
authorVenkataramanan Kumar <venkataramanan.kumar@amd.com>
Tue, 9 Oct 2012 15:48:45 +0000 (15:48 +0000)
committerVenkataramanan Kumar <vekumar@gcc.gnu.org>
Tue, 9 Oct 2012 15:48:45 +0000 (15:48 +0000)
From-SVN: r192261

gcc/ChangeLog
gcc/cfgloop.h
gcc/testsuite/gcc.dg/pr53397-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr53397-2.c [new file with mode: 0644]
gcc/tree-ssa-loop-prefetch.c

index 655f85fa10b90abb4da6acc83b709c846d497652..6d245742d977ca0946edff055a66bff1f7488474 100644 (file)
@@ -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
index 9d7b784174d3124eb42af3fc463a40b8a9f045db..80af7d8dbc439a99123682e76d292b5a0bab8c4e 100644 (file)
@@ -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 (file)
index 0000000..abb83c6
--- /dev/null
@@ -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 (file)
index 0000000..4793ae0
--- /dev/null
@@ -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" } } */
+
index fe4df9a06f7f2e83ef8b70bb62f0b749c4153924..dcc65e19abbc2374a140198d60dd6b13d6e96e21 100644 (file)
@@ -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.  */