diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c7878d70e65..8a8dcac21e7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2002-02-21 Richard Henderson + + * 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 * dwarf2out.c (DWARF_LINE_MIN_INSTR_LENGTH): Removed. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index fd84c07239e..009b5d8511b 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 82dd61a5f64..836fbf5385a 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 a72a03be64c..7a770ee897c 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 a903b14ebb9..b7304350b7f 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 84b8cb240ce..55cbfc6fbbe 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