]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree.c (build_zero_cst): New.
authorJan Hubicka <jh@suse.cz>
Mon, 13 Sep 2010 16:37:06 +0000 (18:37 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Mon, 13 Sep 2010 16:37:06 +0000 (16:37 +0000)
* tree.c (build_zero_cst): New.
* tree.h (build_zero_cst): Declare.
* tree-ssa-ccp.c (get_constant_value): Accept general operands.
(get_base_constructor): Break out from ...
(fold_const_aggregate_ref): Here; handle empty constructors.

* gcc.dg/torture/pr23821.c: Drop static keyword.
* gcc.dg/tree-ssa/loop-19.c: Likewise.
* gcc.dg/tree-ssa/foldconst-4.c: New.

From-SVN: r164250

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr23821.c
gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loop-19.c
gcc/tree-ssa-ccp.c
gcc/tree.c
gcc/tree.h

index 8d47a83402ec8b70fabf528ba579b34dc2505e48..9341f89ec4a07a1ec27c36a52d205169ddbaae0b 100644 (file)
@@ -1,3 +1,11 @@
+2010-09-13  Jan Hubicka  <jh@suse.cz>
+
+       * tree.c (build_zero_cst): New.
+       * tree.h (build_zero_cst): Declare.
+       * tree-ssa-ccp.c (get_constant_value): Accept general operands.
+       (get_base_constructor): Break out from ...
+       (fold_const_aggregate_ref): Here; handle empty constructors.
+
 2010-09-13  Marcus Shawcroft  <marcus.shawcroft@arm.com>
 
        * config/arm/arm.md: (define_attr "conds"): Update comment.
index efcecb6c53e2909eb46841bb6c373683c58ffd2c..59118c228b7496c833a1cb229248ccd91a9674e7 100644 (file)
@@ -1,3 +1,9 @@
+2010-09-13  Jan Hubicka  <jh@suse.cz>
+
+       * gcc.dg/torture/pr23821.c: Drop static keyword.
+       * gcc.dg/tree-ssa/loop-19.c: Likewise.
+       * gcc.dg/tree-ssa/foldconst-4.c: New testcase.
+
 2010-09-13  Marcus Shawcroft  <marcus.shawcroft@arm.com>
 
        * gcc.target/arm/sync-1.c: New.
index 7d425831bb8e7182040cba8e2e672f447ff059b1..7632d8425ca8b744ac1a42cf1b8dca202f1aac65 100644 (file)
@@ -5,7 +5,7 @@
 /* { dg-skip-if "" { *-*-* } { "-O1" } { "" } } */
 /* { dg-options "-fdump-tree-ivcanon-details" } */
 
-static int a[199];
+int a[199];
 
 extern void abort (void);
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c
new file mode 100644 (file)
index 0000000..b416d37
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-ccp2" } */
+
+struct a {int a,b;};
+const static struct a a;
+static int b[10];
+int c;
+test()
+{
+  return a.a+b[c];
+}
+/* { dg-final { scan-tree-dump "return 0;" "ccp2" } } */
+/* { dg-final { cleanup-tree-dump "ccp2" } } */
index 4dfd2277dbc5145cce463b5488aec9adde8edcf0..80f2e601e31ce068a3ae8639b46fb347a5850217 100644 (file)
@@ -9,7 +9,7 @@
 /* { dg-options "-O3 -fno-prefetch-loop-arrays -fdump-tree-optimized" } */
 
 # define N      2000000
-static double   a[N],c[N];
+double   a[N],c[N];
 void tuned_STREAM_Copy()
 {
   int j;
index 0bc90ad9291708cd15f122a3eb42f08879751dbc..42b8a58b9d32311551a38cdbcde6186f9df17de9 100644 (file)
@@ -315,7 +315,14 @@ get_value (tree var)
 static inline tree
 get_constant_value (tree var)
 {
-  prop_value_t *val = get_value (var);
+  prop_value_t *val;
+  if (TREE_CODE (var) != SSA_NAME)
+    {
+      if (is_gimple_min_invariant (var))
+        return var;
+      return NULL_TREE;
+    }
+  val = get_value (var);
   if (val
       && val->lattice_val == CONSTANT
       && (TREE_CODE (val->value) != INTEGER_CST
@@ -1308,6 +1315,62 @@ ccp_fold (gimple stmt)
     }
 }
 
+/* See if we can find constructor defining value of BASE.
+
+   As a special case, return error_mark_node when constructor
+   is not explicitly available, but it is known to be zero
+   such as 'static const int a;'.  */
+static tree
+get_base_constructor (tree base, tree *offset)
+{
+  *offset = NULL;
+  if (TREE_CODE (base) == MEM_REF)
+    {
+      if (!integer_zerop (TREE_OPERAND (base, 1)))
+        *offset = TREE_OPERAND (base, 1);
+
+      base = get_constant_value (TREE_OPERAND (base, 0));
+      if (!base || TREE_CODE (base) != ADDR_EXPR)
+        return NULL_TREE;
+      base = TREE_OPERAND (base, 0);
+    }
+
+  /* Get a CONSTRUCTOR.  If BASE is a VAR_DECL, get its
+     DECL_INITIAL.  If BASE is a nested reference into another
+     ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
+     the inner reference.  */
+  switch (TREE_CODE (base))
+    {
+    case VAR_DECL:
+      if (!TREE_READONLY (base)
+         || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
+             && !varpool_get_node (base)->const_value_known))
+       return NULL_TREE;
+
+      /* Fallthru.  */
+    case CONST_DECL:
+      if (!DECL_INITIAL (base)
+         && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
+        return error_mark_node;
+      return DECL_INITIAL (base);
+      
+      break;
+
+    case ARRAY_REF:
+    case COMPONENT_REF:
+      return fold_const_aggregate_ref (base);
+      break;
+
+    case STRING_CST:
+    case CONSTRUCTOR:
+      return base;
+      break;
+
+    default:
+      return NULL_TREE;
+    }
+}
+
 /* Return the tree representing the element referenced by T if T is an
    ARRAY_REF or COMPONENT_REF into constant aggregates.  Return
    NULL_TREE otherwise.  */
@@ -1315,7 +1378,7 @@ ccp_fold (gimple stmt)
 tree
 fold_const_aggregate_ref (tree t)
 {
-  tree base, ctor, idx, field;
+  tree ctor, idx, field;
   unsigned HOST_WIDE_INT cnt;
   tree cfield, cval;
   tree tem;
@@ -1330,46 +1393,13 @@ fold_const_aggregate_ref (tree t)
   switch (TREE_CODE (t))
     {
     case ARRAY_REF:
-      /* Get a CONSTRUCTOR.  If BASE is a VAR_DECL, get its
-        DECL_INITIAL.  If BASE is a nested reference into another
-        ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
-        the inner reference.  */
-      base = TREE_OPERAND (t, 0);
-      switch (TREE_CODE (base))
-       {
-       case MEM_REF:
-         /* ???  We could handle this case.  */
-         if (!integer_zerop (TREE_OPERAND (base, 1)))
-           return NULL_TREE;
-         base = get_base_address (base);
-         if (!base
-             || TREE_CODE (base) != VAR_DECL)
-           return NULL_TREE;
+      ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx);
 
-         /* Fallthru.  */
-       case VAR_DECL:
-         if (!TREE_READONLY (base)
-             || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
-             || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
-                 && !varpool_get_node (base)->const_value_known))
-           return NULL_TREE;
-
-         ctor = DECL_INITIAL (base);
-         break;
-
-       case ARRAY_REF:
-       case COMPONENT_REF:
-         ctor = fold_const_aggregate_ref (base);
-         break;
-
-       case STRING_CST:
-       case CONSTRUCTOR:
-         ctor = base;
-         break;
+      if (idx)
+       return NULL_TREE;
 
-       default:
-         return NULL_TREE;
-       }
+      if (ctor == error_mark_node)
+       return build_zero_cst (TREE_TYPE (t));
 
       if (ctor == NULL_TREE
          || (TREE_CODE (ctor) != CONSTRUCTOR
@@ -1436,27 +1466,13 @@ fold_const_aggregate_ref (tree t)
         DECL_INITIAL.  If BASE is a nested reference into another
         ARRAY_REF or COMPONENT_REF, make a recursive call to resolve
         the inner reference.  */
-      base = TREE_OPERAND (t, 0);
-      switch (TREE_CODE (base))
-       {
-       case VAR_DECL:
-         if (!TREE_READONLY (base)
-             || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
-             || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
-                 && !varpool_get_node (base)->const_value_known))
-           return NULL_TREE;
+      ctor = get_base_constructor (TREE_OPERAND (t, 0), &idx);
 
-         ctor = DECL_INITIAL (base);
-         break;
-
-       case ARRAY_REF:
-       case COMPONENT_REF:
-         ctor = fold_const_aggregate_ref (base);
-         break;
+      if (idx)
+       return NULL_TREE;
 
-       default:
-         return NULL_TREE;
-       }
+      if (ctor == error_mark_node)
+       return build_zero_cst (TREE_TYPE (t));
 
       if (ctor == NULL_TREE
          || TREE_CODE (ctor) != CONSTRUCTOR)
@@ -1482,55 +1498,29 @@ fold_const_aggregate_ref (tree t)
       }
 
     case MEM_REF:
-      /* Get the base object we are accessing.  */
-      base = TREE_OPERAND (t, 0);
-      if (TREE_CODE (base) == SSA_NAME
-         && (tem = get_constant_value (base)))
-       base = tem;
-      if (TREE_CODE (base) != ADDR_EXPR)
-       return NULL_TREE;
-      base = TREE_OPERAND (base, 0);
-      switch (TREE_CODE (base))
-       {
-       case VAR_DECL:
-         if (DECL_P (base)
-             && !AGGREGATE_TYPE_P (TREE_TYPE (base))
-             && integer_zerop (TREE_OPERAND (t, 1)))
-           {
-             tree res = get_symbol_constant_value (base);
-             if (res
-                 && !useless_type_conversion_p
-                       (TREE_TYPE (t), TREE_TYPE (res)))
-               res = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), res);
-             return res;
-           }
-
-         if (!TREE_READONLY (base)
-             || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
-             || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
-                 && !varpool_get_node (base)->const_value_known))
-           return NULL_TREE;
+      ctor = get_base_constructor (t, &idx);
 
-         ctor = DECL_INITIAL (base);
-         break;
-
-       case STRING_CST:
-       case CONSTRUCTOR:
-         ctor = base;
-         break;
+      if (ctor == error_mark_node)
+       return build_zero_cst (TREE_TYPE (t));
 
-       default:
-         return NULL_TREE;
+      if (ctor && !AGGREGATE_TYPE_P (TREE_TYPE (ctor))
+         && !idx)
+       {
+         if (ctor
+             && !useless_type_conversion_p
+                   (TREE_TYPE (t), TREE_TYPE (ctor)))
+           ctor = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (t), ctor);
+         return ctor;
        }
 
+      if (!idx)
+       idx = integer_zero_node;
+
       if (ctor == NULL_TREE
          || (TREE_CODE (ctor) != CONSTRUCTOR
              && TREE_CODE (ctor) != STRING_CST))
        return NULL_TREE;
 
-      /* Get the byte offset.  */
-      idx = TREE_OPERAND (t, 1);
-
       /* Fold read from constant string.  */
       if (TREE_CODE (ctor) == STRING_CST)
        {
index c20d3b6c5cee8b428d4bef597c4212a27fd77d42..fd593e39ebd05cbac11fef6e4b063658c179a4e5 100644 (file)
@@ -1583,6 +1583,18 @@ build_one_cst (tree type)
     }
 }
 
+/* Build 0 constant of type TYPE.  This is used by constructor folding and thus
+   the constant should correspond zero in memory representation.  */
+
+tree
+build_zero_cst (tree type)
+{
+  if (!AGGREGATE_TYPE_P (type))
+    return fold_convert (type, integer_zero_node);
+  return build_constructor (type, NULL);
+}
+
+
 /* Build a BINFO with LEN language slots.  */
 
 tree
index a75a852561c67295a39de8edf7246ebf9ba0c9da..d261c3fffefbfd03a70c24492ddc8a37038ac33e 100644 (file)
@@ -4038,6 +4038,7 @@ extern tree build_constructor_from_list (tree, tree);
 extern tree build_real_from_int_cst (tree, const_tree);
 extern tree build_complex (tree, tree, tree);
 extern tree build_one_cst (tree);
+extern tree build_zero_cst (tree);
 extern tree build_string (int, const char *);
 extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
 #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)