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:
parent
5c626f5260
commit
0631e0bfb7
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
20
gcc/gcse.c
20
gcc/gcse.c
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user