fold-canst.c (tree_call_nonnegative_warnv_p): New.

2008-04-08  Rafael Espindola  <espindola@google.com>

	* fold-canst.c (tree_call_nonnegative_warnv_p): New.
	(tree_invalid_nonnegative_warnv_p): Use tree_call_nonnegative_warnv_p.
	* tree.h (tree_call_nonnegative_warnv_p): New.

From-SVN: r134102
This commit is contained in:
Rafael Avila de Espindola 2008-04-08 18:25:09 +00:00 committed by Rafael Espindola
parent 581edf9260
commit a1a6e27102
3 changed files with 151 additions and 125 deletions

View File

@ -1,3 +1,9 @@
2008-04-08 Rafael Espindola <espindola@google.com>
* fold-canst.c (tree_call_nonnegative_warnv_p): New.
(tree_invalid_nonnegative_warnv_p): Use tree_call_nonnegative_warnv_p.
* tree.h (tree_call_nonnegative_warnv_p): New.
2008-04-08 Jan Hubicka <jh@suse.cz>
* function.c (free_after_compilation): Clear out regno_reg_rtx

View File

@ -13996,6 +13996,140 @@ tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
return false;
}
/* Return true if T is known to be non-negative. If the return
value is based on the assumption that signed overflow is undefined,
set *STRICT_OVERFLOW_P to true; otherwise, don't change
*STRICT_OVERFLOW_P. */
bool
tree_call_nonnegative_warnv_p (enum tree_code code, tree type, tree fndecl,
tree arg0, tree arg1, bool *strict_overflow_p)
{
if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (fndecl))
{
CASE_FLT_FN (BUILT_IN_ACOS):
CASE_FLT_FN (BUILT_IN_ACOSH):
CASE_FLT_FN (BUILT_IN_CABS):
CASE_FLT_FN (BUILT_IN_COSH):
CASE_FLT_FN (BUILT_IN_ERFC):
CASE_FLT_FN (BUILT_IN_EXP):
CASE_FLT_FN (BUILT_IN_EXP10):
CASE_FLT_FN (BUILT_IN_EXP2):
CASE_FLT_FN (BUILT_IN_FABS):
CASE_FLT_FN (BUILT_IN_FDIM):
CASE_FLT_FN (BUILT_IN_HYPOT):
CASE_FLT_FN (BUILT_IN_POW10):
CASE_INT_FN (BUILT_IN_FFS):
CASE_INT_FN (BUILT_IN_PARITY):
CASE_INT_FN (BUILT_IN_POPCOUNT):
case BUILT_IN_BSWAP32:
case BUILT_IN_BSWAP64:
/* Always true. */
return true;
CASE_FLT_FN (BUILT_IN_SQRT):
/* sqrt(-0.0) is -0.0. */
if (!HONOR_SIGNED_ZEROS (TYPE_MODE (type)))
return true;
return tree_expr_nonnegative_warnv_p (arg0,
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_ASINH):
CASE_FLT_FN (BUILT_IN_ATAN):
CASE_FLT_FN (BUILT_IN_ATANH):
CASE_FLT_FN (BUILT_IN_CBRT):
CASE_FLT_FN (BUILT_IN_CEIL):
CASE_FLT_FN (BUILT_IN_ERF):
CASE_FLT_FN (BUILT_IN_EXPM1):
CASE_FLT_FN (BUILT_IN_FLOOR):
CASE_FLT_FN (BUILT_IN_FMOD):
CASE_FLT_FN (BUILT_IN_FREXP):
CASE_FLT_FN (BUILT_IN_LCEIL):
CASE_FLT_FN (BUILT_IN_LDEXP):
CASE_FLT_FN (BUILT_IN_LFLOOR):
CASE_FLT_FN (BUILT_IN_LLCEIL):
CASE_FLT_FN (BUILT_IN_LLFLOOR):
CASE_FLT_FN (BUILT_IN_LLRINT):
CASE_FLT_FN (BUILT_IN_LLROUND):
CASE_FLT_FN (BUILT_IN_LRINT):
CASE_FLT_FN (BUILT_IN_LROUND):
CASE_FLT_FN (BUILT_IN_MODF):
CASE_FLT_FN (BUILT_IN_NEARBYINT):
CASE_FLT_FN (BUILT_IN_RINT):
CASE_FLT_FN (BUILT_IN_ROUND):
CASE_FLT_FN (BUILT_IN_SCALB):
CASE_FLT_FN (BUILT_IN_SCALBLN):
CASE_FLT_FN (BUILT_IN_SCALBN):
CASE_FLT_FN (BUILT_IN_SIGNBIT):
CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
CASE_FLT_FN (BUILT_IN_SINH):
CASE_FLT_FN (BUILT_IN_TANH):
CASE_FLT_FN (BUILT_IN_TRUNC):
/* True if the 1st argument is nonnegative. */
return tree_expr_nonnegative_warnv_p (arg0,
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_FMAX):
/* True if the 1st OR 2nd arguments are nonnegative. */
return (tree_expr_nonnegative_warnv_p (arg0,
strict_overflow_p)
|| (tree_expr_nonnegative_warnv_p (arg1,
strict_overflow_p)));
CASE_FLT_FN (BUILT_IN_FMIN):
/* True if the 1st AND 2nd arguments are nonnegative. */
return (tree_expr_nonnegative_warnv_p (arg0,
strict_overflow_p)
&& (tree_expr_nonnegative_warnv_p (arg1,
strict_overflow_p)));
CASE_FLT_FN (BUILT_IN_COPYSIGN):
/* True if the 2nd argument is nonnegative. */
return tree_expr_nonnegative_warnv_p (arg1,
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_POWI):
/* True if the 1st argument is nonnegative or the second
argument is an even integer. */
if (TREE_CODE (arg1) == INTEGER_CST)
{
tree arg1 = arg1;
if ((TREE_INT_CST_LOW (arg1) & 1) == 0)
return true;
}
return tree_expr_nonnegative_warnv_p (arg0,
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_POW):
/* True if the 1st argument is nonnegative or the second
argument is an even integer valued real. */
if (TREE_CODE (arg1) == REAL_CST)
{
REAL_VALUE_TYPE c;
HOST_WIDE_INT n;
c = TREE_REAL_CST (arg1);
n = real_to_integer (&c);
if ((n & 1) == 0)
{
REAL_VALUE_TYPE cint;
real_from_integer (&cint, VOIDmode, n,
n < 0 ? -1 : 0, 0);
if (real_identical (&c, &cint))
return true;
}
}
return tree_expr_nonnegative_warnv_p (arg0,
strict_overflow_p);
default:
break;
}
return tree_simple_nonnegative_warnv_p (code,
type);
}
/* Return true if T is known to be non-negative. If the return
value is based on the assumption that signed overflow is undefined,
set *STRICT_OVERFLOW_P to true; otherwise, don't change
@ -14045,133 +14179,16 @@ tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p)
case CALL_EXPR:
{
tree fndecl = get_callee_fndecl (t);
if (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
switch (DECL_FUNCTION_CODE (fndecl))
{
CASE_FLT_FN (BUILT_IN_ACOS):
CASE_FLT_FN (BUILT_IN_ACOSH):
CASE_FLT_FN (BUILT_IN_CABS):
CASE_FLT_FN (BUILT_IN_COSH):
CASE_FLT_FN (BUILT_IN_ERFC):
CASE_FLT_FN (BUILT_IN_EXP):
CASE_FLT_FN (BUILT_IN_EXP10):
CASE_FLT_FN (BUILT_IN_EXP2):
CASE_FLT_FN (BUILT_IN_FABS):
CASE_FLT_FN (BUILT_IN_FDIM):
CASE_FLT_FN (BUILT_IN_HYPOT):
CASE_FLT_FN (BUILT_IN_POW10):
CASE_INT_FN (BUILT_IN_FFS):
CASE_INT_FN (BUILT_IN_PARITY):
CASE_INT_FN (BUILT_IN_POPCOUNT):
case BUILT_IN_BSWAP32:
case BUILT_IN_BSWAP64:
/* Always true. */
return true;
tree arg0 = call_expr_nargs (t) > 0 ? CALL_EXPR_ARG (t, 0) : NULL_TREE;
tree arg1 = call_expr_nargs (t) > 1 ? CALL_EXPR_ARG (t, 1) : NULL_TREE;
CASE_FLT_FN (BUILT_IN_SQRT):
/* sqrt(-0.0) is -0.0. */
if (!HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (t))))
return true;
return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_ASINH):
CASE_FLT_FN (BUILT_IN_ATAN):
CASE_FLT_FN (BUILT_IN_ATANH):
CASE_FLT_FN (BUILT_IN_CBRT):
CASE_FLT_FN (BUILT_IN_CEIL):
CASE_FLT_FN (BUILT_IN_ERF):
CASE_FLT_FN (BUILT_IN_EXPM1):
CASE_FLT_FN (BUILT_IN_FLOOR):
CASE_FLT_FN (BUILT_IN_FMOD):
CASE_FLT_FN (BUILT_IN_FREXP):
CASE_FLT_FN (BUILT_IN_LCEIL):
CASE_FLT_FN (BUILT_IN_LDEXP):
CASE_FLT_FN (BUILT_IN_LFLOOR):
CASE_FLT_FN (BUILT_IN_LLCEIL):
CASE_FLT_FN (BUILT_IN_LLFLOOR):
CASE_FLT_FN (BUILT_IN_LLRINT):
CASE_FLT_FN (BUILT_IN_LLROUND):
CASE_FLT_FN (BUILT_IN_LRINT):
CASE_FLT_FN (BUILT_IN_LROUND):
CASE_FLT_FN (BUILT_IN_MODF):
CASE_FLT_FN (BUILT_IN_NEARBYINT):
CASE_FLT_FN (BUILT_IN_RINT):
CASE_FLT_FN (BUILT_IN_ROUND):
CASE_FLT_FN (BUILT_IN_SCALB):
CASE_FLT_FN (BUILT_IN_SCALBLN):
CASE_FLT_FN (BUILT_IN_SCALBN):
CASE_FLT_FN (BUILT_IN_SIGNBIT):
CASE_FLT_FN (BUILT_IN_SIGNIFICAND):
CASE_FLT_FN (BUILT_IN_SINH):
CASE_FLT_FN (BUILT_IN_TANH):
CASE_FLT_FN (BUILT_IN_TRUNC):
/* True if the 1st argument is nonnegative. */
return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_FMAX):
/* True if the 1st OR 2nd arguments are nonnegative. */
return (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p)
|| (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1),
strict_overflow_p)));
CASE_FLT_FN (BUILT_IN_FMIN):
/* True if the 1st AND 2nd arguments are nonnegative. */
return (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p)
&& (tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1),
strict_overflow_p)));
CASE_FLT_FN (BUILT_IN_COPYSIGN):
/* True if the 2nd argument is nonnegative. */
return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 1),
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_POWI):
/* True if the 1st argument is nonnegative or the second
argument is an even integer. */
if (TREE_CODE (CALL_EXPR_ARG (t, 1)) == INTEGER_CST)
{
tree arg1 = CALL_EXPR_ARG (t, 1);
if ((TREE_INT_CST_LOW (arg1) & 1) == 0)
return true;
}
return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p);
CASE_FLT_FN (BUILT_IN_POW):
/* True if the 1st argument is nonnegative or the second
argument is an even integer valued real. */
if (TREE_CODE (CALL_EXPR_ARG (t, 1)) == REAL_CST)
{
REAL_VALUE_TYPE c;
HOST_WIDE_INT n;
c = TREE_REAL_CST (CALL_EXPR_ARG (t, 1));
n = real_to_integer (&c);
if ((n & 1) == 0)
{
REAL_VALUE_TYPE cint;
real_from_integer (&cint, VOIDmode, n,
n < 0 ? -1 : 0, 0);
if (real_identical (&c, &cint))
return true;
}
}
return tree_expr_nonnegative_warnv_p (CALL_EXPR_ARG (t, 0),
strict_overflow_p);
default:
break;
}
return tree_simple_nonnegative_warnv_p (TREE_CODE (t),
TREE_TYPE (t));
return tree_call_nonnegative_warnv_p (TREE_CODE (t),
TREE_TYPE (t),
get_callee_fndecl (t),
arg0,
arg1,
strict_overflow_p);
}
break;
case COMPOUND_EXPR:
case MODIFY_EXPR:
case GIMPLE_MODIFY_STMT:

View File

@ -4846,6 +4846,9 @@ extern bool tree_binary_nonnegative_warnv_p (enum tree_code, tree, tree, tree,
bool *);
extern bool tree_single_nonnegative_warnv_p (tree t, bool *strict_overflow_p);
extern bool tree_invalid_nonnegative_warnv_p (tree t, bool *strict_overflow_p);
extern bool tree_call_nonnegative_warnv_p (enum tree_code code, tree, tree,
tree, tree, bool *);
extern bool tree_expr_nonzero_warnv_p (tree, bool *);
extern bool fold_real_zero_addition_p (const_tree, const_tree, int);