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:
parent
5504e5d864
commit
1f6eac9041
9 changed files with 263 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
57
gcc/testsuite/gcc.dg/tree-ssa/vrp89.c
Normal file
57
gcc/testsuite/gcc.dg/tree-ssa/vrp89.c
Normal 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)
|
||||
}
|
188
gcc/tree-vrp.c
188
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))
|
||||
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)
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue