OSDN Git Service

gcc/
authorkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 8 May 2005 21:22:21 +0000 (21:22 +0000)
committerkazu <kazu@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 8 May 2005 21:22:21 +0000 (21:22 +0000)
PR tree-optimization/14841, tree-optimization/15838
* tree-ssa-ccp.c (fold_const_aggregate_ref): New.
(evaluate_stmt): Call it.

testsuite/
PR tree-optimization/14841, tree-optimization/15838
* gcc.dg/tree-ssa/pr14841.c: New.

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

gcc/ChangeLog
gcc/Makefile.in
gcc/testsuite/gcc.dg/tree-ssa/pr14841.c [new file with mode: 0644]
gcc/tree-ssa-ccp.c

index 0da6d51..cc33cab 100644 (file)
@@ -1,3 +1,10 @@
+2005-05-08  Steven Bosscher  <stevenb@suse.de>
+           Kazu Hirata  <kazu@cs.umass.edu>
+
+       PR tree-optimization/14841, tree-optimization/15838
+       * tree-ssa-ccp.c (fold_const_aggregate_ref): New.
+       (evaluate_stmt): Call it.
+
 2005-05-08  Jakub Jelinek  <jakub@redhat.com>
 
        * config/ia64/ia64.c (ia64_override_options): Don't set
index 531c003..de72370 100644 (file)
@@ -2078,7 +2078,7 @@ tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h \
    $(DIAGNOSTIC_H) errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h \
    $(TREE_DUMP_H) $(BASIC_BLOCK_H) tree-pass.h langhooks.h \
-   tree-ssa-propagate.h $(FLAGS_H)
+   tree-ssa-propagate.h $(FLAGS_H) $(TARGET_H)
 tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) errors.h $(TREE_H) $(RTL_H) \
     $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) tree-inline.h \
     $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(TREE_GIMPLE_H) \
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c
new file mode 100644 (file)
index 0000000..4acc6ce
--- /dev/null
@@ -0,0 +1,29 @@
+/* PR tree-optimization/14841
+   Make sure that we can fold a possible nested reference into a
+   constant aggregate.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-store_ccp-details" } */
+
+struct car {
+  int speed;
+  int tire_pressure[4];
+};
+
+const struct car cars[] = {
+  { 75, { 10, 20, 30, 40 } },
+  { 35, { 12, 34, 56, 78 } },
+  { 40, { 19, 28, 37, 46 } }
+};
+
+extern void link_error (void);
+
+void
+foo (void)
+{
+  if (cars[1].tire_pressure[2] != 56)
+    link_error ();
+}
+
+/* { dg-final { scan-tree-dump-times "with if \\(0\\)" 1 "store_ccp"} } */
+/* { dg-final { cleanup-tree-dump "store_ccp" } } */
index 2d16957..58b8c2c 100644 (file)
@@ -209,6 +209,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-pass.h"
 #include "tree-ssa-propagate.h"
 #include "langhooks.h"
+#include "target.h"
 
 
 /* Possible lattice values.  */
@@ -970,6 +971,127 @@ ccp_fold (tree stmt)
 }
 
 
+/* 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.  */
+
+static tree
+fold_const_aggregate_ref (tree t)
+{
+  prop_value_t *value;
+  tree base, ctor, idx, field, elt;
+
+  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 VAR_DECL:
+         if (!TREE_READONLY (base)
+             || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
+             || !targetm.binds_local_p (base))
+           return NULL_TREE;
+
+         ctor = DECL_INITIAL (base);
+         break;
+
+       case ARRAY_REF:
+       case COMPONENT_REF:
+         ctor = fold_const_aggregate_ref (base);
+         break;
+
+       default:
+         return NULL_TREE;
+       }
+
+      if (ctor == NULL_TREE
+         || TREE_CODE (ctor) != CONSTRUCTOR
+         || !TREE_STATIC (ctor))
+       return NULL_TREE;
+
+      /* Get the index.  If we have an SSA_NAME, try to resolve it
+        with the current lattice value for the SSA_NAME.  */
+      idx = TREE_OPERAND (t, 1);
+      switch (TREE_CODE (idx))
+       {
+       case SSA_NAME:
+         if ((value = get_value (idx, true))
+             && value->lattice_val == CONSTANT
+             && TREE_CODE (value->value) == INTEGER_CST)
+           idx = value->value;
+         else
+           return NULL_TREE;
+         break;
+
+       case INTEGER_CST:
+         break;
+
+       default:
+         return NULL_TREE;
+       }
+
+      /* Whoo-hoo!  I'll fold ya baby.  Yeah!  */
+      for (elt = CONSTRUCTOR_ELTS (ctor);
+          (elt && !tree_int_cst_equal (TREE_PURPOSE (elt), idx));
+          elt = TREE_CHAIN (elt))
+       ;
+
+      if (elt)
+       return TREE_VALUE (elt);
+      break;
+
+    case COMPONENT_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 VAR_DECL:
+         if (!TREE_READONLY (base)
+             || TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
+             || !targetm.binds_local_p (base))
+           return NULL_TREE;
+
+         ctor = DECL_INITIAL (base);
+         break;
+
+       case ARRAY_REF:
+       case COMPONENT_REF:
+         ctor = fold_const_aggregate_ref (base);
+         break;
+
+       default:
+         return NULL_TREE;
+       }
+
+      if (ctor == NULL_TREE
+         || TREE_CODE (ctor) != CONSTRUCTOR
+         || !TREE_STATIC (ctor))
+       return NULL_TREE;
+
+      field = TREE_OPERAND (t, 1);
+
+      for (elt = CONSTRUCTOR_ELTS (ctor); elt; elt = TREE_CHAIN (elt))
+       if (TREE_PURPOSE (elt) == field
+           /* FIXME: Handle bit-fields.  */
+           && ! DECL_BIT_FIELD (TREE_PURPOSE (elt)))
+         return TREE_VALUE (elt);
+      break;
+
+    default:
+      break;
+    }
+
+  return NULL_TREE;
+}
+  
 /* Evaluate statement STMT.  */
 
 static prop_value_t
@@ -989,10 +1111,13 @@ evaluate_stmt (tree stmt)
      bother folding the statement.  */
   else if (likelyvalue == VARYING)
     simplified = get_rhs (stmt);
-  /* Otherwise the statement is likely to have an UNDEFINED value and
-     there will be nothing to do.  */
+  /* If the statement is an ARRAY_REF or COMPONENT_REF into constant
+     aggregates, extract the referenced constant.  Otherwise the
+     statement is likely to have an UNDEFINED value, and there will be
+     nothing to do.  Note that fold_const_aggregate_ref returns
+     NULL_TREE if the first case does not match.  */
   else
-    simplified = NULL_TREE;
+    simplified = fold_const_aggregate_ref (get_rhs (stmt));
 
   if (simplified && is_gimple_min_invariant (simplified))
     {