Skip to content

Commit

Permalink
RISC-V: Support segment intrinsics
Browse files Browse the repository at this point in the history
Add segment load/store intrinsics:
riscv-non-isa/rvv-intrinsic-doc#198

gcc/ChangeLog:

	* config/riscv/riscv-vector-builtins-bases.cc (fold_fault_load):
	New function.
	(class vlseg): New class.
	(class vsseg): Ditto.
	(class vlsseg): Ditto.
	(class vssseg): Ditto.
	(class seg_indexed_load): Ditto.
	(class seg_indexed_store): Ditto.
	(class vlsegff): Ditto.
	(BASE): Ditto.
	* config/riscv/riscv-vector-builtins-bases.h: Ditto.
	* config/riscv/riscv-vector-builtins-functions.def (vlseg):
	Ditto.
	(vsseg): Ditto.
	(vlsseg): Ditto.
	(vssseg): Ditto.
	(vluxseg): Ditto.
	(vloxseg): Ditto.
	(vsuxseg): Ditto.
	(vsoxseg): Ditto.
	(vlsegff): Ditto.
	* config/riscv/riscv-vector-builtins-shapes.cc (struct
	seg_loadstore_def): Ditto.
	(struct seg_indexed_loadstore_def): Ditto.
	(struct seg_fault_load_def): Ditto.
	(SHAPE): Ditto.
	* config/riscv/riscv-vector-builtins-shapes.h: Ditto.
	* config/riscv/riscv-vector-builtins.cc
	(function_builder::append_nf): New function.
	* config/riscv/riscv-vector-builtins.def (vfloat32m1x2_t):
	Change ptr from double into float.
	(vfloat32m1x3_t): Ditto.
	(vfloat32m1x4_t): Ditto.
	(vfloat32m1x5_t): Ditto.
	(vfloat32m1x6_t): Ditto.
	(vfloat32m1x7_t): Ditto.
	(vfloat32m1x8_t): Ditto.
	(vfloat32m2x2_t): Ditto.
	(vfloat32m2x3_t): Ditto.
	(vfloat32m2x4_t): Ditto.
	(vfloat32m4x2_t): Ditto.
	* config/riscv/riscv-vector-builtins.h: Add segment intrinsics.
	* config/riscv/riscv-vsetvl.cc (fault_first_load_p): Adapt for
	segment ff load.
	* config/riscv/riscv.md: Add segment instructions.
	* config/riscv/vector-iterators.md: Support segment intrinsics.
	* config/riscv/vector.md (@pred_unit_strided_load<mode>): New
	pattern.
	(@pred_unit_strided_store<mode>): Ditto.
	(@pred_strided_load<mode>): Ditto.
	(@pred_strided_store<mode>): Ditto.
	(@pred_fault_load<mode>): Ditto.
	(@pred_indexed_<order>load<V1T:mode><V1I:mode>): Ditto.
	(@pred_indexed_<order>load<V2T:mode><V2I:mode>): Ditto.
	(@pred_indexed_<order>load<V4T:mode><V4I:mode>): Ditto.
	(@pred_indexed_<order>load<V8T:mode><V8I:mode>): Ditto.
	(@pred_indexed_<order>load<V16T:mode><V16I:mode>): Ditto.
	(@pred_indexed_<order>load<V32T:mode><V32I:mode>): Ditto.
	(@pred_indexed_<order>load<V64T:mode><V64I:mode>): Ditto.
	(@pred_indexed_<order>store<V1T:mode><V1I:mode>): Ditto.
	(@pred_indexed_<order>store<V2T:mode><V2I:mode>): Ditto.
	(@pred_indexed_<order>store<V4T:mode><V4I:mode>): Ditto.
	(@pred_indexed_<order>store<V8T:mode><V8I:mode>): Ditto.
	(@pred_indexed_<order>store<V16T:mode><V16I:mode>): Ditto.
	(@pred_indexed_<order>store<V32T:mode><V32I:mode>): Ditto.
	(@pred_indexed_<order>store<V64T:mode><V64I:mode>): Ditto.

Signed-off-by: Ju-Zhe Zhong <juzhe.zhong@rivai.ai>
  • Loading branch information
zhongjuzhe authored and Liaoshihua committed Mar 12, 2024
1 parent 678d6cd commit edf5b0d
Show file tree
Hide file tree
Showing 12 changed files with 1,325 additions and 118 deletions.
270 changes: 227 additions & 43 deletions gcc/config/riscv/riscv-vector-builtins-bases.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,54 @@ enum lst_type
LST_INDEXED,
};

/* Helper function to fold vleff and vlsegff. */
static gimple *
fold_fault_load (gimple_folder &f)
{
/* fold fault_load (const *base, size_t *new_vl, size_t vl)
====> fault_load (const *base, size_t vl)
new_vl = MEM_REF[read_vl ()]. */

auto_vec<tree> vargs (gimple_call_num_args (f.call) - 1);

for (unsigned i = 0; i < gimple_call_num_args (f.call); i++)
{
/* Exclude size_t *new_vl argument. */
if (i == gimple_call_num_args (f.call) - 2)
continue;

vargs.quick_push (gimple_call_arg (f.call, i));
}

gimple *repl = gimple_build_call_vec (gimple_call_fn (f.call), vargs);
gimple_call_set_lhs (repl, f.lhs);

/* Handle size_t *new_vl by read_vl. */
tree new_vl = gimple_call_arg (f.call, gimple_call_num_args (f.call) - 2);
if (integer_zerop (new_vl))
{
/* This case happens when user passes the nullptr to new_vl argument.
In this case, we just need to ignore the new_vl argument and return
fault_load instruction directly. */
return repl;
}

tree tmp_var = create_tmp_var (size_type_node, "new_vl");
tree decl = get_read_vl_decl ();
gimple *g = gimple_build_call (decl, 0);
gimple_call_set_lhs (g, tmp_var);
tree indirect
= fold_build2 (MEM_REF, size_type_node,
gimple_call_arg (f.call, gimple_call_num_args (f.call) - 2),
build_int_cst (build_pointer_type (size_type_node), 0));
gassign *assign = gimple_build_assign (indirect, tmp_var);

gsi_insert_after (f.gsi, assign, GSI_SAME_STMT);
gsi_insert_after (f.gsi, g, GSI_SAME_STMT);
return repl;
}

/* Implements vsetvl<mode> && vsetvlmax<mode>. */
template<bool VLMAX_P>
class vsetvl : public function_base
Expand Down Expand Up @@ -1655,49 +1703,7 @@ class vleff : public function_base

gimple *fold (gimple_folder &f) const override
{
/* fold vleff (const *base, size_t *new_vl, size_t vl)
====> vleff (const *base, size_t vl)
new_vl = MEM_REF[read_vl ()]. */

auto_vec<tree> vargs (gimple_call_num_args (f.call) - 1);

for (unsigned i = 0; i < gimple_call_num_args (f.call); i++)
{
/* Exclude size_t *new_vl argument. */
if (i == gimple_call_num_args (f.call) - 2)
continue;

vargs.quick_push (gimple_call_arg (f.call, i));
}

gimple *repl = gimple_build_call_vec (gimple_call_fn (f.call), vargs);
gimple_call_set_lhs (repl, f.lhs);

/* Handle size_t *new_vl by read_vl. */
tree new_vl = gimple_call_arg (f.call, gimple_call_num_args (f.call) - 2);
if (integer_zerop (new_vl))
{
/* This case happens when user passes the nullptr to new_vl argument.
In this case, we just need to ignore the new_vl argument and return
vleff instruction directly. */
return repl;
}

tree tmp_var = create_tmp_var (size_type_node, "new_vl");
tree decl = get_read_vl_decl ();
gimple *g = gimple_build_call (decl, 0);
gimple_call_set_lhs (g, tmp_var);
tree indirect
= fold_build2 (MEM_REF, size_type_node,
gimple_call_arg (f.call,
gimple_call_num_args (f.call) - 2),
build_int_cst (build_pointer_type (size_type_node), 0));
gassign *assign = gimple_build_assign (indirect, tmp_var);

gsi_insert_after (f.gsi, assign, GSI_SAME_STMT);
gsi_insert_after (f.gsi, g, GSI_SAME_STMT);
return repl;
return fold_fault_load (f);
}

rtx expand (function_expander &e) const override
Expand All @@ -1722,6 +1728,166 @@ class vlenb : public function_base
}
};

/* Implements vlseg.v. */
class vlseg : public function_base
{
public:
unsigned int call_properties (const function_instance &) const override
{
return CP_READ_MEMORY;
}

bool can_be_overloaded_p (enum predication_type_index pred) const override
{
return pred != PRED_TYPE_none && pred != PRED_TYPE_mu;
}

rtx expand (function_expander &e) const override
{
return e.use_exact_insn (
code_for_pred_unit_strided_load (e.vector_mode ()));
}
};

/* Implements vsseg.v. */
class vsseg : public function_base
{
public:
bool apply_tail_policy_p () const override { return false; }
bool apply_mask_policy_p () const override { return false; }

unsigned int call_properties (const function_instance &) const override
{
return CP_WRITE_MEMORY;
}

bool can_be_overloaded_p (enum predication_type_index) const override
{
return true;
}

rtx expand (function_expander &e) const override
{
return e.use_exact_insn (
code_for_pred_unit_strided_store (e.vector_mode ()));
}
};

/* Implements vlsseg.v. */
class vlsseg : public function_base
{
public:
unsigned int call_properties (const function_instance &) const override
{
return CP_READ_MEMORY;
}

bool can_be_overloaded_p (enum predication_type_index pred) const override
{
return pred != PRED_TYPE_none && pred != PRED_TYPE_mu;
}

rtx expand (function_expander &e) const override
{
return e.use_exact_insn (
code_for_pred_strided_load (e.vector_mode ()));
}
};

/* Implements vssseg.v. */
class vssseg : public function_base
{
public:
bool apply_tail_policy_p () const override { return false; }
bool apply_mask_policy_p () const override { return false; }

unsigned int call_properties (const function_instance &) const override
{
return CP_WRITE_MEMORY;
}

bool can_be_overloaded_p (enum predication_type_index) const override
{
return true;
}

rtx expand (function_expander &e) const override
{
return e.use_exact_insn (
code_for_pred_strided_store (e.vector_mode ()));
}
};

template<int UNSPEC>
class seg_indexed_load : public function_base
{
public:
unsigned int call_properties (const function_instance &) const override
{
return CP_READ_MEMORY;
}

bool can_be_overloaded_p (enum predication_type_index) const override
{
return true;
}

rtx expand (function_expander &e) const override
{
return e.use_exact_insn (
code_for_pred_indexed_load (UNSPEC, e.vector_mode (), e.index_mode ()));
}
};

template<int UNSPEC>
class seg_indexed_store : public function_base
{
public:
bool apply_tail_policy_p () const override { return false; }
bool apply_mask_policy_p () const override { return false; }

unsigned int call_properties (const function_instance &) const override
{
return CP_WRITE_MEMORY;
}

bool can_be_overloaded_p (enum predication_type_index) const override
{
return true;
}

rtx expand (function_expander &e) const override
{
return e.use_exact_insn (
code_for_pred_indexed_store (UNSPEC, e.vector_mode (), e.index_mode ()));
}
};

/* Implements vlsegff.v. */
class vlsegff : public function_base
{
public:
unsigned int call_properties (const function_instance &) const override
{
return CP_READ_MEMORY | CP_WRITE_CSR;
}

bool can_be_overloaded_p (enum predication_type_index pred) const override
{
return pred != PRED_TYPE_none && pred != PRED_TYPE_mu;
}

gimple *fold (gimple_folder &f) const override
{
return fold_fault_load (f);
}

rtx expand (function_expander &e) const override
{
return e.use_exact_insn (code_for_pred_fault_load (e.vector_mode ()));
}
};

static CONSTEXPR const vsetvl<false> vsetvl_obj;
static CONSTEXPR const vsetvl<true> vsetvlmax_obj;
static CONSTEXPR const loadstore<false, LST_UNIT_STRIDE, false> vle_obj;
Expand Down Expand Up @@ -1933,6 +2099,15 @@ static CONSTEXPR const vget vget_obj;
static CONSTEXPR const read_vl read_vl_obj;
static CONSTEXPR const vleff vleff_obj;
static CONSTEXPR const vlenb vlenb_obj;
static CONSTEXPR const vlseg vlseg_obj;
static CONSTEXPR const vsseg vsseg_obj;
static CONSTEXPR const vlsseg vlsseg_obj;
static CONSTEXPR const vssseg vssseg_obj;
static CONSTEXPR const seg_indexed_load<UNSPEC_UNORDERED> vluxseg_obj;
static CONSTEXPR const seg_indexed_load<UNSPEC_ORDERED> vloxseg_obj;
static CONSTEXPR const seg_indexed_store<UNSPEC_UNORDERED> vsuxseg_obj;
static CONSTEXPR const seg_indexed_store<UNSPEC_ORDERED> vsoxseg_obj;
static CONSTEXPR const vlsegff vlsegff_obj;

/* Declare the function base NAME, pointing it to an instance
of class <NAME>_obj. */
Expand Down Expand Up @@ -2150,5 +2325,14 @@ BASE (vget)
BASE (read_vl)
BASE (vleff)
BASE (vlenb)
BASE (vlseg)
BASE (vsseg)
BASE (vlsseg)
BASE (vssseg)
BASE (vluxseg)
BASE (vloxseg)
BASE (vsuxseg)
BASE (vsoxseg)
BASE (vlsegff)

} // end namespace riscv_vector
9 changes: 9 additions & 0 deletions gcc/config/riscv/riscv-vector-builtins-bases.h
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,15 @@ extern const function_base *const vget;
extern const function_base *const read_vl;
extern const function_base *const vleff;
extern const function_base *const vlenb;
extern const function_base *const vlseg;
extern const function_base *const vsseg;
extern const function_base *const vlsseg;
extern const function_base *const vssseg;
extern const function_base *const vluxseg;
extern const function_base *const vloxseg;
extern const function_base *const vsuxseg;
extern const function_base *const vsoxseg;
extern const function_base *const vlsegff;
}

} // end namespace riscv_vector
Expand Down
21 changes: 21 additions & 0 deletions gcc/config/riscv/riscv-vector-builtins-functions.def
Original file line number Diff line number Diff line change
Expand Up @@ -536,5 +536,26 @@ DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_lmul4_x2_ops)
// Tuple types
DEF_RVV_FUNCTION (vset, vset, none_preds, all_v_vset_tuple_ops)
DEF_RVV_FUNCTION (vget, vget, none_preds, all_v_vget_tuple_ops)
DEF_RVV_FUNCTION (vlseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ops)
DEF_RVV_FUNCTION (vsseg, seg_loadstore, none_m_preds, tuple_v_scalar_ptr_ops)
DEF_RVV_FUNCTION (vlsseg, seg_loadstore, full_preds, tuple_v_scalar_const_ptr_ptrdiff_ops)
DEF_RVV_FUNCTION (vssseg, seg_loadstore, none_m_preds, tuple_v_scalar_ptr_ptrdiff_ops)
DEF_RVV_FUNCTION (vluxseg, seg_indexed_loadstore, full_preds, tuple_v_scalar_const_ptr_eew8_index_ops)
DEF_RVV_FUNCTION (vluxseg, seg_indexed_loadstore, full_preds, tuple_v_scalar_const_ptr_eew16_index_ops)
DEF_RVV_FUNCTION (vluxseg, seg_indexed_loadstore, full_preds, tuple_v_scalar_const_ptr_eew32_index_ops)
DEF_RVV_FUNCTION (vluxseg, seg_indexed_loadstore, full_preds, tuple_v_scalar_const_ptr_eew64_index_ops)
DEF_RVV_FUNCTION (vloxseg, seg_indexed_loadstore, full_preds, tuple_v_scalar_const_ptr_eew8_index_ops)
DEF_RVV_FUNCTION (vloxseg, seg_indexed_loadstore, full_preds, tuple_v_scalar_const_ptr_eew16_index_ops)
DEF_RVV_FUNCTION (vloxseg, seg_indexed_loadstore, full_preds, tuple_v_scalar_const_ptr_eew32_index_ops)
DEF_RVV_FUNCTION (vloxseg, seg_indexed_loadstore, full_preds, tuple_v_scalar_const_ptr_eew64_index_ops)
DEF_RVV_FUNCTION (vsuxseg, seg_indexed_loadstore, none_m_preds, tuple_v_scalar_ptr_eew8_index_ops)
DEF_RVV_FUNCTION (vsuxseg, seg_indexed_loadstore, none_m_preds, tuple_v_scalar_ptr_eew16_index_ops)
DEF_RVV_FUNCTION (vsuxseg, seg_indexed_loadstore, none_m_preds, tuple_v_scalar_ptr_eew32_index_ops)
DEF_RVV_FUNCTION (vsuxseg, seg_indexed_loadstore, none_m_preds, tuple_v_scalar_ptr_eew64_index_ops)
DEF_RVV_FUNCTION (vsoxseg, seg_indexed_loadstore, none_m_preds, tuple_v_scalar_ptr_eew8_index_ops)
DEF_RVV_FUNCTION (vsoxseg, seg_indexed_loadstore, none_m_preds, tuple_v_scalar_ptr_eew16_index_ops)
DEF_RVV_FUNCTION (vsoxseg, seg_indexed_loadstore, none_m_preds, tuple_v_scalar_ptr_eew32_index_ops)
DEF_RVV_FUNCTION (vsoxseg, seg_indexed_loadstore, none_m_preds, tuple_v_scalar_ptr_eew64_index_ops)
DEF_RVV_FUNCTION (vlsegff, seg_fault_load, full_preds, tuple_v_scalar_const_ptr_size_ptr_ops)

#undef DEF_RVV_FUNCTION
Loading

0 comments on commit edf5b0d

Please sign in to comment.