/* This field is only used for the processing of const functions.
These functions cannot read memory, but they can read the stack
- because that is where they may get their parms. It is set to
- true if the insn may contain a stack pointer based store. */
+ because that is where they may get their parms. We need to be
+ this conservative because, like the store motion pass, we don't
+ consider CALL_INSN_FUNCTION_USAGE when processing call insns.
+ Moreover, we need to distinguish two cases:
+ 1. Before reload (register elimination), the stores related to
+ outgoing arguments are stack pointer based and thus deemed
+ of non-constant base in this pass. This requires special
+ handling but also means that the frame pointer based stores
+ need not be killed upon encountering a const function call.
+ 2. After reload, the stores related to outgoing arguments can be
+ either stack pointer or hard frame pointer based. This means
+ that we have no other choice than also killing all the frame
+ pointer based stores upon encountering a const function call.
+ This field is set after reload for const function calls. Having
+ this set is less severe than a wild read, it just means that all
+ the frame related stores are killed rather than all the stores. */
+ bool frame_read;
+
+ /* This field is only used for the processing of const functions.
+ It is set if the insn may contain a stack pointer based store. */
bool stack_pointer_based;
/* This is true if any of the sets within the store contains a
continue;
new_mode = smallest_mode_for_size (access_size * BITS_PER_UNIT,
- GET_MODE_CLASS (read_mode));
+ MODE_INT);
new_reg = gen_reg_rtx (new_mode);
start_sequence ();
of the arguments and could be precomputed. It may
not be worth doing so. We could precompute if
worthwhile or at least cache the results. The result
- technically depends on SHIFT, ACCESS_SIZE, and
- GET_MODE_CLASS (READ_MODE). But in practice the
- answer will depend only on ACCESS_SIZE. */
+ technically depends on both SHIFT and ACCESS_SIZE,
+ but in practice the answer will depend only on ACCESS_SIZE. */
if (cost > COSTS_N_INSNS (1))
continue;
if (!dbg_cnt (dse))
return false;
- if (GET_MODE_CLASS (read_mode) != GET_MODE_CLASS (store_mode))
+ if (GET_MODE_CLASS (read_mode) != MODE_INT
+ || GET_MODE_CLASS (store_mode) != MODE_INT)
return false;
/* To get here the read is within the boundaries of the write so
call to get rid of the read. */
if (shift)
{
- if (access_size > UNITS_PER_WORD || FLOAT_MODE_P (store_mode))
+ if (access_size > UNITS_PER_WORD)
return false;
shift_seq = find_shift_sequence (read_reg, access_size, store_info,
if (dump_file)
fprintf (dump_file, "const call %d\n", INSN_UID (insn));
+ /* See the head comment of the frame_read field. */
+ if (reload_completed)
+ insn_info->frame_read = true;
+
+ /* Loop over the active stores and remove those which are
+ killed by the const function call. */
while (i_ptr)
{
- /* Remove the stack pointer based stores. */
+ bool remove_store = false;
+
+ /* The stack pointer based stores are always killed. */
if (i_ptr->stack_pointer_based)
+ remove_store = true;
+
+ /* 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
+ && VEC_index (group_info_t, rtx_group_vec,
+ store_info->group_id)->frame_related)
+ remove_store = true;
+ }
+
+ if (remove_store)
{
if (dump_file)
dump_insn_info ("removing from active", i_ptr);
}
else
last = i_ptr;
+
i_ptr = i_ptr->next_local_store;
}
}
int i;
group_info_t group;
+ /* If this insn reads the frame, kill all the frame related stores. */
+ if (insn_info->frame_read)
+ {
+ for (i = 0; VEC_iterate (group_info_t, rtx_group_vec, i, group); i++)
+ if (group->process_globally && group->frame_related)
+ {
+ if (kill)
+ bitmap_ior_into (kill, group->group_kill);
+ bitmap_and_compl_into (gen, group->group_kill);
+ }
+ }
+
while (read_info)
{
for (i = 0; VEC_iterate (group_info_t, rtx_group_vec, i, group); i++)