https://gcc.gnu.org/g:0b89341f124eadc689682d01193309225adfec23

commit r15-5887-g0b89341f124eadc689682d01193309225adfec23
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Tue Dec 3 11:16:37 2024 +0100

    bitintlower: Fix up ?ROTATE_EXPR lowering [PR117847]
    
    In the ?ROTATE_EXPR lowering I forgot to handle rotation by 0 correctly.
    INTEGER_CST 0 is very unlikely, it would be probably folded away, but
    a non-constant count can't use just p - n because then the shift count
    is out of bounds for zero.
    
    In the FE I use n == 0 ? x : (x << n) | (x >> (p - n)) but bitintlower
    here isn't prepared at this point to have bb split and am not sure if
    using COND_EXPR is a good idea either, so the patch uses (p - n) % p.
    Perhaps I should just disable lowering the rotate in the FE for the
    non-mode precision BITINT_TYPEs too.
    
    2024-12-03  Jakub Jelinek  <ja...@redhat.com>
    
            PR middle-end/117847
            * gimple-lower-bitint.cc (gimple_lower_bitint) <case LROTATE_EXPR>:
            Use m = (p - n) % p instead of m = p - n for the other shift count.
    
            * gcc.dg/torture/bitint-75.c: New test.

Diff:
---
 gcc/gimple-lower-bitint.cc               | 13 +++++++++++--
 gcc/testsuite/gcc.dg/torture/bitint-75.c | 27 +++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc
index 1b7c2f46230c..7fa679b731ba 100644
--- a/gcc/gimple-lower-bitint.cc
+++ b/gcc/gimple-lower-bitint.cc
@@ -6233,11 +6233,20 @@ gimple_lower_bitint (void)
                  tree p = build_int_cst (TREE_TYPE (n),
                                          TYPE_PRECISION (type));
                  if (TREE_CODE (n) == INTEGER_CST)
-                   m = fold_build2 (MINUS_EXPR, TREE_TYPE (n), p, n);
+                   {
+                     if (integer_zerop (n))
+                       m = n;
+                     else
+                       m = fold_build2 (MINUS_EXPR, TREE_TYPE (n), p, n);
+                   }
                  else
                    {
+                     tree tem = make_ssa_name (TREE_TYPE (n));
+                     g = gimple_build_assign (tem, MINUS_EXPR, p, n);
+                     gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+                     gimple_set_location (g, loc);
                      m = make_ssa_name (TREE_TYPE (n));
-                     g = gimple_build_assign (m, MINUS_EXPR, p, n);
+                     g = gimple_build_assign (m, TRUNC_MOD_EXPR, tem, p);
                      gsi_insert_before (&gsi, g, GSI_SAME_STMT);
                      gimple_set_location (g, loc);
                    }
diff --git a/gcc/testsuite/gcc.dg/torture/bitint-75.c 
b/gcc/testsuite/gcc.dg/torture/bitint-75.c
new file mode 100644
index 000000000000..365e6d623c15
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bitint-75.c
@@ -0,0 +1,27 @@
+/* PR middle-end/117847 */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c23" } */
+/* { dg-skip-if "" { ! run_expensive_tests }  { "*" } { "-O0" "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __BITINT_MAXWIDTH__ >= 512
+typedef unsigned _BitInt(512) B;
+
+__attribute__((noipa)) B
+foo (B a, int r)
+{
+  B b = __builtin_stdc_rotate_left (a, r);
+  return b;
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 512
+  B a = 
0x4ad4fdecc8717d7c6f8b1afb82fdb742477ef2ab34057d1dcc79ba30c38a352dea3253c8c25126d98da02213ad54b90d2998f947941ea4b45e71c61dc1fe3192uwb;
+  B x = foo (a, 0);
+  if (x != a)
+    __builtin_abort ();
+#endif
+}

Reply via email to