public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [SVE ACLE] Two infrastructure tweaks
@ 2019-01-10 14:47 Richard Sandiford
  0 siblings, 0 replies; only message in thread
From: Richard Sandiford @ 2019-01-10 14:47 UTC (permalink / raw)
  To: gcc-patches; +Cc: Kugan Vivekanandarajah, Prathamesh Kulkarni

[-- Attachment #1: Type: text/plain, Size: 379 bytes --]

Hi,

The first patch replaces the autogenerated function enum with an
explicit one, so that we can have more than one .def entry with
the same function base name (e.g. predicated AND vs. integer AND).

The second patch makes us get the expected modes from the insn data,
rather than force callers to supply the modes explicitly.

Committed to aarch64/sve-acle-branch.

Richard



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: explicit-function-enum.patch --]
[-- Type: text/x-diff, Size: 9416 bytes --]

[SVE ACLE] Don't autogenerate the function enum

We need to be able to specify two .def entries with the same function
base name.  This patch does that by specifying the function enum
explicitly and using a separate enum for the .def file entries.

There is no change in behaviour.


diff --git a/gcc/config/aarch64/aarch64-sve-builtins.c b/gcc/config/aarch64/aarch64-sve-builtins.c
index 6b4018c0e45..a439fb9358e 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.c
+++ b/gcc/config/aarch64/aarch64-sve-builtins.c
@@ -147,9 +147,28 @@ typedef enum type_suffix type_suffix_pair[2];
 
 /* Enumerates the function base names, such as "svadd".  */
 enum function {
-#define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PRED) FUNC_ ## NAME,
+  FUNC_svabd,
+  FUNC_svadd,
+  FUNC_svasrd,
+  FUNC_svdup,
+  FUNC_svindex,
+  FUNC_svmax,
+  FUNC_svmin,
+  FUNC_svmul,
+  FUNC_svptrue,
+  FUNC_svqadd,
+  FUNC_svqsub,
+  FUNC_svsub,
+  FUNC_svsubr
+};
+
+/* Enumerates the function groups defined in aarch64-sve-builtins.def.  */
+#define GROUP_ID(NAME, SHAPE, TYPES, PREDS) \
+  GROUP_##NAME##_##SHAPE##_##TYPES##_##PREDS
+enum group_id {
+#define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
+  GROUP_ID (NAME, SHAPE, TYPES, PREDS),
 #include "aarch64-sve-builtins.def"
-  NUM_FUNCS
 };
 
 /* Static information about each single-predicate or single-vector
@@ -187,6 +206,9 @@ struct type_suffix_info {
 
 /* Static information about a set of functions.  */
 struct function_group {
+  /* The unique identifier of the group.  */
+  group_id id;
+
   /* The base name, as a string and an enum.  */
   const char *name;
   function func;
@@ -209,8 +231,7 @@ struct function_group {
 /* Describes a fully-resolved function (i.e. one that has a unique full
    name).  */
 struct GTY(()) function_instance {
-  function_instance () {}
-  function_instance (function, function_mode, const type_suffix_pair &,
+  function_instance (group_id, function_mode, const type_suffix_pair &,
 		     predication);
 
   bool operator== (const function_instance &) const;
@@ -221,7 +242,7 @@ struct GTY(()) function_instance {
   tree vector_type (unsigned int) const;
 
   /* The explicit "enum"s are required for gengtype.  */
-  enum function func;
+  enum group_id group;
   enum function_mode mode;
   type_suffix_pair types;
   enum predication pred;
@@ -391,6 +412,7 @@ private:
 
   /* The function being called.  */
   const function_instance &m_fi;
+  const function_group &m_group;
 
   /* The call we're folding.  */
   gcall *m_call;
@@ -448,6 +470,7 @@ private:
   /* The function being called.  */
   const registered_function &m_rfn;
   const function_instance &m_fi;
+  const function_group &m_group;
 
   /* The function call expression.  */
   tree m_exp;
@@ -552,7 +575,8 @@ static const predication preds_mxznone[] = { PRED_m, PRED_x, PRED_z,
 /* A list of all SVE ACLE functions.  */
 static const function_group function_groups[] = {
 #define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
-  { #NAME, FUNC_##NAME, SHAPE_##SHAPE, types_##TYPES, preds_##PREDS },
+  { GROUP_ID (NAME, SHAPE, TYPES, PREDS), #NAME, FUNC_##NAME, SHAPE_##SHAPE, \
+    types_##TYPES, preds_##PREDS },
 #include "aarch64-sve-builtins.def"
 };
 
@@ -610,11 +634,11 @@ report_out_of_range (location_t location, tree decl, unsigned int argno,
 }
 
 inline
-function_instance::function_instance (function func_in,
+function_instance::function_instance (group_id group_in,
 				      function_mode mode_in,
 				      const type_suffix_pair &types_in,
 				      predication pred_in)
-  : func (func_in), mode (mode_in), pred (pred_in)
+  : group (group_in), mode (mode_in), pred (pred_in)
 {
   memcpy (types, types_in, sizeof (types));
 }
@@ -622,7 +646,7 @@ function_instance::function_instance (function func_in,
 inline bool
 function_instance::operator== (const function_instance &other) const
 {
-  return (func == other.func
+  return (group == other.group
 	  && mode == other.mode
 	  && pred == other.pred
 	  && types[0] == other.types[0]
@@ -639,7 +663,7 @@ hashval_t
 function_instance::hash () const
 {
   inchash::hash h;
-  h.add_int (func);
+  h.add_int (group);
   h.add_int (mode);
   h.add_int (types[0]);
   h.add_int (types[1]);
@@ -748,7 +772,7 @@ arm_sve_h_builder::build_all (function_signature signature,
   for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
     for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
       {
-	function_instance instance (group.func, mode, group.types[ti],
+	function_instance instance (group.id, mode, group.types[ti],
 				    group.preds[pi]);
 	(this->*signature) (instance, types);
 	apply_predication (instance, types);
@@ -888,9 +912,8 @@ arm_sve_h_builder::add_overloaded_functions (const function_group &group,
       type_suffix_pair prev_types = { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES };
       if (explicit_types == 0)
 	/* One overloaded function for all type combinations.  */
-	add_overloaded_function
-	  (function_instance (group.func, mode, prev_types,
-			      group.preds[pi]));
+	add_overloaded_function (function_instance (group.id, mode, prev_types,
+						    group.preds[pi]));
       else
 	for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
 	     ++ti)
@@ -907,8 +930,8 @@ arm_sve_h_builder::add_overloaded_functions (const function_group &group,
 		&& types[0] == prev_types[0]
 		&& types[1] == prev_types[1])
 	      continue;
-	    add_overloaded_function
-	      (function_instance (group.func, mode, types, group.preds[pi]));
+	    add_overloaded_function (function_instance (group.id, mode, types,
+							group.preds[pi]));
 	    memcpy (prev_types, types, sizeof (types));
 	  }
     }
@@ -957,7 +980,7 @@ tree
 arm_sve_h_builder::get_attributes (const function_instance &instance)
 {
   tree attrs = NULL_TREE;
-  switch (instance.func)
+  switch (function_groups[instance.group].func)
     {
     case FUNC_svabd:
     case FUNC_svadd:
@@ -990,9 +1013,6 @@ arm_sve_h_builder::get_attributes (const function_instance &instance)
       attrs = add_attribute ("const", attrs);
       attrs = add_attribute ("nothrow", attrs);
       break;
-
-    case NUM_FUNCS:
-      break;
     }
   return add_attribute ("leaf", attrs);
 }
@@ -1022,7 +1042,7 @@ char *
 arm_sve_h_builder::get_name (const function_instance &instance,
 			     bool overloaded_p)
 {
-  const function_group &group = function_groups[instance.func];
+  const function_group &group = function_groups[instance.group];
   unsigned int explicit_types
     = (overloaded_p ? get_explicit_types (group.shape) : 3);
 
@@ -1064,7 +1084,7 @@ function_resolver::function_resolver (location_t location,
 				      const registered_function &rfn,
 				      vec<tree, va_gc> &arglist)
   : m_location (location), m_rfn (rfn), m_arglist (arglist),
-    m_group (function_groups[rfn.instance.func])
+    m_group (function_groups[rfn.instance.group])
 {
 }
 
@@ -1333,7 +1353,7 @@ function_resolver::lookup_form (function_mode mode, type_suffix type0,
 				type_suffix type1)
 {
   type_suffix_pair types = { type0, type1 };
-  function_instance instance (m_rfn.instance.func, mode, types,
+  function_instance instance (m_rfn.instance.group, mode, types,
 			      m_rfn.instance.pred);
   registered_function *rfn
     = function_table->find_with_hash (instance, instance.hash ());
@@ -1344,7 +1364,7 @@ function_checker::function_checker (location_t location,
 				    const function_instance &fi, tree decl,
 				    unsigned int nargs, tree *args)
   : m_location (location), m_fi (fi), m_decl (decl), m_nargs (nargs),
-    m_args (args), m_group (function_groups[m_fi.func])
+    m_args (args), m_group (function_groups[m_fi.group])
 {
 }
 
@@ -1527,8 +1547,9 @@ check_builtin_call (location_t location, vec<location_t>, unsigned int code,
 /* Construct a folder for CALL, which calls the SVE function with
    subcode CODE.  */
 gimple_folder::gimple_folder (unsigned int code, gcall *call)
-  : m_fi ((*registered_functions)[code]->instance), m_call (call),
-    m_lhs (gimple_call_lhs (call))
+  : m_fi ((*registered_functions)[code]->instance),
+    m_group (function_groups[m_fi.group]),
+    m_call (call), m_lhs (gimple_call_lhs (call))
 {
 }
 
@@ -1537,7 +1558,7 @@ gimple_folder::gimple_folder (unsigned int code, gcall *call)
 gimple *
 gimple_folder::fold ()
 {
-  switch (m_fi.func)
+  switch (m_group.func)
     {
     case FUNC_svabd:
     case FUNC_svadd:
@@ -1551,7 +1572,6 @@ gimple_folder::fold ()
     case FUNC_svqsub:
     case FUNC_svsub:
     case FUNC_svsubr:
-    case NUM_FUNCS:
       return NULL;
 
     case FUNC_svptrue:
@@ -1592,6 +1612,7 @@ gimple_fold_builtin (unsigned int code, gcall *stmt)
 function_expander::function_expander (unsigned int code, tree exp, rtx target)
   : m_rfn (*(*registered_functions)[code]),
     m_fi (m_rfn.instance),
+    m_group (function_groups[m_fi.group]),
     m_exp (exp), m_location (EXPR_LOCATION (exp)), m_target (target)
 {
 }
@@ -1605,7 +1626,7 @@ function_expander::expand ()
   for (unsigned int i = 0; i < nargs; ++i)
     m_args.quick_push (expand_normal (CALL_EXPR_ARG (m_exp, i)));
 
-  switch (m_fi.func)
+  switch (m_group.func)
     {
     case FUNC_svabd:
       return expand_abd ();
@@ -1645,9 +1666,6 @@ function_expander::expand ()
 
     case FUNC_svsubr:
       return expand_sub (true);
-
-    case NUM_FUNCS:
-      break;
     }
   gcc_unreachable ();
 }

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: modes-from-insn-data.patch --]
[-- Type: text/x-diff, Size: 9147 bytes --]

[SVE ACLE] Get operand modes from insn_data

Specifying the modes of operands explicitly was getting awkward,
and getting the modes from the insn patterns still gives a decent
amount of sanity checking.


diff --git a/gcc/config/aarch64/aarch64-sve-builtins.c b/gcc/config/aarch64/aarch64-sve-builtins.c
index a439fb9358e..46ff17caf86 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.c
+++ b/gcc/config/aarch64/aarch64-sve-builtins.c
@@ -444,10 +444,10 @@ private:
 
   rtx expand_signed_pred_op (rtx_code, rtx_code, int);
   rtx expand_signed_pred_op (int, int, int);
-  rtx expand_via_unpred_direct_optab (optab, unsigned int = 0);
-  rtx expand_via_unpred_insn (insn_code, unsigned int = 0);
+  rtx expand_via_unpred_direct_optab (optab);
+  rtx expand_via_unpred_insn (insn_code);
   rtx expand_via_pred_direct_optab (optab, unsigned int = DEFAULT_MERGE_ARGNO);
-  rtx expand_via_sel_insn (insn_code, unsigned int);
+  rtx expand_via_sel_insn (insn_code);
   rtx expand_via_pred_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
   rtx expand_via_signed_unpred_insn (rtx_code, rtx_code);
   rtx expand_via_pred_x_insn (insn_code);
@@ -462,8 +462,9 @@ private:
   rtx get_fallback_value (machine_mode, unsigned int,
 			  unsigned int, unsigned int &);
 
-  void add_output_operand (machine_mode);
-  void add_input_operand (rtx, machine_mode);
+  machine_mode get_next_operand_mode (insn_code);
+  void add_output_operand (insn_code);
+  void add_input_operand (insn_code, rtx);
   void add_integer_operand (HOST_WIDE_INT);
   rtx generate_insn (insn_code);
 
@@ -1712,21 +1713,16 @@ function_expander::expand_dup ()
 {
   if (m_fi.pred == PRED_none
       || m_fi.pred == PRED_x)
-    return expand_via_unpred_direct_optab (vec_duplicate_optab, 1);
+    return expand_via_unpred_direct_optab (vec_duplicate_optab);
   else
     {
       insn_code icode;
       machine_mode mode = get_mode (0);
       if (valid_for_const_vector_p (GET_MODE_INNER (mode), m_args.last ()))
-	{
-	  icode = code_for_vcond_mask (get_mode (0), get_mode (0));
-	  return expand_via_sel_insn (icode, 0);
-	}
+	icode = code_for_vcond_mask (get_mode (0), get_mode (0));
       else
-	{
-	  icode = code_for_aarch64_sel_dup (get_mode (0));
-	  return expand_via_sel_insn (icode, 1);
-	}
+	icode = code_for_aarch64_sel_dup (get_mode (0));
+      return expand_via_sel_insn (icode);
     }
 }
 
@@ -1734,7 +1730,7 @@ function_expander::expand_dup ()
 rtx
 function_expander::expand_index ()
 {
-  return expand_via_unpred_direct_optab (vec_series_optab, 2);
+  return expand_via_unpred_direct_optab (vec_series_optab);
 }
 
 /* Expand a call to svmax.  */
@@ -1824,36 +1820,28 @@ function_expander::expand_sub (bool reversed_p)
 }
 
 /* Implement the call using optab OP, which is an unpredicated direct
-   (i.e. single-mode) optab.  The last NSCALAR inputs are scalar, and
-   map to scalar operands in the underlying instruction.  */
+   (i.e. single-mode) optab.  */
 rtx
-function_expander::expand_via_unpred_direct_optab (optab op,
-						   unsigned int nscalar)
+function_expander::expand_via_unpred_direct_optab (optab op)
 {
   machine_mode mode = get_mode (0);
   insn_code icode = direct_optab_handler (op, mode);
-  return expand_via_unpred_insn (icode, nscalar);
+  return expand_via_unpred_insn (icode);
 }
 
-/* Implement the call using instruction ICODE.  The last NSCALAR inputs
-   are scalar, and map to scalar operands in the underlying instruction.  */
+/* Implement the call using instruction ICODE.  */
 rtx
-function_expander::expand_via_unpred_insn (insn_code icode,
-					   unsigned int nscalar)
+function_expander::expand_via_unpred_insn (insn_code icode)
 {
   /* Discount the output operand.  */
   unsigned int nops = insn_data[icode].n_operands - 1;
   /* Drop the predicate argument in the case of _x predication.  */
   unsigned int bias = (m_fi.pred == PRED_x ? 1 : 0);
-  machine_mode mode = get_mode (0);
   unsigned int i = 0;
 
-  add_output_operand (mode);
-
-  for (; i < nops - nscalar; ++i)
-    add_input_operand (m_args[i + bias], mode);
+  add_output_operand (icode);
   for (; i < nops; ++i)
-    add_input_operand (m_args[i + bias], GET_MODE_INNER (mode));
+    add_input_operand (icode, m_args[i + bias]);
 
   return generate_insn (icode);
 }
@@ -1876,29 +1864,21 @@ function_expander::expand_via_pred_direct_optab (optab op,
    0: output
    1: true value
    2: false value
-   3: predicate
-
-   The last NSCALAR inputs are scalar, and map to scalar operands
-   in the underlying instruction.  */
+   3: predicate.  */
 rtx
-function_expander::expand_via_sel_insn (insn_code icode,
-					unsigned int nscalar)
+function_expander::expand_via_sel_insn (insn_code icode)
 {
   machine_mode mode = get_mode (0);
-  machine_mode pred_mode = get_pred_mode (0);
 
   unsigned int opno = 0;
   rtx false_arg = get_fallback_value (mode, 1, 0, opno);
   rtx pred_arg = m_args[opno++];
   rtx true_arg = m_args[opno++];
 
-  add_output_operand (mode);
-  if (nscalar)
-    add_input_operand (true_arg, GET_MODE_INNER (mode));
-  else
-    add_input_operand (true_arg, mode);
-  add_input_operand (false_arg, mode);
-  add_input_operand (pred_arg, pred_mode);
+  add_output_operand (icode);
+  add_input_operand (icode, true_arg);
+  add_input_operand (icode, false_arg);
+  add_input_operand (icode, pred_arg);
   return generate_insn (icode);
 }
 
@@ -1915,17 +1895,16 @@ function_expander::expand_via_pred_insn (insn_code icode,
   /* Discount the output, predicate, and fallback value.  */
   unsigned int nops = insn_data[icode].n_operands - 3;
   machine_mode mode = get_mode (0);
-  machine_mode pred_mode = get_pred_mode (0);
 
   unsigned int opno = 0;
   rtx fallback_arg = get_fallback_value (mode, nops, merge_argno, opno);
   rtx pred_arg = m_args[opno++];
 
-  add_output_operand (mode);
-  add_input_operand (pred_arg, pred_mode);
+  add_output_operand (icode);
+  add_input_operand (icode, pred_arg);
   for (unsigned int i = 0; i < nops; ++i)
-    add_input_operand (m_args[opno + i], mode);
-  add_input_operand (fallback_arg, mode);
+    add_input_operand (icode, m_args[opno + i]);
+  add_input_operand (icode, fallback_arg);
   return generate_insn (icode);
 }
 
@@ -1939,10 +1918,10 @@ function_expander::expand_via_pred_x_insn (insn_code icode)
   machine_mode pred_mode = get_pred_mode (0);
 
   /* Add the normal operands.  */
-  add_output_operand (mode);
-  add_input_operand (m_args[0], pred_mode);
+  add_output_operand (icode);
+  add_input_operand (icode, m_args[0]);
   for (unsigned int i = 0; i < nops; ++i)
-    add_input_operand (m_args[i + 1], mode);
+    add_input_operand (icode, m_args[i + 1]);
 
   /* Add a flag that indicates whether unpredicated instructions
      are allowed.  */
@@ -2150,29 +2129,43 @@ function_expander::get_fallback_value (machine_mode mode, unsigned int nops,
   return m_args[merge_argno];
 }
 
-/* Add an output operand of mode MODE to the instruction, binding it
-   to the preferred target rtx if possible.  */
+/* Return the mode of the next operand of the instruction we're building,
+   which has code ICODE.  */
+machine_mode
+function_expander::get_next_operand_mode (insn_code icode)
+{
+  machine_mode mode = insn_data[icode].operand[m_ops.length ()].mode;
+  /* SVE ACLE patterns must specify a mode for every operand.  */
+  gcc_assert (mode != VOIDmode);
+  return mode;
+}
+
+/* Add an output operand to the instruction we're building, which has
+   code ICODE.  Bind the output to the preferred target rtx if possible.  */
 void
-function_expander::add_output_operand (machine_mode mode)
+function_expander::add_output_operand (insn_code icode)
 {
+  machine_mode mode = get_next_operand_mode (icode);
   m_ops.safe_grow (m_ops.length () + 1);
   create_output_operand (&m_ops.last (), m_target, mode);
 }
 
-/* Add an input operand with mode MODE to the instruction.  Calculate
-   the value of the operand as follows:
+/* Add an input operand to the instruction we're building, which has
+   code ICODE.  Calculate the value of the operand as follows:
 
-   - If MODE is a vector and X is not, broadcast X to fill a vector of
-     mode MODE.
+   - If the operand is a vector and X is not, broadcast X to fill a
+     vector of the appropriate mode.
 
-   - Otherwise, if MODE is a predicate mode, coerce X to have that mode.
-     In this case X is known to be VNx16BImode.
+   - Otherwise, if the operand is a predicate, coerce X to have the
+     mode that the instruction expects.  In this case X is known to be
+     VNx16BImode (the mode of svbool_t).
 
-   - Otherwise use X directly.  The expand machinery checks that X is
-     consistent with MODE.  */
+   - Otherwise use X directly.  The expand machinery checks that X has
+     the right mode for the instruction.  */
 void
-function_expander::add_input_operand (rtx x, machine_mode mode)
+function_expander::add_input_operand (insn_code icode, rtx x)
 {
+  machine_mode mode = get_next_operand_mode (icode);
   if (!VECTOR_MODE_P (GET_MODE (x)) && VECTOR_MODE_P (mode))
     x = expand_vector_broadcast (mode, x);
   else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2019-01-10 14:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-10 14:47 [SVE ACLE] Two infrastructure tweaks Richard Sandiford

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).