https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127345

--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Completely untested patch, just no idea what exactly to do with update_bitmask.

--- a/gcc/testsuite/gcc.dg/torture/pr127345.c   2026-09-14 13:50:06.291692521
+0200
+++ b/gcc/testsuite/gcc.dg/torture/pr127345.c   2026-09-14 13:49:46.180950918
+0200
@@ -0,0 +1,19 @@
+/* PR tree-optimization/127345 */
+
+int a;
+long b;
+
+int
+main ()
+{
+  long d = 0;
+  struct { _BitInt (3) c; } e;
+  if (!b)
+    {
+      for (; a; d = 1)
+       ;
+      e.c = d - 1;
+    }
+  if ((unsigned long long) (long long) e.c != -1ULL)
+    __builtin_abort ();
+}
--- a/gcc/range-op.cc   2026-09-03 09:43:55.775409905 +0200
+++ b/gcc/range-op.cc   2026-09-14 13:42:34.763515024 +0200
@@ -3347,16 +3347,21 @@ operator_cast::op1_range (irange &r, tre
   return true;
 }

-// VIEW_CONVERT_EXPR works like a cast between integral values.
-// If the number of bits are not the same, behaviour is undefined,
-// so cast behaviour still works.
+// VIEW_CONVERT_EXPR works like a cast between integral values
+// in some cases.

 bool
 operator_view::fold_range (irange &r, tree type,
                           const irange &op1, const irange &op2,
                           relation_trio rel) const
 {
-  return m_cast.fold_range (r, type, op1, op2, rel);
+  if (op1.undefined_p ())
+    return false;
+  unsigned lhs_prec = TYPE_PRECISION (type);
+  unsigned op1_prec = TYPE_PRECISION (op1.type ());
+  if (lhs_prec <= op1_prec || TREE_CODE (op1.type ()) == BOOLEAN_TYPE)
+    return m_cast.fold_range (r, type, op1, op2, rel);
+  return false;
 }

 bool
@@ -3364,14 +3369,27 @@ operator_view::fold_range (prange &r, tr
                           const prange &op1, const prange &op2,
                           relation_trio rel) const
 {
-  return m_cast.fold_range (r, type, op1, op2, rel);
+  if (op1.undefined_p ())
+    return false;
+  unsigned lhs_prec = TYPE_PRECISION (type);
+  unsigned op1_prec = TYPE_PRECISION (op1.type ());
+  if (lhs_prec <= op1_prec)
+    return m_cast.fold_range (r, type, op1, op2, rel);
+  return false;
 }
+
 bool
 operator_view::fold_range (irange &r, tree type,
                           const prange &op1, const irange &op2,
                           relation_trio rel) const
 {
-  return m_cast.fold_range (r, type, op1, op2, rel);
+  if (op1.undefined_p ())
+    return false;
+  unsigned lhs_prec = TYPE_PRECISION (type);
+  unsigned op1_prec = TYPE_PRECISION (op1.type ());
+  if (lhs_prec <= op1_prec)
+    return m_cast.fold_range (r, type, op1, op2, rel);
+  return false;
 }

 bool
@@ -3379,7 +3397,13 @@ operator_view::fold_range (prange &r, tr
                           const irange &op1, const prange &op2,
                           relation_trio rel) const
 {
-  return m_cast.fold_range (r, type, op1, op2, rel);
+  if (op1.undefined_p ())
+    return false;
+  unsigned lhs_prec = TYPE_PRECISION (type);
+  unsigned op1_prec = TYPE_PRECISION (op1.type ());
+  if (lhs_prec <= op1_prec)
+    return m_cast.fold_range (r, type, op1, op2, rel);
+  return false;
 }

 bool
@@ -3387,7 +3411,13 @@ operator_view::op1_range (irange &r, tre
                          const irange &lhs, const irange &op2,
                          relation_trio rel) const
 {
-  return m_cast.op1_range (r, type, lhs, op2, rel);
+  if (lhs.undefined_p ())
+    return false;
+  unsigned op1_prec = TYPE_PRECISION (type);
+  unsigned lhs_prec = TYPE_PRECISION (lhs.type ());
+  if (lhs_prec >= op1_prec)
+    return m_cast.op1_range (r, type, lhs, op2, rel);
+  return false;
 }

 bool
@@ -3395,7 +3425,13 @@ operator_view::op1_range (prange &r, tre
                          const prange &lhs, const prange &op2,
                          relation_trio rel) const
 {
-  return m_cast.op1_range (r, type, lhs, op2, rel);
+  if (lhs.undefined_p ())
+    return false;
+  unsigned op1_prec = TYPE_PRECISION (type);
+  unsigned lhs_prec = TYPE_PRECISION (lhs.type ());
+  if (lhs_prec >= op1_prec)
+    return m_cast.op1_range (r, type, lhs, op2, rel);
+  return false;
 }

 bool
@@ -3403,7 +3439,13 @@ operator_view::op1_range (irange &r, tre
                          const prange &lhs, const irange &op2,
                          relation_trio rel) const
 {
-  return m_cast.op1_range (r, type, lhs, op2, rel);
+  if (lhs.undefined_p ())
+    return false;
+  unsigned op1_prec = TYPE_PRECISION (type);
+  unsigned lhs_prec = TYPE_PRECISION (lhs.type ());
+  if (lhs_prec >= op1_prec)
+    return m_cast.op1_range (r, type, lhs, op2, rel);
+  return false;
 }

 bool
@@ -3411,7 +3453,13 @@ operator_view::op1_range (prange &r, tre
                          const irange &lhs, const prange &op2,
                          relation_trio rel) const
 {
-  return m_cast.op1_range (r, type, lhs, op2, rel);
+  if (lhs.undefined_p ())
+    return false;
+  unsigned op1_prec = TYPE_PRECISION (type);
+  unsigned lhs_prec = TYPE_PRECISION (lhs.type ());
+  if (lhs_prec >= op1_prec)
+    return m_cast.op1_range (r, type, lhs, op2, rel);
+  return false;
 }

 void

Reply via email to