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
This commit is contained in:
Richard Kenner 2001-02-06 12:39:15 +00:00 committed by Richard Kenner
parent a87b425794
commit d14057222f
5 changed files with 114 additions and 54 deletions

View File

@ -1,3 +1,18 @@
Mon Feb 5 21:56:16 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* 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 <bkoz@redhat.com>
* Makefile.in (-DGPLUSPLUS_TOOL_INCLUDE_DIR): Change to target

View File

@ -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

View File

@ -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);

View File

@ -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))

View File

@ -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