OSDN Git Service

2013-04-11 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Apr 2013 11:21:18 +0000 (11:21 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Apr 2013 11:21:18 +0000 (11:21 +0000)
PR tree-optimization/56878
* tree-flow.h (outermost_invariant_loop_for_expr): Declare.
* tree-ssa-loop-ivopts.c (outermost_invariant_loop_for_expr):
New function.
* tree-vect-data-refs.c (vect_enhance_data_refs_alignment):
Prefer to align the DR with the most invariant base address.

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

gcc/ChangeLog
gcc/tree-flow.h
gcc/tree-ssa-loop-ivopts.c
gcc/tree-vect-data-refs.c

index f9ef230..de5bee5 100644 (file)
@@ -1,3 +1,12 @@
+2013-04-11  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/56878
+       * tree-flow.h (outermost_invariant_loop_for_expr): Declare.
+       * tree-ssa-loop-ivopts.c (outermost_invariant_loop_for_expr):
+       New function.
+       * tree-vect-data-refs.c (vect_enhance_data_refs_alignment):
+       Prefer to align the DR with the most invariant base address.
+
 2013-04-11  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
 
        * opts.c (common_handle_option): Fix formatting and add FALLTHRU
index 389246d..227fe56 100644 (file)
@@ -749,6 +749,7 @@ extern void tree_check_data_deps (void);
 /* In tree-ssa-loop-ivopts.c  */
 bool expr_invariant_in_loop_p (struct loop *, tree);
 bool stmt_invariant_in_loop_p (struct loop *, gimple);
+struct loop *outermost_invariant_loop_for_expr (struct loop *, tree);
 bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode,
                                      addr_space_t);
 bool may_be_nonaddressable_p (tree expr);
index 2940bf1..0099275 100644 (file)
@@ -1367,6 +1367,54 @@ find_interesting_uses_cond (struct ivopts_data *data, gimple stmt)
   record_use (data, NULL, civ, stmt, USE_COMPARE);
 }
 
+/* Returns the outermost loop EXPR is obviously invariant in
+   relative to the loop LOOP, i.e. if all its operands are defined
+   outside of the returned loop.  Returns NULL if EXPR is not
+   even obviously invariant in LOOP.  */
+
+struct loop *
+outermost_invariant_loop_for_expr (struct loop *loop, tree expr)
+{
+  basic_block def_bb;
+  unsigned i, len;
+
+  if (is_gimple_min_invariant (expr))
+    return current_loops->tree_root;
+
+  if (TREE_CODE (expr) == SSA_NAME)
+    {
+      def_bb = gimple_bb (SSA_NAME_DEF_STMT (expr));
+      if (def_bb)
+       {
+         if (flow_bb_inside_loop_p (loop, def_bb))
+           return NULL;
+         return superloop_at_depth (loop,
+                                    loop_depth (def_bb->loop_father) + 1);
+       }
+
+      return current_loops->tree_root;
+    }
+
+  if (!EXPR_P (expr))
+    return NULL;
+
+  unsigned maxdepth = 0;
+  len = TREE_OPERAND_LENGTH (expr);
+  for (i = 0; i < len; i++)
+    {
+      struct loop *ivloop;
+      if (!TREE_OPERAND (expr, i))
+       continue;
+
+      ivloop = outermost_invariant_loop_for_expr (loop, TREE_OPERAND (expr, i));
+      if (!ivloop)
+       return NULL;
+      maxdepth = MAX (maxdepth, loop_depth (ivloop));
+    }
+
+  return superloop_at_depth (loop, maxdepth);
+}
+
 /* Returns true if expression EXPR is obviously invariant in LOOP,
    i.e. if all its operands are defined outside of the LOOP.  LOOP
    should not be the function body.  */
index e20ab1f..64f2a8b 100644 (file)
@@ -1456,20 +1456,35 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
             }
           else
             {
-              /* If we don't know all the misalignment values, we prefer
-                 peeling for data-ref that has maximum number of data-refs
+              /* If we don't know any misalignment values, we prefer
+                 peeling for data-ref that has the maximum number of data-refs
                  with the same alignment, unless the target prefers to align
                  stores over load.  */
               if (all_misalignments_unknown)
                 {
-                  if (same_align_drs_max 
-                       < STMT_VINFO_SAME_ALIGN_REFS (stmt_info).length ()
-                      || !dr0)
+                 unsigned same_align_drs
+                   = STMT_VINFO_SAME_ALIGN_REFS (stmt_info).length ();
+                  if (!dr0
+                     || same_align_drs_max < same_align_drs)
                     {
-                      same_align_drs_max
-                         = STMT_VINFO_SAME_ALIGN_REFS (stmt_info).length ();
+                      same_align_drs_max = same_align_drs;
                       dr0 = dr;
                     }
+                 /* For data-refs with the same number of related
+                    accesses prefer the one where the misalign
+                    computation will be invariant in the outermost loop.  */
+                 else if (same_align_drs_max == same_align_drs)
+                   {
+                     struct loop *ivloop0, *ivloop;
+                     ivloop0 = outermost_invariant_loop_for_expr
+                         (loop, DR_BASE_ADDRESS (dr0));
+                     ivloop = outermost_invariant_loop_for_expr
+                         (loop, DR_BASE_ADDRESS (dr));
+                     if ((ivloop && !ivloop0)
+                         || (ivloop && ivloop0
+                             && flow_loop_nested_p (ivloop, ivloop0)))
+                       dr0 = dr;
+                   }
 
                   if (!first_store && DR_IS_WRITE (dr))
                     first_store = dr;
@@ -1478,8 +1493,6 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
               /* If there are both known and unknown misaligned accesses in the
                  loop, we choose peeling amount according to the known
                  accesses.  */
-
-
               if (!supportable_dr_alignment)
                 {
                   dr0 = dr;