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]

[PATCH] Fix PR37305, make constant propagations not set TREE_OVERFLOW for conversions


Currently fold_convert sets the overflow flag if you convert a constant
to a type where its value doesn't fit.  VRP treats the overflow flag on
the min/max values as "undefined", but explicit conversions are covered
by implementation defined behavior.

Now, the mess is deep and we rely on the overflow flag being set in
multiple places (even VRP), so we cannot "fix" this in fold.  So the
following patch touches two of the obvious places where we are "leaking"
constants with TREE_OVERFLOW set.

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

In some distant future TREE_OVERFLOW should be banned from the middle-end
completely.

Richard.

2008-09-01  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/37305
	* tree-ssa-ccp.c (ccp_fold): Do not set TREE_OVERFLOW on
	the result of constant conversions.
	(fold_gimple_assign): Likewise.

Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c	(revision 139854)
--- gcc/tree-ssa-ccp.c	(working copy)
*************** ccp_fold (gimple stmt)
*** 941,946 ****
--- 941,947 ----
                   so this should almost always return a simplified RHS.  */
                tree lhs = gimple_assign_lhs (stmt);
                tree op0 = gimple_assign_rhs1 (stmt);
+ 	      tree res;
  
                /* Simplify the operand down to a constant.  */
                if (TREE_CODE (op0) == SSA_NAME)
*************** ccp_fold (gimple stmt)
*** 976,983 ****
  		  return op0;
  		}
  
!               return fold_unary (subcode, gimple_expr_type (stmt), op0);
!             }  
  
            case GIMPLE_BINARY_RHS:
              {
--- 977,997 ----
  		  return op0;
  		}
  
!               res = fold_unary (subcode, gimple_expr_type (stmt), op0);
! 
! 	      /* If the operation was a conversion do _not_ mark a
! 	         resulting constant with TREE_OVERFLOW if the original
! 		 constant was not.  These conversions have implementation
! 		 defined behavior and retaining the TREE_OVERFLOW flag
! 		 here would confuse later passes such as VRP.  */
! 	      if (res
! 		  && TREE_CODE (res) == INTEGER_CST
! 		  && TREE_CODE (op0) == INTEGER_CST
! 		  && CONVERT_EXPR_CODE_P (subcode))
! 		TREE_OVERFLOW (res) = TREE_OVERFLOW (op0);
! 
! 	      return res;
!             }
  
            case GIMPLE_BINARY_RHS:
              {
*************** fold_gimple_assign (gimple_stmt_iterator
*** 2644,2669 ****
        break;
  
      case GIMPLE_UNARY_RHS:
!       result = fold_unary (subcode,
!                            gimple_expr_type (stmt),
!                            gimple_assign_rhs1 (stmt));
  
!       if (result)
!         {
!           STRIP_USELESS_TYPE_CONVERSION (result);
!           if (valid_gimple_rhs_p (result))
! 	    return result;
!         }
!       else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
! 	       && POINTER_TYPE_P (gimple_expr_type (stmt))
! 	       && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
! 	{
! 	  tree type = gimple_expr_type (stmt);
! 	  tree t = maybe_fold_offset_to_address (gimple_assign_rhs1 (stmt),
! 						 integer_zero_node, type);
! 	  if (t)
! 	    return t;
! 	}
        break;
  
      case GIMPLE_BINARY_RHS:
--- 2658,2694 ----
        break;
  
      case GIMPLE_UNARY_RHS:
!       {
! 	tree rhs = gimple_assign_rhs1 (stmt);
  
! 	result = fold_unary (subcode, gimple_expr_type (stmt), rhs);
! 	if (result)
! 	  {
! 	    /* If the operation was a conversion do _not_ mark a
! 	       resulting constant with TREE_OVERFLOW if the original
! 	       constant was not.  These conversions have implementation
! 	       defined behavior and retaining the TREE_OVERFLOW flag
! 	       here would confuse later passes such as VRP.  */
! 	    if (CONVERT_EXPR_CODE_P (subcode)
! 		&& TREE_CODE (result) == INTEGER_CST
! 		&& TREE_CODE (rhs) == INTEGER_CST)
! 	      TREE_OVERFLOW (result) = TREE_OVERFLOW (rhs);
! 
! 	    STRIP_USELESS_TYPE_CONVERSION (result);
! 	    if (valid_gimple_rhs_p (result))
! 	      return result;
! 	  }
! 	else if (CONVERT_EXPR_CODE_P (subcode)
! 		 && POINTER_TYPE_P (gimple_expr_type (stmt))
! 		 && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
! 	  {
! 	    tree type = gimple_expr_type (stmt);
! 	    tree t = maybe_fold_offset_to_address (gimple_assign_rhs1 (stmt),
! 						   integer_zero_node, type);
! 	    if (t)
! 	      return t;
! 	  }
!       }
        break;
  
      case GIMPLE_BINARY_RHS:
Index: gcc/testsuite/gcc.c-torture/compile/pr37305.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/pr37305.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/compile/pr37305.c	(revision 0)
***************
*** 0 ****
--- 1,19 ----
+ typedef int int32_t;
+ typedef unsigned int uint32_t;
+ static inline int
+ safe_add_s_s (int si1, int si2)
+ {
+   if ((si1 > 0) && (si2 > 0) && (si1 > (si2)) || (si1 < 0) && (si2 < 0)
+       && (si1 < ((-__INT_MAX__ - 1) - si2)))
+     return si1;
+ }
+ 
+ uint32_t g_8;
+ uint32_t
+ func_24 (int32_t p_25)
+ {
+   uint32_t l_30 = -1L;
+   if ((safe_mod_u_u (1, 1)) | (safe_add_s_s (g_8, l_30)))
+     return 1;
+ }
+ 


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