Commit fdf473ae by Richard Henderson Committed by Richard Henderson

expr.c (expand_expr): Mind EXPAND_INITIALIZER for truncation also.

        * expr.c (expand_expr): Mind EXPAND_INITIALIZER for truncation also.
        * final.c (output_addr_const): Accept and discard SUBREG.
        * varasm.c (decode_addr_const): Don't abort on unknown expressions --
        mark them unknown instead.
        (simplify_subtraction): Handle RTX_UNKNOWN.
        (initializer_constant_valid_p): Strip NOP_EXPRs that narrow the mode.

        * gcc.c-torture/compile/labels-3.c: New.

From-SVN: r49622
parent 30d28794
2002-02-08 Richard Henderson <rth@redhat.com>
* expr.c (expand_expr): Mind EXPAND_INITIALIZER for truncation also.
* final.c (output_addr_const): Accept and discard SUBREG.
* varasm.c (decode_addr_const): Don't abort on unknown expressions --
mark them unknown instead.
(simplify_subtraction): Handle RTX_UNKNOWN.
(initializer_constant_valid_p): Strip NOP_EXPRs that narrow the mode.
2002-02-08 David Edelsohn <edelsohn@gnu.org> 2002-02-08 David Edelsohn <edelsohn@gnu.org>
* doc/invoke.texi (RS/6000 and PowerPC Options): Fix typo. * doc/invoke.texi (RS/6000 and PowerPC Options): Fix typo.
......
...@@ -7274,15 +7274,24 @@ expand_expr (exp, target, tmode, modifier) ...@@ -7274,15 +7274,24 @@ expand_expr (exp, target, tmode, modifier)
return op0; return op0;
} }
op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0); op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
if (GET_MODE (op0) == mode) if (GET_MODE (op0) == mode)
return op0; return op0;
/* If OP0 is a constant, just convert it into the proper mode. */ /* If OP0 is a constant, just convert it into the proper mode. */
if (CONSTANT_P (op0)) if (CONSTANT_P (op0))
return {
convert_modes (mode, TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))), tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))); enum machine_mode inner_mode = TYPE_MODE (inner_type);
if (modifier == EXPAND_INITIALIZER)
return simplify_gen_subreg (mode, op0, inner_mode,
subreg_lowpart_offset (mode,
inner_mode));
else
return convert_modes (mode, inner_mode, op0,
TREE_UNSIGNED (inner_type));
}
if (modifier == EXPAND_INITIALIZER) if (modifier == EXPAND_INITIALIZER)
return gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0); return gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
......
...@@ -3461,6 +3461,7 @@ output_addr_const (file, x) ...@@ -3461,6 +3461,7 @@ output_addr_const (file, x)
case ZERO_EXTEND: case ZERO_EXTEND:
case SIGN_EXTEND: case SIGN_EXTEND:
case SUBREG:
output_addr_const (file, XEXP (x, 0)); output_addr_const (file, XEXP (x, 0));
break; break;
......
2002-02-08 Richard Henderson <rth@redhat.com>
* gcc.c-torture/compile/labels-3.c: New.
2002-02-08 Jakub Jelinek <jakub@redhat.com> 2002-02-08 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/20020206-1.c: Test whether nesting 2 * gcc.c-torture/execute/20020206-1.c: Test whether nesting 2
......
/* Verify that we can narrow the storage associated with label diffs. */
int foo (int a)
{
static const short ar[] = { &&l1 - &&l1, &&l2 - &&l1 };
void *p = &&l1 + ar[a];
goto *p;
l1:
return 1;
l2:
return 2;
}
...@@ -2382,7 +2382,7 @@ decode_addr_const (exp, value) ...@@ -2382,7 +2382,7 @@ decode_addr_const (exp, value)
value->offset = offset; value->offset = offset;
} }
enum kind { RTX_DOUBLE, RTX_INT, RTX_UNSPEC }; enum kind { RTX_UNKNOWN, RTX_DOUBLE, RTX_INT, RTX_UNSPEC };
struct rtx_const struct rtx_const
{ {
ENUM_BITFIELD(kind) kind : 16; ENUM_BITFIELD(kind) kind : 16;
...@@ -3610,7 +3610,8 @@ decode_rtx_const (mode, x, value) ...@@ -3610,7 +3610,8 @@ decode_rtx_const (mode, x, value)
break; break;
default: default:
abort (); value->kind = RTX_UNKNOWN;
break;
} }
if (value->kind == RTX_INT && value->un.addr.base != 0 if (value->kind == RTX_INT && value->un.addr.base != 0
...@@ -3630,7 +3631,7 @@ decode_rtx_const (mode, x, value) ...@@ -3630,7 +3631,7 @@ decode_rtx_const (mode, x, value)
} }
} }
if (value->kind != RTX_DOUBLE && value->un.addr.base != 0) if (value->kind > RTX_DOUBLE && value->un.addr.base != 0)
switch (GET_CODE (value->un.addr.base)) switch (GET_CODE (value->un.addr.base))
{ {
case SYMBOL_REF: case SYMBOL_REF:
...@@ -3660,9 +3661,11 @@ simplify_subtraction (x) ...@@ -3660,9 +3661,11 @@ simplify_subtraction (x)
decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0); decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0);
decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1); decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1);
if (val0.kind != RTX_DOUBLE && val0.kind == val1.kind if (val0.kind > RTX_DOUBLE
&& val0.kind == val1.kind
&& val0.un.addr.base == val1.un.addr.base) && val0.un.addr.base == val1.un.addr.base)
return GEN_INT (val0.un.addr.offset - val1.un.addr.offset); return GEN_INT (val0.un.addr.offset - val1.un.addr.offset);
return x; return x;
} }
...@@ -4370,8 +4373,37 @@ initializer_constant_valid_p (value, endtype) ...@@ -4370,8 +4373,37 @@ initializer_constant_valid_p (value, endtype)
tree op0, op1; tree op0, op1;
op0 = TREE_OPERAND (value, 0); op0 = TREE_OPERAND (value, 0);
op1 = TREE_OPERAND (value, 1); op1 = TREE_OPERAND (value, 1);
STRIP_NOPS (op0);
STRIP_NOPS (op1); /* Like STRIP_NOPS except allow the operand mode to widen.
This works around a feature of fold that simplfies
(int)(p1 - p2) to ((int)p1 - (int)p2) under the theory
that the narrower operation is cheaper. */
while (TREE_CODE (op0) == NOP_EXPR
|| TREE_CODE (op0) == CONVERT_EXPR
|| TREE_CODE (op0) == NON_LVALUE_EXPR)
{
tree inner = TREE_OPERAND (op0, 0);
if (inner == error_mark_node
|| ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
|| (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
> GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
break;
op0 = inner;
}
while (TREE_CODE (op1) == NOP_EXPR
|| TREE_CODE (op1) == CONVERT_EXPR
|| TREE_CODE (op1) == NON_LVALUE_EXPR)
{
tree inner = TREE_OPERAND (op1, 0);
if (inner == error_mark_node
|| ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
|| (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
> GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
break;
op1 = inner;
}
if (TREE_CODE (op0) == ADDR_EXPR if (TREE_CODE (op0) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL && TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment