diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 2001-02-06 12:39:15 +0000 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 2001-02-06 07:39:15 -0500 |
commit | d14057222fec681710cd1b1ac1d47478c0466bfb (patch) | |
tree | ef948bedc788321fdca09d6b2f508f386ee213d9 /gcc/function.c | |
parent | a87b4257946d4453f250585aa22adc4f70db1165 (diff) | |
download | gcc-d14057222fec681710cd1b1ac1d47478c0466bfb.tar.gz |
combine.c (nonzero_bits, case PLUS): If pointers extend unsigned and this is the sum of a pointer and a constant...
* combine.c (nonzero_bits, case PLUS): If pointers extend unsigned
and this is the sum of a pointer and a constant, we know the result
did not overflow.
(num_sign_bit_copies, case PLUS): Likewise.
* explow.c (convert_memory_address): Remove opposite SUBREG.
* function.c (instantiate_new_reg): New function (from common code).
(instantiate_virtual_regs_1): Call it.
For PLUS, handle if (plus (subreg (virt-reg) (const_int))
if pointers sign- or zero-extend.
* simplify-rtx.c (simplify_unary_operation, case ZERO_EXTEND):
If pointers extend unsigned, use inside of SUBREG.
(simplify_unary_operation, case SIGN_EXTEND): Likewise, if sign extend.
From-SVN: r39489
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 111 |
1 files changed, 60 insertions, 51 deletions
diff --git a/gcc/function.c b/gcc/function.c index 5421450c4a8..259ccca4fb0 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -269,6 +269,7 @@ static void optimize_bit_field PARAMS ((rtx, rtx, rtx *)); static void instantiate_decls PARAMS ((tree, int)); static void instantiate_decls_1 PARAMS ((tree, int)); static void instantiate_decl PARAMS ((rtx, HOST_WIDE_INT, int)); +static rtx instantiate_new_reg PARAMS ((rtx, HOST_WIDE_INT *)); static int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int)); static void delete_handlers PARAMS ((void)); static void pad_to_arg_alignment PARAMS ((struct args_size *, int, @@ -3680,6 +3681,35 @@ instantiate_decl (x, size, valid_only) XEXP (x, 0) = addr; } +/* Given a piece of RTX and a pointer to a HOST_WIDE_INT, if the RTX + is a virtual register, return the requivalent hard register and set the + offset indirectly through the pointer. Otherwise, return 0. */ + +static rtx +instantiate_new_reg (x, poffset) + rtx x; + HOST_WIDE_INT *poffset; +{ + rtx new; + HOST_WIDE_INT offset; + + if (x == virtual_incoming_args_rtx) + new = arg_pointer_rtx, offset = in_arg_offset; + else if (x == virtual_stack_vars_rtx) + new = frame_pointer_rtx, offset = var_offset; + else if (x == virtual_stack_dynamic_rtx) + new = stack_pointer_rtx, offset = dynamic_offset; + else if (x == virtual_outgoing_args_rtx) + new = stack_pointer_rtx, offset = out_arg_offset; + else if (x == virtual_cfa_rtx) + new = arg_pointer_rtx, offset = cfa_offset; + else + return 0; + + *poffset = offset; + return new; +} + /* Given a pointer to a piece of rtx and an optional pointer to the containing object, instantiate any virtual registers present in it. @@ -3739,21 +3769,14 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) the actual register should receive the source minus the appropriate offset. This is used, for example, in the handling of non-local gotos. */ - if (SET_DEST (x) == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = -in_arg_offset; - else if (SET_DEST (x) == virtual_stack_vars_rtx) - new = frame_pointer_rtx, offset = -var_offset; - else if (SET_DEST (x) == virtual_stack_dynamic_rtx) - new = stack_pointer_rtx, offset = -dynamic_offset; - else if (SET_DEST (x) == virtual_outgoing_args_rtx) - new = stack_pointer_rtx, offset = -out_arg_offset; - else if (SET_DEST (x) == virtual_cfa_rtx) - new = arg_pointer_rtx, offset = -cfa_offset; - - if (new) + if ((new = instantiate_new_reg (SET_DEST (x), &offset)) != 0) { rtx src = SET_SRC (x); + /* We are setting the register, not using it, so the relevant + offset is the negative of the offset to use were we using + the register. */ + offset = - offset; instantiate_virtual_regs_1 (&src, NULL_RTX, 0); /* The only valid sources here are PLUS or REG. Just do @@ -3793,40 +3816,37 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) /* Check for (plus (plus VIRT foo) (const_int)) first. */ if (GET_CODE (XEXP (x, 0)) == PLUS) { - rtx inner = XEXP (XEXP (x, 0), 0); - - if (inner == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = in_arg_offset; - else if (inner == virtual_stack_vars_rtx) - new = frame_pointer_rtx, offset = var_offset; - else if (inner == virtual_stack_dynamic_rtx) - new = stack_pointer_rtx, offset = dynamic_offset; - else if (inner == virtual_outgoing_args_rtx) - new = stack_pointer_rtx, offset = out_arg_offset; - else if (inner == virtual_cfa_rtx) - new = arg_pointer_rtx, offset = cfa_offset; + if ((new = instantiate_new_reg (XEXP (XEXP (x, 0), 0), &offset))) + { + instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object, + extra_insns); + new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1)); + } else { loc = &XEXP (x, 0); goto restart; } - - instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object, - extra_insns); - new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1)); } - else if (XEXP (x, 0) == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = in_arg_offset; - else if (XEXP (x, 0) == virtual_stack_vars_rtx) - new = frame_pointer_rtx, offset = var_offset; - else if (XEXP (x, 0) == virtual_stack_dynamic_rtx) - new = stack_pointer_rtx, offset = dynamic_offset; - else if (XEXP (x, 0) == virtual_outgoing_args_rtx) - new = stack_pointer_rtx, offset = out_arg_offset; - else if (XEXP (x, 0) == virtual_cfa_rtx) - new = arg_pointer_rtx, offset = cfa_offset; - else +#ifdef POINTERS_EXTEND_UNSIGNED + /* If we have (plus (subreg (virtual-reg)) (const_int)), we know + we can commute the PLUS and SUBREG because pointers into the + frame are well-behaved. */ + else if (GET_CODE (XEXP (x, 0)) == SUBREG && GET_MODE (x) == ptr_mode + && GET_CODE (XEXP (x, 1)) == CONST_INT + && 0 != (new + = instantiate_new_reg (SUBREG_REG (XEXP (x, 0)), + &offset)) + && validate_change (object, loc, + plus_constant (gen_lowpart (ptr_mode, + new), + offset + + INTVAL (XEXP (x, 1))), + 0)) + return 1; +#endif + else if ((new = instantiate_new_reg (XEXP (x, 0), &offset)) == 0) { /* We know the second operand is a constant. Unless the first operand is a REG (which has been already checked), @@ -4025,18 +4045,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns) case REG: /* Try to replace with a PLUS. If that doesn't work, compute the sum in front of this insn and substitute the temporary. */ - if (x == virtual_incoming_args_rtx) - new = arg_pointer_rtx, offset = in_arg_offset; - else if (x == virtual_stack_vars_rtx) - new = frame_pointer_rtx, offset = var_offset; - else if (x == virtual_stack_dynamic_rtx) - new = stack_pointer_rtx, offset = dynamic_offset; - else if (x == virtual_outgoing_args_rtx) - new = stack_pointer_rtx, offset = out_arg_offset; - else if (x == virtual_cfa_rtx) - new = arg_pointer_rtx, offset = cfa_offset; - - if (new) + if ((new = instantiate_new_reg (x, &offset)) != 0) { temp = plus_constant (new, offset); if (!validate_change (object, loc, temp, 0)) |