Commit e25b7843 by Alan Modra Committed by Alan Modra

re PR target/41081 (redundant ZERO_EXTENDs)

	PR target/41081
	* fwprop.c (try_fwprop_subst): Allow multiple sets.
	(get_reg_use_in): New function.
	(forward_propagate_subreg): Propagate through subreg of zero_extend
	or sign_extend.

From-SVN: r151022
parent 94d34253
2009-08-23 Alan Modra <amodra@bigpond.net.au>
PR target/41081
* fwprop.c (try_fwprop_subst): Allow multiple sets.
(get_reg_use_in): New function.
(forward_propagate_subreg): Propagate through subreg of zero_extend
or sign_extend.
2009-08-22 Kaz Kojima <kkojima@gcc.gnu.org>
* config/sh/t-sh (TARGET_LIBGCC2_CFLAGS): Define.
......
......@@ -929,9 +929,14 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_
int flags = DF_REF_FLAGS (use);
rtx set = single_set (insn);
bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
int old_cost = rtx_cost (SET_SRC (set), SET, speed);
int old_cost = 0;
bool ok;
/* forward_propagate_subreg may be operating on an instruction with
multiple sets. If so, assume the cost of the new instruction is
not greater than the old one. */
if (set)
old_cost = rtx_cost (SET_SRC (set), SET, speed);
if (dump_file)
{
fprintf (dump_file, "\nIn insn %d, replacing\n ", INSN_UID (insn));
......@@ -951,6 +956,7 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_
}
else if (DF_REF_TYPE (use) == DF_REF_REG_USE
&& set
&& rtx_cost (SET_SRC (set), SET, speed) > old_cost)
{
if (dump_file)
......@@ -1008,8 +1014,26 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_
return ok;
}
#ifdef LOAD_EXTEND_OP
static df_ref
get_reg_use_in (rtx insn, rtx reg)
{
df_ref *use_vec;
/* If USE is a paradoxical subreg, see if it can be replaced by a pseudo. */
for (use_vec = DF_INSN_USES (insn); *use_vec; use_vec++)
{
df_ref use = *use_vec;
if (!DF_REF_IS_ARTIFICIAL (use)
&& DF_REF_TYPE (use) == DF_REF_REG_USE
&& DF_REF_REG (use) == reg)
return use;
}
return NULL;
}
#endif
/* If USE is a subreg, see if it can be replaced by a pseudo. */
static bool
forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set)
......@@ -1017,30 +1041,64 @@ forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set)
rtx use_reg = DF_REF_REG (use);
rtx use_insn, src;
/* Only consider paradoxical subregs... */
/* Only consider subregs... */
enum machine_mode use_mode = GET_MODE (use_reg);
if (GET_CODE (use_reg) != SUBREG
|| !REG_P (SET_DEST (def_set))
|| GET_MODE_SIZE (use_mode)
<= GET_MODE_SIZE (GET_MODE (SUBREG_REG (use_reg))))
|| !REG_P (SET_DEST (def_set)))
return false;
/* If this is a paradoxical SUBREG, we have no idea what value the
extra bits would have. However, if the operand is equivalent to
a SUBREG whose operand is the same as our mode, and all the modes
are within a word, we can just use the inner operand because
these SUBREGs just say how to treat the register. */
use_insn = DF_REF_INSN (use);
src = SET_SRC (def_set);
if (GET_CODE (src) == SUBREG
&& REG_P (SUBREG_REG (src))
&& GET_MODE (SUBREG_REG (src)) == use_mode
&& subreg_lowpart_p (src)
&& all_uses_available_at (def_insn, use_insn))
return try_fwprop_subst (use, DF_REF_LOC (use), SUBREG_REG (src),
def_insn, false);
else
return false;
/* If this is a paradoxical SUBREG... */
if (GET_MODE_SIZE (use_mode)
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (use_reg))))
{
/* If this is a paradoxical SUBREG, we have no idea what value the
extra bits would have. However, if the operand is equivalent to
a SUBREG whose operand is the same as our mode, and all the modes
are within a word, we can just use the inner operand because
these SUBREGs just say how to treat the register. */
use_insn = DF_REF_INSN (use);
src = SET_SRC (def_set);
if (GET_CODE (src) == SUBREG
&& REG_P (SUBREG_REG (src))
&& GET_MODE (SUBREG_REG (src)) == use_mode
&& subreg_lowpart_p (src)
&& all_uses_available_at (def_insn, use_insn))
return try_fwprop_subst (use, DF_REF_LOC (use), SUBREG_REG (src),
def_insn, false);
}
/* If this is a SUBREG of a ZERO_EXTEND or SIGN_EXTEND, and the SUBREG
is the low part of the reg being extended then just use the inner
operand. Don't do this if the ZERO_EXTEND or SIGN_EXTEND insn will
be removed due to it matching a LOAD_EXTEND_OP load from memory. */
else if (subreg_lowpart_p (use_reg))
{
#ifdef LOAD_EXTEND_OP
df_ref prev_use, prev_def;
#endif
use_insn = DF_REF_INSN (use);
src = SET_SRC (def_set);
if ((GET_CODE (src) == ZERO_EXTEND
|| GET_CODE (src) == SIGN_EXTEND)
&& REG_P (XEXP (src, 0))
&& GET_MODE (XEXP (src, 0)) == use_mode
#ifdef LOAD_EXTEND_OP
&& !(LOAD_EXTEND_OP (use_mode) == GET_CODE (src)
&& (prev_use = get_reg_use_in (def_insn, XEXP (src, 0))) != NULL
&& (prev_def = get_def_for_use (prev_use)) != NULL
&& !DF_REF_IS_ARTIFICIAL (prev_def)
&& NONJUMP_INSN_P (DF_REF_INSN (prev_def))
&& GET_CODE (PATTERN (DF_REF_INSN (prev_def))) == SET
&& GET_CODE (SET_SRC (PATTERN (DF_REF_INSN (prev_def)))) == MEM
&& rtx_equal_p (SET_DEST (PATTERN (DF_REF_INSN (prev_def))),
XEXP (src, 0)))
#endif
&& all_uses_available_at (def_insn, use_insn))
return try_fwprop_subst (use, DF_REF_LOC (use), XEXP (src, 0),
def_insn, false);
}
return false;
}
/* Try to replace USE with SRC (defined in DEF_INSN) in __asm. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment