From d14057222fec681710cd1b1ac1d47478c0466bfb Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Tue, 6 Feb 2001 12:39:15 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 15 ++++++ gcc/combine.c | 25 +++++++++- gcc/explow.c | 5 ++ gcc/function.c | 111 ++++++++++++++++++++++++--------------------- gcc/simplify-rtx.c | 12 ++++- 5 files changed, 114 insertions(+), 54 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 547f50fad7d..f0c7159456b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +Mon Feb 5 21:56:16 2001 Richard Kenner + + * 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. + 2001-02-05 Benjamin Kosnik * Makefile.in (-DGPLUSPLUS_TOOL_INCLUDE_DIR): Change to target diff --git a/gcc/combine.c b/gcc/combine.c index 74b02b55a47..662f05f2240 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -8308,6 +8308,16 @@ nonzero_bits (x, mode) if (result_low > 0) nonzero &= ~(((HOST_WIDE_INT) 1 << result_low) - 1); + +#ifdef POINTERS_EXTEND_UNSIGNED + /* If pointers extend unsigned and this is an addition or subtraction + to a pointer in Pmode, all the bits above ptr_mode are known to be + zero. */ + if (POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode + && (code == PLUS || code == MINUS) + && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0))) + nonzero &= GET_MODE_MASK (ptr_mode); +#endif } break; @@ -8646,7 +8656,20 @@ num_sign_bit_copies (x, mode) num0 = num_sign_bit_copies (XEXP (x, 0), mode); num1 = num_sign_bit_copies (XEXP (x, 1), mode); - return MAX (1, MIN (num0, num1) - 1); + result = MAX (1, MIN (num0, num1) - 1); + +#ifdef POINTERS_EXTEND_UNSIGNED + /* If pointers extend signed and this is an addition or subtraction + to a pointer in Pmode, all the bits above ptr_mode are known to be + sign bit copies. */ + if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode + && (code == PLUS || code == MINUS) + && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0))) + result = MAX ((GET_MODE_BITSIZE (Pmode) + - GET_MODE_BITSIZE (ptr_mode) + 1), + result); +#endif + return result; case MULT: /* The number of bits of the product is the sum of the number of diff --git a/gcc/explow.c b/gcc/explow.c index d36ceffa440..b7c0bb9f6d9 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -386,6 +386,11 @@ convert_memory_address (to_mode, x) case CONST_DOUBLE: return x; + case SUBREG: + if (GET_MODE (SUBREG_REG (x)) == to_mode) + return SUBREG_REG (x); + break; + case LABEL_REF: temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0)); LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x); 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)) diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 6ae44b237a0..afd8d264b62 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -623,7 +623,11 @@ simplify_unary_operation (code, mode, op, op_mode) #ifdef POINTERS_EXTEND_UNSIGNED if (! POINTERS_EXTEND_UNSIGNED && mode == Pmode && GET_MODE (op) == ptr_mode - && CONSTANT_P (op)) + && (CONSTANT_P (op) + || (GET_CODE (op) == SUBREG + && GET_CODE (SUBREG_REG (op)) == REG + && REG_POINTER (SUBREG_REG (op)) + && GET_MODE (SUBREG_REG (op)) == Pmode))) return convert_memory_address (Pmode, op); #endif break; @@ -632,7 +636,11 @@ simplify_unary_operation (code, mode, op, op_mode) case ZERO_EXTEND: if (POINTERS_EXTEND_UNSIGNED && mode == Pmode && GET_MODE (op) == ptr_mode - && CONSTANT_P (op)) + && (CONSTANT_P (op) + || (GET_CODE (op) == SUBREG + && GET_CODE (SUBREG_REG (op)) == REG + && REG_POINTER (SUBREG_REG (op)) + && GET_MODE (SUBREG_REG (op)) == Pmode))) return convert_memory_address (Pmode, op); break; #endif -- 2.30.2