emit-rtl.c (offset_address): Use simplify_gen_binary rather than gen_rtx_PLUS to form the sum.

* emit-rtl.c (offset_address): Use simplify_gen_binary rather
        than gen_rtx_PLUS to form the sum.
        * explow.c (force_reg): Rearrange to not allocate new pseudo
        when force_operand returns a register.
        * expr.c (expand_assignment): Allow offset_rtx expansion to
        return a sum.  Do not force addresses into registers.
        (expand_expr): Likewise.
        * simplify-rtx.c (simplify_gen_binary): Use simplify_plus_minus
        to canonicalize arithmetic that didn't simpify.
        (simplify_plus_minus): New argument force; update
        all callers.  Don't split CONST unless we can do something with it,
        and wouldn't lose the constness of the operands.

        * config/i386/i386.c (legitimize_pic_address): Recognize UNSPECs
        that we generated earlier.

From-SVN: r49945
This commit is contained in:
Richard Henderson 2002-02-21 15:06:16 -08:00 committed by Richard Henderson
parent c1a046e50e
commit e3c8ea6725
6 changed files with 109 additions and 57 deletions

View file

@ -1,3 +1,21 @@
2002-02-21 Richard Henderson <rth@redhat.com>
* emit-rtl.c (offset_address): Use simplify_gen_binary rather
than gen_rtx_PLUS to form the sum.
* explow.c (force_reg): Rearrange to not allocate new pseudo
when force_operand returns a register.
* expr.c (expand_assignment): Allow offset_rtx expansion to
return a sum. Do not force addresses into registers.
(expand_expr): Likewise.
* simplify-rtx.c (simplify_gen_binary): Use simplify_plus_minus
to canonicalize arithmetic that didn't simpify.
(simplify_plus_minus): New argument force; update
all callers. Don't split CONST unless we can do something with it,
and wouldn't lose the constness of the operands.
* config/i386/i386.c (legitimize_pic_address): Recognize UNSPECs
that we generated earlier.
2002-02-21 Tom Tromey <tromey@redhat.com>
* dwarf2out.c (DWARF_LINE_MIN_INSTR_LENGTH): Removed.

View file

@ -4986,11 +4986,15 @@ legitimize_pic_address (orig, reg)
if (GET_CODE (addr) == CONST)
{
addr = XEXP (addr, 0);
if (GET_CODE (addr) == UNSPEC)
{
/* Check that the unspec is one of the ones we generate? */
}
else if (GET_CODE (addr) != PLUS)
/* We must match stuff we generate before. Assume the only
unspecs that can get here are ours. Not that we could do
anything with them anyway... */
if (GET_CODE (addr) == UNSPEC
|| (GET_CODE (addr) == PLUS
&& GET_CODE (XEXP (addr, 0)) == UNSPEC))
return orig;
if (GET_CODE (addr) != PLUS)
abort ();
}
if (GET_CODE (addr) == PLUS)

View file

@ -2047,9 +2047,26 @@ offset_address (memref, offset, pow2)
rtx offset;
HOST_WIDE_INT pow2;
{
rtx new = change_address_1 (memref, VOIDmode,
gen_rtx_PLUS (Pmode, XEXP (memref, 0),
force_reg (Pmode, offset)), 1);
rtx new, addr = XEXP (memref, 0);
new = simplify_gen_binary (PLUS, Pmode, addr, offset);
/* At this point we don't know _why_ the address is invalid. It
could have secondary memory refereces, multiplies or anything.
However, if we did go and rearrange things, we can wind up not
being able to recognize the magic around pic_offset_table_rtx.
This stuff is fragile, and is yet another example of why it is
bad to expose PIC machinery too early. */
if (! memory_address_p (GET_MODE (memref), new)
&& GET_CODE (addr) == PLUS
&& XEXP (addr, 0) == pic_offset_table_rtx)
{
addr = force_reg (GET_MODE (addr), addr);
new = simplify_gen_binary (PLUS, Pmode, addr, offset);
}
new = change_address_1 (memref, VOIDmode, new, 1);
/* Update the alignment to reflect the offset. Reset the offset, which
we don't know. */

View file

@ -732,12 +732,23 @@ force_reg (mode, x)
if (GET_CODE (x) == REG)
return x;
temp = gen_reg_rtx (mode);
if (! general_operand (x, mode))
x = force_operand (x, NULL_RTX);
insn = emit_move_insn (temp, x);
if (general_operand (x, mode))
{
temp = gen_reg_rtx (mode);
insn = emit_move_insn (temp, x);
}
else
{
temp = force_operand (x, NULL_RTX);
if (GET_CODE (temp) == REG)
insn = get_last_insn ();
else
{
rtx temp2 = gen_reg_rtx (mode);
insn = emit_move_insn (temp2, temp);
temp = temp2;
}
}
/* Let optimizers know that TEMP's value never changes
and that X can be substituted for it. Don't get confused
@ -746,6 +757,7 @@ force_reg (mode, x)
&& (set = single_set (insn)) != 0
&& SET_DEST (set) == temp)
set_unique_reg_note (insn, REG_EQUAL, x);
return temp;
}

View file

@ -3659,7 +3659,7 @@ expand_assignment (to, from, want_value, suggest_reg)
if (offset != 0)
{
rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
if (GET_CODE (to_rtx) != MEM)
abort ();
@ -3682,15 +3682,7 @@ expand_assignment (to, from, want_value, suggest_reg)
&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
&& MEM_ALIGN (to_rtx) == GET_MODE_ALIGNMENT (mode1))
{
rtx temp
= adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
if (GET_CODE (XEXP (temp, 0)) == REG)
to_rtx = temp;
else
to_rtx = (replace_equiv_address
(to_rtx, force_reg (GET_MODE (XEXP (temp, 0)),
XEXP (temp, 0))));
to_rtx = adjust_address (to_rtx, mode1, bitpos / BITS_PER_UNIT);
bitpos = 0;
}
@ -6852,7 +6844,7 @@ expand_expr (exp, target, tmode, modifier)
if (offset != 0)
{
rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, EXPAND_SUM);
/* If this object is in a register, put it into memory.
This case can't occur in C, but can in Ada if we have
@ -6902,15 +6894,7 @@ expand_expr (exp, target, tmode, modifier)
&& (bitsize % GET_MODE_ALIGNMENT (mode1)) == 0
&& MEM_ALIGN (op0) == GET_MODE_ALIGNMENT (mode1))
{
rtx temp = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
if (GET_CODE (XEXP (temp, 0)) == REG)
op0 = temp;
else
op0 = (replace_equiv_address
(op0,
force_reg (GET_MODE (XEXP (temp, 0)),
XEXP (temp, 0))));
op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
bitpos = 0;
}

View file

@ -99,7 +99,8 @@ static rtx neg_const_int PARAMS ((enum machine_mode, rtx));
static int simplify_plus_minus_op_data_cmp PARAMS ((const void *,
const void *));
static rtx simplify_plus_minus PARAMS ((enum rtx_code,
enum machine_mode, rtx, rtx));
enum machine_mode, rtx,
rtx, int));
static void check_fold_consts PARAMS ((PTR));
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
static void simplify_unary_real PARAMS ((PTR));
@ -137,21 +138,14 @@ simplify_gen_binary (code, mode, op0, op1)
/* If this simplifies, do it. */
tem = simplify_binary_operation (code, mode, op0, op1);
if (tem)
return tem;
/* Handle addition and subtraction of CONST_INT specially. Otherwise,
just form the operation. */
/* Handle addition and subtraction specially. Otherwise, just form
the operation. */
if (GET_CODE (op1) == CONST_INT
&& GET_MODE (op0) != VOIDmode
&& (code == PLUS || code == MINUS))
{
if (code == MINUS)
op1 = neg_const_int (mode, op1);
return plus_constant (op0, INTVAL (op1));
}
if (code == PLUS || code == MINUS)
return simplify_plus_minus (code, mode, op0, op1, 1);
else
return gen_rtx_fmt_ee (code, mode, op0, op1);
}
@ -1152,7 +1146,7 @@ simplify_binary_operation (code, mode, op0, op1)
&& GET_CODE (XEXP (op0, 0)) == PLUS)
|| (GET_CODE (op1) == CONST
&& GET_CODE (XEXP (op1, 0)) == PLUS))
&& (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
&& (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
return tem;
break;
@ -1289,7 +1283,7 @@ simplify_binary_operation (code, mode, op0, op1)
&& GET_CODE (XEXP (op0, 0)) == PLUS)
|| (GET_CODE (op1) == CONST
&& GET_CODE (XEXP (op1, 0)) == PLUS))
&& (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
&& (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
return tem;
/* Don't let a relocatable value get a negative coeff. */
@ -1728,7 +1722,10 @@ simplify_binary_operation (code, mode, op0, op1)
Rather than test for specific case, we do this by a brute-force method
and do all possible simplifications until no more changes occur. Then
we rebuild the operation. */
we rebuild the operation.
If FORCE is true, then always generate the rtx. This is used to
canonicalize stuff emitted from simplify_gen_binary. */
struct simplify_plus_minus_op_data
{
@ -1749,10 +1746,11 @@ simplify_plus_minus_op_data_cmp (p1, p2)
}
static rtx
simplify_plus_minus (code, mode, op0, op1)
simplify_plus_minus (code, mode, op0, op1, force)
enum rtx_code code;
enum machine_mode mode;
rtx op0, op1;
int force;
{
struct simplify_plus_minus_op_data ops[8];
rtx result, tem;
@ -1786,7 +1784,11 @@ simplify_plus_minus (code, mode, op0, op1)
case PLUS:
case MINUS:
if (n_ops == 7)
return 0;
{
if (force)
abort ();
return NULL_RTX;
}
ops[n_ops].op = XEXP (this_op, 1);
ops[n_ops].neg = (this_code == MINUS) ^ this_neg;
@ -1804,9 +1806,18 @@ simplify_plus_minus (code, mode, op0, op1)
break;
case CONST:
ops[i].op = XEXP (this_op, 0);
input_consts++;
changed = 1;
if (n_ops < 7
&& GET_CODE (XEXP (this_op, 0)) == PLUS
&& CONSTANT_P (XEXP (XEXP (this_op, 0), 0))
&& CONSTANT_P (XEXP (XEXP (this_op, 0), 1)))
{
ops[i].op = XEXP (XEXP (this_op, 0), 0);
ops[n_ops].op = XEXP (XEXP (this_op, 0), 1);
ops[n_ops].neg = this_neg;
n_ops++;
input_consts++;
changed = 1;
}
break;
case NOT:
@ -1838,9 +1849,14 @@ simplify_plus_minus (code, mode, op0, op1)
while (changed);
/* If we only have two operands, we can't do anything. */
if (n_ops <= 2)
if (n_ops <= 2 && !force)
return NULL_RTX;
/* Count the number of CONSTs we didn't split above. */
for (i = 0; i < n_ops; i++)
if (GET_CODE (ops[i].op) == CONST)
input_consts++;
/* Now simplify each pair of operands until nothing changes. The first
time through just simplify constants against each other. */
@ -1941,8 +1957,9 @@ simplify_plus_minus (code, mode, op0, op1)
sure we count a CONST as two operands. If we have the same
number of operands, but have made more CONSTs than before, this
is also an improvement, so accept it. */
if (n_ops + n_consts > input_ops
|| (n_ops + n_consts == input_ops && n_consts <= input_consts))
if (!force
&& (n_ops + n_consts > input_ops
|| (n_ops + n_consts == input_ops && n_consts <= input_consts)))
return NULL_RTX;
/* Put a non-negated operand first. If there aren't any, make all