https://gcc.gnu.org/g:d3660f7816fbc403a97492545a687b0651fe3429
commit d3660f7816fbc403a97492545a687b0651fe3429 Author: Christoph Müllner <christoph.muell...@vrull.eu> Date: Tue May 7 22:23:26 2024 +0200 RISC-V: Cover sign-extensions in lshr<GPR:mode>3_zero_extend_4 The lshr<GPR:mode>3_zero_extend_4 pattern targets bit extraction with zero-extension. This pattern represents the canonical form of zero-extensions of a logical right shift. The same optimization can be applied to sign-extensions. Given the two optimizations are so similar, this patch converts the existing one to also cover the sign-extension case as well. gcc/ChangeLog: * config/riscv/iterators.md (ashiftrt): New code attribute 'extract_shift' and adding extractions to optab. * config/riscv/riscv.md (*lshr<GPR:mode>3_zero_extend_4): Rename to... (*<any_extract:optab><GPR:mode>3):...this and add support for sign-extensions. gcc/testsuite/ChangeLog: * gcc.target/riscv/extend-shift-helpers.h: Add helpers for sign-extension. * gcc.target/riscv/sign-extend-rshift-32.c: New test. * gcc.target/riscv/sign-extend-rshift-64.c: New test. * gcc.target/riscv/sign-extend-rshift.c: New test. Signed-off-by: Christoph Müllner <christoph.muell...@vrull.eu> (cherry picked from commit 3ee30d7981987b86bd6a9a2675e26fadec48e5cd) Diff: --- gcc/config/riscv/iterators.md | 4 + gcc/config/riscv/riscv.md | 25 +++-- .../gcc.target/riscv/extend-shift-helpers.h | 20 ++++ .../gcc.target/riscv/sign-extend-rshift-32.c | 17 +++ .../gcc.target/riscv/sign-extend-rshift-64.c | 17 +++ .../gcc.target/riscv/sign-extend-rshift.c | 123 +++++++++++++++++++++ 6 files changed, 198 insertions(+), 8 deletions(-) diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index c5ca01f382a..8a9d1986b4a 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -155,6 +155,8 @@ (define_code_iterator any_extract [sign_extract zero_extract]) (define_code_attr extract_sidi_shift [(sign_extract "sraiw") (zero_extract "srliw")]) +(define_code_attr extract_shift [(sign_extract "ashiftrt") + (zero_extract "lshiftrt")]) ;; This code iterator allows the two right shift instructions to be ;; generated from the same template. @@ -261,6 +263,8 @@ (us_minus "ussub") (sign_extend "extend") (zero_extend "zero_extend") + (sign_extract "extract") + (zero_extract "zero_extract") (fix "fix_trunc") (unsigned_fix "fixuns_trunc")]) diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 58bf7712277..620a1b3bd32 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -2793,24 +2793,33 @@ [(set_attr "type" "shift") (set_attr "mode" "SI")]) -;; Canonical form for a zero-extend of a logical right shift. -;; Special cases are handled above. -;; Skip for single-bit extraction (Zbs/XTheadBs) and th.extu (XTheadBb) -(define_insn_and_split "*lshr<GPR:mode>3_zero_extend_4" +;; Canonical form for a extend of a logical shift right (sign/zero extraction). +;; Special cases, that are ignored (handled elsewhere): +;; * Single-bit extraction (Zbs/XTheadBs) +;; * Single-bit extraction (Zicondops/XVentanaCondops) +;; * Single-bit extraction (SFB) +;; * Extraction instruction th.ext(u) (XTheadBb) +;; * lshrsi3_extend_2 (see above) +(define_insn_and_split "*<any_extract:optab><GPR:mode>3" [(set (match_operand:GPR 0 "register_operand" "=r") - (zero_extract:GPR + (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"))] - "!((TARGET_ZBS || TARGET_XTHEADBS) && (INTVAL (operands[2]) == 1)) - && !TARGET_XTHEADBB" + "!((TARGET_ZBS || TARGET_XTHEADBS || TARGET_ZICOND + || TARGET_XVENTANACONDOPS || TARGET_SFB_ALU) + && (INTVAL (operands[2]) == 1)) + && !TARGET_XTHEADBB + && !(TARGET_64BIT + && (INTVAL (operands[3]) > 0) + && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))" "#" "&& reload_completed" [(set (match_dup 4) (ashift:GPR (match_dup 1) (match_dup 2))) (set (match_dup 0) - (lshiftrt:GPR (match_dup 4) (match_dup 3)))] + (<extract_shift>:GPR (match_dup 4) (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/extend-shift-helpers.h b/gcc/testsuite/gcc.target/riscv/extend-shift-helpers.h index 4853fe490d8..720672de242 100644 --- a/gcc/testsuite/gcc.target/riscv/extend-shift-helpers.h +++ b/gcc/testsuite/gcc.target/riscv/extend-shift-helpers.h @@ -8,6 +8,26 @@ RTS##_##RT##_ext_##CTS##_##CT##_rshift_##N##_##ATS##_##AT(ATS AT v) \ return (CTS CT)(v >> N); \ } +#define SLONG_EXT_SCHAR_RSHIFT_N_SLONG(N) \ + RT_EXT_CT_RSHIFT_N_AT(signed,long,signed,char,N,signed,long) + +#define SLONG_EXT_SSHORT_RSHIFT_N_SLONG(N) \ + RT_EXT_CT_RSHIFT_N_AT(signed,long,signed,short,N,signed,long) + +#define SLONG_EXT_SINT_RSHIFT_N_SLONG(N) \ + RT_EXT_CT_RSHIFT_N_AT(signed,long,signed,int,N,signed,long) + +#define SINT_EXT_SSHORT_RSHIFT_N_SINT(N) \ + RT_EXT_CT_RSHIFT_N_AT(signed,int,signed,short,N,signed,int) + +#define SINT_EXT_SSHORT_RSHIFT_N_SLONG(N) \ + RT_EXT_CT_RSHIFT_N_AT(signed,int,signed,short,N,signed,long) + +#define SLONG_EXT_SSHORT_RSHIFT_N_SINT(N) \ + RT_EXT_CT_RSHIFT_N_AT(signed,long,signed,short,N,signed,int) + + + #define ULONG_EXT_USHORT_RSHIFT_N_ULONG(N) \ RT_EXT_CT_RSHIFT_N_AT(unsigned,long,unsigned,short,N,unsigned,long) diff --git a/gcc/testsuite/gcc.target/riscv/sign-extend-rshift-32.c b/gcc/testsuite/gcc.target/riscv/sign-extend-rshift-32.c new file mode 100644 index 00000000000..895dd18c8f6 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sign-extend-rshift-32.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv32 } */ +/* { dg-options "-march=rv32gc" } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Os" "-Og" "-Oz" "-flto" } } */ + +#include "extend-shift-helpers.h" + +/* { dg-final { scan-assembler "slli\ta\[0-9\],a\[0-9\],15" } } */ +/* { dg-final { scan-assembler "srai\ta\[0-9\],a\[0-9\],24" } } */ +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(9) + +/* { dg-final { scan-assembler "slli\ta\[0-9\],a\[0-9\],2" } } */ +/* { dg-final { scan-assembler "srai\ta\[0-9\],a\[0-9\],16" } } */ +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(14) + +/* { dg-final { scan-assembler "srai\ta\[0-9\],a\[0-9\],23" } } */ +SLONG_EXT_SINT_RSHIFT_N_SLONG(23) diff --git a/gcc/testsuite/gcc.target/riscv/sign-extend-rshift-64.c b/gcc/testsuite/gcc.target/riscv/sign-extend-rshift-64.c new file mode 100644 index 00000000000..13d18f73eab --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sign-extend-rshift-64.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-options "-march=rv64gc" } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Os" "-Og" "-Oz" "-flto" } } */ + +#include "extend-shift-helpers.h" + +/* { dg-final { scan-assembler "slli\ta\[0-9\],a\[0-9\],47" } } */ +/* { dg-final { scan-assembler "srai\ta\[0-9\],a\[0-9\],56" } } */ +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(9) + +/* { dg-final { scan-assembler "slli\ta\[0-9\],a\[0-9\],34" } } */ +/* { dg-final { scan-assembler "srai\ta\[0-9\],a\[0-9\],48" } } */ +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(14) + +/* { dg-final { scan-assembler "srai\ta\[0-9\],a\[0-9\],51" } } */ +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(51) diff --git a/gcc/testsuite/gcc.target/riscv/sign-extend-rshift.c b/gcc/testsuite/gcc.target/riscv/sign-extend-rshift.c new file mode 100644 index 00000000000..90a44eadb59 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/sign-extend-rshift.c @@ -0,0 +1,123 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc" { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os" "-Og" "-Oz" "-flto" } } */ + +// Tests for merging rshifts into sero-extensions. +// s32-casts are skipped as they can be done with one instruction (sext.w). + +#include "extend-shift-helpers.h" + +// Below "slli (24-N); srai 24" for rv32 +// Below "slli ((32+24)-N); srai (32+24)" for rv64 +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(1) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(7) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(8) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(9) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(15) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(16) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(17) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(23) +// Below "srai N" for rv32 +// Below "sraiw N" for rv64 +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(24) +// Below "srai N" for rv32 +// Below "slli ((32+24)-N); srai (32+24)" for rv64 +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(25) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(31) +// Below compiler warning for rv32 +#if __riscv_xlen == 64 +// Below "slli ((32+24)-N); srai (32+24)" for rv64 +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(32) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(33) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(39) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(40) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(41) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(47) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(48) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(49) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(55) +// Below "srai N" for rv64 +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(56) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(57) +SLONG_EXT_SCHAR_RSHIFT_N_SLONG(63) +#endif /* __riscv_xlen == 64 */ + + + +// Below "slli (16-N); srai 16" for rv32 +// Below "slli ((32+16)-N); srai (32+16)" for rv64 +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(1) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(7) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(8) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(9) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(15) +// Below "srai 16" for rv32 +// Below "sraiw 16" for rv64 +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(16) +// Below "srai N" for rv32 +// Below "slli ((32+16)-N); srai (32+16)" for rv64 +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(17) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(23) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(24) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(25) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(31) +// Below compiler warning for rv32 +#if __riscv_xlen == 64 +// Below "slli ((32+16)-N); srai (32+16)" for rv64 +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(32) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(33) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(39) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(40) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(41) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(47) +// Below "srai N" for rv64 +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(48) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(49) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(55) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(56) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(57) +SLONG_EXT_SSHORT_RSHIFT_N_SLONG(63) +#endif /* __riscv_xlen == 64 */ + + + +#if __riscv_xlen == 64 +// Below "slli ((32+16)-N); srai (32+16)" for rv64 +// or "slli (16-N); sraiw 16" for rv64 +SINT_EXT_SSHORT_RSHIFT_N_SINT(1) +SINT_EXT_SSHORT_RSHIFT_N_SINT(7) +SINT_EXT_SSHORT_RSHIFT_N_SINT(8) +SINT_EXT_SSHORT_RSHIFT_N_SINT(9) +SINT_EXT_SSHORT_RSHIFT_N_SINT(15) +// Below "srai N" for rv64 +SINT_EXT_SSHORT_RSHIFT_N_SINT(16) +SINT_EXT_SSHORT_RSHIFT_N_SINT(17) +SINT_EXT_SSHORT_RSHIFT_N_SINT(23) +SINT_EXT_SSHORT_RSHIFT_N_SINT(24) +SINT_EXT_SSHORT_RSHIFT_N_SINT(25) +// Below "sraiw N" for rv64 +SINT_EXT_SSHORT_RSHIFT_N_SINT(31) +#endif /* __riscv_xlen == 64 */ + + + +// Below "slli (16-N); srai 16" for rv32 +// Below "slli ((32+16)-N); srai (32+16)" for rv64 +// or "slli (16-N); sraiw 16" for rv64 +SINT_EXT_SSHORT_RSHIFT_N_SLONG(9) +SINT_EXT_SSHORT_RSHIFT_N_SLONG(15) + + + +// Below "slli (16-N); srai 16" for rv32 +// Below "slli ((32+16)-N); srai (32+16)" for rv64 +SLONG_EXT_SSHORT_RSHIFT_N_SINT(9) +SLONG_EXT_SSHORT_RSHIFT_N_SINT(15) + +/* { dg-final { scan-assembler-times "slli\t" 17 { target { rv32 } } } } */ +/* { dg-final { scan-assembler-times "srai\t" 26 { target { rv32 } } } } */ + +/* { dg-final { scan-assembler-times "slli\t" 44 { target { rv64 } } } } */ +/* { dg-final { scan-assembler-times "srai\t" 51 { target { rv64 } } } } */ +/* { dg-final { scan-assembler-times "sraiw\t" 10 { target { rv64 } } } } */