From 3b9c760072c7792cbae6f38894756d2b96c2fd8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20M=C3=BCllner?= Date: Mon, 6 May 2024 12:33:32 +0200 Subject: RISC-V: Add zero_extract support for rv64gc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The combiner attempts to optimize a zero-extension of a logical right shift using zero_extract. We already utilize this optimization for those cases that result in a single instructions. Let's add a insn_and_split pattern that also matches the generic case, where we can emit an optimized sequence of a slli/srli. Tested with SPEC CPU 2017 (rv64gc). PR target/111501 gcc/ChangeLog: * config/riscv/riscv.md (*lshr3_zero_extend_4): New pattern for zero-extraction. gcc/testsuite/ChangeLog: * gcc.target/riscv/extend-shift-helpers.h: New test. * gcc.target/riscv/pr111501.c: New test. * gcc.target/riscv/zero-extend-rshift-32.c: New test. * gcc.target/riscv/zero-extend-rshift-64.c: New test. * gcc.target/riscv/zero-extend-rshift.c: New test. Signed-off-by: Christoph Müllner --- gcc/config/riscv/riscv.md | 30 ++++++ .../gcc.target/riscv/extend-shift-helpers.h | 26 +++++ gcc/testsuite/gcc.target/riscv/pr111501.c | 21 ++++ .../gcc.target/riscv/zero-extend-rshift-32.c | 13 +++ .../gcc.target/riscv/zero-extend-rshift-64.c | 17 +++ .../gcc.target/riscv/zero-extend-rshift.c | 115 +++++++++++++++++++++ 6 files changed, 222 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/extend-shift-helpers.h create mode 100644 gcc/testsuite/gcc.target/riscv/pr111501.c create mode 100644 gcc/testsuite/gcc.target/riscv/zero-extend-rshift-32.c create mode 100644 gcc/testsuite/gcc.target/riscv/zero-extend-rshift-64.c create mode 100644 gcc/testsuite/gcc.target/riscv/zero-extend-rshift.c (limited to 'gcc') diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index b7fc13e..58bf771 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -2793,6 +2793,36 @@ [(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 "*lshr3_zero_extend_4" + [(set (match_operand:GPR 0 "register_operand" "=r") + (zero_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" + "#" + "&& 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)))] +{ + int regbits = GET_MODE_BITSIZE (GET_MODE (operands[0])).to_constant (); + int sizebits = INTVAL (operands[2]); + int startbits = INTVAL (operands[3]); + int lshamt = regbits - sizebits - startbits; + int rshamt = lshamt + startbits; + operands[2] = GEN_INT (lshamt); + operands[3] = GEN_INT (rshamt); +} + [(set_attr "type" "shift") + (set_attr "mode" "")]) + ;; Handle AND with 2^N-1 for N from 12 to XLEN. This can be split into ;; two logical shifts. Otherwise it requires 3 instructions: lui, ;; xor/addi/srli, and. diff --git a/gcc/testsuite/gcc.target/riscv/extend-shift-helpers.h b/gcc/testsuite/gcc.target/riscv/extend-shift-helpers.h new file mode 100644 index 0000000..4853fe4 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/extend-shift-helpers.h @@ -0,0 +1,26 @@ +#ifndef EXTEND_SHIFT_HELPERS_H +#define EXTEND_SHIFT_HELPERS_H + +#define RT_EXT_CT_RSHIFT_N_AT(RTS,RT,CTS,CT,N,ATS,AT) \ +RTS RT \ +RTS##_##RT##_ext_##CTS##_##CT##_rshift_##N##_##ATS##_##AT(ATS AT v) \ +{ \ + return (CTS CT)(v >> N); \ +} + +#define ULONG_EXT_USHORT_RSHIFT_N_ULONG(N) \ + RT_EXT_CT_RSHIFT_N_AT(unsigned,long,unsigned,short,N,unsigned,long) + +#define ULONG_EXT_UINT_RSHIFT_N_ULONG(N) \ + RT_EXT_CT_RSHIFT_N_AT(unsigned,long,unsigned,int,N,unsigned,long) + +#define UINT_EXT_USHORT_RSHIFT_N_UINT(N) \ + RT_EXT_CT_RSHIFT_N_AT(unsigned,int,unsigned,short,N,unsigned,int) + +#define UINT_EXT_USHORT_RSHIFT_N_ULONG(N) \ + RT_EXT_CT_RSHIFT_N_AT(unsigned,int,unsigned,short,N,unsigned,long) + +#define ULONG_EXT_USHORT_RSHIFT_N_UINT(N) \ + RT_EXT_CT_RSHIFT_N_AT(unsigned,long,unsigned,short,N,unsigned,int) + +#endif /* EXTEND_SHIFT_HELPERS_H */ diff --git a/gcc/testsuite/gcc.target/riscv/pr111501.c b/gcc/testsuite/gcc.target/riscv/pr111501.c new file mode 100644 index 0000000..db48c34 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr111501.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target rv64 } */ +/* { dg-options "-march=rv64gc" { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Os" "-Og" "-Oz" "-flto" } } */ + +unsigned int +do_shift(unsigned long csum) +{ + return (unsigned short)(csum >> 32); +} + +unsigned int +do_shift2(unsigned long csum) +{ + return (csum << 16) >> 48; +} + +/* { dg-final { scan-assembler-times "slli\t" 2 } } */ +/* { dg-final { scan-assembler-times "srli\t" 2 } } */ +/* { dg-final { scan-assembler-times "slli\ta\[0-9\],a\[0-9\],16" 2 } } */ +/* { dg-final { scan-assembler-times "srli\ta\[0-9\],a\[0-9\],48" 2 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/zero-extend-rshift-32.c b/gcc/testsuite/gcc.target/riscv/zero-extend-rshift-32.c new file mode 100644 index 0000000..c995a6e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zero-extend-rshift-32.c @@ -0,0 +1,13 @@ +/* { 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\],2" } } */ +/* { dg-final { scan-assembler "srli\ta\[0-9\],a\[0-9\],16" } } */ +ULONG_EXT_USHORT_RSHIFT_N_ULONG(14) + +/* { dg-final { scan-assembler "srli\ta\[0-9\],a\[0-9\],23" } } */ +ULONG_EXT_UINT_RSHIFT_N_ULONG(23) diff --git a/gcc/testsuite/gcc.target/riscv/zero-extend-rshift-64.c b/gcc/testsuite/gcc.target/riscv/zero-extend-rshift-64.c new file mode 100644 index 0000000..847fadf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zero-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\],34" } } */ +/* { dg-final { scan-assembler "srli\ta\[0-9\],a\[0-9\],48" } } */ +ULONG_EXT_USHORT_RSHIFT_N_ULONG(14) + +/* { dg-final { scan-assembler "srli\ta\[0-9\],a\[0-9\],51" } } */ +ULONG_EXT_USHORT_RSHIFT_N_ULONG(51) + +/* { dg-final { scan-assembler "slli\ta\[0-9\],a\[0-9\],9" } } */ +/* { dg-final { scan-assembler "srli\ta\[0-9\],a\[0-9\],32" } } */ +ULONG_EXT_UINT_RSHIFT_N_ULONG(23) diff --git a/gcc/testsuite/gcc.target/riscv/zero-extend-rshift.c b/gcc/testsuite/gcc.target/riscv/zero-extend-rshift.c new file mode 100644 index 0000000..8b27b0e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zero-extend-rshift.c @@ -0,0 +1,115 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv32gc" { target { rv32 } } } */ +/* { dg-options "-march=rv64gc" { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-Os" "-Og" "-Oz" "-flto" } } */ + +// Tests for merging rshifts into zero-extensions. +// u8-casts are skipped as they can be done with one instruction (andi 0xff). + +#include "extend-shift-helpers.h" + +// Below "slli (16-N); srli 16" for rv32 +// Below "slli ((32+16)-N); srli (32+16)" for rv64 +ULONG_EXT_USHORT_RSHIFT_N_ULONG(1) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(7) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(8) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(9) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(15) +// Below "srli 16" for rv32 +// Below "srliw 16" for rv64 +ULONG_EXT_USHORT_RSHIFT_N_ULONG(16) +// Below "srli N" for rv32 +// Below "slli ((32+16)-N); srli (32+16)" for rv64 +ULONG_EXT_USHORT_RSHIFT_N_ULONG(17) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(23) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(24) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(25) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(31) +// Below compiler warning for rv32 +#if __riscv_xlen == 64 +// Below "slli ((32+16)-N); srli (32+16)" for rv64 +ULONG_EXT_USHORT_RSHIFT_N_ULONG(32) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(33) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(39) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(40) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(41) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(47) +// Below "srli N" for rv64 +ULONG_EXT_USHORT_RSHIFT_N_ULONG(48) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(49) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(55) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(56) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(57) +ULONG_EXT_USHORT_RSHIFT_N_ULONG(63) +#endif /* __riscv_xlen == 64 */ + + + +// Below "srli N" for rv32 +// Below "slli (32-N); srli 32" for rv64 +ULONG_EXT_UINT_RSHIFT_N_ULONG(1) +ULONG_EXT_UINT_RSHIFT_N_ULONG(7) +ULONG_EXT_UINT_RSHIFT_N_ULONG(8) +ULONG_EXT_UINT_RSHIFT_N_ULONG(9) +ULONG_EXT_UINT_RSHIFT_N_ULONG(15) +ULONG_EXT_UINT_RSHIFT_N_ULONG(16) +ULONG_EXT_UINT_RSHIFT_N_ULONG(17) +ULONG_EXT_UINT_RSHIFT_N_ULONG(23) +ULONG_EXT_UINT_RSHIFT_N_ULONG(24) +ULONG_EXT_UINT_RSHIFT_N_ULONG(25) +ULONG_EXT_UINT_RSHIFT_N_ULONG(31) +// Below compiler warning for rv32 +#if __riscv_xlen == 64 +// Below "srli N" for rv64 +ULONG_EXT_UINT_RSHIFT_N_ULONG(32) +ULONG_EXT_UINT_RSHIFT_N_ULONG(33) +ULONG_EXT_UINT_RSHIFT_N_ULONG(39) +ULONG_EXT_UINT_RSHIFT_N_ULONG(40) +ULONG_EXT_UINT_RSHIFT_N_ULONG(41) +ULONG_EXT_UINT_RSHIFT_N_ULONG(47) +ULONG_EXT_UINT_RSHIFT_N_ULONG(48) +ULONG_EXT_UINT_RSHIFT_N_ULONG(49) +ULONG_EXT_UINT_RSHIFT_N_ULONG(55) +ULONG_EXT_UINT_RSHIFT_N_ULONG(56) +ULONG_EXT_UINT_RSHIFT_N_ULONG(57) +ULONG_EXT_UINT_RSHIFT_N_ULONG(63) +#endif /* __riscv_xlen == 64 */ + + + +#if __riscv_xlen == 64 +// Below "slli ((32+16)-N); srli (32+16)" for rv64 +UINT_EXT_USHORT_RSHIFT_N_UINT(1) +UINT_EXT_USHORT_RSHIFT_N_UINT(7) +UINT_EXT_USHORT_RSHIFT_N_UINT(8) +UINT_EXT_USHORT_RSHIFT_N_UINT(9) +UINT_EXT_USHORT_RSHIFT_N_UINT(15) +// Below "srliw N" for rv64 +UINT_EXT_USHORT_RSHIFT_N_UINT(16) +UINT_EXT_USHORT_RSHIFT_N_UINT(17) +UINT_EXT_USHORT_RSHIFT_N_UINT(23) +UINT_EXT_USHORT_RSHIFT_N_UINT(24) +UINT_EXT_USHORT_RSHIFT_N_UINT(25) +UINT_EXT_USHORT_RSHIFT_N_UINT(31) +#endif /* __riscv_xlen == 64 */ + + + +// Below "slli (16-N); srli 16" for rv32 +// Below "slli ((32+16)-N); srli (32+16)" for rv64 +UINT_EXT_USHORT_RSHIFT_N_ULONG(9) +UINT_EXT_USHORT_RSHIFT_N_ULONG(15) + + + +// Below "slli (16-N); srli 16" for rv32 +// Below "slli ((32+16)-N); srli (32+16)" for rv64 +ULONG_EXT_USHORT_RSHIFT_N_UINT(9) +ULONG_EXT_USHORT_RSHIFT_N_UINT(15) + +/* { dg-final { scan-assembler-times "slli\t" 9 { target { rv32 } } } } */ +/* { dg-final { scan-assembler-times "srli\t" 26 { target { rv32 } } } } */ + +/* { dg-final { scan-assembler-times "slli\t" 36 { target { rv64 } } } } */ +/* { dg-final { scan-assembler-times "srli\t" 54 { target { rv64 } } } } */ +/* { dg-final { scan-assembler-times "srliw\t" 7 { target { rv64 } } } } */ -- cgit v1.1