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
This commit is contained in:
Richard Henderson 2002-02-08 14:20:16 -08:00 committed by Richard Henderson
parent 30d287947e
commit fdf473ae1b
6 changed files with 77 additions and 10 deletions

View File

@ -1,3 +1,12 @@
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>
* doc/invoke.texi (RS/6000 and PowerPC Options): Fix typo.

View File

@ -7274,15 +7274,24 @@ expand_expr (exp, target, tmode, modifier)
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)
return op0;
/* If OP0 is a constant, just convert it into the proper mode. */
if (CONSTANT_P (op0))
return
convert_modes (mode, TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
{
tree inner_type = 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)
return gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);

View File

@ -3461,6 +3461,7 @@ output_addr_const (file, x)
case ZERO_EXTEND:
case SIGN_EXTEND:
case SUBREG:
output_addr_const (file, XEXP (x, 0));
break;

View File

@ -1,3 +1,7 @@
2002-02-08 Richard Henderson <rth@redhat.com>
* gcc.c-torture/compile/labels-3.c: New.
2002-02-08 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/20020206-1.c: Test whether nesting 2

View File

@ -0,0 +1,12 @@
/* 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;
}

View File

@ -2382,7 +2382,7 @@ decode_addr_const (exp, value)
value->offset = offset;
}
enum kind { RTX_DOUBLE, RTX_INT, RTX_UNSPEC };
enum kind { RTX_UNKNOWN, RTX_DOUBLE, RTX_INT, RTX_UNSPEC };
struct rtx_const
{
ENUM_BITFIELD(kind) kind : 16;
@ -3610,7 +3610,8 @@ decode_rtx_const (mode, x, value)
break;
default:
abort ();
value->kind = RTX_UNKNOWN;
break;
}
if (value->kind == RTX_INT && value->un.addr.base != 0
@ -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))
{
case SYMBOL_REF:
@ -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, 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)
return GEN_INT (val0.un.addr.offset - val1.un.addr.offset);
return x;
}
@ -4370,8 +4373,37 @@ initializer_constant_valid_p (value, endtype)
tree op0, op1;
op0 = TREE_OPERAND (value, 0);
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
&& TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL