re PR tree-optimization/77848 (Gimple if-conversion results in redundant comparisons)
authorBill Schmidt <wschmidt@linux.vnet.ibm.com>
Wed, 16 Nov 2016 22:17:10 +0000 (22:17 +0000)
committerWilliam Schmidt <wschmidt@gcc.gnu.org>
Wed, 16 Nov 2016 22:17:10 +0000 (22:17 +0000)
2016-11-16  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

PR tree-optimization/77848
* tree-if-conv.c (version_loop_for_if_conversion): When versioning
an outer loop, only save basic block aux information for the inner
loop.
(versionable_outer_loop_p): New function.
(tree_if_conversion): Version the outer loop instead of the inner
one if the pattern will be recognized for outer-loop
vectorization.

From-SVN: r242520

gcc/ChangeLog
gcc/tree-if-conv.c

index bd70d4ea54d95e0454c86d369b680bf4c694e333..d30e6f668d98cab934b64bcf29c19a50a4a747d5 100644 (file)
@@ -1,3 +1,14 @@
+2016-11-16  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
+
+       PR tree-optimization/77848
+       * tree-if-conv.c (version_loop_for_if_conversion): When versioning
+       an outer loop, only save basic block aux information for the inner
+       loop.
+       (versionable_outer_loop_p): New function.
+       (tree_if_conversion): Version the outer loop instead of the inner
+       one if the pattern will be recognized for outer-loop
+       vectorization.
+
 2016-11-16  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gcc/bb-reorder.c: Remove 'toplev.h' include.
index 0b86ffebf7f27a461f12e2d6c91350734957b12b..e173fabf550ff2ff0455ee4b61cb7119a9f16af0 100644 (file)
@@ -2533,6 +2533,7 @@ version_loop_for_if_conversion (struct loop *loop)
   struct loop *new_loop;
   gimple *g;
   gimple_stmt_iterator gsi;
+  unsigned int save_length;
 
   g = gimple_build_call_internal (IFN_LOOP_VECTORIZED, 2,
                                  build_int_cst (integer_type_node, loop->num),
@@ -2540,8 +2541,9 @@ version_loop_for_if_conversion (struct loop *loop)
   gimple_call_set_lhs (g, cond);
 
   /* Save BB->aux around loop_version as that uses the same field.  */
-  void **saved_preds = XALLOCAVEC (void *, loop->num_nodes);
-  for (unsigned i = 0; i < loop->num_nodes; i++)
+  save_length = loop->inner ? loop->inner->num_nodes : loop->num_nodes;
+  void **saved_preds = XALLOCAVEC (void *, save_length);
+  for (unsigned i = 0; i < save_length; i++)
     saved_preds[i] = ifc_bbs[i]->aux;
 
   initialize_original_copy_tables ();
@@ -2550,7 +2552,7 @@ version_loop_for_if_conversion (struct loop *loop)
                           REG_BR_PROB_BASE, true);
   free_original_copy_tables ();
 
-  for (unsigned i = 0; i < loop->num_nodes; i++)
+  for (unsigned i = 0; i < save_length; i++)
     ifc_bbs[i]->aux = saved_preds[i];
 
   if (new_loop == NULL)
@@ -2565,6 +2567,40 @@ version_loop_for_if_conversion (struct loop *loop)
   return true;
 }
 
+/* Return true when LOOP satisfies the follow conditions that will
+   allow it to be recognized by the vectorizer for outer-loop
+   vectorization:
+    - The loop is not the root node of the loop tree.
+    - The loop has exactly one inner loop.
+    - The loop has a single exit.
+    - The loop header has a single successor, which is the inner
+      loop header.
+    - The loop exit block has a single predecessor, which is the
+      inner loop's exit block.  */
+
+static bool
+versionable_outer_loop_p (struct loop *loop)
+{
+  if (!loop_outer (loop)
+      || !loop->inner
+      || loop->inner->next
+      || !single_exit (loop)
+      || !single_succ_p (loop->header)
+      || single_succ (loop->header) != loop->inner->header)
+    return false;
+  
+  basic_block outer_exit = single_pred (loop->latch);
+  basic_block inner_exit = single_pred (loop->inner->latch);
+
+  if (!single_pred_p (outer_exit) || single_pred (outer_exit) != inner_exit)
+    return false;
+
+  if (dump_file)
+    fprintf (dump_file, "Found vectorizable outer loop for versioning\n");
+
+  return true;
+}
+
 /* Performs splitting of critical edges.  Skip splitting and return false
    if LOOP will not be converted because:
 
@@ -2767,8 +2803,16 @@ tree_if_conversion (struct loop *loop)
          || loop->dont_vectorize))
     goto cleanup;
 
+  /* Since we have no cost model, always version loops if vectorization
+     is enabled.  Either version this loop, or if the pattern is right
+     for outer-loop vectorization, version the outer loop.  In the
+     latter case we will still if-convert the original inner loop.  */
+  /* FIXME: When SLP vectorization can handle if-conversion on its own,
+     predicate all of if-conversion on flag_tree_loop_vectorize.  */
   if ((any_pred_load_store || any_complicated_phi)
-      && !version_loop_for_if_conversion (loop))
+      && !version_loop_for_if_conversion
+      (versionable_outer_loop_p (loop_outer (loop))
+       ? loop_outer (loop) : loop))
     goto cleanup;
 
   /* Now all statements are if-convertible.  Combine all the basic