[PATCH v5 05/18] RISC-V: Add ADD_ST macro-fusion recognition
Jin Ma <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
Recognize ADD, ADDW, or ADD.UW followed by an undisplaced scalar integer store that uses the add result as its address. Keep the store-data constraint separate from the common add-memory matcher. Leave the fusion disabled by default. gcc/ChangeLog: * config/riscv/riscv-fusion.cc (riscv_fuse_add_st): New function. (riscv_fusion_table): Add RISCV_FUSE_ADD_ST. * config/riscv/riscv-protos.h (enum riscv_fusion_pairs): Add RISCV_FUSE_ADD_ST. gcc/testsuite/ChangeLog: * gcc.target/riscv/fusion-add-st.c: New test. * gcc.target/riscv/fusion-addw-adduw-st.c: Likewise. Signed-off-by: Jin Ma <[email protected]> --- gcc/config/riscv/riscv-fusion.cc | 29 ++++++++ gcc/config/riscv/riscv-protos.h | 1 + .../gcc.target/riscv/fusion-add-st.c | 13 ++++ .../gcc.target/riscv/fusion-addw-adduw-st.c | 67 +++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-add-st.c create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-addw-adduw-st.c diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc index 840bad47002..bb4076e9ffc 100644 --- a/gcc/config/riscv/riscv-fusion.cc +++ b/gcc/config/riscv/riscv-fusion.cc @@ -773,6 +773,33 @@ riscv_fuse_ldindexed (rtx_insn *prev, rtx_insn *curr) && mem.type != SCHED_FUSION_ST); } +/* Check for RISCV_FUSE_ADD_ST fusion. + prev (one of the following): + (add) == (set (reg rd1) (plus (reg rs1) (reg rs2))) + (addw) == (set (reg rd1) (sign_extend (plus:SI (reg rs1) + (reg rs2)))) + (add.uw) == (set (reg rd1) (plus (zero_extend (reg rs1)) + (reg rs2))) + curr (one of the following): + (store) == (set (mem (rd1, offset)) (reg rs3)) + (store) == (set (mem (rd1, offset)) (const_int 0)) + + Constraints: + rd1 != rs3 for a register-source store + offset == 0. */ + +static bool +riscv_fuse_add_st (rtx_insn *prev, rtx_insn *curr) +{ + rtx add_set, mem_set; + struct riscv_fusion_mem_info mem; + + return (riscv_fuse_add_mem_p (prev, curr, &add_set, &mem_set, &mem) + && mem.type == SCHED_FUSION_ST + && !riscv_fuse_same_reg_p (SET_DEST (add_set), + SET_SRC (mem_set))); +} + /* Check for RISCV_FUSE_EXPANDED_LD fusion. prev (one of the following): (add) == (set (reg rd1) (plus (reg rs1) (reg rs2))) @@ -1211,6 +1238,8 @@ static const struct riscv_fusion_entry riscv_fusion_table[] = riscv_fuse_zexth, "RISCV_FUSE_ZEXTH" }, { RISCV_FUSE_LDINDEXED, riscv_fuse_ldindexed, "RISCV_FUSE_LDINDEXED" }, + { RISCV_FUSE_ADD_ST, + riscv_fuse_add_st, "RISCV_FUSE_ADD_ST" }, { RISCV_FUSE_EXPANDED_LD, riscv_fuse_expanded_ld, "RISCV_FUSE_EXPANDED_LD" }, { RISCV_FUSE_LDPREINCREMENT, diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 20781e14313..0bd26523a98 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -867,6 +867,7 @@ enum riscv_fusion_pairs RISCV_FUSE_EXPANDED_LD = HOST_WIDE_INT_1U << 11, RISCV_FUSE_B_ALUI = HOST_WIDE_INT_1U << 12, RISCV_FUSE_SUB_SEQZ = HOST_WIDE_INT_1U << 13, + RISCV_FUSE_ADD_ST = HOST_WIDE_INT_1U << 14, }; extern bool riscv_macro_fusion_p (void); diff --git a/gcc/testsuite/gcc.target/riscv/fusion-add-st.c b/gcc/testsuite/gcc.target/riscv/fusion-add-st.c new file mode 100644 index 00000000000..e0cebe27972 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/fusion-add-st.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */ +/* { dg-options "-march=rv64g -mabi=lp64d -mtune=xt-c9501fdvt -O2 -fdump-rtl-sched2-details" } */ +/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_ADD_ST" 1 "sched2" { xfail *-*-* } } } */ + +typedef long int64_t; + +/* add + sd should fuse. */ +void +test_add_sd (int64_t *base, long off, int64_t v) +{ + *(int64_t *) ((char *) base + off) = v; +} diff --git a/gcc/testsuite/gcc.target/riscv/fusion-addw-adduw-st.c b/gcc/testsuite/gcc.target/riscv/fusion-addw-adduw-st.c new file mode 100644 index 00000000000..19989e0b902 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/fusion-addw-adduw-st.c @@ -0,0 +1,67 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */ +/* { dg-options "-march=rv64gc_zba -mabi=lp64d -mtune=xt-c9501fdvt -O2 -fdump-rtl-sched2-details" } */ +/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_ADD_ST" 2 "sched2" { xfail *-*-* } } } */ + +/* addw + sd should fuse. */ +long __RTL (startwith ("sched2")) +test_addw_sd (void) +{ +(function "test_addw_sd" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + ;; addw a0, a1, a2 + (cinsn 3 (set (reg:DI a0) + (sign_extend:DI + (plus:SI (reg:SI a1) + (reg:SI a2))))) + ;; sd a3, 0(a0) + (cinsn 4 (set (mem:DI (reg:DI a0) [0 S8 A64]) + (reg:DI a3))) + (cinsn 5 (use (reg/i: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_addw_sd" +} + +/* add.uw + sd should fuse. */ +long __RTL (startwith ("sched2")) +test_adduw_sd (void) +{ +(function "test_adduw_sd" + (insn-chain + (block 2 + (edge-from entry (flags "FALLTHRU")) + (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK) + (cnote 2 NOTE_INSN_FUNCTION_BEG) + ;; add.uw a0, a1, a2 + (cinsn 3 (set (reg:DI a0) + (plus:DI (zero_extend:DI (reg:SI a1)) + (reg:DI a2)))) + ;; sd a3, 0(a0) + (cinsn 4 (set (mem:DI (reg:DI a0) [0 S8 A64]) + (reg:DI a3))) + (cinsn 5 (use (reg/i: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_adduw_sd" +} -- 2.52.0