diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2018-08-02 10:59:35 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2018-08-02 10:59:35 +0000 |
commit | 0016d8d91cb2880e69be74efb44367b282577977 (patch) | |
tree | c65a69b7b2e33e1f21911fa540f0ce7579294e37 /gcc/genemit.c | |
parent | a451882123524de1b9b175af97a1cdd32e5f25c1 (diff) | |
download | gcc-0016d8d91cb2880e69be74efb44367b282577977.zip gcc-0016d8d91cb2880e69be74efb44367b282577977.tar.gz gcc-0016d8d91cb2880e69be74efb44367b282577977.tar.bz2 |
[gen/AArch64] Generate helpers for substituting iterator values into pattern names
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.
2018-08-02 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.
* genopinit.c (handle_overloaded_code_for)
(handle_overloaded_gen): New functions.
(main): Use them to print declarations of maybe_code_for_* and
maybe_gen_* functions, and inline definitions of code_for_* and 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.
From-SVN: r263251
Diffstat (limited to 'gcc/genemit.c')
-rw-r--r-- | gcc/genemit.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/gcc/genemit.c b/gcc/genemit.c index f4179e2..9227030 100644 --- a/gcc/genemit.c +++ b/gcc/genemit.c @@ -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 @@ from the machine description file `md'. */\n\n"); 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); } |