Hi, The attached patch adds value-range info for __builtin_tolower and __builtin_toupper. In the patch, I have just settled for anti-range ~['a', 'z'] for return value of toupper. Would that be correct albeit imprecise ?
A more precise range would be: [0, UCHAR_MAX] intersect ~['a', 'z'] union EOF as mentioned in PR. I am not sure though if it's possible for a SSA_NAME to have multiple disjoint ranges ? Bootstrap+tested on x86_64-unknown-linux-gnu. Thanks, Prathamesh
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr78888.c b/gcc/testsuite/gcc.dg/tree-ssa/pr78888.c new file mode 100644 index 00000000000..2bcddf1f2c3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr78888.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp-slim" } */ + +void g (int x) +{ + if (__builtin_toupper ((unsigned char)x) == 'a') + __builtin_abort (); +} + +void h (int x) +{ + if (__builtin_tolower ((unsigned char)x) == 'A') + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump-not "__builtin_abort" "evrp" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 79a29bf0efb..7137a4c52ec 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -3778,6 +3778,19 @@ extract_range_basic (value_range *vr, gimple *stmt) return; } break; + case CFN_BUILT_IN_TOUPPER: + case CFN_BUILT_IN_TOLOWER: + if (tree lhs = gimple_call_lhs (stmt)) + { + tree type = TREE_TYPE (lhs); + unsigned char min = (cfn == CFN_BUILT_IN_TOUPPER) ? 'a' : 'A'; + unsigned char max = (cfn == CFN_BUILT_IN_TOUPPER) ? 'z' : 'Z'; + tree range_min = build_int_cstu (type, min); + tree range_max = build_int_cstu (type, max); + set_value_range (vr, VR_ANTI_RANGE, range_min, range_max, NULL); + return; + } + break; default: break; }