[gcc r16-808] [RISC-V] Improve (x << C1) + C2 split code
Jeff Law
law@gcc.gnu.org
Wed May 21 22:05:57 GMT 2025
https://gcc.gnu.org/g:0bed343a2a640c7be4a1970d303098ccf62bd1c6
commit r16-808-g0bed343a2a640c7be4a1970d303098ccf62bd1c6
Author: Jeff Law <jlaw@ventanamicro.com>
Date: Wed May 21 16:04:58 2025 -0600
[RISC-V] Improve (x << C1) + C2 split code
I wrote this a couple months ago to fix an instruction count regression in
505.mcf on risc-v, but I don't have a trivial little testcase to add to the
suite.
There were two problems with the pattern.
First, the code was generating a shift followed by an add after reload.
Naturally combine doesn't run after reload and the code stayed in that form
rather than using shadd when available.
Second the splitter was just over-active. We need to make sure that the
shifted form of the constant operand has a cost > 1 to synthesize. It's
useless to split if the shifted constant can be synthesized in a single
instruction.
This has been in my tester since March. So it's been through numerous
riscv64-elf and riscv32-elf test cycles as well as multiple rv64 bootstrap
tests. Waiting on the upstream CI system to render a verdict before moving
forward.
Looking further out I'm hoping this pattern will transform into a simpler and
always active define_split.
gcc/
* config/riscv/riscv.md ((x << C1) + C2): Tighten split condition
and generate more efficient code when splitting.
Diff:
---
gcc/config/riscv/riscv.md | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 7e35d7877ed9..a5b3abbe5d45 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -4704,23 +4704,38 @@
(match_operand 2 "const_int_operand" "n"))
(match_operand 3 "const_int_operand" "n")))
(clobber (match_scratch:DI 4 "=&r"))]
- "(TARGET_64BIT && riscv_const_insns (operands[3], false) == 1)"
+ "(TARGET_64BIT
+ && riscv_const_insns (operands[3], false) == 1
+ && riscv_const_insns (GEN_INT (INTVAL (operands[3])
+ << INTVAL (operands[2])), false) != 1)"
"#"
"&& reload_completed"
[(const_int 0)]
"{
- rtx x = gen_rtx_ASHIFT (DImode, operands[1], operands[2]);
- emit_insn (gen_rtx_SET (operands[0], x));
-
- /* If the constant fits in a simm12, use it directly as we do not
- get another good chance to optimize things again. */
- if (!SMALL_OPERAND (INTVAL (operands[3])))
+ /* Prefer to generate shNadd when we can, even over using an
+ immediate form. If we're not going to be able to generate
+ a shNadd, then use the constant directly if it fits in a
+ simm12 field since we won't get another chance to optimize this. */
+ if ((TARGET_ZBA && imm123_operand (operands[2], word_mode))
+ || !SMALL_OPERAND (INTVAL (operands[3])))
emit_move_insn (operands[4], operands[3]);
else
operands[4] = operands[3];
- x = gen_rtx_PLUS (DImode, operands[0], operands[4]);
- emit_insn (gen_rtx_SET (operands[0], x));
+ if (TARGET_ZBA && imm123_operand (operands[2], word_mode))
+ {
+ rtx x = gen_rtx_ASHIFT (DImode, operands[1], operands[2]);
+ x = gen_rtx_PLUS (DImode, x, operands[4]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ }
+ else
+ {
+ rtx x = gen_rtx_ASHIFT (DImode, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ x = gen_rtx_PLUS (DImode, operands[0], operands[4]);
+ emit_insn (gen_rtx_SET (operands[0], x));
+ }
+
DONE;
}"
[(set_attr "type" "arith")])
More information about the Gcc-cvs
mailing list