https://gcc.gnu.org/g:07ce51abde6d6f92febab863a68c69266a808f9f

commit r17-591-g07ce51abde6d6f92febab863a68c69266a808f9f
Author: Jakub Jelinek <[email protected]>
Date:   Tue May 19 09:29:33 2026 +0200

    optabs: Handle bitreverse using widening or two bitreverses of halves 
[PR50481]
    
    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.
    
    2026-05-19  Jakub Jelinek  <[email protected]>
    
            PR target/50481
            * optabs.cc (widen_bswap): Add UNOPTAB argument and use it instead
            of hardcoded bswap_optab.  Rename to ...
            (widen_bswap_or_bitreverse): ... this.
            (expand_doubleword_bswap): Add UNOPTAB argument and use it instead
            of hardcoded bswap_optab.  Rename to ...
            (expand_doubleword_bswap_or_bitreverse): ... this.
            (expand_bitreverse): Use widen_bswap_or_bitreverse and
            expand_doubleword_bswap_or_bitreverse.
            (expand_unop): Adjust widen_bswap and expand_doubleword_bswap 
callers
            to use new names and add an extra bswap_optab argument.
    
    Reviewed-by: Jeffrey Law <[email protected]>

Diff:
---
 gcc/optabs.cc | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/gcc/optabs.cc b/gcc/optabs.cc
index 87c4ea682fc5..729cdaf605b0 100644
--- a/gcc/optabs.cc
+++ b/gcc/optabs.cc
@@ -2895,16 +2895,18 @@ expand_doubleword_parity (scalar_int_mode mode, rtx 
op0, rtx target)
 /* 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_or_bitreverse (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 +2917,7 @@ widen_bswap (scalar_int_mode mode, rtx op0, rtx target)
   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 +2939,18 @@ widen_bswap (scalar_int_mode mode, rtx op0, rtx target)
   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_or_bitreverse (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 +2976,16 @@ expand_bitreverse (scalar_int_mode mode, rtx op0, rtx 
target)
   if (precision < 4)
     return NULL_RTX;
 
+  if (rtx temp = widen_bswap_or_bitreverse (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_or_bitreverse (mode, op0, target,
+                                                         bitreverse_optab))
+      return temp;
+
   if (target == NULL_RTX
       || target == op0
       || reg_overlap_mentioned_p (target, op0))
@@ -3516,7 +3530,7 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, 
rtx target,
 
       if (is_a <scalar_int_mode> (mode, &int_mode))
        {
-         temp = widen_bswap (int_mode, op0, target);
+         temp = widen_bswap_or_bitreverse (int_mode, op0, target, unoptab);
          if (temp)
            return temp;
 
@@ -3526,7 +3540,8 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, 
rtx target,
              && (UNITS_PER_WORD == 8
                  || optab_handler (unoptab, word_mode) != CODE_FOR_nothing))
            {
-             temp = expand_doubleword_bswap (mode, op0, target);
+             temp = expand_doubleword_bswap_or_bitreverse (mode, op0, target,
+                                                           unoptab);
              if (temp)
                return temp;
            }

Reply via email to