diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-07-06 11:34:17 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-07-06 11:34:17 +0200 |
commit | 1f6eac9041e87e273c2b955a309ed44364f41544 (patch) | |
tree | 5c06ed10d38755e166140f77dd83928e972b3462 /gcc/tree-vrp.c | |
parent | 5504e5d864f7b9c83727669847396c639abdf77b (diff) | |
download | gcc-1f6eac9041e87e273c2b955a309ed44364f41544.zip gcc-1f6eac9041e87e273c2b955a309ed44364f41544.tar.gz gcc-1f6eac9041e87e273c2b955a309ed44364f41544.tar.bz2 |
re PR target/29776 (result of ffs/clz/ctz/popcount/parity are already sign-extended)
PR target/29776
* fold-const.c (tree_call_nonnegative_warnv_p): Return true
for BUILT_IN_C{LZ,LRSB}*.
* tree.h (CASE_INT_FN): Add FN##IMAX case.
* tree-vrp.c (extract_range_basic): Handle
BUILT_IN_{FFS,PARITY,POPCOUNT,C{LZ,TZ,LRSB}}*. For
BUILT_IN_CONSTANT_P if argument isn't (D) of PARM_DECL,
fall thru to code calling set_value*.
* builtins.c (expand_builtin): Remove *IMAX cases.
(fold_builtin_bitop): For BUILT_IN_CLRSB* return NULL_TREE
if width is bigger than 2*HWI.
* libgcc2.c (__floattisf): Avoid undefined signed overflow.
* gcc.dg/tree-ssa/vrp89.c: New test.
From-SVN: r200731
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 192 |
1 files changed, 178 insertions, 14 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index ec7ef8f..ca9d8bd 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -3565,20 +3565,184 @@ extract_range_basic (value_range_t *vr, gimple stmt) bool sop = false; tree type = gimple_expr_type (stmt); - /* If the call is __builtin_constant_p and the argument is a - function parameter resolve it to false. This avoids bogus - array bound warnings. - ??? We could do this as early as inlining is finished. */ - if (gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P)) - { - tree arg = gimple_call_arg (stmt, 0); - if (TREE_CODE (arg) == SSA_NAME - && SSA_NAME_IS_DEFAULT_DEF (arg) - && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL) - set_value_range_to_null (vr, type); - } - else if (INTEGRAL_TYPE_P (type) - && gimple_stmt_nonnegative_warnv_p (stmt, &sop)) + if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) + { + tree fndecl = gimple_call_fndecl (stmt), arg; + int mini, maxi, zerov = 0, prec; + + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_CONSTANT_P: + /* If the call is __builtin_constant_p and the argument is a + function parameter resolve it to false. This avoids bogus + array bound warnings. + ??? We could do this as early as inlining is finished. */ + arg = gimple_call_arg (stmt, 0); + if (TREE_CODE (arg) == SSA_NAME + && SSA_NAME_IS_DEFAULT_DEF (arg) + && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL) + { + set_value_range_to_null (vr, type); + return; + } + break; + /* Both __builtin_ffs* and __builtin_popcount return + [0, prec]. */ + CASE_INT_FN (BUILT_IN_FFS): + CASE_INT_FN (BUILT_IN_POPCOUNT): + arg = gimple_call_arg (stmt, 0); + prec = TYPE_PRECISION (TREE_TYPE (arg)); + mini = 0; + maxi = prec; + if (TREE_CODE (arg) == SSA_NAME) + { + value_range_t *vr0 = get_value_range (arg); + /* If arg is non-zero, then ffs or popcount + are non-zero. */ + if (((vr0->type == VR_RANGE + && integer_nonzerop (vr0->min)) + || (vr0->type == VR_ANTI_RANGE + && integer_zerop (vr0->min))) + && !TREE_OVERFLOW (vr0->min)) + mini = 1; + /* If some high bits are known to be zero, + we can decrease the maximum. */ + if (vr0->type == VR_RANGE + && TREE_CODE (vr0->max) == INTEGER_CST + && !TREE_OVERFLOW (vr0->max)) + maxi = tree_floor_log2 (vr0->max) + 1; + } + goto bitop_builtin; + /* __builtin_parity* returns [0, 1]. */ + CASE_INT_FN (BUILT_IN_PARITY): + mini = 0; + maxi = 1; + goto bitop_builtin; + /* __builtin_c[lt]z* return [0, prec-1], except for + when the argument is 0, but that is undefined behavior. + On many targets where the CLZ RTL or optab value is defined + for 0 the value is prec, so include that in the range + by default. */ + CASE_INT_FN (BUILT_IN_CLZ): + arg = gimple_call_arg (stmt, 0); + prec = TYPE_PRECISION (TREE_TYPE (arg)); + mini = 0; + maxi = prec; + if (optab_handler (clz_optab, TYPE_MODE (TREE_TYPE (arg))) + != CODE_FOR_nothing + && CLZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (TREE_TYPE (arg)), + zerov) + /* Handle only the single common value. */ + && zerov != prec) + /* Magic value to give up, unless vr0 proves + arg is non-zero. */ + mini = -2; + if (TREE_CODE (arg) == SSA_NAME) + { + value_range_t *vr0 = get_value_range (arg); + /* From clz of VR_RANGE minimum we can compute + result maximum. */ + if (vr0->type == VR_RANGE + && TREE_CODE (vr0->min) == INTEGER_CST + && !TREE_OVERFLOW (vr0->min)) + { + maxi = prec - 1 - tree_floor_log2 (vr0->min); + if (maxi != prec) + mini = 0; + } + else if (vr0->type == VR_ANTI_RANGE + && integer_zerop (vr0->min) + && !TREE_OVERFLOW (vr0->min)) + { + maxi = prec - 1; + mini = 0; + } + if (mini == -2) + break; + /* From clz of VR_RANGE maximum we can compute + result minimum. */ + if (vr0->type == VR_RANGE + && TREE_CODE (vr0->max) == INTEGER_CST + && !TREE_OVERFLOW (vr0->max)) + { + mini = prec - 1 - tree_floor_log2 (vr0->max); + if (mini == prec) + break; + } + } + if (mini == -2) + break; + goto bitop_builtin; + /* __builtin_ctz* return [0, prec-1], except for + when the argument is 0, but that is undefined behavior. + If there is a ctz optab for this mode and + CTZ_DEFINED_VALUE_AT_ZERO, include that in the range, + otherwise just assume 0 won't be seen. */ + CASE_INT_FN (BUILT_IN_CTZ): + arg = gimple_call_arg (stmt, 0); + prec = TYPE_PRECISION (TREE_TYPE (arg)); + mini = 0; + maxi = prec - 1; + if (optab_handler (ctz_optab, TYPE_MODE (TREE_TYPE (arg))) + != CODE_FOR_nothing + && CTZ_DEFINED_VALUE_AT_ZERO (TYPE_MODE (TREE_TYPE (arg)), + zerov)) + { + /* Handle only the two common values. */ + if (zerov == -1) + mini = -1; + else if (zerov == prec) + maxi = prec; + else + /* Magic value to give up, unless vr0 proves + arg is non-zero. */ + mini = -2; + } + if (TREE_CODE (arg) == SSA_NAME) + { + value_range_t *vr0 = get_value_range (arg); + /* If arg is non-zero, then use [0, prec - 1]. */ + if (((vr0->type == VR_RANGE + && integer_nonzerop (vr0->min)) + || (vr0->type == VR_ANTI_RANGE + && integer_zerop (vr0->min))) + && !TREE_OVERFLOW (vr0->min)) + { + mini = 0; + maxi = prec - 1; + } + /* If some high bits are known to be zero, + we can decrease the result maximum. */ + if (vr0->type == VR_RANGE + && TREE_CODE (vr0->max) == INTEGER_CST + && !TREE_OVERFLOW (vr0->max)) + { + maxi = tree_floor_log2 (vr0->max); + /* For vr0 [0, 0] give up. */ + if (maxi == -1) + break; + } + } + if (mini == -2) + break; + goto bitop_builtin; + /* __builtin_clrsb* returns [0, prec-1]. */ + CASE_INT_FN (BUILT_IN_CLRSB): + arg = gimple_call_arg (stmt, 0); + prec = TYPE_PRECISION (TREE_TYPE (arg)); + mini = 0; + maxi = prec - 1; + goto bitop_builtin; + bitop_builtin: + set_value_range (vr, VR_RANGE, build_int_cst (type, mini), + build_int_cst (type, maxi), NULL); + return; + default: + break; + } + } + if (INTEGRAL_TYPE_P (type) + && gimple_stmt_nonnegative_warnv_p (stmt, &sop)) set_value_range_to_nonnegative (vr, type, sop || stmt_overflow_infinity (stmt)); else if (vrp_stmt_computes_nonzero (stmt, &sop) |