aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2001-02-06 12:39:15 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2001-02-06 07:39:15 -0500
commitd14057222fec681710cd1b1ac1d47478c0466bfb (patch)
treeef948bedc788321fdca09d6b2f508f386ee213d9 /gcc
parenta87b4257946d4453f250585aa22adc4f70db1165 (diff)
downloadgcc-d14057222fec681710cd1b1ac1d47478c0466bfb.zip
gcc-d14057222fec681710cd1b1ac1d47478c0466bfb.tar.gz
gcc-d14057222fec681710cd1b1ac1d47478c0466bfb.tar.bz2
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')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/combine.c25
-rw-r--r--gcc/explow.c5
-rw-r--r--gcc/function.c111
-rw-r--r--gcc/simplify-rtx.c12
5 files changed, 114 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 547f50f..f0c7159 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/combine.c b/gcc/combine.c
index 74b02b5..662f05f 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 d36ceff..b7c0bb9 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 5421450..259ccca 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 6ae44b2..afd8d26 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