OSDN Git Service

* expr.c (expand_expr): Mind EXPAND_INITIALIZER for truncation also.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 8 Feb 2002 22:20:16 +0000 (22:20 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 8 Feb 2002 22:20:16 +0000 (22:20 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49622 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/final.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/labels-3.c [new file with mode: 0644]
gcc/varasm.c

index dc39fa9..2d78c26 100644 (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.
index 2b8b085..13995ee 100644 (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);
index 3fd93b4..5f8de30 100644 (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;
 
index dbb5cef..2195de6 100644 (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
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 (file)
index 0000000..51ac883
--- /dev/null
@@ -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;
+}
index 18d2008..e542817 100644 (file)
@@ -2382,7 +2382,7 @@ decode_addr_const (exp, value)
   value->offset = offset;
 }
 \f
-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