Adjust ranges for to_upper and to_lower.

Exclude lower case chars from to_upper and upper case chars from to_lower.

	gcc/
	PR tree-optimization/78888
	* gimple-range-fold.cc (fold_using_range::range_of_builtin_call): Add cases
	for CFN_BUILT_IN_TOUPPER and CFN_BUILT_IN_TOLOWER.

	gcc/testsuite/
	* gcc.dg/pr78888.c: New.
This commit is contained in:
Andrew MacLeod 2021-07-26 09:40:32 -04:00
parent cf5f544227
commit 1ce0b26e6e
2 changed files with 61 additions and 0 deletions

View File

@ -868,6 +868,38 @@ fold_using_range::range_of_builtin_call (irange &r, gcall *call,
}
break;
case CFN_BUILT_IN_TOUPPER:
{
arg = gimple_call_arg (call, 0);
if (!src.get_operand (r, arg))
return false;
// Return the range passed in without any lower case characters,
// but including all the upper case ones.
int_range<2> exclude (build_int_cst (type, 'a'),
build_int_cst (type, 'z'), VR_ANTI_RANGE);
r.intersect (exclude);
int_range<2> uppers (build_int_cst (type, 'A'),
build_int_cst (type, 'Z'));
r.union_ (uppers);
return true;
}
case CFN_BUILT_IN_TOLOWER:
{
arg = gimple_call_arg (call, 0);
if (!src.get_operand (r, arg))
return false;
// Return the range passed in without any upper case characters,
// but including all the lower case ones.
int_range<2> exclude (build_int_cst (type, 'A'),
build_int_cst (type, 'Z'), VR_ANTI_RANGE);
r.intersect (exclude);
int_range<2> lowers (build_int_cst (type, 'a'),
build_int_cst (type, 'z'));
r.union_ (lowers);
return true;
}
CASE_CFN_FFS:
CASE_CFN_POPCOUNT:
// __builtin_ffs* and __builtin_popcount* return [0, prec].

View File

@ -0,0 +1,29 @@
/* PR tree-optimization/78888 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-evrp" } */
void kill (void);
void keep (void);
void g (int x)
{
if (__builtin_toupper ((unsigned char)x) == 'a')
kill ();
if (__builtin_toupper ((unsigned char)x) == 'z')
kill ();
if (__builtin_tolower ((unsigned char)x) == 'A')
kill ();
if (__builtin_tolower ((unsigned char)x) == 'Z')
kill ();
if (__builtin_toupper ((unsigned char)x) == 'A')
keep ();
if (__builtin_toupper ((unsigned char)x) == 'Z')
keep ();
if (__builtin_tolower ((unsigned char)x) == 'a')
keep ();
if (__builtin_tolower ((unsigned char)x) == 'z')
keep ();
}
/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */
/* { dg-final { scan-tree-dump-times "keep" 4 "evrp"} } */