]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
optabs: Handle bitreverse using widening or two bitreverses of halves [PR50481]
authorJakub Jelinek <jakub@redhat.com>
Tue, 19 May 2026 07:29:33 +0000 (09:29 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 19 May 2026 07:29:33 +0000 (09:29 +0200)
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  <jakub@redhat.com>

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 <jeffrey.law@oss.qualcomm.com>
gcc/optabs.cc

index 87c4ea682fc502dedd1d08ab63fa83c767495434..729cdaf605b0a059c3629aeec64b27dacb521883 100644 (file)
@@ -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;
            }