diff mbox

Another missed DECL_INITIAL folding

Message ID 20100903235742.GS1664@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Sept. 3, 2010, 11:57 p.m. UTC
Hi,
the following testcases shows problem with fold_const_aggregate_ref
producing non-gimple &global_trees[TI_VOID_TYPE] (taken from DECL_INITIAL)
and later failing it to use it as known constant. We eventually get the constant
value at cfgexpand time only.

I am not sure what is the proper way to fold this, so I ended up with using
maybe_fold_offset_to_address.  With removal of some code redundancy it is hopefully
not too bad.

Bootstrapped/regtested x86_64-linux, OK?
Honza

/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
typedef union tree_node *tree;
enum tree_code
{
  OFFSET_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, POINTER_TYPE, FIXED_POINT_TYPE,
};
struct tree_base
{
  unsigned public_flag:1;
};
struct tree_decl_with_vis
{
  unsigned comdat_flag:1;
};
union tree_node
{
  struct tree_base base;
  struct tree_decl_with_vis decl_with_vis;
};
enum tree_index
{
    TI_LONG_DOUBLE_PTR_TYPE, TI_INTEGER_PTR_TYPE, TI_VOID_TYPE, TI_PTR_TYPE,
    TI_VA_LIST_FPR_COUNTER_FIELD, TI_BOOLEAN_TYPE, TI_FILEPTR_TYPE,
    TI_CURRENT_TARGET_PRAGMA, TI_CURRENT_OPTIMIZE_PRAGMA, TI_MAX
};
extern tree global_trees[TI_MAX];
emit_support_tinfos (void)
{
  static tree *const fundamentals[] = {
    &global_trees[TI_VOID_TYPE], &global_trees[TI_BOOLEAN_TYPE],
  };
  int ix;
  for (ix = 0; fundamentals[ix]; ix++)
    {
	{
	  tree tinfo;
	    {
	      ((void) (!(((tinfo)->base.public_flag) && !(__extension__ (
									  {
									  __typeof
									  (tinfo)
									  __t
									  =
									  (tinfo);
									  __t;}
							  )->decl_with_vis.
							  comdat_flag)) ?
		       fancy_abort ("../../gcc/cp/rtti.c", 1529,
				    __FUNCTION__), 0 : 0));
	    }
	}
    }
}
/* We should copy loop header to fundamentals[0] and then fold it way into
   known value.  */
/* { dg-final { scan-tree-dump-times "fundamental.0" 1 "optimized"} } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
	* gimple.h (canonicalize_consturctor_val): Declare.
	* gimple-fold.c (canonicalize_consturctor_val): New function.
	(get_symbol_constant_value):Use it.
	* tree-ssa-ccp.c (fold_const_aggregate_ref): Likewise.

Comments

Richard Biener Sept. 4, 2010, 8:35 a.m. UTC | #1
On Sat, 4 Sep 2010, Jan Hubicka wrote:

> 
> Hi,
> the following testcases shows problem with fold_const_aggregate_ref
> producing non-gimple &global_trees[TI_VOID_TYPE] (taken from DECL_INITIAL)
> and later failing it to use it as known constant. We eventually get the constant
> value at cfgexpand time only.
> 
> I am not sure what is the proper way to fold this, so I ended up with using
> maybe_fold_offset_to_address.  With removal of some code redundancy it is hopefully
> not too bad.
> 
> Bootstrapped/regtested x86_64-linux, OK?

Ok.

Thanks,
Richard.

> Honza
> 
> /* { dg-do compile } */
> /* { dg-options "-O2 -fdump-tree-optimized" } */
> typedef union tree_node *tree;
> enum tree_code
> {
>   OFFSET_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, POINTER_TYPE, FIXED_POINT_TYPE,
> };
> struct tree_base
> {
>   unsigned public_flag:1;
> };
> struct tree_decl_with_vis
> {
>   unsigned comdat_flag:1;
> };
> union tree_node
> {
>   struct tree_base base;
>   struct tree_decl_with_vis decl_with_vis;
> };
> enum tree_index
> {
>     TI_LONG_DOUBLE_PTR_TYPE, TI_INTEGER_PTR_TYPE, TI_VOID_TYPE, TI_PTR_TYPE,
>     TI_VA_LIST_FPR_COUNTER_FIELD, TI_BOOLEAN_TYPE, TI_FILEPTR_TYPE,
>     TI_CURRENT_TARGET_PRAGMA, TI_CURRENT_OPTIMIZE_PRAGMA, TI_MAX
> };
> extern tree global_trees[TI_MAX];
> emit_support_tinfos (void)
> {
>   static tree *const fundamentals[] = {
>     &global_trees[TI_VOID_TYPE], &global_trees[TI_BOOLEAN_TYPE],
>   };
>   int ix;
>   for (ix = 0; fundamentals[ix]; ix++)
>     {
> 	{
> 	  tree tinfo;
> 	    {
> 	      ((void) (!(((tinfo)->base.public_flag) && !(__extension__ (
> 									  {
> 									  __typeof
> 									  (tinfo)
> 									  __t
> 									  =
> 									  (tinfo);
> 									  __t;}
> 							  )->decl_with_vis.
> 							  comdat_flag)) ?
> 		       fancy_abort ("../../gcc/cp/rtti.c", 1529,
> 				    __FUNCTION__), 0 : 0));
> 	    }
> 	}
>     }
> }
> /* We should copy loop header to fundamentals[0] and then fold it way into
>    known value.  */
> /* { dg-final { scan-tree-dump-times "fundamental.0" 1 "optimized"} } */
> /* { dg-final { cleanup-tree-dump "optimized" } } */
> 	* gimple.h (canonicalize_consturctor_val): Declare.
> 	* gimple-fold.c (canonicalize_consturctor_val): New function.
> 	(get_symbol_constant_value):Use it.
> 	* tree-ssa-ccp.c (fold_const_aggregate_ref): Likewise.
> Index: gimple.h
> ===================================================================
> --- gimple.h	(revision 163808)
> +++ gimple.h	(working copy)
> @@ -4876,6 +4876,7 @@ tree maybe_fold_offset_to_address (locat
>  tree maybe_fold_offset_to_reference (location_t, tree, tree, tree);
>  tree maybe_fold_stmt_addition (location_t, tree, tree, tree);
>  tree get_symbol_constant_value (tree);
> +tree canonicalize_consturctor_val (tree);
>  bool may_propagate_address_into_dereference (tree, tree);
>  extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, 
>  					enum tree_code, tree, tree);
> Index: gimple-fold.c
> ===================================================================
> --- gimple-fold.c	(revision 163808)
> +++ gimple-fold.c	(working copy)
> @@ -31,6 +31,30 @@ along with GCC; see the file COPYING3.  
>  #include "tree-ssa-propagate.h"
>  #include "target.h"
>  
> +/* CVAL is value taken from DECL_INITIAL of variable.  Try to transorm it into
> +   acceptable form for is_gimple_min_invariant.   */
> +
> +tree
> +canonicalize_consturctor_val (tree cval)
> +{
> +  STRIP_NOPS (cval);
> +  if (TREE_CODE (cval) == POINTER_PLUS_EXPR)
> +    {
> +      tree t = maybe_fold_offset_to_address (EXPR_LOCATION (cval),
> +					     TREE_OPERAND (cval, 0),
> +					     TREE_OPERAND (cval, 1),
> +					     TREE_TYPE (cval));
> +      if (t)
> +	cval = t;
> +    }
> +  if (TREE_CODE (cval) == ADDR_EXPR)
> +    {
> +      tree base = get_base_address (TREE_OPERAND (cval, 0));
> +      if (base && TREE_CODE (base) == VAR_DECL)
> +	add_referenced_var (base);
> +    }
> +  return cval;
> +}
>  
>  /* If SYM is a constant variable with known value, return the value.
>     NULL_TREE is returned otherwise.  */
> @@ -45,21 +69,9 @@ get_symbol_constant_value (tree sym)
>        tree val = DECL_INITIAL (sym);
>        if (val)
>  	{
> -	  STRIP_NOPS (val);
> +	  val = canonicalize_consturctor_val (val);
>  	  if (is_gimple_min_invariant (val))
> -	    {
> -	      if (TREE_CODE (val) == ADDR_EXPR)
> -		{
> -		  tree base = get_base_address (TREE_OPERAND (val, 0));
> -		  if (base && TREE_CODE (base) == VAR_DECL)
> -		    {
> -		      TREE_ADDRESSABLE (base) = 1;
> -		      if (gimple_referenced_vars (cfun))
> -			add_referenced_var (base);
> -		    }
> -		}
> -	      return val;
> -	    }
> +	    return val;
>  	}
>        /* Variables declared 'const' without an initializer
>  	 have zero as the initializer if they may not be
> Index: tree-ssa-ccp.c
> ===================================================================
> --- tree-ssa-ccp.c	(revision 163808)
> +++ tree-ssa-ccp.c	(working copy)
> @@ -1413,16 +1417,7 @@ fold_const_aggregate_ref (tree t)
>        /* Whoo-hoo!  I'll fold ya baby.  Yeah!  */
>        FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
>  	if (tree_int_cst_equal (cfield, idx))
> -	  {
> -	    STRIP_NOPS (cval);
> -	    if (TREE_CODE (cval) == ADDR_EXPR)
> -	      {
> -		tree base = get_base_address (TREE_OPERAND (cval, 0));
> -		if (base && TREE_CODE (base) == VAR_DECL)
> -		  add_referenced_var (base);
> -	      }
> -	    return cval;
> -	  }
> +	  return canonicalize_consturctor_val (cval);
>        break;
>  
>      case COMPONENT_REF:
> @@ -1463,16 +1458,7 @@ fold_const_aggregate_ref (tree t)
>  	if (cfield == field
>  	    /* FIXME: Handle bit-fields.  */
>  	    && ! DECL_BIT_FIELD (cfield))
> -	  {
> -	    STRIP_NOPS (cval);
> -	    if (TREE_CODE (cval) == ADDR_EXPR)
> -	      {
> -		tree base = get_base_address (TREE_OPERAND (cval, 0));
> -		if (base && TREE_CODE (base) == VAR_DECL)
> -		  add_referenced_var (base);
> -	      }
> -	    return cval;
> -	  }
> +	  return canonicalize_consturctor_val (cval);
>        break;
>  
>      case REALPART_EXPR:
> @@ -1567,13 +1553,7 @@ fold_const_aggregate_ref (tree t)
>  	  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
>  	    if (tree_int_cst_equal (cfield, idx))
>  	      {
> -		STRIP_NOPS (cval);
> -		if (TREE_CODE (cval) == ADDR_EXPR)
> -		  {
> -		    tree base = get_base_address (TREE_OPERAND (cval, 0));
> -		    if (base && TREE_CODE (base) == VAR_DECL)
> -		      add_referenced_var (base);
> -		  }
> +		cval = canonicalize_consturctor_val (cval);
>  		if (useless_type_conversion_p (TREE_TYPE (t), TREE_TYPE (cval)))
>  		  return cval;
>  		else if (CONSTANT_CLASS_P (cval))
> 
>
H.J. Lu Sept. 6, 2010, 1:50 a.m. UTC | #2
On Fri, Sep 3, 2010 at 4:57 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
>
> Hi,
> the following testcases shows problem with fold_const_aggregate_ref
> producing non-gimple &global_trees[TI_VOID_TYPE] (taken from DECL_INITIAL)
> and later failing it to use it as known constant. We eventually get the constant
> value at cfgexpand time only.
>
> I am not sure what is the proper way to fold this, so I ended up with using
> maybe_fold_offset_to_address.  With removal of some code redundancy it is hopefully
> not too bad.
>
> Bootstrapped/regtested x86_64-linux, OK?
> Honza
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45550


H.J.
diff mbox

Patch

Index: gimple.h
===================================================================
--- gimple.h	(revision 163808)
+++ gimple.h	(working copy)
@@ -4876,6 +4876,7 @@  tree maybe_fold_offset_to_address (locat
 tree maybe_fold_offset_to_reference (location_t, tree, tree, tree);
 tree maybe_fold_stmt_addition (location_t, tree, tree, tree);
 tree get_symbol_constant_value (tree);
+tree canonicalize_consturctor_val (tree);
 bool may_propagate_address_into_dereference (tree, tree);
 extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, 
 					enum tree_code, tree, tree);
Index: gimple-fold.c
===================================================================
--- gimple-fold.c	(revision 163808)
+++ gimple-fold.c	(working copy)
@@ -31,6 +31,30 @@  along with GCC; see the file COPYING3.  
 #include "tree-ssa-propagate.h"
 #include "target.h"
 
+/* CVAL is value taken from DECL_INITIAL of variable.  Try to transorm it into
+   acceptable form for is_gimple_min_invariant.   */
+
+tree
+canonicalize_consturctor_val (tree cval)
+{
+  STRIP_NOPS (cval);
+  if (TREE_CODE (cval) == POINTER_PLUS_EXPR)
+    {
+      tree t = maybe_fold_offset_to_address (EXPR_LOCATION (cval),
+					     TREE_OPERAND (cval, 0),
+					     TREE_OPERAND (cval, 1),
+					     TREE_TYPE (cval));
+      if (t)
+	cval = t;
+    }
+  if (TREE_CODE (cval) == ADDR_EXPR)
+    {
+      tree base = get_base_address (TREE_OPERAND (cval, 0));
+      if (base && TREE_CODE (base) == VAR_DECL)
+	add_referenced_var (base);
+    }
+  return cval;
+}
 
 /* If SYM is a constant variable with known value, return the value.
    NULL_TREE is returned otherwise.  */
@@ -45,21 +69,9 @@  get_symbol_constant_value (tree sym)
       tree val = DECL_INITIAL (sym);
       if (val)
 	{
-	  STRIP_NOPS (val);
+	  val = canonicalize_consturctor_val (val);
 	  if (is_gimple_min_invariant (val))
-	    {
-	      if (TREE_CODE (val) == ADDR_EXPR)
-		{
-		  tree base = get_base_address (TREE_OPERAND (val, 0));
-		  if (base && TREE_CODE (base) == VAR_DECL)
-		    {
-		      TREE_ADDRESSABLE (base) = 1;
-		      if (gimple_referenced_vars (cfun))
-			add_referenced_var (base);
-		    }
-		}
-	      return val;
-	    }
+	    return val;
 	}
       /* Variables declared 'const' without an initializer
 	 have zero as the initializer if they may not be
Index: tree-ssa-ccp.c
===================================================================
--- tree-ssa-ccp.c	(revision 163808)
+++ tree-ssa-ccp.c	(working copy)
@@ -1413,16 +1417,7 @@  fold_const_aggregate_ref (tree t)
       /* Whoo-hoo!  I'll fold ya baby.  Yeah!  */
       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
 	if (tree_int_cst_equal (cfield, idx))
-	  {
-	    STRIP_NOPS (cval);
-	    if (TREE_CODE (cval) == ADDR_EXPR)
-	      {
-		tree base = get_base_address (TREE_OPERAND (cval, 0));
-		if (base && TREE_CODE (base) == VAR_DECL)
-		  add_referenced_var (base);
-	      }
-	    return cval;
-	  }
+	  return canonicalize_consturctor_val (cval);
       break;
 
     case COMPONENT_REF:
@@ -1463,16 +1458,7 @@  fold_const_aggregate_ref (tree t)
 	if (cfield == field
 	    /* FIXME: Handle bit-fields.  */
 	    && ! DECL_BIT_FIELD (cfield))
-	  {
-	    STRIP_NOPS (cval);
-	    if (TREE_CODE (cval) == ADDR_EXPR)
-	      {
-		tree base = get_base_address (TREE_OPERAND (cval, 0));
-		if (base && TREE_CODE (base) == VAR_DECL)
-		  add_referenced_var (base);
-	      }
-	    return cval;
-	  }
+	  return canonicalize_consturctor_val (cval);
       break;
 
     case REALPART_EXPR:
@@ -1567,13 +1553,7 @@  fold_const_aggregate_ref (tree t)
 	  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
 	    if (tree_int_cst_equal (cfield, idx))
 	      {
-		STRIP_NOPS (cval);
-		if (TREE_CODE (cval) == ADDR_EXPR)
-		  {
-		    tree base = get_base_address (TREE_OPERAND (cval, 0));
-		    if (base && TREE_CODE (base) == VAR_DECL)
-		      add_referenced_var (base);
-		  }
+		cval = canonicalize_consturctor_val (cval);
 		if (useless_type_conversion_p (TREE_TYPE (t), TREE_TYPE (cval)))
 		  return cval;
 		else if (CONSTANT_CLASS_P (cval))