Hi!

The following patch extends the widen_bswap and expand_doubleword_bswap
functions to handle also bitreverse, so that all the backends with
say just bitreversesi2 or bitreverse{s,d}i2 can handle also
bitreverse{q,h}i2 and bitreverse{d,t}i2 easily.

Tested on aarch64-linux with just bitreverse{s,d}i2 on
builtin-bitreverse-1.c, ok for trunk if it passes full bootstrap/regtest?

2026-05-18  Jakub Jelinek  <[email protected]>

        PR target/50481
        * optabs.cc (widen_bswap): Add UNOPTAB argument and use it instead
        of hardcoded bswap_optab.
        (expand_doubleword_bswap): Likewise.
        (expand_bitreverse): Use widen_bswap and expand_doubleword_bswap.
        (expand_unop): Adjust widen_bswap and expand_doubleword_bswap callers.

--- gcc/optabs.cc.jj    2026-05-15 09:31:18.383653795 +0200
+++ gcc/optabs.cc       2026-05-18 12:45:19.146458240 +0200
@@ -2895,16 +2895,17 @@ expand_doubleword_parity (scalar_int_mod
 /* Try calculating
        (bswap:narrow x)
    as
-       (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))).  */
+       (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow)))
+   or similarly for bitreverse.  */
 static rtx
-widen_bswap (scalar_int_mode mode, rtx op0, rtx target)
+widen_bswap (scalar_int_mode mode, rtx op0, rtx target, optab unoptab)
 {
   rtx x;
   rtx_insn *last;
   opt_scalar_int_mode wider_mode_iter;
 
   FOR_EACH_WIDER_MODE (wider_mode_iter, mode)
-    if (optab_handler (bswap_optab, wider_mode_iter.require ())
+    if (optab_handler (unoptab, wider_mode_iter.require ())
        != CODE_FOR_nothing)
       break;
 
@@ -2915,7 +2916,7 @@ widen_bswap (scalar_int_mode mode, rtx o
   last = get_last_insn ();
 
   x = widen_operand (op0, wider_mode, mode, true, true);
-  x = expand_unop (wider_mode, bswap_optab, x, NULL_RTX, true);
+  x = expand_unop (wider_mode, unoptab, x, NULL_RTX, true);
 
   gcc_assert (GET_MODE_PRECISION (wider_mode) == GET_MODE_BITSIZE (wider_mode)
              && GET_MODE_PRECISION (mode) == GET_MODE_BITSIZE (mode));
@@ -2937,16 +2938,17 @@ widen_bswap (scalar_int_mode mode, rtx o
   return target;
 }
 
-/* Try calculating bswap as two bswaps of two word-sized operands.  */
+/* Try calculating bswap as two bswaps of two word-sized operands.
+   Similarly for bitreverse.  */
 
 static rtx
-expand_doubleword_bswap (machine_mode mode, rtx op, rtx target)
+expand_doubleword_bswap (machine_mode mode, rtx op, rtx target, optab unoptab)
 {
   rtx t0, t1;
 
-  t1 = expand_unop (word_mode, bswap_optab,
+  t1 = expand_unop (word_mode, unoptab,
                    operand_subword_force (op, 0, mode), NULL_RTX, true);
-  t0 = expand_unop (word_mode, bswap_optab,
+  t0 = expand_unop (word_mode, unoptab,
                    operand_subword_force (op, 1, mode), NULL_RTX, true);
 
   if (target == 0 || !valid_multiword_target_p (target))
@@ -2972,6 +2974,15 @@ expand_bitreverse (scalar_int_mode mode,
   if (precision < 4)
     return NULL_RTX;
 
+  if (rtx temp = widen_bswap (mode, op0, target, bitreverse_optab))
+    return temp;
+
+  if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
+      && optab_handler (bitreverse_optab, word_mode) != CODE_FOR_nothing)
+    if (rtx temp = expand_doubleword_bswap (mode, op0, target,
+                                           bitreverse_optab))
+      return temp;
+
   if (target == NULL_RTX
       || target == op0
       || reg_overlap_mentioned_p (target, op0))
@@ -3516,7 +3527,7 @@ expand_unop (machine_mode mode, optab un
 
       if (is_a <scalar_int_mode> (mode, &int_mode))
        {
-         temp = widen_bswap (int_mode, op0, target);
+         temp = widen_bswap (int_mode, op0, target, unoptab);
          if (temp)
            return temp;
 
@@ -3526,7 +3537,7 @@ expand_unop (machine_mode mode, optab un
              && (UNITS_PER_WORD == 8
                  || optab_handler (unoptab, word_mode) != CODE_FOR_nothing))
            {
-             temp = expand_doubleword_bswap (mode, op0, target);
+             temp = expand_doubleword_bswap (mode, op0, target, unoptab);
              if (temp)
                return temp;
            }

        Jakub

Reply via email to