From fdf473ae1b7e9b775418aa69918641dd651d0150 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 8 Feb 2002 14:20:16 -0800 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 ++++ gcc/expr.c | 17 +++++-- gcc/final.c | 1 + gcc/testsuite/ChangeLog | 4 ++ .../gcc.c-torture/compile/labels-3.c | 12 +++++ gcc/varasm.c | 44 ++++++++++++++++--- 6 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/labels-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dc39fa9ed56..2d78c2699ab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2002-02-08 Richard Henderson + + * 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 * doc/invoke.texi (RS/6000 and PowerPC Options): Fix typo. diff --git a/gcc/expr.c b/gcc/expr.c index 2b8b0856b46..13995eef670 100644 --- a/gcc/expr.c +++ b/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); diff --git a/gcc/final.c b/gcc/final.c index 3fd93b482ef..5f8de303531 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dbb5cefab28..2195de6e780 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2002-02-08 Richard Henderson + + * gcc.c-torture/compile/labels-3.c: New. + 2002-02-08 Jakub Jelinek * gcc.c-torture/execute/20020206-1.c: Test whether nesting 2 diff --git a/gcc/testsuite/gcc.c-torture/compile/labels-3.c b/gcc/testsuite/gcc.c-torture/compile/labels-3.c new file mode 100644 index 00000000000..51ac88380b8 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/labels-3.c @@ -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; +} diff --git a/gcc/varasm.c b/gcc/varasm.c index 18d200863ab..e542817d1d0 100644 --- a/gcc/varasm.c +++ b/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