X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-ssa-dom.c;h=a0d2f28290731c87c519fca33039f540bd006140;hb=b38319aba563f415e57aaf5b9ecaf00a442743e3;hp=71dcd4ffc6d9f5888355572a5f267f64bc345dcf;hpb=63315c52134b81242ec74c4e60ddc158cff37b5c;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 71dcd4ffc6d..a0d2f282907 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -42,6 +42,7 @@ Boston, MA 02110-1301, USA. */ #include "tree-pass.h" #include "tree-ssa-propagate.h" #include "langhooks.h" +#include "params.h" /* This file implements optimizations on the dominator tree. */ @@ -608,6 +609,9 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e) block_stmt_iterator bsi; tree stmt = NULL; tree phi; + int stmt_count = 0; + int max_stmt_count; + /* If E->dest does not end with a conditional, then there is nothing to do. */ @@ -637,6 +641,11 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e) tree src = PHI_ARG_DEF_FROM_EDGE (phi, e); tree dst = PHI_RESULT (phi); + /* Do not include virtual PHIs in our statement count as + they never generate code. */ + if (is_gimple_reg (dst)) + stmt_count++; + /* If the desired argument is not the same as this PHI's result and it is set by a PHI in E->dest, then we can not thread through E->dest. */ @@ -664,6 +673,7 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e) Failure to simplify into the form above merely means that the statement provides no equivalences to help simplify later statements. This does not prevent threading through E->dest. */ + max_stmt_count = PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS); for (bsi = bsi_start (e->dest); ! bsi_end_p (bsi); bsi_next (&bsi)) { tree cached_lhs = NULL; @@ -674,6 +684,12 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e) if (IS_EMPTY_STMT (stmt) || TREE_CODE (stmt) == LABEL_EXPR) continue; + /* If duplicating this block is going to cause too much code + expansion, then do not thread through this block. */ + stmt_count++; + if (stmt_count > max_stmt_count) + return; + /* Safely handle threading across loop backedges. This is over conservative, but still allows us to capture the majority of the cases where we can thread across a loop @@ -1020,14 +1036,14 @@ dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb) { tree last; - /* If we are at a leaf node in the dominator tree, see if we can thread - the edge from BB through its successor. - - Do this before we remove entries from our equivalence tables. */ + /* If we have an outgoing edge to a block with multiple incoming and + outgoing edges, then we may be able to thread the edge. ie, we + may be able to statically determine which of the outgoing edges + will be traversed when the incoming edge from BB is traversed. */ if (single_succ_p (bb) && (single_succ_edge (bb)->flags & EDGE_ABNORMAL) == 0 - && (get_immediate_dominator (CDI_DOMINATORS, single_succ (bb)) != bb - || phi_nodes (single_succ (bb)))) + && !single_pred_p (single_succ (bb)) + && !single_succ_p (single_succ (bb))) { thread_across_edge (walk_data, single_succ_edge (bb)); @@ -1044,10 +1060,9 @@ dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb) extract_true_false_edges_from_block (bb, &true_edge, &false_edge); - /* If the THEN arm is the end of a dominator tree or has PHI nodes, - then try to thread through its edge. */ - if (get_immediate_dominator (CDI_DOMINATORS, true_edge->dest) != bb - || phi_nodes (true_edge->dest)) + /* Only try to thread the edge if it reaches a target block with + more than one predecessor and more than one successor. */ + if (!single_pred_p (true_edge->dest) && !single_succ_p (true_edge->dest)) { struct edge_info *edge_info; unsigned int i; @@ -1094,8 +1109,7 @@ dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb) } /* Similarly for the ELSE arm. */ - if (get_immediate_dominator (CDI_DOMINATORS, false_edge->dest) != bb - || phi_nodes (false_edge->dest)) + if (!single_pred_p (false_edge->dest) && !single_succ_p (false_edge->dest)) { struct edge_info *edge_info; unsigned int i; @@ -1780,6 +1794,7 @@ simplify_rhs_and_lookup_avail_expr (tree stmt, int insert) assignment. Add minus to this, as we handle it specially below. */ if ((associative_tree_code (rhs_code) || rhs_code == MINUS_EXPR) && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME + && num_imm_uses (TREE_OPERAND (rhs, 0)) == 1 && is_gimple_min_invariant (TREE_OPERAND (rhs, 1))) { tree rhs_def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (rhs, 0)); @@ -3188,10 +3203,7 @@ extract_range_from_cond (tree cond, tree *hi_p, tree *lo_p, int *inverted_p) record ranges for enumerations. Presumably this is due to the fact that they're rarely used directly. They are typically cast into an integer type and used that way. */ - if (TREE_CODE (type) != INTEGER_TYPE - /* We don't know how to deal with types with variable bounds. */ - || TREE_CODE (TYPE_MIN_VALUE (type)) != INTEGER_CST - || TREE_CODE (TYPE_MAX_VALUE (type)) != INTEGER_CST) + if (TREE_CODE (type) != INTEGER_TYPE) return 0; switch (TREE_CODE (cond)) @@ -3208,12 +3220,19 @@ extract_range_from_cond (tree cond, tree *hi_p, tree *lo_p, int *inverted_p) case GE_EXPR: low = op1; + + /* Get the highest value of the type. If not a constant, use that + of its base type, if it has one. */ high = TYPE_MAX_VALUE (type); + if (TREE_CODE (high) != INTEGER_CST && TREE_TYPE (type)) + high = TYPE_MAX_VALUE (TREE_TYPE (type)); inverted = 0; break; case GT_EXPR: high = TYPE_MAX_VALUE (type); + if (TREE_CODE (high) != INTEGER_CST && TREE_TYPE (type)) + high = TYPE_MAX_VALUE (TREE_TYPE (type)); if (!tree_int_cst_lt (op1, high)) return 0; low = int_const_binop (PLUS_EXPR, op1, integer_one_node, 1); @@ -3223,11 +3242,15 @@ extract_range_from_cond (tree cond, tree *hi_p, tree *lo_p, int *inverted_p) case LE_EXPR: high = op1; low = TYPE_MIN_VALUE (type); + if (TREE_CODE (low) != INTEGER_CST && TREE_TYPE (type)) + low = TYPE_MIN_VALUE (TREE_TYPE (type)); inverted = 0; break; case LT_EXPR: low = TYPE_MIN_VALUE (type); + if (TREE_CODE (low) != INTEGER_CST && TREE_TYPE (type)) + low = TYPE_MIN_VALUE (TREE_TYPE (type)); if (!tree_int_cst_lt (low, op1)) return 0; high = int_const_binop (MINUS_EXPR, op1, integer_one_node, 1);