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> 2013-07-05 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/55342 PR rtl-optimization/55342

View File

@ -6107,7 +6107,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break; break;
CASE_INT_FN (BUILT_IN_FFS): CASE_INT_FN (BUILT_IN_FFS):
case BUILT_IN_FFSIMAX:
target = expand_builtin_unop (target_mode, exp, target, target = expand_builtin_unop (target_mode, exp, target,
subtarget, ffs_optab); subtarget, ffs_optab);
if (target) if (target)
@ -6115,7 +6114,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break; break;
CASE_INT_FN (BUILT_IN_CLZ): CASE_INT_FN (BUILT_IN_CLZ):
case BUILT_IN_CLZIMAX:
target = expand_builtin_unop (target_mode, exp, target, target = expand_builtin_unop (target_mode, exp, target,
subtarget, clz_optab); subtarget, clz_optab);
if (target) if (target)
@ -6123,7 +6121,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break; break;
CASE_INT_FN (BUILT_IN_CTZ): CASE_INT_FN (BUILT_IN_CTZ):
case BUILT_IN_CTZIMAX:
target = expand_builtin_unop (target_mode, exp, target, target = expand_builtin_unop (target_mode, exp, target,
subtarget, ctz_optab); subtarget, ctz_optab);
if (target) if (target)
@ -6131,7 +6128,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break; break;
CASE_INT_FN (BUILT_IN_CLRSB): CASE_INT_FN (BUILT_IN_CLRSB):
case BUILT_IN_CLRSBIMAX:
target = expand_builtin_unop (target_mode, exp, target, target = expand_builtin_unop (target_mode, exp, target,
subtarget, clrsb_optab); subtarget, clrsb_optab);
if (target) if (target)
@ -6139,7 +6135,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break; break;
CASE_INT_FN (BUILT_IN_POPCOUNT): CASE_INT_FN (BUILT_IN_POPCOUNT):
case BUILT_IN_POPCOUNTIMAX:
target = expand_builtin_unop (target_mode, exp, target, target = expand_builtin_unop (target_mode, exp, target,
subtarget, popcount_optab); subtarget, popcount_optab);
if (target) if (target)
@ -6147,7 +6142,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
break; break;
CASE_INT_FN (BUILT_IN_PARITY): CASE_INT_FN (BUILT_IN_PARITY):
case BUILT_IN_PARITYIMAX:
target = expand_builtin_unop (target_mode, exp, target, target = expand_builtin_unop (target_mode, exp, target,
subtarget, parity_optab); subtarget, parity_optab);
if (target) if (target)
@ -8152,6 +8146,8 @@ fold_builtin_bitop (tree fndecl, tree arg)
break; break;
CASE_INT_FN (BUILT_IN_CLRSB): CASE_INT_FN (BUILT_IN_CLRSB):
if (width > 2 * HOST_BITS_PER_WIDE_INT)
return NULL_TREE;
if (width > HOST_BITS_PER_WIDE_INT if (width > HOST_BITS_PER_WIDE_INT
&& (hi & ((unsigned HOST_WIDE_INT) 1 && (hi & ((unsigned HOST_WIDE_INT) 1
<< (width - HOST_BITS_PER_WIDE_INT - 1))) != 0) << (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_FFS):
CASE_INT_FN (BUILT_IN_PARITY): CASE_INT_FN (BUILT_IN_PARITY):
CASE_INT_FN (BUILT_IN_POPCOUNT): 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_BSWAP32:
case BUILT_IN_BSWAP64: case BUILT_IN_BSWAP64:
/* Always true. */ /* 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> 2013-07-06 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/28262 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,19 +3565,183 @@ extract_range_basic (value_range_t *vr, gimple stmt)
bool sop = false; bool sop = false;
tree type = gimple_expr_type (stmt); tree type = gimple_expr_type (stmt);
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 /* If the call is __builtin_constant_p and the argument is a
function parameter resolve it to false. This avoids bogus function parameter resolve it to false. This avoids bogus
array bound warnings. array bound warnings.
??? We could do this as early as inlining is finished. */ ??? We could do this as early as inlining is finished. */
if (gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P)) arg = gimple_call_arg (stmt, 0);
{
tree arg = gimple_call_arg (stmt, 0);
if (TREE_CODE (arg) == SSA_NAME if (TREE_CODE (arg) == SSA_NAME
&& SSA_NAME_IS_DEFAULT_DEF (arg) && SSA_NAME_IS_DEFAULT_DEF (arg)
&& TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL) && TREE_CODE (SSA_NAME_VAR (arg)) == PARM_DECL)
{
set_value_range_to_null (vr, type); set_value_range_to_null (vr, type);
return;
} }
else if (INTEGRAL_TYPE_P (type) 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)) && gimple_stmt_nonnegative_warnv_p (stmt, &sop))
set_value_range_to_nonnegative (vr, type, set_value_range_to_nonnegative (vr, type,
sop || stmt_overflow_infinity (stmt)); sop || stmt_overflow_infinity (stmt));

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(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_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. */ /* 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> 2013-06-28 Jakub Jelinek <jakub@redhat.com>
PR middle-end/36041 PR middle-end/36041

View File

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