The early-clobber scratch in *<any_extract>3 is unnecessary: slli
reads its source before writing, so the destination register can
safely hold the intermediate value.  This reduces register pressure
and makes the split output simpler.

gcc/ChangeLog:

        * config/riscv/riscv.md (*<any_extract:optab><GPR:mode>3):
        Remove (clobber (match_scratch)) and use operand 0 as the
        intermediate destination for the shift-left half of the split.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/extract-zero-no-scratch.c: New test.
        * gcc.target/riscv/extract-sign-no-scratch.c: New test.
---
 gcc/config/riscv/riscv.md                      |  7 +++----
 .../gcc.target/riscv/extract-sign-no-scratch.c | 18 ++++++++++++++++++
 .../gcc.target/riscv/extract-zero-no-scratch.c | 18 ++++++++++++++++++
 3 files changed, 39 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/extract-sign-no-scratch.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/extract-zero-no-scratch.c

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 2cd26fa99ab..f10a08460ac 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3157,8 +3157,7 @@ (define_insn_and_split "*<any_extract:optab><GPR:mode>3"
         (any_extract:GPR
        (match_operand:GPR 1 "register_operand" " r")
        (match_operand     2 "const_int_operand")
-       (match_operand     3 "const_int_operand")))
-   (clobber (match_scratch:GPR  4 "=&r"))]
+       (match_operand     3 "const_int_operand")))]
   "!((TARGET_ZBS || TARGET_XTHEADBS || TARGET_ZICOND
       || TARGET_XVENTANACONDOPS || TARGET_SFB_ALU)
      && (INTVAL (operands[2]) == 1))
@@ -3169,10 +3168,10 @@ (define_insn_and_split "*<any_extract:optab><GPR:mode>3"
         && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
   "#"
   "&& reload_completed"
-  [(set (match_dup 4)
+  [(set (match_dup 0)
      (ashift:GPR (match_dup 1) (match_dup 2)))
    (set (match_dup 0)
-     (<extract_shift>:GPR (match_dup 4) (match_dup 3)))]
+     (<extract_shift>:GPR (match_dup 0) (match_dup 3)))]
 {
   int regbits = GET_MODE_BITSIZE (GET_MODE (operands[0])).to_constant ();
   int sizebits = INTVAL (operands[2]);
diff --git a/gcc/testsuite/gcc.target/riscv/extract-sign-no-scratch.c 
b/gcc/testsuite/gcc.target/riscv/extract-sign-no-scratch.c
new file mode 100644
index 00000000000..e908737fb5b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/extract-sign-no-scratch.c
@@ -0,0 +1,18 @@
+/* Verify *sign_extract splitter uses the same dest for slli and srai.  */
+/* { dg-do compile { target { ! riscv_abi_e } } } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O2" } */
+/* { dg-skip-if "" { *-*-* } { "-Os" "-Oz" "-Og" "-flto" } } */
+
+long sign_ext_11_5  (long x) { return ((x << 48) >> 53); }
+long sign_ext_16_8  (long x) { return ((x << 40) >> 48); }
+long sign_ext_10_20 (long x) { return ((x << 34) >> 54); }
+
+/* { dg-final { scan-assembler-times "slli\t" 3 } } */
+/* { dg-final { scan-assembler-times "srai\t" 3 } } */
+/* { dg-final { scan-assembler "slli\ta0,a0,48" } } */
+/* { dg-final { scan-assembler "srai\ta0,a0,53" } } */
+/* { dg-final { scan-assembler "slli\ta0,a0,40" } } */
+/* { dg-final { scan-assembler "srai\ta0,a0,48" } } */
+/* { dg-final { scan-assembler "slli\ta0,a0,34" } } */
+/* { dg-final { scan-assembler "srai\ta0,a0,54" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/extract-zero-no-scratch.c 
b/gcc/testsuite/gcc.target/riscv/extract-zero-no-scratch.c
new file mode 100644
index 00000000000..6d6fdecf3a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/extract-zero-no-scratch.c
@@ -0,0 +1,18 @@
+/* Verify *zero_extract splitter uses the same dest for slli and srli.  */
+/* { dg-do compile { target { ! riscv_abi_e } } } */
+/* { dg-require-effective-target rv64 } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O2" } */
+/* { dg-skip-if "" { *-*-* } { "-Os" "-Oz" "-Og" "-flto" } } */
+
+unsigned long zero_ext_20_8  (unsigned long x) { return (x >> 8)  & 0xfffffUL; 
}
+unsigned long zero_ext_16_8  (unsigned long x) { return (x >> 8)  & 0xffffUL;  
}
+unsigned long zero_ext_13_20 (unsigned long x) { return (x >> 20) & 0x1fffUL;  
}
+
+/* { dg-final { scan-assembler-times "slli\t" 3 } } */
+/* { dg-final { scan-assembler-times "srli\t" 3 } } */
+/* { dg-final { scan-assembler "slli\ta0,a0,36" } } */
+/* { dg-final { scan-assembler "srli\ta0,a0,44" } } */
+/* { dg-final { scan-assembler "slli\ta0,a0,40" } } */
+/* { dg-final { scan-assembler "srli\ta0,a0,48" } } */
+/* { dg-final { scan-assembler "slli\ta0,a0,31" } } */
+/* { dg-final { scan-assembler "srli\ta0,a0,51" } } */
-- 
2.52.0

Reply via email to