https://gcc.gnu.org/g:f7e1e41c2525aca1f0c876e872032b08bccb9d18

commit f7e1e41c2525aca1f0c876e872032b08bccb9d18
Author: Jeff Law <j...@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.
    
    (cherry picked from commit 0bed343a2a640c7be4a1970d303098ccf62bd1c6)

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")])

Reply via email to