This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR37305, make constant propagations not set TREE_OVERFLOW for conversions
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 1 Sep 2008 15:36:43 +0200 (CEST)
- Subject: [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;
+ }
+