[PATCH v5 12/18] RISC-V: Add PREINDEX_ST macro-fusion recognition
Jin Ma <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
Recognize a non-word ADDI-type in-place address update followed by a scalar integer or floating-point store. Reuse the indexed-memory helper shared with LDPREINCREMENT, including its store-source constraint. Leave the fusion disabled by default and XFAIL its positive dump checks until a CPU enables it. gcc/ChangeLog: * config/riscv/riscv-fusion.cc (riscv_fuse_preindex_st): New function. (riscv_fusion_table): Add RISCV_FUSE_PREINDEX_ST. * config/riscv/riscv-protos.h (enum riscv_fusion_pairs): Add RISCV_FUSE_PREINDEX_ST. gcc/testsuite/ChangeLog: * gcc.target/riscv/fusion-memory-rtl-shapes-preindex-st.c: New test. * gcc.target/riscv/fusion-preindex-st.c: Likewise. Signed-off-by: Jin Ma <[email protected]> --- gcc/config/riscv/riscv-fusion.cc | 25 ++++++++++++++ gcc/config/riscv/riscv-protos.h | 1 + .../fusion-memory-rtl-shapes-preindex-st.c | 33 +++++++++++++++++++ .../gcc.target/riscv/fusion-preindex-st.c | 27 +++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-memory-rtl-shapes-preindex-st.c create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-preindex-st.c diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc index c6e7073cb23..b8d3c6d7fa6 100644 --- a/gcc/config/riscv/riscv-fusion.cc +++ b/gcc/config/riscv/riscv-fusion.cc @@ -1194,6 +1194,29 @@ riscv_fuse_ldpreincrement (rtx_insn *prev, rtx_insn *curr) return riscv_fuse_indexed_mem_p (prev, curr, true, true); } +/* Check for RISCV_FUSE_PREINDEX_ST fusion. + prev (one of the following): + (addi) == (set (reg rd1) (plus (reg rd1) (const_int imm12))) + (self-mv) == (set (reg rd1) (reg rd1)) + (addi) == (set (reg rd1) (lo_sum (reg rd1) symbol1)) + curr (one of the following): + (store) == (set (mem addr) (reg rs1)) + (store) == (set (mem addr) (const_int 0)) + (fpstore) == (set (mem addr) (reg frs1)) + addr (one of the following): + (rd1, offset) + (lo_sum (reg rd1) symbol2) + + Constraints: + the ADDI-type instruction is not a word form + for a register-source integer store, rd1 != rs1. */ + +static bool +riscv_fuse_preindex_st (rtx_insn *prev, rtx_insn *curr) +{ + return riscv_fuse_indexed_mem_p (prev, curr, false, true); +} + /* Check for RISCV_FUSE_LUI_ADDI fusion. prev (one of the following): (lui) == (set (reg rd1) (const_int imm20)) @@ -1713,6 +1736,8 @@ static const struct riscv_fusion_entry riscv_fusion_table[] = riscv_fuse_expanded_ld, "RISCV_FUSE_EXPANDED_LD" }, { RISCV_FUSE_LDPREINCREMENT, riscv_fuse_ldpreincrement, "RISCV_FUSE_LDPREINCREMENT" }, + { RISCV_FUSE_PREINDEX_ST, + riscv_fuse_preindex_st, "RISCV_FUSE_PREINDEX_ST" }, { RISCV_FUSE_LUI_ADDI, riscv_fuse_lui_addi, "RISCV_FUSE_LUI_ADDI" }, { RISCV_FUSE_AUIPC_ADDI, diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index c107a574ad6..a40c7d56233 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -873,6 +873,7 @@ enum riscv_fusion_pairs RISCV_FUSE_LOGIC_LOGIC = HOST_WIDE_INT_1U << 17, RISCV_FUSE_SLLI_SRLI = HOST_WIDE_INT_1U << 18, RISCV_FUSE_SRLI_ADD = HOST_WIDE_INT_1U << 19, + RISCV_FUSE_PREINDEX_ST = HOST_WIDE_INT_1U << 20, }; extern bool riscv_macro_fusion_p (void); diff --git a/gcc/testsuite/gcc.target/riscv/fusion-memory-rtl-shapes-preindex-st.c b/gcc/testsuite/gcc.target/riscv/fusion-memory-rtl-shapes-preindex-st.c new file mode 100644 index 00000000000..b490927e2df --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/fusion-memory-rtl-shapes-preindex-st.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=xt-c9501fdvt -O2 -fdump-rtl-sched2" } */ +/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_PREINDEX_ST" 1 "sched2" { xfail *-*-* } } } */ + +/* Pre-index update followed by a store of the zero register should fuse. */ +long __RTL (startwith ("sched2")) +test_preindex_store_zero (void) +{ +(function "test_preindex_store_zero" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + (cinsn 3 (set (reg:DI a0) + (plus:DI (reg:DI a0) + (const_int 8)))) + (cinsn 4 (set (mem:DI (reg:DI a0) [0 S8 A64]) + (const_int 0))) + (cinsn 5 (use (reg:DI a0))) + (cjump_insn 6 (simple_return)) + (edge-to exit) + ) ;; block 2 + (cbarrier 7) + ) ;; insn-chain + (crtl + (return_rtx + (reg/i:DI a0) + ) ;; return_rtx + ) ;; crtl +) ;; function "test_preindex_store_zero" +} diff --git a/gcc/testsuite/gcc.target/riscv/fusion-preindex-st.c b/gcc/testsuite/gcc.target/riscv/fusion-preindex-st.c new file mode 100644 index 00000000000..4979154e654 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/fusion-preindex-st.c @@ -0,0 +1,27 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-funroll-loops" "-flto" } } */ +/* { dg-options "-march=rv64gc_zfh -mabi=lp64d -mtune=xt-c9501fdvt -O2 -fdump-rtl-sched2-details" } */ +/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_PREINDEX_ST" 2 "sched2" { xfail *-*-* } } } */ + +typedef signed char int8_t; +/* Pre-increment store of a byte should fuse. */ +void +test_preindex_sb (int8_t *p, int8_t value, int n) +{ + for (int i = 0; i < n; ++i) + { + p += 2; + *p = value; + } +} + +/* Pre-increment store of a double should fuse. */ +void +test_preindex_fsd (double *p, double value, int n) +{ + for (int i = 0; i < n; ++i) + { + p += 2; + *p = value; + } +} -- 2.52.0