[PATCH] Set stores_off_frame_dead_at_return to false if sibling call
Jeff Law
law@redhat.com
Mon Dec 8 21:14:00 GMT 2014
On 12/01/14 11:44, John David Anglin wrote:
>>
>> To do unconditionally set frame_read? Or if we don't want to get
>> that drastic,
>>
>> if (reload_completed || SIBLING_CALL_P (insn))
>> insn_info->frame_read = true;
> Will test but I, if I read the code correctly, setting
> insn_info->frame_read = true results in frame related stores being
> killed in a constant call. This doesn't seem like the right
> solution.
But isn't killing in this context referring to GEN/KILL types of
operations for global dataflow? ISTM that GEN is a store operation
while KILL is a load operation (over-simplification, but stick with me).
Thus a GEN-GEN will get optimized into a single GEN (dead store
eliminated) while a GEN-KILL-GEN can not be optimized by DSE because of
the KILL.
It should always be safe to have an extraneous KILL since that merely
inhibits optimization. While an extraneous GEN can be a disaster.
So with setting frame_read, we're going to have more KILLs in the
dataflow sets, which results in fewer stores being eliminated. They
come from:
/* If the frame is read, the frame related stores are
killed. */
else if (insn_info->frame_read)
{
store_info_t store_info = i_ptr->store_rec;
/* Skip the clobbers. */
while (!store_info->is_set)
store_info = store_info->next;
if (store_info->group_id >= 0
&&
rtx_group_vec[store_info->group_id]->frame_related)
remove_store = true;
}
if (remove_store)
{
if (dump_file && (dump_flags & TDF_DETAILS))
dump_insn_info ("removing from active", i_ptr);
active_local_stores_len--;
if (last)
last->next_local_store = i_ptr->next_local_store;
else
active_local_stores = i_ptr->next_local_store;
}
else
last = i_ptr;
i_ptr = i_ptr->next_local_store;
AFAICT in this loop, setting FRAME_READ causes us to set REMOVE_STORE
more often. REMOVE_STORE in this context seems to indicate that we're
going to remove a store from the list we are tracking for potential
removal. Which seems exactly right.
Here as well:
/* If this insn reads the frame, kill all the frame related stores. */
if (insn_info->frame_read)
{
FOR_EACH_VEC_ELT (rtx_group_vec, i, group)
if (group->process_globally && group->frame_related)
{
if (kill)
bitmap_ior_into (kill, group->group_kill);
bitmap_and_compl_into (gen, group->group_kill);
}
}
Which also seems like exactly what we want since when we set FRAME_READ
we end up with a bigger KILL set and a smaller GEN set.
I think the terminology and variable names certainly makes this tougher
to follow than it should.
>
> Here we have frame related calls being killed before reload because
> the argument stores for the sibcall are off frame:
>
> /* Set the gen set of the exit block, and also any block with no
> successors that does not have a wild read. */
>
> static void dse_step3_exit_block_scan (bb_info_t bb_info) { /* The
> gen set is all 0's for the exit block except for the
> frame_pointer_group. */
>
> if (stores_off_frame_dead_at_return) { unsigned int i; group_info_t
> group;
>
> FOR_EACH_VEC_ELT (rtx_group_vec, i, group) { if
> (group->process_globally && group->frame_related) bitmap_ior_into
> (bb_info->gen, group->group_kill); } } }
I see your point. Expanding the GEN set here seems wrong. If we go
with setting STORES_OFF_FRAME_DEAD_AT_RETURN, then we definitely need to
update its documentation.
I think an argument could be made that we want both changes if I've
interpreted this code correctly.
Jeff
More information about the Gcc-patches
mailing list