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]

Re: [PATCH] Make SCCVN fold more constant initializers


On Sat, 15 Mar 2008, Richard Guenther wrote:

> 
> This makes SCCVN use the helper function from CCP which handles
> more cases.  Unfortunately this breaks g++.dg/opt/static3.C and
> I found no way to xfail a link test.
> 
> Otherwise bootstrapped and tested on x86_64-unknown-linux-gnu.
> 
> I'll apply this once I found a way to xfail the above test
> (or figure out a way to detect this case where binds_local_p
> returns false incorrectly).

The easy fix is to just restore behavior to the pre-35494 state
for symbols with an initializer.  Overriding

  const int foo = 1;

with anything else than 1 is - err - questionable.  No standards
at hand here, but this was previous behavior for years.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2008-03-14  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-ccp.c (get_symbol_constant_value): Export.
	(fold_const_aggregate_ref): Likewise.
	(get_value): Return NULL if we don't have any values.
	(ccp_finalize): Set const_val to NULL after freeing it.
	* tree-flow.h (get_symbol_constant_value): Declare.
	(fold_const_aggregate_ref): Likewise.
	* tree-ssa-sccvn.c (try_to_simplify): Use them.

	* gcc.dg/pr23911.c: Adjust testcase.
	* gcc.dg/tree-ssa/pr14841.c: Likewise.
	* gcc.dg/tree-ssa/20030922-2.c: Likewise.

Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h.orig	2008-03-15 00:53:46.000000000 +0100
--- gcc/tree-flow.h	2008-03-15 13:13:25.000000000 +0100
*************** void set_current_def (tree, tree);
*** 940,945 ****
--- 940,947 ----
  /* In tree-ssa-ccp.c  */
  bool fold_stmt (tree *);
  bool fold_stmt_inplace (tree);
+ tree get_symbol_constant_value (tree);
+ tree fold_const_aggregate_ref (tree);
  tree widen_bitfield (tree, tree, tree);
  
  /* In tree-vrp.c  */
Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c.orig	2008-03-15 00:53:46.000000000 +0100
--- gcc/tree-ssa-sccvn.c	2008-03-15 13:13:25.000000000 +0100
*************** simplify_unary_expression (tree rhs)
*** 1597,1644 ****
  static tree
  try_to_simplify (tree stmt, tree rhs)
  {
    /* For stores we can end up simplifying a SSA_NAME rhs.  Just return
       in this case, there is no point in doing extra work.  */
    if (TREE_CODE (rhs) == SSA_NAME)
      return rhs;
!   else
      {
!       switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
! 	{
! 	  /* For references, see if we find a result for the lookup,
! 	     and use it if we do.  */
! 	case tcc_declaration:
! 	  /* Pull out any truly constant values.  */
! 	  if (TREE_READONLY (rhs)
! 	      && TREE_STATIC (rhs)
! 	      && DECL_INITIAL (rhs)
! 	      && valid_gimple_expression_p (DECL_INITIAL (rhs)))
! 	    return DECL_INITIAL (rhs);
! 
! 	    /* Fallthrough. */
! 	case tcc_reference:
! 	  /* Do not do full-blown reference lookup here.
! 	     ???  But like for tcc_declaration, we should simplify
! 		  from constant initializers.  */
! 
! 	  /* Fallthrough for some codes that can operate on registers.  */
! 	  if (!(TREE_CODE (rhs) == REALPART_EXPR
! 	        || TREE_CODE (rhs) == IMAGPART_EXPR
! 		|| TREE_CODE (rhs) == VIEW_CONVERT_EXPR))
! 	    break;
! 	  /* We could do a little more with unary ops, if they expand
! 	     into binary ops, but it's debatable whether it is worth it. */
! 	case tcc_unary:
! 	  return simplify_unary_expression (rhs);
! 	  break;
! 	case tcc_comparison:
! 	case tcc_binary:
! 	  return simplify_binary_expression (stmt, rhs);
! 	  break;
! 	default:
! 	  break;
! 	}
      }
    return rhs;
  }
  
--- 1597,1642 ----
  static tree
  try_to_simplify (tree stmt, tree rhs)
  {
+   tree tem;
+ 
    /* For stores we can end up simplifying a SSA_NAME rhs.  Just return
       in this case, there is no point in doing extra work.  */
    if (TREE_CODE (rhs) == SSA_NAME)
      return rhs;
! 
!   switch (TREE_CODE_CLASS (TREE_CODE (rhs)))
      {
!     case tcc_declaration:
!       tem = get_symbol_constant_value (rhs);
!       if (tem)
! 	return tem;
!       break;
! 
!     case tcc_reference:
!       /* Do not do full-blown reference lookup here, but simplify
! 	 reads from constant aggregates.  */
!       tem = fold_const_aggregate_ref (rhs);
!       if (tem)
! 	return tem;
! 
!       /* Fallthrough for some codes that can operate on registers.  */
!       if (!(TREE_CODE (rhs) == REALPART_EXPR
! 	    || TREE_CODE (rhs) == IMAGPART_EXPR
! 	    || TREE_CODE (rhs) == VIEW_CONVERT_EXPR))
! 	break;
!       /* We could do a little more with unary ops, if they expand
! 	 into binary ops, but it's debatable whether it is worth it. */
!     case tcc_unary:
!       return simplify_unary_expression (rhs);
!       break;
!     case tcc_comparison:
!     case tcc_binary:
!       return simplify_binary_expression (stmt, rhs);
!       break;
!     default:
!       break;
      }
+ 
    return rhs;
  }
  
Index: gcc/testsuite/gcc.dg/pr23911.c
===================================================================
*** gcc/testsuite/gcc.dg/pr23911.c.orig	2008-03-15 00:53:46.000000000 +0100
--- gcc/testsuite/gcc.dg/pr23911.c	2008-03-15 13:13:25.000000000 +0100
***************
*** 1,7 ****
  /* This was a missed optimization in tree constant propagation
     that CSE would catch later on.  */
  /* { dg-do compile } */
! /* { dg-options "-O2 -fdump-tree-store_ccp" } */
  
  double _Complex *a; 
  static const double _Complex b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 
--- 1,7 ----
  /* This was a missed optimization in tree constant propagation
     that CSE would catch later on.  */
  /* { dg-do compile } */
! /* { dg-options "-O -fdump-tree-dce2" } */
  
  double _Complex *a; 
  static const double _Complex b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 
*************** test (void) 
*** 14,22 ****
    return; 
  } 
  
! /* After store_ccp, there should not be any assignments from real or
!    imaginary parts anymore.  The constants should be loaded from b and
!    propagated into the elements of a.  */
! /* { dg-final { scan-tree-dump-times "= CR" 0 "store_ccp" } } */
! /* { dg-final { scan-tree-dump-times "= CI" 0 "store_ccp" } } */
! /* { dg-final { cleanup-tree-dump "store_ccp" } } */
--- 14,21 ----
    return; 
  } 
  
! /* After DCE2 which runs after FRE, the expressions should be fully
!    constant folded.  There should be no loads from b left.  */
! /* { dg-final { scan-tree-dump-times "__complex__ \\\(1.0e\\\+0, 0.0\\\)" 2 "dce2" } } */
! /* { dg-final { scan-tree-dump-times "= b" 0 "dce2" } } */
! /* { dg-final { cleanup-tree-dump "dce2" } } */
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c.orig	2008-03-15 13:13:16.000000000 +0100
--- gcc/tree-ssa-ccp.c	2008-03-15 13:29:54.000000000 +0100
*************** ccp_decl_initial_min_invariant (tree t)
*** 295,317 ****
  /* If SYM is a constant variable with known value, return the value.
     NULL_TREE is returned otherwise.  */
  
! static tree
  get_symbol_constant_value (tree sym)
  {
    if (TREE_STATIC (sym)
        && TREE_READONLY (sym)
!       && !MTAG_P (sym)
!       /* Check if a read-only definition may be overridden at
! 	 link and run time.  */
!       && targetm.binds_local_p (sym))
      {
        tree val = DECL_INITIAL (sym);
        if (val
  	  && ccp_decl_initial_min_invariant (val))
  	return val;
        /* Variables declared 'const' without an initializer
! 	 have zero as the intializer.  */
        if (!val
            && (INTEGRAL_TYPE_P (TREE_TYPE (sym))
  	       || SCALAR_FLOAT_TYPE_P (TREE_TYPE (sym))))
          return fold_convert (TREE_TYPE (sym), integer_zero_node);
--- 295,316 ----
  /* If SYM is a constant variable with known value, return the value.
     NULL_TREE is returned otherwise.  */
  
! tree
  get_symbol_constant_value (tree sym)
  {
    if (TREE_STATIC (sym)
        && TREE_READONLY (sym)
!       && !MTAG_P (sym))
      {
        tree val = DECL_INITIAL (sym);
        if (val
  	  && ccp_decl_initial_min_invariant (val))
  	return val;
        /* Variables declared 'const' without an initializer
! 	 have zero as the intializer if they may not be
! 	 overridden at link or run time.  */
        if (!val
+ 	  && targetm.binds_local_p (sym)
            && (INTEGRAL_TYPE_P (TREE_TYPE (sym))
  	       || SCALAR_FLOAT_TYPE_P (TREE_TYPE (sym))))
          return fold_convert (TREE_TYPE (sym), integer_zero_node);
*************** get_default_value (tree var)
*** 406,413 ****
  static inline prop_value_t *
  get_value (tree var)
  {
!   prop_value_t *val = &const_val[SSA_NAME_VERSION (var)];
  
    if (val->lattice_val == UNINITIALIZED)
      *val = get_default_value (var);
  
--- 405,416 ----
  static inline prop_value_t *
  get_value (tree var)
  {
!   prop_value_t *val;
  
+   if (const_val == NULL)
+     return NULL;
+ 
+   val = &const_val[SSA_NAME_VERSION (var)];
    if (val->lattice_val == UNINITIALIZED)
      *val = get_default_value (var);
  
*************** ccp_finalize (void)
*** 722,727 ****
--- 725,731 ----
    bool something_changed = substitute_and_fold (const_val, false);
  
    free (const_val);
+   const_val = NULL;
    return something_changed;;
  }
  
*************** ccp_fold (tree stmt)
*** 1026,1032 ****
     ARRAY_REF or COMPONENT_REF into constant aggregates.  Return
     NULL_TREE otherwise.  */
  
! static tree
  fold_const_aggregate_ref (tree t)
  {
    prop_value_t *value;
--- 1030,1036 ----
     ARRAY_REF or COMPONENT_REF into constant aggregates.  Return
     NULL_TREE otherwise.  */
  
! tree
  fold_const_aggregate_ref (tree t)
  {
    prop_value_t *value;
Index: gcc/testsuite/gcc.dg/tree-ssa/20030922-2.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/20030922-2.c.orig	2008-03-15 00:53:46.000000000 +0100
--- gcc/testsuite/gcc.dg/tree-ssa/20030922-2.c	2008-03-15 13:13:25.000000000 +0100
*************** struct rtx_def
*** 7,14 ****
  {
    int bb;
  };
! static int *block_to_bb;
! static int target_bb;
  
  int
  rgn_rank (rtx insn1, rtx insn2)
--- 7,14 ----
  {
    int bb;
  };
! int *block_to_bb;
! int target_bb;
  
  int
  rgn_rank (rtx insn1, rtx insn2)
Index: gcc/testsuite/gcc.dg/tree-ssa/pr14841.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/pr14841.c.orig	2008-03-15 00:53:46.000000000 +0100
--- gcc/testsuite/gcc.dg/tree-ssa/pr14841.c	2008-03-15 13:13:25.000000000 +0100
***************
*** 2,9 ****
     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;
--- 2,9 ----
     Make sure that we can fold a possible nested reference into a
     constant aggregate.  */
  
! /* { dg-do link } */
! /* { dg-options "-O" } */
  
  struct car {
    int speed;
*************** foo (void)
*** 25,29 ****
      link_error ();
  }
  
! /* { dg-final { scan-tree-dump-times "Folded statement: if " 1 "store_ccp"} } */
! /* { dg-final { cleanup-tree-dump "store_ccp" } } */
--- 25,29 ----
      link_error ();
  }
  
! int main () { return 0; }
! 


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