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
This commit is contained in:
Jakub Jelinek 2013-07-06 11:34:17 +02:00 committed by Jakub Jelinek
parent 5504e5d864
commit 1f6eac9041
9 changed files with 263 additions and 20 deletions

View File

@ -1,3 +1,17 @@
2013-07-06 Jakub Jelinek <jakub@redhat.com>
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.
2013-07-05 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/55342

View File

@ -6107,7 +6107,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
CASE_INT_FN (BUILT_IN_FFS):
case BUILT_IN_FFSIMAX:
target = expand_builtin_unop (target_mode, exp, target,
subtarget, ffs_optab);
if (target)
@ -6115,7 +6114,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
CASE_INT_FN (BUILT_IN_CLZ):
case BUILT_IN_CLZIMAX:
target = expand_builtin_unop (target_mode, exp, target,
subtarget, clz_optab);
if (target)
@ -6123,7 +6121,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
CASE_INT_FN (BUILT_IN_CTZ):
case BUILT_IN_CTZIMAX:
target = expand_builtin_unop (target_mode, exp, target,
subtarget, ctz_optab);
if (target)
@ -6131,7 +6128,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
CASE_INT_FN (BUILT_IN_CLRSB):
case BUILT_IN_CLRSBIMAX:
target = expand_builtin_unop (target_mode, exp, target,
subtarget, clrsb_optab);
if (target)
@ -6139,7 +6135,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
CASE_INT_FN (BUILT_IN_POPCOUNT):
case BUILT_IN_POPCOUNTIMAX:
target = expand_builtin_unop (target_mode, exp, target,
subtarget, popcount_optab);
if (target)
@ -6147,7 +6142,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break;
CASE_INT_FN (BUILT_IN_PARITY):
case BUILT_IN_PARITYIMAX:
target = expand_builtin_unop (target_mode, exp, target,
subtarget, parity_optab);
if (target)
@ -8152,6 +8146,8 @@ fold_builtin_bitop (tree fndecl, tree arg)
break;
CASE_INT_FN (BUILT_IN_CLRSB):
if (width > 2 * HOST_BITS_PER_WIDE_INT)
return NULL_TREE;
if (width > HOST_BITS_PER_WIDE_INT
&& (hi & ((unsigned HOST_WIDE_INT) 1
<< (width - HOST_BITS_PER_WIDE_INT - 1))) != 0)

View File

@ -15606,6 +15606,8 @@ tree_call_nonnegative_warnv_p (tree type, tree fndecl,
CASE_INT_FN (BUILT_IN_FFS):
CASE_INT_FN (BUILT_IN_PARITY):
CASE_INT_FN (BUILT_IN_POPCOUNT):
CASE_INT_FN (BUILT_IN_CLZ):
CASE_INT_FN (BUILT_IN_CLRSB):
case BUILT_IN_BSWAP32:
case BUILT_IN_BSWAP64:
/* Always true. */

View File

@ -1,3 +1,8 @@
2013-07-06 Jakub Jelinek <jakub@redhat.com>
PR target/29776
* gcc.dg/tree-ssa/vrp89.c: New test.
2013-07-06 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/28262

View File

@ -0,0 +1,57 @@
/* PR target/29776 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1" } */
/* { dg-final { scan-tree-dump-not "link_error" "vrp1"} } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */
#define A(fn, arg, min, max) \
if (__builtin_##fn (arg) < min || __builtin_##fn (arg) > max) \
link_error ();
#define B(fn, min, max) \
A (fn, a, min, max) A (fn##l, b, min, max) A (fn##ll, c, min, max)
#define C(fn, min, sub) \
A (fn, a, min, ((int) sizeof (a) * __CHAR_BIT__ - sub)) \
A (fn##l, b, min, ((int) sizeof (b) * __CHAR_BIT__ - sub)) \
A (fn##ll, c, min, ((int) sizeof (c) * __CHAR_BIT__ - sub))
#define D(fn, sub1, sub2) \
A (fn, a, ((int) sizeof (a) * __CHAR_BIT__ - sub1), \
((int) sizeof (a) * __CHAR_BIT__ - sub2)) \
A (fn##l, b, ((int) sizeof (b) * __CHAR_BIT__ - sub1), \
((int) sizeof (b) * __CHAR_BIT__ - sub2)) \
A (fn##ll, c, ((int) sizeof (c) * __CHAR_BIT__ - sub1), \
((int) sizeof (c) * __CHAR_BIT__ - sub2))
extern void link_error (void);
unsigned int d;
unsigned long e;
unsigned long long f;
void
foo (unsigned int a, unsigned long b, unsigned long long c)
{
B (parity, 0, 1)
C (ffs, 0, 0)
C (popcount, 0, 0)
C (clz, 0, 0)
C (ctz, -1, 0)
a &= 63;
b &= 63;
c &= 63;
B (ffs, 0, 6)
B (popcount, 0, 6)
a += 3; b += 3; c += 3;
B (ffs, 1, 7)
B (popcount, 1, 7)
a = 32U + (d & 1023U);
b = 32UL + (e & 1023UL);
c = 32ULL + (f & 1023ULL);
D (clz, 11, 6)
B (ctz, 0, 10)
}
void
bar (int a, long b, long long c)
{
C (clrsb, 0, 1)
}

View File

@ -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))
if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
{
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);
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;
}
}
else if (INTEGRAL_TYPE_P (type)
&& gimple_stmt_nonnegative_warnv_p (stmt, &sop))
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)

View File

@ -322,7 +322,7 @@ extern const char * built_in_names[(int) END_BUILTINS];
#define CASE_FLT_FN(FN) case FN: case FN##F: case FN##L
#define CASE_FLT_FN_REENT(FN) case FN##_R: case FN##F_R: case FN##L_R
#define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL
#define CASE_INT_FN(FN) case FN: case FN##L: case FN##LL: case FN##IMAX
/* In an OMP_CLAUSE node. */

View File

@ -1,3 +1,8 @@
2013-07-06 Jakub Jelinek <jakub@redhat.com>
PR target/29776
* libgcc2.c (__floattisf): Avoid undefined signed overflow.
2013-06-28 Jakub Jelinek <jakub@redhat.com>
PR middle-end/36041

View File

@ -1571,7 +1571,7 @@ FUNC (DWtype u)
/* Otherwise, find the power of two. */
Wtype hi = u >> W_TYPE_SIZE;
if (hi < 0)
hi = -hi;
hi = -(UWtype) hi;
UWtype count, shift;
count_leading_zeros (count, hi);