aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2002-02-08 14:20:16 -0800
committerRichard Henderson <rth@gcc.gnu.org>2002-02-08 14:20:16 -0800
commitfdf473ae1b7e9b775418aa69918641dd651d0150 (patch)
tree9c571efba5f72e86224f8701d8dd1487d6780ced /gcc
parent30d287947efab771a850c16a1fb60fc65b2ae148 (diff)
downloadgcc-fdf473ae1b7e9b775418aa69918641dd651d0150.zip
gcc-fdf473ae1b7e9b775418aa69918641dd651d0150.tar.gz
gcc-fdf473ae1b7e9b775418aa69918641dd651d0150.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/expr.c17
-rw-r--r--gcc/final.c1
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/labels-3.c12
-rw-r--r--gcc/varasm.c44
6 files changed, 77 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dc39fa9..2d78c26 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/expr.c b/gcc/expr.c
index 2b8b085..13995ee 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 3fd93b4..5f8de30 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 dbb5cef..2195de6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
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 0000000..51ac883
--- /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 18d2008..e542817 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