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> 2001-02-05 Benjamin Kosnik <bkoz@redhat.com>
* Makefile.in (-DGPLUSPLUS_TOOL_INCLUDE_DIR): Change to target * Makefile.in (-DGPLUSPLUS_TOOL_INCLUDE_DIR): Change to target

View File

@ -8308,6 +8308,16 @@ nonzero_bits (x, mode)
if (result_low > 0) if (result_low > 0)
nonzero &= ~(((HOST_WIDE_INT) 1 << result_low) - 1); 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; break;
@ -8646,7 +8656,20 @@ num_sign_bit_copies (x, mode)
num0 = num_sign_bit_copies (XEXP (x, 0), mode); num0 = num_sign_bit_copies (XEXP (x, 0), mode);
num1 = num_sign_bit_copies (XEXP (x, 1), 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: case MULT:
/* The number of bits of the product is the sum of the number of /* 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: case CONST_DOUBLE:
return x; return x;
case SUBREG:
if (GET_MODE (SUBREG_REG (x)) == to_mode)
return SUBREG_REG (x);
break;
case LABEL_REF: case LABEL_REF:
temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0)); temp = gen_rtx_LABEL_REF (to_mode, XEXP (x, 0));
LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x); 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 PARAMS ((tree, int));
static void instantiate_decls_1 PARAMS ((tree, int)); static void instantiate_decls_1 PARAMS ((tree, int));
static void instantiate_decl PARAMS ((rtx, HOST_WIDE_INT, 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 int instantiate_virtual_regs_1 PARAMS ((rtx *, rtx, int));
static void delete_handlers PARAMS ((void)); static void delete_handlers PARAMS ((void));
static void pad_to_arg_alignment PARAMS ((struct args_size *, int, 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; 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 /* Given a pointer to a piece of rtx and an optional pointer to the
containing object, instantiate any virtual registers present in it. 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 the actual register should receive the source minus the
appropriate offset. This is used, for example, in the handling appropriate offset. This is used, for example, in the handling
of non-local gotos. */ of non-local gotos. */
if (SET_DEST (x) == virtual_incoming_args_rtx) if ((new = instantiate_new_reg (SET_DEST (x), &offset)) != 0)
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)
{ {
rtx src = SET_SRC (x); 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); instantiate_virtual_regs_1 (&src, NULL_RTX, 0);
/* The only valid sources here are PLUS or REG. Just do /* 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. */ /* Check for (plus (plus VIRT foo) (const_int)) first. */
if (GET_CODE (XEXP (x, 0)) == PLUS) if (GET_CODE (XEXP (x, 0)) == PLUS)
{ {
rtx inner = XEXP (XEXP (x, 0), 0); if ((new = instantiate_new_reg (XEXP (XEXP (x, 0), 0), &offset)))
{
if (inner == virtual_incoming_args_rtx) instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 1), object,
new = arg_pointer_rtx, offset = in_arg_offset; extra_insns);
else if (inner == virtual_stack_vars_rtx) new = gen_rtx_PLUS (Pmode, new, XEXP (XEXP (x, 0), 1));
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;
else else
{ {
loc = &XEXP (x, 0); loc = &XEXP (x, 0);
goto restart; 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) #ifdef POINTERS_EXTEND_UNSIGNED
new = arg_pointer_rtx, offset = in_arg_offset; /* If we have (plus (subreg (virtual-reg)) (const_int)), we know
else if (XEXP (x, 0) == virtual_stack_vars_rtx) we can commute the PLUS and SUBREG because pointers into the
new = frame_pointer_rtx, offset = var_offset; frame are well-behaved. */
else if (XEXP (x, 0) == virtual_stack_dynamic_rtx) else if (GET_CODE (XEXP (x, 0)) == SUBREG && GET_MODE (x) == ptr_mode
new = stack_pointer_rtx, offset = dynamic_offset; && GET_CODE (XEXP (x, 1)) == CONST_INT
else if (XEXP (x, 0) == virtual_outgoing_args_rtx) && 0 != (new
new = stack_pointer_rtx, offset = out_arg_offset; = instantiate_new_reg (SUBREG_REG (XEXP (x, 0)),
else if (XEXP (x, 0) == virtual_cfa_rtx) &offset))
new = arg_pointer_rtx, offset = cfa_offset; && validate_change (object, loc,
else 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 /* We know the second operand is a constant. Unless the
first operand is a REG (which has been already checked), first operand is a REG (which has been already checked),
@ -4025,18 +4045,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
case REG: case REG:
/* Try to replace with a PLUS. If that doesn't work, compute the sum /* Try to replace with a PLUS. If that doesn't work, compute the sum
in front of this insn and substitute the temporary. */ in front of this insn and substitute the temporary. */
if (x == virtual_incoming_args_rtx) if ((new = instantiate_new_reg (x, &offset)) != 0)
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)
{ {
temp = plus_constant (new, offset); temp = plus_constant (new, offset);
if (!validate_change (object, loc, temp, 0)) 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 #ifdef POINTERS_EXTEND_UNSIGNED
if (! POINTERS_EXTEND_UNSIGNED if (! POINTERS_EXTEND_UNSIGNED
&& mode == Pmode && GET_MODE (op) == ptr_mode && 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); return convert_memory_address (Pmode, op);
#endif #endif
break; break;
@ -632,7 +636,11 @@ simplify_unary_operation (code, mode, op, op_mode)
case ZERO_EXTEND: case ZERO_EXTEND:
if (POINTERS_EXTEND_UNSIGNED if (POINTERS_EXTEND_UNSIGNED
&& mode == Pmode && GET_MODE (op) == ptr_mode && 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); return convert_memory_address (Pmode, op);
break; break;
#endif #endif