OSDN Git Service

* tree.h (categorize_ctor_elements): Adjust prototype and add
authorhainque <hainque@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 18 Jul 2006 13:07:28 +0000 (13:07 +0000)
committerhainque <hainque@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 18 Jul 2006 13:07:28 +0000 (13:07 +0000)
descriptive comment, both in accordance with the interface change
described below.
* varasm.c (constructor_static_from_elts_p): New function.
Whether a constructor node is a valid static constant initializer
if all its elements are.
(initializer_constant_valid_p) <CONSTRUCTOR value>: Use it.
* output.h: Declare it.
* expr.c (categorize_ctor_elements_1): Return whether the constructor
is a valid constant initializer instead of computing the number of
non-constant elements.  Use constructor_static_from_elts_p for this
purpose.  Replace the head comment with an indication that this is a
helper for categorize_ctor_elements.
(categorize_ctor_elements): Same interface change as for the _1
helper.  Former head comment from this helper moved here, adjusted to
account for the interface changes.
(mostly_zeros_p): Adjust call to categorize_ctor_elements.
(all_zeros_p): Likewise.
* gimplify.c (gimplify_init_constructor): Decide whether we can make
static versions of the constructor from the categorize_ctor_elements
return value instead of the formerly computed number of non-constant
elements.

* gnat.dg/outer_agg_bitfield_constructor.adb: New test.
* gnat.dg/nested_agg_bitfield_constructor.adb: New test.

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

gcc/ChangeLog
gcc/expr.c
gcc/gimplify.c
gcc/output.h
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb [new file with mode: 0644]
gcc/tree.h
gcc/varasm.c

index 5cc02be..558765d 100644 (file)
@@ -1,3 +1,28 @@
+2006-07-18  Olivier Hainque  <hainque@adacore.com>
+
+       * tree.h (categorize_ctor_elements): Adjust prototype and add
+       descriptive comment, both in accordance with the interface change
+       described below.
+       * varasm.c (constructor_static_from_elts_p): New function.
+       Whether a constructor node is a valid static constant initializer
+       if all its elements are.
+       (initializer_constant_valid_p) <CONSTRUCTOR value>: Use it.
+       * output.h: Declare it. 
+       * expr.c (categorize_ctor_elements_1): Return whether the constructor
+       is a valid constant initializer instead of computing the number of
+       non-constant elements.  Use constructor_static_from_elts_p for this
+       purpose.  Replace the head comment with an indication that this is a
+       helper for categorize_ctor_elements.
+       (categorize_ctor_elements): Same interface change as for the _1
+       helper.  Former head comment from this helper moved here, adjusted to
+       account for the interface changes.
+       (mostly_zeros_p): Adjust call to categorize_ctor_elements.
+       (all_zeros_p): Likewise.        
+       * gimplify.c (gimplify_init_constructor): Decide whether we can make
+       static versions of the constructor from the categorize_ctor_elements
+       return value instead of the formerly computed number of non-constant
+       elements.
+
 2006-07-18  Paolo Bonzini  <bonzini@gnu.org>
 
         * configure: Regenerate.
index e46e3e7..48ec0ef 100644 (file)
@@ -4531,28 +4531,24 @@ store_expr (tree exp, rtx target, int call_param_p)
   return NULL_RTX;
 }
 \f
-/* Examine CTOR to discover:
-   * how many scalar fields are set to nonzero values,
-     and place it in *P_NZ_ELTS;
-   * how many scalar fields are set to non-constant values,
-     and place it in  *P_NC_ELTS; and
-   * how many scalar fields in total are in CTOR,
-     and place it in *P_ELT_COUNT.
-   * if a type is a union, and the initializer from the constructor
-     is not the largest element in the union, then set *p_must_clear.  */
+/* Helper for categorize_ctor_elements.  Identical interface.  */
 
-static void
+static bool
 categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
-                           HOST_WIDE_INT *p_nc_elts,
                            HOST_WIDE_INT *p_elt_count,
                            bool *p_must_clear)
 {
   unsigned HOST_WIDE_INT idx;
-  HOST_WIDE_INT nz_elts, nc_elts, elt_count;
+  HOST_WIDE_INT nz_elts, elt_count;
   tree value, purpose;
 
+  /* Whether CTOR is a valid constant initializer, in accordance with what
+     initializer_constant_valid_p does.  If inferred from the constructor
+     elements, true until proven otherwise.  */
+  bool const_from_elts_p = constructor_static_from_elts_p (ctor);
+  bool const_p = const_from_elts_p ? true : TREE_STATIC (ctor);
+
   nz_elts = 0;
-  nc_elts = 0;
   elt_count = 0;
 
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, purpose, value)
@@ -4574,11 +4570,16 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
        {
        case CONSTRUCTOR:
          {
-           HOST_WIDE_INT nz = 0, nc = 0, ic = 0;
-           categorize_ctor_elements_1 (value, &nz, &nc, &ic, p_must_clear);
+           HOST_WIDE_INT nz = 0, ic = 0;
+           
+           bool const_elt_p
+             = categorize_ctor_elements_1 (value, &nz, &ic, p_must_clear);
+
            nz_elts += mult * nz;
-           nc_elts += mult * nc;
-           elt_count += mult * ic;
+           elt_count += mult * ic;
+
+           if (const_from_elts_p && const_p)
+             const_p = const_elt_p;
          }
          break;
 
@@ -4617,8 +4618,10 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
        default:
          nz_elts += mult;
          elt_count += mult;
-         if (!initializer_constant_valid_p (value, TREE_TYPE (value)))
-           nc_elts += mult;
+
+         if (const_from_elts_p && const_p)
+           const_p = initializer_constant_valid_p (value, TREE_TYPE (value))
+                     != NULL_TREE;
          break;
        }
     }
@@ -4660,22 +4663,33 @@ categorize_ctor_elements_1 (tree ctor, HOST_WIDE_INT *p_nz_elts,
     }
 
   *p_nz_elts += nz_elts;
-  *p_nc_elts += nc_elts;
   *p_elt_count += elt_count;
+
+  return const_p;
 }
 
-void
+/* Examine CTOR to discover:
+   * how many scalar fields are set to nonzero values,
+     and place it in *P_NZ_ELTS;
+   * how many scalar fields in total are in CTOR,
+     and place it in *P_ELT_COUNT.
+   * if a type is a union, and the initializer from the constructor
+     is not the largest element in the union, then set *p_must_clear.
+
+   Return whether or not CTOR is a valid static constant initializer, the same
+   as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0".  */
+
+bool
 categorize_ctor_elements (tree ctor, HOST_WIDE_INT *p_nz_elts,
-                         HOST_WIDE_INT *p_nc_elts,
                          HOST_WIDE_INT *p_elt_count,
                          bool *p_must_clear)
 {
   *p_nz_elts = 0;
-  *p_nc_elts = 0;
   *p_elt_count = 0;
   *p_must_clear = false;
-  categorize_ctor_elements_1 (ctor, p_nz_elts, p_nc_elts, p_elt_count,
-                             p_must_clear);
+
+  return
+    categorize_ctor_elements_1 (ctor, p_nz_elts, p_elt_count, p_must_clear);
 }
 
 /* Count the number of scalars in TYPE.  Return -1 on overflow or
@@ -4777,10 +4791,10 @@ mostly_zeros_p (tree exp)
   if (TREE_CODE (exp) == CONSTRUCTOR)
 
     {
-      HOST_WIDE_INT nz_elts, nc_elts, count, elts;
+      HOST_WIDE_INT nz_elts, count, elts;
       bool must_clear;
 
-      categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count, &must_clear);
+      categorize_ctor_elements (exp, &nz_elts, &count, &must_clear);
       if (must_clear)
        return 1;
 
@@ -4800,10 +4814,10 @@ all_zeros_p (tree exp)
   if (TREE_CODE (exp) == CONSTRUCTOR)
 
     {
-      HOST_WIDE_INT nz_elts, nc_elts, count;
+      HOST_WIDE_INT nz_elts, count;
       bool must_clear;
 
-      categorize_ctor_elements (exp, &nz_elts, &nc_elts, &count, &must_clear);
+      categorize_ctor_elements (exp, &nz_elts, &count, &must_clear);
       return nz_elts == 0;
     }
 
index a5e7e66..16e4d3c 100644 (file)
@@ -2940,8 +2940,8 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
       {
        struct gimplify_init_ctor_preeval_data preeval_data;
        HOST_WIDE_INT num_type_elements, num_ctor_elements;
-       HOST_WIDE_INT num_nonzero_elements, num_nonconstant_elements;
-       bool cleared;
+       HOST_WIDE_INT num_nonzero_elements;
+       bool cleared, valid_const_initializer;
 
        /* Aggregate types must lower constructors to initialization of
           individual elements.  The exception is that a CONSTRUCTOR node
@@ -2949,13 +2949,16 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
        if (VEC_empty (constructor_elt, elts))
          break;
 
-       categorize_ctor_elements (ctor, &num_nonzero_elements,
-                                 &num_nonconstant_elements,
-                                 &num_ctor_elements, &cleared);
+       /* Fetch information about the constructor to direct later processing.
+          We might want to make static versions of it in various cases, and
+          can only do so if it known to be a valid constant initializer.  */
+       valid_const_initializer
+         = categorize_ctor_elements (ctor, &num_nonzero_elements,
+                                     &num_ctor_elements, &cleared);
 
        /* If a const aggregate variable is being initialized, then it
           should never be a lose to promote the variable to be static.  */
-       if (num_nonconstant_elements == 0
+       if (valid_const_initializer
            && num_nonzero_elements > 1
            && TREE_READONLY (object)
            && TREE_CODE (object) == VAR_DECL)
@@ -3012,7 +3015,7 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p,
           for sparse arrays, though, as it's more efficient to follow
           the standard CONSTRUCTOR behavior of memset followed by
           individual element initialization.  */
-       if (num_nonconstant_elements == 0 && !cleared)
+       if (valid_const_initializer && !cleared)
          {
            HOST_WIDE_INT size = int_size_in_bytes (type);
            unsigned int align;
index 6d518c4..3cfe32c 100644 (file)
@@ -280,6 +280,13 @@ extern void output_shared_constant_pool (void);
 
 extern void output_object_blocks (void);
 
+/* Whether a constructor CTOR is a valid static constant initializer if all
+   its elements are.  This used to be internal to initializer_constant_valid_p
+   and has been exposed to let other functions like categorize_ctor_elements
+   evaluate the property while walking a constructor for other purposes.  */
+
+extern bool constructor_static_from_elts_p (tree);
+
 /* Return nonzero if VALUE is a valid constant-valued expression
    for use in initializing a static variable; one that can be an
    element of a "constant" initializer.
index 0828f4a..f73f2e6 100644 (file)
@@ -1,3 +1,8 @@
+2006-07-18  Olivier Hainque  <hainque@adacore.com>
+
+       * gnat.dg/outer_agg_bitfield_constructor.adb: New test.
+       * gnat.dg/nested_agg_bitfield_constructor.adb: New test.
+       
 2006-07-18  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c/28286
diff --git a/gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb b/gcc/testsuite/gnat.dg/nested_agg_bitfield_constructor.adb
new file mode 100644 (file)
index 0000000..6015900
--- /dev/null
@@ -0,0 +1,34 @@
+-- { dg-do compile }
+-- { dg-options "-gnatws" }
+--              (bits of "Header" unused)
+
+procedure Nested_Agg_Bitfield_Constructor is
+
+    type Uint64 is mod 2 ** 64;
+    type Uint16 is mod 2 ** 16;
+
+    type Time_Stamp is record
+       Sec  : Uint64;
+       Year : Uint16;
+    end record;
+
+    type Msg_Header is record
+       Stamp : Time_Stamp;
+    end record;
+    for Msg_Header use record
+       Stamp at 0 range 0 .. 64+16-1;
+    end record;
+    for Msg_Header'Size use 80;
+
+    type Msg is record
+       Header : Msg_Header;
+    end record;
+
+    for Msg use record
+       Header at 0 range 0 .. 191;
+    end record;
+
+    M : Msg := (Header => (Stamp => (2, 4)));
+begin
+   null;
+end;
diff --git a/gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb b/gcc/testsuite/gnat.dg/outer_agg_bitfield_constructor.adb
new file mode 100644 (file)
index 0000000..6658042
--- /dev/null
@@ -0,0 +1,44 @@
+-- { dg-do run }
+
+procedure Outer_Agg_Bitfield_Constructor is
+
+    type Mod_64 is mod 2 ** 64;
+    for Mod_64'Size use 64;
+
+    type Uint_16 is range 0 .. 2 ** 16 - 1;
+    for Uint_16'Size use 16;
+
+    type Values_Type is record
+       M64 : Mod_64;
+       U16 : Uint_16;
+    end record;
+
+    for Values_Type use record
+       M64 at 0 range 0 .. 63;
+       U16 at 8 range 0 .. 15;
+    end record;
+
+    type Wrapper_Type is record
+       Values : Values_Type;
+    end record;
+
+    for Wrapper_Type use record
+       Values at 0 range 0 .. 79;
+    end record;
+
+    M : constant := 2;
+    U : constant := 4;
+
+    W : Wrapper_Type := (Values => (M, U));
+
+    procedure Check (O : Wrapper_Type) is
+    begin
+       if O.Values.M64 /= M or else O.Values.U16 /= U then
+          raise Program_Error;
+       end if;
+    end;
+begin
+   Check (W);
+end;
+
+
index 12e2f59..dfea92a 100644 (file)
@@ -3924,8 +3924,20 @@ extern int fields_length (tree);
 
 extern bool initializer_zerop (tree);
 
-extern void categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
-                                     HOST_WIDE_INT *, bool *);
+/* Examine CTOR to discover:
+   * how many scalar fields are set to nonzero values,
+     and place it in *P_NZ_ELTS;
+   * how many scalar fields in total are in CTOR,
+     and place it in *P_ELT_COUNT.
+   * if a type is a union, and the initializer from the constructor
+     is not the largest element in the union, then set *p_must_clear.
+
+   Return whether or not CTOR is a valid static constant initializer, the same
+   as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0".  */
+
+extern bool categorize_ctor_elements (tree, HOST_WIDE_INT *, HOST_WIDE_INT *,
+                                     bool *);
+
 extern HOST_WIDE_INT count_type_elements (tree, bool);
 
 /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0.  */
index 9dcc3b4..1f5f43a 100644 (file)
@@ -3699,6 +3699,20 @@ output_addressed_constants (tree exp)
     }
 }
 \f
+/* Whether a constructor CTOR is a valid static constant initializer if all
+   its elements are.  This used to be internal to initializer_constant_valid_p
+   and has been exposed to let other functions like categorize_ctor_elements
+   evaluate the property while walking a constructor for other purposes.  */
+
+bool
+constructor_static_from_elts_p (tree ctor)
+{
+  return (TREE_CONSTANT (ctor)
+         && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE
+             || TREE_CODE (TREE_TYPE (ctor)) == RECORD_TYPE)
+         && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
+}
+
 /* Return nonzero if VALUE is a valid constant-valued expression
    for use in initializing a static variable; one that can be an
    element of a "constant" initializer.
@@ -3719,10 +3733,7 @@ initializer_constant_valid_p (tree value, tree endtype)
   switch (TREE_CODE (value))
     {
     case CONSTRUCTOR:
-      if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
-          || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
-         && TREE_CONSTANT (value)
-         && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (value)))
+      if (constructor_static_from_elts_p (value))
        {
          unsigned HOST_WIDE_INT idx;
          tree elt;