diff options
Diffstat (limited to 'gcc/tree-ssa-loop-ivopts.c')
-rw-r--r-- | gcc/tree-ssa-loop-ivopts.c | 310 |
1 files changed, 113 insertions, 197 deletions
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index fb72232ca8d..c01f64131ed 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -322,11 +322,6 @@ struct iv_ca_delta #define ALWAYS_PRUNE_CAND_SET_BOUND \ ((unsigned) PARAM_VALUE (PARAM_IV_ALWAYS_PRUNE_CAND_SET_BOUND)) -/* The list of trees for that the decl_rtl field must be reset is stored - here. */ - -static VEC(tree,heap) *decl_rtl_to_reset; - /* Number of uses recorded in DATA. */ static inline unsigned @@ -726,6 +721,10 @@ niter_for_exit (struct ivopts_data *data, edge exit) exit, &nfe_desc->niter, true); *slot = nfe_desc; + + if (nfe_desc->valid_p) + nfe_desc->niter.niter + = expand_simple_operations (nfe_desc->niter.niter); } else nfe_desc = *slot; @@ -773,7 +772,6 @@ tree_ssa_iv_optimize_init (struct loops *loops, struct ivopts_data *data) data->iv_uses = VEC_alloc (iv_use_p, heap, 20); data->iv_candidates = VEC_alloc (iv_cand_p, heap, 20); - decl_rtl_to_reset = VEC_alloc (tree, heap, 20); } /* Returns a memory object to that EXPR points. In case we are able to @@ -2582,106 +2580,6 @@ seq_cost (rtx seq) return cost; } -/* Produce DECL_RTL for object obj so it looks like it is stored in memory. */ -static rtx -produce_memory_decl_rtl (tree obj, int *regno) -{ - rtx x; - - gcc_assert (obj); - if (TREE_STATIC (obj) || DECL_EXTERNAL (obj)) - { - const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (obj)); - x = gen_rtx_SYMBOL_REF (Pmode, name); - } - else - x = gen_raw_REG (Pmode, (*regno)++); - - return gen_rtx_MEM (DECL_MODE (obj), x); -} - -/* Prepares decl_rtl for variables referred in *EXPR_P. Callback for - walk_tree. DATA contains the actual fake register number. */ - -static tree -prepare_decl_rtl (tree *expr_p, int *ws, void *data) -{ - tree obj = NULL_TREE; - rtx x = NULL_RTX; - int *regno = data; - - switch (TREE_CODE (*expr_p)) - { - case ADDR_EXPR: - for (expr_p = &TREE_OPERAND (*expr_p, 0); - handled_component_p (*expr_p); - expr_p = &TREE_OPERAND (*expr_p, 0)) - continue; - obj = *expr_p; - if (DECL_P (obj)) - x = produce_memory_decl_rtl (obj, regno); - break; - - case SSA_NAME: - *ws = 0; - obj = SSA_NAME_VAR (*expr_p); - if (!DECL_RTL_SET_P (obj)) - x = gen_raw_REG (DECL_MODE (obj), (*regno)++); - break; - - case VAR_DECL: - case PARM_DECL: - case RESULT_DECL: - *ws = 0; - obj = *expr_p; - - if (DECL_RTL_SET_P (obj)) - break; - - if (DECL_MODE (obj) == BLKmode) - x = produce_memory_decl_rtl (obj, regno); - else - x = gen_raw_REG (DECL_MODE (obj), (*regno)++); - - break; - - default: - break; - } - - if (x) - { - VEC_safe_push (tree, heap, decl_rtl_to_reset, obj); - SET_DECL_RTL (obj, x); - } - - return NULL_TREE; -} - -/* Determines cost of the computation of EXPR. */ - -static unsigned -computation_cost (tree expr) -{ - rtx seq, rslt; - tree type = TREE_TYPE (expr); - unsigned cost; - /* Avoid using hard regs in ways which may be unsupported. */ - int regno = LAST_VIRTUAL_REGISTER + 1; - - walk_tree (&expr, prepare_decl_rtl, ®no, NULL); - start_sequence (); - rslt = expand_expr (expr, NULL_RTX, TYPE_MODE (type), EXPAND_NORMAL); - seq = get_insns (); - end_sequence (); - - cost = seq_cost (seq); - if (MEM_P (rslt)) - cost += address_cost (XEXP (rslt, 0), TYPE_MODE (type)); - - return cost; -} - /* Returns variable containing the value of candidate CAND at statement AT. */ static tree @@ -2869,7 +2767,7 @@ get_computation_aff (struct loop *loop, happen, fold is able to apply the distributive law to obtain this form anyway. */ - aff_combination_scale (&cbase_aff, double_int_negate (&cbase_aff, rat)); + aff_combination_scale (&cbase_aff, double_int_negate (cbase_aff.mask, rat)); aff_combination_scale (&expr_aff, rat); aff_combination_add (aff, &cbase_aff); aff_combination_add (aff, &expr_aff); @@ -3226,78 +3124,77 @@ convert_cost (enum machine_mode mode_to, enum machine_mode mode_from, costs[mode_to][mode_from][unsigned_p] = cost; if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "Conversion from %sto %s costs %d\n", + fprintf (dump_file, "Conversion from %sto %s costs %d\n", GET_MODE_NAME (mode_from), GET_MODE_NAME (mode_to), cost); return cost; } -/* Estimates cost of forcing expression EXPR into a variable. */ +/* Returns the cost of forcing an integer constant in MODE to be + an operand. Not implemented yet, for now we assume all constants + are cheap (which is not always the case). */ -unsigned -force_expr_to_var_cost (tree expr) +static unsigned +integer_cost (enum machine_mode mode) { - static bool costs_initialized = false; - static unsigned integer_cost; - static unsigned symbol_cost; - static unsigned address_cost; - tree op0 = NULL_TREE, op1 = NULL_TREE, inner_type; - unsigned cost0 = 0, cost1 = 0, cost; - enum machine_mode mode; + static unsigned costs[NUM_MACHINE_MODES]; - if (!costs_initialized) + if (!costs[mode]) { - tree var = create_tmp_var_raw (integer_type_node, "test_var"); - rtx x = gen_rtx_MEM (DECL_MODE (var), - gen_rtx_SYMBOL_REF (Pmode, "test_var")); - tree addr; - tree type = build_pointer_type (integer_type_node); + /* TODO -- determine the cost. */ + costs[mode] = 1; - integer_cost = computation_cost (build_int_cst_type (integer_type_node, - 2000)); + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Cost of integer constant in %s is 0\n", + GET_MODE_NAME (mode)); + } + return costs[mode] - 1; +} - SET_DECL_RTL (var, x); - TREE_STATIC (var) = 1; - addr = build1 (ADDR_EXPR, type, var); - symbol_cost = computation_cost (addr) + 1; +/* Retunrs the cost of using a fixed address as an operand. Not implemented + yet, for now we assume all such expressions are cheap (which is not always + the case). */ - address_cost - = computation_cost (build2 (PLUS_EXPR, type, - addr, - build_int_cst_type (type, 2000))) + 1; - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "force_expr_to_var_cost:\n"); - fprintf (dump_file, " integer %d\n", (int) integer_cost); - fprintf (dump_file, " symbol %d\n", (int) symbol_cost); - fprintf (dump_file, " address %d\n", (int) address_cost); - fprintf (dump_file, " other %d\n", (int) target_spill_cost); - fprintf (dump_file, "\n"); - } +static unsigned +fixed_address_cost (void) +{ + static unsigned cost = 0; - costs_initialized = true; + if (!cost) + { + /* TODO -- determine the cost. */ + cost = 1; + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Cost of taking a fixed address is 0\n"); } + return cost - 1; +} + +/* Estimates cost of forcing expression EXPR into a variable. */ + +unsigned +force_expr_to_var_cost (tree expr) +{ + tree op0 = NULL_TREE, op1 = NULL_TREE, inner_type; + unsigned cost0 = 0, cost1 = 0, cost; + enum machine_mode mode; + STRIP_NOPS (expr); if (SSA_VAR_P (expr)) return 0; + mode = TYPE_MODE (TREE_TYPE (expr)); + if (TREE_INVARIANT (expr)) { if (TREE_CODE (expr) == INTEGER_CST) - return integer_cost; - - if (TREE_CODE (expr) == ADDR_EXPR) - { - tree obj = TREE_OPERAND (expr, 0); - - if (TREE_CODE (obj) == VAR_DECL - || TREE_CODE (obj) == PARM_DECL - || TREE_CODE (obj) == RESULT_DECL) - return symbol_cost; - } + return integer_cost (mode); - return address_cost; + /* TODO -- this might also be address of parameter, or other invariants + that do not really qualify as object with fixed address. */ + return fixed_address_cost (); } switch (TREE_CODE (expr)) @@ -3330,7 +3227,6 @@ force_expr_to_var_cost (tree expr) return target_spill_cost; } - mode = TYPE_MODE (TREE_TYPE (expr)); switch (TREE_CODE (expr)) { case PLUS_EXPR: @@ -3386,16 +3282,22 @@ force_var_cost (struct ivopts_data *data, /* Determines the cost of the computation COMP. A set of invariants the expression depends on is stored in DEPENDS_ON. COMP is modified - in the progress. */ + in the progress. OUTER_ADDITION is set to true if there is an + addition outside any multiplication in the final expression. */ static unsigned aff_combination_cost (struct ivopts_data *data, aff_tree *comp, - bitmap *depends_on) + bitmap *depends_on, bool *outer_addition) { int n_adds = comp->n - 1; unsigned i, j, cost = 0; - bool all_negated = true; + unsigned positive_terms = 0; enum machine_mode mode = TYPE_MODE (comp->type); + double_int positive, negative; + bool seen_positive; + + if (outer_addition) + *outer_addition = false; if (comp->n == 0 && !comp->rest) { @@ -3408,56 +3310,76 @@ aff_combination_cost (struct ivopts_data *data, aff_tree *comp, { n_adds++; cost += force_var_cost (data, comp->rest, depends_on); - all_negated = false; + positive_terms++; } if (!double_int_zero_p (comp->offset)) { n_adds++; - all_negated = false; + positive_terms++; } - /* Compute the cost of multiplications. Using distributivity, each - coefficient needs to be considered only once. Furthermore, we - do not need to consider both constant and its negation. + for (i = 0; i < comp->n; i++) + cost += force_var_cost (data, comp->elts[i], depends_on); + + /* Compute the cost of multiplications and number of additions. Using + distributivity, each coefficient needs to be considered only once. + Furthermore, we do not need to consider both constant and its negation. If all elements are multiplied by negative number, we must perform one multiplication by a negative constant (and use MINUS_EXPR for the rest). - Otherwise, it is possible to always multiply be a positive constant. */ + Otherwise, it is possible to always multiply be a positive constant, + which should usually be cheaper. */ for (i = 0; i < comp->n; i++) { - cost += force_var_cost (data, comp->elts[i], depends_on); - if (double_int_negative_p (comp, comp->coefs[i])) - comp->coefs[i] = double_int_negate (comp, comp->coefs[i]); - else - all_negated = false; - - if (double_int_one_p (comp->coefs[i])) + if (double_int_zero_p (comp->coefs[i])) continue; - for (j = 0; j < i; j++) - if (double_int_equal_p (comp->coefs[i], comp->coefs[j])) - break; - if (j < i) - continue; + if (double_int_negative_p (comp->mask, comp->coefs[i])) + { + negative = comp->coefs[i]; + positive = double_int_negate (comp->mask, comp->coefs[i]); + seen_positive = false; + } + else + { + positive = comp->coefs[i]; + negative = double_int_negate (comp->mask, comp->coefs[i]); + seen_positive = true; + } + + for (j = i + 1; j < comp->n; j++) + { + if (double_int_equal_p (positive, comp->coefs[j])) + seen_positive = true; + else if (!double_int_equal_p (negative, comp->coefs[j])) + continue; + comp->coefs[j] = hwi_to_double_int (0); + } - if (double_int_fits_in_hwi_p (comp, comp->coefs[i])) + if (!double_int_fits_in_hwi_p (comp->mask, comp->coefs[i])) { /* comp->coefs[i] almost always fits into HOST_WIDE_INT, so do not worry about this this case. */ cost += target_spill_cost; } else - cost += multiply_by_cost (double_int_to_hwi (comp, comp->coefs[i]), + cost += multiply_by_cost (double_int_to_hwi (comp->mask, comp->coefs[i]), mode); + + if (seen_positive) + positive_terms++; } - if (all_negated) + if (positive_terms == 0) { /* This is not really precise -- multiplying by a negative constant could be cheaper than multiplyiing by its negation and negating. */ cost += multiply_by_cost (-1, mode); } + if (outer_addition) + *outer_addition = (positive_terms >= 2); + return cost + n_adds * add_cost (mode); } @@ -3474,6 +3396,7 @@ aff_combination_cost_address (struct ivopts_data *data, aff_tree *comp, unsigned cost = 0, i, nelts; bool symbol_present = false, var_present = false, index_used = false; enum machine_mode mode = TYPE_MODE (comp->type); + bool outer_addition; /* Try finding a symbol. */ for (i = 0; i < comp->n; i++) @@ -3489,7 +3412,7 @@ aff_combination_cost_address (struct ivopts_data *data, aff_tree *comp, } } - if (double_int_fits_in_hwi_p (comp, ratio) + if (double_int_fits_in_hwi_p (comp->mask, ratio) && !double_int_one_p (ratio)) { /* Try separating index from comp. */ @@ -3499,9 +3422,9 @@ aff_combination_cost_address (struct ivopts_data *data, aff_tree *comp, if (i < comp->n) { - double_int ratio_neg = double_int_negate (comp, ratio); + double_int ratio_neg = double_int_negate (comp->mask, ratio); int n_add = -1; - rat = double_int_to_hwi (comp, ratio); + rat = double_int_to_hwi (comp->mask, ratio); for (; i < comp->n; ) { @@ -3525,9 +3448,9 @@ aff_combination_cost_address (struct ivopts_data *data, aff_tree *comp, if (!double_int_zero_p (comp->offset)) { - if (double_int_fits_in_hwi_p (comp, comp->offset)) + if (double_int_fits_in_hwi_p (comp->mask, comp->offset)) { - off = double_int_to_hwi (comp, comp->offset); + off = double_int_to_hwi (comp->mask, comp->offset); comp->offset = hwi_to_double_int (0); } else @@ -3538,13 +3461,13 @@ aff_combination_cost_address (struct ivopts_data *data, aff_tree *comp, if (nelts) { - cost += aff_combination_cost (data, comp, depends_on); + cost += aff_combination_cost (data, comp, depends_on, &outer_addition); /* We can save one addition by using BASE + INDEX addressing mode, if present and if index is not used already. */ if (index_used) var_present = true; - else if (nelts > 1) + else if (outer_addition) { var_present = true; cost -= add_cost (mode); @@ -3606,7 +3529,7 @@ get_computation_cost_at (struct ivopts_data *data, if (address_p) cost = aff_combination_cost_address (data, &comp, depends_on, rat); else - cost = aff_combination_cost (data, &comp, depends_on); + cost = aff_combination_cost (data, &comp, depends_on, NULL); gcc_assert ((signed) cost >= 0); return cost; @@ -3722,7 +3645,7 @@ may_eliminate_iv (struct ivopts_data *data, if (stmt_after_increment (loop, cand, use->stmt)) base = fold_build2 (PLUS_EXPR, type, base, step); - return select_condition_shape (niter->niter, base, step, + return select_condition_shape (loop, niter->niter, base, step, (exit->flags & EDGE_TRUE_VALUE) != 0, cmp, bound); } @@ -5616,7 +5539,6 @@ free_loop_data (struct ivopts_data *data) { unsigned i, j; bitmap_iterator bi; - tree obj; htab_empty (data->niters); @@ -5670,11 +5592,6 @@ free_loop_data (struct ivopts_data *data) } data->max_inv_id = 0; - - for (i = 0; VEC_iterate (tree, decl_rtl_to_reset, i, obj); i++) - SET_DECL_RTL (obj, NULL_RTX); - - VEC_truncate (tree, decl_rtl_to_reset, 0); } /* Finalizes data structures used by the iv optimization pass. LOOPS is the @@ -5698,7 +5615,6 @@ tree_ssa_iv_optimize_finalize (struct loops *loops, struct ivopts_data *data) BITMAP_FREE (data->important_candidates); htab_delete (data->niters); - VEC_free (tree, heap, decl_rtl_to_reset); VEC_free (iv_use_p, heap, data->iv_uses); VEC_free (iv_cand_p, heap, data->iv_candidates); } |