rtlanal.c (operand_preference): Fix preference for objects.

* rtlanal.c (operand_preference): Fix preference for objects.

	* gcse.c (handle_avail_expr): Be prepared to handle single_set
	parallels.

	* combine.c (if_then_else_cond): Use simplify_subreg instead
	of operand_subword.
	* integreate.c (sub_constants): Likewise.

	* emit-rtl.c (constant_subword): Deprecate; remove most of code
	and use simplify_gen_subreg.

Mon Jun  4 19:55:23 CEST 2001  Lars Brinkhoff  <lars@nocrew.org>

	* sibcall.c (skip_copy_to_return_value): recognize the situation
	when the called function's return value is copied into an
	intermediate pseudo, and then into the calling functions return
	value register.

From-SVN: r42864
This commit is contained in:
Jan Hubicka 2001-06-04 18:04:36 +00:00
parent 5c626f5260
commit 0631e0bfb7
9 changed files with 92 additions and 128 deletions

View File

@ -1,3 +1,30 @@
Mon Jun 4 20:03:05 CEST 2001 Jan Hubicka <jh@suse.cz>
* rtlanal.c (operand_preference): Fix preference for objects.
Mon Jun 4 20:00:40 CEST 2001 Jan Hubicka <jh@suse.cz>
* gcse.c (handle_avail_expr): Be prepared to handle single_set
parallels.
Mon Jun 4 19:59:46 CEST 2001 Jan Hubicka <jh@suse.cz>
* combine.c (if_then_else_cond): Use simplify_subreg instead
of operand_subword.
* integreate.c (sub_constants): Likewise.
Mon Jun 4 19:59:12 CEST 2001 Jan Hubicka <jh@suse.cz>
* emit-rtl.c (constant_subword): Deprecate; remove most of code
and use simplify_gen_subreg.
Mon Jun 4 19:55:23 CEST 2001 Lars Brinkhoff <lars@nocrew.org>
* sibcall.c (skip_copy_to_return_value): recognize the situation
when the called function's return value is copied into an
intermediate pseudo, and then into the calling functions return
value register.
Mon Jun 4 16:50:33 CEST 2001 Jan Hubicka <jh@suse.cz>
* simplify_rtx.c (simplify_subreg): Keep subregs on return values,

View File

@ -7293,29 +7293,16 @@ if_then_else_cond (x, ptrue, pfalse)
return cond0;
}
/* If X is a normal SUBREG with both inner and outer modes integral,
we can narrow both the true and false values of the inner expression,
if there is a condition. */
else if (code == SUBREG && GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_INT
&& GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
/* If X is a SUBREG, we can narrow both the true and false values
if the inner expression, if there is a condition. */
else if (code == SUBREG
&& 0 != (cond0 = if_then_else_cond (SUBREG_REG (x),
&true0, &false0)))
{
if ((GET_CODE (SUBREG_REG (x)) == REG
|| GET_CODE (SUBREG_REG (x)) == MEM
|| CONSTANT_P (SUBREG_REG (x)))
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
&& (WORDS_BIG_ENDIAN || SUBREG_BYTE (x) >= UNITS_PER_WORD))
{
true0 = operand_subword (true0, SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
GET_MODE (SUBREG_REG (x)));
false0 = operand_subword (false0, SUBREG_BYTE (x) / UNITS_PER_WORD, 0,
GET_MODE (SUBREG_REG (x)));
}
*ptrue = force_to_mode (true0, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
*pfalse
= force_to_mode (false0, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
*ptrue = simplify_gen_subreg (mode, true0,
GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
*pfalse = simplify_gen_subreg (mode, false0,
GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
return cond0;
}

View File

@ -1414,7 +1414,7 @@ const248_operand (op, mode)
int
incdec_operand (op, mode)
register rtx op;
enum machine_mode mode;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
/* On Pentium4, the inc and dec operations causes extra dependancy on flag
registers, since carry flag is not set. */

View File

@ -1430,7 +1430,10 @@ constant_subword (op, offset, mode)
??? This is still rather broken for some cases. The problem for the
moment is that all callers of this thing provide no 'goal mode' to
tell us to work with. This exists because all callers were written
in a word based SUBREG world. */
in a word based SUBREG world.
Now use of this function can be deprecated by simplify_subreg in most
cases.
*/
rtx
operand_subword (op, offset, validate_address, mode)
@ -1439,6 +1442,7 @@ operand_subword (op, offset, validate_address, mode)
int validate_address;
enum machine_mode mode;
{
rtx new;
if (mode == VOIDmode)
mode = GET_MODE (op);
@ -1455,82 +1459,6 @@ operand_subword (op, offset, validate_address, mode)
&& (offset + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))
return const0_rtx;
switch (GET_CODE (op))
{
case REG:
case SUBREG:
case CONCAT:
case MEM:
break;
default:
/* The only remaining cases are when OP is a constant. If the host and
target floating formats are the same, handling two-word floating
constants are easy. Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
are defined as returning one or two 32 bit values, respectively,
and not values of BITS_PER_WORD bits. */
return constant_subword (op, offset, mode);
}
/* If OP is already an integer word, return it. */
if (GET_MODE_CLASS (mode) == MODE_INT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD)
return op;
/* If OP is a REG or SUBREG, we can handle it very simply. */
if (GET_CODE (op) == REG)
{
if (REGNO (op) < FIRST_PSEUDO_REGISTER)
{
int final_regno = REGNO (op) +
subreg_regno_offset (REGNO (op), GET_MODE (op),
offset * UNITS_PER_WORD,
word_mode);
/* If the register is not valid for MODE, return 0. If we don't
do this, there is no way to fix up the resulting REG later. */
if (! HARD_REGNO_MODE_OK (final_regno, word_mode))
return 0;
/* integrate.c can't handle parts of a return value register.
??? Then integrate.c should be fixed!
??? What about CLASS_CANNOT_CHANGE_SIZE? */
if ((! REG_FUNCTION_VALUE_P (op)
|| ! rtx_equal_function_value_matters)
/* ??? What about CLASS_CANNOT_CHANGE_SIZE? */
/* We want to keep the stack, frame, and arg pointers
special. */
&& op != frame_pointer_rtx
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
&& op != arg_pointer_rtx
#endif
&& op != stack_pointer_rtx)
return gen_rtx_REG (word_mode, final_regno);
}
/* Just return a normal SUBREG. */
return gen_rtx_SUBREG (word_mode, op,
(offset * UNITS_PER_WORD));
}
else if (GET_CODE (op) == SUBREG)
{
int final_offset = ((offset * UNITS_PER_WORD) + SUBREG_BYTE (op));
/* When working with SUBREGs the rule is that the byte
offset must be a multiple of the SUBREG's mode. */
final_offset = (final_offset / GET_MODE_SIZE (word_mode));
final_offset = (final_offset * GET_MODE_SIZE (word_mode));
return gen_rtx_SUBREG (word_mode, SUBREG_REG (op), final_offset);
}
else if (GET_CODE (op) == CONCAT)
{
unsigned int partwords = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
if (offset < partwords)
return operand_subword (XEXP (op, 0), offset, validate_address, mode);
return operand_subword (XEXP (op, 1), offset - partwords,
validate_address, mode);
}
/* Form a new MEM at the requested address. */
if (GET_CODE (op) == MEM)
{
@ -1553,8 +1481,8 @@ operand_subword (op, offset, validate_address, mode)
return new;
}
/* Unreachable... (famous last words) */
abort ();
/* Rest can be handled by simplify_subreg. */
return simplify_gen_subreg (word_mode, op, mode, (offset * UNITS_PER_WORD));
}
/* Similar to `operand_subword', but never return 0. If we can't extract

View File

@ -3472,7 +3472,7 @@ handle_avail_expr (insn, expr)
rtx insn;
struct expr *expr;
{
rtx pat, insn_computes_expr;
rtx pat, insn_computes_expr, expr_set;
rtx to;
struct reg_set *this_reg;
int found_setting, use_src;
@ -3483,6 +3483,9 @@ handle_avail_expr (insn, expr)
insn_computes_expr = computing_insn (expr, insn);
if (insn_computes_expr == NULL)
return 0;
expr_set = single_set (insn_computes_expr);
if (!expr_set)
abort ();
found_setting = 0;
use_src = 0;
@ -3490,12 +3493,12 @@ handle_avail_expr (insn, expr)
/* At this point we know only one computation of EXPR outside of this
block reaches this insn. Now try to find a register that the
expression is computed into. */
if (GET_CODE (SET_SRC (PATTERN (insn_computes_expr))) == REG)
if (GET_CODE (SET_SRC (expr_set)) == REG)
{
/* This is the case when the available expression that reaches
here has already been handled as an available expression. */
unsigned int regnum_for_replacing
= REGNO (SET_SRC (PATTERN (insn_computes_expr)));
= REGNO (SET_SRC (expr_set));
/* If the register was created by GCSE we can't use `reg_set_table',
however we know it's set only once. */
@ -3514,7 +3517,7 @@ handle_avail_expr (insn, expr)
if (!found_setting)
{
unsigned int regnum_for_replacing
= REGNO (SET_DEST (PATTERN (insn_computes_expr)));
= REGNO (SET_DEST (expr_set));
/* This shouldn't happen. */
if (regnum_for_replacing >= max_gcse_regno)
@ -3533,9 +3536,9 @@ handle_avail_expr (insn, expr)
{
pat = PATTERN (insn);
if (use_src)
to = SET_SRC (PATTERN (insn_computes_expr));
to = SET_SRC (expr_set);
else
to = SET_DEST (PATTERN (insn_computes_expr));
to = SET_DEST (expr_set);
changed = validate_change (insn, &SET_SRC (pat), to, 0);
/* We should be able to ignore the return code from validate_change but
@ -3563,15 +3566,14 @@ handle_avail_expr (insn, expr)
replace all uses of REGB with REGN. */
rtx new_insn;
to = gen_reg_rtx (GET_MODE (SET_DEST (PATTERN (insn_computes_expr))));
to = gen_reg_rtx (GET_MODE (SET_DEST (expr_set)));
/* Generate the new insn. */
/* ??? If the change fails, we return 0, even though we created
an insn. I think this is ok. */
new_insn
= emit_insn_after (gen_rtx_SET (VOIDmode, to,
SET_DEST (PATTERN
(insn_computes_expr))),
SET_DEST (expr_set)),
insn_computes_expr);
/* Keep block number table up to date. */

View File

@ -2411,19 +2411,14 @@ subst_constants (loc, insn, map, memonly)
valid. We handle two cases: extracting a full word in an
integral mode and extracting the low part. */
subst_constants (&inner, NULL_RTX, map, 0);
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
&& GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
&& GET_MODE (SUBREG_REG (x)) != VOIDmode)
new = operand_subword (inner, SUBREG_BYTE (x) / UNITS_PER_WORD,
0, GET_MODE (SUBREG_REG (x)));
cancel_changes (num_changes);
if (new == 0 && subreg_lowpart_p (x))
new = gen_lowpart_common (GET_MODE (x), inner);
new = simplify_gen_subreg (GET_MODE (x), inner,
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x));
if (new)
validate_change (insn, loc, new, 1);
else
cancel_changes (num_changes);
return;
}

View File

@ -2515,16 +2515,16 @@ operand_preference (op)
{
/* Constants always come the second operand. Prefer "nice" constants. */
if (GET_CODE (op) == CONST_INT)
return -4;
return -5;
if (GET_CODE (op) == CONST_DOUBLE)
return -3;
return -4;
if (CONSTANT_P (op))
return -2;
return -3;
/* SUBREGs of objects should come second. */
if (GET_CODE (op) == SUBREG
&& GET_RTX_CLASS (GET_CODE (SUBREG_REG (op))) == 'o')
return -1;
return -2;
/* If only one operand is a `neg', `not',
`mult', `plus', or `minus' expression, it will be the first
@ -2534,9 +2534,10 @@ operand_preference (op)
|| GET_CODE (op) == MINUS)
return 2;
/* Complex expressions should be the first. */
/* Complex expressions should be the first, so decrease priority
of objects. */
if (GET_RTX_CLASS (GET_CODE (op)) == 'o')
return 1;
return -1;
return 0;
}

View File

@ -169,6 +169,30 @@ skip_copy_to_return_value (orig_insn)
&& SET_SRC (set) == softret)
return insn;
/* Recognize the situation when the called function's return value
is copied in two steps: first into an intermediate pseudo, then
the into the calling functions return value register. */
if (REG_P (SET_DEST (set))
&& SET_SRC (set) == softret)
{
rtx x = SET_DEST (set);
insn = next_nonnote_insn (insn);
if (! insn)
return orig_insn;
set = single_set (insn);
if (! set)
return orig_insn;
if (SET_DEST (set) == current_function_return_rtx
&& REG_P (SET_DEST (set))
&& OUTGOING_REGNO (REGNO (SET_DEST (set))) == REGNO (hardret)
&& SET_SRC (set) == x)
return insn;
}
/* It did not look like a copy of the return value, so return the
same insn we were passed. */
return orig_insn;

View File

@ -2227,9 +2227,9 @@ simplify_subreg (outermode, op, innermode, byte)
&& GET_MODE_SIZE (innermode) > UNITS_PER_WORD
&& GET_MODE_CLASS (outermode) == MODE_INT)
{
rtx new = operand_subword (op,
(byte / UNITS_PER_WORD),
0, innermode);
rtx new = constant_subword (op,
(byte / UNITS_PER_WORD),
innermode);
if (new)
return new;
}