As suggested by rth here: http://gcc.gnu.org/ml/gcc-patches/2012-07/msg01281.html
this patch converts all the #define accessors in expmed.h to use inline functions instead. By itself, doing that conversion is not very exciting. Followup patches might: * Move setters into expmed.c; * Reduce space of fields by not using NUM_MACHINE_MODES, similar to the convert_cost case; * Possibly moving the getters into expmed.c, assuming that LTO will take care of the performance hit. Doing so enables target_expmed to not be exposed everywhere. * Lazily initialize the costs. Tested on x86_64-unknown-linux-gnu. OK to commit? -Nathan * expmed.h (alg_hash, alg_hash_used_p, sdiv_pow2_cheap, smod_pow2_cheap, zero_cost, add_cost, neg_cost, shift_cost) shiftadd_cost, shiftsub0_cost, shiftsub1_cost, mul_cost, sdiv_cost, udiv_cost, mul_widen_cost, mul_highpart_cost): Delete macro definitions and re-purpose as inline functions. (alg_hash_entry_ptr, set_alg_hash_used_p, sdiv_pow2_cheap_ptr, set_sdiv_pow2_cheap, smod_pow2_cheap_ptr, set_smod_pow2_cheap, zero_cost_ptr, set_zero_cost, add_cost_ptr, set_add_cost, neg_cost_ptr, set_neg_cost, shift_cost_ptr, set_shift_cost, shiftadd_cost_ptr, set_shiftadd_cost, shiftsub0_cost_ptr, set_shiftsub0_cost, shiftsub1_cost_ptr, set_shiftsub1_cost, mul_cost_ptr, set_mul_cost, sdiv_cost_ptr, set_sdiv_cost, udiv_cost_ptr, set_udiv_cost, mul_widen_cost_ptr, set_mul_widen_cost, mul_highpart_cost_ptr, set_mul_highpart_cost): New functions. (convert_cost_ptr): New function, split out from... (set_convert_cost, convert_cost): ...here. * expmed.c, tree-ssa-loop-ivopts.c: Update for new functions. * gimple-ssa-strength-reduction.c: Likewise. --- gcc/expmed.c | 230 ++++++++++--------- gcc/expmed.h | 441 +++++++++++++++++++++++++++++++---- gcc/gimple-ssa-strength-reduction.c | 6 +- gcc/tree-ssa-loop-ivopts.c | 24 +- 4 files changed, 533 insertions(+), 168 deletions(-) diff --git a/gcc/expmed.c b/gcc/expmed.c index e660a3f..9743fc0 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -143,20 +143,24 @@ init_expmed_one_mode (struct init_expmed_rtl *all, PUT_MODE (&all->shift_sub1, mode); PUT_MODE (&all->convert, mode); - add_cost[speed][mode] = set_src_cost (&all->plus, speed); - neg_cost[speed][mode] = set_src_cost (&all->neg, speed); - mul_cost[speed][mode] = set_src_cost (&all->mult, speed); - sdiv_cost[speed][mode] = set_src_cost (&all->sdiv, speed); - udiv_cost[speed][mode] = set_src_cost (&all->udiv, speed); - - sdiv_pow2_cheap[speed][mode] = (set_src_cost (&all->sdiv_32, speed) - <= 2 * add_cost[speed][mode]); - smod_pow2_cheap[speed][mode] = (set_src_cost (&all->smod_32, speed) - <= 4 * add_cost[speed][mode]); - - shift_cost[speed][mode][0] = 0; - shiftadd_cost[speed][mode][0] = shiftsub0_cost[speed][mode][0] - = shiftsub1_cost[speed][mode][0] = add_cost[speed][mode]; + set_add_cost (speed, mode, set_src_cost (&all->plus, speed)); + set_neg_cost (speed, mode, set_src_cost (&all->neg, speed)); + set_mul_cost (speed, mode, set_src_cost (&all->mult, speed)); + set_sdiv_cost (speed, mode, set_src_cost (&all->sdiv, speed)); + set_udiv_cost (speed, mode, set_src_cost (&all->udiv, speed)); + + set_sdiv_pow2_cheap (speed, mode, (set_src_cost (&all->sdiv_32, speed) + <= 2 * add_cost (speed, mode))); + set_smod_pow2_cheap (speed, mode, (set_src_cost (&all->smod_32, speed) + <= 4 * add_cost (speed, mode))); + + set_shift_cost (speed, mode, 0, 0); + { + int cost = add_cost (speed, mode); + set_shiftadd_cost (speed, mode, 0, cost); + set_shiftsub0_cost (speed, mode, 0, cost); + set_shiftsub1_cost (speed, mode, 0, cost); + } n = MIN (MAX_BITS_PER_WORD, mode_bitsize); for (m = 1; m < n; m++) @@ -164,10 +168,10 @@ init_expmed_one_mode (struct init_expmed_rtl *all, XEXP (&all->shift, 1) = all->cint[m]; XEXP (&all->shift_mult, 1) = all->pow2[m]; - shift_cost[speed][mode][m] = set_src_cost (&all->shift, speed); - shiftadd_cost[speed][mode][m] = set_src_cost (&all->shift_add, speed); - shiftsub0_cost[speed][mode][m] = set_src_cost (&all->shift_sub0, speed); - shiftsub1_cost[speed][mode][m] = set_src_cost (&all->shift_sub1, speed); + set_shift_cost (speed, mode, m, set_src_cost (&all->shift, speed)); + set_shiftadd_cost (speed, mode, m, set_src_cost (&all->shift_add, speed)); + set_shiftsub0_cost (speed, mode, m, set_src_cost (&all->shift_sub0, speed)); + set_shiftsub1_cost (speed, mode, m, set_src_cost (&all->shift_sub1, speed)); } if (SCALAR_INT_MODE_P (mode)) @@ -181,10 +185,8 @@ init_expmed_one_mode (struct init_expmed_rtl *all, PUT_MODE (&all->wide_lshr, wider_mode); XEXP (&all->wide_lshr, 1) = GEN_INT (mode_bitsize); - mul_widen_cost[speed][wider_mode] - = set_src_cost (&all->wide_mult, speed); - mul_highpart_cost[speed][mode] - = set_src_cost (&all->wide_trunc, speed); + set_mul_widen_cost (speed, wider_mode, set_src_cost (&all->wide_mult, speed)); + set_mul_highpart_cost (speed, mode, set_src_cost (&all->wide_trunc, speed)); } for (mode_from = GET_CLASS_NARROWEST_MODE (MODE_INT); @@ -295,7 +297,7 @@ init_expmed (void) for (speed = 0; speed < 2; speed++) { crtl->maybe_hot_insn_p = speed; - zero_cost[speed] = set_src_cost (const0_rtx, speed); + set_zero_cost (speed, set_src_cost (const0_rtx, speed)); for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; @@ -308,10 +310,13 @@ init_expmed (void) init_expmed_one_mode (&all, mode, speed); } - if (alg_hash_used_p) - memset (alg_hash, 0, sizeof (alg_hash)); + if (alg_hash_used_p ()) + { + struct alg_hash_entry *p = alg_hash_entry_ptr (0); + memset (p, 0, sizeof (*p) * NUM_ALG_HASH_ENTRIES); + } else - alg_hash_used_p = true; + set_alg_hash_used_p (true); default_rtl_profile (); } @@ -2259,8 +2264,9 @@ expand_shift_1 (enum tree_code code, enum machine_mode mode, rtx shifted, && INTVAL (op1) > 0 && INTVAL (op1) < GET_MODE_PRECISION (mode) && INTVAL (op1) < MAX_BITS_PER_WORD - && shift_cost[speed][mode][INTVAL (op1)] > INTVAL (op1) * add_cost[speed][mode] - && shift_cost[speed][mode][INTVAL (op1)] != MAX_COST) + && (shift_cost (speed, mode, INTVAL (op1)) + > INTVAL (op1) * add_cost (speed, mode)) + && shift_cost (speed, mode, INTVAL (op1)) != MAX_COST) { int i; for (i = 0; i < INTVAL (op1); i++) @@ -2436,6 +2442,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, enum alg_code cache_alg = alg_zero; bool speed = optimize_insn_for_speed_p (); enum machine_mode imode; + struct alg_hash_entry *entry_ptr; /* Indicate that no algorithm is yet found. If no algorithm is found, this value will be returned and indicate failure. */ @@ -2470,13 +2477,13 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, fail now. */ if (t == 0) { - if (MULT_COST_LESS (cost_limit, zero_cost[speed])) + if (MULT_COST_LESS (cost_limit, zero_cost (speed))) return; else { alg_out->ops = 1; - alg_out->cost.cost = zero_cost[speed]; - alg_out->cost.latency = zero_cost[speed]; + alg_out->cost.cost = zero_cost (speed); + alg_out->cost.latency = zero_cost (speed); alg_out->op[0] = alg_zero; return; } @@ -2492,19 +2499,20 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, hash_index = (t ^ (unsigned int) mode ^ (speed * 256)) % NUM_ALG_HASH_ENTRIES; /* See if we already know what to do for T. */ - if (alg_hash[hash_index].t == t - && alg_hash[hash_index].mode == mode - && alg_hash[hash_index].mode == mode - && alg_hash[hash_index].speed == speed - && alg_hash[hash_index].alg != alg_unknown) + entry_ptr = alg_hash_entry_ptr (hash_index); + if (entry_ptr->t == t + && entry_ptr->mode == mode + && entry_ptr->mode == mode + && entry_ptr->speed == speed + && entry_ptr->alg != alg_unknown) { - cache_alg = alg_hash[hash_index].alg; + cache_alg = entry_ptr->alg; if (cache_alg == alg_impossible) { /* The cache tells us that it's impossible to synthesize - multiplication by T within alg_hash[hash_index].cost. */ - if (!CHEAPER_MULT_COST (&alg_hash[hash_index].cost, cost_limit)) + multiplication by T within entry_ptr->cost. */ + if (!CHEAPER_MULT_COST (&entry_ptr->cost, cost_limit)) /* COST_LIMIT is at least as restrictive as the one recorded in the hash table, in which case we have no hope of synthesizing a multiplication. Just @@ -2518,7 +2526,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, } else { - if (CHEAPER_MULT_COST (cost_limit, &alg_hash[hash_index].cost)) + if (CHEAPER_MULT_COST (cost_limit, &entry_ptr->cost)) /* The cached algorithm shows that this multiplication requires more cost than COST_LIMIT. Just return. This way, we don't clobber this cache entry with @@ -2564,10 +2572,10 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, q = t >> m; /* The function expand_shift will choose between a shift and a sequence of additions, so the observed cost is given as - MIN (m * add_cost[speed][mode], shift_cost[speed][mode][m]). */ - op_cost = m * add_cost[speed][mode]; - if (shift_cost[speed][mode][m] < op_cost) - op_cost = shift_cost[speed][mode][m]; + MIN (m * add_cost(speed, mode), shift_cost(speed, mode, m)). */ + op_cost = m * add_cost (speed, mode); + if (shift_cost (speed, mode, m) < op_cost) + op_cost = shift_cost (speed, mode, m); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_cost; synth_mult (alg_in, q, &new_limit, mode); @@ -2594,11 +2602,11 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, q = ~(~orig_t >> m); /* The function expand_shift will choose between a shift and a sequence of additions, so the observed cost is - given as MIN (m * add_cost[speed][mode], - shift_cost[speed][mode][m]). */ - op_cost = m * add_cost[speed][mode]; - if (shift_cost[speed][mode][m] < op_cost) - op_cost = shift_cost[speed][mode][m]; + given as MIN (m * add_cost(speed, mode), + shift_cost(speed, mode, m)). */ + op_cost = m * add_cost (speed, mode); + if (shift_cost (speed, mode, m) < op_cost) + op_cost = shift_cost (speed, mode, m); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_cost; synth_mult (alg_in, q, &new_limit, mode); @@ -2640,7 +2648,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, { /* T ends with ...111. Multiply by (T + 1) and subtract 1. */ - op_cost = add_cost[speed][mode]; + op_cost = add_cost (speed, mode); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_cost; synth_mult (alg_in, t + 1, &new_limit, mode); @@ -2660,7 +2668,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, { /* T ends with ...01 or ...011. Multiply by (T - 1) and add 1. */ - op_cost = add_cost[speed][mode]; + op_cost = add_cost (speed, mode); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_cost; synth_mult (alg_in, t - 1, &new_limit, mode); @@ -2682,7 +2690,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, m = exact_log2 (-orig_t + 1); if (m >= 0 && m < maxm) { - op_cost = shiftsub1_cost[speed][mode][m]; + op_cost = shiftsub1_cost (speed, mode, m); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_cost; synth_mult (alg_in, (unsigned HOST_WIDE_INT) (-orig_t + 1) >> m, @@ -2729,14 +2737,14 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, equal to its cost, otherwise assume that on superscalar hardware the shift may be executed concurrently with the earlier steps in the algorithm. */ - op_cost = add_cost[speed][mode] + shift_cost[speed][mode][m]; - if (shiftadd_cost[speed][mode][m] < op_cost) + op_cost = add_cost (speed, mode) + shift_cost (speed, mode, m); + if (shiftadd_cost (speed, mode, m) < op_cost) { - op_cost = shiftadd_cost[speed][mode][m]; + op_cost = shiftadd_cost (speed, mode, m); op_latency = op_cost; } else - op_latency = add_cost[speed][mode]; + op_latency = add_cost (speed, mode); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_latency; @@ -2768,14 +2776,14 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, equal to it's cost, otherwise assume that on superscalar hardware the shift may be executed concurrently with the earlier steps in the algorithm. */ - op_cost = add_cost[speed][mode] + shift_cost[speed][mode][m]; - if (shiftsub0_cost[speed][mode][m] < op_cost) + op_cost = add_cost (speed, mode) + shift_cost (speed, mode, m); + if (shiftsub0_cost (speed, mode, m) < op_cost) { - op_cost = shiftsub0_cost[speed][mode][m]; + op_cost = shiftsub0_cost (speed, mode, m); op_latency = op_cost; } else - op_latency = add_cost[speed][mode]; + op_latency = add_cost (speed, mode); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_latency; @@ -2809,7 +2817,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, m = exact_log2 (q); if (m >= 0 && m < maxm) { - op_cost = shiftadd_cost[speed][mode][m]; + op_cost = shiftadd_cost (speed, mode, m); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_cost; synth_mult (alg_in, (t - 1) >> m, &new_limit, mode); @@ -2834,7 +2842,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, m = exact_log2 (q); if (m >= 0 && m < maxm) { - op_cost = shiftsub0_cost[speed][mode][m]; + op_cost = shiftsub0_cost (speed, mode, m); new_limit.cost = best_cost.cost - op_cost; new_limit.latency = best_cost.latency - op_cost; synth_mult (alg_in, (t + 1) >> m, &new_limit, mode); @@ -2863,23 +2871,23 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, we are asked to find an algorithm for T within the same or lower COST_LIMIT, we can immediately return to the caller. */ - alg_hash[hash_index].t = t; - alg_hash[hash_index].mode = mode; - alg_hash[hash_index].speed = speed; - alg_hash[hash_index].alg = alg_impossible; - alg_hash[hash_index].cost = *cost_limit; + entry_ptr->t = t; + entry_ptr->mode = mode; + entry_ptr->speed = speed; + entry_ptr->alg = alg_impossible; + entry_ptr->cost = *cost_limit; return; } /* Cache the result. */ if (!cache_hit) { - alg_hash[hash_index].t = t; - alg_hash[hash_index].mode = mode; - alg_hash[hash_index].speed = speed; - alg_hash[hash_index].alg = best_alg->op[best_alg->ops]; - alg_hash[hash_index].cost.cost = best_cost.cost; - alg_hash[hash_index].cost.latency = best_cost.latency; + entry_ptr->t = t; + entry_ptr->mode = mode; + entry_ptr->speed = speed; + entry_ptr->alg = best_alg->op[best_alg->ops]; + entry_ptr->cost.cost = best_cost.cost; + entry_ptr->cost.latency = best_cost.latency; } /* If we are getting a too long sequence for `struct algorithm' @@ -2925,7 +2933,7 @@ choose_mult_variant (enum machine_mode mode, HOST_WIDE_INT val, /* Ensure that mult_cost provides a reasonable upper bound. Any constant multiplication can be performed with less than 2 * bits additions. */ - op_cost = 2 * GET_MODE_UNIT_BITSIZE (mode) * add_cost[speed][mode]; + op_cost = 2 * GET_MODE_UNIT_BITSIZE (mode) * add_cost (speed, mode); if (mult_cost > op_cost) mult_cost = op_cost; @@ -2938,7 +2946,7 @@ choose_mult_variant (enum machine_mode mode, HOST_WIDE_INT val, `unsigned int' */ if (HOST_BITS_PER_INT >= GET_MODE_UNIT_BITSIZE (mode)) { - op_cost = neg_cost[speed][mode]; + op_cost = neg_cost(speed, mode); if (MULT_COST_LESS (&alg->cost, mult_cost)) { limit.cost = alg->cost.cost - op_cost; @@ -2958,7 +2966,7 @@ choose_mult_variant (enum machine_mode mode, HOST_WIDE_INT val, } /* This proves very useful for division-by-constant. */ - op_cost = add_cost[speed][mode]; + op_cost = add_cost (speed, mode); if (MULT_COST_LESS (&alg->cost, mult_cost)) { limit.cost = alg->cost.cost - op_cost; @@ -3249,7 +3257,7 @@ expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, Exclude cost of op0 from max_cost to match the cost calculation of the synth_mult. */ max_cost = (set_src_cost (gen_rtx_MULT (mode, fake_reg, op1), speed) - - neg_cost[speed][mode]); + - neg_cost(speed, mode)); if (max_cost > 0 && choose_mult_variant (mode, -coeff, &algorithm, &variant, max_cost)) @@ -3350,7 +3358,7 @@ expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, /* Exclude cost of op0 from max_cost to match the cost calculation of the synth_mult. */ - max_cost = mul_widen_cost[speed][mode]; + max_cost = mul_widen_cost (speed, mode); if (choose_mult_variant (mode, coeff, &algorithm, &variant, max_cost)) { @@ -3564,7 +3572,7 @@ expmed_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1, /* Firstly, try using a multiplication insn that only generates the needed high part of the product, and in the sign flavor of unsignedp. */ - if (mul_highpart_cost[speed][mode] < max_cost) + if (mul_highpart_cost (speed, mode) < max_cost) { moptab = unsignedp ? umul_highpart_optab : smul_highpart_optab; tem = expand_binop (mode, moptab, op0, narrow_op1, target, @@ -3576,8 +3584,9 @@ expmed_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1, /* Secondly, same as above, but use sign flavor opposite of unsignedp. Need to adjust the result after the multiplication. */ if (size - 1 < BITS_PER_WORD - && (mul_highpart_cost[speed][mode] + 2 * shift_cost[speed][mode][size-1] - + 4 * add_cost[speed][mode] < max_cost)) + && (mul_highpart_cost (speed, mode) + + 2 * shift_cost (speed, mode, size-1) + + 4 * add_cost (speed, mode) < max_cost)) { moptab = unsignedp ? smul_highpart_optab : umul_highpart_optab; tem = expand_binop (mode, moptab, op0, narrow_op1, target, @@ -3591,7 +3600,7 @@ expmed_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1, /* Try widening multiplication. */ moptab = unsignedp ? umul_widen_optab : smul_widen_optab; if (widening_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing - && mul_widen_cost[speed][wider_mode] < max_cost) + && mul_widen_cost (speed, wider_mode) < max_cost) { tem = expand_binop (wider_mode, moptab, op0, narrow_op1, 0, unsignedp, OPTAB_WIDEN); @@ -3602,7 +3611,8 @@ expmed_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1, /* Try widening the mode and perform a non-widening multiplication. */ if (optab_handler (smul_optab, wider_mode) != CODE_FOR_nothing && size - 1 < BITS_PER_WORD - && mul_cost[speed][wider_mode] + shift_cost[speed][mode][size-1] < max_cost) + && (mul_cost (speed, wider_mode) + shift_cost (speed, mode, size-1) + < max_cost)) { rtx insns, wop0, wop1; @@ -3629,8 +3639,9 @@ expmed_mult_highpart_optab (enum machine_mode mode, rtx op0, rtx op1, moptab = unsignedp ? smul_widen_optab : umul_widen_optab; if (widening_optab_handler (moptab, wider_mode, mode) != CODE_FOR_nothing && size - 1 < BITS_PER_WORD - && (mul_widen_cost[speed][wider_mode] + 2 * shift_cost[speed][mode][size-1] - + 4 * add_cost[speed][mode] < max_cost)) + && (mul_widen_cost (speed, wider_mode) + + 2 * shift_cost (speed, mode, size-1) + + 4 * add_cost (speed, mode) < max_cost)) { tem = expand_binop (wider_mode, moptab, op0, narrow_op1, NULL_RTX, ! unsignedp, OPTAB_WIDEN); @@ -3684,13 +3695,13 @@ expmed_mult_highpart (enum machine_mode mode, rtx op0, rtx op1, return expmed_mult_highpart_optab (mode, op0, op1, target, unsignedp, max_cost); - extra_cost = shift_cost[speed][mode][GET_MODE_BITSIZE (mode) - 1]; + extra_cost = shift_cost (speed, mode, GET_MODE_BITSIZE (mode) - 1); /* Check whether we try to multiply by a negative constant. */ if (!unsignedp && ((cnst1 >> (GET_MODE_BITSIZE (mode) - 1)) & 1)) { sign_adjust = true; - extra_cost += add_cost[speed][mode]; + extra_cost += add_cost (speed, mode); } /* See whether shift/add multiplication is cheap enough. */ @@ -3880,7 +3891,8 @@ expand_sdiv_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) temp = gen_reg_rtx (mode); temp = emit_store_flag (temp, LT, op0, const0_rtx, mode, 0, -1); - if (shift_cost[optimize_insn_for_speed_p ()][mode][ushift] > COSTS_N_INSNS (1)) + if (shift_cost (optimize_insn_for_speed_p (), mode, ushift) + > COSTS_N_INSNS (1)) temp = expand_binop (mode, and_optab, temp, GEN_INT (d - 1), NULL_RTX, 0, OPTAB_LIB_WIDEN); else @@ -4083,10 +4095,13 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, /* Only deduct something for a REM if the last divide done was for a different constant. Then set the constant of the last divide. */ - max_cost = unsignedp ? udiv_cost[speed][compute_mode] : sdiv_cost[speed][compute_mode]; + max_cost = (unsignedp + ? udiv_cost (speed, compute_mode) + : sdiv_cost (speed, compute_mode)); if (rem_flag && ! (last_div_const != 0 && op1_is_constant && INTVAL (op1) == last_div_const)) - max_cost -= mul_cost[speed][compute_mode] + add_cost[speed][compute_mode]; + max_cost -= (mul_cost (speed, compute_mode) + + add_cost (speed, compute_mode)); last_div_const = ! rem_flag && op1_is_constant ? INTVAL (op1) : 0; @@ -4200,9 +4215,9 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, goto fail1; extra_cost - = (shift_cost[speed][compute_mode][post_shift - 1] - + shift_cost[speed][compute_mode][1] - + 2 * add_cost[speed][compute_mode]); + = (shift_cost (speed, compute_mode, post_shift - 1) + + shift_cost (speed, compute_mode, 1) + + 2 * add_cost (speed, compute_mode)); t1 = expmed_mult_highpart (compute_mode, op0, GEN_INT (ml), NULL_RTX, 1, @@ -4233,8 +4248,8 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, (RSHIFT_EXPR, compute_mode, op0, pre_shift, NULL_RTX, 1); extra_cost - = (shift_cost[speed][compute_mode][pre_shift] - + shift_cost[speed][compute_mode][post_shift]); + = (shift_cost (speed, compute_mode, pre_shift) + + shift_cost (speed, compute_mode, post_shift)); t2 = expmed_mult_highpart (compute_mode, t1, GEN_INT (ml), NULL_RTX, 1, @@ -4293,8 +4308,9 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, goto fail1; } else if (EXACT_POWER_OF_2_OR_ZERO_P (d) - && (rem_flag ? smod_pow2_cheap[speed][compute_mode] - : sdiv_pow2_cheap[speed][compute_mode]) + && (rem_flag + ? smod_pow2_cheap (speed, compute_mode) + : sdiv_pow2_cheap (speed, compute_mode)) /* We assume that cheap metric is true if the optab has an expander for this mode. */ && ((optab_handler ((rem_flag ? smod_optab @@ -4314,7 +4330,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, return gen_lowpart (mode, remainder); } - if (sdiv_pow2_cheap[speed][compute_mode] + if (sdiv_pow2_cheap (speed, compute_mode) && ((optab_handler (sdiv_optab, compute_mode) != CODE_FOR_nothing) || (optab_handler (sdivmod_optab, compute_mode) @@ -4358,9 +4374,9 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, || size - 1 >= BITS_PER_WORD) goto fail1; - extra_cost = (shift_cost[speed][compute_mode][post_shift] - + shift_cost[speed][compute_mode][size - 1] - + add_cost[speed][compute_mode]); + extra_cost = (shift_cost (speed, compute_mode, post_shift) + + shift_cost (speed, compute_mode, size - 1) + + add_cost (speed, compute_mode)); t1 = expmed_mult_highpart (compute_mode, op0, GEN_INT (ml), NULL_RTX, 0, max_cost - extra_cost); @@ -4393,9 +4409,9 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, ml |= (~(unsigned HOST_WIDE_INT) 0) << (size - 1); mlr = gen_int_mode (ml, compute_mode); - extra_cost = (shift_cost[speed][compute_mode][post_shift] - + shift_cost[speed][compute_mode][size - 1] - + 2 * add_cost[speed][compute_mode]); + extra_cost = (shift_cost (speed, compute_mode, post_shift) + + shift_cost (speed, compute_mode, size - 1) + + 2 * add_cost (speed, compute_mode)); t1 = expmed_mult_highpart (compute_mode, op0, mlr, NULL_RTX, 0, max_cost - extra_cost); @@ -4481,9 +4497,9 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, size - 1, NULL_RTX, 0); t2 = expand_binop (compute_mode, xor_optab, op0, t1, NULL_RTX, 0, OPTAB_WIDEN); - extra_cost = (shift_cost[speed][compute_mode][post_shift] - + shift_cost[speed][compute_mode][size - 1] - + 2 * add_cost[speed][compute_mode]); + extra_cost = (shift_cost (speed, compute_mode, post_shift) + + shift_cost (speed, compute_mode, size - 1) + + 2 * add_cost (speed, compute_mode)); t3 = expmed_mult_highpart (compute_mode, t2, GEN_INT (ml), NULL_RTX, 1, max_cost - extra_cost); diff --git a/gcc/expmed.h b/gcc/expmed.h index ea141bc..97e17f3 100644 --- a/gcc/expmed.h +++ b/gcc/expmed.h @@ -171,45 +171,393 @@ extern struct target_expmed *this_target_expmed; #define this_target_expmed (&default_target_expmed) #endif -#define alg_hash \ - (this_target_expmed->x_alg_hash) -#define alg_hash_used_p \ - (this_target_expmed->x_alg_hash_used_p) -#define sdiv_pow2_cheap \ - (this_target_expmed->x_sdiv_pow2_cheap) -#define smod_pow2_cheap \ - (this_target_expmed->x_smod_pow2_cheap) -#define zero_cost \ - (this_target_expmed->x_zero_cost) -#define add_cost \ - (this_target_expmed->x_add_cost) -#define neg_cost \ - (this_target_expmed->x_neg_cost) -#define shift_cost \ - (this_target_expmed->x_shift_cost) -#define shiftadd_cost \ - (this_target_expmed->x_shiftadd_cost) -#define shiftsub0_cost \ - (this_target_expmed->x_shiftsub0_cost) -#define shiftsub1_cost \ - (this_target_expmed->x_shiftsub1_cost) -#define mul_cost \ - (this_target_expmed->x_mul_cost) -#define sdiv_cost \ - (this_target_expmed->x_sdiv_cost) -#define udiv_cost \ - (this_target_expmed->x_udiv_cost) -#define mul_widen_cost \ - (this_target_expmed->x_mul_widen_cost) -#define mul_highpart_cost \ - (this_target_expmed->x_mul_highpart_cost) +/* Return a pointer to the alg_hash_entry at IDX. */ -/* Set the COST for converting from FROM_MODE to TO_MODE when optimizing +static inline struct alg_hash_entry * +alg_hash_entry_ptr (int idx) +{ + return &this_target_expmed->x_alg_hash[idx]; +} + +/* Return true if the x_alg_hash field might have been used. */ + +static inline bool +alg_hash_used_p (void) +{ + return this_target_expmed->x_alg_hash_used_p; +} + +/* Set whether the x_alg_hash field might have been used. */ + +static inline void +set_alg_hash_used_p (bool usedp) +{ + this_target_expmed->x_alg_hash_used_p = usedp; +} + +/* Subroutine of {set_,}sdiv_pow2_cheap. Not to be used otherwise. */ + +static inline bool * +sdiv_pow2_cheap_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_sdiv_pow2_cheap[speed][mode]; +} + +/* Set whether a signed division by a power of 2 is cheap in MODE + when optimizing for SPEED. */ + +static inline void +set_sdiv_pow2_cheap (bool speed, enum machine_mode mode, bool cheap_p) +{ + *sdiv_pow2_cheap_ptr (speed, mode) = cheap_p; +} + +/* Return whether a signed division by a power of 2 is cheap in MODE + when optimizing for SPEED. */ + +static inline bool +sdiv_pow2_cheap (bool speed, enum machine_mode mode) +{ + return *sdiv_pow2_cheap_ptr (speed, mode); +} + +/* Subroutine of {set_,}smod_pow2_cheap. Not to be used otherwise. */ + +static inline bool * +smod_pow2_cheap_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_smod_pow2_cheap[speed][mode]; +} + +/* Set whether a signed modulo by a power of 2 is CHEAP in MODE when + optimizing for SPEED. */ + +static inline void +set_smod_pow2_cheap (bool speed, enum machine_mode mode, bool cheap) +{ + *smod_pow2_cheap_ptr (speed, mode) = cheap; +} + +/* Return whether a signed modulo by a power of 2 is cheap in MODE + when optimizing for SPEED. */ + +static inline bool +smod_pow2_cheap (bool speed, enum machine_mode mode) +{ + return *smod_pow2_cheap_ptr (speed, mode); +} + +/* Subroutine of {set_,}zero_cost. Not to be used otherwise. */ + +static inline int * +zero_cost_ptr (bool speed) +{ + return &this_target_expmed->x_zero_cost[speed]; +} + +/* Set the COST of loading zero when optimizing for SPEED. */ + +static inline void +set_zero_cost (bool speed, int cost) +{ + *zero_cost_ptr (speed) = cost; +} + +/* Return the COST of loading zero when optimizing for SPEED. */ + +static inline int +zero_cost (bool speed) +{ + return *zero_cost_ptr (speed); +} + +/* Subroutine of {set_,}add_cost. Not to be used otherwise. */ + +static inline int * +add_cost_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_add_cost[speed][mode]; +} + +/* Set the COST of computing an add in MODE when optimizing for SPEED. */ + +static inline void +set_add_cost (bool speed, enum machine_mode mode, int cost) +{ + *add_cost_ptr (speed, mode) = cost; +} + +/* Return the cost of computing an add in MODE when optimizing for SPEED. */ + +static inline int +add_cost (bool speed, enum machine_mode mode) +{ + return *add_cost_ptr (speed, mode); +} + +/* Subroutine of {set_,}neg_cost. Not to be used otherwise. */ + +static inline int * +neg_cost_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_neg_cost[speed][mode]; +} + +/* Set the COST of computing a negation in MODE when optimizing for SPEED. */ + +static inline void +set_neg_cost (bool speed, enum machine_mode mode, int cost) +{ + *neg_cost_ptr (speed, mode) = cost; +} + +/* Return the cost of computing a negation in MODE when optimizing for + SPEED. */ + +static inline int +neg_cost (bool speed, enum machine_mode mode) +{ + return *neg_cost_ptr (speed, mode); +} + +/* Subroutine of {set_,}shift_cost. Not to be used otherwise. */ + +static inline int * +shift_cost_ptr (bool speed, enum machine_mode mode, int bits) +{ + return &this_target_expmed->x_shift_cost[speed][mode][bits]; +} + +/* Set the COST of doing a shift in MODE by BITS when optimizing for SPEED. */ + +static inline void +set_shift_cost (bool speed, enum machine_mode mode, int bits, int cost) +{ + *shift_cost_ptr (speed, mode, bits) = cost; +} + +/* Return the cost of doing a shift in MODE by BITS when optimizing for + SPEED. */ + +static inline int +shift_cost (bool speed, enum machine_mode mode, int bits) +{ + return *shift_cost_ptr (speed, mode, bits); +} + +/* Subroutine of {set_,}shiftadd_cost. Not to be used otherwise. */ + +static inline int * +shiftadd_cost_ptr (bool speed, enum machine_mode mode, int bits) +{ + return &this_target_expmed->x_shiftadd_cost[speed][mode][bits]; +} + +/* Set the COST of doing a shift in MODE by BITS followed by an add when + optimizing for SPEED. */ + +static inline void +set_shiftadd_cost (bool speed, enum machine_mode mode, int bits, int cost) +{ + *shiftadd_cost_ptr (speed, mode, bits) = cost; +} + +/* Return the cost of doing a shift in MODE by BITS followed by an add + when optimizing for SPEED. */ + +static inline int +shiftadd_cost (bool speed, enum machine_mode mode, int bits) +{ + return *shiftadd_cost_ptr (speed, mode, bits); +} + +/* Subroutine of {set_,}shiftsub0_cost. Not to be used otherwise. */ + +static inline int * +shiftsub0_cost_ptr (bool speed, enum machine_mode mode, int bits) +{ + return &this_target_expmed->x_shiftsub0_cost[speed][mode][bits]; +} + +/* Set the COST of doing a shift in MODE by BITS and then subtracting a + value when optimizing for SPEED. */ + +static inline void +set_shiftsub0_cost (bool speed, enum machine_mode mode, int bits, int cost) +{ + *shiftsub0_cost_ptr (speed, mode, bits) = cost; +} + +/* Return the cost of doing a shift in MODE by BITS and then subtracting + a value when optimizing for SPEED. */ + +static inline int +shiftsub0_cost (bool speed, enum machine_mode mode, int bits) +{ + return *shiftsub0_cost_ptr (speed, mode, bits); +} + +/* Subroutine of {set_,}shiftsub1_cost. Not to be used otherwise. */ + +static inline int * +shiftsub1_cost_ptr (bool speed, enum machine_mode mode, int bits) +{ + return &this_target_expmed->x_shiftsub1_cost[speed][mode][bits]; +} + +/* Set the COST of subtracting a shift in MODE by BITS from a value when + optimizing for SPEED. */ + +static inline void +set_shiftsub1_cost (bool speed, enum machine_mode mode, int bits, int cost) +{ + *shiftsub1_cost_ptr (speed, mode, bits) = cost; +} + +/* Return the cost of subtracting a shift in MODE by BITS from a value + when optimizing for SPEED. */ + +static inline int +shiftsub1_cost (bool speed, enum machine_mode mode, int bits) +{ + return *shiftsub1_cost_ptr (speed, mode, bits); +} + +/* Subroutine of {set_,}mul_cost. Not to be used otherwise. */ + +static inline int * +mul_cost_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_mul_cost[speed][mode]; +} + +/* Set the COST of doing a multiplication in MODE when optimizing for + SPEED. */ + +static inline void +set_mul_cost (bool speed, enum machine_mode mode, int cost) +{ + *mul_cost_ptr (speed, mode) = cost; +} + +/* Return the cost of doing a multiplication in MODE when optimizing + for SPEED. */ + +static inline int +mul_cost (bool speed, enum machine_mode mode) +{ + return *mul_cost_ptr (speed, mode); +} + +/* Subroutine of {set_,}sdiv_cost. Not to be used otherwise. */ + +static inline int * +sdiv_cost_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_sdiv_cost[speed][mode]; +} + +/* Set the COST of doing a signed division in MODE when optimizing for SPEED. */ static inline void -set_convert_cost (enum machine_mode to_mode, enum machine_mode from_mode, - bool speed, int cost) +set_sdiv_cost (bool speed, enum machine_mode mode, int cost) +{ + *sdiv_cost_ptr (speed, mode) = cost; +} + +/* Return the cost of doing a signed division in MODE when optimizing + for SPEED. */ + +static inline int +sdiv_cost (bool speed, enum machine_mode mode) +{ + return *sdiv_cost_ptr (speed, mode); +} + +/* Subroutine of {set_,}udiv_cost. Not to be used otherwise. */ + +static inline int * +udiv_cost_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_udiv_cost[speed][mode]; +} + +/* Set the COST of doing an unsigned division in MODE when optimizing + for SPEED. */ + +static inline void +set_udiv_cost (bool speed, enum machine_mode mode, int cost) +{ + *udiv_cost_ptr (speed, mode) = cost; +} + +/* Return the cost of doing an unsigned division in MODE when + optimizing for SPEED. */ + +static inline int +udiv_cost (bool speed, enum machine_mode mode) +{ + return *udiv_cost_ptr (speed, mode); +} + +/* Subroutine of {set_,}mul_widen_cost. Not to be used otherwise. */ + +static inline int * +mul_widen_cost_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_mul_widen_cost[speed][mode]; +} + +/* Set the COST for computing a widening multiplication in MODE when + optimizing for SPEED. */ + +static inline void +set_mul_widen_cost (bool speed, enum machine_mode mode, int cost) +{ + *mul_widen_cost_ptr (speed, mode) = cost; +} + +/* Return the cost for computing a widening multiplication in MODE when + optimizing for SPEED. */ + +static inline int +mul_widen_cost (bool speed, enum machine_mode mode) +{ + return *mul_widen_cost_ptr (speed, mode); +} + +/* Subroutine of {set_,}mul_highpart_cost. Not to be used otherwise. */ + +static inline int * +mul_highpart_cost_ptr (bool speed, enum machine_mode mode) +{ + return &this_target_expmed->x_mul_highpart_cost[speed][mode]; +} + +/* Set the COST for computing the high part of a multiplication in MODE + when optimizing for SPEED. */ + +static inline void +set_mul_highpart_cost (bool speed, enum machine_mode mode, int cost) +{ + *mul_highpart_cost_ptr (speed, mode) = cost; +} + +/* Return the cost for computing the high part of a multiplication in MODE + when optimizing for SPEED. */ + +static inline int +mul_highpart_cost (bool speed, enum machine_mode mode) +{ + return *mul_highpart_cost_ptr (speed, mode); +} + +/* Subroutine of {set_,}convert_cost. Not to be used otherwise. */ + +static inline int * +convert_cost_ptr (enum machine_mode to_mode, enum machine_mode from_mode, + bool speed) { int to_idx, from_idx; @@ -220,7 +568,17 @@ set_convert_cost (enum machine_mode to_mode, enum machine_mode from_mode, to_idx = to_mode - MIN_MODE_INT; from_idx = from_mode - MIN_MODE_INT; - this_target_expmed->x_convert_cost[speed][to_idx][from_idx] = cost; + return &this_target_expmed->x_convert_cost[speed][to_idx][from_idx]; +} + +/* Set the COST for converting from FROM_MODE to TO_MODE when optimizing + for SPEED. */ + +static inline void +set_convert_cost (enum machine_mode to_mode, enum machine_mode from_mode, + bool speed, int cost) +{ + *convert_cost_ptr (to_mode, from_mode, speed) = cost; } /* Return the cost for converting from FROM_MODE to TO_MODE when optimizing @@ -230,16 +588,7 @@ static inline int convert_cost (enum machine_mode to_mode, enum machine_mode from_mode, bool speed) { - int to_idx, from_idx; - - gcc_assert (to_mode >= MIN_MODE_INT - && to_mode <= MAX_MODE_INT - && from_mode >= MIN_MODE_INT - && from_mode <= MAX_MODE_INT); - - to_idx = to_mode - MIN_MODE_INT; - from_idx = from_mode - MIN_MODE_INT; - return this_target_expmed->x_convert_cost[speed][to_idx][from_idx]; + return *convert_cost_ptr (to_mode, from_mode, speed); } extern int mult_by_coeff_cost (HOST_WIDE_INT, enum machine_mode, bool); diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index afeb70f..66ddfd7 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -344,16 +344,16 @@ stmt_cost (gimple gs, bool speed) return mult_by_coeff_cost (TREE_INT_CST_LOW (rhs2), lhs_mode, speed); gcc_assert (TREE_CODE (rhs1) != INTEGER_CST); - return mul_cost[speed][lhs_mode]; + return mul_cost (speed, lhs_mode); case PLUS_EXPR: case POINTER_PLUS_EXPR: case MINUS_EXPR: rhs2 = gimple_assign_rhs2 (gs); - return add_cost[speed][lhs_mode]; + return add_cost (speed, lhs_mode); case NEGATE_EXPR: - return neg_cost[speed][lhs_mode]; + return neg_cost (speed, lhs_mode); case NOP_EXPR: return convert_cost (lhs_mode, TYPE_MODE (TREE_TYPE (rhs1)), speed); diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 0d3e1bf..41c811f 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -3308,7 +3308,7 @@ get_address_cost (bool symbol_present, bool var_present, If VAR_PRESENT is true, try whether the mode with SYMBOL_PRESENT = false is cheaper even with cost of addition, and if this is the case, use it. */ - add_c = add_cost[speed][address_mode]; + add_c = add_cost (speed, address_mode); for (i = 0; i < 8; i++) { var_p = i & 1; @@ -3392,7 +3392,7 @@ get_address_cost (bool symbol_present, bool var_present, cost += mult_by_coeff_cost (ratio, address_mode, speed); if (s_offset && !offset_p && !symbol_present) - cost += add_cost[speed][address_mode]; + cost += add_cost (speed, address_mode); if (may_autoinc) *may_autoinc = autoinc; @@ -3422,10 +3422,10 @@ get_shiftadd_cost (tree expr, enum machine_mode mode, comp_cost cost0, return false; sa_cost = (TREE_CODE (expr) != MINUS_EXPR - ? shiftadd_cost[speed][mode][m] + ? shiftadd_cost (speed, mode, m) : (mult == op1 - ? shiftsub1_cost[speed][mode][m] - : shiftsub0_cost[speed][mode][m])); + ? shiftsub1_cost (speed, mode, m) + : shiftsub0_cost (speed, mode, m))); res = new_cost (sa_cost, 0); res = add_costs (res, mult == op1 ? cost0 : cost1); @@ -3559,7 +3559,7 @@ force_expr_to_var_cost (tree expr, bool speed) case PLUS_EXPR: case MINUS_EXPR: case NEGATE_EXPR: - cost = new_cost (add_cost[speed][mode], 0); + cost = new_cost (add_cost (speed, mode), 0); if (TREE_CODE (expr) != NEGATE_EXPR) { tree mult = NULL_TREE; @@ -3571,8 +3571,8 @@ force_expr_to_var_cost (tree expr, bool speed) if (mult != NULL_TREE && cst_and_fits_in_hwi (TREE_OPERAND (mult, 1)) - && get_shiftadd_cost (expr, mode, cost0, cost1, mult, speed, - &sa_cost)) + && get_shiftadd_cost (expr, mode, cost0, cost1, mult, + speed, &sa_cost)) return sa_cost; } break; @@ -4060,7 +4060,7 @@ get_computation_cost_at (struct ivopts_data *data, &symbol_present, &var_present, &offset, depends_on)); cost.cost /= avg_loop_niter (data->current_loop); - cost.cost += add_cost[data->speed][TYPE_MODE (ctype)]; + cost.cost += add_cost (data->speed, TYPE_MODE (ctype)); } if (inv_expr_id) @@ -4101,14 +4101,14 @@ get_computation_cost_at (struct ivopts_data *data, are added once to the variable, if present. */ if (var_present && (symbol_present || offset)) cost.cost += adjust_setup_cost (data, - add_cost[speed][TYPE_MODE (ctype)]); + add_cost (speed, TYPE_MODE (ctype))); /* Having offset does not affect runtime cost in case it is added to symbol, but it increases complexity. */ if (offset) cost.complexity++; - cost.cost += add_cost[speed][TYPE_MODE (ctype)]; + cost.cost += add_cost (speed, TYPE_MODE (ctype)); aratio = ratio > 0 ? ratio : -ratio; if (aratio != 1) @@ -4958,7 +4958,7 @@ determine_iv_cost (struct ivopts_data *data, struct iv_cand *cand) or a const set. */ if (cost_base.cost == 0) cost_base.cost = COSTS_N_INSNS (1); - cost_step = add_cost[data->speed][TYPE_MODE (TREE_TYPE (base))]; + cost_step = add_cost (data->speed, TYPE_MODE (TREE_TYPE (base))); cost = cost_step + adjust_setup_cost (data, cost_base.cost); -- 1.7.4.1