[PATCH v5 11/18] RISC-V: Generalize LDPREINCREMENT macro-fusion recognition
Jin Ma <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
Allow LDPREINCREMENT to match non-word ADDI-type in-place address updates followed by scalar integer or floating-point loads. Support register-plus-offset and LO_SUM addresses, self moves, and either load-destination relationship. Put the common pre/post-index load/store constraints in a parameterized helper for later fusion rules. gcc/ChangeLog: * config/riscv/riscv-fusion.cc (riscv_fuse_indexed_mem_p): New function. (riscv_fuse_ldpreincrement): Use it and accept scalar integer or floating-point loads. gcc/testsuite/ChangeLog: * gcc.target/riscv/fusion-preindex-load.c: New test. * gcc.target/riscv/fusion-preindex-load-rtl.c: Likewise. Signed-off-by: Jin Ma <[email protected]> --- gcc/config/riscv/riscv-fusion.cc | 77 +++++++++++++------ .../riscv/fusion-preindex-load-rtl.c | 66 ++++++++++++++++ .../gcc.target/riscv/fusion-preindex-load.c | 31 ++++++++ 3 files changed, 149 insertions(+), 25 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-preindex-load-rtl.c create mode 100644 gcc/testsuite/gcc.target/riscv/fusion-preindex-load.c diff --git a/gcc/config/riscv/riscv-fusion.cc b/gcc/config/riscv/riscv-fusion.cc index c24fb29cbaf..c6e7073cb23 100644 --- a/gcc/config/riscv/riscv-fusion.cc +++ b/gcc/config/riscv/riscv-fusion.cc @@ -800,6 +800,45 @@ riscv_fuse_add_mem_p (rtx_insn *prev, rtx_insn *curr, return true; } +/* Match an in-place ADDI-type address update and a scalar load or store using + the updated address. LOAD_P selects loads rather than stores, and + PREINDEX_P selects whether the update precedes the memory instruction. */ + +static bool +riscv_fuse_indexed_mem_p (rtx_insn *prev, rtx_insn *curr, + bool load_p, bool preindex_p) +{ + rtx prev_set, curr_set; + if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set)) + return false; + + rtx_insn *update_insn = preindex_p ? prev : curr; + rtx_insn *mem_insn = preindex_p ? curr : prev; + rtx update_set = preindex_p ? prev_set : curr_set; + rtx mem_set = preindex_p ? curr_set : prev_set; + rtx update_dest = SET_DEST (update_set); + rtx update_base = NULL_RTX; + struct riscv_fusion_mem_info mem; + + if (!riscv_insn_is_addi_type_p (update_insn, false, &update_base) + || update_base == NULL_RTX + || !riscv_fuse_mem_p (mem_insn, &mem) + || (load_p + ? mem.type == SCHED_FUSION_ST + : mem.type != SCHED_FUSION_ST) + || !(mem.addr.type == ADDRESS_REG + || mem.addr.type == ADDRESS_LO_SUM) + || riscv_regno (update_dest) == INVALID_REGNUM + || !riscv_fuse_same_reg_p (update_base, update_dest) + || !riscv_fuse_same_reg_p (mem.addr.reg, update_dest)) + return false; + + if (load_p) + return true; + + return !riscv_fuse_same_reg_p (SET_SRC (mem_set), update_dest); +} + /* Check the common RTL for ZEXTW, ZEXTWS and ZEXTH fusion. */ static bool @@ -1134,37 +1173,25 @@ riscv_fuse_expanded_ld (rtx_insn *prev, rtx_insn *curr) } /* Check for RISCV_FUSE_LDPREINCREMENT fusion. - prev (addi) == (set (reg rd1) - (plus (reg rd1) (const_int offset))) - curr (load) == (set (reg rd2) (mem (reg rd1))) + 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): + (load) == (set (reg rd2) (mem addr)) + (load) == (set (reg rd2) (any_extend (mem addr))) + (fpload) == (set (reg frd) (mem addr)) + addr (one of the following): + (rd1, offset) + (lo_sum (reg rd1) symbol2) Constraints: - rd1 == rd2. */ + the ADDI-type instruction is not a word form. */ static bool riscv_fuse_ldpreincrement (rtx_insn *prev, rtx_insn *curr) { - rtx prev_set, curr_set; - if (!riscv_fuse_sets_p (prev, curr, &prev_set, &curr_set)) - return false; - - if (!riscv_fuse_same_dest_p (prev_set, curr_set)) - return false; - - struct riscv_fusion_mem_info mem; - - if (riscv_fuse_mem_p (curr, &mem) - && mem.type == SCHED_FUSION_LD - && !mem.fp_p - && mem.addr.type == ADDRESS_REG - && INTVAL (mem.addr.offset) == 0 - && riscv_set_is_addi_p (prev_set) - && riscv_fuse_same_reg_p (XEXP (SET_SRC (prev_set), 0), - SET_DEST (prev_set)) - && riscv_fuse_same_reg_p (mem.addr.reg, SET_DEST (prev_set))) - return true; - - return false; + return riscv_fuse_indexed_mem_p (prev, curr, true, true); } /* Check for RISCV_FUSE_LUI_ADDI fusion. diff --git a/gcc/testsuite/gcc.target/riscv/fusion-preindex-load-rtl.c b/gcc/testsuite/gcc.target/riscv/fusion-preindex-load-rtl.c new file mode 100644 index 00000000000..c8cceb4740a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/fusion-preindex-load-rtl.c @@ -0,0 +1,66 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-flto" } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -mexplicit-relocs -O2 -mtune=xt-c9501fdvt -fdump-rtl-sched2-details" } */ +/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_LDPREINCREMENT" 2 "sched2" { xfail *-*-* } } } */ + +extern double preindex_symbol; + +/* The load may write the address-update destination. */ +long __RTL (startwith ("sched2")) +test_preindex_same_destination (void) +{ +(function "test_preindex_same_destination" + (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 1)))) + (cinsn 4 (set (reg:DI a0) + (zero_extend:DI + (mem:QI (reg:DI a0) [0 S1 A8])))) + (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)) + ) ;; crtl +) ;; function "test_preindex_same_destination" +} + +/* LO_SUM updates and addresses are accepted for floating-point loads. */ +long __RTL (startwith ("sched2")) +test_preindex_lo_sum_fload (void) +{ +(function "test_preindex_lo_sum_fload" + (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) + (lo_sum:DI + (reg:DI a0) + (symbol_ref:DI ("preindex_symbol"))))) + (cinsn 4 (set (reg:DF fa0) + (mem:DF + (lo_sum:DI + (reg:DI a0) + (symbol_ref:DI ("preindex_symbol"))) + [0 S8 A64]))) + (cinsn 5 (use (reg:DI a0))) + (cinsn 6 (use (reg:DF fa0))) + (cjump_insn 7 (simple_return)) + (edge-to exit) + ) ;; block 2 + (cbarrier 8) + ) ;; insn-chain + (crtl + (return_rtx (reg/i:DI a0)) + ) ;; crtl +) ;; function "test_preindex_lo_sum_fload" +} diff --git a/gcc/testsuite/gcc.target/riscv/fusion-preindex-load.c b/gcc/testsuite/gcc.target/riscv/fusion-preindex-load.c new file mode 100644 index 00000000000..6fd83652d55 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/fusion-preindex-load.c @@ -0,0 +1,31 @@ +/* { dg-do compile { target { rv64 } } } */ +/* { dg-skip-if "" { *-*-* } { "-O0" "-O1" "-O3" "-O[sgz]" "-funroll-loops" "-flto" } } */ +/* { dg-options "-march=rv64gc -mabi=lp64d -mtune=xt-c9501fdvt -O2 -fdump-rtl-sched2-details" } */ +/* No tune enables this fusion pair yet. */ +/* { dg-final { scan-rtl-dump-times "RISCV_FUSE_LDPREINCREMENT" 2 "sched2" { xfail *-*-* } } } */ + +typedef signed char int8_t; + +int8_t +test_preindex_lb (int8_t *p, int n) +{ + int8_t sum = 0; + for (int i = 0; i < n; ++i) + { + p += 2; + sum += *p; + } + return sum; +} + +double +test_preindex_fld (double *p, int n) +{ + double sum = 0; + for (int i = 0; i < n; ++i) + { + p += 2; + sum += *p; + } + return sum; +} -- 2.52.0