]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR tree-optimization/56625
authoramker <amker@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 20 Apr 2016 15:41:45 +0000 (15:41 +0000)
committeramker <amker@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 20 Apr 2016 15:41:45 +0000 (15:41 +0000)
PR tree-optimization/69489
* tree-data-ref.h (DR_INNERMOST): New macro.
* tree-if-conv.c (innermost_loop_behavior_hash): New class for
hashing struct innermost_loop_behavior.
(ref_DR_map): Remove.
(innermost_DR_map): New map.
(baseref_DR_map): Revise comment.
(hash_memrefs_baserefs_and_store_DRs_read_written_info): Store DR
to innermost_DR_map accroding to its innermost loop behavior.
(ifcvt_memrefs_wont_trap): Get DR from innermost_DR_map according
to its innermost loop behavior.
(if_convertible_loop_p_1): Remove intialization for ref_DR_map.
Add initialization for innermost_DR_map.  Record memory reference
in DR_BASE_ADDRESS if the reference is compound one or it doesn't
have innermost loop behavior.
(if_convertible_loop_p): Remove release for ref_DR_map.  Release
innermost_DR_map.

gcc/testsuite/ChangeLog
PR tree-optimization/56625
PR tree-optimization/69489
* gcc.dg/vect/pr56625.c: New test.
* gcc.dg/tree-ssa/ifc-pr69489-1.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235289 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/pr56625.c [new file with mode: 0644]
gcc/tree-data-ref.h
gcc/tree-if-conv.c

index ab668c3615b89f24fa4dd296e72f3a87c6cd5181..1f3d66b24de98cb7265425e9573c3f33d4fd37d2 100644 (file)
@@ -1,3 +1,24 @@
+2016-04-20  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/56625
+       PR tree-optimization/69489
+       * tree-data-ref.h (DR_INNERMOST): New macro.
+       * tree-if-conv.c (innermost_loop_behavior_hash): New class for
+       hashing struct innermost_loop_behavior.
+       (ref_DR_map): Remove.
+       (innermost_DR_map): New map.
+       (baseref_DR_map): Revise comment.
+       (hash_memrefs_baserefs_and_store_DRs_read_written_info): Store DR
+       to innermost_DR_map accroding to its innermost loop behavior.
+       (ifcvt_memrefs_wont_trap): Get DR from innermost_DR_map according
+       to its innermost loop behavior.
+       (if_convertible_loop_p_1): Remove intialization for ref_DR_map.
+       Add initialization for innermost_DR_map.  Record memory reference
+       in DR_BASE_ADDRESS if the reference is compound one or it doesn't
+       have innermost loop behavior.
+       (if_convertible_loop_p): Remove release for ref_DR_map.  Release
+       innermost_DR_map.
+
 2016-04-20  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (*lea<mode>_general_1): Rename from
index 543837ff57963e7d7ef9f61628d2454b0dc6b06e..50d37d21ff060fe5a6f73bb1bc4e25e1807f69d6 100644 (file)
@@ -1,3 +1,10 @@
+2016-04-20  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/56625
+       PR tree-optimization/69489
+       * gcc.dg/vect/pr56625.c: New test.
+       * gcc.dg/tree-ssa/ifc-pr69489-1.c: New test.
+
 2016-04-20  Andrew Pinski  <apinski@cavium.com>
 
        PR target/64971
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-1.c
new file mode 100644 (file)
index 0000000..4131afc
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-ifcvt-stats" { target *-*-* } } */
+
+void foo (int a[], int b[])
+{
+  int i;
+  for (i = 0; i < 100; i++)
+    {
+      if (a[i] == 0)
+       a[i] = b[i]*4;
+      else
+       a[i] = b[i]*3;
+    }
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr56625.c b/gcc/testsuite/gcc.dg/vect/pr56625.c
new file mode 100644 (file)
index 0000000..b903be3
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+void foo (int a[], int b[])
+{
+  int i;
+  for (i = 0; i < 100; i++)
+    {
+      if (a[i] == 0)
+       a[i] = b[i]*4;
+      else
+       a[i] = b[i]*3;
+    }
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
index eb24d16486c5038c03c5ac37e37817687b12c0cb..856dd58f3ad20be0c8d8e4f7cefd09d3c83b3450 100644 (file)
@@ -144,6 +144,7 @@ struct data_reference
 #define DR_STEP(DR)                (DR)->innermost.step
 #define DR_PTR_INFO(DR)            (DR)->alias.ptr_info
 #define DR_ALIGNED_TO(DR)          (DR)->innermost.aligned_to
+#define DR_INNERMOST(DR)           (DR)->innermost
 
 typedef struct data_reference *data_reference_p;
 
index 72e808ef8832b83f937f932f7ddba389965ccf2b..691811322f71e81c842bbfd63255e7f3f86bf072 100644 (file)
@@ -114,16 +114,68 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "params.h"
 
+/* Hash for struct innermost_loop_behavior.  It depends on the user to
+   free the memory.  */
+
+struct innermost_loop_behavior_hash : nofree_ptr_hash <innermost_loop_behavior>
+{
+  static inline hashval_t hash (const value_type &);
+  static inline bool equal (const value_type &,
+                           const compare_type &);
+};
+
+inline hashval_t
+innermost_loop_behavior_hash::hash (const value_type &e)
+{
+  hashval_t hash;
+
+  hash = iterative_hash_expr (e->base_address, 0);
+  hash = iterative_hash_expr (e->offset, hash);
+  hash = iterative_hash_expr (e->init, hash);
+  return iterative_hash_expr (e->step, hash);
+}
+
+inline bool
+innermost_loop_behavior_hash::equal (const value_type &e1,
+                                    const compare_type &e2)
+{
+  if ((e1->base_address && !e2->base_address)
+      || (!e1->base_address && e2->base_address)
+      || (!e1->offset && e2->offset)
+      || (e1->offset && !e2->offset)
+      || (!e1->init && e2->init)
+      || (e1->init && !e2->init)
+      || (!e1->step && e2->step)
+      || (e1->step && !e2->step))
+    return false;
+
+  if (e1->base_address && e2->base_address
+      && !operand_equal_p (e1->base_address, e2->base_address, 0))
+    return false;
+  if (e1->offset && e2->offset
+      && !operand_equal_p (e1->offset, e2->offset, 0))
+    return false;
+  if (e1->init && e2->init
+      && !operand_equal_p (e1->init, e2->init, 0))
+    return false;
+  if (e1->step && e2->step
+      && !operand_equal_p (e1->step, e2->step, 0))
+    return false;
+
+  return true;
+}
+
 /* List of basic blocks in if-conversion-suitable order.  */
 static basic_block *ifc_bbs;
 
 /* Apply more aggressive (extended) if-conversion if true.  */
 static bool aggressive_if_conv;
 
-/* Hash table to store references, DR pairs.  */
-static hash_map<tree_operand_hash, data_reference_p> *ref_DR_map;
+/* Hash table to store <DR's innermost loop behavior, DR> pairs.  */
+static hash_map<innermost_loop_behavior_hash,
+               data_reference_p> *innermost_DR_map;
 
-/* Hash table to store base reference, DR pairs.  */
+/* Hash table to store <base reference, DR> pairs.  */
 static hash_map<tree_operand_hash, data_reference_p> *baseref_DR_map;
 
 /* Structure used to predicate basic blocks.  This is attached to the
@@ -623,17 +675,12 @@ hash_memrefs_baserefs_and_store_DRs_read_written_info (data_reference_p a)
 {
 
   data_reference_p *master_dr, *base_master_dr;
-  tree ref = DR_REF (a);
   tree base_ref = DR_BASE_OBJECT (a);
+  innermost_loop_behavior *innermost = &DR_INNERMOST (a);
   tree ca = bb_predicate (gimple_bb (DR_STMT (a)));
   bool exist1, exist2;
 
-  while (TREE_CODE (ref) == COMPONENT_REF
-        || TREE_CODE (ref) == IMAGPART_EXPR
-        || TREE_CODE (ref) == REALPART_EXPR)
-    ref = TREE_OPERAND (ref, 0);
-
-  master_dr = &ref_DR_map->get_or_insert (ref, &exist1);
+  master_dr = &innermost_DR_map->get_or_insert (innermost, &exist1);
   if (!exist1)
     *master_dr = a;
 
@@ -695,21 +742,18 @@ ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs)
   data_reference_p *master_dr, *base_master_dr;
   data_reference_p a = drs[gimple_uid (stmt) - 1];
 
-  tree ref_base_a = DR_REF (a);
   tree base = DR_BASE_OBJECT (a);
+  innermost_loop_behavior *innermost = &DR_INNERMOST (a);
 
   gcc_assert (DR_STMT (a) == stmt);
+  gcc_assert (DR_BASE_ADDRESS (a) || DR_OFFSET (a)
+              || DR_INIT (a) || DR_STEP (a));
 
-  while (TREE_CODE (ref_base_a) == COMPONENT_REF
-        || TREE_CODE (ref_base_a) == IMAGPART_EXPR
-        || TREE_CODE (ref_base_a) == REALPART_EXPR)
-    ref_base_a = TREE_OPERAND (ref_base_a, 0);
+  master_dr = innermost_DR_map->get (innermost);
+  gcc_assert (master_dr != NULL);
 
-  master_dr = ref_DR_map->get (ref_base_a);
   base_master_dr = baseref_DR_map->get (base);
 
-  gcc_assert (master_dr != NULL);
-
   /* If a is unconditionally written to it doesn't trap.  */
   if (DR_W_UNCONDITIONALLY (*master_dr))
     return true;
@@ -1238,13 +1282,16 @@ if_convertible_loop_p_1 (struct loop *loop,
 
   data_reference_p dr;
 
-  ref_DR_map = new hash_map<tree_operand_hash, data_reference_p>;
+  innermost_DR_map
+         = new hash_map<innermost_loop_behavior_hash, data_reference_p>;
   baseref_DR_map = new hash_map<tree_operand_hash, data_reference_p>;
 
   predicate_bbs (loop);
 
   for (i = 0; refs->iterate (i, &dr); i++)
     {
+      tree ref = DR_REF (dr);
+
       dr->aux = XNEW (struct ifc_dr);
       DR_BASE_W_UNCONDITIONALLY (dr) = false;
       DR_RW_UNCONDITIONALLY (dr) = false;
@@ -1254,6 +1301,27 @@ if_convertible_loop_p_1 (struct loop *loop,
       IFC_DR (dr)->base_w_predicate = boolean_false_node;
       if (gimple_uid (DR_STMT (dr)) == 0)
        gimple_set_uid (DR_STMT (dr), i + 1);
+
+      /* If DR doesn't have innermost loop behavior or it's a compound
+         memory reference, we synthesize its innermost loop behavior
+         for hashing.  */
+      if (TREE_CODE (ref) == COMPONENT_REF
+          || TREE_CODE (ref) == IMAGPART_EXPR
+          || TREE_CODE (ref) == REALPART_EXPR
+          || !(DR_BASE_ADDRESS (dr) || DR_OFFSET (dr)
+              || DR_INIT (dr) || DR_STEP (dr)))
+        {
+          while (TREE_CODE (ref) == COMPONENT_REF
+                || TREE_CODE (ref) == IMAGPART_EXPR
+                || TREE_CODE (ref) == REALPART_EXPR)
+           ref = TREE_OPERAND (ref, 0);
+
+          DR_BASE_ADDRESS (dr) = ref;
+          DR_OFFSET (dr) = NULL;
+          DR_INIT (dr) = NULL;
+          DR_STEP (dr) = NULL;
+          DR_ALIGNED_TO (dr) = NULL;
+        }
       hash_memrefs_baserefs_and_store_DRs_read_written_info (dr);
     }
 
@@ -1348,8 +1416,8 @@ if_convertible_loop_p (struct loop *loop, bool *any_mask_load_store)
 
   free_data_refs (refs);
 
-  delete ref_DR_map;
-  ref_DR_map = NULL;
+  delete innermost_DR_map;
+  innermost_DR_map = NULL;
 
   delete baseref_DR_map;
   baseref_DR_map = NULL;