From: Bin Cheng Date: Tue, 3 May 2016 09:04:46 +0000 (+0000) Subject: re PR tree-optimization/56541 (vectorizaton fails in conditional assignment of a... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1cfcd39eee915a7582adc113fa6e7faac8b943e4;p=gcc.git re PR tree-optimization/56541 (vectorizaton fails in conditional assignment of a constant) PR tree-optimization/56541 * doc/invoke.texi (@item max-tree-if-conversion-phi-args): New item. * params.def (PARAM_MAX_TREE_IF_CONVERSION_PHI_ARGS): new param. * tree-if-conv.c (MAX_PHI_ARG_NUM): new macro. (any_complicated_phi): new static variable. (aggressive_if_conv): delete. (if_convertible_phi_p): support phis with more than two arguments. (if_convertible_bb_p): remvoe check on aggressive_if_conv and critical pred edges. (ifcvt_split_critical_edges): support phis with more than two arguments by checking new parameter. only split critical edges if needed. (tree_if_conversion): handle simd pragma marked loop using new local variable aggressive_if_conv. check any_complicated_phi. gcc/testsuite PR tree-optimization/56541 * gcc.dg/tree-ssa/ifc-pr56541.c: new test. * gcc.dg/vect/pr56541.c: new test. From-SVN: r235808 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 45670bc2000..ffe45b718a5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2016-05-03 bin cheng + + PR tree-optimization/56541 + * doc/invoke.texi (@item max-tree-if-conversion-phi-args): New item. + * params.def (PARAM_MAX_TREE_IF_CONVERSION_PHI_ARGS): new param. + * tree-if-conv.c (MAX_PHI_ARG_NUM): new macro. + (any_complicated_phi): new static variable. + (aggressive_if_conv): delete. + (if_convertible_phi_p): support phis with more than two arguments. + (if_convertible_bb_p): remvoe check on aggressive_if_conv and + critical pred edges. + (ifcvt_split_critical_edges): support phis with more than two + arguments by checking new parameter. only split critical edges + if needed. + (tree_if_conversion): handle simd pragma marked loop using new + local variable aggressive_if_conv. check any_complicated_phi. + 2016-05-03 Bin Cheng * tree-ssa-loop-ivopts.c (get_computation_cost_at): Check depends_on diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 515d948ce71..f5413faf116 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -9020,6 +9020,10 @@ Large expressions slow the analyzer. Bound on the complexity of the expressions in the scalar evolutions analyzer. Complex expressions slow the analyzer. +@item max-tree-if-conversion-phi-args +Maximum number of arguments in a PHI supported by TREE if conversion +unless the loop is marked with simd pragma. + @item vect-max-version-for-alignment-checks The maximum number of run-time checks that can be performed when doing loop versioning for alignment in the vectorizer. diff --git a/gcc/params.def b/gcc/params.def index 9e05401f028..62a1e404a1a 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -530,6 +530,12 @@ DEFPARAM(PARAM_SCEV_MAX_EXPR_COMPLEXITY, "Bound on the complexity of the expressions in the scalar evolutions analyzer.", 10, 0, 0) +DEFPARAM (PARAM_MAX_TREE_IF_CONVERSION_PHI_ARGS, + "max-tree-if-conversion-phi-args", + "Maximum number of arguments in a PHI supported by TREE if-conversion " + "unless the loop is marked with simd pragma.", + 4, 2, 0) + DEFPARAM(PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS, "vect-max-version-for-alignment-checks", "Bound on number of runtime checks inserted by the vectorizer's loop versioning for alignment check.", diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0f91bdf7628..6ce2c7e916c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2016-05-03 bin cheng + + PR tree-optimization/56541 + * gcc.dg/tree-ssa/ifc-pr56541.c: new test. + * gcc.dg/vect/pr56541.c: new test. + 2016-05-02 Michael Meissner * gcc.target/powerpc/float128-complex-1.c: New tests for complex diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr56541.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr56541.c new file mode 100644 index 00000000000..a52bacacedf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr56541.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-ifcvt-stats" } */ + +float a,b,c,d; + +float z[1024]; int ok[1024]; +const float rBig = 150.; + +void foo() +{ + int i; + + for (i=0; i!=1024; ++i) + { + float rR = a*z[i]; + float rL = b*z[i]; + float rMin = (rR0) ? rMin : rBig; + rMin = (rMin>0) ? rMin : rMax; + ok[i] = rMin-c0) ? rMin : rBig; + rMin = (rMin>0) ? rMin : rMax; + ok[i] = rMin-c pairs. */ static hash_map *innermost_DR_map; @@ -639,13 +647,9 @@ phi_convertible_by_degenerating_args (gphi *phi) } /* Return true when PHI is if-convertible. PHI is part of loop LOOP - and it belongs to basic block BB. - - PHI is not if-convertible if: - - it has more than 2 arguments. - - When the aggressive_if_conv is set, PHI can have more than - two arguments. */ + and it belongs to basic block BB. Note at this point, it is sure + that PHI is if-convertible. This function updates global variable + ANY_COMPLICATED_PHI if PHI is complicated. */ static bool if_convertible_phi_p (struct loop *loop, basic_block bb, gphi *phi) @@ -656,17 +660,10 @@ if_convertible_phi_p (struct loop *loop, basic_block bb, gphi *phi) print_gimple_stmt (dump_file, phi, 0, TDF_SLIM); } - if (bb != loop->header) - { - if (gimple_phi_num_args (phi) > 2 - && !aggressive_if_conv - && !phi_convertible_by_degenerating_args (phi)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Phi can't be predicated by single cond.\n"); - return false; - } - } + if (bb != loop->header + && gimple_phi_num_args (phi) > 2 + && !phi_convertible_by_degenerating_args (phi)) + any_complicated_phi = true; return true; } @@ -1012,8 +1009,6 @@ has_pred_critical_p (basic_block bb) - it is after the exit block but before the latch, - its edges are not normal. - Last restriction is valid if aggressive_if_conv is false. - EXIT_BB is the basic block containing the exit of the LOOP. BB is inside LOOP. */ @@ -1062,19 +1057,6 @@ if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb) return false; } - /* At least one incoming edge has to be non-critical as otherwise edge - predicates are not equal to basic-block predicates of the edge - source. This check is skipped if aggressive_if_conv is true. */ - if (!aggressive_if_conv - && EDGE_COUNT (bb->preds) > 1 - && bb != loop->header - && all_preds_critical_p (bb)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "only critical predecessors\n"); - return false; - } - return true; } @@ -2380,11 +2362,16 @@ version_loop_for_if_conversion (struct loop *loop) return true; } -/* Performs splitting of critical edges if aggressive_if_conv is true. - Returns false if loop won't be if converted and true otherwise. */ +/* Performs splitting of critical edges. Skip splitting and return false + if LOOP will not be converted because: + + - LOOP is not well formed. + - LOOP has PHI with more than MAX_PHI_ARG_NUM arguments. + + Last restriction is valid only if AGGRESSIVE_IF_CONV is false. */ static bool -ifcvt_split_critical_edges (struct loop *loop) +ifcvt_split_critical_edges (struct loop *loop, bool aggressive_if_conv) { basic_block *body; basic_block bb; @@ -2393,30 +2380,51 @@ ifcvt_split_critical_edges (struct loop *loop) gimple *stmt; edge e; edge_iterator ei; + vec critical_edges = vNULL; - if (num <= 2) - return false; - if (loop->inner) - return false; - if (!single_exit (loop)) + /* Loop is not well formed. */ + if (num <= 2 || loop->inner || !single_exit (loop)) return false; body = get_loop_body (loop); for (i = 0; i < num; i++) { bb = body[i]; - if (bb == loop->latch - || bb_with_exit_edge_p (loop, bb)) + if (!aggressive_if_conv + && phi_nodes (bb) + && EDGE_COUNT (bb->preds) > MAX_PHI_ARG_NUM) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, + "BB %d has complicated PHI with more than %u args.\n", + bb->index, MAX_PHI_ARG_NUM); + + free (body); + critical_edges.release (); + return false; + } + if (bb == loop->latch || bb_with_exit_edge_p (loop, bb)) continue; + stmt = last_stmt (bb); /* Skip basic blocks not ending with conditional branch. */ - if (!(stmt && gimple_code (stmt) == GIMPLE_COND)) + if (!stmt || gimple_code (stmt) != GIMPLE_COND) continue; + FOR_EACH_EDGE (e, ei, bb->succs) if (EDGE_CRITICAL_P (e) && e->dest->loop_father == loop) - split_edge (e); + critical_edges.safe_push (e); } free (body); + + while (critical_edges.length () > 0) + { + e = critical_edges.pop (); + /* Don't split if bb can be predicated along non-critical edge. */ + if (EDGE_COUNT (e->dest->preds) > 2 || all_preds_critical_p (e->dest)) + split_edge (e); + } + return true; } @@ -2713,12 +2721,16 @@ static unsigned int tree_if_conversion (struct loop *loop) { unsigned int todo = 0; + bool aggressive_if_conv; + ifc_bbs = NULL; any_pred_load_store = false; + any_complicated_phi = false; - /* Set up aggressive if-conversion for loops marked with simd pragma. */ + /* Apply more aggressive if-conversion when loop or its outer loop were + marked with simd pragma. When that's the case, we try to if-convert + loop containing PHIs with more than MAX_PHI_ARG_NUM arguments. */ aggressive_if_conv = loop->force_vectorize; - /* Check either outer loop was marked with simd pragma. */ if (!aggressive_if_conv) { struct loop *outer_loop = loop_outer (loop); @@ -2726,20 +2738,20 @@ tree_if_conversion (struct loop *loop) aggressive_if_conv = true; } - if (aggressive_if_conv) - if (!ifcvt_split_critical_edges (loop)) - goto cleanup; + if (!ifcvt_split_critical_edges (loop, aggressive_if_conv)) + goto cleanup; if (!if_convertible_loop_p (loop) || !dbg_cnt (if_conversion_tree)) goto cleanup; - if (any_pred_load_store + if ((any_pred_load_store || any_complicated_phi) && ((!flag_tree_loop_vectorize && !loop->force_vectorize) || loop->dont_vectorize)) goto cleanup; - if (any_pred_load_store && !version_loop_for_if_conversion (loop)) + if ((any_pred_load_store || any_complicated_phi) + && !version_loop_for_if_conversion (loop)) goto cleanup; /* Now all statements are if-convertible. Combine all the basic @@ -2749,11 +2761,8 @@ tree_if_conversion (struct loop *loop) /* Delete dead predicate computations and repair tree correspondent to bool pattern to delete multiple uses of predicates. */ - if (aggressive_if_conv) - { - ifcvt_local_dce (loop->header); - ifcvt_repair_bool_pattern (loop->header); - } + ifcvt_local_dce (loop->header); + ifcvt_repair_bool_pattern (loop->header); todo |= TODO_cleanup_cfg; mark_virtual_operands_for_renaming (cfun);