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> 2009-08-22 Kaz Kojima <kkojima@gcc.gnu.org>
* config/sh/t-sh (TARGET_LIBGCC2_CFLAGS): Define. * 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_ ...@@ -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); int flags = DF_REF_FLAGS (use);
rtx set = single_set (insn); rtx set = single_set (insn);
bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (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; 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) if (dump_file)
{ {
fprintf (dump_file, "\nIn insn %d, replacing\n ", INSN_UID (insn)); 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_ ...@@ -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 else if (DF_REF_TYPE (use) == DF_REF_REG_USE
&& set
&& rtx_cost (SET_SRC (set), SET, speed) > old_cost) && rtx_cost (SET_SRC (set), SET, speed) > old_cost)
{ {
if (dump_file) if (dump_file)
...@@ -1008,8 +1014,26 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_ ...@@ -1008,8 +1014,26 @@ try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_
return ok; 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 static bool
forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set) forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set)
...@@ -1017,14 +1041,16 @@ forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set) ...@@ -1017,14 +1041,16 @@ forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set)
rtx use_reg = DF_REF_REG (use); rtx use_reg = DF_REF_REG (use);
rtx use_insn, src; rtx use_insn, src;
/* Only consider paradoxical subregs... */ /* Only consider subregs... */
enum machine_mode use_mode = GET_MODE (use_reg); enum machine_mode use_mode = GET_MODE (use_reg);
if (GET_CODE (use_reg) != SUBREG if (GET_CODE (use_reg) != SUBREG
|| !REG_P (SET_DEST (def_set)) || !REG_P (SET_DEST (def_set)))
|| GET_MODE_SIZE (use_mode)
<= GET_MODE_SIZE (GET_MODE (SUBREG_REG (use_reg))))
return false; 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 /* If this is a paradoxical SUBREG, we have no idea what value the
extra bits would have. However, if the operand is equivalent to 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 a SUBREG whose operand is the same as our mode, and all the modes
...@@ -1039,7 +1065,39 @@ forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set) ...@@ -1039,7 +1065,39 @@ forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set)
&& all_uses_available_at (def_insn, use_insn)) && all_uses_available_at (def_insn, use_insn))
return try_fwprop_subst (use, DF_REF_LOC (use), SUBREG_REG (src), return try_fwprop_subst (use, DF_REF_LOC (use), SUBREG_REG (src),
def_insn, false); def_insn, false);
else }
/* 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; return false;
} }
......
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