This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [4.5] Autoinc support in tree-ssa-loop-ivopts.c
- From: Zdenek Dvorak <rakdver at kam dot mff dot cuni dot cz>
- To: Bernd Schmidt <bernds_cb1 at t-online dot de>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 13 May 2009 19:44:21 +0200
- Subject: Re: [4.5] Autoinc support in tree-ssa-loop-ivopts.c
- References: <4999939F.70405@t-online.de> <20090217163948.GA30309@kam.mff.cuni.cz> <4A0AEC7E.5050406@t-online.de>
Hi,
> >Another thing: is this really the right condition to detect? I would
> >expect autoinc modes to be useful even in cases where more than one
> >memory reference and possibly also the exit test are based on the
> >autoincremented induction variable.
>
> Here's a new patch which has been extensively changed.
>
> One possible condition to test for would be whether the uses closest to
> the position of the biv increment (either before or after) allow
> autoincrement. That seems to me rather expensive since we'd have to
> walk the basic blocks a few times to determine an order for the uses, so
> I've chosen something slightly weaker: either all uses before the
> increment, or all uses after the increment must allow autoincrement.
> This condition gives us a strict superset of opportunites compared to
> the one used by the previous patch.
>
> The cost of the code in iv_ca_recount_cost is reduced by this since most
> of the tracking is now done in iv_ca_set{_no,}_cp.
>
> I've added code to test for the availability of each of the four autoinc
> addressing modes for every machine mode.
>
> Not too much testing yet other than comparing generated code for a lot
> of examples. If this looks OK to you, I'll start bootstrap etc.
yes, this looks fine.
> + autoinc = false;
> + msize = GET_MODE_SIZE (mem_mode);
> + autoinc_offset = offset;
> + if (stmt_after_inc)
> + autoinc_offset += cstep * ratio;
> + if (s_offset || symbol_present || var_present || ratio != 1)
> + autoinc = false;
> + else if (0
> + || (has_postinc[mem_mode] && autoinc_offset == 0
> + && msize == cstep)
> + || (has_postdec[mem_mode] && autoinc_offset == 0
> + && msize == -cstep)
> + || (has_preinc[mem_mode] && autoinc_offset == msize
> + && msize == cstep)
> + || (has_predec[mem_mode] && autoinc_offset == -msize
> + && msize == -cstep))
> + autoinc = true;
This is rather hard to read; as far as I can tell, your code is
equivalent to
autoinc = false;
if (s_offset == 0 && !symbol_present && !var_present && ratio == 1)
{
msize = GET_MODE_SIZE (mem_mode);
if ((has_postinc[mem_mode] && !stmt_after_inc && msize == cstep)
|| (has_postdec[mem_mode] && !stmt_after_inc && msize == -cstep)
|| (has_preinc[mem_mode] && stmt_after_inc && msize == cstep)
|| (has_predec[mem_mode] && stmt_after_inc && msize == -cstep))
autoinc = true;
}
> @@ -4204,9 +4291,27 @@ static void
> iv_ca_recount_cost (struct ivopts_data *data, struct iv_ca *ivs)
> {
> comp_cost cost = ivs->cand_use_cost;
> + unsigned i;
> +
> cost.cost += ivs->cand_cost;
> cost.cost += ivopts_global_cost_for_size (data, ivs->n_regs);
>
> + /* Try to give a bonus to single uses of a candidate in an address,
> + where we think this might lead to autoinc addressing later on. */
> + for (i = 0; i < n_iv_cands (data); i++)
> + {
> + struct iv_cand *cand = iv_cand (data, i);
> + if ((ivs->n_cand_uses_before_inc[i] > 0
> + && (ivs->n_cand_autoinc_uses_before_inc[i]
> + == ivs->n_cand_uses_before_inc[i]))
> + || (ivs->n_cand_uses_after_inc[i] > 0
> + && (ivs->n_cand_autoinc_uses_after_inc[i]
> + == ivs->n_cand_uses_after_inc[i])))
> + {
> + cost.cost -= cand->cost_step;
> + }
> + }
> +
> ivs->cost = cost;
This loop can be avoided, by doing the computation in iv_ca_set_no_cp
and iv_ca_set_cp; let get_cand_cost (cand) return cand->cost if autoinc
is not possible and cand->cost - cand->cost_step otherwise, using the
condition (ivs->n_cand_uses_before_inc[cand->id] > 0 && ...).
In iv_ca_set_no_cp, change the code to
orig_cand_cost = get_cand_cost (cand);
... /* Recompute n_cand_autoinc_uses_after_inc etc. */
new_cand_cost = get_cand_cost (cand);
if (ivs->n_cand_uses[cid] == 0)
{
...
ivs->cand_cost -= orig_cand_cost;
}
else
ivs->cand_cost += new_cand_cost - orig_cand_cost;
And similarly in iv_ca_set_cp.
Zdenek