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:
parent
c1a046e50e
commit
e3c8ea6725
6 changed files with 109 additions and 57 deletions
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
24
gcc/explow.c
24
gcc/explow.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
24
gcc/expr.c
24
gcc/expr.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue