https://gcc.gnu.org/g:3c9c52a1c0fa7af22f769a2116b28a0b7ea18129

commit r15-646-g3c9c52a1c0fa7af22f769a2116b28a0b7ea18129
Author: Jeff Law <j...@ventanamicro.com>
Date:   Sat May 18 15:08:07 2024 -0600

    [to-be-committed,RISC-V] Improve some shift-add sequences
    
    So this is a minor fix/improvement for shift-add sequences.  This was
    supposed to help xz in a minor way IIRC.
    
    Combine may present us with (x + C2') << C1 which was canonicalized from
    (x << C1) + C2.
    
    Depending on the precise values of C2 and C2' one form may be better
    than the other.  We can (somewhat awkwardly) use riscv_const_insns to
    test for which sequence would be preferred.
    
    Tested on Ventana's CI system as well as my own.  Waiting on CI results
    from Rivos's tester before moving forward.
    
    Jeff
    gcc/
            * config/riscv/riscv.md: Add new patterns to allow selection
            between (x << C1) + C2 vs (x + C2') << C1 depending on the
            cost C2 vs C2'.
    
    gcc/testsuite
    
            * gcc.target/riscv/shift-add-1.c: New test.

Diff:
---
 gcc/config/riscv/riscv.md                    | 56 ++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/riscv/shift-add-1.c | 21 +++++++++++
 2 files changed, 77 insertions(+)

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index ff4557c1325f..78c16adee980 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -4162,6 +4162,62 @@
   }
 )
 
+;; These are forms of (x << C1) + C2, potentially canonicalized from
+;; ((x + C2') << C1.  Depending on the cost to load C2 vs C2' we may
+;; want to go ahead and recognize this form as C2 may be cheaper to
+;; synthesize than C2'.
+;;
+;; It might be better to refactor riscv_const_insns a bit so that we
+;; can have an API that passes integer values around rather than
+;; constructing a lot of garbage RTL.
+;;
+;; The mvconst_internal pattern in effect requires this pattern to
+;; also be a define_insn_and_split due to insn count costing when
+;; splitting in combine.
+(define_insn_and_split ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
+                           (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])
+    && ((riscv_const_insns (operands[3])
+        < riscv_const_insns (GEN_INT (INTVAL (operands[3]) >> INTVAL 
(operands[2]))))
+       || riscv_const_insns (GEN_INT (INTVAL (operands[3]) >> INTVAL 
(operands[2]))) == 0))"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 0) (ashift:DI (match_dup 1) (match_dup 2)))
+   (set (match_dup 4) (match_dup 3))
+   (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
+  ""
+  [(set_attr "type" "arith")])
+
+(define_insn_and_split ""
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (sign_extend:DI (plus:SI (ashift:SI
+                                  (match_operand:SI 1 "register_operand" "r")
+                                  (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])
+    && ((riscv_const_insns (operands[3])
+        < riscv_const_insns (GEN_INT (INTVAL (operands[3]) >> INTVAL 
(operands[2]))))
+       || riscv_const_insns (GEN_INT (INTVAL (operands[3]) >> INTVAL 
(operands[2]))) == 0))"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 0) (ashift:DI (match_dup 1) (match_dup 2)))
+   (set (match_dup 4) (match_dup 3))
+   (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 5) (match_dup 6))))]
+  "{
+     operands[1] = gen_lowpart (DImode, operands[1]);
+     operands[5] = gen_lowpart (SImode, operands[0]);
+     operands[6] = gen_lowpart (SImode, operands[4]);
+   }"
+  [(set_attr "type" "arith")])
+
+
 (include "bitmanip.md")
 (include "crypto.md")
 (include "sync.md")
diff --git a/gcc/testsuite/gcc.target/riscv/shift-add-1.c 
b/gcc/testsuite/gcc.target/riscv/shift-add-1.c
new file mode 100644
index 000000000000..d98875c32716
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/shift-add-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zba_zbb_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+int composeFromSurrogate(const unsigned short high) {
+
+        return  ((high - 0xD800) << 10) ;
+}
+
+
+long composeFromSurrogate_2(const unsigned long high) {
+
+        return  ((high - 0xD800) << 10) ;
+}
+
+
+/* { dg-final { scan-assembler-times "\tli\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tslli\t" 2 } } */
+/* { dg-final { scan-assembler-times "\taddw\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tadd\t" 1 } } */
+

Reply via email to