OSDN Git Service

* config/sparc/sparc.md (adddi3_insn_sp32): Add earlyclobber.
[pf3gnuchains/gcc-fork.git] / gcc / optabs.h
index c5b4a3d..6ad6dae 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions for code generation pass of GNU compiler.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -29,38 +29,49 @@ 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.
 
-   A few optabs, such as move_optab and cmp_optab, are used
-   by special code.  */
+   A few optabs, such as move_optab, are used by special code.  */
 
-struct optab_handlers GTY(())
+struct optab_handlers
 {
-  enum insn_code insn_code;
-  rtx libfunc;
+  /* 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 GTY(())
+struct widening_optab_handlers
+{
+  struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
+};
+
+struct optab_d
 {
   enum rtx_code code;
+  char libcall_suffix;
+  const char *libcall_basename;
+  void (*libcall_gen)(struct optab_d *, const char *name, char suffix,
+                     enum machine_mode);
   struct optab_handlers handlers[NUM_MACHINE_MODES];
+  struct widening_optab_handlers *widening;
 };
-typedef struct optab * optab;
+typedef struct optab_d * optab;
 
 /* A convert_optab is for some sort of conversion operation between
    modes.  The first array index is the destination mode, the second
    is the source mode.  */
-struct convert_optab GTY(())
+struct convert_optab_d
 {
   enum rtx_code code;
+  const char *libcall_basename;
+  void (*libcall_gen)(struct convert_optab_d *, const char *name,
+                     enum machine_mode,
+                     enum machine_mode);
   struct optab_handlers handlers[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
 };
-typedef struct convert_optab *convert_optab;
+typedef struct convert_optab_d *convert_optab;
 
 /* Given an enum insn_code, access the function to construct
    the body of that kind of insn.  */
@@ -69,6 +80,20 @@ typedef struct convert_optab *convert_optab;
 /* Enumeration of valid indexes into optab_table.  */
 enum optab_index
 {
+  /* Fixed-point operators with signed/unsigned saturation */
+  OTI_ssadd,
+  OTI_usadd,
+  OTI_sssub,
+  OTI_ussub,
+  OTI_ssmul,
+  OTI_usmul,
+  OTI_ssdiv,
+  OTI_usdiv,
+  OTI_ssneg,
+  OTI_usneg,
+  OTI_ssashl,
+  OTI_usashl,
+
   OTI_add,
   OTI_addv,
   OTI_sub,
@@ -91,12 +116,28 @@ enum optab_index
   /* Unsigned multiply and add with the result and addend one machine mode
      wider than the multiplicand and multiplier.  */
   OTI_umadd_widen,
+  /* Signed multiply and add with the result and addend one machine mode
+     wider than the multiplicand and multiplier.
+     All involved operations are saturating.  */
+  OTI_ssmadd_widen,
+  /* Unsigned multiply and add with the result and addend one machine mode
+     wider than the multiplicand and multiplier.
+     All involved operations are saturating.  */
+  OTI_usmadd_widen,
   /* Signed multiply and subtract the result and minuend one machine mode
      wider than the multiplicand and multiplier.  */
   OTI_smsub_widen,
   /* Unsigned multiply and subtract the result and minuend one machine mode
      wider than the multiplicand and multiplier.  */
   OTI_umsub_widen,
+  /* Signed multiply and subtract the result and minuend one machine mode
+     wider than the multiplicand and multiplier.
+     All involved operations are saturating.  */
+  OTI_ssmsub_widen,
+  /* Unsigned multiply and subtract the result and minuend one machine mode
+     wider than the multiplicand and multiplier.
+     All involved operations are saturating.  */
+  OTI_usmsub_widen,
 
   /* Signed divide */
   OTI_sdiv,
@@ -131,6 +172,18 @@ enum optab_index
   OTI_rotl,
   /* Rotate right */
   OTI_rotr,
+
+  /* Arithmetic shift left of vector by vector */
+  OTI_vashl,
+  /* Logical shift right of vector by vector */
+  OTI_vlshr,
+  /* Arithmetic shift right of vector by vector */
+  OTI_vashr,
+  /* Rotate left of vector by vector */
+  OTI_vrotl,
+  /* Rotate right of vector by vector */
+  OTI_vrotr,
+
   /* Signed and floating-point minimum value */
   OTI_smin,
   /* Signed and floating-point maximum value */
@@ -143,6 +196,11 @@ enum optab_index
   OTI_pow,
   /* Arc tangent of y/x */
   OTI_atan2,
+  /* Floating multiply/add */
+  OTI_fma,
+  OTI_fms,
+  OTI_fnma,
+  OTI_fnms,
 
   /* Move instruction.  */
   OTI_mov,
@@ -168,6 +226,7 @@ enum optab_index
   OTI_ffs,
   OTI_clz,
   OTI_ctz,
+  OTI_clrsb,
   OTI_popcount,
   OTI_parity,
   /* Square root */
@@ -194,6 +253,8 @@ enum optab_index
   OTI_ldexp,
   /* Multiply floating-point number by integral power of radix */
   OTI_scalb,
+  /* Mantissa of a floating-point number */
+  OTI_significand,
   /* Radix-independent exponent */
   OTI_logb,
   OTI_ilogb,
@@ -223,12 +284,9 @@ enum optab_index
   /* Test for infinite value */
   OTI_isinf,
 
-  /* Compare insn; two operands.  */
+  /* Compare insn; two operands.  Used only for libcalls.  */
   OTI_cmp,
-  /* Used only for libcalls for unsigned comparisons.  */
   OTI_ucmp,
-  /* tst insn; compare one operand against 0 */
-  OTI_tst,
 
   /* Floating point comparison optabs - used primarily for libfuncs */
   OTI_eq,
@@ -242,10 +300,11 @@ enum optab_index
   /* String length */
   OTI_strlen,
 
-  /* Combined compare & jump/store flags/move operations.  */
+  /* Combined compare & jump/move/store flags/trap operations.  */
   OTI_cbranch,
   OTI_cmov,
   OTI_cstore,
+  OTI_ctrap,
 
   /* Push instruction.  */
   OTI_push,
@@ -273,12 +332,6 @@ enum optab_index
   OTI_vec_set,
   /* Extract specified field of vector operand.  */
   OTI_vec_extract,
-  /* Extract even/odd fields of vector operands.  */
-  OTI_vec_extract_even,
-  OTI_vec_extract_odd,
-  /* Interleave fields of vector operands.  */
-  OTI_vec_interleave_high,
-  OTI_vec_interleave_low,
   /* Initialize vector operand.  */
   OTI_vec_init,
   /* Whole vector shift. The shift amount is in bits.  */
@@ -286,12 +339,18 @@ enum optab_index
   OTI_vec_shr,
   /* Extract specified elements from vectors, for vector load.  */
   OTI_vec_realign_load,
-  /* Widening multiplication.  
+  /* Widening multiplication.
      The high/low part of the resulting vector of products is returned.  */
   OTI_vec_widen_umult_hi,
   OTI_vec_widen_umult_lo,
   OTI_vec_widen_smult_hi,
   OTI_vec_widen_smult_lo,
+  /* Widening shift left.
+     The high/low part of the resulting vector is returned.  */
+  OTI_vec_widen_ushiftl_hi,
+  OTI_vec_widen_ushiftl_lo,
+  OTI_vec_widen_sshiftl_hi,
+  OTI_vec_widen_sshiftl_lo,
   /* Extract and widen the high/low part of a vector of signed or
      floating point elements.  */
   OTI_vec_unpacks_hi,
@@ -321,158 +380,226 @@ enum optab_index
   /* Perform a raise to the power of integer.  */
   OTI_powi,
 
+  /* Atomic compare and swap.  */
+  OTI_sync_compare_and_swap,
+
+  /* Atomic exchange with acquire semantics.  */
+  OTI_sync_lock_test_and_set,
+
+  /* This second set is atomic operations in which we return the value
+     that existed in memory before the operation.  */
+  OTI_sync_old_add,
+  OTI_sync_old_sub,
+  OTI_sync_old_ior,
+  OTI_sync_old_and,
+  OTI_sync_old_xor,
+  OTI_sync_old_nand,
+
+  /* This third set is atomic operations in which we return the value
+     that resulted after performing the operation.  */
+  OTI_sync_new_add,
+  OTI_sync_new_sub,
+  OTI_sync_new_ior,
+  OTI_sync_new_and,
+  OTI_sync_new_xor,
+  OTI_sync_new_nand,
+
   OTI_MAX
 };
 
-extern GTY(()) optab optab_table[OTI_MAX];
-
-#define add_optab (optab_table[OTI_add])
-#define sub_optab (optab_table[OTI_sub])
-#define smul_optab (optab_table[OTI_smul])
-#define addv_optab (optab_table[OTI_addv])
-#define subv_optab (optab_table[OTI_subv])
-#define smul_highpart_optab (optab_table[OTI_smul_highpart])
-#define umul_highpart_optab (optab_table[OTI_umul_highpart])
-#define smul_widen_optab (optab_table[OTI_smul_widen])
-#define umul_widen_optab (optab_table[OTI_umul_widen])
-#define usmul_widen_optab (optab_table[OTI_usmul_widen])
-#define smadd_widen_optab (optab_table[OTI_smadd_widen])
-#define umadd_widen_optab (optab_table[OTI_umadd_widen])
-#define smsub_widen_optab (optab_table[OTI_smsub_widen])
-#define umsub_widen_optab (optab_table[OTI_umsub_widen])
-#define sdiv_optab (optab_table[OTI_sdiv])
-#define smulv_optab (optab_table[OTI_smulv])
-#define sdivv_optab (optab_table[OTI_sdivv])
-#define sdivmod_optab (optab_table[OTI_sdivmod])
-#define udiv_optab (optab_table[OTI_udiv])
-#define udivmod_optab (optab_table[OTI_udivmod])
-#define smod_optab (optab_table[OTI_smod])
-#define umod_optab (optab_table[OTI_umod])
-#define fmod_optab (optab_table[OTI_fmod])
-#define remainder_optab (optab_table[OTI_remainder])
-#define ftrunc_optab (optab_table[OTI_ftrunc])
-#define and_optab (optab_table[OTI_and])
-#define ior_optab (optab_table[OTI_ior])
-#define xor_optab (optab_table[OTI_xor])
-#define ashl_optab (optab_table[OTI_ashl])
-#define lshr_optab (optab_table[OTI_lshr])
-#define ashr_optab (optab_table[OTI_ashr])
-#define rotl_optab (optab_table[OTI_rotl])
-#define rotr_optab (optab_table[OTI_rotr])
-#define smin_optab (optab_table[OTI_smin])
-#define smax_optab (optab_table[OTI_smax])
-#define umin_optab (optab_table[OTI_umin])
-#define umax_optab (optab_table[OTI_umax])
-#define pow_optab (optab_table[OTI_pow])
-#define atan2_optab (optab_table[OTI_atan2])
-
-#define mov_optab (optab_table[OTI_mov])
-#define movstrict_optab (optab_table[OTI_movstrict])
-#define movmisalign_optab (optab_table[OTI_movmisalign])
-#define storent_optab (optab_table[OTI_storent])
-
-#define neg_optab (optab_table[OTI_neg])
-#define negv_optab (optab_table[OTI_negv])
-#define abs_optab (optab_table[OTI_abs])
-#define absv_optab (optab_table[OTI_absv])
-#define one_cmpl_optab (optab_table[OTI_one_cmpl])
-#define bswap_optab (optab_table[OTI_bswap])
-#define ffs_optab (optab_table[OTI_ffs])
-#define clz_optab (optab_table[OTI_clz])
-#define ctz_optab (optab_table[OTI_ctz])
-#define popcount_optab (optab_table[OTI_popcount])
-#define parity_optab (optab_table[OTI_parity])
-#define sqrt_optab (optab_table[OTI_sqrt])
-#define sincos_optab (optab_table[OTI_sincos])
-#define sin_optab (optab_table[OTI_sin])
-#define asin_optab (optab_table[OTI_asin])
-#define cos_optab (optab_table[OTI_cos])
-#define acos_optab (optab_table[OTI_acos])
-#define exp_optab (optab_table[OTI_exp])
-#define exp10_optab (optab_table[OTI_exp10])
-#define exp2_optab (optab_table[OTI_exp2])
-#define expm1_optab (optab_table[OTI_expm1])
-#define ldexp_optab (optab_table[OTI_ldexp])
-#define scalb_optab (optab_table[OTI_scalb])
-#define logb_optab (optab_table[OTI_logb])
-#define ilogb_optab (optab_table[OTI_ilogb])
-#define log_optab (optab_table[OTI_log])
-#define log10_optab (optab_table[OTI_log10])
-#define log2_optab (optab_table[OTI_log2])
-#define log1p_optab (optab_table[OTI_log1p])
-#define floor_optab (optab_table[OTI_floor])
-#define ceil_optab (optab_table[OTI_ceil])
-#define btrunc_optab (optab_table[OTI_btrunc])
-#define round_optab (optab_table[OTI_round])
-#define nearbyint_optab (optab_table[OTI_nearbyint])
-#define rint_optab (optab_table[OTI_rint])
-#define tan_optab (optab_table[OTI_tan])
-#define atan_optab (optab_table[OTI_atan])
-#define copysign_optab (optab_table[OTI_copysign])
-#define signbit_optab (optab_table[OTI_signbit])
-#define isinf_optab (optab_table[OTI_isinf])
-
-#define cmp_optab (optab_table[OTI_cmp])
-#define ucmp_optab (optab_table[OTI_ucmp])
-#define tst_optab (optab_table[OTI_tst])
-
-#define eq_optab (optab_table[OTI_eq])
-#define ne_optab (optab_table[OTI_ne])
-#define gt_optab (optab_table[OTI_gt])
-#define ge_optab (optab_table[OTI_ge])
-#define lt_optab (optab_table[OTI_lt])
-#define le_optab (optab_table[OTI_le])
-#define unord_optab (optab_table[OTI_unord])
-
-#define strlen_optab (optab_table[OTI_strlen])
-
-#define cbranch_optab (optab_table[OTI_cbranch])
-#define cmov_optab (optab_table[OTI_cmov])
-#define cstore_optab (optab_table[OTI_cstore])
-#define push_optab (optab_table[OTI_push])
-#define addcc_optab (optab_table[OTI_addcc])
-
-#define reduc_smax_optab (optab_table[OTI_reduc_smax])
-#define reduc_umax_optab (optab_table[OTI_reduc_umax])
-#define reduc_smin_optab (optab_table[OTI_reduc_smin])
-#define reduc_umin_optab (optab_table[OTI_reduc_umin])
-#define reduc_splus_optab (optab_table[OTI_reduc_splus])
-#define reduc_uplus_optab (optab_table[OTI_reduc_uplus])
-
-#define ssum_widen_optab (optab_table[OTI_ssum_widen])
-#define usum_widen_optab (optab_table[OTI_usum_widen])
-#define sdot_prod_optab (optab_table[OTI_sdot_prod])
-#define udot_prod_optab (optab_table[OTI_udot_prod])
-
-#define vec_set_optab (optab_table[OTI_vec_set])
-#define vec_extract_optab (optab_table[OTI_vec_extract])
-#define vec_extract_even_optab (optab_table[OTI_vec_extract_even])
-#define vec_extract_odd_optab (optab_table[OTI_vec_extract_odd])
-#define vec_interleave_high_optab (optab_table[OTI_vec_interleave_high])
-#define vec_interleave_low_optab (optab_table[OTI_vec_interleave_low])
-#define vec_init_optab (optab_table[OTI_vec_init])
-#define vec_shl_optab (optab_table[OTI_vec_shl])
-#define vec_shr_optab (optab_table[OTI_vec_shr])
-#define vec_realign_load_optab (optab_table[OTI_vec_realign_load])
-#define vec_widen_umult_hi_optab (optab_table[OTI_vec_widen_umult_hi])
-#define vec_widen_umult_lo_optab (optab_table[OTI_vec_widen_umult_lo])
-#define vec_widen_smult_hi_optab (optab_table[OTI_vec_widen_smult_hi])
-#define vec_widen_smult_lo_optab (optab_table[OTI_vec_widen_smult_lo])
-#define vec_unpacks_hi_optab (optab_table[OTI_vec_unpacks_hi])
-#define vec_unpacks_lo_optab (optab_table[OTI_vec_unpacks_lo])
-#define vec_unpacku_hi_optab (optab_table[OTI_vec_unpacku_hi])
-#define vec_unpacku_lo_optab (optab_table[OTI_vec_unpacku_lo])
-#define vec_unpacks_float_hi_optab (optab_table[OTI_vec_unpacks_float_hi])
-#define vec_unpacks_float_lo_optab (optab_table[OTI_vec_unpacks_float_lo])
-#define vec_unpacku_float_hi_optab (optab_table[OTI_vec_unpacku_float_hi])
-#define vec_unpacku_float_lo_optab (optab_table[OTI_vec_unpacku_float_lo])
-#define vec_pack_trunc_optab (optab_table[OTI_vec_pack_trunc])
-#define vec_pack_ssat_optab (optab_table[OTI_vec_pack_ssat])
-#define vec_pack_usat_optab (optab_table[OTI_vec_pack_usat])
-#define vec_pack_sfix_trunc_optab (optab_table[OTI_vec_pack_sfix_trunc])
-#define vec_pack_ufix_trunc_optab (optab_table[OTI_vec_pack_ufix_trunc])
-
-#define powi_optab (optab_table[OTI_powi])
+#define ssadd_optab (&optab_table[OTI_ssadd])
+#define usadd_optab (&optab_table[OTI_usadd])
+#define sssub_optab (&optab_table[OTI_sssub])
+#define ussub_optab (&optab_table[OTI_ussub])
+#define ssmul_optab (&optab_table[OTI_ssmul])
+#define usmul_optab (&optab_table[OTI_usmul])
+#define ssdiv_optab (&optab_table[OTI_ssdiv])
+#define usdiv_optab (&optab_table[OTI_usdiv])
+#define ssneg_optab (&optab_table[OTI_ssneg])
+#define usneg_optab (&optab_table[OTI_usneg])
+#define ssashl_optab (&optab_table[OTI_ssashl])
+#define usashl_optab (&optab_table[OTI_usashl])
+
+#define add_optab (&optab_table[OTI_add])
+#define sub_optab (&optab_table[OTI_sub])
+#define smul_optab (&optab_table[OTI_smul])
+#define addv_optab (&optab_table[OTI_addv])
+#define subv_optab (&optab_table[OTI_subv])
+#define smul_highpart_optab (&optab_table[OTI_smul_highpart])
+#define umul_highpart_optab (&optab_table[OTI_umul_highpart])
+#define smul_widen_optab (&optab_table[OTI_smul_widen])
+#define umul_widen_optab (&optab_table[OTI_umul_widen])
+#define usmul_widen_optab (&optab_table[OTI_usmul_widen])
+#define smadd_widen_optab (&optab_table[OTI_smadd_widen])
+#define umadd_widen_optab (&optab_table[OTI_umadd_widen])
+#define ssmadd_widen_optab (&optab_table[OTI_ssmadd_widen])
+#define usmadd_widen_optab (&optab_table[OTI_usmadd_widen])
+#define smsub_widen_optab (&optab_table[OTI_smsub_widen])
+#define umsub_widen_optab (&optab_table[OTI_umsub_widen])
+#define ssmsub_widen_optab (&optab_table[OTI_ssmsub_widen])
+#define usmsub_widen_optab (&optab_table[OTI_usmsub_widen])
+#define sdiv_optab (&optab_table[OTI_sdiv])
+#define smulv_optab (&optab_table[OTI_smulv])
+#define sdivv_optab (&optab_table[OTI_sdivv])
+#define sdivmod_optab (&optab_table[OTI_sdivmod])
+#define udiv_optab (&optab_table[OTI_udiv])
+#define udivmod_optab (&optab_table[OTI_udivmod])
+#define smod_optab (&optab_table[OTI_smod])
+#define umod_optab (&optab_table[OTI_umod])
+#define fmod_optab (&optab_table[OTI_fmod])
+#define remainder_optab (&optab_table[OTI_remainder])
+#define ftrunc_optab (&optab_table[OTI_ftrunc])
+#define and_optab (&optab_table[OTI_and])
+#define ior_optab (&optab_table[OTI_ior])
+#define xor_optab (&optab_table[OTI_xor])
+#define ashl_optab (&optab_table[OTI_ashl])
+#define lshr_optab (&optab_table[OTI_lshr])
+#define ashr_optab (&optab_table[OTI_ashr])
+#define rotl_optab (&optab_table[OTI_rotl])
+#define rotr_optab (&optab_table[OTI_rotr])
+#define vashl_optab (&optab_table[OTI_vashl])
+#define vlshr_optab (&optab_table[OTI_vlshr])
+#define vashr_optab (&optab_table[OTI_vashr])
+#define vrotl_optab (&optab_table[OTI_vrotl])
+#define vrotr_optab (&optab_table[OTI_vrotr])
+#define smin_optab (&optab_table[OTI_smin])
+#define smax_optab (&optab_table[OTI_smax])
+#define umin_optab (&optab_table[OTI_umin])
+#define umax_optab (&optab_table[OTI_umax])
+#define pow_optab (&optab_table[OTI_pow])
+#define atan2_optab (&optab_table[OTI_atan2])
+#define fma_optab (&optab_table[OTI_fma])
+#define fms_optab (&optab_table[OTI_fms])
+#define fnma_optab (&optab_table[OTI_fnma])
+#define fnms_optab (&optab_table[OTI_fnms])
+
+#define mov_optab (&optab_table[OTI_mov])
+#define movstrict_optab (&optab_table[OTI_movstrict])
+#define movmisalign_optab (&optab_table[OTI_movmisalign])
+#define storent_optab (&optab_table[OTI_storent])
+
+#define neg_optab (&optab_table[OTI_neg])
+#define negv_optab (&optab_table[OTI_negv])
+#define abs_optab (&optab_table[OTI_abs])
+#define absv_optab (&optab_table[OTI_absv])
+#define one_cmpl_optab (&optab_table[OTI_one_cmpl])
+#define bswap_optab (&optab_table[OTI_bswap])
+#define ffs_optab (&optab_table[OTI_ffs])
+#define clz_optab (&optab_table[OTI_clz])
+#define ctz_optab (&optab_table[OTI_ctz])
+#define clrsb_optab (&optab_table[OTI_clrsb])
+#define popcount_optab (&optab_table[OTI_popcount])
+#define parity_optab (&optab_table[OTI_parity])
+#define sqrt_optab (&optab_table[OTI_sqrt])
+#define sincos_optab (&optab_table[OTI_sincos])
+#define sin_optab (&optab_table[OTI_sin])
+#define asin_optab (&optab_table[OTI_asin])
+#define cos_optab (&optab_table[OTI_cos])
+#define acos_optab (&optab_table[OTI_acos])
+#define exp_optab (&optab_table[OTI_exp])
+#define exp10_optab (&optab_table[OTI_exp10])
+#define exp2_optab (&optab_table[OTI_exp2])
+#define expm1_optab (&optab_table[OTI_expm1])
+#define ldexp_optab (&optab_table[OTI_ldexp])
+#define scalb_optab (&optab_table[OTI_scalb])
+#define significand_optab (&optab_table[OTI_significand])
+#define logb_optab (&optab_table[OTI_logb])
+#define ilogb_optab (&optab_table[OTI_ilogb])
+#define log_optab (&optab_table[OTI_log])
+#define log10_optab (&optab_table[OTI_log10])
+#define log2_optab (&optab_table[OTI_log2])
+#define log1p_optab (&optab_table[OTI_log1p])
+#define floor_optab (&optab_table[OTI_floor])
+#define ceil_optab (&optab_table[OTI_ceil])
+#define btrunc_optab (&optab_table[OTI_btrunc])
+#define round_optab (&optab_table[OTI_round])
+#define nearbyint_optab (&optab_table[OTI_nearbyint])
+#define rint_optab (&optab_table[OTI_rint])
+#define tan_optab (&optab_table[OTI_tan])
+#define atan_optab (&optab_table[OTI_atan])
+#define copysign_optab (&optab_table[OTI_copysign])
+#define signbit_optab (&optab_table[OTI_signbit])
+#define isinf_optab (&optab_table[OTI_isinf])
+
+#define cmp_optab (&optab_table[OTI_cmp])
+#define ucmp_optab (&optab_table[OTI_ucmp])
+
+#define eq_optab (&optab_table[OTI_eq])
+#define ne_optab (&optab_table[OTI_ne])
+#define gt_optab (&optab_table[OTI_gt])
+#define ge_optab (&optab_table[OTI_ge])
+#define lt_optab (&optab_table[OTI_lt])
+#define le_optab (&optab_table[OTI_le])
+#define unord_optab (&optab_table[OTI_unord])
+
+#define strlen_optab (&optab_table[OTI_strlen])
+
+#define cbranch_optab (&optab_table[OTI_cbranch])
+#define cmov_optab (&optab_table[OTI_cmov])
+#define cstore_optab (&optab_table[OTI_cstore])
+#define ctrap_optab (&optab_table[OTI_ctrap])
+
+#define push_optab (&optab_table[OTI_push])
+#define addcc_optab (&optab_table[OTI_addcc])
+
+#define reduc_smax_optab (&optab_table[OTI_reduc_smax])
+#define reduc_umax_optab (&optab_table[OTI_reduc_umax])
+#define reduc_smin_optab (&optab_table[OTI_reduc_smin])
+#define reduc_umin_optab (&optab_table[OTI_reduc_umin])
+#define reduc_splus_optab (&optab_table[OTI_reduc_splus])
+#define reduc_uplus_optab (&optab_table[OTI_reduc_uplus])
+
+#define ssum_widen_optab (&optab_table[OTI_ssum_widen])
+#define usum_widen_optab (&optab_table[OTI_usum_widen])
+#define sdot_prod_optab (&optab_table[OTI_sdot_prod])
+#define udot_prod_optab (&optab_table[OTI_udot_prod])
+
+#define vec_set_optab (&optab_table[OTI_vec_set])
+#define vec_extract_optab (&optab_table[OTI_vec_extract])
+#define vec_init_optab (&optab_table[OTI_vec_init])
+#define vec_shl_optab (&optab_table[OTI_vec_shl])
+#define vec_shr_optab (&optab_table[OTI_vec_shr])
+#define vec_realign_load_optab (&optab_table[OTI_vec_realign_load])
+#define vec_widen_umult_hi_optab (&optab_table[OTI_vec_widen_umult_hi])
+#define vec_widen_umult_lo_optab (&optab_table[OTI_vec_widen_umult_lo])
+#define vec_widen_smult_hi_optab (&optab_table[OTI_vec_widen_smult_hi])
+#define vec_widen_smult_lo_optab (&optab_table[OTI_vec_widen_smult_lo])
+#define vec_widen_ushiftl_hi_optab (&optab_table[OTI_vec_widen_ushiftl_hi])
+#define vec_widen_ushiftl_lo_optab (&optab_table[OTI_vec_widen_ushiftl_lo])
+#define vec_widen_sshiftl_hi_optab (&optab_table[OTI_vec_widen_sshiftl_hi])
+#define vec_widen_sshiftl_lo_optab (&optab_table[OTI_vec_widen_sshiftl_lo])
+#define vec_unpacks_hi_optab (&optab_table[OTI_vec_unpacks_hi])
+#define vec_unpacks_lo_optab (&optab_table[OTI_vec_unpacks_lo])
+#define vec_unpacku_hi_optab (&optab_table[OTI_vec_unpacku_hi])
+#define vec_unpacku_lo_optab (&optab_table[OTI_vec_unpacku_lo])
+#define vec_unpacks_float_hi_optab (&optab_table[OTI_vec_unpacks_float_hi])
+#define vec_unpacks_float_lo_optab (&optab_table[OTI_vec_unpacks_float_lo])
+#define vec_unpacku_float_hi_optab (&optab_table[OTI_vec_unpacku_float_hi])
+#define vec_unpacku_float_lo_optab (&optab_table[OTI_vec_unpacku_float_lo])
+#define vec_pack_trunc_optab (&optab_table[OTI_vec_pack_trunc])
+#define vec_pack_ssat_optab (&optab_table[OTI_vec_pack_ssat])
+#define vec_pack_usat_optab (&optab_table[OTI_vec_pack_usat])
+#define vec_pack_sfix_trunc_optab (&optab_table[OTI_vec_pack_sfix_trunc])
+#define vec_pack_ufix_trunc_optab (&optab_table[OTI_vec_pack_ufix_trunc])
+
+#define powi_optab (&optab_table[OTI_powi])
+
+#define sync_compare_and_swap_optab \
+  (&optab_table[(int) OTI_sync_compare_and_swap])
+#define sync_lock_test_and_set_optab \
+  (&optab_table[(int) OTI_sync_lock_test_and_set])
+#define sync_old_add_optab (&optab_table[(int) OTI_sync_old_add])
+#define sync_old_sub_optab (&optab_table[(int) OTI_sync_old_sub])
+#define sync_old_ior_optab (&optab_table[(int) OTI_sync_old_ior])
+#define sync_old_and_optab (&optab_table[(int) OTI_sync_old_and])
+#define sync_old_xor_optab (&optab_table[(int) OTI_sync_old_xor])
+#define sync_old_nand_optab (&optab_table[(int) OTI_sync_old_nand])
+#define sync_new_add_optab (&optab_table[(int) OTI_sync_new_add])
+#define sync_new_sub_optab (&optab_table[(int) OTI_sync_new_sub])
+#define sync_new_ior_optab (&optab_table[(int) OTI_sync_new_ior])
+#define sync_new_and_optab (&optab_table[(int) OTI_sync_new_and])
+#define sync_new_xor_optab (&optab_table[(int) OTI_sync_new_xor])
+#define sync_new_nand_optab (&optab_table[(int) OTI_sync_new_nand])
 
 /* Conversion optabs have their own table and indexes.  */
 enum convert_optab_index
@@ -495,113 +622,233 @@ enum convert_optab_index
   COI_lfloor,
   COI_lceil,
 
+  COI_fract,
+  COI_fractuns,
+  COI_satfract,
+  COI_satfractuns,
+
+  COI_vec_load_lanes,
+  COI_vec_store_lanes,
+
+  /* Vector conditional operations.  */
+  COI_vcond,
+  COI_vcondu,
+
   COI_MAX
 };
 
-extern GTY(()) convert_optab 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])
-#define sfix_optab (convert_optab_table[COI_sfix])
-#define ufix_optab (convert_optab_table[COI_ufix])
-#define sfixtrunc_optab (convert_optab_table[COI_sfixtrunc])
-#define ufixtrunc_optab (convert_optab_table[COI_ufixtrunc])
-#define sfloat_optab (convert_optab_table[COI_sfloat])
-#define ufloat_optab (convert_optab_table[COI_ufloat])
-#define lrint_optab (convert_optab_table[COI_lrint])
-#define lround_optab (convert_optab_table[COI_lround])
-#define lfloor_optab (convert_optab_table[COI_lfloor])
-#define lceil_optab (convert_optab_table[COI_lceil])
-
-/* 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];
+#define sext_optab (&convert_optab_table[COI_sext])
+#define zext_optab (&convert_optab_table[COI_zext])
+#define trunc_optab (&convert_optab_table[COI_trunc])
+#define sfix_optab (&convert_optab_table[COI_sfix])
+#define ufix_optab (&convert_optab_table[COI_ufix])
+#define sfixtrunc_optab (&convert_optab_table[COI_sfixtrunc])
+#define ufixtrunc_optab (&convert_optab_table[COI_ufixtrunc])
+#define sfloat_optab (&convert_optab_table[COI_sfloat])
+#define ufloat_optab (&convert_optab_table[COI_ufloat])
+#define lrint_optab (&convert_optab_table[COI_lrint])
+#define lround_optab (&convert_optab_table[COI_lround])
+#define lfloor_optab (&convert_optab_table[COI_lfloor])
+#define lceil_optab (&convert_optab_table[COI_lceil])
+#define fract_optab (&convert_optab_table[COI_fract])
+#define fractuns_optab (&convert_optab_table[COI_fractuns])
+#define satfract_optab (&convert_optab_table[COI_satfract])
+#define satfractuns_optab (&convert_optab_table[COI_satfractuns])
+#define vec_load_lanes_optab (&convert_optab_table[COI_vec_load_lanes])
+#define vec_store_lanes_optab (&convert_optab_table[COI_vec_store_lanes])
+#define vcond_optab (&convert_optab_table[(int) COI_vcond])
+#define vcondu_optab (&convert_optab_table[(int) COI_vcondu])
 
 /* Contains the optab used for each rtx code.  */
-extern GTY(()) optab code_to_optab[NUM_RTX_CODE + 1];
+extern optab code_to_optab[NUM_RTX_CODE + 1];
 
 \f
 typedef rtx (*rtxfun) (rtx);
 
-/* Indexed by the rtx-code for a conditional (e.g. EQ, LT,...)
-   gives the gen_function to make a branch to test that condition.  */
-
-extern rtxfun bcc_gen_fctn[NUM_RTX_CODE];
+/* 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
+  /* Conditional move operations.  */
+  DOI_movcc,
+#endif
 
-/* Indexed by the rtx-code for a conditional (e.g. EQ, LT,...)
-   gives the insn code to make a store-condition insn
-   to test that condition.  */
+  /* Operations that use a scratch register to perform input and output
+     reloads of special objects.  */
+  DOI_reload_in,
+  DOI_reload_out,
+
+  /* Block move operation.  */
+  DOI_movmem,
+
+  /* Block set operation.  */
+  DOI_setmem,
+
+  /* Various types of block compare operation.  */
+  DOI_cmpstr,
+  DOI_cmpstrn,
+  DOI_cmpmem,
+
+  /* Atomic clear with release semantics.  */
+  DOI_sync_lock_release,
+
+  /* Atomic operation with no resulting value.  */
+  DOI_sync_add,
+  DOI_sync_sub,
+  DOI_sync_ior,
+  DOI_sync_and,
+  DOI_sync_xor,
+  DOI_sync_nand,
+
+  /* Atomic operations with memory model parameters. */
+  DOI_atomic_exchange,
+  DOI_atomic_compare_and_swap,
+  DOI_atomic_load,
+  DOI_atomic_store,
+  DOI_atomic_add_fetch,
+  DOI_atomic_sub_fetch,
+  DOI_atomic_and_fetch,
+  DOI_atomic_nand_fetch,
+  DOI_atomic_xor_fetch,
+  DOI_atomic_or_fetch,
+  DOI_atomic_fetch_add,
+  DOI_atomic_fetch_sub,
+  DOI_atomic_fetch_and,
+  DOI_atomic_fetch_nand,
+  DOI_atomic_fetch_xor,
+  DOI_atomic_fetch_or,
+  DOI_atomic_add,
+  DOI_atomic_sub,
+  DOI_atomic_and,
+  DOI_atomic_nand,
+  DOI_atomic_xor,
+  DOI_atomic_or,
+  DOI_atomic_always_lock_free,
+  DOI_atomic_is_lock_free,
+  DOI_atomic_thread_fence,
+  DOI_atomic_signal_fence,
+
+  /* Vector permutation.  */
+  DOI_vec_perm,
+  DOI_vec_perm_const,
+
+  DOI_MAX
+};
 
-extern enum insn_code setcc_gen_code[NUM_RTX_CODE];
+/* 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;
 
 #ifdef HAVE_conditional_move
-/* Indexed by the machine mode, gives the insn code to make a conditional
-   move insn.  */
-
-extern enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
+#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 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_lock_release_optab \
+  (&direct_optab_table[(int) DOI_sync_lock_release])
+#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 atomic_exchange_optab \
+  (&direct_optab_table[(int) DOI_atomic_exchange])
+#define atomic_compare_and_swap_optab \
+  (&direct_optab_table[(int) DOI_atomic_compare_and_swap])
+#define atomic_load_optab \
+  (&direct_optab_table[(int) DOI_atomic_load])
+#define atomic_store_optab \
+  (&direct_optab_table[(int) DOI_atomic_store])
+#define atomic_add_fetch_optab \
+  (&direct_optab_table[(int) DOI_atomic_add_fetch])
+#define atomic_sub_fetch_optab \
+  (&direct_optab_table[(int) DOI_atomic_sub_fetch])
+#define atomic_and_fetch_optab \
+  (&direct_optab_table[(int) DOI_atomic_and_fetch])
+#define atomic_nand_fetch_optab \
+  (&direct_optab_table[(int) DOI_atomic_nand_fetch])
+#define atomic_xor_fetch_optab \
+  (&direct_optab_table[(int) DOI_atomic_xor_fetch])
+#define atomic_or_fetch_optab \
+  (&direct_optab_table[(int) DOI_atomic_or_fetch])
+#define atomic_fetch_add_optab \
+  (&direct_optab_table[(int) DOI_atomic_fetch_add])
+#define atomic_fetch_sub_optab \
+  (&direct_optab_table[(int) DOI_atomic_fetch_sub])
+#define atomic_fetch_and_optab \
+  (&direct_optab_table[(int) DOI_atomic_fetch_and])
+#define atomic_fetch_nand_optab \
+  (&direct_optab_table[(int) DOI_atomic_fetch_nand])
+#define atomic_fetch_xor_optab \
+  (&direct_optab_table[(int) DOI_atomic_fetch_xor])
+#define atomic_fetch_or_optab \
+  (&direct_optab_table[(int) DOI_atomic_fetch_or])
+#define atomic_add_optab \
+  (&direct_optab_table[(int) DOI_atomic_add])
+#define atomic_sub_optab \
+  (&direct_optab_table[(int) DOI_atomic_sub])
+#define atomic_and_optab \
+  (&direct_optab_table[(int) DOI_atomic_and])
+#define atomic_nand_optab \
+  (&direct_optab_table[(int) DOI_atomic_nand])
+#define atomic_xor_optab \
+  (&direct_optab_table[(int) DOI_atomic_xor])
+#define atomic_or_optab \
+  (&direct_optab_table[(int) DOI_atomic_or])
+#define atomic_always_lock_free_optab \
+  (&direct_optab_table[(int) DOI_atomic_always_lock_free])
+#define atomic_is_lock_free_optab \
+  (&direct_optab_table[(int) DOI_atomic_is_lock_free])
+#define atomic_thread_fence_optab \
+  (&direct_optab_table[(int) DOI_atomic_thread_fence])
+#define atomic_signal_fence_optab \
+  (&direct_optab_table[(int) DOI_atomic_signal_fence])
+
+#define vec_perm_optab (&direct_optab_table[DOI_vec_perm])
+#define vec_perm_const_optab (&direct_optab_table[(int) DOI_vec_perm_const])
+\f
+/* 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];
-extern enum insn_code sync_compare_and_swap_cc[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)
+\f
 /* Define functions given in optabs.c.  */
 
-extern rtx expand_widen_pattern_expr (tree exp, rtx op0, rtx op1, rtx wide_op,
+extern rtx expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op,
                                       rtx target, int unsignedp);
 
 extern rtx expand_ternary_op (enum machine_mode mode, optab ternary_optab,
@@ -612,6 +859,10 @@ extern rtx expand_ternary_op (enum machine_mode mode, optab ternary_optab,
 extern rtx expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
                         enum optab_methods);
 
+extern rtx simplify_expand_binop (enum machine_mode mode, optab binoptab,
+                                 rtx op0, rtx op1, rtx target, int unsignedp,
+                                 enum optab_methods methods);
+
 extern bool force_expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
                                enum optab_methods);
 
@@ -637,24 +888,40 @@ extern rtx expand_unop (enum machine_mode, optab, rtx, rtx, int);
 extern rtx expand_abs_nojump (enum machine_mode, rtx, rtx, int);
 extern rtx expand_abs (enum machine_mode, rtx, rtx, int, int);
 
+/* Expand the one's complement absolute value operation.  */
+extern rtx expand_one_cmpl_abs_nojump (enum machine_mode, rtx, rtx);
+
 /* Expand the copysign operation.  */
 extern rtx expand_copysign (rtx, rtx, rtx);
 
 /* Generate an instruction with a given INSN_CODE with an output and
    an input.  */
-extern void emit_unop_insn (int, rtx, rtx, enum rtx_code);
-
-/* Excapsulate the block in REG_LIBCALL, and REG_RETVAL reg notes and add 
-   REG_LIBCALL_ID notes to all insns in block.  */
-extern void maybe_encapsulate_block (rtx, rtx, rtx);
-
-/* Emit code to perform a series of operations on a multi-word quantity, one
-   word at a time.  */
-extern rtx emit_no_conflict_block (rtx, rtx, rtx, rtx, rtx);
+extern void emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
+extern bool maybe_emit_unop_insn (enum insn_code, rtx, rtx, enum rtx_code);
+
+/* Find a widening optab even if it doesn't widen as much as we want.  */
+#define find_widening_optab_handler(A,B,C,D) \
+  find_widening_optab_handler_and_mode (A, B, C, D, NULL)
+extern enum insn_code find_widening_optab_handler_and_mode (optab,
+                                                           enum machine_mode,
+                                                           enum machine_mode,
+                                                           int,
+                                                           enum machine_mode *);
+
+/* An extra flag to control optab_for_tree_code's behavior.  This is needed to
+   distinguish between machines with a vector shift that takes a scalar for the
+   shift amount vs. machines that take a vector for the shift amount.  */
+enum optab_subtype
+{
+  optab_default,
+  optab_scalar,
+  optab_vector
+};
 
-/* Emit one rtl insn to compare two rtx's.  */
-extern void emit_cmp_insn (rtx, rtx, enum rtx_code, rtx, enum machine_mode,
-                          int);
+/* Return the optab used for computing the given operation on the type given by
+   the second argument.  The third argument distinguishes between the types of
+   vector shifts and rotates */
+extern optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype);
 
 /* The various uses that a comparison can have; used by can_compare_p:
    jumps, conditional moves, store flag operations.  */
@@ -665,10 +932,6 @@ enum can_compare_purpose
   ccp_store_flag
 };
 
-/* Return the optab used for computing the given operation on the type
-   given by the second argument.  */
-extern optab optab_for_tree_code (enum tree_code, const_tree);
-
 /* Nonzero if a compare of mode MODE can be done straightforwardly
    (without splitting it into pieces).  */
 extern int can_compare_p (enum rtx_code, enum machine_mode,
@@ -687,26 +950,310 @@ extern void set_optab_libfunc (optab, enum machine_mode, const char *);
 extern void set_conv_libfunc (convert_optab, enum machine_mode,
                              enum machine_mode, const char *);
 
+/* Call this to install all of the __sync libcalls up to size MAX.  */
+extern void init_sync_libfuncs (int max);
+
+/* Generate code for a FIXED_CONVERT_EXPR.  */
+extern void expand_fixed_convert (rtx, rtx, int, int);
+
 /* Generate code for a FLOAT_EXPR.  */
 extern void expand_float (rtx, rtx, int);
 
+/* Return the insn_code for a FLOAT_EXPR.  */
+enum insn_code can_float_p (enum machine_mode, enum machine_mode, int);
+
+/* Return true if there is an inline compare and swap pattern.  */
+extern bool can_compare_and_swap_p (enum machine_mode, bool);
+
+/* Return true if there is an inline atomic exchange pattern.  */
+extern bool can_atomic_exchange_p (enum machine_mode, bool);
+
+/* Generate code for a compare and swap.  */
+extern bool expand_atomic_compare_and_swap (rtx *, rtx *, rtx, rtx, rtx, bool,
+                                           enum memmodel, enum memmodel);
+
+/* Generate memory barriers.  */
+extern void expand_mem_thread_fence (enum memmodel);
+extern void expand_mem_signal_fence (enum memmodel);
+
+/* Check whether an operation represented by the code CODE is a
+   convert operation that is supported by the target platform in
+   vector form */
+bool supportable_convert_operation (enum tree_code, tree, tree, tree *, 
+                                    enum tree_code *);
+
 /* Generate code for a FIX_EXPR.  */
 extern void expand_fix (rtx, rtx, int);
 
 /* Generate code for float to integral conversion.  */
 extern bool expand_sfix_optab (rtx, rtx, convert_optab);
 
+/* Generate code for a widening multiply.  */
+extern rtx expand_widening_mult (enum machine_mode, rtx, rtx, rtx, int, optab);
+
 /* Return tree if target supports vector operations for COND_EXPR.  */
-bool expand_vec_cond_expr_p (tree, enum machine_mode);
+bool expand_vec_cond_expr_p (tree, tree);
 
 /* Generate code for VEC_COND_EXPR.  */
-extern rtx expand_vec_cond_expr (tree, rtx);
-
+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 (tree, rtx);
+extern rtx expand_vec_shift_expr (sepops, rtx);
+
+/* Return tree if target supports vector operations for VEC_PERM_EXPR.  */
+extern bool can_vec_perm_p (enum machine_mode, bool, const unsigned char *);
+
+/* Generate code for VEC_PERM_EXPR.  */
+extern rtx expand_vec_perm (enum machine_mode, rtx, rtx, rtx, rtx);
+
+/* 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);
+}
 
-#define optab_handler(optab,mode) (&(optab)->handlers[(int) (mode)])
-#define convert_optab_handler(optab,mode,mode2) \
-       (&(optab)->handlers[(int) (mode)][(int) (mode2)])
+/* Like optab_handler, but for widening_operations that have a TO_MODE and
+  a FROM_MODE.  */
+
+static inline enum insn_code
+widening_optab_handler (optab op, enum machine_mode to_mode,
+                       enum machine_mode from_mode)
+{
+  if (to_mode == from_mode || from_mode == VOIDmode)
+    return optab_handler (op, to_mode);
+
+  if (op->widening)
+    return (enum insn_code) (op->widening->handlers[(int) to_mode][(int) from_mode].insn_code
+                            + (int) CODE_FOR_nothing);
+
+  return 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;
+}
+
+/* Like set_optab_handler, but for widening operations that have a TO_MODE
+   and a FROM_MODE.  */
+
+static inline void
+set_widening_optab_handler (optab op, enum machine_mode to_mode,
+                           enum machine_mode from_mode, enum insn_code code)
+{
+  if (to_mode == from_mode)
+    set_optab_handler (op, to_mode, code);
+  else
+    {
+      if (op->widening == NULL)
+       op->widening = (struct widening_optab_handlers *)
+             xcalloc (1, sizeof (struct widening_optab_handlers));
+
+      op->widening->handlers[(int) to_mode][(int) from_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,
+                                 enum machine_mode mode2);
+
+extern bool insn_operand_matches (enum insn_code icode, unsigned int opno,
+                                 rtx operand);
+
+/* Describes the type of an expand_operand.  Each value is associated
+   with a create_*_operand function; see the comments above those
+   functions for details.  */
+enum expand_operand_type {
+  EXPAND_FIXED,
+  EXPAND_OUTPUT,
+  EXPAND_INPUT,
+  EXPAND_CONVERT_TO,
+  EXPAND_CONVERT_FROM,
+  EXPAND_ADDRESS,
+  EXPAND_INTEGER
+};
+
+/* Information about an operand for instruction expansion.  */
+struct expand_operand {
+  /* The type of operand.  */
+  ENUM_BITFIELD (expand_operand_type) type : 8;
+
+  /* True if any conversion should treat VALUE as being unsigned
+     rather than signed.  Only meaningful for certain types.  */
+  unsigned int unsigned_p : 1;
+
+  /* Unused; available for future use.  */
+  unsigned int unused : 7;
+
+  /* The mode passed to the convert_*_operand function.  It has a
+     type-dependent meaning.  */
+  ENUM_BITFIELD (machine_mode) mode : 16;
+
+  /* The value of the operand.  */
+  rtx value;
+};
+
+/* Initialize OP with the given fields.  Initialise the other fields
+   to their default values.  */
+
+static inline void
+create_expand_operand (struct expand_operand *op,
+                      enum expand_operand_type type,
+                      rtx value, enum machine_mode mode,
+                      bool unsigned_p)
+{
+  op->type = type;
+  op->unsigned_p = unsigned_p;
+  op->unused = 0;
+  op->mode = mode;
+  op->value = value;
+}
+
+/* Make OP describe an operand that must use rtx X, even if X is volatile.  */
+
+static inline void
+create_fixed_operand (struct expand_operand *op, rtx x)
+{
+  create_expand_operand (op, EXPAND_FIXED, x, VOIDmode, false);
+}
+
+/* Make OP describe an output operand that must have mode MODE.
+   X, if nonnull, is a suggestion for where the output should be stored.
+   It is OK for VALUE to be inconsistent with MODE, although it will just
+   be ignored in that case.  */
+
+static inline void
+create_output_operand (struct expand_operand *op, rtx x,
+                      enum machine_mode mode)
+{
+  create_expand_operand (op, EXPAND_OUTPUT, x, mode, false);
+}
+
+/* Make OP describe an input operand that must have mode MODE and
+   value VALUE; MODE cannot be VOIDmode.  The backend may request that
+   VALUE be copied into a different kind of rtx before being passed
+   as an operand.  */
+
+static inline void
+create_input_operand (struct expand_operand *op, rtx value,
+                     enum machine_mode mode)
+{
+  create_expand_operand (op, EXPAND_INPUT, value, mode, false);
+}
+
+/* Like create_input_operand, except that VALUE must first be converted
+   to mode MODE.  UNSIGNED_P says whether VALUE is unsigned.  */
+
+static inline void
+create_convert_operand_to (struct expand_operand *op, rtx value,
+                          enum machine_mode mode, bool unsigned_p)
+{
+  create_expand_operand (op, EXPAND_CONVERT_TO, value, mode, unsigned_p);
+}
+
+/* Make OP describe an input operand that should have the same value
+   as VALUE, after any mode conversion that the backend might request.
+   If VALUE is a CONST_INT, it should be treated as having mode MODE.
+   UNSIGNED_P says whether VALUE is unsigned.  */
+
+static inline void
+create_convert_operand_from (struct expand_operand *op, rtx value,
+                            enum machine_mode mode, bool unsigned_p)
+{
+  create_expand_operand (op, EXPAND_CONVERT_FROM, value, mode, unsigned_p);
+}
+
+extern void create_convert_operand_from_type (struct expand_operand *op,
+                                             rtx value, tree type);
+
+/* Make OP describe an input Pmode address operand.  VALUE is the value
+   of the address, but it may need to be converted to Pmode first.  */
+
+static inline void
+create_address_operand (struct expand_operand *op, rtx value)
+{
+  create_expand_operand (op, EXPAND_ADDRESS, value, Pmode, false);
+}
+
+/* Make OP describe an input operand that has value INTVAL and that has
+   no inherent mode.  This function should only be used for operands that
+   are always expand-time constants.  The backend may request that INTVAL
+   be copied into a different kind of rtx, but it must specify the mode
+   of that rtx if so.  */
+
+static inline void
+create_integer_operand (struct expand_operand *op, HOST_WIDE_INT intval)
+{
+  create_expand_operand (op, EXPAND_INTEGER, GEN_INT (intval), VOIDmode, false);
+}
+
+extern bool valid_multiword_target_p (rtx);
+
+extern bool maybe_legitimize_operands (enum insn_code icode,
+                                      unsigned int opno, unsigned int nops,
+                                      struct expand_operand *ops);
+extern rtx maybe_gen_insn (enum insn_code icode, unsigned int nops,
+                          struct expand_operand *ops);
+extern bool maybe_expand_insn (enum insn_code icode, unsigned int nops,
+                              struct expand_operand *ops);
+extern bool maybe_expand_jump_insn (enum insn_code icode, unsigned int nops,
+                                   struct expand_operand *ops);
+extern void expand_insn (enum insn_code icode, unsigned int nops,
+                        struct expand_operand *ops);
+extern void expand_jump_insn (enum insn_code icode, unsigned int nops,
+                             struct expand_operand *ops);
+
+extern rtx prepare_operand (enum insn_code, rtx, int, enum machine_mode,
+                           enum machine_mode, int);
 
 #endif /* GCC_OPTABS_H */