This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ RFC] Re: PR 10776


On Sat, Jan 10, 2004 at 07:12:29PM +0100, Jan Hubicka wrote:
> the testcase in PR 10776 contains insanely large initializer that
> results in insanely large basic blocks containing many memory locations
> and CSElib just explodes in invalidating memory location after each
> store.

While your two patches are still moderately interesting from the point
of view of sanely handling extremely large basic blocks, it sort of 
misses the point that we're doing something insanely stupid here with
the initialization of this object.

The following patch splits the initialization into compile-time and
run-time pieces.  For this test, all but one store can be done at
compile-time.

Testing is still underway.  C++ folk, did I miss anything?


r~


	* typeck2.c (split_nonconstant_init_1, split_nonconstant_init): New.
	(store_init_value): Use it.
	* decl.c (check_initializer): Expect full initialization code
	from store_init_value.
	* init.c (expand_aggr_init_1): Likewise.
	* decl2.c (maybe_emit_vtables): Abort if runtime init needed.

Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1171
diff -c -p -d -r1.1171 decl.c
*** decl.c	10 Jan 2004 01:18:08 -0000	1.1171
--- decl.c	11 Jan 2004 09:24:48 -0000
*************** static tree
*** 4395,4400 ****
--- 4395,4401 ----
  check_initializer (tree decl, tree init, int flags, tree *cleanup)
  {
    tree type = TREE_TYPE (decl);
+   tree init_code = NULL;
  
    /* If `start_decl' didn't like having an initialization, ignore it now.  */
    if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
*************** check_initializer (tree decl, tree init,
*** 4511,4517 ****
  	{
  	dont_use_constructor:
  	  if (TREE_CODE (init) != TREE_VEC)
! 	    init = store_init_value (decl, init);
  	}
      }
    else if (DECL_EXTERNAL (decl))
--- 4512,4521 ----
  	{
  	dont_use_constructor:
  	  if (TREE_CODE (init) != TREE_VEC)
! 	    {
! 	      init_code = store_init_value (decl, init);
! 	      init = NULL;
! 	    }
  	}
      }
    else if (DECL_EXTERNAL (decl))
*************** check_initializer (tree decl, tree init,
*** 4534,4542 ****
      check_for_uninitialized_const_var (decl);
  
    if (init && init != error_mark_node)
!     init = build (INIT_EXPR, type, decl, init);
  
!   return init;
  }
  
  /* If DECL is not a local variable, give it RTL.  */
--- 4538,4546 ----
      check_for_uninitialized_const_var (decl);
  
    if (init && init != error_mark_node)
!     init_code = build (INIT_EXPR, type, decl, init);
  
!   return init_code;
  }
  
  /* If DECL is not a local variable, give it RTL.  */
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.693
diff -c -p -d -r1.693 decl2.c
*** decl2.c	23 Dec 2003 16:53:50 -0000	1.693
--- decl2.c	11 Jan 2004 09:24:48 -0000
*************** maybe_emit_vtables (tree ctype)
*** 1605,1611 ****
  	cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl));
  
        if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
! 	store_init_value (vtbl, DECL_INITIAL (vtbl));
  
        if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
  	{
--- 1605,1615 ----
  	cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl));
  
        if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
! 	{
! 	  /* It had better be all done at compile-time.  */
! 	  if (store_init_value (vtbl, DECL_INITIAL (vtbl)))
! 	    abort ();
! 	}
  
        if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
  	{
Index: init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.354
diff -c -p -d -r1.354 init.c
*** init.c	22 Dec 2003 06:06:56 -0000	1.354
--- init.c	11 Jan 2004 09:24:49 -0000
*************** expand_aggr_init_1 (tree binfo, tree tru
*** 1272,1279 ****
        /* If store_init_value returns NULL_TREE, the INIT has been
  	 record in the DECL_INITIAL for EXP.  That means there's
  	 nothing more we have to do.  */
!       if (store_init_value (exp, init))
! 	finish_expr_stmt (build (INIT_EXPR, type, exp, init));
        return;
      }
  
--- 1272,1280 ----
        /* If store_init_value returns NULL_TREE, the INIT has been
  	 record in the DECL_INITIAL for EXP.  That means there's
  	 nothing more we have to do.  */
!       init = store_init_value (exp, init);
!       if (init)
! 	finish_expr_stmt (init);
        return;
      }
  
Index: typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.152
diff -c -p -d -r1.152 typeck2.c
*** typeck2.c	21 Dec 2003 21:07:32 -0000	1.152
--- typeck2.c	11 Jan 2004 09:24:49 -0000
*************** cxx_incomplete_type_error (tree value, t
*** 284,289 ****
--- 284,378 ----
  }
  
  
+ /* A subroutine of store_init_value.  Splits non-constant static 
+    initializers into a constant part and then generates code to
+    perform the non-constant part of the initialization.  Returns
+    the code for the runtime init.  */
+ 
+ static tree *
+ split_nonconstant_init_1 (tree dest, tree init, tree *pcode)
+ {
+   tree *pelt, elt, type = TREE_TYPE (dest);
+   tree sub, code, inner_type = NULL;
+   bool array_type_p = false;
+ 
+   pelt = &CONSTRUCTOR_ELTS (init);
+   switch (TREE_CODE (type))
+     {
+     case ARRAY_TYPE:
+       inner_type = TREE_TYPE (type);
+       array_type_p = true;
+       /* FALLTHRU */
+ 
+     case RECORD_TYPE:
+     case UNION_TYPE:
+     case QUAL_UNION_TYPE:
+       while ((elt = *pelt))
+ 	{
+ 	  tree field_index = TREE_PURPOSE (elt);
+ 	  tree value = TREE_VALUE (elt);
+ 
+ 	  if (!array_type_p)
+ 	    inner_type = TREE_TYPE (field_index);
+ 
+ 	  if (TREE_CODE (value) == CONSTRUCTOR)
+ 	    {
+ 	      if (array_type_p)
+ 	        sub = build (ARRAY_REF, inner_type, dest, field_index);
+ 	      else
+ 	        sub = build (COMPONENT_REF, inner_type, dest, field_index);
+ 
+ 	      pcode = split_nonconstant_init_1 (sub, value, pcode);
+ 	    }
+ 	  else if (!initializer_constant_valid_p (value, inner_type))
+ 	    {
+ 	      *pelt = TREE_CHAIN (elt);
+ 
+ 	      if (array_type_p)
+ 	        sub = build (ARRAY_REF, inner_type, dest, field_index);
+ 	      else
+ 	        sub = build (COMPONENT_REF, inner_type, dest, field_index);
+ 
+ 	      code = build (MODIFY_EXPR, inner_type, sub, value);
+ 	      code = build_stmt (EXPR_STMT, code);
+ 
+ 	      *pcode = code;
+ 	      pcode = &TREE_CHAIN (code);
+ 	      continue;
+ 	    }
+ 	  pelt = &TREE_CHAIN (elt);
+ 	}
+       break;
+ 
+     case VECTOR_TYPE:
+       if (!initializer_constant_valid_p (init, type))
+ 	{
+ 	  CONSTRUCTOR_ELTS (init) = NULL;
+ 	  code = build (MODIFY_EXPR, type, dest, init);
+ 	  code = build_stmt (EXPR_STMT, code);
+ 	  pcode = &TREE_CHAIN (code);
+ 	}
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
+   return pcode;
+ }
+ 
+ static tree
+ split_nonconstant_init (tree dest, tree init)
+ {
+   tree code = build_stmt (COMPOUND_STMT, NULL_TREE);
+   split_nonconstant_init_1 (dest, init, &COMPOUND_BODY (code));
+ 
+   code = build1 (STMT_EXPR, void_type_node, code);
+   TREE_SIDE_EFFECTS (code) = 1;
+ 
+   return code;
+ }
+ 
  /* Perform appropriate conversions on the initial value of a variable,
     store it in the declaration DECL,
     and print any error messages that are appropriate.
*************** cxx_incomplete_type_error (tree value, t
*** 299,307 ****
     into a CONSTRUCTOR and use standard initialization techniques.
     Perhaps a warning should be generated?
  
!    Returns value of initializer if initialization could not be
!    performed for static variable.  In that case, caller must do
!    the storing.  */
  
  tree
  store_init_value (tree decl, tree init)
--- 388,395 ----
     into a CONSTRUCTOR and use standard initialization techniques.
     Perhaps a warning should be generated?
  
!    Returns code to be executed if initialization could not be performed
!    for static variable.  In that case, caller must emit the code.  */
  
  tree
  store_init_value (tree decl, tree init)
*************** store_init_value (tree decl, tree init)
*** 356,366 ****
       constructing never make it into DECL_INITIAL, and passes 'init' to
       build_aggr_init without checking DECL_INITIAL.  So just return.  */
    else if (TYPE_NEEDS_CONSTRUCTING (type))
!     return value;
    else if (TREE_STATIC (decl)
  	   && (! TREE_CONSTANT (value)
  	       || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
!     return value;
    
    /* Store the VALUE in DECL_INITIAL.  If we're building a
       statement-tree we will actually expand the initialization later
--- 444,459 ----
       constructing never make it into DECL_INITIAL, and passes 'init' to
       build_aggr_init without checking DECL_INITIAL.  So just return.  */
    else if (TYPE_NEEDS_CONSTRUCTING (type))
!     return build (INIT_EXPR, type, decl, value);
    else if (TREE_STATIC (decl)
  	   && (! TREE_CONSTANT (value)
  	       || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
!     {
!       /* VALUE will be modified in place by split_nonconstant_init to
! 	 contain only the constant elements.  */
!       DECL_INITIAL (decl) = value;
!       return split_nonconstant_init (decl, value);
!     }
    
    /* Store the VALUE in DECL_INITIAL.  If we're building a
       statement-tree we will actually expand the initialization later


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]