aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-02-21 15:06:16 -0800
committerRichard Henderson <rth@gcc.gnu.org>2002-02-21 15:06:16 -0800
commite3c8ea672563a4f8762b60f302a0a13c788405f7 (patch)
treea3e850cb8cef839fc826131f523c7a39605ea9d5 /gcc
parentc1a046e50ee5d3fe4b789ed2ad51c60db6687788 (diff)
downloadgcc-e3c8ea672563a4f8762b60f302a0a13c788405f7.zip
gcc-e3c8ea672563a4f8762b60f302a0a13c788405f7.tar.gz
gcc-e3c8ea672563a4f8762b60f302a0a13c788405f7.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/config/i386/i386.c14
-rw-r--r--gcc/emit-rtl.c23
-rw-r--r--gcc/explow.c24
-rw-r--r--gcc/expr.c24
-rw-r--r--gcc/simplify-rtx.c63
6 files changed, 109 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c7878d7..8a8dcac 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index fd84c07..009b5d8 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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)
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 82dd61a..836fbf5 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -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. */
diff --git a/gcc/explow.c b/gcc/explow.c
index a72a03b..7a770ee 100644
--- a/gcc/explow.c
+++ b/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;
}
diff --git a/gcc/expr.c b/gcc/expr.c
index a903b14..b730435 100644
--- a/gcc/expr.c
+++ b/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;
}
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 84b8cb2..55cbfc6 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -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