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;
}