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);

Reply via email to