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.

Jeff

gcc/
        * config/riscv/riscv.md ((x << C1) + C2): Tighten split condition
        and generate more efficient code when splitting.

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index e48d78a899e..5eb35d2fa64 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -4864,23 +4864,38 @@ (define_insn_and_split ""
                            (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