tree-if-conv.c (tree-ssa-loop.h): Include header file.
authorBin Cheng <bin.cheng@arm.com>
Mon, 9 May 2016 11:44:03 +0000 (11:44 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Mon, 9 May 2016 11:44:03 +0000 (11:44 +0000)
* tree-if-conv.c (tree-ssa-loop.h): Include header file.
(tree-ssa-loop-niter.h): Ditto.
(idx_within_array_bound, ref_within_array_bound): New functions.
(ifcvt_memrefs_wont_trap): Check if array ref is within bound.
Factor out check on writable base object to ...
(base_object_writable): ... here.

gcc/testsuite/
* gcc.dg/tree-ssa/ifc-9.c: New test.
* gcc.dg/tree-ssa/ifc-10.c: New test.
* gcc.dg/tree-ssa/ifc-11.c: New test.
* gcc.dg/tree-ssa/ifc-12.c: New test.
* gcc.dg/vect/pr61194.c: Remove XFAIL.
* gcc.dg/vect/vect-23.c: Remove XFAIL.
* gcc.dg/vect/vect-mask-store-move-1.c: Revise test check.

From-SVN: r236026

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ifc-10.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ifc-11.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ifc-12.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ifc-9.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/pr61194.c
gcc/testsuite/gcc.dg/vect/vect-23.c
gcc/testsuite/gcc.dg/vect/vect-mask-store-move-1.c
gcc/tree-if-conv.c

index 478b179ac71c38213f29151792b9d0769a06f5bc..ad4f9f7bcffa5b78a998f43c8ab3279df4e7d71f 100644 (file)
@@ -1,3 +1,12 @@
+2016-05-09  Bin Cheng  <bin.cheng@arm.com>
+
+       * tree-if-conv.c (tree-ssa-loop.h): Include header file.
+       (tree-ssa-loop-niter.h): Ditto.
+       (idx_within_array_bound, ref_within_array_bound): New functions.
+       (ifcvt_memrefs_wont_trap): Check if array ref is within bound.
+       Factor out check on writable base object to ...
+       (base_object_writable): ... here.
+
 2016-05-09  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/arm/arm.md (probe_stack): Add modes to set source
index 02bdf337c92a5cff8804c1e7fb4e62e2579d3f9d..bcb75c42cddd346dc14b403bafd6286c7c1da934 100644 (file)
@@ -1,3 +1,13 @@
+2016-05-09  Bin Cheng  <bin.cheng@arm.com>
+
+       * gcc.dg/tree-ssa/ifc-9.c: New test.
+       * gcc.dg/tree-ssa/ifc-10.c: New test.
+       * gcc.dg/tree-ssa/ifc-11.c: New test.
+       * gcc.dg/tree-ssa/ifc-12.c: New test.
+       * gcc.dg/vect/pr61194.c: Remove XFAIL.
+       * gcc.dg/vect/vect-23.c: Remove XFAIL.
+       * gcc.dg/vect/vect-mask-store-move-1.c: Revise test check.
+
 2016-05-09  Richard Biener  <rguenther@suse.de>
 
        PR fortran/70937
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-10.c
new file mode 100644 (file)
index 0000000..70b7422
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-ifcvt-stats" } */
+/* { dg-require-visibility "" } */
+
+int b[256] = {0}, y;
+void bar (int *);
+int foo (int x, int n)
+{
+  int i;
+  int a[128];
+
+  for (i = 0; i < n; i++)
+    {
+      a[i] = i;
+      if (x > i)
+       b[i] = y;
+    }
+  bar (a);
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-11.c
new file mode 100644 (file)
index 0000000..bacf428
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-ifcvt-stats" } */
+/* { dg-require-visibility "" } */
+
+int a[1024] = {0.0};
+int b[1024] = {0.0};
+int c[1024] = {0.0};
+int foo (float *x)
+{
+  int i = 0;
+
+  for (i = 0; i < 1024; i++)
+    {
+      c[i] = (x[i] > 0.0) ? a[i] : b[i];
+    }
+
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-12.c
new file mode 100644 (file)
index 0000000..89d42b4
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-ifcvt-stats" } */
+/* { dg-require-visibility "" } */
+
+struct st
+{
+  int a[1024];
+  int b[1024];
+};
+
+struct st s = {0};
+int foo (int x)
+{
+  int i;
+  struct st *p = &s;
+
+  for (i = 0; i < 1024; i++)
+    {
+      if (x > i)
+       p->a[i] = p->b[i];
+    }
+
+  return 0;
+}
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-9.c
new file mode 100644 (file)
index 0000000..24c19c0
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -fdump-tree-ifcvt-stats" } */
+/* { dg-require-visibility "" } */
+
+extern int b[256], y;
+void bar (int *, int);
+int foo (int x, int n)
+{
+  int i;
+  int a[128];
+
+  for (i = 0; i < n; i++)
+    {
+      a[i] = i;
+      if (x > i)
+       y = b[i];
+    }
+  bar (a, y);
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
index 8d74e0096949eb1876c3620983d59d9816ada47d..f7c71b91b4889597c571618e26cda5bada742f57 100644 (file)
@@ -38,4 +38,4 @@ int main()
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
index 44bed755fd39fa62f52ca847061808509fed7445..e463f1b5cc9daf681183e2df7ece8f7c8dc2559c 100644 (file)
@@ -123,5 +123,5 @@ int main (void)
   return main1 ();
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" } } */
 /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */
index f5cae4fcf75081552f01cc118604b04604854c7c..f928dbf4c21675f886edc35a1062fbc366dfa2b9 100644 (file)
@@ -15,4 +15,4 @@ void foo (int n)
       }
 }
 
-/* { dg-final { scan-tree-dump-times "Move stmt to created bb" 6 "vect" { target { i?86-*-* x86_64-*-* } } } } */
+/* { dg-final { scan-tree-dump-times "Move stmt to created bb" 4 "vect" { target { i?86-*-* x86_64-*-* } } } } */
index 3ad8e8701ed7b7d7b2f74688e3a4a67d76aa81c6..c38e21b32ce85c19eb3d255bed3e6726f2567c48 100644 (file)
@@ -106,6 +106,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "cfgloop.h"
 #include "tree-data-ref.h"
 #include "tree-scalar-evolution.h"
+#include "tree-ssa-loop.h"
+#include "tree-ssa-loop-niter.h"
 #include "tree-ssa-loop-ivopts.h"
 #include "tree-ssa-address.h"
 #include "dbgcnt.h"
@@ -718,6 +720,105 @@ hash_memrefs_baserefs_and_store_DRs_read_written_info (data_reference_p a)
     }
 }
 
+/* Return TRUE if can prove the index IDX of an array reference REF is
+   within array bound.  Return false otherwise.  */
+
+static bool
+idx_within_array_bound (tree ref, tree *idx, void *dta)
+{
+  bool overflow;
+  widest_int niter, valid_niter, delta, wi_step;
+  tree ev, init, step;
+  tree low, high;
+  struct loop *loop = (struct loop*) dta;
+
+  /* Only support within-bound access for array references.  */
+  if (TREE_CODE (ref) != ARRAY_REF)
+    return false;
+
+  /* For arrays at the end of the structure, we are not guaranteed that they
+     do not really extend over their declared size.  However, for arrays of
+     size greater than one, this is unlikely to be intended.  */
+  if (array_at_struct_end_p (ref))
+    return false;
+
+  ev = analyze_scalar_evolution (loop, *idx);
+  ev = instantiate_parameters (loop, ev);
+  init = initial_condition (ev);
+  step = evolution_part_in_loop_num (ev, loop->num);
+
+  if (!init || TREE_CODE (init) != INTEGER_CST
+      || (step && TREE_CODE (step) != INTEGER_CST))
+    return false;
+
+  low = array_ref_low_bound (ref);
+  high = array_ref_up_bound (ref);
+
+  /* The case of nonconstant bounds could be handled, but it would be
+     complicated.  */
+  if (TREE_CODE (low) != INTEGER_CST
+      || !high || TREE_CODE (high) != INTEGER_CST)
+    return false;
+
+  /* Check if the intial idx is within bound.  */
+  if (wi::to_widest (init) < wi::to_widest (low)
+      || wi::to_widest (init) > wi::to_widest (high))
+    return false;
+
+  /* The idx is always within bound.  */
+  if (!step || integer_zerop (step))
+    return true;
+
+  if (!max_loop_iterations (loop, &niter))
+    return false;
+
+  if (wi::to_widest (step) < 0)
+    {
+      delta = wi::to_widest (init) - wi::to_widest (low);
+      wi_step = -wi::to_widest (step);
+    }
+  else
+    {
+      delta = wi::to_widest (high) - wi::to_widest (init);
+      wi_step = wi::to_widest (step);
+    }
+
+  valid_niter = wi::div_floor (delta, wi_step, SIGNED, &overflow);
+  /* The iteration space of idx is within array bound.  */
+  if (!overflow && niter <= valid_niter)
+    return true;
+
+  return false;
+}
+
+/* Return TRUE if ref is a within bound array reference.  */
+
+static bool
+ref_within_array_bound (gimple *stmt, tree ref)
+{
+  struct loop *loop = loop_containing_stmt (stmt);
+
+  gcc_assert (loop != NULL);
+  return for_each_index (&ref, idx_within_array_bound, loop);
+}
+
+
+/* Given a memory reference expression T, return TRUE if base object
+   it refers to is writable.  The base object of a memory reference
+   is the main object being referenced, which is returned by function
+   get_base_address.  */
+
+static bool
+base_object_writable (tree ref)
+{
+  tree base_tree = get_base_address (ref);
+
+  return (base_tree
+         && DECL_P (base_tree)
+         && decl_binds_to_current_def_p (base_tree)
+         && !TREE_READONLY (base_tree));
+}
+
 /* Return true when the memory references of STMT won't trap in the
    if-converted code.  There are two things that we have to check for:
 
@@ -765,8 +866,13 @@ ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs)
   if (DR_W_UNCONDITIONALLY (*master_dr))
     return true;
 
-  /* If a is unconditionally accessed then ... */
-  if (DR_RW_UNCONDITIONALLY (*master_dr))
+  /* If a is unconditionally accessed then ...
+
+     Even a is conditional access, we can treat it as an unconditional
+     one if it's an array reference and all its index are within array
+     bound.  */
+  if (DR_RW_UNCONDITIONALLY (*master_dr)
+      || ref_within_array_bound (stmt, DR_REF (a)))
     {
       /* an unconditional read won't trap.  */
       if (DR_IS_READ (a))
@@ -777,16 +883,11 @@ ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs)
       if (base_master_dr
          && DR_BASE_W_UNCONDITIONALLY (*base_master_dr))
        return PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES);
-      else
-       {
-         /* or the base is know to be not readonly.  */
-         tree base_tree = get_base_address (DR_REF (a));
-         if (DECL_P (base_tree)
-             && decl_binds_to_current_def_p (base_tree)
-             && ! TREE_READONLY (base_tree))
-           return PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES);
-       }
+      /* or the base is known to be not readonly.  */
+      else if (base_object_writable (DR_REF (a)))
+       return PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES);
     }
+
   return false;
 }