This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Repost: RFA [4.1]: improvement to if-conversion and cross-jumping (PR20070)
- From: Bernd Schmidt <bernds_cb1 at t-online dot de>
- To: Joern RENNECKE <joern dot rennecke at st dot com>
- Cc: Steven Bosscher <stevenb at suse dot de>, Richard Henderson <rth at redhat dot com>, gcc-patches at gcc dot gnu dot org, jh at suse dot cz
- Date: Thu, 01 Dec 2005 00:18:57 +0100
- Subject: Re: Repost: RFA [4.1]: improvement to if-conversion and cross-jumping (PR20070)
- References: <41E59432.7080504@st.com> <42CD71E0.3070804@st.com> <42D3B666.6050701@st.com> <200507121547.21305.stevenb@suse.de> <42D3E705.9030507@st.com> <42D7C264.6030507@st.com> <438C567A.7030104@t-online.de> <438CCE0F.6020209@st.com> <438DC224.8020300@t-online.de> <438E1734.3090502@st.com>
Still trying to wrap my head around this - the REG handling in
function seems difficult; maybe more comments describing the whys of
what we are doing might be helpful.
Couldn't we just enter the same register into the [xy]_local arrays
multiple times, along with a bit that records the change (live <->
dead)? We'd save the scan backwards, and we could always restore to a
previous checkpoint, which in turn means we no longer need the rerun
machinery? MAX_LOCAL probably needs to grow, but if we're not going
to loop over these arrays anymore, that's no problem.
I don't think the rerun machinery is expensive.
Neither do I, but I think by making checkpoints always restorable, the
code could be simplified. I'll see if I can come up with a way of doing
that.
I'm still unable to understand all the details of the REG handling in
function struct_equiv, and would like simplifications if at all
possible. The code you write is always very clever, but for me at least
that makes it very hard to understand.
Let's take an example of something that's unclear to me: we're matching
two blocks where R0 and R5 are alive at the end of both; the last insn
in block X is
(insn:HI 47 44 48 5 (set (mem/s/f:SI (reg/f:SI 2 r2 [orig:162 ivtmp.1356
] [162]) [3 <variable>.subreg_loc+0 S4 A32])
(reg:SI 0 r0 [170])) 171 {movsi_i} (nil)
(expr_list:REG_EQUAL (const_int 0 [0x0])
(nil)))
and the last insn in block Y is
(insn:HI 30 28 76 3 (set (mem/s/f:SI (reg/f:SI 2 r2 [orig:162 ivtmp.1356
] [162]) [3 <variable>.subreg_loc+0 S4 A32])
(reg/v/f:SI 5 r5 [orig:166 y ] [166])) 171 {movsi_i} (nil)
(nil))
We eventually end up in the REG case of struct_equiv, with x == (reg:SI
0 r0 [170]), and y == (reg/v/f:SI 5 r5 [orig:166 y ] [166]). Both regs
are in common_live, so we end up in
else if (x_common_live)
{
if (! rvalue || info->input_cost < 0 || no_new_pseudos)
return false;
/* If info->live_update is not set, we are processing notes.
We then allow a match with x_input / y_input found in a
previous pass. */
if (info->live_update && !info->input_valid)
{
info->input_valid = true;
info->x_input = x;
info->y_input = y;
info->input_count += optimize_size ? 2 : 1;
if (info->input_reg
&& GET_MODE (info->input_reg) != GET_MODE
(info->x_input))
info->input_reg = NULL_RTX;
if (!info->input_reg)
info->input_reg = gen_reg_rtx (GET_MODE (info->x_input));
validate_change (info->x_start, xp, info->input_reg, 1);
}
else if ((info->live_update ? ! info->input_valid : !
info->x_input)
|| ! rtx_equal_p (x, info->x_input)
|| ! rtx_equal_p (y, info->y_input))
return false;
validate_change (info->x_start, xp, info->input_reg, 1);
}
Nevermind the fact that this has a duplicate call of validate_change.
What is this code trying to do? I would have naively thought that if we
have R5 and R0 live at the end, then previous uses of either register
must match exactly.
Can you post an RTL example of what you're trying to accomplish with the
code related to input_reg? What can be done with it that can't be done
by examining the local_regs still live at the start of a block?
This bit of code:
if (reload_completed
&& (code == REG || (code == SUBREG && REG_P (SUBREG_REG (y))))
&& rtx_renumbered_equal_p (x, y))
{
int regno = true_regnum (x);
int nregs = hard_regno_nregs[regno][GET_MODE (x)];
int i;
for (i = nregs; --i>= 0; regno++)
if (REGNO_REG_SET_P (info->x_local_live, regno)
|| REGNO_REG_SET_P (info->y_local_live, regno))
return false;
if (!rvalue && info->input_valid
&& (reg_overlap_mentioned_for_reload_p (x, info->x_input)
|| reg_overlap_mentioned_for_reload_p (x, info->y_input)))
return false;
/* Update liveness information. */
if (info->live_update
&& assign_reg_reg_set (info->common_live, x, rvalue))
info->version++;
return true;
}
is partially duplicated just a few lines down, without the
reload_completed guard. This is very confusing, please merge the two.
Also, it doesn't seem to test for rvalue when marking the reg as live?
Bernd