https://gcc.gnu.org/g:3d102b7a40bd179c93eccc31b74f95c69f81f45e

commit r16-4603-g3d102b7a40bd179c93eccc31b74f95c69f81f45e
Author: Andrew MacLeod <[email protected]>
Date:   Tue Oct 21 16:05:22 2025 -0400

    Create and apply bitmasks for truncating casts.
    
    When folding a cast, we were not applying the bitmask if we reached
    a VARYING result.
    We were also not creating a bitmask to represent the lower bits of a
    truncating cast in op1_range.  So GORI was losing bits.
    
            PR tree-optimization/118254
            PR tree-optimization/114331
            gcc/
            * range-op.cc (operator_cast::fold_range): When VARYING is
            reached, update the bitmask if we reach VARYING.
            (operator_cast::op1_range): For truncating casts, create a
            bitmask bit in LHS.
    
            gcc/testsuite/
            * gcc.dg/pr114331.c: New.
            * gcc.dg/pr118254.c: New.

Diff:
---
 gcc/range-op.cc                 | 22 +++++++++++++++++++++-
 gcc/testsuite/gcc.dg/pr114331.c | 20 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/pr118254.c | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 1f91066a44e7..762fd349e5f7 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -3103,8 +3103,9 @@ operator_cast::fold_range (irange &r, tree type 
ATTRIBUTE_UNUSED,
       int_range_max tmp;
       fold_pair (tmp, x, inner, outer);
       r.union_ (tmp);
+      // If we hit varying, go update the bitmask.
       if (r.varying_p ())
-       return true;
+       break;
     }
 
   update_bitmask (r, inner, outer);
@@ -3204,6 +3205,25 @@ operator_cast::op1_range (irange &r, tree type,
        }
       // And intersect with any known value passed in the extra operand.
       r.intersect (op2);
+      if (r.undefined_p ())
+       return true;
+
+      // Now create a bitmask indicating that the lower bit must match the
+      // bits in the LHS.   Zero-extend LHS bitmask to precision of op1.
+      irange_bitmask bm = lhs.get_bitmask ();
+      wide_int mask = wide_int::from (bm.mask (), TYPE_PRECISION (type),
+                                     UNSIGNED);
+      wide_int value = wide_int::from (bm.value (), TYPE_PRECISION (type),
+                                      UNSIGNED);
+
+      // Set then additonal unknown bits in mask.
+      wide_int lim = wi::mask (TYPE_PRECISION (lhs_type), true,
+                              TYPE_PRECISION (type));
+      mask = mask | lim;
+
+      // Now set the new bitmask for the range.
+      irange_bitmask new_bm (value, mask);
+      r.update_bitmask (new_bm);
       return true;
     }
 
diff --git a/gcc/testsuite/gcc.dg/pr114331.c b/gcc/testsuite/gcc.dg/pr114331.c
new file mode 100644
index 000000000000..e93289e651b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr114331.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int src(int num) {
+    switch((short)num){
+        case 111:
+         /* Should fold to 110.  */
+          return num & 0xfffe;
+        case 267:
+        case 204:
+        case 263:
+          return 0;
+        default:
+          return 0;
+    }
+}
+
+
+/* { dg-final { scan-tree-dump "110"  "optimized" } } */
+
diff --git a/gcc/testsuite/gcc.dg/pr118254.c b/gcc/testsuite/gcc.dg/pr118254.c
new file mode 100644
index 000000000000..5a0553ba6f95
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr118254.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void foo(void);
+int il=1000;
+
+int m1(void)
+{
+  short t = il;
+  unsigned t1 = t;
+  if (t1 == 0) {
+    char b = t1;
+    if (b != 1)
+      return 0;
+    foo();
+  }
+  return 0;
+}
+
+int m2(void)
+{
+  short t = il;
+  unsigned t1 = t;
+  if (t1 == 0) {
+    char b = il;
+    if (b != 1)
+      return 0;
+    foo();
+  }
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "foo"  "evrp" } } */
+

Reply via email to