The following testcase is miscompiled. The problem is in the last_ovf step.
The second operand has signed _BitInt(513) type but has the MSB clear,
so range_to_prec returns 512 for it (i.e. it fits into unsigned
_BitInt(512)). Because of that the last step actually doesn't need to get
the most significant bit from the second operand, but the code was deciding
what to use purely from TYPE_UNSIGNED (type1) - if unsigned, use 0,
otherwise sign-extend the last processed bit; but that in this case was set.
We don't want to treat the positive operand as if it was negative regardless
of the bit below that precision, and precN >= 0 indicates that the operand
is in the [0, inf) range.
2024-09-03 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/116501
* gimple-lower-bitint.cc (bitint_large_huge::lower_addsub_overflow):
In the last_ovf case, use build_zero_cst operand not just when
TYPE_UNSIGNED (typeN), but also when precN >= 0.
* gcc.dg/torture/bitint-73.c: New test.
else
{
m_data_cnt = data_cnt;
- if (TYPE_UNSIGNED (type0))
+ if (TYPE_UNSIGNED (type0) || prec0 >= 0)
rhs1 = build_zero_cst (m_limb_type);
else
{
rhs1 = add_cast (m_limb_type, gimple_assign_lhs (g));
}
}
- if (TYPE_UNSIGNED (type1))
+ if (TYPE_UNSIGNED (type1) || prec1 >= 0)
rhs2 = build_zero_cst (m_limb_type);
else
{
--- /dev/null
+/* PR tree-optimization/116501 */
+/* { dg-do run { target bitint575 } } */
+/* { dg-options "-std=c23" } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+_BitInt (4) a;
+
+int
+foo (_BitInt(513) b)
+{
+ return __builtin_sub_overflow_p (a, b, (_BitInt (511)) 0);
+}
+
+int
+main ()
+{
+ if (!foo (0xffffffffffffffff0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff0000000000000000wb))
+ __builtin_abort ();
+}