]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Adjust ranges for to_upper and to_lower.
authorAndrew MacLeod <amacleod@redhat.com>
Mon, 26 Jul 2021 13:40:32 +0000 (09:40 -0400)
committerAndrew MacLeod <amacleod@redhat.com>
Mon, 26 Jul 2021 18:14:30 +0000 (14:14 -0400)
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.

gcc/gimple-range-fold.cc
gcc/testsuite/gcc.dg/pr78888.c [new file with mode: 0644]

index f95af3d5866667c45abc60f6445b73412f7517db..8465b4a82f64fe703846a1705077e21371cd0352 100644 (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].
diff --git a/gcc/testsuite/gcc.dg/pr78888.c b/gcc/testsuite/gcc.dg/pr78888.c
new file mode 100644 (file)
index 0000000..77a130c
--- /dev/null
@@ -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"} } */