From: Tom de Vries Date: Thu, 19 May 2011 09:03:12 +0000 (+0000) Subject: re PR middle-end/45098 (Missed induction variable optimization) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bb8d292d395e5ac5aaf96ff44f58822918b94859;p=gcc.git re PR middle-end/45098 (Missed induction variable optimization) 2011-05-19 Tom de Vries PR target/45098 * tree-ssa-loop-ivopts.c (get_expr_id): Factored new function out of get_loop_invariant_expr_id. (get_loop_invariant_expr_id): Use get_expr_id. (parm_decl_cost): New function. (determine_use_iv_cost_condition): Use get_expr_id and parm_decl_cost. Improve bound cost estimation. Use different inv_expr_id for elim and express cases. From-SVN: r173894 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a3ce4ef982d..a22cc926bdd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2011-05-19 Tom de Vries + + PR target/45098 + * tree-ssa-loop-ivopts.c (get_expr_id): Factored new function out of + get_loop_invariant_expr_id. + (get_loop_invariant_expr_id): Use get_expr_id. + (parm_decl_cost): New function. + (determine_use_iv_cost_condition): Use get_expr_id and parm_decl_cost. + Improve bound cost estimation. Use different inv_expr_id for elim and + express cases. + 2011-05-19 Tom de Vries PR target/45098 diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 1580aec006a..64647c9e054 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -3837,6 +3837,28 @@ compare_aff_trees (aff_tree *aff1, aff_tree *aff2) return true; } +/* Stores EXPR in DATA->inv_expr_tab, and assigns it an inv_expr_id. */ + +static int +get_expr_id (struct ivopts_data *data, tree expr) +{ + struct iv_inv_expr_ent ent; + struct iv_inv_expr_ent **slot; + + ent.expr = expr; + ent.hash = iterative_hash_expr (expr, 0); + slot = (struct iv_inv_expr_ent **) htab_find_slot (data->inv_expr_tab, + &ent, INSERT); + if (*slot) + return (*slot)->id; + + *slot = XNEW (struct iv_inv_expr_ent); + (*slot)->expr = expr; + (*slot)->hash = ent.hash; + (*slot)->id = data->inv_expr_id++; + return (*slot)->id; +} + /* Returns the pseudo expr id if expression UBASE - RATIO * CBASE requires a new compiler generated temporary. Returns -1 otherwise. ADDRESS_P is a flag indicating if the expression is for address @@ -3849,8 +3871,6 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase, { aff_tree ubase_aff, cbase_aff; tree expr, ub, cb; - struct iv_inv_expr_ent ent; - struct iv_inv_expr_ent **slot; STRIP_NOPS (ubase); STRIP_NOPS (cbase); @@ -3938,18 +3958,7 @@ get_loop_invariant_expr_id (struct ivopts_data *data, tree ubase, aff_combination_scale (&cbase_aff, shwi_to_double_int (-1 * ratio)); aff_combination_add (&ubase_aff, &cbase_aff); expr = aff_combination_to_tree (&ubase_aff); - ent.expr = expr; - ent.hash = iterative_hash_expr (expr, 0); - slot = (struct iv_inv_expr_ent **) htab_find_slot (data->inv_expr_tab, - &ent, INSERT); - if (*slot) - return (*slot)->id; - - *slot = XNEW (struct iv_inv_expr_ent); - (*slot)->expr = expr; - (*slot)->hash = ent.hash; - (*slot)->id = data->inv_expr_id++; - return (*slot)->id; + return get_expr_id (data, expr); } @@ -4414,6 +4423,23 @@ may_eliminate_iv (struct ivopts_data *data, return true; } + /* Calculates the cost of BOUND, if it is a PARM_DECL. A PARM_DECL must + be copied, if is is used in the loop body and DATA->body_includes_call. */ + +static int +parm_decl_cost (struct ivopts_data *data, tree bound) +{ + tree sbound = bound; + STRIP_NOPS (sbound); + + if (TREE_CODE (sbound) == SSA_NAME + && TREE_CODE (SSA_NAME_VAR (sbound)) == PARM_DECL + && gimple_nop_p (SSA_NAME_DEF_STMT (sbound)) + && data->body_includes_call) + return COSTS_N_INSNS (1); + + return 0; +} /* Determines cost of basing replacement of USE on CAND in a condition. */ @@ -4424,9 +4450,9 @@ determine_use_iv_cost_condition (struct ivopts_data *data, tree bound = NULL_TREE; struct iv *cmp_iv; bitmap depends_on_elim = NULL, depends_on_express = NULL, depends_on; - comp_cost elim_cost, express_cost, cost; + comp_cost elim_cost, express_cost, cost, bound_cost; bool ok; - int inv_expr_id = -1; + int elim_inv_expr_id = -1, express_inv_expr_id = -1, inv_expr_id; tree *control_var, *bound_cst; /* Only consider real candidates. */ @@ -4440,6 +4466,21 @@ determine_use_iv_cost_condition (struct ivopts_data *data, if (may_eliminate_iv (data, use, cand, &bound)) { elim_cost = force_var_cost (data, bound, &depends_on_elim); + if (elim_cost.cost == 0) + elim_cost.cost = parm_decl_cost (data, bound); + else if (TREE_CODE (bound) == INTEGER_CST) + elim_cost.cost = 0; + /* If we replace a loop condition 'i < n' with 'p < base + n', + depends_on_elim will have 'base' and 'n' set, which implies + that both 'base' and 'n' will be live during the loop. More likely, + 'base + n' will be loop invariant, resulting in only one live value + during the loop. So in that case we clear depends_on_elim and set + elim_inv_expr_id instead. */ + if (depends_on_elim && bitmap_count_bits (depends_on_elim) > 1) + { + elim_inv_expr_id = get_expr_id (data, bound); + bitmap_clear (depends_on_elim); + } /* The bound is a loop invariant, so it will be only computed once. */ elim_cost.cost = adjust_setup_cost (data, elim_cost.cost); @@ -4467,16 +4508,25 @@ determine_use_iv_cost_condition (struct ivopts_data *data, express_cost = get_computation_cost (data, use, cand, false, &depends_on_express, NULL, - &inv_expr_id); + &express_inv_expr_id); fd_ivopts_data = data; walk_tree (&cmp_iv->base, find_depends, &depends_on_express, NULL); + /* Count the cost of the original bound as well. */ + bound_cost = force_var_cost (data, *bound_cst, NULL); + if (bound_cost.cost == 0) + bound_cost.cost = parm_decl_cost (data, *bound_cst); + else if (TREE_CODE (*bound_cst) == INTEGER_CST) + bound_cost.cost = 0; + express_cost.cost += bound_cost.cost; + /* Choose the better approach, preferring the eliminated IV. */ if (compare_costs (elim_cost, express_cost) <= 0) { cost = elim_cost; depends_on = depends_on_elim; depends_on_elim = NULL; + inv_expr_id = elim_inv_expr_id; } else { @@ -4484,6 +4534,7 @@ determine_use_iv_cost_condition (struct ivopts_data *data, depends_on = depends_on_express; depends_on_express = NULL; bound = NULL_TREE; + inv_expr_id = express_inv_expr_id; } set_use_iv_cost (data, use, cand, cost, depends_on, bound, inv_expr_id);