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; }
