https://gcc.gnu.org/g:9d11ed33f54b395948521654218e2eb98c237b0e
commit r17-5059-g9d11ed33f54b395948521654218e2eb98c237b0e Author: Jeff Law <[email protected]> Date: Sun Oct 11 08:30:00 2026 -0600 [RISC-V] Fix pack* tests for RISC-V after any-or-plus changes The RISC-V port has had a handful of scan-asm failures since the most recent any-or-plus patches. This isn't a huge surprise. This is the first of a few patches to get regression testing happy again. This particular patch focuses on the pack family. They're a poster-child for AOP in the sense we've going to have an operation like IOR/XOR/PLUS where the two inputs are known to have zero overlap in set bits. With generic parts of the compiler steering towards PLUS, the explicit IOR matching RTL no longer works. Fixing these is pretty simple, mostly a matter of creating a code iterator and using it in the pack patterns. Additionally, there's costing code that needs to be updated for the new forms that are showing up. When the pack instructions were added we had to special case them in riscv_rtx_costs or they'd get horribly (5X reality) costed and combine would reject. We just copy that over to the PLUS handling. This stands on its own regardless of how we're steering AOP as it merely supports the additional valid forms. This fixes all the pack* failures in the default test runs for riscv32-elf and riscv64-elf. It's been bootstrapped and regression tested on the k3 and c920 as part of the larger set of patches (k1 is still in progress, but not expecting problems). gcc/ * config/riscv/iterators.md (oxp): New code iterator. * config/riscv/crypto.md (pack patterns and splitters): Accept oxp in matching RTL. Fix whitespace goofs. Generate the PLUS forms when possible in splitters. * config/riscv/riscv.cc (riscv_rtx_cost, case PLUS): Handle PLUS form of pack instructions. (riscv_move_integer): Trivial adjustment for crypto.md changes. Diff: --- gcc/config/riscv/crypto.md | 36 ++++++++++++++++++------------------ gcc/config/riscv/iterators.md | 1 + gcc/config/riscv/riscv.cc | 24 +++++++++++++++++++++++- 3 files changed, 42 insertions(+), 19 deletions(-) diff --git a/gcc/config/riscv/crypto.md b/gcc/config/riscv/crypto.md index 2f3cc7e43b04..c3930ce4a2f5 100644 --- a/gcc/config/riscv/crypto.md +++ b/gcc/config/riscv/crypto.md @@ -107,9 +107,9 @@ ;; This is slightly more complex than the other pack patterns ;; that fully expose the RTL as it needs to self-adjust to ;; rv32 and rv64. But it's not that hard. -(define_insn "riscv_xpack_<X:mode>_<HX:mode>_2" +(define_insn "riscv_xpack_<code>_<X:mode>_<HX:mode>_2" [(set (match_operand:X 0 "register_operand" "=r") - (ior:X (ashift:X (match_operand:X 1 "register_operand" "r") + (oxp:X (ashift:X (match_operand:X 1 "register_operand" "r") (match_operand 2 "immediate_operand" "n")) (zero_extend:X (match_operand:HX 3 "register_operand" "r"))))] @@ -141,7 +141,7 @@ ;; to be the canonical form. The other form doesn't seem to trigger. (define_insn "*riscv_packh_<mode>_3" [(set (match_operand:X 0 "register_operand" "=r") - (ior:X (and:X (ashift:X (match_operand:X 1 "register_operand" "r") + (oxp:X (and:X (ashift:X (match_operand:X 1 "register_operand" "r") (const_int 8)) (const_int 65280)) (zero_extend:X (match_operand:QI 2 "register_operand" "r"))))] @@ -151,8 +151,8 @@ (define_insn "riscv_packw" [(set (match_operand:DI 0 "register_operand" "=r") - (unspec:DI [(match_operand:HI 1 "register_operand" "r") - (match_operand:HI 2 "register_operand" "r")] + (unspec:DI [(match_operand:HI 1 "register_operand" "r") + (match_operand:HI 2 "register_operand" "r")] UNSPEC_PACKW))] "TARGET_ZBKB && TARGET_64BIT" "packw\t%0,%1,%2" @@ -163,55 +163,55 @@ ;; allows later code to eliminate subsequent explicit sign extensions. (define_split [(set (match_operand:DI 0 "register_operand") - (ior:DI (ashift:DI + (oxp:DI (ashift:DI (sign_extend:DI (match_operand:HI 1 "register_operand")) (const_int 16)) (zero_extend:DI (match_operand:HI 2 "register_operand"))))] "TARGET_ZBKB && TARGET_64BIT" [(set (match_dup 0) - (sign_extend:DI (ior:SI (ashift:SI (match_dup 1) (const_int 16)) - (zero_extend:SI (match_dup 2)))))] + (sign_extend:DI (plus:SI (ashift:SI (match_dup 1) (const_int 16)) + (zero_extend:SI (match_dup 2)))))] "operands[1] = gen_lowpart (SImode, operands[1]);") (define_split [(set (match_operand:DI 0 "register_operand") - (ior:DI (zero_extend:DI (match_operand:HI 1 "register_operand")) + (oxp:DI (zero_extend:DI (match_operand:HI 1 "register_operand")) (ashift:DI (sign_extend:DI (match_operand:HI 2 "register_operand")) (const_int 16))))] "TARGET_ZBKB && TARGET_64BIT" [(set (match_dup 0) - (sign_extend:DI (ior:SI (ashift:SI (match_dup 2) (const_int 16)) - (zero_extend:SI (match_dup 1)))))] + (sign_extend:DI (plus:SI (ashift:SI (match_dup 2) (const_int 16)) + (zero_extend:SI (match_dup 1)))))] "operands[2] = gen_lowpart (SImode, operands[2]);") (define_split [(set (match_operand:DI 0 "register_operand") - (ior:DI (sign_extend:DI + (oxp:DI (sign_extend:DI (ashift:SI (match_operand:SI 1 "register_operand") (const_int 16))) (zero_extend:DI (match_operand:HI 2 "register_operand"))))] "TARGET_ZBKB && TARGET_64BIT" [(set (match_dup 0) - (sign_extend:DI (ior:SI (ashift:SI (match_dup 1) (const_int 16)) - (zero_extend:SI (match_dup 2)))))]) + (sign_extend:DI (plus:SI (ashift:SI (match_dup 1) (const_int 16)) + (zero_extend:SI (match_dup 2)))))]) (define_split [(set (match_operand:DI 0 "register_operand") - (ior:DI (zero_extend:DI (match_operand:HI 1 "register_operand")) + (oxp:DI (zero_extend:DI (match_operand:HI 1 "register_operand")) (sign_extend:DI (ashift:SI (match_operand:SI 2 "register_operand") (const_int 16)))))] "TARGET_ZBKB && TARGET_64BIT" [(set (match_dup 0) - (sign_extend:DI (ior:SI (ashift:SI (match_dup 2) (const_int 16)) - (zero_extend:SI (match_dup 1)))))]) + (sign_extend:DI (plus:SI (ashift:SI (match_dup 2) (const_int 16)) + (zero_extend:SI (match_dup 1)))))]) ;; And this patches the result of the splitter above. (define_insn "*riscv_packw_2" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI - (ior:SI + (oxp:SI (ashift:SI (match_operand:SI 1 "register_operand" "r") (const_int 16)) (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))))] diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index d8869810de76..c7fc97f6a0f1 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -246,6 +246,7 @@ ;; This code iterator allows ior and xor instructions to be generated ;; from the same template. (define_code_iterator any_or [ior xor]) +(define_code_iterator oxp [ior xor plus]) ;; This code iterator allows unsigned and signed division to be generated ;; from the same template. diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index ae3fd8e3d72b..bf1290317f3b 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -3705,7 +3705,7 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value) rtx t2 = codes[i].code == VEC_MERGE ? old_value : x; gcc_assert (t2); t2 = gen_lowpart (SImode, t2); - emit_insn (gen_riscv_xpack_di_si_2 (t, x, GEN_INT (32), t2)); + emit_insn (gen_riscv_xpack_plus_di_si_2 (t, x, GEN_INT (32), t2)); x = t; } } @@ -5057,6 +5057,28 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN return true; } + /* packh for zbkb. Alternate forms haven't shown up as a + costing problem. Obviously we can add the additional + variants if needed. We tend to canonicalize to this form + after the any-or-plus changes. */ + if (TARGET_ZBKB + && GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 0)) == AND + && GET_CODE (XEXP (XEXP (x, 0), 0)) == ASHIFT + && register_operand (XEXP (XEXP (XEXP (x, 0), 0), 0), word_mode) + && CONST_INT_P (XEXP (XEXP (XEXP (x, 0), 0), 1)) + && INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)) == 8 + && CONST_INT_P (XEXP (XEXP (x, 0), 1)) + && INTVAL (XEXP (XEXP (x, 0), 1)) == 0xff00 + && GET_CODE (XEXP (x, 1)) == ZERO_EXTEND + && GET_MODE (XEXP (x, 1)) == word_mode + && GET_MODE (XEXP (XEXP (x, 1), 0)) == QImode) + { + *total = COSTS_N_INSNS (1); + return true; + } + + if (float_mode_p) *total = tune_param->fp_add[mode == DFmode]; else
