[PATCH] Fix CCP regression wrt global constant initializers

Richard Guenther rguenther@suse.de
Fri Feb 5 15:24:00 GMT 2010


As noted in PR42952 we miss propagation of the constant address
in 4.5 due to type system interactions.  Fixed with the following.

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

Richard.

2010-02-04  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-ccp.c (get_symbol_constant_value): Strip all
	conversions.
	(fold_const_aggregate_ref): Likewise.
	(ccp_fold_stmt): Substitute loads.
	(maybe_fold_reference): Verify types before substituting.
	Unshare properly.
	(fold_gimple_assign): Unshare properly.
	(fold_stmt_1): Insert conversion if necessary before replacing
	the RHS.

	* gcc.dg/tree-ssa/ssa-ccp-28.c: New testcase.

Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c	(revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c	(revision 0)
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do run } */
+ /* { dg-options "-O -fdump-tree-ccp1" } */
+ 
+ extern void abort (void);
+ 
+ static int g[1];
+ 
+ static int * const p = &g[0];
+ static int * const q = &g[0];
+ 
+ int main(void)
+ {
+   g[0] = 1;
+   *p = 0;
+   *p = *q;
+   if (g[0] != 0)
+     abort ();
+   return 0;
+ }
+ 
+ /* We should have replaced all loads from p and q with the constant
+    initial value.  */
+ 
+ /* { dg-final { scan-tree-dump-times "= p;" 0 "ccp1" } } */
+ /* { dg-final { scan-tree-dump-times "= q;" 0 "ccp1" } } */
+ /* { dg-final { cleanup-tree-dump "ccp1" } } */
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c	(revision 156493)
--- gcc/tree-ssa-ccp.c	(working copy)
*************** get_symbol_constant_value (tree sym)
*** 283,289 ****
        tree val = DECL_INITIAL (sym);
        if (val)
  	{
! 	  STRIP_USELESS_TYPE_CONVERSION (val);
  	  if (is_gimple_min_invariant (val))
  	    {
  	      if (TREE_CODE (val) == ADDR_EXPR)
--- 283,289 ----
        tree val = DECL_INITIAL (sym);
        if (val)
  	{
! 	  STRIP_NOPS (val);
  	  if (is_gimple_min_invariant (val))
  	    {
  	      if (TREE_CODE (val) == ADDR_EXPR)
*************** fold_const_aggregate_ref (tree t)
*** 1297,1303 ****
        FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
  	if (tree_int_cst_equal (cfield, idx))
  	  {
! 	    STRIP_USELESS_TYPE_CONVERSION (cval);
  	    if (TREE_CODE (cval) == ADDR_EXPR)
  	      {
  		tree base = get_base_address (TREE_OPERAND (cval, 0));
--- 1297,1303 ----
        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));
*************** fold_const_aggregate_ref (tree t)
*** 1346,1352 ****
  	    /* FIXME: Handle bit-fields.  */
  	    && ! DECL_BIT_FIELD (cfield))
  	  {
! 	    STRIP_USELESS_TYPE_CONVERSION (cval);
  	    if (TREE_CODE (cval) == ADDR_EXPR)
  	      {
  		tree base = get_base_address (TREE_OPERAND (cval, 0));
--- 1346,1352 ----
  	    /* 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));
*************** ccp_fold_stmt (gimple_stmt_iterator *gsi
*** 1552,1557 ****
--- 1552,1579 ----
  	return changed;
        }
  
+     case GIMPLE_ASSIGN:
+       {
+ 	tree lhs = gimple_assign_lhs (stmt);
+ 	prop_value_t *val;
+ 
+ 	/* If we have a load that turned out to be constant replace it
+ 	   as we cannot propagate into all uses in all cases.  */
+ 	if (gimple_assign_single_p (stmt)
+ 	    && TREE_CODE (lhs) == SSA_NAME
+ 	    && (val = get_value (lhs))
+ 	    && val->lattice_val == CONSTANT)
+ 	  {
+ 	    tree rhs = unshare_expr (val->value);
+ 	    if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ 	      rhs = fold_convert (TREE_TYPE (lhs), rhs);
+ 	    gimple_assign_set_rhs_from_tree (gsi, rhs);
+ 	    return true;
+ 	  }
+ 
+ 	return false;
+       }
+ 
      default:
        return false;
      }
*************** maybe_fold_reference (tree expr, bool is
*** 2412,2420 ****
  	   && DECL_P (*t))
      {
        tree tem = get_symbol_constant_value (*t);
!       if (tem)
  	{
! 	  *t = tem;
  	  tem = maybe_fold_reference (expr, is_lhs);
  	  if (tem)
  	    return tem;
--- 2434,2443 ----
  	   && DECL_P (*t))
      {
        tree tem = get_symbol_constant_value (*t);
!       if (tem
! 	  && useless_type_conversion_p (TREE_TYPE (*t), TREE_TYPE (tem)))
  	{
! 	  *t = unshare_expr (tem);
  	  tem = maybe_fold_reference (expr, is_lhs);
  	  if (tem)
  	    return tem;
*************** fold_gimple_assign (gimple_stmt_iterator
*** 2824,2830 ****
  	  }
  
  	else if (DECL_P (rhs))
! 	  return get_symbol_constant_value (rhs);
  
          /* If we couldn't fold the RHS, hand over to the generic
             fold routines.  */
--- 2847,2853 ----
  	  }
  
  	else if (DECL_P (rhs))
! 	  return unshare_expr (get_symbol_constant_value (rhs));
  
          /* If we couldn't fold the RHS, hand over to the generic
             fold routines.  */
*************** fold_stmt_1 (gimple_stmt_iterator *gsi,
*** 3035,3041 ****
        {
  	unsigned old_num_ops = gimple_num_ops (stmt);
  	tree new_rhs = fold_gimple_assign (gsi);
! 	if (new_rhs != NULL_TREE
  	    && (!inplace
  		|| get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops))
  	  {
--- 3058,3069 ----
        {
  	unsigned old_num_ops = gimple_num_ops (stmt);
  	tree new_rhs = fold_gimple_assign (gsi);
! 	tree lhs = gimple_assign_lhs (stmt);
! 	if (new_rhs
! 	    && !useless_type_conversion_p (TREE_TYPE (lhs),
! 					   TREE_TYPE (new_rhs)))
! 	  new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
! 	if (new_rhs
  	    && (!inplace
  		|| get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops))
  	  {



More information about the Gcc-patches mailing list