https://gcc.gnu.org/g:7ca53f9d86ef5f4c6a49f414f3cdd88d2b8a0bad

commit r17-549-g7ca53f9d86ef5f4c6a49f414f3cdd88d2b8a0bad
Author: Jakub Jelinek <[email protected]>
Date:   Sat May 16 10:50:00 2026 +0200

    tree-ssa-ccp: Fix up __builtin_bitreverse* handling [PR50481]
    
    The committed __builtin_bitreverse* patch mishandled the
    bitwise CCP handling, it is true that BUILT_IN_BITREVERSE* can be
    handled there similarly to BUILT_IN_BSWAP*, but not exactly, for
    the latter we need (and do) bswap the value and mask constants,
    while for the former we obviously need to bitreverse them instead.
    
    2026-05-16  Jakub Jelinek  <[email protected]>
    
            PR target/50481
            * tree-ssa-ccp.cc (evaluate_stmt): Fix up
            BUILT_IN_BITREVERSE{8,16,32,64} handling.
    
            * gcc.dg/builtin-bitreverse-3.c: New test.
    
    Reviewed-by: Andrew Pinski <[email protected]>

Diff:
---
 gcc/testsuite/gcc.dg/builtin-bitreverse-3.c | 31 +++++++++++++++++++++++++++++
 gcc/tree-ssa-ccp.cc                         | 31 +++++++++++++++++++++++++----
 2 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/builtin-bitreverse-3.c 
b/gcc/testsuite/gcc.dg/builtin-bitreverse-3.c
new file mode 100644
index 000000000000..bd5601292b6c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/builtin-bitreverse-3.c
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#if __SIZEOF_INT__ == 4 && __CHAR_BIT__ == 8
+[[gnu::noipa]] bool
+foo (unsigned x)
+{
+  x &= 0x499a750a;
+  x |= 0x5a7c04f;
+  x = __builtin_bitreverse32 (x);
+  return (x & ~0x351848) == 0x4fc0a705;
+}
+
+[[gnu::noipa]] bool
+bar (unsigned x)
+{
+  x &= 0x499a750a;
+  x |= 0x5a7c04f;
+  x = __builtin_bitreverse32 (x);
+  return (x & ~0xac1812) == 0xf203e5a0;
+}
+#endif
+
+int
+main ()
+{
+#if __SIZEOF_INT__ == 4 && __CHAR_BIT__ == 8
+  if (foo (~0) || !bar (~0))
+    __builtin_abort ();
+#endif
+}
diff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc
index 974bef17832f..891fcc12cafc 100644
--- a/gcc/tree-ssa-ccp.cc
+++ b/gcc/tree-ssa-ccp.cc
@@ -2435,10 +2435,6 @@ evaluate_stmt (gimple *stmt)
            case BUILT_IN_BSWAP32:
            case BUILT_IN_BSWAP64:
            case BUILT_IN_BSWAP128:
-           case BUILT_IN_BITREVERSE8:
-           case BUILT_IN_BITREVERSE16:
-           case BUILT_IN_BITREVERSE32:
-           case BUILT_IN_BITREVERSE64:
              val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
              if (val.lattice_val == UNDEFINED)
                break;
@@ -2466,6 +2462,33 @@ evaluate_stmt (gimple *stmt)
              val.mask = -1;
              break;
 
+           case BUILT_IN_BITREVERSE8:
+           case BUILT_IN_BITREVERSE16:
+           case BUILT_IN_BITREVERSE32:
+           case BUILT_IN_BITREVERSE64:
+             val = get_value_for_expr (gimple_call_arg (stmt, 0), true);
+             if (val.lattice_val == UNDEFINED)
+               break;
+             else if (val.lattice_val == CONSTANT
+                      && val.value
+                      && TREE_CODE (val.value) == INTEGER_CST)
+               {
+                 tree type = TREE_TYPE (gimple_call_lhs (stmt));
+                 int prec = TYPE_PRECISION (type);
+                 wide_int wval = wi::to_wide (val.value);
+                 wval = wide_int::from (wval, prec, UNSIGNED);
+                 wide_int wmask = wide_int::from (val.mask, prec, UNSIGNED);
+                 val.value = wide_int_to_tree (type, wi::bitreverse (wval));
+                 val.mask = widest_int::from (wi::bitreverse (wmask),
+                                              UNSIGNED);
+                 if (wi::sext (val.mask, prec) != -1)
+                   break;
+               }
+             val.lattice_val = VARYING;
+             val.value = NULL_TREE;
+             val.mask = -1;
+             break;
+
            default:;
            }
        }

Reply via email to