+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.
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),
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 ();
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)
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:
|| 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