https://gcc.gnu.org/g:48ae7b09bc6b61bd383c45c25ddb36224a86c712
commit r17-5347-g48ae7b09bc6b61bd383c45c25ddb36224a86c712 Author: Jeff Law <[email protected]> Date: Mon Oct 19 10:01:18 2026 -0600 [PR target/127865][RISC-V] Refine selection of AOP for RISC-V So Anton's test showed a case where we'd have been better off steering towards PLUS for rv64 that had not occurred to me. In particular if we steer towards PLUS, then we can get sign extensions for free via addw/addiw; the sequence doesn't even have to end, they can appear in the middle of an instruction stream and allow us to eliminate a sign extension later as evidenced by Anton's test. So one more reason to steer towards PLUS. This has the potential to make identification of bseti harder. We'll have to monitor that and I wouldn't be surprised if final resolution of an AOP op really needs to wait until after combine is done. But that's definitely in the future work space. Bootstrapped and regression tested on the k3 and c920. K1 is in flight. Also tested on riscv32-elf and riscv64-elf. Pushing to the trunk. Assisted-By: LLM for patch review PR target/127865 gcc/ * config/riscv/riscv.md (aop<mode>3): Steer more operations towards PLUS for rv64. gcc/testsuite * gcc.target/riscv/pr127865.c: New test. Diff: --- gcc/config/riscv/riscv.md | 16 +++------------- gcc/testsuite/gcc.target/riscv/pr127865.c | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 448bd2415379..da6394d1ae6b 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -5491,21 +5491,11 @@ { /* If we have shift-add insns and arguments are all registers, steer towards PLUS, otherwise steer towards IOR. */ - if (TARGET_ZBA && REG_P (operands[2])) + if ((TARGET_ZBA && REG_P (operands[2])) + || (TARGET_64BIT && GET_MODE (operands[0]) == SImode)) emit_insn (gen_add<mode>3 (operands[0], operands[1], operands[2])); else - { - /* We accept GPRs, so we need to do the right thing for SI on rv64. */ - if (GET_MODE (operands[0]) != word_mode) - { - operands[0] = gen_lowpart (word_mode, operands[0]); - operands[1] = gen_lowpart (word_mode, operands[1]); - operands[2] = gen_lowpart (word_mode, operands[2]); - emit_insn (gen_iordi3 (operands[0], operands[1], operands[2])); - } - else - emit_insn (gen_ior<mode>3 (operands[0], operands[1], operands[2])); - } + emit_insn (gen_ior<mode>3 (operands[0], operands[1], operands[2])); DONE; } ) diff --git a/gcc/testsuite/gcc.target/riscv/pr127865.c b/gcc/testsuite/gcc.target/riscv/pr127865.c new file mode 100644 index 000000000000..0dc877238dd7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr127865.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target rv64 } } */ +/* { dg-skip-if "" { *-*-* } { "-O0"} } */ + + + +unsigned +f4 (unsigned *p) +{ + unsigned s1 = p[0], s2 = p[1]; + unsigned b = ((s1 << 13) ^ s1) >> 19; + s1 = ((s1 & 0xFFFFFFFEU) << 12) ^ b; + b = ((s2 << 2) ^ s2) >> 25; + s2 = ((s2 & 0xFFFFFFF8U) << 4) ^ b; + p[0] = s1; + p[1] = s2; + return s1 ^ s2; +} + +/* { dg-final { scan-assembler-not "sext.w\t" } } */ +
