From 9e16e6568110b66016b082cf4143b7a8ee3077c8 Mon Sep 17 00:00:00 2001 From: Bill Schmidt Date: Wed, 16 Nov 2016 22:17:10 +0000 Subject: [PATCH] re PR tree-optimization/77848 (Gimple if-conversion results in redundant comparisons) 2016-11-16 Bill Schmidt 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 | 11 ++++++++++ gcc/tree-if-conv.c | 52 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bd70d4ea54d..d30e6f668d9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-11-16 Bill Schmidt + + 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 * gcc/bb-reorder.c: Remove 'toplev.h' include. diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 0b86ffebf7f..e173fabf550 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -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