Oh and one comment: GCC always uses this_kind_of_convension for function and variable name, notThisKind :)
Kito Cheng <[email protected]> 於 2026年6月24日週三 下午8:54寫道: > > Hi LiQin: > > Thanks for the patch, few comments from my first scan attached :) > > > > diff --git a/gcc/ChangeLog b/gcc/ChangeLog > > index 326943d7efa..0853e4323ea 100644 > > --- a/gcc/ChangeLog > > +++ b/gcc/ChangeLog > > For GCC project, you just need put changelog into git commit message, and then > this file will be auto update later. > > > diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md > > index 0d16d79df3a..ca337563620 100644 > > --- a/gcc/config/riscv/bitmanip.md > > +++ b/gcc/config/riscv/bitmanip.md > > @@ -39,6 +39,19 @@ > > [(set_attr "type" "bitmanip") > > (set_attr "mode" "<X:MODE>")]) > > > > +(define_insn "base_idx_shxadd<X:MODE>" > > Add @ to the pattern name (@base_idx_shxadd<X:MODE>) and then GCC will > generate > `gen_base_idx_shxadd(<MODE>, op0, op1, op2, op3, op4)` function > Then you can drop riscv_base_idx_shxadd. > > > diff --git a/gcc/config/riscv/riscv-fold-base-idx.cc > > b/gcc/config/riscv/riscv-fold-base-idx.cc > > new file mode 100644 > > index 00000000000..92149e82772 > > --- /dev/null > > +++ b/gcc/config/riscv/riscv-fold-base-idx.cc > > @@ -0,0 +1,583 @@ > > +/* fold-base-idx pass for RISC-V. > > + Copyright (C) 2018-2024 Free Software Foundation, Inc. > > 2026 instead of 2018-2024 > > > +/* > > +This optimization is mainly to explain the low address of ADDI to the > > memory > > +offset of ld/st, reducing the low address calculation instructions. > > +1. Without GP relaxation: > > + lui + addi + add/add.uw/shxadd/shxadd.uw + ld/st > > + ----------------Transform--------------------- > > + lui + add/add.uw/shxadd/shxadd.uw + ld/st (iff addend == 0) > > + > > + lui + addi + addi + add/add.uw/shxadd/shxadd.uw + ld/st > > + ----------------Transform--------------------- > > + lui + add/add.uw/shxadd/shxadd.uw + ld/st (iff addend > 0) > > +2. With GP relaxation > > + lui + addi + add/add.uw/shxadd/shxadd.uw + ld/st > > + ----------------Transform--------------------- > > + add/add.uw/shxadd/shxadd.uw + ld/st > > +*/ > > + > > +namespace { > > + > > +const pass_data pass_data_fold_base_idx = { > > + RTL_PASS, /* type */ > > + "fold_gp", /* name */ > > + OPTGROUP_NONE, /* optinfo_flags */ > > + TV_NONE, /* tv_id */ > > + 0, /* properties_required */ > > + 0, /* properties_provided */ > > + 0, /* properties_destroyed */ > > + 0, /* todo_flags_start */ > > + 0, /* todo_flags_finish */ > > +}; > > + > > +class pass_fold_base_idx : public rtl_opt_pass { > > +public: > > + pass_fold_base_idx(gcc::context *ctxt) > > + : rtl_opt_pass(pass_data_fold_base_idx, ctxt) {} > > + > > + /* opt_pass methods: */ > > + virtual bool gate(function *) { return optimize > 0; } > > + virtual unsigned int execute(function *); > > + > > +private: > > + void analyze_and_transform(rtx_insn *hi, rtx_insn *lo, rtx_insn *add, > > + rtx_insn *mem); > > + bool detectFoldable(rtx_insn *high_insn, rtx_insn *&lo_insn); > > + rtx getMemAddrAndOffset(rtx_insn *mem); > > + // In this case, where a struct accesses a non-first element, the > > memory's > > + // Offset is not zero, we can update the hi/lo's symbol with the memory's > > + // offset. > > + void merge_mem_offset_into_symbol(rtx_insn *&hi, rtx_insn *&lo, > > + rtx_insn *mem); > > + // In this case, where the addi offset is not zero and addi only oneUse > > in add > > + // insn, we can directly remove the addi insn and update the hi/lo's > > symbol > > + // with the addi's offset. > > + void remove_addi_and_merge_addioff(rtx_insn *&hi_insn, rtx_insn > > *&lo_insn, > > + rtx_insn *&add_insn); > > + bool foldGPIntoMemoryOps(rtx_insn *lo, rtx_insn *&add, rtx_insn *&mem); > > +}; // class pass_fold_base_idx > > + > > +/* > > + Iff the insn has only one used insn, and use_insn can't be used in JUMP > > or > > + CALL, and except the DEBUG Insn. > > +*/ > > +static bool hasOneUse(rtx_insn *insn, rtx dest, rtx_insn *&use_insn) { > > has_one_use > > > + if (!REG_P(dest)) > > + return false; > > + > > + df_ref use; > > + int use_count = 0; > > + unsigned int regno = REGNO(dest); > > + > > + for (use = DF_REG_USE_CHAIN(regno); use; use = DF_REF_NEXT_REG(use)) { > > + if (!DF_REF_INSN_INFO(use)) > > + continue; > > + > > + if (CALL_P(DF_REF_INSN(use)) || JUMP_P(DF_REF_INSN(use))) > > + return false; > > + > > + if (DEBUG_INSN_P(DF_REF_INSN(use))) > > + continue; > > + > > + use_count++; > > + use_insn = DF_REF_INSN(use); > > + } > > + > > + if (use_count == 1 && use_insn) > > + return true; > > + > > + return false; > > +} > > + > > +/* Symbol Bind is not local can be optimize */ > > +static bool symbol_binds_local_p(const_rtx x) { > > + if (SYMBOL_REF_P(x)) > > + return (SYMBOL_REF_DECL(x) ? targetm.binds_local_p(SYMBOL_REF_DECL(x)) > > + : SYMBOL_REF_LOCAL_P(x)); > > + else > > + return false; > > +} > > + > > +/* > > +Detect the patterns: > > +(set (reg/f:DI 137) > > + (high:DI (symbol_ref:DI ("sym")))) > > +(set (reg/f:DI 138) > > + (lo_sum:DI (reg/f:DI 137) (symbol_ref:DI ("sym")))) > > + > > +The pattern is only accepted if: > > +1. The first instruction has only one use, which is in the LO_SUM > > +2. The symbol need is the Global Address or anchor symbols > > +*/ > > +bool pass_fold_base_idx::detectFoldable(rtx_insn *hi_insn, rtx_insn > > *&lo_insn) { > > + rtx hi_set = single_set(hi_insn); > > + if (hi_set == NULL_RTX) > > + return false; > > + > > + if (GET_CODE(SET_SRC(hi_set)) != HIGH) > > + return false; > > + > > + rtx hi_sym = XEXP(SET_SRC(hi_set), 0); > > + if (GET_CODE(hi_sym) != SYMBOL_REF) > > + return false; > > + > > + // Allow non-local symbols or anchor symbols > > + if (symbol_binds_local_p(hi_sym) && !SYMBOL_REF_ANCHOR_P(hi_sym)) > > + return false; > > + > > + if (!hasOneUse(hi_insn, SET_DEST(hi_set), lo_insn)) > > + return false; > > + > > + rtx lo_set = single_set(lo_insn); > > + if (lo_set == NULL_RTX) > > + return false; > > + > > + if (GET_CODE(SET_SRC(lo_set)) != LO_SUM) > > + return false; > > + > > + rtx lo_sym = XEXP(SET_SRC(lo_set), 1); > > + if (GET_CODE(lo_sym) != SYMBOL_REF) > > + return false; > > + > > + // Allow non-local symbols or anchor symbols > > + if (symbol_binds_local_p(lo_sym) && !SYMBOL_REF_ANCHOR_P(lo_sym)) > > + return false; > > + > > + return true; > > +} > > + > > +rtx pass_fold_base_idx::getMemAddrAndOffset(rtx_insn *mem) { > > + if (!mem) > > + return NULL_RTX; > > + > > + rtx mem_dst = SET_DEST(PATTERN(mem)); > > + rtx mem_src = SET_SRC(PATTERN(mem)); > > + > > + if (MEM_P(mem_src)) > > + return XEXP(mem_src, 0); > > + else if (MEM_P(mem_dst)) > > + return XEXP(mem_dst, 0); > > + else if ((GET_CODE(mem_src) == ZERO_EXTEND || > > + GET_CODE(mem_src) == SIGN_EXTEND) && > > + MEM_P(XEXP(mem_src, 0))) > > + return XEXP(XEXP(mem_src, 0), 0); > > + > > + return NULL_RTX; > > +} > > + > > +// we have two cases to update the symbol with new offset: > > +// 1. mem access with offset, we can directly update the symbol with mem's > > +// offset > > +// 2. remove addi and update the symbol with addi's offset > > +static void update_symbol_offset(rtx_insn *&hi, rtx_insn *&lo, > > + HOST_WIDE_INT offset) { > > + rtx old_sym = XEXP(SET_SRC(PATTERN(hi)), 0); > > + rtx new_sym = NULL_RTX; > > + > > + // if the old symbol is already a plus of symbol with offset, we can > > directly > > + // update the offset of the plus. > > + if (GET_CODE(old_sym) != SYMBOL_REF && GET_CODE(old_sym) == CONST && > > + GET_CODE(XEXP(old_sym, 0)) == PLUS) { > > + HOST_WIDE_INT old_off = INTVAL(XEXP(XEXP(old_sym, 0), 1)); > > + XEXP(XEXP(old_sym, 0), 1) = GEN_INT(old_off + offset); > > + new_sym = old_sym; > > + } else { > > + machine_mode mode = GET_MODE(old_sym); > > + rtx plus = gen_rtx_PLUS(mode, old_sym, GEN_INT(offset)); > > + new_sym = gen_rtx_CONST(mode, plus); > > + } > > + > > + // update hi and lo symbol > > + XEXP(SET_SRC(PATTERN(hi)), 0) = new_sym; > > + XEXP(SET_SRC(PATTERN(lo)), 1) = new_sym; > > +} > > + > > +/* > > +mainly deal with access the struct member varival which not the first. > > +Update the sym with mem's addr offset. > > +example as: > > +struct bin_info_s { > > + int reg_size; > > + int slab_size; > > +}; > > +typedef struct bin_info_s bin_info_t; > > +extern bin_info_t bin_infos[100]; > > +int __attribute__((noinline)) test_gp(int i) { > > + return bin_infos[i].slab_size; > > +} > > + > > +Pattern Transform: > > +(set (reg/f:DI hi_dst) > > + (high:DI (symbol_ref:DI ("bin_infos")))) > > +(set (reg/f:DI lo_dst) > > + (lo_sum:DI (reg/f:DI hi_dst) > > + (symbol_ref:DI ("bin_infos")))) > > +(set (reg/f:DI plus_dst) > > + (plus:DI (reg/f:DI lo_dst) (reg:DI 140))) > > +(set (reg/i:DI 10 a0) > > + (zero_extend:DI (mem:QI (plus:DI (reg/f:DI plus_dst) (const_int > > mem_off [0x4]))))) > > + > > +------- Transform -------- > > + > > +(set (reg/f:DI hi_dst) > > + (high:DI (const:DI (plus:DI (symbol_ref:DI ("bin_infos")) > > + (const_int mem_off))))) > > +(set (reg/f:DI lo_dst) > > + (lo_sum:DI (reg/f:DI hi_dst) > > + (const:DI (plus:DI (symbol_ref:DI ("bin_infos")) > > + (const_int mem_off))))) > > +(set (reg/f:DI plus_dst) > > + (plus:DI (reg/f:DI hi_dst) (reg:DI plus_src1))) > > +(set (reg/i:DI 10 a0) > > + (zero_extend:DI (mem:QI (plus:DI (reg/f:DI plus_dst) (const_int > > mem_off))))) > > This example little bit confuse me, where is (reg:DI 140) and (reg/f:DI > lo_dst) > after transform? is (reg:DI plus_src1) = (reg:DI 140)? > > > +*/ > > +void pass_fold_base_idx::merge_mem_offset_into_symbol(rtx_insn *&hi, > > + rtx_insn *&lo, > > + rtx_insn *mem) { > > + rtx mem_addr = getMemAddrAndOffset(mem); > > + // if mem_off is zero, we don't need to update the symbol, just return. > > + if (REG_P(mem_addr)) > > + return; > > + > > + // mem(plus reg/f:DI src1, (const_int mem_off)) > > + update_symbol_offset(hi, lo, INTVAL(XEXP(mem_addr, 1))); > > +} > > + > > +/* > > +Example as: > > +extern long long sym[100]; > > +long long __attribute__((noinline)) foo(int i) { > > + return sym[i + 3]; > > +} > > + > > +(set (reg/f:DI hi_dst) > > + (high:DI (symbol_ref:DI ("sym")))) > > +(set (reg/f:DI lo_dst) > > + (lo_sum:DI (reg/f:DI hi_dst) > > + (symbol_ref:DI ("sym")))) > > +(set (reg:DI remove_addi_dst) > > + (sign_extend:DI (plus:SI (subreg:SI (reg:DI remove_addi_src) 0) > > + (const_int addi_offset)))) > > +(set (reg/f:DI plus_dst) > > + (plus:DI (ashift:DI (reg:DI remove_addi_dst) (const_int ashift_num > > [0x3])) > > + (reg/f:DI lo_dst))) > > What is remove_addi_src? it's `i`? > > > +void pass_fold_base_idx::analyze_and_transform(rtx_insn *hi, rtx_insn *lo, > > + rtx_insn *add, rtx_insn > > *mem) { > > + if (!detectFoldable(hi, lo)) > > + return; > > + > > + if (foldGPIntoMemoryOps(lo, add, mem)) { > > + merge_mem_offset_into_symbol(hi, lo, mem); > > + remove_addi_and_merge_addioff(hi, lo, add); > > + targetm.base_idx_sym_emit(hi, lo, add, mem); > > we don't need define that in target hook because it's RISC-V specific pass. > > > + } > > +} > > + > > +unsigned int pass_fold_base_idx::execute(function *fn) { > > + basic_block bb; > > + rtx_insn *insn; > > + FOR_ALL_BB_FN(bb, fn) { > > + FOR_BB_INSNS(bb, insn) > > + analyze_and_transform(insn, NULL, NULL, NULL); > > + } > > + > > + return 0; > > +} > > + > > +} // namespace > > + > > +rtl_opt_pass *make_pass_fold_base_idx(gcc::context *ctxt) { > > + return new pass_fold_base_idx(ctxt); > > +} > > diff --git a/gcc/config/riscv/riscv-passes.def > > b/gcc/config/riscv/riscv-passes.def > > index bc6b3c8b98d..4ff5ee5cc13 100644 > > --- a/gcc/config/riscv/riscv-passes.def > > +++ b/gcc/config/riscv/riscv-passes.def > > @@ -17,6 +17,7 @@ > > along with GCC; see the file COPYING3. If not see > > <http://www.gnu.org/licenses/>. */ > > > > +INSERT_PASS_AFTER (pass_combine, 1, pass_fold_base_idx); > > INSERT_PASS_AFTER (pass_combine, 1, pass_bclr_lowest_set_bit); > > INSERT_PASS_AFTER (pass_rtl_store_motion, 1, pass_shorten_memrefs); > > INSERT_PASS_AFTER (pass_split_all_insns, 1, pass_avlprop); > > diff --git a/gcc/config/riscv/riscv-protos.h > > b/gcc/config/riscv/riscv-protos.h > > index dd029c70413..9e85e0743c1 100644 > > --- a/gcc/config/riscv/riscv-protos.h > > +++ b/gcc/config/riscv/riscv-protos.h > > @@ -36,8 +36,9 @@ enum riscv_symbol_type { > > SYMBOL_TLS_IE, > > SYMBOL_TLS_GD, > > SYMBOL_TLSDESC, > > + SYMBOL_BASE_IDX_ADD, > > }; > > -#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1) > > +#define NUM_SYMBOL_TYPES (SYMBOL_BASE_IDX_ADD + 1) > > > > /* Classifies an address. > > > > @@ -202,6 +203,7 @@ extern void riscv_parse_arch_string (const char *, > > struct gcc_options *, locatio > > > > extern bool riscv_hard_regno_rename_ok (unsigned, unsigned); > > > > +rtl_opt_pass *make_pass_fold_base_idx(gcc::context *ctxt); > > rtl_opt_pass * make_pass_shorten_memrefs (gcc::context *ctxt); > > rtl_opt_pass * make_pass_avlprop (gcc::context *ctxt); > > rtl_opt_pass * make_pass_vsetvl (gcc::context *ctxt); > > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > > index 8a39c791c26..cd685700e28 100644 > > --- a/gcc/config/riscv/riscv.cc > > +++ b/gcc/config/riscv/riscv.cc > > @@ -1878,6 +1878,8 @@ static int riscv_symbol_insns (enum riscv_symbol_type > > type) > > case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the > > reference. */ > > case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference. */ > > case SYMBOL_FORCE_TO_MEM: return 3; /* AUIPC + LD + the reference. */ > > + case SYMBOL_BASE_IDX_ADD: > > + return 3; /* LUI + the reference + ADD/SHXADD/ADD_UW/SHXADD_UW */ > > default: gcc_unreachable (); > > } > > } > > @@ -2178,6 +2180,9 @@ riscv_split_symbol_type (enum riscv_symbol_type > > symbol_type) > > if (!TARGET_EXPLICIT_RELOCS) > > return false; > > > > + if (symbol_type == SYMBOL_BASE_IDX_ADD) > > + return true; > > + > > return symbol_type == SYMBOL_ABSOLUTE || symbol_type == SYMBOL_PCREL; > > } > > > > @@ -2954,6 +2959,168 @@ static rtx riscv_tls_add_tp_le (rtx dest, rtx base, > > rtx sym) > > return gen_tls_add_tp_lesi (dest, base, tp, sym); > > } > > > > +// Add %base_idx_add reloc for global array non-const addressing > > optimization > > + > > +// To ensure consistent output across all assembly code, > > +// swap the positions of the two operands of plus. > > +// (plus:DI (reg/f:DI lo_dst) (reg:DI plus_src1))) > > +// ----------- Transform to ----------- > > +// (unspec:DI (reg/f:DI plus_src1) (reg:DI hi_dst))) > > + > > +static rtx riscv_base_idx_add(rtx dest, rtx plus_src1, rtx update_addr, > > + rtx sym) { > > + if (Pmode == DImode) > > + return gen_base_idx_adddi(dest, plus_src1, update_addr, sym); > > + else > > + return gen_base_idx_addsi(dest, plus_src1, update_addr, sym); > > +} > > + > > +// (plus:DI (zero_extend:DI (subreg:SI (reg:DI zextend_src) 0)) (reg/f:DI > > +// lo_dst))) > > +// ----------- Transform to ----------- > > +// (unspec:DI (zero_extend:DI (zextend_src))) (reg/f:DI hi_dst))) > > + > > +static rtx riscv_base_idx_adduw(rtx dest, rtx zextend_src, rtx update_addr, > > + rtx sym) { > > + return gen_base_idx_adduwDI(dest, zextend_src, update_addr, sym); > > +} > > + > > +// (plus:DI (ashift:DI (reg:DI ashift_src0) (const_int sshift_src1)) > > (reg/f:DI > > +// lo_dst)) > > +// ----------- Transform to ----------- > > +// (unspec:DI (ashift:DI (reg:DI ashift_src0) (const_int sshift_src1)) > > (reg/f:DI > > +// hi_dst)) > > + > > +static rtx riscv_base_idx_shxadd(rtx dest, rtx ashift, rtx update_addr, > > + rtx sym) { > > + if (Xmode == DImode) > > + return gen_base_idx_shxaddDI(dest, XEXP(ashift, 0), XEXP(ashift, 1), > > + update_addr, sym); > > + else > > + return gen_base_idx_shxaddSI(dest, XEXP(ashift, 0), XEXP(ashift, 1), > > + update_addr, sym); > > +} > > + > > +// (plus:DI (and:DI (ashift:DI (reg:DI ashift_src0) (const_int > > sshift_src1)) > > +// (const_int and_mask)) > > +// (reg/f:DI lo_dst)) > > +// ----------- Transform to -----------> > > +// (unspec:DI (and:DI (ashift:DI (reg:DI ashift_src0) (const_int > > sshift_src1)) > > +// (const_int and_mask)) > > +// (reg/f:DI hi_dst)) > > + > > +static rtx riscv_base_idx_shxadduw(rtx dest, rtx ashift, rtx and_mask, > > + rtx update_addr, rtx sym) { > > + return gen_base_idx_shxadduwDI(dest, XEXP(ashift, 0), XEXP(ashift, 1), > > + and_mask, update_addr, sym); > > +} > > + > > +// Mem Pattern as and support mode include DImode/SImode/HImode/QImode: > > +// 1. (set (mem:SI (reg/f:DI mem_addr))) > > +// 2. (set (reg/i:DI 10 a0) (mem:DI (reg/f:DI mem_addr))) > > +// 3. (set (reg/i:DI 10 a0) (zero_extend:DI (mem:QI (reg/f:DI mem_addr) > > +// 4. (set (reg/i:DI 10 a0) (sign_extend:DI (mem:SI (reg/f:DI mem_addr) > > +static void set_mem_address(rtx_insn *&mem, rtx addr) { > > + rtx pattern = PATTERN(mem); > > + if (GET_CODE(pattern) != SET) > > + return; > > + > > + rtx mem_dst = SET_DEST(PATTERN(mem)); > > + rtx mem_src = SET_SRC(PATTERN(mem)); > > + > > + if (MEM_P(mem_src)) > > + XEXP(mem_src, 0) = addr; > > + else if (MEM_P(mem_dst)) > > + XEXP(mem_dst, 0) = addr; > > + else if ((GET_CODE(mem_src) == ZERO_EXTEND || > > + GET_CODE(mem_src) == SIGN_EXTEND) && > > + MEM_P(XEXP(mem_src, 0))) > > + XEXP(XEXP(mem_src, 0), 0) = addr; > > +} > > + > > +// Add new relocation types for add and ld/st memory instructions to > > +// ensure that subsequent address calculations are correct. > > +// 1. Relace the add insn by new add insn with base idx relocation type. > > +// 2. Update the add insn which uses lo_sum dst to use high dst instead. > > +// 3. Update the mem_addr to use lo_sum of new add insn dst and regrel > > +// relocation type. > > +static void riscv_base_idx_sym_emit(rtx_insn *hi, rtx_insn *lo, rtx_insn > > *add, > > + rtx_insn *mem) { > > + rtx_insn *mem_insn = NULL; > > + > > + rtx hi_set = single_set(hi); > > + rtx lo_set = single_set(lo); > > + rtx add_set = single_set(add); > > + > > + rtx hi_dst = SET_DEST(hi_set); > > + rtx lo_dst = SET_DEST(lo_set); > > + rtx lo_src = SET_SRC(lo_set); > > + // get symbol operand > > + rtx lo_op1 = XEXP(lo_src, 1); > > + > > + rtx add_dst = SET_DEST(add_set); > > + rtx add_src = SET_SRC(add_set); > > + rtx add_op0 = XEXP(add_src, 0); > > + rtx add_op1 = XEXP(add_src, 1); > > + > > + machine_mode mode = GET_MODE(add_dst); > > + enum riscv_symbol_type symbol_type; > > + > > + // get the insert place for add_insn > > + rtx_insn *add_prev = PREV_INSN(add); > > + rtx add_with_rel = NULL_RTX; > > + if (TARGET_ZBA && GET_CODE(add_op0) == ASHIFT) { > > + // lo_sum will lowering to mem_addr, so we need to update inst that > > uses > > + // lo_sum dst to use high dst instead Replace shxadd dst, src0, hi_dst, > > + // %shxadd_regrel to shxadd dst, src0, lo_dst > > + add_with_rel = riscv_base_idx_shxadd(add_dst, add_op0, hi_dst, lo_op1); > > + } else if (GET_CODE(add_op0) == REG) { > > + // Replace add dst, src1, hi_dst, %base_idx_add(sym) to add dst, > > lo_dst, > > + // src1 > > + add_with_rel = riscv_base_idx_add(add_dst, add_op1, hi_dst, lo_op1); > > + } else if (TARGET_64BIT && TARGET_ZBA && GET_CODE(add_op0) == AND) { > > + // Replace shxadd.uw dst, src0, hi_dst, %shxadd_regrel to shxadd dst, > > src0, > > + // lo_dst > > + rtx ashift = XEXP( > > + add_op0, 0); // Get ashift from (and:DI (ashift:DI src0 shift) > > mask) > > + rtx and_mask = > > + XEXP(add_op0, 1); // Get mask from (and:DI (ashift:DI ...) mask) > > + add_with_rel = > > + riscv_base_idx_shxadduw(add_dst, ashift, and_mask, hi_dst, lo_op1); > > + } else if (TARGET_64BIT && TARGET_ZBA && GET_CODE(add_op0) == > > ZERO_EXTEND) { > > + // add_op0 is (zero_extend:DI (SI_operand)) > > + rtx si_operand = XEXP(add_op0, 0); > > + // Replace add.uw dst, src0, hi_dst, %add_regrel to add dst, src0, > > lo_dst. > > + add_with_rel = riscv_base_idx_adduw(add_dst, si_operand, hi_dst, > > lo_op1); > > + } > > + > > + if (add_with_rel) { > > + symbol_type = SYMBOL_BASE_IDX_ADD; > > + emit_insn_after(add_with_rel, add_prev); > > + } > > + > > + // Update mem_addr to use lo_sum of new add insn dst and relocation > > + rtx addr = > > + gen_rtx_LO_SUM(mode, add_dst, riscv_unspec_address(lo_op1, > > symbol_type)); > > + // lo_sum will lowering to mem_addr > > + set_mem_address(mem, addr); > > + > > + rtx_insn *mem_prev = PREV_INSN(mem); > > + mem_insn = emit_insn_after(single_set(mem), mem_prev); > > + if (INSN_P(mem_insn)) { > > + rtx note = find_reg_note(mem, REG_DEAD, NULL_RTX); > > + if (note) { > > + add_reg_note(mem_insn, REG_DEAD, XEXP(note, 0)); > > + } > > + } > > + > > + delete_insn(add); > > + delete_insn(lo); > > + delete_insn(mem); > > + df_insn_rescan(mem_insn); > > + df_analyze(); > > +} > > + > > /* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise > > it appears in a MEM of that mode. Return true if ADDR is a legitimate > > constant in that context and can be split into high and low parts. > > @@ -7780,6 +7947,10 @@ riscv_print_operand_reloc (FILE *file, rtx op, bool > > hi_reloc) > > reloc = hi_reloc ? "%hi" : "%lo"; > > break; > > > > + case SYMBOL_BASE_IDX_ADD: > > + reloc = hi_reloc ? "%base_idx_add" : "%base_idx_lo"; > > + break; > > + > > case SYMBOL_PCREL: > > reloc = hi_reloc ? "%pcrel_hi" : "%pcrel_lo"; > > break; > > @@ -16611,6 +16782,9 @@ riscv_prefetch_offset_address_p (rtx x, > > machine_mode mode) > > #undef TARGET_NOCE_CONVERSION_PROFITABLE_P > > #define TARGET_NOCE_CONVERSION_PROFITABLE_P > > riscv_noce_conversion_profitable_p > > > > +#undef TARGET_BASE_IDX_SYM_EMIT > > +#define TARGET_BASE_IDX_SYM_EMIT riscv_base_idx_sym_emit > > + > > Drop TARGET_BASE_IDX_SYM_EMIT define and move riscv_base_idx_sym_emit > to that pass. > > > #undef TARGET_ASM_FILE_START > > #define TARGET_ASM_FILE_START riscv_file_start > > #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE > > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md > > index 3fe0ad0ccdf..922f6cdd550 100644 > > --- a/gcc/config/riscv/riscv.md > > +++ b/gcc/config/riscv/riscv.md > > @@ -49,6 +49,8 @@ > > UNSPEC_TLS_IE > > UNSPEC_TLS_GD > > UNSPEC_TLSDESC > > + ;; Relax the non-constant subscript addressing of global arrays > > + UNSPEC_BASE_IDX_ADD > > ;; High part of PC-relative address. > > UNSPEC_AUIPC > > > > @@ -2602,6 +2604,18 @@ > > [(set_attr "type" "arith") > > (set_attr "mode" "HI")]) > > > > +(define_insn "base_idx_add<mode>" > > Add @ to the name, same trick as base_idx_shxadd can be used here. > > > diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi > > index 5edddd7f36e..3c1cdf799b7 100644 > > --- a/gcc/doc/tm.texi > > +++ b/gcc/doc/tm.texi > > @@ -7471,6 +7471,10 @@ scheduler from undoing address optimizations. The > > instruction containing the > > memref is @var{insn}. The default implementation returns @code{true}. > > @end deftypefn > > > > +@deftypefn {Target Hook} void TARGET_BASE_IDX_SYM_EMIT (rtx_insn > > *@var{hi}, rtx_insn *@var{lo}, rtx_insn *@var{add}, rtx_insn *@var{mem}) > > +This hook will add new Relocs for global array non-const addressing > > optimization > > +@end deftypefn > > + > > Drop this. > > > --- a/gcc/doc/tm.texi.in > > +++ b/gcc/doc/tm.texi.in > > @@ -4794,6 +4794,8 @@ Define this macro if a non-short-circuit operation > > produced by > > > > @hook TARGET_NEW_ADDRESS_PROFITABLE_P > > > > +@hook TARGET_BASE_IDX_SYM_EMIT > > + > > Drop this. > > > @hook TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P > > > > @hook TARGET_ESTIMATED_POLY_VALUE > > diff --git a/gcc/target.def b/gcc/target.def > > index a9fcce7850f..f867504c900 100644 > > --- a/gcc/target.def > > +++ b/gcc/target.def > > @@ -4195,6 +4195,12 @@ candidate as a replacement for the if-convertible > > sequence described in\n\ > > bool, (rtx_insn *seq, struct noce_if_info *if_info), > > default_noce_conversion_profitable_p) > > > > +DEFHOOK > > +(base_idx_sym_emit, > > + "This hook will add new Relocs for global array non-const addressing > > optimization", > > +void, (rtx_insn *hi, rtx_insn *lo, rtx_insn *add, rtx_insn *mem), > > +default_base_idx_sym_emit) > > + > > Drop this. > > > /* Return true if new_addr should be preferred over the existing address > > used by > > memref in insn. */ > > DEFHOOK > > diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc > > index 5f1eac75122..99625ad0f91 100644 > > --- a/gcc/targhooks.cc > > +++ b/gcc/targhooks.cc > > @@ -1856,6 +1856,9 @@ default_new_address_profitable_p (rtx memref > > ATTRIBUTE_UNUSED, > > return true; > > } > > > > +void default_base_idx_sym_emit(rtx_insn *, rtx_insn *, rtx_insn *, > > rtx_insn *) { > > +} > > + > > Drop this. > > > bool > > default_target_option_valid_attribute_p (tree ARG_UNUSED (fndecl), > > tree ARG_UNUSED (name), > > diff --git a/gcc/targhooks.h b/gcc/targhooks.h > > index 9582233e69f..309575caa31 100644 > > --- a/gcc/targhooks.h > > +++ b/gcc/targhooks.h > > @@ -196,6 +196,8 @@ extern unsigned int default_hard_regno_nregs (unsigned > > int, machine_mode); > > extern bool default_hard_regno_scratch_ok (unsigned int); > > extern bool default_mode_dependent_address_p (const_rtx, addr_space_t); > > extern bool default_new_address_profitable_p (rtx, rtx_insn *, rtx); > > +extern void default_base_idx_sym_emit(rtx_insn *, rtx_insn *, rtx_insn *, > > + rtx_insn *); > > Drop this. > > > extern bool default_target_option_valid_attribute_p (tree, tree, tree, > > int); > > extern bool default_target_option_valid_version_attribute_p (tree, tree, > > tree, int); > > extern bool default_target_option_pragma_parse (tree, tree);
