https://gcc.gnu.org/g:a6d9810385f6773ff897fc5c4fe80bfbeef1a2fc
commit r17-5403-ga6d9810385f6773ff897fc5c4fe80bfbeef1a2fc Author: Jakub Jelinek <[email protected]> Date: Tue Oct 20 12:11:19 2026 +0200 switchlower: Fix up middle/large/huge BITINT_TYPE handling [PR128003] If a BITINT_TYPE is wider than 64-bit (where we have a guarantee that each switch cluster has at most 64-bit span), jump_table_cluster::emit emits the value - low > high - low condition for clearly no match in this cluster (well, high - low is replaced by maximum of the narrower type). I've mistakenly used !TYPE_OVERFLOW_WRAPS condition whether it needs to be cast to unsigned before that subtraction/comparison. That should have been !TYPE_UNSIGNED, otherwise for -fwrapv values out of the range which are above the range are handled correctly (except the ones that wrap), but values below the range are mishandled, value - low > high - low isn't true for those but it is still out of range. Fixed thusly. 2026-10-20 Jakub Jelinek <[email protected]> PR tree-optimization/128003 * tree-switch-conversion.cc (jump_table_cluster::emit): Cast to unsigned_type_for whenever !TYPE_UNSIGNED rather than when !TYPE_OVERFLOW_WRAPS. * gcc.dg/torture/bitint-113.c: New test. Reviewed-by: Richard Biener <[email protected]> Diff: --- gcc/testsuite/gcc.dg/torture/bitint-113.c | 34 +++++++++++++++++++++++++++++++ gcc/tree-switch-conversion.cc | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.dg/torture/bitint-113.c b/gcc/testsuite/gcc.dg/torture/bitint-113.c new file mode 100644 index 000000000000..b11f474fa21b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/bitint-113.c @@ -0,0 +1,34 @@ +/* PR tree-optimization/128003 */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-fwrapv" } */ + +#if __BITINT_MAXWIDTH__ >= 128 +volatile int v; + +[[gnu::noipa]] void +foo (_BitInt(128) x) +{ + switch (x) + { + case 10: v = 10; break; + case 11: v = 11; break; + case 12: v = 12; break; + case 13: v = 13; break; + case 14: v = 14; break; + case 15: v = 15; break; + case 16: v = 16; break; + case 17: v = 17; break; + default: v = -1; break; + } +} +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 128 + foo (-18446744073709551605wb); + if (v != -1) + __builtin_abort (); +#endif +} diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc index 16564e5ee017..ffd6c7baafca 100644 --- a/gcc/tree-switch-conversion.cc +++ b/gcc/tree-switch-conversion.cc @@ -1550,7 +1550,7 @@ jump_table_cluster::emit (tree index_expr, tree, tree this_low = low, type; gimple *g; gimple_seq seq = NULL; - if (!TYPE_OVERFLOW_WRAPS (TREE_TYPE (index_expr))) + if (!TYPE_UNSIGNED (TREE_TYPE (index_expr))) { type = unsigned_type_for (TREE_TYPE (index_expr)); index_expr = gimple_convert (&seq, type, index_expr);
