Skip to content

Commit

Permalink
arm: [MVE intrinsics] add viddup shape
Browse files Browse the repository at this point in the history
This patch adds the viddup shape description for vidup and vddup.

This requires the addition of report_not_one_of and
function_checker::require_immediate_one_of to
gcc/config/arm/arm-mve-builtins.cc (they are copies of the aarch64 SVE
counterpart).

This patch also introduces MODE_wb.

2024-08-21  Christophe Lyon  <christophe.lyon@linaro.org>

	gcc/

	* config/arm/arm-mve-builtins-shapes.cc (viddup): New.
	* config/arm/arm-mve-builtins-shapes.h (viddup): New.
	* config/arm/arm-mve-builtins.cc (report_not_one_of): New.
	(function_checker::require_immediate_one_of): New.
	* config/arm/arm-mve-builtins.def (wb): New mode.
	* config/arm/arm-mve-builtins.h (function_checker) Add
	require_immediate_one_of.
  • Loading branch information
Christophe Lyon committed Oct 18, 2024
1 parent 387b121 commit e38566a
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 0 deletions.
85 changes: 85 additions & 0 deletions gcc/config/arm/arm-mve-builtins-shapes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2191,6 +2191,91 @@ struct vcvtx_def : public overloaded_base<0>
};
SHAPE (vcvtx)

/* <T0>_t vfoo[_n]_t0(uint32_t, const int)
<T0>_t vfoo[_wb]_t0(uint32_t *, const int)
Shape for vector increment or decrement and duplicate operations that take
an integer or pointer to integer first argument and an immediate, and
produce a vector.
Check that 'imm' is one of 1, 2, 4 or 8.
Example: vddupq.
uint8x16_t [__arm_]vddupq[_n]_u8(uint32_t a, const int imm)
uint8x16_t [__arm_]vddupq[_wb]_u8(uint32_t *a, const int imm)
uint8x16_t [__arm_]vddupq_m[_n_u8](uint8x16_t inactive, uint32_t a, const int imm, mve_pred16_t p)
uint8x16_t [__arm_]vddupq_m[_wb_u8](uint8x16_t inactive, uint32_t *a, const int imm, mve_pred16_t p)
uint8x16_t [__arm_]vddupq_x[_n]_u8(uint32_t a, const int imm, mve_pred16_t p)
uint8x16_t [__arm_]vddupq_x[_wb]_u8(uint32_t *a, const int imm, mve_pred16_t p) */
struct viddup_def : public overloaded_base<0>
{
bool
explicit_type_suffix_p (unsigned int i, enum predication_index pred,
enum mode_suffix_index,
type_suffix_info) const override
{
return ((i == 0) && (pred != PRED_m));
}

bool
skip_overload_p (enum predication_index, enum mode_suffix_index mode) const override
{
/* For MODE_wb, share the overloaded instance with MODE_n. */
if (mode == MODE_wb)
return true;

return false;
}

void
build (function_builder &b, const function_group_info &group,
bool preserve_user_namespace) const override
{
b.add_overloaded_functions (group, MODE_none, preserve_user_namespace);
build_all (b, "v0,su32,su64", group, MODE_n, preserve_user_namespace);
build_all (b, "v0,as,su64", group, MODE_wb, preserve_user_namespace);
}

tree
resolve (function_resolver &r) const override
{
unsigned int i, nargs;
type_suffix_index type_suffix = NUM_TYPE_SUFFIXES;
if (!r.check_gp_argument (2, i, nargs))
return error_mark_node;

type_suffix = r.type_suffix_ids[0];
/* With PRED_m, ther is no type suffix, so infer it from the first (inactive)
argument. */
if (type_suffix == NUM_TYPE_SUFFIXES)
type_suffix = r.infer_vector_type (0);

unsigned int last_arg = i - 1;
/* Check that last_arg is either scalar or pointer. */
if (!r.scalar_argument_p (last_arg))
return error_mark_node;

if (!r.require_integer_immediate (last_arg + 1))
return error_mark_node;

/* With MODE_n we expect a scalar, with MODE_wb we expect a pointer. */
mode_suffix_index mode_suffix;
if (POINTER_TYPE_P (r.get_argument_type (last_arg)))
mode_suffix = MODE_wb;
else
mode_suffix = MODE_n;

return r.resolve_to (mode_suffix, type_suffix);
}

bool
check (function_checker &c) const override
{
return c.require_immediate_one_of (1, 1, 2, 4, 8);
}
};
SHAPE (viddup)

/* <T0>_t vfoo[_t0](<T0>_t, <T0>_t, mve_pred16_t)
i.e. a version of the standard ternary shape in which
Expand Down
1 change: 1 addition & 0 deletions gcc/config/arm/arm-mve-builtins-shapes.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ namespace arm_mve
extern const function_shape *const vcvt_f16_f32;
extern const function_shape *const vcvt_f32_f16;
extern const function_shape *const vcvtx;
extern const function_shape *const viddup;
extern const function_shape *const vpsel;

} /* end namespace arm_mve::shapes */
Expand Down
44 changes: 44 additions & 0 deletions gcc/config/arm/arm-mve-builtins.cc
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,20 @@ report_not_enum (location_t location, tree fndecl, unsigned int argno,
" a valid %qT value", actual, argno + 1, fndecl, enumtype);
}

/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
the value ACTUAL, whereas the function requires one of VALUE0..3.
ARGNO counts from zero. */
static void
report_not_one_of (location_t location, tree fndecl, unsigned int argno,
HOST_WIDE_INT actual, HOST_WIDE_INT value0,
HOST_WIDE_INT value1, HOST_WIDE_INT value2,
HOST_WIDE_INT value3)
{
error_at (location, "passing %wd to argument %d of %qE, which expects"
" %wd, %wd, %wd or %wd", actual, argno + 1, fndecl, value0, value1,
value2, value3);
}

/* Checks that the mve.fp extension is enabled, given that REQUIRES_FLOAT
indicates whether it is required or not for function FNDECL.
Report an error against LOCATION if not. */
Expand Down Expand Up @@ -1969,6 +1983,36 @@ function_checker::require_immediate_enum (unsigned int rel_argno, tree type)
return false;
}

/* Check that argument REL_ARGNO is an integer constant expression that
has one of the given values. */
bool
function_checker::require_immediate_one_of (unsigned int rel_argno,
HOST_WIDE_INT value0,
HOST_WIDE_INT value1,
HOST_WIDE_INT value2,
HOST_WIDE_INT value3)
{
unsigned int argno = m_base_arg + rel_argno;
if (!argument_exists_p (argno))
return true;

HOST_WIDE_INT actual;
if (!require_immediate (argno, actual))
return false;

if (actual != value0
&& actual != value1
&& actual != value2
&& actual != value3)
{
report_not_one_of (location, fndecl, argno, actual,
value0, value1, value2, value3);
return false;
}

return true;
}

/* Check that argument REL_ARGNO is an integer constant expression in the
range [MIN, MAX]. REL_ARGNO counts from the end of the predication
arguments. */
Expand Down
1 change: 1 addition & 0 deletions gcc/config/arm/arm-mve-builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
DEF_MVE_MODE (n, none, none, none)
DEF_MVE_MODE (offset, none, none, bytes)
DEF_MVE_MODE (r, none, none, none)
DEF_MVE_MODE (wb, none, none, none)

#define REQUIRES_FLOAT false
DEF_MVE_TYPE (mve_pred16_t, boolean_type_node)
Expand Down
2 changes: 2 additions & 0 deletions gcc/config/arm/arm-mve-builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,8 @@ class function_checker : public function_call_info

bool require_immediate_enum (unsigned int, tree);
bool require_immediate_lane_index (unsigned int, unsigned int = 1);
bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
HOST_WIDE_INT, HOST_WIDE_INT);
bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);

bool check ();
Expand Down

0 comments on commit e38566a

Please sign in to comment.