diff options
Diffstat (limited to 'gcc/optabs.h')
-rw-r--r-- | gcc/optabs.h | 273 |
1 files changed, 199 insertions, 74 deletions
diff --git a/gcc/optabs.h b/gcc/optabs.h index faa4330e5dd..547339bcee6 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -29,10 +29,6 @@ along with GCC; see the file COPYING3. If not see For example, add_optab applies to addition. - The insn_code slot is the enum insn_code that says how to - generate an insn for this operation on a particular machine mode. - It is CODE_FOR_nothing if there is no such insn on the target machine. - The `lib_call' slot is the name of the library function that can be used to perform the operation. @@ -40,7 +36,10 @@ along with GCC; see the file COPYING3. If not see struct optab_handlers { - enum insn_code insn_code; + /* I - CODE_FOR_nothing, where I is either the insn code of the + associated insn generator or CODE_FOR_nothing if there is no such + insn on the target machine. */ + int insn_code; }; struct optab_d @@ -372,8 +371,6 @@ enum optab_index OTI_MAX }; -extern struct optab_d optab_table[OTI_MAX]; - #define ssadd_optab (&optab_table[OTI_ssadd]) #define usadd_optab (&optab_table[OTI_usadd]) #define sssub_optab (&optab_table[OTI_sssub]) @@ -575,8 +572,6 @@ enum convert_optab_index COI_MAX }; -extern struct convert_optab_d convert_optab_table[COI_MAX]; - #define sext_optab (&convert_optab_table[COI_sext]) #define zext_optab (&convert_optab_table[COI_zext]) #define trunc_optab (&convert_optab_table[COI_trunc]) @@ -595,79 +590,152 @@ extern struct convert_optab_d convert_optab_table[COI_MAX]; #define satfract_optab (&convert_optab_table[COI_satfract]) #define satfractuns_optab (&convert_optab_table[COI_satfractuns]) -/* These arrays record the insn_code of insns that may be needed to - perform input and output reloads of special objects. They provide a - place to pass a scratch register. */ -extern enum insn_code reload_in_optab[NUM_MACHINE_MODES]; -extern enum insn_code reload_out_optab[NUM_MACHINE_MODES]; - /* Contains the optab used for each rtx code. */ extern optab code_to_optab[NUM_RTX_CODE + 1]; typedef rtx (*rtxfun) (rtx); +/* Enumerates operations that have a named .md pattern associated + with them, but which are not implemented as library functions. */ +enum direct_optab_index +{ #ifdef HAVE_conditional_move -/* Indexed by the machine mode, gives the insn code to make a conditional - move insn. */ + /* Conditional move operations. */ + DOI_movcc, +#endif + + /* Operations that use a scratch register to perform input and output + reloads of special objects. */ + DOI_reload_in, + DOI_reload_out, + + /* Vector conditional operations. */ + DOI_vcond, + DOI_vcondu, + + /* Block move operation. */ + DOI_movmem, + + /* Block set operation. */ + DOI_setmem, + + /* Various types of block compare operation. */ + DOI_cmpstr, + DOI_cmpstrn, + DOI_cmpmem, + + /* Synchronization primitives. This first set is atomic operation for + which we don't care about the resulting value. */ + DOI_sync_add, + DOI_sync_sub, + DOI_sync_ior, + DOI_sync_and, + DOI_sync_xor, + DOI_sync_nand, + + /* This second set is atomic operations in which we return the value + that existed in memory before the operation. */ + DOI_sync_old_add, + DOI_sync_old_sub, + DOI_sync_old_ior, + DOI_sync_old_and, + DOI_sync_old_xor, + DOI_sync_old_nand, + + /* This third set is atomic operations in which we return the value + that resulted after performing the operation. */ + DOI_sync_new_add, + DOI_sync_new_sub, + DOI_sync_new_ior, + DOI_sync_new_and, + DOI_sync_new_xor, + DOI_sync_new_nand, + + /* Atomic compare and swap. */ + DOI_sync_compare_and_swap, + + /* Atomic exchange with acquire semantics. */ + DOI_sync_lock_test_and_set, + + /* Atomic clear with release semantics. */ + DOI_sync_lock_release, + + DOI_MAX +}; + +/* A structure that says which insn should be used to perform an operation + in a particular mode. */ +struct direct_optab_d +{ + struct optab_handlers handlers[NUM_MACHINE_MODES]; +}; +typedef struct direct_optab_d *direct_optab; -extern enum insn_code movcc_gen_code[NUM_MACHINE_MODES]; +#ifdef HAVE_conditional_move +#define movcc_optab (&direct_optab_table[(int) DOI_movcc]) #endif +#define reload_in_optab (&direct_optab_table[(int) DOI_reload_in]) +#define reload_out_optab (&direct_optab_table[(int) DOI_reload_out]) +#define vcond_optab (&direct_optab_table[(int) DOI_vcond]) +#define vcondu_optab (&direct_optab_table[(int) DOI_vcondu]) +#define movmem_optab (&direct_optab_table[(int) DOI_movmem]) +#define setmem_optab (&direct_optab_table[(int) DOI_setmem]) +#define cmpstr_optab (&direct_optab_table[(int) DOI_cmpstr]) +#define cmpstrn_optab (&direct_optab_table[(int) DOI_cmpstrn]) +#define cmpmem_optab (&direct_optab_table[(int) DOI_cmpmem]) +#define sync_add_optab (&direct_optab_table[(int) DOI_sync_add]) +#define sync_sub_optab (&direct_optab_table[(int) DOI_sync_sub]) +#define sync_ior_optab (&direct_optab_table[(int) DOI_sync_ior]) +#define sync_and_optab (&direct_optab_table[(int) DOI_sync_and]) +#define sync_xor_optab (&direct_optab_table[(int) DOI_sync_xor]) +#define sync_nand_optab (&direct_optab_table[(int) DOI_sync_nand]) +#define sync_old_add_optab (&direct_optab_table[(int) DOI_sync_old_add]) +#define sync_old_sub_optab (&direct_optab_table[(int) DOI_sync_old_sub]) +#define sync_old_ior_optab (&direct_optab_table[(int) DOI_sync_old_ior]) +#define sync_old_and_optab (&direct_optab_table[(int) DOI_sync_old_and]) +#define sync_old_xor_optab (&direct_optab_table[(int) DOI_sync_old_xor]) +#define sync_old_nand_optab (&direct_optab_table[(int) DOI_sync_old_nand]) +#define sync_new_add_optab (&direct_optab_table[(int) DOI_sync_new_add]) +#define sync_new_sub_optab (&direct_optab_table[(int) DOI_sync_new_sub]) +#define sync_new_ior_optab (&direct_optab_table[(int) DOI_sync_new_ior]) +#define sync_new_and_optab (&direct_optab_table[(int) DOI_sync_new_and]) +#define sync_new_xor_optab (&direct_optab_table[(int) DOI_sync_new_xor]) +#define sync_new_nand_optab (&direct_optab_table[(int) DOI_sync_new_nand]) +#define sync_compare_and_swap_optab \ + (&direct_optab_table[(int) DOI_sync_compare_and_swap]) +#define sync_lock_test_and_set_optab \ + (&direct_optab_table[(int) DOI_sync_lock_test_and_set]) +#define sync_lock_release_optab \ + (&direct_optab_table[(int) DOI_sync_lock_release]) + +/* Target-dependent globals. */ +struct target_optabs { + /* Tables of patterns that may have an associated libcall. */ + struct optab_d x_optab_table[(int) OTI_MAX]; -/* Indexed by the machine mode, gives the insn code for vector conditional - operation. */ - -extern enum insn_code vcond_gen_code[NUM_MACHINE_MODES]; -extern enum insn_code vcondu_gen_code[NUM_MACHINE_MODES]; - -/* This array records the insn_code of insns to perform block moves. */ -extern enum insn_code movmem_optab[NUM_MACHINE_MODES]; - -/* This array records the insn_code of insns to perform block sets. */ -extern enum insn_code setmem_optab[NUM_MACHINE_MODES]; - -/* These arrays record the insn_code of two different kinds of insns - to perform block compares. */ -extern enum insn_code cmpstr_optab[NUM_MACHINE_MODES]; -extern enum insn_code cmpstrn_optab[NUM_MACHINE_MODES]; -extern enum insn_code cmpmem_optab[NUM_MACHINE_MODES]; - -/* Synchronization primitives. This first set is atomic operation for - which we don't care about the resulting value. */ -extern enum insn_code sync_add_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_sub_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_ior_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_and_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_xor_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_nand_optab[NUM_MACHINE_MODES]; - -/* This second set is atomic operations in which we return the value - that existed in memory before the operation. */ -extern enum insn_code sync_old_add_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_old_sub_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_old_ior_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_old_and_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_old_xor_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_old_nand_optab[NUM_MACHINE_MODES]; - -/* This third set is atomic operations in which we return the value - that resulted after performing the operation. */ -extern enum insn_code sync_new_add_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_new_sub_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_new_ior_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_new_and_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_new_xor_optab[NUM_MACHINE_MODES]; -extern enum insn_code sync_new_nand_optab[NUM_MACHINE_MODES]; - -/* Atomic compare and swap. */ -extern enum insn_code sync_compare_and_swap[NUM_MACHINE_MODES]; - -/* Atomic exchange with acquire semantics. */ -extern enum insn_code sync_lock_test_and_set[NUM_MACHINE_MODES]; - -/* Atomic clear with release semantics. */ -extern enum insn_code sync_lock_release[NUM_MACHINE_MODES]; + /* Tables of patterns for converting one mode to another. */ + struct convert_optab_d x_convert_optab_table[(int) COI_MAX]; + + /* Tables of patterns for direct optabs (i.e. those which cannot be + implemented using a libcall). */ + struct direct_optab_d x_direct_optab_table[(int) DOI_MAX]; +}; + +extern struct target_optabs default_target_optabs; +#if SWITCHABLE_TARGET +extern struct target_optabs *this_target_optabs; +#else +#define this_target_optabs (&default_target_optabs) +#endif +#define optab_table \ + (this_target_optabs->x_optab_table) +#define convert_optab_table \ + (this_target_optabs->x_convert_optab_table) +#define direct_optab_table \ + (this_target_optabs->x_direct_optab_table) + /* Define functions given in optabs.c. */ extern rtx expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op, @@ -782,9 +850,66 @@ extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx); /* Generate code for VEC_LSHIFT_EXPR and VEC_RSHIFT_EXPR. */ extern rtx expand_vec_shift_expr (sepops, rtx); -#define optab_handler(optab,mode) (&(optab)->handlers[(int) (mode)]) -#define convert_optab_handler(optab,mode,mode2) \ - (&(optab)->handlers[(int) (mode)][(int) (mode2)]) +/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing + if the target does not have such an insn. */ + +static inline enum insn_code +optab_handler (optab op, enum machine_mode mode) +{ + return (enum insn_code) (op->handlers[(int) mode].insn_code + + (int) CODE_FOR_nothing); +} + +/* Record that insn CODE should be used to implement mode MODE of OP. */ + +static inline void +set_optab_handler (optab op, enum machine_mode mode, enum insn_code code) +{ + op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing; +} + +/* Return the insn used to perform conversion OP from mode FROM_MODE + to mode TO_MODE; return CODE_FOR_nothing if the target does not have + such an insn. */ + +static inline enum insn_code +convert_optab_handler (convert_optab op, enum machine_mode to_mode, + enum machine_mode from_mode) +{ + return ((enum insn_code) + (op->handlers[(int) to_mode][(int) from_mode].insn_code + + (int) CODE_FOR_nothing)); +} + +/* Record that insn CODE should be used to perform conversion OP + from mode FROM_MODE to mode TO_MODE. */ + +static inline void +set_convert_optab_handler (convert_optab op, enum machine_mode to_mode, + enum machine_mode from_mode, enum insn_code code) +{ + op->handlers[(int) to_mode][(int) from_mode].insn_code + = (int) code - (int) CODE_FOR_nothing; +} + +/* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing + if the target does not have such an insn. */ + +static inline enum insn_code +direct_optab_handler (direct_optab op, enum machine_mode mode) +{ + return (enum insn_code) (op->handlers[(int) mode].insn_code + + (int) CODE_FOR_nothing); +} + +/* Record that insn CODE should be used to implement mode MODE of OP. */ + +static inline void +set_direct_optab_handler (direct_optab op, enum machine_mode mode, + enum insn_code code) +{ + op->handlers[(int) mode].insn_code = (int) code - (int) CODE_FOR_nothing; +} extern rtx optab_libfunc (optab optab, enum machine_mode mode); extern rtx convert_optab_libfunc (convert_optab optab, enum machine_mode mode1, |