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:
parent
30d287947e
commit
fdf473ae1b
6 changed files with 77 additions and 10 deletions
|
@ -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.
|
||||
|
|
17
gcc/expr.c
17
gcc/expr.c
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
12
gcc/testsuite/gcc.c-torture/compile/labels-3.c
Normal file
12
gcc/testsuite/gcc.c-torture/compile/labels-3.c
Normal 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;
|
||||
}
|
44
gcc/varasm.c
44
gcc/varasm.c
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue