This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [gen/AArch64] Generate helpers for substituting iterator values into pattern names


On 13/07/18 10:15, Richard Sandiford wrote:
> Given a pattern like:
> 
>   (define_insn "aarch64_frecpe<mode>" ...)
> 
> the SVE ACLE implementation wants to generate the pattern for a
> particular (non-constant) mode.  This patch automatically generates
> helpers to do that, specifically:
> 
>   // Return CODE_FOR_nothing on failure.
>   insn_code maybe_code_for_aarch64_frecpe (machine_mode);
> 
>   // Assert that the code exists.
>   insn_code code_for_aarch64_frecpe (machine_mode);
> 
>   // Return NULL_RTX on failure.
>   rtx maybe_gen_aarch64_frecpe (machine_mode, rtx, rtx);
> 
>   // Assert that generation succeeds.
>   rtx gen_aarch64_frecpe (machine_mode, rtx, rtx);
> 
> Many patterns don't have sensible names when all <...>s are removed.
> E.g. "<optab><mode>2" would give a base name "2".  The new functions
> therefore require explicit opt-in, which should also help to reduce
> code bloat.
> 
> The (arbitrary) opt-in syntax I went for was to prefix the pattern
> name with '@', similarly to the existing '*' marker.
> 
> The patch also makes config/aarch64 use the new routines in cases where
> they obviously apply.  This was mostly straight-forward, but it seemed
> odd that we defined:
> 
>    aarch64_reload_movcp<...><P:mode>
> 
> but then only used it with DImode, never SImode.  If we should be
> using Pmode instead of DImode, then that's a simple change,
> but should probably be a separate patch.
> 
> Tested on aarch64-linux-gnu (with and without SVE), aarch64_be-elf
> and x86_64-linux-gnu.  I think I can self-approve the gen* bits,
> but OK for the AArch64 parts?
> 
> Any objections to this approach or syntax?

So if I have two or more iterator rules in the MD, with a similar
'shape', eg

(define_insn "@fred<all_int:mode>"...

(define_insn "@fred<all_fp:mode>"...

this will generate a single factory function?  If so, that sounds sensible.

(havent looked at the details of the patch, but if James has already
done that, then that should be enough).

R.

> 
> Richard
> 
> 
> 2018-07-13  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* doc/md.texi: Expand the documentation of instruction names
> 	to mention port-local uses.  Document '@' in pattern names.
> 	* read-md.h (overloaded_instance, overloaded_name): New structs.
> 	(mapping): Declare.
> 	(md_reader::handle_overloaded_name): New member function.
> 	(md_reader::get_overloads): Likewise.
> 	(md_reader::m_first_overload): New member variable.
> 	(md_reader::m_next_overload_ptr): Likewise.
> 	(md_reader::m_overloads_htab): Likewise.
> 	* read-md.c (md_reader::md_reader): Initialize m_first_overload,
> 	m_next_overload_ptr and m_overloads_htab.
> 	* read-rtl.c (iterator_group): Add "type" and "get_c_token" fields.
> 	(get_mode_token, get_code_token, get_int_token): New functions.
> 	(map_attr_string): Add an optional argument that passes back
> 	the associated iterator.
> 	(overloaded_name_hash, overloaded_name_eq_p, named_rtx_p):
> 	(md_reader::handle_overloaded_name, add_overload_instance): New
> 	functions.
> 	(apply_iterators): Handle '@' names.  Report an error if '@'
> 	is used without iterators.
> 	(initialize_iterators): Initialize the new iterator_group fields.
> 	* gencodes.c (handle_overloaded_code_for): New function.
> 	(main): Use it to print declarations of maybe_code_for_* functions
> 	and inline definitions of code_for_*.
> 	* genflags.c (emit_overloaded_gen_proto): New function.
> 	(main): Use it to print declarations of maybe_gen_* functions
> 	and inline definitions of gen_*.
> 	* genemit.c (print_overload_arguments, print_overload_test)
> 	(handle_overloaded_code_for, handle_overloaded_gen): New functions.
> 	(main): Use it to print definitions of maybe_code_for_* and
> 	maybe_gen_* functions.
> 	* config/aarch64/aarch64.c (aarch64_split_128bit_move): Use
> 	gen_aarch64_mov{low,high}_di and gen_aarch64_movdi_{low,high}
> 	instead of explicit mode checks.
> 	(aarch64_split_simd_combine): Likewise gen_aarch64_simd_combine.
> 	(aarch64_split_simd_move): Likewise gen_aarch64_split_simd_mov.
> 	(aarch64_emit_load_exclusive): Likewise gen_aarch64_load_exclusive.
> 	(aarch64_emit_store_exclusive): Likewise gen_aarch64_store_exclusive.
> 	(aarch64_expand_compare_and_swap): Likewise
> 	gen_aarch64_compare_and_swap and gen_aarch64_compare_and_swap_lse
> 	(aarch64_gen_atomic_cas): Likewise gen_aarch64_atomic_cas.
> 	(aarch64_emit_atomic_swap): Likewise gen_aarch64_atomic_swp.
> 	(aarch64_constant_pool_reload_icode): Delete.
> 	(aarch64_secondary_reload): Use code_for_aarch64_reload_movcp
> 	instead of aarch64_constant_pool_reload_icode.  Use
> 	code_for_aarch64_reload_mov instead of explicit mode checks.
> 	(rsqrte_type, get_rsqrte_type, rsqrts_type, get_rsqrts_type): Delete.
> 	(aarch64_emit_approx_sqrt): Use gen_aarch64_rsqrte instead of
> 	get_rsqrte_type and gen_aarch64_rsqrts instead of gen_rqrts_type.
> 	(recpe_type, get_recpe_type, recps_type, get_recps_type): Delete.
> 	(aarch64_emit_approx_div): Use gen_aarch64_frecpe instead of
> 	get_recpe_type and gen_aarch64_frecps instead of get_recps_type.
> 	(aarch64_atomic_load_op_code): Delete.
> 	(aarch64_emit_atomic_load_op): Likewise.
> 	(aarch64_gen_atomic_ldop): Use UNSPECV_ATOMIC_* instead of
> 	aarch64_atomic_load_op_code.  Use gen_aarch64_atomic_load
> 	instead of aarch64_emit_atomic_load_op.
> 	* config/aarch64/aarch64.md (aarch64_reload_movcp<GPF_TF:mode><P:mode>)
> 	(aarch64_reload_movcp<VALL:mode><P:mode>, aarch64_reload_mov<mode>)
> 	(aarch64_movdi_<mode>low, aarch64_movdi_<mode>high)
> 	(aarch64_mov<mode>high_di, aarch64_mov<mode>low_di): Add a '@'
> 	character before the pattern name.
> 	* config/aarch64/aarch64-simd.md (aarch64_split_simd_mov<mode>)
> 	(aarch64_rsqrte<mode>, aarch64_rsqrts<mode>)
> 	(aarch64_simd_combine<mode>, aarch64_frecpe<mode>)
> 	(aarch64_frecps<mode>): Likewise.
> 	* config/aarch64/atomics.md (atomic_compare_and_swap<mode>)
> 	(aarch64_compare_and_swap<mode>, aarch64_compare_and_swap<mode>_lse)
> 	(aarch64_load_exclusive<mode>, aarch64_store_exclusive<mode>)
> 	(aarch64_atomic_swp<mode>, aarch64_atomic_cas<mode>)
> 	(aarch64_atomic_load<atomic_ldop><mode>): Likewise.
> 
> Index: gcc/doc/md.texi
> ===================================================================
> --- gcc/doc/md.texi	2018-07-13 10:11:13.533851181 +0100
> +++ gcc/doc/md.texi	2018-07-13 10:11:35.361665853 +0100
> @@ -115,26 +115,37 @@ A @code{define_insn} is an RTL expressio
>  
>  @enumerate
>  @item
> -An optional name.  The presence of a name indicates that this instruction
> -pattern can perform a certain standard job for the RTL-generation
> -pass of the compiler.  This pass knows certain names and will use
> -the instruction patterns with those names, if the names are defined
> -in the machine description.
> +An optional name @var{n}.  When a name is present, the compiler
> +automically generates a C++ function @samp{gen_@var{n}} that takes
> +the operands of the instruction as arguments and returns the instruction's
> +rtx pattern.  The compiler also assigns the instruction a unique code
> +@samp{CODE_FOR_@var{n}}, with all such codes belonging to an enum
> +called @code{insn_code}.
> +
> +These names serve one of two purposes.  The first is to indicate that the
> +instruction performs a certain standard job for the RTL-generation
> +pass of the compiler, such as a move, an addition, or a conditional
> +jump.  The second is to help the target generate certain target-specific
> +operations, such as when implementing target-specific intrinsic functions.
> +
> +It is better to prefix target-specific names with the name of the
> +target, to avoid any clash with current or future standard names.
>  
>  The absence of a name is indicated by writing an empty string
>  where the name should go.  Nameless instruction patterns are never
>  used for generating RTL code, but they may permit several simpler insns
>  to be combined later on.
>  
> -Names that are not thus known and used in RTL-generation have no
> -effect; they are equivalent to no name at all.
> -
>  For the purpose of debugging the compiler, you may also specify a
>  name beginning with the @samp{*} character.  Such a name is used only
>  for identifying the instruction in RTL dumps; it is equivalent to having
>  a nameless pattern for all other purposes.  Names beginning with the
>  @samp{*} character are not required to be unique.
>  
> +The name may also have the form @samp{@@@var{n}}.  This has the same
> +effect as a name @samp{@var{n}}, but in addition tells the compiler to
> +generate further helper functions; see @xref{Parameterized Names} for details.
> +
>  @item
>  The @dfn{RTL template}: This is a vector of incomplete RTL expressions
>  which describe the semantics of the instruction (@pxref{RTL Template}).
> @@ -10476,6 +10487,7 @@ facilities to make this process easier.
>  * Code Iterators::         Doing the same for codes.
>  * Int Iterators::          Doing the same for integers.
>  * Subst Iterators::	   Generating variations of patterns for define_subst.
> +* Parameterized Names::	   Specifying iterator values in C++ code.
>  @end menu
>  
>  @node Mode Iterators
> @@ -10871,4 +10883,99 @@ replaced in the first copy of the origin
>  @var{subst-applied-value} is a value with which subst-attribute would be
>  replaced in the second copy of the original RTL-template.
>  
> +@node Parameterized Names
> +@subsection Parameterized Names
> +@cindex @samp{@@} in instruction pattern names
> +Ports sometimes need to apply iterators using C++ code, in order to
> +get the code or RTL pattern for a specific instruction.  For example,
> +suppose we have the @samp{neon_vq<absneg><mode>} pattern given above:
> +
> +@smallexample
> +(define_int_iterator QABSNEG [UNSPEC_VQABS UNSPEC_VQNEG])
> +
> +(define_int_attr absneg [(UNSPEC_VQABS "abs") (UNSPEC_VQNEG "neg")])
> +
> +(define_insn "neon_vq<absneg><mode>"
> +  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
> +	(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
> +		       (match_operand:SI 2 "immediate_operand" "i")]
> +		      QABSNEG))]
> +  @dots{}
> +)
> +@end smallexample
> +
> +A port might need to generate this pattern for a variable
> +@samp{QABSNEG} value and a variable @samp{VDQIW} mode.  There are two
> +ways of doing this.  The first is to build the rtx for the pattern
> +directly from C++ code; this is a valid technique and avoids any risk
> +of combinatorial explosion.  The second is to prefix the instruction
> +name with the special character @samp{@@}.  This tells GCC to generate
> +the four additional functions below, where @var{name} is the name of
> +the instruction without the @samp{@@} and without the @samp{<@dots{}>}
> +placeholders.
> +
> +@table @samp
> +@item insn_code maybe_code_for_@var{name} (@var{i1}, @var{i2}, @dots{})
> +See whether replacing the first @samp{<@dots{}>} placeholder with
> +iterator value @var{i1}, the second with iterator value @var{i2}, and
> +so on, gives a valid instruction.  Return its code if so, otherwise
> +return @code{CODE_FOR_nothing}.
> +
> +@item insn_code code_for_@var{name} (@var{i1}, @var{i2}, @dots{})
> +Same, but abort the compiler if the requested instruction does not exist.
> +
> +@item rtx maybe_gen_@var{name} (@var{i1}, @var{i2}, @dots{}, @var{op0}, @var{op1}, @dots{})
> +Check for a valid instruction in the same way as
> +@code{maybe_code_for_@var{name}}.  If the instruction exists,
> +generate an instance of it using the operand values given by @var{op0},
> +@var{op1}, and so on, otherwise return null.
> +
> +@item rtx gen_@var{name} (@var{i1}, @var{i2}, @dots{}, @var{op0}, @var{op1}, @dots{})
> +Same, but abort the compiler if the requested instruction does not exist,
> +or if the instruction generator invoked the @code{FAIL} macro.
> +@end table
> +
> +For example, changing the pattern above to:
> +
> +@smallexample
> +(define_insn "@@neon_vq<absneg><mode>"
> +  [(set (match_operand:VDQIW 0 "s_register_operand" "=w")
> +	(unspec:VDQIW [(match_operand:VDQIW 1 "s_register_operand" "w")
> +		       (match_operand:SI 2 "immediate_operand" "i")]
> +		      QABSNEG))]
> +  @dots{}
> +)
> +@end smallexample
> +
> +would define the same patterns as before, but in addition would generate
> +the four functions below:
> +
> +@smallexample
> +insn_code maybe_code_for_neon_vq (int, machine_mode);
> +insn_code code_for_neon_vq (int, machine_mode);
> +rtx maybe_gen_neon_vq (int, machine_mode, rtx, rtx, rtx);
> +rtx gen_neon_vq (int, machine_mode, rtx, rtx, rtx);
> +@end smallexample
> +
> +Calling @samp{code_for_neon_vq (UNSPEC_VQABS, V8QImode)}
> +would then give @code{CODE_FOR_neon_vqabsv8qi}.
> +
> +It is possible to have multiple @samp{@@} patterns with the same
> +name and same types of iterator.  For example:
> +
> +@smallexample
> +(define_insn "@@some_arithmetic_op<mode>"
> +  [(set (match_operand:INTEGER_MODES 0 "register_operand") @dots{})]
> +  @dots{}
> +)
> +
> +(define_insn "@@some_arithmetic_op<mode>"
> +  [(set (match_operand:FLOAT_MODES 0 "register_operand") @dots{})]
> +  @dots{}
> +)
> +@end smallexample
> +
> +would produce a single set of functions that handles both
> +@code{INTEGER_MODES} and @code{FLOAT_MODES}.
> +
>  @end ifset
> Index: gcc/read-md.h
> ===================================================================
> --- gcc/read-md.h	2018-05-02 08:38:14.397364434 +0100
> +++ gcc/read-md.h	2018-07-13 10:11:35.361665853 +0100
> @@ -91,6 +91,48 @@ struct enum_type {
>    unsigned int num_values;
>  };
>  
> +/* Describes one instance of an overloaded_name.  */
> +struct overloaded_instance {
> +  /* The next instance in the chain, or null if none.  */
> +  overloaded_instance *next;
> +
> +  /* The values that the overloaded_name arguments should have for this
> +     instance to be chosen.  Each value is a C token.  */
> +  vec<const char *> arg_values;
> +
> +  /* The full (non-overloaded) name of the pattern.  */
> +  const char *name;
> +
> +  /* The corresponding define_expand or define_insn.  */
> +  rtx insn;
> +};
> +
> +/* Describes a define_expand or define_insn whose name was preceded by '@'.
> +   Overloads are uniquely determined by their name and the types of their
> +   arguments; it's possible to have overloads with the same name but
> +   different argument types.  */
> +struct overloaded_name {
> +  /* The next overloaded name in the chain.  */
> +  overloaded_name *next;
> +
> +  /* The overloaded name (i.e. the name with "@" character and
> +     "<...>" placeholders removed).  */
> +  const char *name;
> +
> +  /* The C types of the iterators that determine the underlying pattern,
> +     in the same order as in the pattern name.  E.g. "<mode>" in the
> +     pattern name would give a "machine_mode" argument here.  */
> +  vec<const char *> arg_types;
> +
> +  /* The first instance associated with this overloaded_name.  */
> +  overloaded_instance *first_instance;
> +
> +  /* Where to chain new overloaded_instances.  */
> +  overloaded_instance **next_instance_ptr;
> +};
> +
> +struct mapping;
> +
>  /* A class for reading .md files and RTL dump files.
>  
>     Implemented in read-md.c.
> @@ -165,6 +207,7 @@ struct enum_type {
>  				      rtx x, unsigned int index,
>  				      const char *name);
>    struct mapping *read_mapping (struct iterator_group *group, htab_t table);
> +  overloaded_name *handle_overloaded_name (rtx, vec<mapping *> *);
>  
>    const char *get_top_level_filename () const { return m_toplevel_fname; }
>    const char *get_filename () const { return m_read_md_filename; }
> @@ -174,6 +217,8 @@ struct enum_type {
>    struct obstack *get_string_obstack () { return &m_string_obstack; }
>    htab_t get_md_constants () { return m_md_constants; }
>  
> +  overloaded_name *get_overloads () const { return m_first_overload; }
> +
>   private:
>    /* A singly-linked list of filenames.  */
>    struct file_name_list {
> @@ -253,6 +298,16 @@ struct enum_type {
>    /* If non-zero, filter the input to just this subset of lines.  */
>    int m_first_line;
>    int m_last_line;
> +
> +  /* The first overloaded_name.  */
> +  overloaded_name *m_first_overload;
> +
> +  /* Where to chain further overloaded_names,  */
> +  overloaded_name **m_next_overload_ptr;
> +
> +  /* A hash table of overloaded_names, keyed off their name and the types of
> +     their arguments.  */
> +  htab_t m_overloads_htab;
>  };
>  
>  /* Global singleton; constrast with rtx_reader_ptr below.  */
> Index: gcc/read-md.c
> ===================================================================
> --- gcc/read-md.c	2018-05-02 08:38:14.393364473 +0100
> +++ gcc/read-md.c	2018-07-13 10:11:35.361665853 +0100
> @@ -1003,7 +1003,10 @@ md_reader::md_reader (bool compact)
>    m_first_dir_md_include (NULL),
>    m_last_dir_md_include_ptr (&m_first_dir_md_include),
>    m_first_line (0),
> -  m_last_line (0)
> +  m_last_line (0),
> +  m_first_overload (NULL),
> +  m_next_overload_ptr (&m_first_overload),
> +  m_overloads_htab (NULL)
>  {
>    /* Set the global singleton pointer.  */
>    md_reader_ptr = this;
> Index: gcc/read-rtl.c
> ===================================================================
> --- gcc/read-rtl.c	2018-05-02 08:38:10.513401159 +0100
> +++ gcc/read-rtl.c	2018-07-13 10:11:35.361665853 +0100
> @@ -72,6 +72,9 @@ struct iterator_group {
>       iterators.  */
>    htab_t attrs, iterators;
>  
> +  /* The C++ type of the iterator, such as "machine_mode" for modes.  */
> +  const char *type;
> +
>    /* Treat the given string as the name of a standard mode, etc., and
>       return its integer value.  */
>    int (*find_builtin) (const char *);
> @@ -80,6 +83,9 @@ struct iterator_group {
>       If the iterator applies to operands, the second argument gives the
>       operand index, otherwise it is ignored.  */
>    void (*apply_iterator) (rtx, unsigned int, int);
> +
> +  /* Return the C token for the given standard mode, code, etc.  */
> +  const char *(*get_c_token) (int);
>  };
>  
>  /* Records one use of an iterator.  */
> @@ -163,6 +169,12 @@ apply_mode_iterator (rtx x, unsigned int
>    PUT_MODE (x, (machine_mode) mode);
>  }
>  
> +static const char *
> +get_mode_token (int mode)
> +{
> +  return concat ("E_", GET_MODE_NAME (mode), "mode", NULL);
> +}
> +
>  /* In compact dumps, the code of insns is prefixed with "c", giving "cinsn",
>     "cnote" etc, and CODE_LABEL is special-cased as "clabel".  */
>  
> @@ -206,6 +218,15 @@ apply_code_iterator (rtx x, unsigned int
>    PUT_CODE (x, (enum rtx_code) code);
>  }
>  
> +static const char *
> +get_code_token (int code)
> +{
> +  char *name = xstrdup (GET_RTX_NAME (code));
> +  for (int i = 0; name[i]; ++i)
> +    name[i] = TOUPPER (name[i]);
> +  return name;
> +}
> +
>  /* Implementations of the iterator_group callbacks for ints.  */
>  
>  /* Since GCC does not construct a table of valid constants,
> @@ -228,6 +249,14 @@ apply_int_iterator (rtx x, unsigned int
>      XINT (x, index) = value;
>  }
>  
> +static const char *
> +get_int_token (int value)
> +{
> +  char buffer[HOST_BITS_PER_INT + 1];
> +  sprintf (buffer, "%d", value);
> +  return xstrdup (buffer);
> +}
> +
>  #ifdef GENERATOR_FILE
>  
>  /* This routine adds attribute or does nothing depending on VALUE.  When
> @@ -317,10 +346,11 @@ find_subst_iter_by_attr (const char *att
>  }
>  
>  /* Map attribute string P to its current value.  Return null if the attribute
> -   isn't known.  */
> +   isn't known.  If ITERATOR_OUT is nonnull, store the associated iterator
> +   there.  */
>  
>  static struct map_value *
> -map_attr_string (const char *p)
> +map_attr_string (const char *p, mapping **iterator_out = 0)
>  {
>    const char *attr;
>    struct mapping *iterator;
> @@ -369,7 +399,11 @@ map_attr_string (const char *p)
>  	     iterator value.  */
>  	  for (v = m->values; v; v = v->next)
>  	    if (v->number == iterator->current_value->number)
> -	      return v;
> +	      {
> +		if (iterator_out)
> +		  *iterator_out = iterator;
> +		return v;
> +	      }
>  	}
>      }
>    return NULL;
> @@ -545,6 +579,156 @@ add_current_iterators (void **slot, void
>    return 1;
>  }
>  
> +/* Return a hash value for overloaded_name UNCAST_ONAME.  There shouldn't
> +   be many instances of two overloaded_names having the same name but
> +   different arguments, so hashing on the name should be good enough in
> +   practice.  */
> +
> +static hashval_t
> +overloaded_name_hash (const void *uncast_oname)
> +{
> +  const overloaded_name *oname = (const overloaded_name *) uncast_oname;
> +  return htab_hash_string (oname->name);
> +}
> +
> +/* Return true if two overloaded_names are similar enough to share
> +   the same generated functions.  */
> +
> +static int
> +overloaded_name_eq_p (const void *uncast_oname1, const void *uncast_oname2)
> +{
> +  const overloaded_name *oname1 = (const overloaded_name *) uncast_oname1;
> +  const overloaded_name *oname2 = (const overloaded_name *) uncast_oname2;
> +  if (strcmp (oname1->name, oname2->name) != 0
> +      || oname1->arg_types.length () != oname2->arg_types.length ())
> +    return 0;
> +
> +  for (unsigned int i = 0; i < oname1->arg_types.length (); ++i)
> +    if (strcmp (oname1->arg_types[i], oname2->arg_types[i]) != 0)
> +      return 0;
> +
> +  return 1;
> +}
> +
> +/* Return true if X has an instruction name in XSTR (X, 0).  */
> +
> +static bool
> +named_rtx_p (rtx x)
> +{
> +  switch (GET_CODE (x))
> +    {
> +    case DEFINE_EXPAND:
> +    case DEFINE_INSN:
> +    case DEFINE_INSN_AND_SPLIT:
> +      return true;
> +
> +    default:
> +      return false;
> +    }
> +}
> +
> +/* Check whether ORIGINAL is a named pattern whose name starts with '@'.
> +   If so, return the associated overloaded_name and add the iterator for
> +   each argument to ITERATORS.  Return null otherwise.  */
> +
> +overloaded_name *
> +md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
> +{
> +  /* Check for the leading '@'.  */
> +  if (!named_rtx_p (original) || XSTR (original, 0)[0] != '@')
> +    return NULL;
> +
> +  /* Remove the '@', so that no other code needs to worry about it.  */
> +  const char *name = XSTR (original, 0);
> +  copy_md_ptr_loc (name + 1, name);
> +  name += 1;
> +  XSTR (original, 0) = name;
> +
> +  /* Build a copy of the name without the '<...>' attribute strings.
> +     Add the iterator associated with each such attribute string to ITERATORS
> +     and add an associated argument to TMP_ONAME.  */
> +  char *copy = ASTRDUP (name);
> +  char *base = copy, *start, *end;
> +  overloaded_name tmp_oname;
> +  tmp_oname.arg_types.create (current_iterators.length ());
> +  while ((start = strchr (base, '<')) && (end = strchr (start, '>')))
> +    {
> +      *end = 0;
> +      mapping *iterator;
> +      if (!map_attr_string (start + 1, &iterator))
> +	fatal_with_file_and_line ("unknown iterator `%s'", start + 1);
> +      *end = '>';
> +
> +      /* Add the text between either the last '>' or the start of the string
> +	 and this '<'.  */
> +      obstack_grow (&m_string_obstack, base, start - base);
> +      base = end + 1;
> +
> +      /* Record an argument for ITERATOR.  */
> +      iterators->safe_push (iterator);
> +      tmp_oname.arg_types.safe_push (iterator->group->type);
> +    }
> +  if (base == copy)
> +    fatal_with_file_and_line ("no iterator attributes in name `%s'", name);
> +
> +  /* Get the completed name.  */
> +  obstack_grow (&m_string_obstack, base, strlen (base) + 1);
> +  char *new_name = XOBFINISH (&m_string_obstack, char *);
> +  tmp_oname.name = new_name;
> +
> +  if (!m_overloads_htab)
> +    m_overloads_htab = htab_create (31, overloaded_name_hash,
> +				    overloaded_name_eq_p, NULL);
> +
> +  /* See whether another pattern had the same overload name and list
> +     of argument types.  Create a new permanent one if not.  */
> +  void **slot = htab_find_slot (m_overloads_htab, &tmp_oname, INSERT);
> +  overloaded_name *oname = (overloaded_name *) *slot;
> +  if (!oname)
> +    {
> +      *slot = oname = new overloaded_name;
> +      oname->name = tmp_oname.name;
> +      oname->arg_types = tmp_oname.arg_types;
> +      oname->next = NULL;
> +      oname->first_instance = NULL;
> +      oname->next_instance_ptr = &oname->first_instance;
> +
> +      *m_next_overload_ptr = oname;
> +      m_next_overload_ptr = &oname->next;
> +    }
> +  else
> +    {
> +      obstack_free (&m_string_obstack, new_name);
> +      tmp_oname.arg_types.release ();
> +    }
> +
> +  return oname;
> +}
> +
> +/* Add an instance of ONAME for instruction pattern X.  ITERATORS[I]
> +   gives the iterator associated with argument I of ONAME.  */
> +
> +static void
> +add_overload_instance (overloaded_name *oname, vec<mapping *> iterators, rtx x)
> +{
> +  /* Create the instance.  */
> +  overloaded_instance *instance = new overloaded_instance;
> +  instance->next = NULL;
> +  instance->arg_values.create (oname->arg_types.length ());
> +  for (unsigned int i = 0; i < iterators.length (); ++i)
> +    {
> +      int value = iterators[i]->current_value->number;
> +      const char *name = iterators[i]->group->get_c_token (value);
> +      instance->arg_values.quick_push (name);
> +    }
> +  instance->name = XSTR (x, 0);
> +  instance->insn = x;
> +
> +  /* Chain it onto the end of ONAME's list.  */
> +  *oname->next_instance_ptr = instance;
> +  oname->next_instance_ptr = &instance->next;
> +}
> +
>  /* Expand all iterators in the current rtx, which is given as ORIGINAL.
>     Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE.  */
>  
> @@ -562,6 +746,10 @@ apply_iterators (rtx original, vec<rtx>
>      {
>        /* Raise an error if any attributes were used.  */
>        apply_attribute_uses ();
> +
> +      if (named_rtx_p (original) && XSTR (original, 0)[0] == '@')
> +	fatal_with_file_and_line ("'@' used without iterators");
> +
>        queue->safe_push (original);
>        return;
>      }
> @@ -583,6 +771,11 @@ apply_iterators (rtx original, vec<rtx>
>    htab_traverse (substs.iterators, add_current_iterators, NULL);
>    gcc_assert (!current_iterators.is_empty ());
>  
> +  /* Check whether this is a '@' overloaded pattern.  */
> +  auto_vec<mapping *, 16> iterators;
> +  overloaded_name *oname
> +    = rtx_reader_ptr->handle_overloaded_name (original, &iterators);
> +
>    for (;;)
>      {
>        /* Apply the current iterator values.  Accumulate a condition to
> @@ -616,6 +809,10 @@ apply_iterators (rtx original, vec<rtx>
>  						     v->number);
>  	    }
>  	}
> +
> +      if (oname)
> +	add_overload_instance (oname, iterators, x);
> +
>        /* Add the new rtx to the end of the queue.  */
>        queue->safe_push (x);
>  
> @@ -692,28 +889,36 @@ initialize_iterators (void)
>    modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
>    modes.iterators = htab_create (13, leading_string_hash,
>  				 leading_string_eq_p, 0);
> +  modes.type = "machine_mode";
>    modes.find_builtin = find_mode;
>    modes.apply_iterator = apply_mode_iterator;
> +  modes.get_c_token = get_mode_token;
>  
>    codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
>    codes.iterators = htab_create (13, leading_string_hash,
>  				 leading_string_eq_p, 0);
> +  codes.type = "rtx_code";
>    codes.find_builtin = find_code;
>    codes.apply_iterator = apply_code_iterator;
> +  codes.get_c_token = get_code_token;
>  
>    ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
>    ints.iterators = htab_create (13, leading_string_hash,
>  				 leading_string_eq_p, 0);
> +  ints.type = "int";
>    ints.find_builtin = find_int;
>    ints.apply_iterator = apply_int_iterator;
> +  ints.get_c_token = get_int_token;
>  
>    substs.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0);
>    substs.iterators = htab_create (13, leading_string_hash,
>  				 leading_string_eq_p, 0);
> +  substs.type = "int";
>    substs.find_builtin = find_int; /* We don't use it, anyway.  */
>  #ifdef GENERATOR_FILE
>    substs.apply_iterator = apply_subst_iterator;
>  #endif
> +  substs.get_c_token = get_int_token;
>  
>    lower = add_mapping (&modes, modes.attrs, "mode");
>    upper = add_mapping (&modes, modes.attrs, "MODE");
> Index: gcc/gencodes.c
> ===================================================================
> --- gcc/gencodes.c	2018-05-02 08:38:14.397364434 +0100
> +++ gcc/gencodes.c	2018-07-13 10:11:35.361665853 +0100
> @@ -46,6 +46,29 @@ gen_insn (md_rtx_info *info)
>      }
>  }
>  
> +/* Declare the maybe_code_for_* function for ONAME, and provide
> +   an inline definition of the assserting code_for_* wrapper.  */
> +
> +static void
> +handle_overloaded_code_for (overloaded_name *oname)
> +{
> +  printf ("\nextern insn_code maybe_code_for_%s (", oname->name);
> +  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
> +    printf ("%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
> +  printf (");\n");
> +
> +  printf ("inline insn_code\ncode_for_%s (", oname->name);
> +  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
> +    printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
> +  printf (")\n{\n  insn_code code = maybe_code_for_%s (", oname->name);
> +  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
> +    printf ("%sarg%d", i == 0 ? "" : ", ", i);
> +  printf (");\n"
> +	  "  gcc_assert (code != CODE_FOR_nothing);\n"
> +	  "  return code;\n"
> +	  "}\n");
> +}
> +
>  int
>  main (int argc, const char **argv)
>  {
> @@ -85,8 +108,13 @@ enum insn_code {\n\
>  
>    printf ("\n};\n\
>  \n\
> -const unsigned int NUM_INSN_CODES = %d;\n\
> -#endif /* GCC_INSN_CODES_H */\n", get_num_insn_codes ());
> +const unsigned int NUM_INSN_CODES = %d;\n", get_num_insn_codes ());
> +
> +  for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
> +       oname; oname = oname->next)
> +    handle_overloaded_code_for (oname);
> +
> +  printf ("\n#endif /* GCC_INSN_CODES_H */\n");
>  
>    if (ferror (stdout) || fflush (stdout) || fclose (stdout))
>      return FATAL_EXIT_CODE;
> Index: gcc/genflags.c
> ===================================================================
> --- gcc/genflags.c	2018-05-02 08:38:10.537400932 +0100
> +++ gcc/genflags.c	2018-07-13 10:11:35.361665853 +0100
> @@ -197,6 +197,37 @@ gen_insn (md_rtx_info *info)
>    obstack_grow (&obstack, &insn, sizeof (rtx));
>  }
>  
> +/* Declare the maybe_gen_* function for ONAME, and provide
> +   an inline definition of the assserting gen_* wrapper.  */
> +
> +static void
> +emit_overloaded_gen_proto (overloaded_name *oname)
> +{
> +  unsigned int num_ops = num_operands (oname->first_instance->insn);
> +
> +  printf ("\nextern rtx maybe_gen_%s (", oname->name);
> +  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
> +    printf ("%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
> +  for (unsigned int i = 0; i < num_ops; ++i)
> +    printf (", rtx");
> +  printf (");\n");
> +
> +  printf ("inline rtx\ngen_%s (", oname->name);
> +  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
> +    printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
> +  for (unsigned int i = 0; i < num_ops; ++i)
> +    printf (", rtx x%d", i);
> +  printf (")\n{\n  rtx res = maybe_gen_%s (", oname->name);
> +  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
> +    printf ("%sarg%d", i == 0 ? "" : ", ", i);
> +  for (unsigned int i = 0; i < num_ops; ++i)
> +    printf (", x%d", i);
> +  printf (");\n"
> +	  "  gcc_assert (res);\n"
> +	  "  return res;\n"
> +	  "}\n");
> +}
> +
>  int
>  main (int argc, const char **argv)
>  {
> @@ -242,6 +273,10 @@ main (int argc, const char **argv)
>    for (insn_ptr = insns; *insn_ptr; insn_ptr++)
>      gen_proto (*insn_ptr);
>  
> +  for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
> +       oname; oname = oname->next)
> +    emit_overloaded_gen_proto (oname);
> +
>    puts ("\n#endif /* GCC_INSN_FLAGS_H */");
>  
>    if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
> Index: gcc/genemit.c
> ===================================================================
> --- gcc/genemit.c	2018-05-02 08:37:33.505751103 +0100
> +++ gcc/genemit.c	2018-07-13 10:11:35.361665853 +0100
> @@ -752,6 +752,92 @@ output_peephole2_scratches (rtx split)
>      }
>  }
>  
> +/* Print "arg<N>" parameter declarations for each argument N of ONAME.  */
> +
> +static void
> +print_overload_arguments (overloaded_name *oname)
> +{
> +  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
> +    printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
> +}
> +
> +/* Print code to test whether INSTANCE should be chosne, given that
> +   argument N of the overload is available as "arg<N>".  */
> +
> +static void
> +print_overload_test (overloaded_instance *instance)
> +{
> +  for (unsigned int i = 0; i < instance->arg_values.length (); ++i)
> +    printf ("%sarg%d == %s", i == 0 ? "  if (" : "\n      && ",
> +	    i, instance->arg_values[i]);
> +  printf (")\n");
> +}
> +
> +/* Emit a maybe_code_for_* function for ONAME.  */
> +
> +static void
> +handle_overloaded_code_for (overloaded_name *oname)
> +{
> +  /* Print the function prototype.  */
> +  printf ("\ninsn_code\nmaybe_code_for_%s (", oname->name);
> +  print_overload_arguments (oname);
> +  printf (")\n{\n");
> +
> +  /* Use a sequence of "if" statements for each instance.  */
> +  for (overloaded_instance *instance = oname->first_instance;
> +       instance; instance = instance->next)
> +    {
> +      print_overload_test (instance);
> +      printf ("    return CODE_FOR_%s;\n", instance->name);
> +    }
> +
> +  /* Return null if no match was found.  */
> +  printf ("  return CODE_FOR_nothing;\n}\n");
> +}
> +
> +/* Emit a maybe_gen_* function for ONAME.  */
> +
> +static void
> +handle_overloaded_gen (overloaded_name *oname)
> +{
> +  /* All patterns must have the same number of operands.  */
> +  pattern_stats stats;
> +  get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1));
> +  for (overloaded_instance *instance = oname->first_instance->next;
> +       instance; instance = instance->next)
> +    {
> +      pattern_stats stats2;
> +      get_pattern_stats (&stats2, XVEC (instance->insn, 1));
> +      if (stats.num_generator_args != stats2.num_generator_args)
> +	fatal_at (get_file_location (instance->insn),
> +		  "inconsistent number of operands for '%s'; "
> +		  "this instance has %d, but previous instances had %d",
> +		  oname->name, stats2.num_generator_args,
> +		  stats.num_generator_args);
> +    }
> +
> +  /* Print the function prototype.  */
> +  printf ("\nrtx\nmaybe_gen_%s (", oname->name);
> +  print_overload_arguments (oname);
> +  for (int i = 0; i < stats.num_generator_args; ++i)
> +    printf (", rtx x%d", i);
> +  printf (")\n{\n");
> +
> +  /* Use maybe_code_for_*, instead of duplicating the selection logic here.  */
> +  printf ("  insn_code code = maybe_code_for_%s (", oname->name);
> +  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
> +    printf ("%sarg%d", i == 0 ? "" : ", ", i);
> +  printf (");\n"
> +	  "  if (code != CODE_FOR_nothing)\n"
> +	  "    return GEN_FCN (code) (");
> +  for (int i = 0; i < stats.num_generator_args; ++i)
> +    printf ("%sx%d", i == 0 ? "" : ", ", i);
> +  printf (");\n"
> +	  "  else\n"
> +	  "    return NULL_RTX;\n"
> +	  "}\n");
> +}
> +
>  int
>  main (int argc, const char **argv)
>  {
> @@ -840,6 +926,13 @@ #define DEF_INTERNAL_OPTAB_FN(NAME, FLAG
>    output_add_clobbers ();
>    output_added_clobbers_hard_reg_p ();
>  
> +  for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
> +       oname; oname = oname->next)
> +    {
> +      handle_overloaded_code_for (oname);
> +      handle_overloaded_gen (oname);
> +    }
> +
>    fflush (stdout);
>    return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
>  }
> Index: gcc/config/aarch64/aarch64.c
> ===================================================================
> --- gcc/config/aarch64/aarch64.c	2018-07-13 10:11:14.969838990 +0100
> +++ gcc/config/aarch64/aarch64.c	2018-07-13 10:11:35.357665887 +0100
> @@ -1980,16 +1980,8 @@ aarch64_split_128bit_move (rtx dst, rtx
>  	  src_lo = gen_lowpart (word_mode, src);
>  	  src_hi = gen_highpart (word_mode, src);
>  
> -	  if (mode == TImode)
> -	    {
> -	      emit_insn (gen_aarch64_movtilow_di (dst, src_lo));
> -	      emit_insn (gen_aarch64_movtihigh_di (dst, src_hi));
> -	    }
> -	  else
> -	    {
> -	      emit_insn (gen_aarch64_movtflow_di (dst, src_lo));
> -	      emit_insn (gen_aarch64_movtfhigh_di (dst, src_hi));
> -	    }
> +	  emit_insn (gen_aarch64_movlow_di (mode, dst, src_lo));
> +	  emit_insn (gen_aarch64_movhigh_di (mode, dst, src_hi));
>  	  return;
>  	}
>        else if (GP_REGNUM_P (dst_regno) && FP_REGNUM_P (src_regno))
> @@ -1997,16 +1989,8 @@ aarch64_split_128bit_move (rtx dst, rtx
>  	  dst_lo = gen_lowpart (word_mode, dst);
>  	  dst_hi = gen_highpart (word_mode, dst);
>  
> -	  if (mode == TImode)
> -	    {
> -	      emit_insn (gen_aarch64_movdi_tilow (dst_lo, src));
> -	      emit_insn (gen_aarch64_movdi_tihigh (dst_hi, src));
> -	    }
> -	  else
> -	    {
> -	      emit_insn (gen_aarch64_movdi_tflow (dst_lo, src));
> -	      emit_insn (gen_aarch64_movdi_tfhigh (dst_hi, src));
> -	    }
> +	  emit_insn (gen_aarch64_movdi_low (mode, dst_lo, src));
> +	  emit_insn (gen_aarch64_movdi_high (mode, dst_hi, src));
>  	  return;
>  	}
>      }
> @@ -2049,36 +2033,7 @@ aarch64_split_simd_combine (rtx dst, rtx
>  	      && register_operand (src1, src_mode)
>  	      && register_operand (src2, src_mode));
>  
> -  rtx (*gen) (rtx, rtx, rtx);
> -
> -  switch (src_mode)
> -    {
> -    case E_V8QImode:
> -      gen = gen_aarch64_simd_combinev8qi;
> -      break;
> -    case E_V4HImode:
> -      gen = gen_aarch64_simd_combinev4hi;
> -      break;
> -    case E_V2SImode:
> -      gen = gen_aarch64_simd_combinev2si;
> -      break;
> -    case E_V4HFmode:
> -      gen = gen_aarch64_simd_combinev4hf;
> -      break;
> -    case E_V2SFmode:
> -      gen = gen_aarch64_simd_combinev2sf;
> -      break;
> -    case E_DImode:
> -      gen = gen_aarch64_simd_combinedi;
> -      break;
> -    case E_DFmode:
> -      gen = gen_aarch64_simd_combinedf;
> -      break;
> -    default:
> -      gcc_unreachable ();
> -    }
> -
> -  emit_insn (gen (dst, src1, src2));
> +  emit_insn (gen_aarch64_simd_combine (src_mode, dst, src1, src2));
>    return;
>  }
>  
> @@ -2094,39 +2049,8 @@ aarch64_split_simd_move (rtx dst, rtx sr
>  
>    if (REG_P (dst) && REG_P (src))
>      {
> -      rtx (*gen) (rtx, rtx);
> -
>        gcc_assert (VECTOR_MODE_P (src_mode));
> -
> -      switch (src_mode)
> -	{
> -	case E_V16QImode:
> -	  gen = gen_aarch64_split_simd_movv16qi;
> -	  break;
> -	case E_V8HImode:
> -	  gen = gen_aarch64_split_simd_movv8hi;
> -	  break;
> -	case E_V4SImode:
> -	  gen = gen_aarch64_split_simd_movv4si;
> -	  break;
> -	case E_V2DImode:
> -	  gen = gen_aarch64_split_simd_movv2di;
> -	  break;
> -	case E_V8HFmode:
> -	  gen = gen_aarch64_split_simd_movv8hf;
> -	  break;
> -	case E_V4SFmode:
> -	  gen = gen_aarch64_split_simd_movv4sf;
> -	  break;
> -	case E_V2DFmode:
> -	  gen = gen_aarch64_split_simd_movv2df;
> -	  break;
> -	default:
> -	  gcc_unreachable ();
> -	}
> -
> -      emit_insn (gen (dst, src));
> -      return;
> +      emit_insn (gen_aarch64_split_simd_mov (src_mode, dst, src));
>      }
>  }
>  
> @@ -7422,51 +7346,6 @@ aarch64_legitimize_address (rtx x, rtx /
>    return x;
>  }
>  
> -/* Return the reload icode required for a constant pool in mode.  */
> -static enum insn_code
> -aarch64_constant_pool_reload_icode (machine_mode mode)
> -{
> -  switch (mode)
> -    {
> -    case E_SFmode:
> -      return CODE_FOR_aarch64_reload_movcpsfdi;
> -
> -    case E_DFmode:
> -      return CODE_FOR_aarch64_reload_movcpdfdi;
> -
> -    case E_TFmode:
> -      return CODE_FOR_aarch64_reload_movcptfdi;
> -
> -    case E_V8QImode:
> -      return CODE_FOR_aarch64_reload_movcpv8qidi;
> -
> -    case E_V16QImode:
> -      return CODE_FOR_aarch64_reload_movcpv16qidi;
> -
> -    case E_V4HImode:
> -      return CODE_FOR_aarch64_reload_movcpv4hidi;
> -
> -    case E_V8HImode:
> -      return CODE_FOR_aarch64_reload_movcpv8hidi;
> -
> -    case E_V2SImode:
> -      return CODE_FOR_aarch64_reload_movcpv2sidi;
> -
> -    case E_V4SImode:
> -      return CODE_FOR_aarch64_reload_movcpv4sidi;
> -
> -    case E_V2DImode:
> -      return CODE_FOR_aarch64_reload_movcpv2didi;
> -
> -    case E_V2DFmode:
> -      return CODE_FOR_aarch64_reload_movcpv2dfdi;
> -
> -    default:
> -      gcc_unreachable ();
> -    }
> -
> -  gcc_unreachable ();
> -}
>  static reg_class_t
>  aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x,
>  			  reg_class_t rclass,
> @@ -7494,7 +7373,7 @@ aarch64_secondary_reload (bool in_p ATTR
>  	  || targetm.vector_mode_supported_p (GET_MODE (x)))
>        && !aarch64_pcrelative_literal_loads)
>      {
> -      sri->icode = aarch64_constant_pool_reload_icode (mode);
> +      sri->icode = code_for_aarch64_reload_movcp (mode, DImode);
>        return NO_REGS;
>      }
>  
> @@ -7504,10 +7383,7 @@ aarch64_secondary_reload (bool in_p ATTR
>        && FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD
>        && reg_class_subset_p (rclass, FP_REGS))
>      {
> -      if (mode == TFmode)
> -        sri->icode = CODE_FOR_aarch64_reload_movtf;
> -      else if (mode == TImode)
> -        sri->icode = CODE_FOR_aarch64_reload_movti;
> +      sri->icode = code_for_aarch64_reload_mov (mode);
>        return NO_REGS;
>      }
>  
> @@ -9873,43 +9749,6 @@ aarch64_builtin_reciprocal (tree fndecl)
>    return aarch64_builtin_rsqrt (DECL_FUNCTION_CODE (fndecl));
>  }
>  
> -typedef rtx (*rsqrte_type) (rtx, rtx);
> -
> -/* Select reciprocal square root initial estimate insn depending on machine
> -   mode.  */
> -
> -static rsqrte_type
> -get_rsqrte_type (machine_mode mode)
> -{
> -  switch (mode)
> -  {
> -    case E_DFmode:   return gen_aarch64_rsqrtedf;
> -    case E_SFmode:   return gen_aarch64_rsqrtesf;
> -    case E_V2DFmode: return gen_aarch64_rsqrtev2df;
> -    case E_V2SFmode: return gen_aarch64_rsqrtev2sf;
> -    case E_V4SFmode: return gen_aarch64_rsqrtev4sf;
> -    default: gcc_unreachable ();
> -  }
> -}
> -
> -typedef rtx (*rsqrts_type) (rtx, rtx, rtx);
> -
> -/* Select reciprocal square root series step insn depending on machine mode.  */
> -
> -static rsqrts_type
> -get_rsqrts_type (machine_mode mode)
> -{
> -  switch (mode)
> -  {
> -    case E_DFmode:   return gen_aarch64_rsqrtsdf;
> -    case E_SFmode:   return gen_aarch64_rsqrtssf;
> -    case E_V2DFmode: return gen_aarch64_rsqrtsv2df;
> -    case E_V2SFmode: return gen_aarch64_rsqrtsv2sf;
> -    case E_V4SFmode: return gen_aarch64_rsqrtsv4sf;
> -    default: gcc_unreachable ();
> -  }
> -}
> -
>  /* Emit instruction sequence to compute either the approximate square root
>     or its approximate reciprocal, depending on the flag RECP, and return
>     whether the sequence was emitted or not.  */
> @@ -9954,7 +9793,7 @@ aarch64_emit_approx_sqrt (rtx dst, rtx s
>  
>    /* Estimate the approximate reciprocal square root.  */
>    rtx xdst = gen_reg_rtx (mode);
> -  emit_insn ((*get_rsqrte_type (mode)) (xdst, src));
> +  emit_insn (gen_aarch64_rsqrte (mode, xdst, src));
>  
>    /* Iterate over the series twice for SF and thrice for DF.  */
>    int iterations = (GET_MODE_INNER (mode) == DFmode) ? 3 : 2;
> @@ -9973,7 +9812,7 @@ aarch64_emit_approx_sqrt (rtx dst, rtx s
>        rtx x2 = gen_reg_rtx (mode);
>        emit_set_insn (x2, gen_rtx_MULT (mode, xdst, xdst));
>  
> -      emit_insn ((*get_rsqrts_type (mode)) (x1, src, x2));
> +      emit_insn (gen_aarch64_rsqrts (mode, x1, src, x2));
>  
>        if (iterations > 0)
>  	emit_set_insn (xdst, gen_rtx_MULT (mode, xdst, x1));
> @@ -9998,42 +9837,6 @@ aarch64_emit_approx_sqrt (rtx dst, rtx s
>    return true;
>  }
>  
> -typedef rtx (*recpe_type) (rtx, rtx);
> -
> -/* Select reciprocal initial estimate insn depending on machine mode.  */
> -
> -static recpe_type
> -get_recpe_type (machine_mode mode)
> -{
> -  switch (mode)
> -  {
> -    case E_SFmode:   return (gen_aarch64_frecpesf);
> -    case E_V2SFmode: return (gen_aarch64_frecpev2sf);
> -    case E_V4SFmode: return (gen_aarch64_frecpev4sf);
> -    case E_DFmode:   return (gen_aarch64_frecpedf);
> -    case E_V2DFmode: return (gen_aarch64_frecpev2df);
> -    default:         gcc_unreachable ();
> -  }
> -}
> -
> -typedef rtx (*recps_type) (rtx, rtx, rtx);
> -
> -/* Select reciprocal series step insn depending on machine mode.  */
> -
> -static recps_type
> -get_recps_type (machine_mode mode)
> -{
> -  switch (mode)
> -  {
> -    case E_SFmode:   return (gen_aarch64_frecpssf);
> -    case E_V2SFmode: return (gen_aarch64_frecpsv2sf);
> -    case E_V4SFmode: return (gen_aarch64_frecpsv4sf);
> -    case E_DFmode:   return (gen_aarch64_frecpsdf);
> -    case E_V2DFmode: return (gen_aarch64_frecpsv2df);
> -    default:         gcc_unreachable ();
> -  }
> -}
> -
>  /* Emit the instruction sequence to compute the approximation for the division
>     of NUM by DEN in QUO and return whether the sequence was emitted or not.  */
>  
> @@ -10061,7 +9864,7 @@ aarch64_emit_approx_div (rtx quo, rtx nu
>  
>    /* Estimate the approximate reciprocal.  */
>    rtx xrcp = gen_reg_rtx (mode);
> -  emit_insn ((*get_recpe_type (mode)) (xrcp, den));
> +  emit_insn (gen_aarch64_frecpe (mode, xrcp, den));
>  
>    /* Iterate over the series twice for SF and thrice for DF.  */
>    int iterations = (GET_MODE_INNER (mode) == DFmode) ? 3 : 2;
> @@ -10075,7 +9878,7 @@ aarch64_emit_approx_div (rtx quo, rtx nu
>    rtx xtmp = gen_reg_rtx (mode);
>    while (iterations--)
>      {
> -      emit_insn ((*get_recps_type (mode)) (xtmp, xrcp, den));
> +      emit_insn (gen_aarch64_frecps (mode, xtmp, xrcp, den));
>  
>        if (iterations > 0)
>  	emit_set_insn (xrcp, gen_rtx_MULT (mode, xrcp, xtmp));
> @@ -14213,19 +14016,7 @@ aarch64_start_file (void)
>  aarch64_emit_load_exclusive (machine_mode mode, rtx rval,
>  			     rtx mem, rtx model_rtx)
>  {
> -  rtx (*gen) (rtx, rtx, rtx);
> -
> -  switch (mode)
> -    {
> -    case E_QImode: gen = gen_aarch64_load_exclusiveqi; break;
> -    case E_HImode: gen = gen_aarch64_load_exclusivehi; break;
> -    case E_SImode: gen = gen_aarch64_load_exclusivesi; break;
> -    case E_DImode: gen = gen_aarch64_load_exclusivedi; break;
> -    default:
> -      gcc_unreachable ();
> -    }
> -
> -  emit_insn (gen (rval, mem, model_rtx));
> +  emit_insn (gen_aarch64_load_exclusive (mode, rval, mem, model_rtx));
>  }
>  
>  /* Emit store exclusive.  */
> @@ -14234,19 +14025,7 @@ aarch64_emit_load_exclusive (machine_mod
>  aarch64_emit_store_exclusive (machine_mode mode, rtx bval,
>  			      rtx rval, rtx mem, rtx model_rtx)
>  {
> -  rtx (*gen) (rtx, rtx, rtx, rtx);
> -
> -  switch (mode)
> -    {
> -    case E_QImode: gen = gen_aarch64_store_exclusiveqi; break;
> -    case E_HImode: gen = gen_aarch64_store_exclusivehi; break;
> -    case E_SImode: gen = gen_aarch64_store_exclusivesi; break;
> -    case E_DImode: gen = gen_aarch64_store_exclusivedi; break;
> -    default:
> -      gcc_unreachable ();
> -    }
> -
> -  emit_insn (gen (bval, rval, mem, model_rtx));
> +  emit_insn (gen_aarch64_store_exclusive (mode, bval, rval, mem, model_rtx));
>  }
>  
>  /* Mark the previous jump instruction as unlikely.  */
> @@ -14265,23 +14044,6 @@ aarch64_expand_compare_and_swap (rtx ope
>  {
>    rtx bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f, x;
>    machine_mode mode, cmp_mode;
> -  typedef rtx (*gen_cas_fn) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
> -  int idx;
> -  gen_cas_fn gen;
> -  const gen_cas_fn split_cas[] =
> -  {
> -    gen_aarch64_compare_and_swapqi,
> -    gen_aarch64_compare_and_swaphi,
> -    gen_aarch64_compare_and_swapsi,
> -    gen_aarch64_compare_and_swapdi
> -  };
> -  const gen_cas_fn atomic_cas[] =
> -  {
> -    gen_aarch64_compare_and_swapqi_lse,
> -    gen_aarch64_compare_and_swaphi_lse,
> -    gen_aarch64_compare_and_swapsi_lse,
> -    gen_aarch64_compare_and_swapdi_lse
> -  };
>  
>    bval = operands[0];
>    rval = operands[1];
> @@ -14324,21 +14086,14 @@ aarch64_expand_compare_and_swap (rtx ope
>        gcc_unreachable ();
>      }
>  
> -  switch (mode)
> -    {
> -    case E_QImode: idx = 0; break;
> -    case E_HImode: idx = 1; break;
> -    case E_SImode: idx = 2; break;
> -    case E_DImode: idx = 3; break;
> -    default:
> -      gcc_unreachable ();
> -    }
>    if (TARGET_LSE)
> -    gen = atomic_cas[idx];
> +    emit_insn (gen_aarch64_compare_and_swap_lse (mode, rval, mem, oldval,
> +						 newval, is_weak, mod_s,
> +						 mod_f));
>    else
> -    gen = split_cas[idx];
> +    emit_insn (gen_aarch64_compare_and_swap (mode, rval, mem, oldval, newval,
> +					     is_weak, mod_s, mod_f));
>  
> -  emit_insn (gen (rval, mem, oldval, newval, is_weak, mod_s, mod_f));
>  
>    if (mode == QImode || mode == HImode)
>      emit_move_insn (operands[1], gen_lowpart (mode, rval));
> @@ -14401,26 +14156,15 @@ aarch64_gen_atomic_cas (rtx rval, rtx me
>  			rtx expected, rtx desired,
>  			rtx model)
>  {
> -  rtx (*gen) (rtx, rtx, rtx, rtx);
>    machine_mode mode;
>  
>    mode = GET_MODE (mem);
>  
> -  switch (mode)
> -    {
> -    case E_QImode: gen = gen_aarch64_atomic_casqi; break;
> -    case E_HImode: gen = gen_aarch64_atomic_cashi; break;
> -    case E_SImode: gen = gen_aarch64_atomic_cassi; break;
> -    case E_DImode: gen = gen_aarch64_atomic_casdi; break;
> -    default:
> -      gcc_unreachable ();
> -    }
> -
>    /* Move the expected value into the CAS destination register.  */
>    emit_insn (gen_rtx_SET (rval, expected));
>  
>    /* Emit the CAS.  */
> -  emit_insn (gen (rval, mem, desired, model));
> +  emit_insn (gen_aarch64_atomic_cas (mode, rval, mem, desired, model));
>  
>    /* Compare the expected value with the value loaded by the CAS, to establish
>       whether the swap was made.  */
> @@ -14549,91 +14293,7 @@ aarch64_emit_bic (machine_mode mode, rtx
>  aarch64_emit_atomic_swap (machine_mode mode, rtx dst, rtx value,
>  			  rtx mem, rtx model)
>  {
> -  rtx (*gen) (rtx, rtx, rtx, rtx);
> -
> -  switch (mode)
> -    {
> -    case E_QImode: gen = gen_aarch64_atomic_swpqi; break;
> -    case E_HImode: gen = gen_aarch64_atomic_swphi; break;
> -    case E_SImode: gen = gen_aarch64_atomic_swpsi; break;
> -    case E_DImode: gen = gen_aarch64_atomic_swpdi; break;
> -    default:
> -      gcc_unreachable ();
> -    }
> -
> -  emit_insn (gen (dst, mem, value, model));
> -}
> -
> -/* Operations supported by aarch64_emit_atomic_load_op.  */
> -
> -enum aarch64_atomic_load_op_code
> -{
> -  AARCH64_LDOP_PLUS,	/* A + B  */
> -  AARCH64_LDOP_XOR,	/* A ^ B  */
> -  AARCH64_LDOP_OR,	/* A | B  */
> -  AARCH64_LDOP_BIC	/* A & ~B  */
> -};
> -
> -/* Emit an atomic load-operate.  */
> -
> -static void
> -aarch64_emit_atomic_load_op (enum aarch64_atomic_load_op_code code,
> -			     machine_mode mode, rtx dst, rtx src,
> -			     rtx mem, rtx model)
> -{
> -  typedef rtx (*aarch64_atomic_load_op_fn) (rtx, rtx, rtx, rtx);
> -  const aarch64_atomic_load_op_fn plus[] =
> -  {
> -    gen_aarch64_atomic_loadaddqi,
> -    gen_aarch64_atomic_loadaddhi,
> -    gen_aarch64_atomic_loadaddsi,
> -    gen_aarch64_atomic_loadadddi
> -  };
> -  const aarch64_atomic_load_op_fn eor[] =
> -  {
> -    gen_aarch64_atomic_loadeorqi,
> -    gen_aarch64_atomic_loadeorhi,
> -    gen_aarch64_atomic_loadeorsi,
> -    gen_aarch64_atomic_loadeordi
> -  };
> -  const aarch64_atomic_load_op_fn ior[] =
> -  {
> -    gen_aarch64_atomic_loadsetqi,
> -    gen_aarch64_atomic_loadsethi,
> -    gen_aarch64_atomic_loadsetsi,
> -    gen_aarch64_atomic_loadsetdi
> -  };
> -  const aarch64_atomic_load_op_fn bic[] =
> -  {
> -    gen_aarch64_atomic_loadclrqi,
> -    gen_aarch64_atomic_loadclrhi,
> -    gen_aarch64_atomic_loadclrsi,
> -    gen_aarch64_atomic_loadclrdi
> -  };
> -  aarch64_atomic_load_op_fn gen;
> -  int idx = 0;
> -
> -  switch (mode)
> -    {
> -    case E_QImode: idx = 0; break;
> -    case E_HImode: idx = 1; break;
> -    case E_SImode: idx = 2; break;
> -    case E_DImode: idx = 3; break;
> -    default:
> -      gcc_unreachable ();
> -    }
> -
> -  switch (code)
> -    {
> -    case AARCH64_LDOP_PLUS: gen = plus[idx]; break;
> -    case AARCH64_LDOP_XOR: gen = eor[idx]; break;
> -    case AARCH64_LDOP_OR: gen = ior[idx]; break;
> -    case AARCH64_LDOP_BIC: gen = bic[idx]; break;
> -    default:
> -      gcc_unreachable ();
> -    }
> -
> -  emit_insn (gen (dst, mem, src, model));
> +  emit_insn (gen_aarch64_atomic_swp (mode, dst, mem, value, model));
>  }
>  
>  /* Emit an atomic load+operate.  CODE is the operation.  OUT_DATA is the
> @@ -14650,7 +14310,7 @@ aarch64_gen_atomic_ldop (enum rtx_code c
>    machine_mode mode = GET_MODE (mem);
>    machine_mode wmode = (mode == DImode ? DImode : SImode);
>    const bool short_mode = (mode < SImode);
> -  aarch64_atomic_load_op_code ldop_code;
> +  int ldop_code;
>    rtx src;
>    rtx x;
>  
> @@ -14697,15 +14357,15 @@ aarch64_gen_atomic_ldop (enum rtx_code c
>        }
>        /* Fall-through.  */
>      case PLUS:
> -      ldop_code = AARCH64_LDOP_PLUS;
> +      ldop_code = UNSPECV_ATOMIC_LDOP_PLUS;
>        break;
>  
>      case IOR:
> -      ldop_code = AARCH64_LDOP_OR;
> +      ldop_code = UNSPECV_ATOMIC_LDOP_OR;
>        break;
>  
>      case XOR:
> -      ldop_code = AARCH64_LDOP_XOR;
> +      ldop_code = UNSPECV_ATOMIC_LDOP_XOR;
>        break;
>  
>      case AND:
> @@ -14722,7 +14382,7 @@ aarch64_gen_atomic_ldop (enum rtx_code c
>  	if (short_mode)
>  	  src = gen_lowpart (mode, src);
>        }
> -      ldop_code = AARCH64_LDOP_BIC;
> +      ldop_code = UNSPECV_ATOMIC_LDOP_BIC;
>        break;
>  
>      default:
> @@ -14730,7 +14390,8 @@ aarch64_gen_atomic_ldop (enum rtx_code c
>        gcc_unreachable ();
>      }
>  
> -  aarch64_emit_atomic_load_op (ldop_code, mode, out_data, src, mem, model_rtx);
> +  emit_insn (gen_aarch64_atomic_load (ldop_code, mode,
> +				      out_data, mem, src, model_rtx));
>  
>    /* If necessary, calculate the data in memory after the update by redoing the
>       operation from values in registers.  */
> Index: gcc/config/aarch64/aarch64.md
> ===================================================================
> --- gcc/config/aarch64/aarch64.md	2018-07-03 08:56:35.194425798 +0100
> +++ gcc/config/aarch64/aarch64.md	2018-07-13 10:11:35.357665887 +0100
> @@ -5517,7 +5517,7 @@ (define_expand "xorsign<mode>3"
>  ;; -------------------------------------------------------------------
>  ;; Reload Scalar Floating point modes from constant pool.
>  ;; The AArch64 port doesn't have __int128 constant move support.
> -(define_expand "aarch64_reload_movcp<GPF_TF:mode><P:mode>"
> +(define_expand "@aarch64_reload_movcp<GPF_TF:mode><P:mode>"
>   [(set (match_operand:GPF_TF 0 "register_operand" "=w")
>         (mem:GPF_TF (match_operand 1 "aarch64_constant_pool_symref" "S")))
>    (clobber (match_operand:P 2 "register_operand" "=&r"))]
> @@ -5530,7 +5530,7 @@ (define_expand "aarch64_reload_movcp<GPF
>  )
>  
>  ;; Reload Vector modes from constant pool.
> -(define_expand "aarch64_reload_movcp<VALL:mode><P:mode>"
> +(define_expand "@aarch64_reload_movcp<VALL:mode><P:mode>"
>   [(set (match_operand:VALL 0 "register_operand" "=w")
>         (mem:VALL (match_operand 1 "aarch64_constant_pool_symref" "S")))
>    (clobber (match_operand:P 2 "register_operand" "=&r"))]
> @@ -5542,7 +5542,7 @@ (define_expand "aarch64_reload_movcp<VAL
>   }
>  )
>  
> -(define_expand "aarch64_reload_mov<mode>"
> +(define_expand "@aarch64_reload_mov<mode>"
>    [(set (match_operand:TX 0 "register_operand" "=w")
>          (match_operand:TX 1 "register_operand" "w"))
>     (clobber (match_operand:DI 2 "register_operand" "=&r"))
> @@ -5562,7 +5562,7 @@ (define_expand "aarch64_reload_mov<mode>
>  ;; after or during reload as we don't want these patterns to start
>  ;; kicking in during the combiner.
>  
> -(define_insn "aarch64_movdi_<mode>low"
> +(define_insn "@aarch64_movdi_<mode>low"
>    [(set (match_operand:DI 0 "register_operand" "=r")
>  	(zero_extract:DI (match_operand:TX 1 "register_operand" "w")
>  			 (const_int 64) (const_int 0)))]
> @@ -5572,7 +5572,7 @@ (define_insn "aarch64_movdi_<mode>low"
>     (set_attr "length" "4")
>    ])
>  
> -(define_insn "aarch64_movdi_<mode>high"
> +(define_insn "@aarch64_movdi_<mode>high"
>    [(set (match_operand:DI 0 "register_operand" "=r")
>  	(zero_extract:DI (match_operand:TX 1 "register_operand" "w")
>  			 (const_int 64) (const_int 64)))]
> @@ -5582,7 +5582,7 @@ (define_insn "aarch64_movdi_<mode>high"
>     (set_attr "length" "4")
>    ])
>  
> -(define_insn "aarch64_mov<mode>high_di"
> +(define_insn "@aarch64_mov<mode>high_di"
>    [(set (zero_extract:TX (match_operand:TX 0 "register_operand" "+w")
>                           (const_int 64) (const_int 64))
>          (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
> @@ -5592,7 +5592,7 @@ (define_insn "aarch64_mov<mode>high_di"
>     (set_attr "length" "4")
>    ])
>  
> -(define_insn "aarch64_mov<mode>low_di"
> +(define_insn "@aarch64_mov<mode>low_di"
>    [(set (match_operand:TX 0 "register_operand" "=w")
>          (zero_extend:TX (match_operand:DI 1 "register_operand" "r")))]
>    "TARGET_FLOAT && (reload_completed || reload_in_progress)"
> Index: gcc/config/aarch64/aarch64-simd.md
> ===================================================================
> --- gcc/config/aarch64/aarch64-simd.md	2018-07-13 10:11:14.961839058 +0100
> +++ gcc/config/aarch64/aarch64-simd.md	2018-07-13 10:11:35.357665887 +0100
> @@ -257,7 +257,7 @@ (define_split
>    DONE;
>  })
>  
> -(define_expand "aarch64_split_simd_mov<mode>"
> +(define_expand "@aarch64_split_simd_mov<mode>"
>    [(set (match_operand:VQ 0)
>          (match_operand:VQ 1))]
>    "TARGET_SIMD"
> @@ -559,7 +559,7 @@ (define_insn "*aarch64_mul3_elt_from_dup
>    [(set_attr "type" "neon<fp>_mul_<stype>_scalar<q>")]
>  )
>  
> -(define_insn "aarch64_rsqrte<mode>"
> +(define_insn "@aarch64_rsqrte<mode>"
>    [(set (match_operand:VHSDF_HSDF 0 "register_operand" "=w")
>  	(unspec:VHSDF_HSDF [(match_operand:VHSDF_HSDF 1 "register_operand" "w")]
>  		     UNSPEC_RSQRTE))]
> @@ -567,7 +567,7 @@ (define_insn "aarch64_rsqrte<mode>"
>    "frsqrte\\t%<v>0<Vmtype>, %<v>1<Vmtype>"
>    [(set_attr "type" "neon_fp_rsqrte_<stype><q>")])
>  
> -(define_insn "aarch64_rsqrts<mode>"
> +(define_insn "@aarch64_rsqrts<mode>"
>    [(set (match_operand:VHSDF_HSDF 0 "register_operand" "=w")
>  	(unspec:VHSDF_HSDF [(match_operand:VHSDF_HSDF 1 "register_operand" "w")
>  			    (match_operand:VHSDF_HSDF 2 "register_operand" "w")]
> @@ -3144,7 +3144,7 @@ (define_expand "aarch64_combine<mode>"
>  }
>  )
>  
> -(define_expand "aarch64_simd_combine<mode>"
> +(define_expand "@aarch64_simd_combine<mode>"
>    [(match_operand:<VDBL> 0 "register_operand")
>     (match_operand:VDC 1 "register_operand")
>     (match_operand:VDC 2 "register_operand")]
> @@ -5841,7 +5841,7 @@ (define_insn "aarch64_simd_ld1<mode>_x2"
>  )
>  
>  
> -(define_insn "aarch64_frecpe<mode>"
> +(define_insn "@aarch64_frecpe<mode>"
>    [(set (match_operand:VHSDF 0 "register_operand" "=w")
>  	(unspec:VHSDF [(match_operand:VHSDF 1 "register_operand" "w")]
>  	 UNSPEC_FRECPE))]
> @@ -5859,7 +5859,7 @@ (define_insn "aarch64_frecp<FRECP:frecp_
>    [(set_attr "type" "neon_fp_recp<FRECP:frecp_suffix>_<GPF_F16:stype>")]
>  )
>  
> -(define_insn "aarch64_frecps<mode>"
> +(define_insn "@aarch64_frecps<mode>"
>    [(set (match_operand:VHSDF_HSDF 0 "register_operand" "=w")
>  	(unspec:VHSDF_HSDF
>  	  [(match_operand:VHSDF_HSDF 1 "register_operand" "w")
> Index: gcc/config/aarch64/atomics.md
> ===================================================================
> --- gcc/config/aarch64/atomics.md	2018-05-02 08:38:17.517334934 +0100
> +++ gcc/config/aarch64/atomics.md	2018-07-13 10:11:35.361665853 +0100
> @@ -20,7 +20,7 @@
>  
>  ;; Instruction patterns.
>  
> -(define_expand "atomic_compare_and_swap<mode>"
> +(define_expand "@atomic_compare_and_swap<mode>"
>    [(match_operand:SI 0 "register_operand" "")			;; bool out
>     (match_operand:ALLI 1 "register_operand" "")			;; val out
>     (match_operand:ALLI 2 "aarch64_sync_memory_operand" "")	;; memory
> @@ -36,7 +36,7 @@ (define_expand "atomic_compare_and_swap<
>    }
>  )
>  
> -(define_insn_and_split "aarch64_compare_and_swap<mode>"
> +(define_insn_and_split "@aarch64_compare_and_swap<mode>"
>    [(set (reg:CC CC_REGNUM)					;; bool out
>      (unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
>     (set (match_operand:SI 0 "register_operand" "=&r")	   ;; val out
> @@ -61,7 +61,7 @@ (define_insn_and_split "aarch64_compare_
>    }
>  )
>  
> -(define_insn_and_split "aarch64_compare_and_swap<mode>"
> +(define_insn_and_split "@aarch64_compare_and_swap<mode>"
>    [(set (reg:CC CC_REGNUM)					;; bool out
>      (unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
>     (set (match_operand:GPI 0 "register_operand" "=&r")		;; val out
> @@ -85,7 +85,7 @@ (define_insn_and_split "aarch64_compare_
>    }
>  )
>  
> -(define_insn_and_split "aarch64_compare_and_swap<mode>_lse"
> +(define_insn_and_split "@aarch64_compare_and_swap<mode>_lse"
>    [(set (reg:CC CC_REGNUM)					;; bool out
>      (unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
>     (set (match_operand:SI 0 "register_operand" "=&r")		;; val out
> @@ -111,7 +111,7 @@ (define_insn_and_split "aarch64_compare_
>    }
>  )
>  
> -(define_insn_and_split "aarch64_compare_and_swap<mode>_lse"
> +(define_insn_and_split "@aarch64_compare_and_swap<mode>_lse"
>    [(set (reg:CC CC_REGNUM)					;; bool out
>      (unspec_volatile:CC [(const_int 0)] UNSPECV_ATOMIC_CMPSW))
>     (set (match_operand:GPI 0 "register_operand" "=&r")		;; val out
> @@ -496,7 +496,7 @@ (define_insn "atomic_store<mode>"
>    }
>  )
>  
> -(define_insn "aarch64_load_exclusive<mode>"
> +(define_insn "@aarch64_load_exclusive<mode>"
>    [(set (match_operand:SI 0 "register_operand" "=r")
>      (zero_extend:SI
>        (unspec_volatile:SHORT
> @@ -513,7 +513,7 @@ (define_insn "aarch64_load_exclusive<mod
>    }
>  )
>  
> -(define_insn "aarch64_load_exclusive<mode>"
> +(define_insn "@aarch64_load_exclusive<mode>"
>    [(set (match_operand:GPI 0 "register_operand" "=r")
>      (unspec_volatile:GPI
>        [(match_operand:GPI 1 "aarch64_sync_memory_operand" "Q")
> @@ -529,7 +529,7 @@ (define_insn "aarch64_load_exclusive<mod
>    }
>  )
>  
> -(define_insn "aarch64_store_exclusive<mode>"
> +(define_insn "@aarch64_store_exclusive<mode>"
>    [(set (match_operand:SI 0 "register_operand" "=r")
>      (unspec_volatile:SI [(const_int 0)] UNSPECV_SX))
>     (set (match_operand:ALLI 1 "aarch64_sync_memory_operand" "=Q")
> @@ -586,7 +586,7 @@ (define_insn "*dmb"
>  ;; ARMv8.1-A LSE instructions.
>  
>  ;; Atomic swap with memory.
> -(define_insn "aarch64_atomic_swp<mode>"
> +(define_insn "@aarch64_atomic_swp<mode>"
>   [(set (match_operand:ALLI 0 "register_operand" "+&r")
>     (match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q"))
>    (set (match_dup 1)
> @@ -609,7 +609,7 @@ (define_insn "aarch64_atomic_swp<mode>"
>  
>  ;; Atomic compare-and-swap: HI and smaller modes.
>  
> -(define_insn "aarch64_atomic_cas<mode>"
> +(define_insn "@aarch64_atomic_cas<mode>"
>   [(set (match_operand:SI 0 "register_operand" "+&r")		  ;; out
>     (zero_extend:SI
>      (match_operand:SHORT 1 "aarch64_sync_memory_operand" "+Q")))  ;; memory.
> @@ -634,7 +634,7 @@ (define_insn "aarch64_atomic_cas<mode>"
>  
>  ;; Atomic compare-and-swap: SI and larger modes.
>  
> -(define_insn "aarch64_atomic_cas<mode>"
> +(define_insn "@aarch64_atomic_cas<mode>"
>   [(set (match_operand:GPI 0 "register_operand" "+&r")	      ;; out
>     (match_operand:GPI 1 "aarch64_sync_memory_operand" "+Q"))  ;; memory.
>    (set (match_dup 1)
> @@ -658,7 +658,7 @@ (define_insn "aarch64_atomic_cas<mode>"
>  
>  ;; Atomic load-op: Load data, operate, store result, keep data.
>  
> -(define_insn "aarch64_atomic_load<atomic_ldop><mode>"
> +(define_insn "@aarch64_atomic_load<atomic_ldop><mode>"
>   [(set (match_operand:ALLI 0 "register_operand" "=r")
>     (match_operand:ALLI 1 "aarch64_sync_memory_operand" "+Q"))
>    (set (match_dup 1)
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]