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