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]

Symtab cleanup 6/17: fix handling of constructors of aliases


Hi,
this patch makes it possible to fold through aliases.  It may seem unimportant, but we
run into those cases in C++ where extra name aliases may get used by devirtualization
machinery.  The patch also fixes the following long standing bug:
jh@gcc10:~/trunk/build2/gcc$ cat t.c
static int a=4;
static int b __attribute__ ((alias("a")));
main()
{
   return b+a;
}
jh@gcc10:~/trunk/build2/gcc$ gcc -O2 t.c -S
jh@gcc10:~/trunk/build2/gcc$ more t.s
        .file   "t.c"
        .text
        .p2align 4,,15
.globl main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        movl    $4, %eax
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .section        .rodata
        .align 4
        .type   a, @object
        .size   a, 4
a:
        .long   4
        .set    b,a
        .ident  "GCC: (Debian 4.4.5-8) 4.4.5"
        .section        .note.GNU-stack,"",@progbits
jh@gcc10:~/trunk/build2/gcc$ gcc --version
gcc (Debian 4.4.5-8) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

jh@gcc10:~/trunk/build2/gcc$ ./xgcc -B ./ -O2 t.c -S
jh@gcc10:~/trunk/build2/gcc$ more t.s
        .file   "t.c"
        .section        .text.startup,"ax",@progbits
        .p2align 4,,15
        .globl  main
        .type   main, @function
main:
.LFB0:
        .cfi_startproc
        movl    $8, %eax
        ret
        .cfi_endproc
.LFE0:
        .size   main, .-main
        .ident  "GCC: (GNU) 4.9.0 20130616 (experimental)"
        .section        .note.GNU-stack,"",@progbits

The main idea is to replace const_value_known_p predicate by ctor_for_folding
that returns the ctor and is able to look through aliases via the symbol table.
The huge change in expand_expr_real_1 is really just a reformating.

I have bootstrapped/regtested the patch on x86_64-linux and tested with Firefox build.
I am running now PPC64 test and will wait for Richard's renaming patch.

Honza

	* cgraph.h (const_value_known_p): Replace by ...
	(ctor_for_folding): .. this one.
	* cgraphunit.c (process_function_and_variable_attributes): Use it.
	* lto-cgraph.c (compute_ltrans_boundary): Use ctor_for_folding.
	* expr.c (expand_expr_real_1): Likewise.
	(string_constant): Likewise.
	* tree-ssa-loop-ivcanon.c (constant_after_peeling): Likewise.
	* ipa.c (process_references): Likewise.
	(symtab_remove_unreachable_nodes): Likewise.
	* ipa-inline-analysis.c (param_change_prob): Likewise.
	* gimple-fold.c (canonicalize_constructor_val): Likewise.
	(get_base_constructor): Likwise.
	* varpool.c (varpool_remove_node): Likewise.
	(varpool_remove_initializer): LIkewise.
	(dump_varpool_node): LIkwise.
	(const_value_known_p): Rewrite to ...
	(ctor_for_folding): ... this one.

	* lto-partition.c (add_references_to_partition): Use
	ctor_for_folding.

	* gcc.dg/tree-ssa/attr-alias-2.c: New testcase.
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 200147)
--- cgraph.h	(working copy)
*************** void varpool_analyze_node (struct varpoo
*** 797,803 ****
  struct varpool_node * varpool_extra_name_alias (tree, tree);
  struct varpool_node * varpool_create_variable_alias (tree, tree);
  void varpool_reset_queue (void);
! bool const_value_known_p (tree);
  bool varpool_for_node_and_aliases (struct varpool_node *,
  		                   bool (*) (struct varpool_node *, void *),
  			           void *, bool);
--- 797,803 ----
  struct varpool_node * varpool_extra_name_alias (tree, tree);
  struct varpool_node * varpool_create_variable_alias (tree, tree);
  void varpool_reset_queue (void);
! tree ctor_for_folding (tree);
  bool varpool_for_node_and_aliases (struct varpool_node *,
  		                   bool (*) (struct varpool_node *, void *),
  			           void *, bool);
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 200147)
--- cgraphunit.c	(working copy)
*************** process_function_and_variable_attributes
*** 761,768 ****
      {
        tree decl = vnode->symbol.decl;
        if (DECL_EXTERNAL (decl)
! 	  && DECL_INITIAL (decl)
! 	  && const_value_known_p (decl))
  	varpool_finalize_decl (decl);
        if (DECL_PRESERVE_P (decl))
  	vnode->symbol.force_output = true;
--- 761,767 ----
      {
        tree decl = vnode->symbol.decl;
        if (DECL_EXTERNAL (decl)
! 	  && DECL_INITIAL (decl))
  	varpool_finalize_decl (decl);
        if (DECL_PRESERVE_P (decl))
  	vnode->symbol.force_output = true;
Index: testsuite/gcc.dg/tree-ssa/attr-alias-2.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/attr-alias-2.c	(revision 0)
--- testsuite/gcc.dg/tree-ssa/attr-alias-2.c	(revision 0)
***************
*** 0 ****
--- 1,10 ----
+ /* { dg-do compile } */
+ /* { dg-require-alias "" } */
+ /* { dg-options "-O2 -fdump-tree-optimized" } */
+ static int a=4;
+ static int b __attribute__ ((alias("a")));
+ main()
+ {
+    return b+a;
+ }
+ /* { dg-final { scan-tree-dump "return 8" "optimized" } } */
Index: lto-cgraph.c
===================================================================
*** lto-cgraph.c	(revision 200147)
--- lto-cgraph.c	(working copy)
*************** compute_ltrans_boundary (lto_symtab_enco
*** 766,775 ****
        symtab_node node = lto_symtab_encoder_deref (encoder, i);
        if (varpool_node *vnode = dyn_cast <varpool_node> (node))
  	{
! 	  if (DECL_INITIAL (vnode->symbol.decl)
! 	      && !lto_symtab_encoder_encode_initializer_p (encoder,
! 							   vnode)
! 	      && const_value_known_p (vnode->symbol.decl))
  	    {
  	      lto_set_symtab_encoder_encode_initializer (encoder, vnode);
  	      add_references (encoder, &vnode->symbol.ref_list);
--- 766,774 ----
        symtab_node node = lto_symtab_encoder_deref (encoder, i);
        if (varpool_node *vnode = dyn_cast <varpool_node> (node))
  	{
! 	  if (!lto_symtab_encoder_encode_initializer_p (encoder,
! 							vnode)
! 	      && ctor_for_folding (vnode->symbol.decl) != error_mark_node)
  	    {
  	      lto_set_symtab_encoder_encode_initializer (encoder, vnode);
  	      add_references (encoder, &vnode->symbol.ref_list);
Index: expr.c
===================================================================
*** expr.c	(revision 200147)
--- expr.c	(working copy)
*************** expand_expr_real_1 (tree exp, rtx target
*** 9698,9703 ****
--- 9698,9704 ----
        {
  	tree array = treeop0;
  	tree index = treeop1;
+         tree init;
  
  	/* Fold an expression like: "foo"[2].
  	   This is not done in fold so it won't happen inside &.
*************** expand_expr_real_1 (tree exp, rtx target
*** 9744,9819 ****
  		 && modifier != EXPAND_INITIALIZER
  		 && modifier != EXPAND_MEMORY
  		 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
! 		 && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
! 		 && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK
! 		 && const_value_known_p (array))
  	  {
! 	    if (TREE_CODE (index) == INTEGER_CST)
  	      {
! 		tree init = DECL_INITIAL (array);
  
! 		if (TREE_CODE (init) == CONSTRUCTOR)
! 		  {
! 		    unsigned HOST_WIDE_INT ix;
! 		    tree field, value;
  
! 		    FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix,
! 					      field, value)
! 		      if (tree_int_cst_equal (field, index))
  			{
! 			  if (TREE_SIDE_EFFECTS (value))
  			    break;
  
! 			  if (TREE_CODE (value) == CONSTRUCTOR)
! 			    {
! 			      /* If VALUE is a CONSTRUCTOR, this
! 				 optimization is only useful if
! 				 this doesn't store the CONSTRUCTOR
! 				 into memory.  If it does, it is more
! 				 efficient to just load the data from
! 				 the array directly.  */
! 			      rtx ret = expand_constructor (value, target,
! 							    modifier, true);
! 			      if (ret == NULL_RTX)
! 				break;
! 			    }
  
! 			  return expand_expr (fold (value), target, tmode,
! 					      modifier);
! 			}
! 		  }
! 		else if(TREE_CODE (init) == STRING_CST)
  		  {
! 		    tree index1 = index;
! 		    tree low_bound = array_ref_low_bound (exp);
! 		    index1 = fold_convert_loc (loc, sizetype,
! 					       treeop1);
! 
! 		    /* Optimize the special-case of a zero lower bound.
! 
! 		       We convert the low_bound to sizetype to avoid some problems
! 		       with constant folding.  (E.g. suppose the lower bound is 1,
! 		       and its mode is QI.  Without the conversion,l (ARRAY
! 		       +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
! 		       +INDEX), which becomes (ARRAY+255+INDEX).  Opps!)  */
! 
! 		    if (! integer_zerop (low_bound))
! 		      index1 = size_diffop_loc (loc, index1,
! 					    fold_convert_loc (loc, sizetype,
! 							      low_bound));
! 
! 		    if (0 > compare_tree_int (index1,
! 					      TREE_STRING_LENGTH (init)))
! 		      {
! 			tree type = TREE_TYPE (TREE_TYPE (init));
! 			enum machine_mode mode = TYPE_MODE (type);
  
! 			if (GET_MODE_CLASS (mode) == MODE_INT
! 			    && GET_MODE_SIZE (mode) == 1)
! 			  return gen_int_mode (TREE_STRING_POINTER (init)
! 					       [TREE_INT_CST_LOW (index1)],
! 					       mode);
! 		      }
  		  }
  	      }
  	  }
--- 9745,9816 ----
  		 && modifier != EXPAND_INITIALIZER
  		 && modifier != EXPAND_MEMORY
  		 && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
! 		 && TREE_CODE (index) == INTEGER_CST
! 		 && (TREE_CODE (array) == VAR_DECL
! 		     || TREE_CODE (array) == CONST_DECL)
! 		 && (init = ctor_for_folding (array)) != error_mark_node)
  	  {
! 	    if (TREE_CODE (init) == CONSTRUCTOR)
  	      {
! 		unsigned HOST_WIDE_INT ix;
! 		tree field, value;
  
! 		FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix,
! 					  field, value)
! 		  if (tree_int_cst_equal (field, index))
! 		    {
! 		      if (TREE_SIDE_EFFECTS (value))
! 			break;
  
! 		      if (TREE_CODE (value) == CONSTRUCTOR)
  			{
! 			  /* If VALUE is a CONSTRUCTOR, this
! 			     optimization is only useful if
! 			     this doesn't store the CONSTRUCTOR
! 			     into memory.  If it does, it is more
! 			     efficient to just load the data from
! 			     the array directly.  */
! 			  rtx ret = expand_constructor (value, target,
! 							modifier, true);
! 			  if (ret == NULL_RTX)
  			    break;
+ 			}
  
! 		      return expand_expr (fold (value), target, tmode,
! 					  modifier);
! 		    }
! 	      }
! 	    else if(TREE_CODE (init) == STRING_CST)
! 	      {
! 		tree index1 = index;
! 		tree low_bound = array_ref_low_bound (exp);
! 		index1 = fold_convert_loc (loc, sizetype,
! 					   treeop1);
! 
! 		/* Optimize the special-case of a zero lower bound.
! 
! 		   We convert the low_bound to sizetype to avoid some problems
! 		   with constant folding.  (E.g. suppose the lower bound is 1,
! 		   and its mode is QI.  Without the conversion,l (ARRAY
! 		   +(INDEX-(unsigned char)1)) becomes ((ARRAY+(-(unsigned char)1))
! 		   +INDEX), which becomes (ARRAY+255+INDEX).  Opps!)  */
! 
! 		if (! integer_zerop (low_bound))
! 		  index1 = size_diffop_loc (loc, index1,
! 					fold_convert_loc (loc, sizetype,
! 							  low_bound));
  
! 		if (0 > compare_tree_int (index1,
! 					  TREE_STRING_LENGTH (init)))
  		  {
! 		    tree type = TREE_TYPE (TREE_TYPE (init));
! 		    enum machine_mode mode = TYPE_MODE (type);
  
! 		    if (GET_MODE_CLASS (mode) == MODE_INT
! 			&& GET_MODE_SIZE (mode) == 1)
! 		      return gen_int_mode (TREE_STRING_POINTER (init)
! 					   [TREE_INT_CST_LOW (index1)],
! 					   mode);
  		  }
  	      }
  	  }
*************** string_constant (tree arg, tree *ptr_off
*** 10676,10692 ****
  	   || TREE_CODE (array) == CONST_DECL)
      {
        int length;
  
        /* Variables initialized to string literals can be handled too.  */
!       if (!const_value_known_p (array)
! 	  || !DECL_INITIAL (array)
! 	  || TREE_CODE (DECL_INITIAL (array)) != STRING_CST)
  	return 0;
  
        /* Avoid const char foo[4] = "abcde";  */
        if (DECL_SIZE_UNIT (array) == NULL_TREE
  	  || TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
! 	  || (length = TREE_STRING_LENGTH (DECL_INITIAL (array))) <= 0
  	  || compare_tree_int (DECL_SIZE_UNIT (array), length) < 0)
  	return 0;
  
--- 10673,10690 ----
  	   || TREE_CODE (array) == CONST_DECL)
      {
        int length;
+       tree init = ctor_for_folding (array);
  
        /* Variables initialized to string literals can be handled too.  */
!       if (init == error_mark_node
! 	  || !init
! 	  || TREE_CODE (init) != STRING_CST)
  	return 0;
  
        /* Avoid const char foo[4] = "abcde";  */
        if (DECL_SIZE_UNIT (array) == NULL_TREE
  	  || TREE_CODE (DECL_SIZE_UNIT (array)) != INTEGER_CST
! 	  || (length = TREE_STRING_LENGTH (init)) <= 0
  	  || compare_tree_int (DECL_SIZE_UNIT (array), length) < 0)
  	return 0;
  
*************** string_constant (tree arg, tree *ptr_off
*** 10699,10705 ****
  	return 0;
  
        *ptr_offset = offset;
!       return DECL_INITIAL (array);
      }
  
    return 0;
--- 10697,10703 ----
  	return 0;
  
        *ptr_offset = offset;
!       return init;
      }
  
    return 0;
Index: tree-ssa-loop-ivcanon.c
===================================================================
*** tree-ssa-loop-ivcanon.c	(revision 200147)
--- tree-ssa-loop-ivcanon.c	(working copy)
*************** constant_after_peeling (tree op, gimple
*** 174,180 ****
        while (handled_component_p (base))
  	base = TREE_OPERAND (base, 0);
        if ((DECL_P (base)
! 	   && const_value_known_p (base))
  	  || CONSTANT_CLASS_P (base))
  	{
  	  /* If so, see if we understand all the indices.  */
--- 174,180 ----
        while (handled_component_p (base))
  	base = TREE_OPERAND (base, 0);
        if ((DECL_P (base)
! 	   && ctor_for_folding (base) != error_mark_node)
  	  || CONSTANT_CLASS_P (base))
  	{
  	  /* If so, see if we understand all the indices.  */
Index: ipa.c
===================================================================
*** ipa.c	(revision 200147)
--- ipa.c	(working copy)
*************** process_references (struct ipa_ref_list
*** 145,151 ****
  		     constant folding.  Keep references alive so partitioning
  		     knows about potential references.  */
  		  || (TREE_CODE (node->symbol.decl) == VAR_DECL
! 		      && flag_wpa && const_value_known_p (node->symbol.decl)))))
  	pointer_set_insert (reachable, node);
        enqueue_node ((symtab_node) node, first, reachable);
      }
--- 145,153 ----
  		     constant folding.  Keep references alive so partitioning
  		     knows about potential references.  */
  		  || (TREE_CODE (node->symbol.decl) == VAR_DECL
! 		      && flag_wpa
! 		      && ctor_for_folding (node->symbol.decl)
! 		         != error_mark_node))))
  	pointer_set_insert (reachable, node);
        enqueue_node ((symtab_node) node, first, reachable);
      }
*************** symtab_remove_unreachable_nodes (bool be
*** 400,405 ****
--- 402,408 ----
  	}
        else if (!pointer_set_contains (reachable, vnode))
          {
+ 	  tree init;
  	  if (vnode->symbol.definition)
  	    {
  	      if (file)
*************** symtab_remove_unreachable_nodes (bool be
*** 411,418 ****
  	  vnode->symbol.aux = NULL;
  
  	  /* Keep body if it may be useful for constant folding.  */
! 	  if (!const_value_known_p (vnode->symbol.decl))
  	    varpool_remove_initializer (vnode);
  	  ipa_remove_all_references (&vnode->symbol.ref_list);
  	}
        else
--- 414,423 ----
  	  vnode->symbol.aux = NULL;
  
  	  /* Keep body if it may be useful for constant folding.  */
! 	  if ((init = ctor_for_folding (vnode->symbol.decl)) == error_mark_node)
  	    varpool_remove_initializer (vnode);
+ 	  else
+ 	    DECL_INITIAL (vnode->symbol.decl) = init;
  	  ipa_remove_all_references (&vnode->symbol.ref_list);
  	}
        else
Index: ipa-inline-analysis.c
===================================================================
*** ipa-inline-analysis.c	(revision 200147)
--- ipa-inline-analysis.c	(working copy)
*************** param_change_prob (gimple stmt, int i)
*** 2106,2113 ****
        struct record_modified_bb_info info;
        bitmap_iterator bi;
        unsigned index;
  
!       if (const_value_known_p (base))
  	return 0;
        if (!bb->frequency)
  	return REG_BR_PROB_BASE;
--- 2106,2114 ----
        struct record_modified_bb_info info;
        bitmap_iterator bi;
        unsigned index;
+       tree init = ctor_for_folding (base);
  
!       if (init != error_mark_node)
  	return 0;
        if (!bb->frequency)
  	return REG_BR_PROB_BASE;
Index: gimple-fold.c
===================================================================
*** gimple-fold.c	(revision 200147)
--- gimple-fold.c	(working copy)
*************** canonicalize_constructor_val (tree cval,
*** 192,200 ****
  tree
  get_symbol_constant_value (tree sym)
  {
!   if (const_value_known_p (sym))
      {
-       tree val = DECL_INITIAL (sym);
        if (val)
  	{
  	  val = canonicalize_constructor_val (unshare_expr (val), sym);
--- 192,200 ----
  tree
  get_symbol_constant_value (tree sym)
  {
!   tree val = ctor_for_folding (sym);
!   if (val != error_mark_node)
      {
        if (val)
  	{
  	  val = canonicalize_constructor_val (unshare_expr (val), sym);
*************** get_base_constructor (tree base, HOST_WI
*** 2695,2713 ****
    switch (TREE_CODE (base))
      {
      case VAR_DECL:
-       if (!const_value_known_p (base))
- 	return NULL_TREE;
- 
-       /* Fallthru.  */
      case CONST_DECL:
!       if (!DECL_INITIAL (base)
! 	  && (TREE_STATIC (base) || DECL_EXTERNAL (base)))
!         return error_mark_node;
!       /* Do not return an error_mark_node DECL_INITIAL.  LTO uses this
!          as special marker (_not_ zero ...) for its own purposes.  */
!       if (DECL_INITIAL (base) == error_mark_node)
! 	return NULL_TREE;
!       return DECL_INITIAL (base);
  
      case ARRAY_REF:
      case COMPONENT_REF:
--- 2695,2712 ----
    switch (TREE_CODE (base))
      {
      case VAR_DECL:
      case CONST_DECL:
!       {
! 	tree init = ctor_for_folding (base);
! 
! 	/* Our semantic is exact oposite of ctor_for_folding;
! 	   NULL means unknown, while error_mark_node is 0.  */
! 	if (init == error_mark_node)
! 	  return NULL_TREE;
! 	if (!init)
! 	  return error_mark_node;
! 	return init;
!       }
  
      case ARRAY_REF:
      case COMPONENT_REF:
Index: lto/lto-partition.c
===================================================================
*** lto/lto-partition.c	(revision 200147)
--- lto/lto-partition.c	(working copy)
*************** add_references_to_partition (ltrans_part
*** 146,152 ****
         Recursively look into the initializers of the constant variable and add
         references, too.  */
      else if (is_a <varpool_node> (ref->referred)
! 	     && const_value_known_p (ref->referred->symbol.decl)
  	     && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
        {
  	if (!part->initializers_visited)
--- 146,152 ----
         Recursively look into the initializers of the constant variable and add
         references, too.  */
      else if (is_a <varpool_node> (ref->referred)
! 	     && ctor_for_folding (ref->referred->symbol.decl) != error_mark_node
  	     && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred))
        {
  	if (!part->initializers_visited)
Index: varpool.c
===================================================================
*** varpool.c	(revision 200147)
--- varpool.c	(working copy)
*************** void
*** 66,77 ****
  varpool_remove_node (struct varpool_node *node)
  {
    symtab_unregister_node ((symtab_node)node);
  
    /* Because we remove references from external functions before final compilation,
       we may end up removing useful constructors.
       FIXME: We probably want to trace boundaries better.  */
!   if (!const_value_known_p (node->symbol.decl))
      varpool_remove_initializer (node);
    ggc_free (node);
  }
  
--- 66,80 ----
  varpool_remove_node (struct varpool_node *node)
  {
    symtab_unregister_node ((symtab_node)node);
+   tree init;
  
    /* Because we remove references from external functions before final compilation,
       we may end up removing useful constructors.
       FIXME: We probably want to trace boundaries better.  */
!   if ((init = ctor_for_folding (node->symbol.decl)) == error_mark_node)
      varpool_remove_initializer (node);
+   else
+     DECL_INITIAL (node->symbol.decl) = init;
    ggc_free (node);
  }
  
*************** varpool_remove_initializer (struct varpo
*** 84,90 ****
        /* Keep vtables for BINFO folding.  */
        && !DECL_VIRTUAL_P (node->symbol.decl)
        /* FIXME: http://gcc.gnu.org/PR55395 */
!       && debug_info_level == DINFO_LEVEL_NONE)
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
  }
  
--- 87,96 ----
        /* Keep vtables for BINFO folding.  */
        && !DECL_VIRTUAL_P (node->symbol.decl)
        /* FIXME: http://gcc.gnu.org/PR55395 */
!       && debug_info_level == DINFO_LEVEL_NONE
!       /* During LTO streaming we may have multiple nodes
! 	 associated to a given decl.  */
!       && cgraph_state != CGRAPH_LTO_STREAMING)
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
  }
  
*************** dump_varpool_node (FILE *f, struct varpo
*** 104,110 ****
      fprintf (f, " output");
    if (TREE_READONLY (node->symbol.decl))
      fprintf (f, " read-only");
!   if (const_value_known_p (node->symbol.decl))
      fprintf (f, " const-value-known");
    fprintf (f, "\n");
  }
--- 110,116 ----
      fprintf (f, " output");
    if (TREE_READONLY (node->symbol.decl))
      fprintf (f, " read-only");
!   if (ctor_for_folding (node->symbol.decl) != error_mark_node)
      fprintf (f, " const-value-known");
    fprintf (f, "\n");
  }
*************** varpool_node_for_asm (tree asmname)
*** 139,182 ****
  }
  
  /* Return if DECL is constant and its initial value is known (so we can do
!    constant folding using DECL_INITIAL (decl)).  */
  
! bool
! const_value_known_p (tree decl)
  {
    if (TREE_CODE (decl) != VAR_DECL
!       &&TREE_CODE (decl) != CONST_DECL)
!     return false;
  
    if (TREE_CODE (decl) == CONST_DECL
        || DECL_IN_CONSTANT_POOL (decl))
!     return true;
! 
!   gcc_assert (TREE_CODE (decl) == VAR_DECL);
  
!   if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl))
!     return false;
  
!   /* Gimplifier takes away constructors of local vars  */
    if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
!     return DECL_INITIAL (decl) != NULL;
  
!   gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
  
    /* Variables declared 'const' without an initializer
       have zero as the initializer if they may not be
       overridden at link or run time.  */
!   if (!DECL_INITIAL (decl)
!       && (DECL_EXTERNAL (decl)
! 	  || decl_replaceable_p (decl)))
!     return false;
  
    /* Variables declared `const' with an initializer are considered
       to not be overwritable with different initializer by default. 
  
       ??? Previously we behaved so for scalar variables but not for array
       accesses.  */
!   return true;
  }
  
  /* Add the variable DECL to the varpool.
--- 145,237 ----
  }
  
  /* Return if DECL is constant and its initial value is known (so we can do
!    constant folding using DECL_INITIAL (decl)).
!    Return ERROR_MARK_NODE when value is unknown.  */
  
! tree
! ctor_for_folding (tree decl)
  {
+   struct varpool_node *node, *real_node;
+   tree real_decl;
+ 
    if (TREE_CODE (decl) != VAR_DECL
!       && TREE_CODE (decl) != CONST_DECL)
!     return error_mark_node;
  
    if (TREE_CODE (decl) == CONST_DECL
        || DECL_IN_CONSTANT_POOL (decl))
!     return DECL_INITIAL (decl);
  
!   if (TREE_THIS_VOLATILE (decl))
!     return error_mark_node;
  
!   /* Do not care about automatic variables.  Those are never initialized
!      anyway, because gimplifier exapnds the code*/
    if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
!     {
!       gcc_assert (!TREE_PUBLIC (decl));
!       return error_mark_node;
!     }
! 
!   gcc_assert (TREE_CODE (decl) == VAR_DECL);
! 
!   node = varpool_get_node (decl);
!   if (node)
!     {
!       real_node = varpool_variable_node (node);
!       real_decl = real_node->symbol.decl;
!     }
!   else
!     real_decl = decl;
  
!   /* See if we are dealing with alias.
!      In most cases alias is just alternative symbol pointing to a given
!      constructor.  This allows us to use interposition rules of DECL
!      constructor of REAL_NODE.  However weakrefs are special by being just
!      alternative name of their target (if defined).  */
!   if (decl != real_decl)
!     {
!       gcc_assert (!DECL_INITIAL (decl)
! 		  || DECL_INITIAL (decl) == error_mark_node);
!       if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
! 	{
! 	  node = varpool_alias_target (node);
! 	  decl = node->symbol.decl;
! 	}
!     }
! 
!   /* Vtables are defined by their types and must match no matter of interposition
!      rules.  */
!   if (DECL_VIRTUAL_P (real_decl))
!     {
!       gcc_checking_assert (TREE_READONLY (real_decl));
!       return DECL_INITIAL (real_decl);
!     }
! 
!   /* If thre is no constructor, we have nothing to do.  */
!   if (DECL_INITIAL (real_decl) == error_mark_node)
!     return error_mark_node;
! 
!   /* Non-readonly alias of readonly variable is also de-facto readonly,
!      because the variable itself is in readonly section.  
!      We also honnor READONLY flag on alias assuming that user knows
!      what he is doing.  */
!   if (!TREE_READONLY (decl) && !TREE_READONLY (real_decl))
!     return error_mark_node;
  
    /* Variables declared 'const' without an initializer
       have zero as the initializer if they may not be
       overridden at link or run time.  */
!   if (!DECL_INITIAL (real_decl)
!       && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl)))
!     return error_mark_node;
  
    /* Variables declared `const' with an initializer are considered
       to not be overwritable with different initializer by default. 
  
       ??? Previously we behaved so for scalar variables but not for array
       accesses.  */
!   return DECL_INITIAL (real_decl);
  }
  
  /* Add the variable DECL to the varpool.


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