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);

Reply via email to