aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-09-17 14:28:59 +0000
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>2015-09-17 14:28:59 +0000
commit947ed59a55265a3cfc28416744feab6d0b614269 (patch)
treeb4c04d6027cb1108af25cc0d42827303e661abb5 /gcc/optabs.c
parente429e3bd7a4ee90fd247e078d29aee17ad3b15c2 (diff)
Split up optabs.[hc]
optabs.[hc] is a bit of a behemoth. It includes basic functions for querying what a target can do, related tree- and gimple-level query functions, related rtl-level query functions, and the functions that actually generate code. Some gimple optimisations therefore need: #include "insn-config.h" #include "expmed.h" #include "dojump.h" #include "explow.h" #include "emit-rtl.h" #include "varasm.h" #include "stmt.h" #include "expr.h" purely to query whether the target has support for a particular operation. This patch splits optabs up as follows: - optabs-query.[hc]: IL-independent functions for querying what a target can do natively. - optabs-tree.[hc]: tree and gimple query functions (an extension of optabs-query.[hc]). - optabs-libfuncs.[hc]: optabs-specific libfuncs (an extension of libfuncs.h) - optabs.h: For now includes optabs-query.h and optabs-libfuncs.h. Only two files outside optabs need to include both optabs.h and optabs-tree.h: expr.c and function.c. I think that's expected given that both are related to expand. It might be good to split optabs.h further, but this is already quite a big patch. I changed can_conditionally_move_p from returning an int to returning a bool and fixed a few formatting glitches. There should be no other changes to the functions themselves. gcc/ * Makefile.in (OBJS): Add optabs-libfuncs.o, optabs-query.o and optabs-tree.o. (GTFILES): Replace optabs.c with optabs-libfunc.c. * genopinit.c (main): Add an include guard to insn-opinit.h. Protect the rtx_code parts with NUM_RTX_CODE. * optabs.h: Split parts out to... * optabs-libfuncs.h, optabs-query.h, optabs-tree.h: ...these new files. * optabs.c: Split parts out to... * optabs-libfuncs.c, optabs-query.c, optabs-tree.c: ...these new files. * cilk-common.c: Include optabs-query.h rather than optabs.h. * fold-const.c: Likewise. * target-globals.c: Likewise. * tree-if-conv.c: Likewise. * tree-ssa-forwprop.c: Likewise. * tree-ssa-loop-prefetch.c: Likewise. * tree-ssa-math-opts.c: Include optabs-tree.h rather than optabs.h. Remove unncessary include files. * tree-ssa-phiopt.c: Likewise. * tree-ssa-reassoc.c: Likewise. * tree-switch-conversion.c: Likewise. * tree-vect-data-refs.c: Likewise. * tree-vect-generic.c: Likewise. * tree-vect-loop.c: Likewise. * tree-vect-patterns.c: Likewise. * tree-vect-slp.c: Likewise. * tree-vect-stmts.c: Likewise. * tree-vrp.c: Likewise. * toplev.c: Include optabs-query.h and optabs-libfuncs.h rather than optabs.h. * expr.c: Include optabs-tree.h. * function.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@227865 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c1846
1 files changed, 2 insertions, 1844 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index c2a9b1ce9ef..c49d66b5a0e 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -33,8 +33,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "tree-hasher.h"
#include "stor-layout.h"
-#include "stringpool.h"
-#include "varasm.h"
#include "tm_p.h"
#include "flags.h"
#include "except.h"
@@ -47,22 +45,12 @@ along with GCC; see the file COPYING3. If not see
#include "expr.h"
#include "insn-codes.h"
#include "optabs.h"
+#include "optabs-tree.h"
#include "libfuncs.h"
#include "recog.h"
#include "reload.h"
#include "target.h"
-struct target_optabs default_target_optabs;
-struct target_libfuncs default_target_libfuncs;
-struct target_optabs *this_fn_optabs = &default_target_optabs;
-#if SWITCHABLE_TARGET
-struct target_optabs *this_target_optabs = &default_target_optabs;
-struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs;
-#endif
-
-#define libfunc_hash \
- (this_target_libfuncs->x_libfunc_hash)
-
static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *,
machine_mode *);
static rtx expand_unop_direct (machine_mode, optab, rtx, rtx, int);
@@ -70,101 +58,6 @@ static void emit_libcall_block_1 (rtx_insn *, rtx, rtx, rtx, bool);
/* Debug facility for use in GDB. */
void debug_optab_libfuncs (void);
-
-/* Prefixes for the current version of decimal floating point (BID vs. DPD) */
-#if ENABLE_DECIMAL_BID_FORMAT
-#define DECIMAL_PREFIX "bid_"
-#else
-#define DECIMAL_PREFIX "dpd_"
-#endif
-
-/* Used for libfunc_hash. */
-
-hashval_t
-libfunc_hasher::hash (libfunc_entry *e)
-{
- return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op);
-}
-
-/* Used for libfunc_hash. */
-
-bool
-libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2)
-{
- return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2;
-}
-
-/* Return libfunc corresponding operation defined by OPTAB converting
- from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL
- if no libfunc is available. */
-rtx
-convert_optab_libfunc (convert_optab optab, machine_mode mode1,
- machine_mode mode2)
-{
- struct libfunc_entry e;
- struct libfunc_entry **slot;
-
- /* ??? This ought to be an assert, but not all of the places
- that we expand optabs know about the optabs that got moved
- to being direct. */
- if (!(optab >= FIRST_CONV_OPTAB && optab <= LAST_CONVLIB_OPTAB))
- return NULL_RTX;
-
- e.op = optab;
- e.mode1 = mode1;
- e.mode2 = mode2;
- slot = libfunc_hash->find_slot (&e, NO_INSERT);
- if (!slot)
- {
- const struct convert_optab_libcall_d *d
- = &convlib_def[optab - FIRST_CONV_OPTAB];
-
- if (d->libcall_gen == NULL)
- return NULL;
-
- d->libcall_gen (optab, d->libcall_basename, mode1, mode2);
- slot = libfunc_hash->find_slot (&e, NO_INSERT);
- if (!slot)
- return NULL;
- }
- return (*slot)->libfunc;
-}
-
-/* Return libfunc corresponding operation defined by OPTAB in MODE.
- Trigger lazy initialization if needed, return NULL if no libfunc is
- available. */
-rtx
-optab_libfunc (optab optab, machine_mode mode)
-{
- struct libfunc_entry e;
- struct libfunc_entry **slot;
-
- /* ??? This ought to be an assert, but not all of the places
- that we expand optabs know about the optabs that got moved
- to being direct. */
- if (!(optab >= FIRST_NORM_OPTAB && optab <= LAST_NORMLIB_OPTAB))
- return NULL_RTX;
-
- e.op = optab;
- e.mode1 = mode;
- e.mode2 = VOIDmode;
- slot = libfunc_hash->find_slot (&e, NO_INSERT);
- if (!slot)
- {
- const struct optab_libcall_d *d
- = &normlib_def[optab - FIRST_NORM_OPTAB];
-
- if (d->libcall_gen == NULL)
- return NULL;
-
- d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode);
- slot = libfunc_hash->find_slot (&e, NO_INSERT);
- if (!slot)
- return NULL;
- }
- return (*slot)->libfunc;
-}
-
/* Add a REG_EQUAL note to the last insn in INSNS. TARGET is being set to
the result of operation CODE applied to OP0 (and OP1 if it is a binary
@@ -298,56 +191,6 @@ widened_mode (machine_mode to_mode, rtx op0, rtx op1)
return result;
}
-/* Like optab_handler, but for widening_operations that have a
- TO_MODE and a FROM_MODE. */
-
-enum insn_code
-widening_optab_handler (optab op, machine_mode to_mode,
- machine_mode from_mode)
-{
- unsigned scode = (op << 16) | to_mode;
- if (to_mode != from_mode && from_mode != VOIDmode)
- {
- /* ??? Why does find_widening_optab_handler_and_mode attempt to
- widen things that can't be widened? E.g. add_optab... */
- if (op > LAST_CONV_OPTAB)
- return CODE_FOR_nothing;
- scode |= from_mode << 8;
- }
- return raw_optab_handler (scode);
-}
-
-/* Find a widening optab even if it doesn't widen as much as we want.
- E.g. if from_mode is HImode, and to_mode is DImode, and there is no
- direct HI->SI insn, then return SI->DI, if that exists.
- If PERMIT_NON_WIDENING is non-zero then this can be used with
- non-widening optabs also. */
-
-enum insn_code
-find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
- machine_mode from_mode,
- int permit_non_widening,
- machine_mode *found_mode)
-{
- for (; (permit_non_widening || from_mode != to_mode)
- && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
- && from_mode != VOIDmode;
- from_mode = GET_MODE_WIDER_MODE (from_mode))
- {
- enum insn_code handler = widening_optab_handler (op, to_mode,
- from_mode);
-
- if (handler != CODE_FOR_nothing)
- {
- if (found_mode)
- *found_mode = from_mode;
- return handler;
- }
- }
-
- return CODE_FOR_nothing;
-}
-
/* Widen OP to MODE and return the rtx for the widened operand. UNSIGNEDP
says whether OP is signed or unsigned. NO_EXTEND is nonzero if we need
not actually do a sign-extend or zero-extend, but can leave the
@@ -386,245 +229,6 @@ widen_operand (rtx op, machine_mode mode, machine_mode oldmode,
return result;
}
-/* Return the optab used for computing the operation given by the tree code,
- CODE and the tree EXP. This function is not always usable (for example, it
- cannot give complete results for multiplication or division) but probably
- ought to be relied on more widely throughout the expander. */
-optab
-optab_for_tree_code (enum tree_code code, const_tree type,
- enum optab_subtype subtype)
-{
- bool trapv;
- switch (code)
- {
- case BIT_AND_EXPR:
- return and_optab;
-
- case BIT_IOR_EXPR:
- return ior_optab;
-
- case BIT_NOT_EXPR:
- return one_cmpl_optab;
-
- case BIT_XOR_EXPR:
- return xor_optab;
-
- case MULT_HIGHPART_EXPR:
- return TYPE_UNSIGNED (type) ? umul_highpart_optab : smul_highpart_optab;
-
- case TRUNC_MOD_EXPR:
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
-
- case RDIV_EXPR:
- case TRUNC_DIV_EXPR:
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- case EXACT_DIV_EXPR:
- if (TYPE_SATURATING (type))
- return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab;
- return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
-
- case LSHIFT_EXPR:
- if (TREE_CODE (type) == VECTOR_TYPE)
- {
- if (subtype == optab_vector)
- return TYPE_SATURATING (type) ? unknown_optab : vashl_optab;
-
- gcc_assert (subtype == optab_scalar);
- }
- if (TYPE_SATURATING (type))
- return TYPE_UNSIGNED (type) ? usashl_optab : ssashl_optab;
- return ashl_optab;
-
- case RSHIFT_EXPR:
- if (TREE_CODE (type) == VECTOR_TYPE)
- {
- if (subtype == optab_vector)
- return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
-
- gcc_assert (subtype == optab_scalar);
- }
- return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
-
- case LROTATE_EXPR:
- if (TREE_CODE (type) == VECTOR_TYPE)
- {
- if (subtype == optab_vector)
- return vrotl_optab;
-
- gcc_assert (subtype == optab_scalar);
- }
- return rotl_optab;
-
- case RROTATE_EXPR:
- if (TREE_CODE (type) == VECTOR_TYPE)
- {
- if (subtype == optab_vector)
- return vrotr_optab;
-
- gcc_assert (subtype == optab_scalar);
- }
- return rotr_optab;
-
- case MAX_EXPR:
- return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
-
- case MIN_EXPR:
- return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
-
- case REALIGN_LOAD_EXPR:
- return vec_realign_load_optab;
-
- case WIDEN_SUM_EXPR:
- return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
-
- case DOT_PROD_EXPR:
- return TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab;
-
- case SAD_EXPR:
- return TYPE_UNSIGNED (type) ? usad_optab : ssad_optab;
-
- case WIDEN_MULT_PLUS_EXPR:
- return (TYPE_UNSIGNED (type)
- ? (TYPE_SATURATING (type)
- ? usmadd_widen_optab : umadd_widen_optab)
- : (TYPE_SATURATING (type)
- ? ssmadd_widen_optab : smadd_widen_optab));
-
- case WIDEN_MULT_MINUS_EXPR:
- return (TYPE_UNSIGNED (type)
- ? (TYPE_SATURATING (type)
- ? usmsub_widen_optab : umsub_widen_optab)
- : (TYPE_SATURATING (type)
- ? ssmsub_widen_optab : smsub_widen_optab));
-
- case FMA_EXPR:
- return fma_optab;
-
- case REDUC_MAX_EXPR:
- return TYPE_UNSIGNED (type)
- ? reduc_umax_scal_optab : reduc_smax_scal_optab;
-
- case REDUC_MIN_EXPR:
- return TYPE_UNSIGNED (type)
- ? reduc_umin_scal_optab : reduc_smin_scal_optab;
-
- case REDUC_PLUS_EXPR:
- return reduc_plus_scal_optab;
-
- case VEC_WIDEN_MULT_HI_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
-
- case VEC_WIDEN_MULT_LO_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
-
- case VEC_WIDEN_MULT_EVEN_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_widen_umult_even_optab : vec_widen_smult_even_optab;
-
- case VEC_WIDEN_MULT_ODD_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
-
- case VEC_WIDEN_LSHIFT_HI_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab;
-
- case VEC_WIDEN_LSHIFT_LO_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab;
-
- case VEC_UNPACK_HI_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_unpacku_hi_optab : vec_unpacks_hi_optab;
-
- case VEC_UNPACK_LO_EXPR:
- return TYPE_UNSIGNED (type) ?
- vec_unpacku_lo_optab : vec_unpacks_lo_optab;
-
- case VEC_UNPACK_FLOAT_HI_EXPR:
- /* The signedness is determined from input operand. */
- return TYPE_UNSIGNED (type) ?
- vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab;
-
- case VEC_UNPACK_FLOAT_LO_EXPR:
- /* The signedness is determined from input operand. */
- return TYPE_UNSIGNED (type) ?
- vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab;
-
- case VEC_PACK_TRUNC_EXPR:
- return vec_pack_trunc_optab;
-
- case VEC_PACK_SAT_EXPR:
- return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
-
- case VEC_PACK_FIX_TRUNC_EXPR:
- /* The signedness is determined from output operand. */
- return TYPE_UNSIGNED (type) ?
- vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab;
-
- default:
- break;
- }
-
- trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
- switch (code)
- {
- case POINTER_PLUS_EXPR:
- case PLUS_EXPR:
- if (TYPE_SATURATING (type))
- return TYPE_UNSIGNED (type) ? usadd_optab : ssadd_optab;
- return trapv ? addv_optab : add_optab;
-
- case MINUS_EXPR:
- if (TYPE_SATURATING (type))
- return TYPE_UNSIGNED (type) ? ussub_optab : sssub_optab;
- return trapv ? subv_optab : sub_optab;
-
- case MULT_EXPR:
- if (TYPE_SATURATING (type))
- return TYPE_UNSIGNED (type) ? usmul_optab : ssmul_optab;
- return trapv ? smulv_optab : smul_optab;
-
- case NEGATE_EXPR:
- if (TYPE_SATURATING (type))
- return TYPE_UNSIGNED (type) ? usneg_optab : ssneg_optab;
- return trapv ? negv_optab : neg_optab;
-
- case ABS_EXPR:
- return trapv ? absv_optab : abs_optab;
-
- default:
- return unknown_optab;
- }
-}
-
-/* Given optab UNOPTAB that reduces a vector to a scalar, find instead the old
- optab that produces a vector with the reduction result in one element,
- for a tree with type TYPE. */
-
-optab
-scalar_reduc_to_vector (optab unoptab, const_tree type)
-{
- switch (unoptab)
- {
- case reduc_plus_scal_optab:
- return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab;
-
- case reduc_smin_scal_optab: return reduc_smin_optab;
- case reduc_umin_scal_optab: return reduc_umin_optab;
- case reduc_smax_scal_optab: return reduc_smax_optab;
- case reduc_umax_scal_optab: return reduc_umax_optab;
- default: return unknown_optab;
- }
-}
-
/* Expand vector widening operations.
There are two different classes of operations handled here:
@@ -4606,23 +4210,6 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1,
return NULL_RTX;
}
-/* Return nonzero if a conditional move of mode MODE is supported.
-
- This function is for combine so it can tell whether an insn that looks
- like a conditional move is actually supported by the hardware. If we
- guess wrong we lose a bit on optimization, but that's it. */
-/* ??? sparc64 supports conditionally moving integers values based on fp
- comparisons, and vice versa. How do we handle them? */
-
-int
-can_conditionally_move_p (machine_mode mode)
-{
- if (direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing)
- return 1;
-
- return 0;
-}
-
/* Emit a conditional addition instruction if the machine supports one for that
condition and machine mode.
@@ -4853,22 +4440,6 @@ have_sub2_insn (rtx x, rtx y)
return 1;
}
-/* Return the insn code used to extend FROM_MODE to TO_MODE.
- UNSIGNEDP specifies zero-extension instead of sign-extension. If
- no such operation exists, CODE_FOR_nothing will be returned. */
-
-enum insn_code
-can_extend_p (machine_mode to_mode, machine_mode from_mode,
- int unsignedp)
-{
- convert_optab tab;
- if (unsignedp < 0 && targetm.have_ptr_extend ())
- return targetm.code_for_ptr_extend;
-
- tab = unsignedp ? zext_optab : sext_optab;
- return convert_optab_handler (tab, to_mode, from_mode);
-}
-
/* Generate the body of an insn to extend Y (with mode MFROM)
into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
@@ -4880,110 +4451,6 @@ gen_extend_insn (rtx x, rtx y, machine_mode mto,
return GEN_FCN (icode) (x, y);
}
-/* can_fix_p and can_float_p say whether the target machine
- can directly convert a given fixed point type to
- a given floating point type, or vice versa.
- The returned value is the CODE_FOR_... value to use,
- or CODE_FOR_nothing if these modes cannot be directly converted.
-
- *TRUNCP_PTR is set to 1 if it is necessary to output
- an explicit FTRUNC insn before the fix insn; otherwise 0. */
-
-static enum insn_code
-can_fix_p (machine_mode fixmode, machine_mode fltmode,
- int unsignedp, int *truncp_ptr)
-{
- convert_optab tab;
- enum insn_code icode;
-
- tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
- icode = convert_optab_handler (tab, fixmode, fltmode);
- if (icode != CODE_FOR_nothing)
- {
- *truncp_ptr = 0;
- return icode;
- }
-
- /* FIXME: This requires a port to define both FIX and FTRUNC pattern
- for this to work. We need to rework the fix* and ftrunc* patterns
- and documentation. */
- tab = unsignedp ? ufix_optab : sfix_optab;
- icode = convert_optab_handler (tab, fixmode, fltmode);
- if (icode != CODE_FOR_nothing
- && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
- {
- *truncp_ptr = 1;
- return icode;
- }
-
- *truncp_ptr = 0;
- return CODE_FOR_nothing;
-}
-
-enum insn_code
-can_float_p (machine_mode fltmode, machine_mode fixmode,
- int unsignedp)
-{
- convert_optab tab;
-
- tab = unsignedp ? ufloat_optab : sfloat_optab;
- return convert_optab_handler (tab, fltmode, fixmode);
-}
-
-/* Function supportable_convert_operation
-
- Check whether an operation represented by the code CODE is a
- convert operation that is supported by the target platform in
- vector form (i.e., when operating on arguments of type VECTYPE_IN
- producing a result of type VECTYPE_OUT).
-
- Convert operations we currently support directly are FIX_TRUNC and FLOAT.
- This function checks if these operations are supported
- by the target platform either directly (via vector tree-codes), or via
- target builtins.
-
- Output:
- - CODE1 is code of vector operation to be used when
- vectorizing the operation, if available.
- - DECL is decl of target builtin functions to be used
- when vectorizing the operation, if available. In this case,
- CODE1 is CALL_EXPR. */
-
-bool
-supportable_convert_operation (enum tree_code code,
- tree vectype_out, tree vectype_in,
- tree *decl, enum tree_code *code1)
-{
- machine_mode m1,m2;
- int truncp;
-
- m1 = TYPE_MODE (vectype_out);
- m2 = TYPE_MODE (vectype_in);
-
- /* First check if we can done conversion directly. */
- if ((code == FIX_TRUNC_EXPR
- && can_fix_p (m1,m2,TYPE_UNSIGNED (vectype_out), &truncp)
- != CODE_FOR_nothing)
- || (code == FLOAT_EXPR
- && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
- != CODE_FOR_nothing))
- {
- *code1 = code;
- return true;
- }
-
- /* Now check for builtin. */
- if (targetm.vectorize.builtin_conversion
- && targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
- {
- *code1 = CALL_EXPR;
- *decl = targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in);
- return true;
- }
- return false;
-}
-
-
/* Generate code to convert FROM to floating point
and store in TO. FROM must be fixed point and not VOIDmode.
UNSIGNEDP nonzero means regard FROM as unsigned.
@@ -5197,7 +4664,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
enum insn_code icode;
rtx target = to;
machine_mode fmode, imode;
- int must_trunc = 0;
+ bool must_trunc = false;
/* We first try to find a pair of modes, one real and one integer, at
least as wide as FROM and TO, respectively, in which we can open-code
@@ -5478,871 +4945,6 @@ have_insn_for (enum rtx_code code, machine_mode mode)
!= CODE_FOR_nothing));
}
-/* Initialize the libfunc fields of an entire group of entries in some
- optab. Each entry is set equal to a string consisting of a leading
- pair of underscores followed by a generic operation name followed by
- a mode name (downshifted to lowercase) followed by a single character
- representing the number of operands for the given operation (which is
- usually one of the characters '2', '3', or '4').
-
- OPTABLE is the table in which libfunc fields are to be initialized.
- OPNAME is the generic (string) name of the operation.
- SUFFIX is the character which specifies the number of operands for
- the given generic operation.
- MODE is the mode to generate for.
-*/
-
-static void
-gen_libfunc (optab optable, const char *opname, int suffix,
- machine_mode mode)
-{
- unsigned opname_len = strlen (opname);
- const char *mname = GET_MODE_NAME (mode);
- unsigned mname_len = strlen (mname);
- int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
- int len = prefix_len + opname_len + mname_len + 1 + 1;
- char *libfunc_name = XALLOCAVEC (char, len);
- char *p;
- const char *q;
-
- p = libfunc_name;
- *p++ = '_';
- *p++ = '_';
- if (targetm.libfunc_gnu_prefix)
- {
- *p++ = 'g';
- *p++ = 'n';
- *p++ = 'u';
- *p++ = '_';
- }
- for (q = opname; *q; )
- *p++ = *q++;
- for (q = mname; *q; q++)
- *p++ = TOLOWER (*q);
- *p++ = suffix;
- *p = '\0';
-
- set_optab_libfunc (optable, mode,
- ggc_alloc_string (libfunc_name, p - libfunc_name));
-}
-
-/* Like gen_libfunc, but verify that integer operation is involved. */
-
-void
-gen_int_libfunc (optab optable, const char *opname, char suffix,
- machine_mode mode)
-{
- int maxsize = 2 * BITS_PER_WORD;
- int minsize = BITS_PER_WORD;
-
- if (GET_MODE_CLASS (mode) != MODE_INT)
- return;
- if (maxsize < LONG_LONG_TYPE_SIZE)
- maxsize = LONG_LONG_TYPE_SIZE;
- if (minsize > INT_TYPE_SIZE
- && (trapv_binoptab_p (optable)
- || trapv_unoptab_p (optable)))
- minsize = INT_TYPE_SIZE;
- if (GET_MODE_BITSIZE (mode) < minsize
- || GET_MODE_BITSIZE (mode) > maxsize)
- return;
- gen_libfunc (optable, opname, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that FP and set decimal prefix if needed. */
-
-void
-gen_fp_libfunc (optab optable, const char *opname, char suffix,
- machine_mode mode)
-{
- char *dec_opname;
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- gen_libfunc (optable, opname, suffix, mode);
- if (DECIMAL_FLOAT_MODE_P (mode))
- {
- dec_opname = XALLOCAVEC (char, sizeof (DECIMAL_PREFIX) + strlen (opname));
- /* For BID support, change the name to have either a bid_ or dpd_ prefix
- depending on the low level floating format used. */
- memcpy (dec_opname, DECIMAL_PREFIX, sizeof (DECIMAL_PREFIX) - 1);
- strcpy (dec_opname + sizeof (DECIMAL_PREFIX) - 1, opname);
- gen_libfunc (optable, dec_opname, suffix, mode);
- }
-}
-
-/* Like gen_libfunc, but verify that fixed-point operation is involved. */
-
-void
-gen_fixed_libfunc (optab optable, const char *opname, char suffix,
- machine_mode mode)
-{
- if (!ALL_FIXED_POINT_MODE_P (mode))
- return;
- gen_libfunc (optable, opname, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that signed fixed-point operation is
- involved. */
-
-void
-gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix,
- machine_mode mode)
-{
- if (!SIGNED_FIXED_POINT_MODE_P (mode))
- return;
- gen_libfunc (optable, opname, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that unsigned fixed-point operation is
- involved. */
-
-void
-gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix,
- machine_mode mode)
-{
- if (!UNSIGNED_FIXED_POINT_MODE_P (mode))
- return;
- gen_libfunc (optable, opname, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that FP or INT operation is involved. */
-
-void
-gen_int_fp_libfunc (optab optable, const char *name, char suffix,
- machine_mode mode)
-{
- if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
- gen_fp_libfunc (optable, name, suffix, mode);
- if (INTEGRAL_MODE_P (mode))
- gen_int_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that FP or INT operation is involved
- and add 'v' suffix for integer operation. */
-
-void
-gen_intv_fp_libfunc (optab optable, const char *name, char suffix,
- machine_mode mode)
-{
- if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
- gen_fp_libfunc (optable, name, suffix, mode);
- if (GET_MODE_CLASS (mode) == MODE_INT)
- {
- int len = strlen (name);
- char *v_name = XALLOCAVEC (char, len + 2);
- strcpy (v_name, name);
- v_name[len] = 'v';
- v_name[len + 1] = 0;
- gen_int_libfunc (optable, v_name, suffix, mode);
- }
-}
-
-/* Like gen_libfunc, but verify that FP or INT or FIXED operation is
- involved. */
-
-void
-gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix,
- machine_mode mode)
-{
- if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
- gen_fp_libfunc (optable, name, suffix, mode);
- if (INTEGRAL_MODE_P (mode))
- gen_int_libfunc (optable, name, suffix, mode);
- if (ALL_FIXED_POINT_MODE_P (mode))
- gen_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that FP or INT or signed FIXED operation is
- involved. */
-
-void
-gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix,
- machine_mode mode)
-{
- if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT)
- gen_fp_libfunc (optable, name, suffix, mode);
- if (INTEGRAL_MODE_P (mode))
- gen_int_libfunc (optable, name, suffix, mode);
- if (SIGNED_FIXED_POINT_MODE_P (mode))
- gen_signed_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that INT or FIXED operation is
- involved. */
-
-void
-gen_int_fixed_libfunc (optab optable, const char *name, char suffix,
- machine_mode mode)
-{
- if (INTEGRAL_MODE_P (mode))
- gen_int_libfunc (optable, name, suffix, mode);
- if (ALL_FIXED_POINT_MODE_P (mode))
- gen_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that INT or signed FIXED operation is
- involved. */
-
-void
-gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix,
- machine_mode mode)
-{
- if (INTEGRAL_MODE_P (mode))
- gen_int_libfunc (optable, name, suffix, mode);
- if (SIGNED_FIXED_POINT_MODE_P (mode))
- gen_signed_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Like gen_libfunc, but verify that INT or unsigned FIXED operation is
- involved. */
-
-void
-gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix,
- machine_mode mode)
-{
- if (INTEGRAL_MODE_P (mode))
- gen_int_libfunc (optable, name, suffix, mode);
- if (UNSIGNED_FIXED_POINT_MODE_P (mode))
- gen_unsigned_fixed_libfunc (optable, name, suffix, mode);
-}
-
-/* Initialize the libfunc fields of an entire group of entries of an
- inter-mode-class conversion optab. The string formation rules are
- similar to the ones for init_libfuncs, above, but instead of having
- a mode name and an operand count these functions have two mode names
- and no operand count. */
-
-void
-gen_interclass_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- size_t opname_len = strlen (opname);
- size_t mname_len = 0;
-
- const char *fname, *tname;
- const char *q;
- int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
- char *libfunc_name, *suffix;
- char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
- char *p;
-
- /* If this is a decimal conversion, add the current BID vs. DPD prefix that
- depends on which underlying decimal floating point format is used. */
- const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
-
- mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
-
- nondec_name = XALLOCAVEC (char, prefix_len + opname_len + mname_len + 1 + 1);
- nondec_name[0] = '_';
- nondec_name[1] = '_';
- if (targetm.libfunc_gnu_prefix)
- {
- nondec_name[2] = 'g';
- nondec_name[3] = 'n';
- nondec_name[4] = 'u';
- nondec_name[5] = '_';
- }
-
- memcpy (&nondec_name[prefix_len], opname, opname_len);
- nondec_suffix = nondec_name + opname_len + prefix_len;
-
- dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
- dec_name[0] = '_';
- dec_name[1] = '_';
- memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
- memcpy (&dec_name[2+dec_len], opname, opname_len);
- dec_suffix = dec_name + dec_len + opname_len + 2;
-
- fname = GET_MODE_NAME (fmode);
- tname = GET_MODE_NAME (tmode);
-
- if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
- {
- libfunc_name = dec_name;
- suffix = dec_suffix;
- }
- else
- {
- libfunc_name = nondec_name;
- suffix = nondec_suffix;
- }
-
- p = suffix;
- for (q = fname; *q; p++, q++)
- *p = TOLOWER (*q);
- for (q = tname; *q; p++, q++)
- *p = TOLOWER (*q);
-
- *p = '\0';
-
- set_conv_libfunc (tab, tmode, fmode,
- ggc_alloc_string (libfunc_name, p - libfunc_name));
-}
-
-/* Same as gen_interclass_conv_libfunc but verify that we are producing
- int->fp conversion. */
-
-void
-gen_int_to_fp_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (GET_MODE_CLASS (fmode) != MODE_INT)
- return;
- if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
- return;
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* ufloat_optab is special by using floatun for FP and floatuns decimal fp
- naming scheme. */
-
-void
-gen_ufloat_conv_libfunc (convert_optab tab,
- const char *opname ATTRIBUTE_UNUSED,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (DECIMAL_FLOAT_MODE_P (tmode))
- gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode);
- else
- gen_int_to_fp_conv_libfunc (tab, "floatun", tmode, fmode);
-}
-
-/* Same as gen_interclass_conv_libfunc but verify that we are producing
- fp->int conversion. */
-
-void
-gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (GET_MODE_CLASS (fmode) != MODE_INT)
- return;
- if (GET_MODE_CLASS (tmode) != MODE_FLOAT)
- return;
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Same as gen_interclass_conv_libfunc but verify that we are producing
- fp->int conversion with no decimal floating point involved. */
-
-void
-gen_fp_to_int_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
- return;
- if (GET_MODE_CLASS (tmode) != MODE_INT)
- return;
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Initialize the libfunc fields of an of an intra-mode-class conversion optab.
- The string formation rules are
- similar to the ones for init_libfunc, above. */
-
-void
-gen_intraclass_conv_libfunc (convert_optab tab, const char *opname,
- machine_mode tmode, machine_mode fmode)
-{
- size_t opname_len = strlen (opname);
- size_t mname_len = 0;
-
- const char *fname, *tname;
- const char *q;
- int prefix_len = targetm.libfunc_gnu_prefix ? 6 : 2;
- char *nondec_name, *dec_name, *nondec_suffix, *dec_suffix;
- char *libfunc_name, *suffix;
- char *p;
-
- /* If this is a decimal conversion, add the current BID vs. DPD prefix that
- depends on which underlying decimal floating point format is used. */
- const size_t dec_len = sizeof (DECIMAL_PREFIX) - 1;
-
- mname_len = strlen (GET_MODE_NAME (tmode)) + strlen (GET_MODE_NAME (fmode));
-
- nondec_name = XALLOCAVEC (char, 2 + opname_len + mname_len + 1 + 1);
- nondec_name[0] = '_';
- nondec_name[1] = '_';
- if (targetm.libfunc_gnu_prefix)
- {
- nondec_name[2] = 'g';
- nondec_name[3] = 'n';
- nondec_name[4] = 'u';
- nondec_name[5] = '_';
- }
- memcpy (&nondec_name[prefix_len], opname, opname_len);
- nondec_suffix = nondec_name + opname_len + prefix_len;
-
- dec_name = XALLOCAVEC (char, 2 + dec_len + opname_len + mname_len + 1 + 1);
- dec_name[0] = '_';
- dec_name[1] = '_';
- memcpy (&dec_name[2], DECIMAL_PREFIX, dec_len);
- memcpy (&dec_name[2 + dec_len], opname, opname_len);
- dec_suffix = dec_name + dec_len + opname_len + 2;
-
- fname = GET_MODE_NAME (fmode);
- tname = GET_MODE_NAME (tmode);
-
- if (DECIMAL_FLOAT_MODE_P (fmode) || DECIMAL_FLOAT_MODE_P (tmode))
- {
- libfunc_name = dec_name;
- suffix = dec_suffix;
- }
- else
- {
- libfunc_name = nondec_name;
- suffix = nondec_suffix;
- }
-
- p = suffix;
- for (q = fname; *q; p++, q++)
- *p = TOLOWER (*q);
- for (q = tname; *q; p++, q++)
- *p = TOLOWER (*q);
-
- *p++ = '2';
- *p = '\0';
-
- set_conv_libfunc (tab, tmode, fmode,
- ggc_alloc_string (libfunc_name, p - libfunc_name));
-}
-
-/* Pick proper libcall for trunc_optab. We need to chose if we do
- truncation or extension and interclass or intraclass. */
-
-void
-gen_trunc_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
- return;
- if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
- return;
- if (tmode == fmode)
- return;
-
- if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
- || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-
- if (GET_MODE_PRECISION (fmode) <= GET_MODE_PRECISION (tmode))
- return;
-
- if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
- && GET_MODE_CLASS (fmode) == MODE_FLOAT)
- || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
- gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for extend_optab. We need to chose if we do
- truncation or extension and interclass or intraclass. */
-
-void
-gen_extend_conv_libfunc (convert_optab tab,
- const char *opname ATTRIBUTE_UNUSED,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode))
- return;
- if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode))
- return;
- if (tmode == fmode)
- return;
-
- if ((GET_MODE_CLASS (tmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (fmode))
- || (GET_MODE_CLASS (fmode) == MODE_FLOAT && DECIMAL_FLOAT_MODE_P (tmode)))
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-
- if (GET_MODE_PRECISION (fmode) > GET_MODE_PRECISION (tmode))
- return;
-
- if ((GET_MODE_CLASS (tmode) == MODE_FLOAT
- && GET_MODE_CLASS (fmode) == MODE_FLOAT)
- || (DECIMAL_FLOAT_MODE_P (fmode) && DECIMAL_FLOAT_MODE_P (tmode)))
- gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for fract_optab. We need to chose if we do
- interclass or intraclass. */
-
-void
-gen_fract_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (tmode == fmode)
- return;
- if (!(ALL_FIXED_POINT_MODE_P (tmode) || ALL_FIXED_POINT_MODE_P (fmode)))
- return;
-
- if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
- gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
- else
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for fractuns_optab. */
-
-void
-gen_fractuns_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (tmode == fmode)
- return;
- /* One mode must be a fixed-point mode, and the other must be an integer
- mode. */
- if (!((ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT)
- || (ALL_FIXED_POINT_MODE_P (fmode)
- && GET_MODE_CLASS (tmode) == MODE_INT)))
- return;
-
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for satfract_optab. We need to chose if we do
- interclass or intraclass. */
-
-void
-gen_satfract_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (tmode == fmode)
- return;
- /* TMODE must be a fixed-point mode. */
- if (!ALL_FIXED_POINT_MODE_P (tmode))
- return;
-
- if (GET_MODE_CLASS (tmode) == GET_MODE_CLASS (fmode))
- gen_intraclass_conv_libfunc (tab, opname, tmode, fmode);
- else
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Pick proper libcall for satfractuns_optab. */
-
-void
-gen_satfractuns_conv_libfunc (convert_optab tab,
- const char *opname,
- machine_mode tmode,
- machine_mode fmode)
-{
- if (tmode == fmode)
- return;
- /* TMODE must be a fixed-point mode, and FMODE must be an integer mode. */
- if (!(ALL_FIXED_POINT_MODE_P (tmode) && GET_MODE_CLASS (fmode) == MODE_INT))
- return;
-
- gen_interclass_conv_libfunc (tab, opname, tmode, fmode);
-}
-
-/* Hashtable callbacks for libfunc_decls. */
-
-struct libfunc_decl_hasher : ggc_ptr_hash<tree_node>
-{
- static hashval_t
- hash (tree entry)
- {
- return IDENTIFIER_HASH_VALUE (DECL_NAME (entry));
- }
-
- static bool
- equal (tree decl, tree name)
- {
- return DECL_NAME (decl) == name;
- }
-};
-
-/* A table of previously-created libfuncs, hashed by name. */
-static GTY (()) hash_table<libfunc_decl_hasher> *libfunc_decls;
-
-/* Build a decl for a libfunc named NAME. */
-
-tree
-build_libfunc_function (const char *name)
-{
- tree decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL,
- get_identifier (name),
- build_function_type (integer_type_node, NULL_TREE));
- /* ??? We don't have any type information except for this is
- a function. Pretend this is "int foo()". */
- DECL_ARTIFICIAL (decl) = 1;
- DECL_EXTERNAL (decl) = 1;
- TREE_PUBLIC (decl) = 1;
- gcc_assert (DECL_ASSEMBLER_NAME (decl));
-
- /* Zap the nonsensical SYMBOL_REF_DECL for this. What we're left with
- are the flags assigned by targetm.encode_section_info. */
- SET_SYMBOL_REF_DECL (XEXP (DECL_RTL (decl), 0), NULL);
-
- return decl;
-}
-
-rtx
-init_one_libfunc (const char *name)
-{
- tree id, decl;
- hashval_t hash;
-
- if (libfunc_decls == NULL)
- libfunc_decls = hash_table<libfunc_decl_hasher>::create_ggc (37);
-
- /* See if we have already created a libfunc decl for this function. */
- id = get_identifier (name);
- hash = IDENTIFIER_HASH_VALUE (id);
- tree *slot = libfunc_decls->find_slot_with_hash (id, hash, INSERT);
- decl = *slot;
- if (decl == NULL)
- {
- /* Create a new decl, so that it can be passed to
- targetm.encode_section_info. */
- decl = build_libfunc_function (name);
- *slot = decl;
- }
- return XEXP (DECL_RTL (decl), 0);
-}
-
-/* Adjust the assembler name of libfunc NAME to ASMSPEC. */
-
-rtx
-set_user_assembler_libfunc (const char *name, const char *asmspec)
-{
- tree id, decl;
- hashval_t hash;
-
- id = get_identifier (name);
- hash = IDENTIFIER_HASH_VALUE (id);
- tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT);
- gcc_assert (slot);
- decl = (tree) *slot;
- set_user_assembler_name (decl, asmspec);
- return XEXP (DECL_RTL (decl), 0);
-}
-
-/* Call this to reset the function entry for one optab (OPTABLE) in mode
- MODE to NAME, which should be either 0 or a string constant. */
-void
-set_optab_libfunc (optab op, machine_mode mode, const char *name)
-{
- rtx val;
- struct libfunc_entry e;
- struct libfunc_entry **slot;
-
- e.op = op;
- e.mode1 = mode;
- e.mode2 = VOIDmode;
-
- if (name)
- val = init_one_libfunc (name);
- else
- val = 0;
- slot = libfunc_hash->find_slot (&e, INSERT);
- if (*slot == NULL)
- *slot = ggc_alloc<libfunc_entry> ();
- (*slot)->op = op;
- (*slot)->mode1 = mode;
- (*slot)->mode2 = VOIDmode;
- (*slot)->libfunc = val;
-}
-
-/* Call this to reset the function entry for one conversion optab
- (OPTABLE) from mode FMODE to mode TMODE to NAME, which should be
- either 0 or a string constant. */
-void
-set_conv_libfunc (convert_optab optab, machine_mode tmode,
- machine_mode fmode, const char *name)
-{
- rtx val;
- struct libfunc_entry e;
- struct libfunc_entry **slot;
-
- e.op = optab;
- e.mode1 = tmode;
- e.mode2 = fmode;
-
- if (name)
- val = init_one_libfunc (name);
- else
- val = 0;
- slot = libfunc_hash->find_slot (&e, INSERT);
- if (*slot == NULL)
- *slot = ggc_alloc<libfunc_entry> ();
- (*slot)->op = optab;
- (*slot)->mode1 = tmode;
- (*slot)->mode2 = fmode;
- (*slot)->libfunc = val;
-}
-
-/* Call this to initialize the contents of the optabs
- appropriately for the current target machine. */
-
-void
-init_optabs (void)
-{
- if (libfunc_hash)
- libfunc_hash->empty ();
- else
- libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10);
-
- /* Fill in the optabs with the insns we support. */
- init_all_optabs (this_fn_optabs);
-
- /* The ffs function operates on `int'. Fall back on it if we do not
- have a libgcc2 function for that width. */
- if (INT_TYPE_SIZE < BITS_PER_WORD)
- set_optab_libfunc (ffs_optab, mode_for_size (INT_TYPE_SIZE, MODE_INT, 0),
- "ffs");
-
- /* Explicitly initialize the bswap libfuncs since we need them to be
- valid for things other than word_mode. */
- if (targetm.libfunc_gnu_prefix)
- {
- set_optab_libfunc (bswap_optab, SImode, "__gnu_bswapsi2");
- set_optab_libfunc (bswap_optab, DImode, "__gnu_bswapdi2");
- }
- else
- {
- set_optab_libfunc (bswap_optab, SImode, "__bswapsi2");
- set_optab_libfunc (bswap_optab, DImode, "__bswapdi2");
- }
-
- /* Use cabs for double complex abs, since systems generally have cabs.
- Don't define any libcall for float complex, so that cabs will be used. */
- if (complex_double_type_node)
- set_optab_libfunc (abs_optab, TYPE_MODE (complex_double_type_node),
- "cabs");
-
- abort_libfunc = init_one_libfunc ("abort");
- memcpy_libfunc = init_one_libfunc ("memcpy");
- memmove_libfunc = init_one_libfunc ("memmove");
- memcmp_libfunc = init_one_libfunc ("memcmp");
- memset_libfunc = init_one_libfunc ("memset");
- setbits_libfunc = init_one_libfunc ("__setbits");
-
-#ifndef DONT_USE_BUILTIN_SETJMP
- setjmp_libfunc = init_one_libfunc ("__builtin_setjmp");
- longjmp_libfunc = init_one_libfunc ("__builtin_longjmp");
-#else
- setjmp_libfunc = init_one_libfunc ("setjmp");
- longjmp_libfunc = init_one_libfunc ("longjmp");
-#endif
- unwind_sjlj_register_libfunc = init_one_libfunc ("_Unwind_SjLj_Register");
- unwind_sjlj_unregister_libfunc
- = init_one_libfunc ("_Unwind_SjLj_Unregister");
-
- /* For function entry/exit instrumentation. */
- profile_function_entry_libfunc
- = init_one_libfunc ("__cyg_profile_func_enter");
- profile_function_exit_libfunc
- = init_one_libfunc ("__cyg_profile_func_exit");
-
- gcov_flush_libfunc = init_one_libfunc ("__gcov_flush");
-
- /* Allow the target to add more libcalls or rename some, etc. */
- targetm.init_libfuncs ();
-}
-
-/* Use the current target and options to initialize
- TREE_OPTIMIZATION_OPTABS (OPTNODE). */
-
-void
-init_tree_optimization_optabs (tree optnode)
-{
- /* Quick exit if we have already computed optabs for this target. */
- if (TREE_OPTIMIZATION_BASE_OPTABS (optnode) == this_target_optabs)
- return;
-
- /* Forget any previous information and set up for the current target. */
- TREE_OPTIMIZATION_BASE_OPTABS (optnode) = this_target_optabs;
- struct target_optabs *tmp_optabs = (struct target_optabs *)
- TREE_OPTIMIZATION_OPTABS (optnode);
- if (tmp_optabs)
- memset (tmp_optabs, 0, sizeof (struct target_optabs));
- else
- tmp_optabs = ggc_alloc<target_optabs> ();
-
- /* Generate a new set of optabs into tmp_optabs. */
- init_all_optabs (tmp_optabs);
-
- /* If the optabs changed, record it. */
- if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs)))
- TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs;
- else
- {
- TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
- ggc_free (tmp_optabs);
- }
-}
-
-/* A helper function for init_sync_libfuncs. Using the basename BASE,
- install libfuncs into TAB for BASE_N for 1 <= N <= MAX. */
-
-static void
-init_sync_libfuncs_1 (optab tab, const char *base, int max)
-{
- machine_mode mode;
- char buf[64];
- size_t len = strlen (base);
- int i;
-
- gcc_assert (max <= 8);
- gcc_assert (len + 3 < sizeof (buf));
-
- memcpy (buf, base, len);
- buf[len] = '_';
- buf[len + 1] = '0';
- buf[len + 2] = '\0';
-
- mode = QImode;
- for (i = 1; i <= max; i *= 2)
- {
- buf[len + 1] = '0' + i;
- set_optab_libfunc (tab, mode, buf);
- mode = GET_MODE_2XWIDER_MODE (mode);
- }
-}
-
-void
-init_sync_libfuncs (int max)
-{
- if (!flag_sync_libcalls)
- return;
-
- init_sync_libfuncs_1 (sync_compare_and_swap_optab,
- "__sync_val_compare_and_swap", max);
- init_sync_libfuncs_1 (sync_lock_test_and_set_optab,
- "__sync_lock_test_and_set", max);
-
- init_sync_libfuncs_1 (sync_old_add_optab, "__sync_fetch_and_add", max);
- init_sync_libfuncs_1 (sync_old_sub_optab, "__sync_fetch_and_sub", max);
- init_sync_libfuncs_1 (sync_old_ior_optab, "__sync_fetch_and_or", max);
- init_sync_libfuncs_1 (sync_old_and_optab, "__sync_fetch_and_and", max);
- init_sync_libfuncs_1 (sync_old_xor_optab, "__sync_fetch_and_xor", max);
- init_sync_libfuncs_1 (sync_old_nand_optab, "__sync_fetch_and_nand", max);
-
- init_sync_libfuncs_1 (sync_new_add_optab, "__sync_add_and_fetch", max);
- init_sync_libfuncs_1 (sync_new_sub_optab, "__sync_sub_and_fetch", max);
- init_sync_libfuncs_1 (sync_new_ior_optab, "__sync_or_and_fetch", max);
- init_sync_libfuncs_1 (sync_new_and_optab, "__sync_and_and_fetch", max);
- init_sync_libfuncs_1 (sync_new_xor_optab, "__sync_xor_and_fetch", max);
- init_sync_libfuncs_1 (sync_new_nand_optab, "__sync_nand_and_fetch", max);
-}
-
/* Print information about the current contents of the optabs on
STDERR. */
@@ -6385,7 +4987,6 @@ debug_optab_libfuncs (void)
}
}
-
/* Generate insns to trap with code TCODE if OP1 and OP2 satisfy condition
CODE. Return 0 on failure. */
@@ -6534,63 +5135,6 @@ vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1,
return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value);
}
-/* Return true if VEC_PERM_EXPR of arbitrary input vectors can be expanded using
- SIMD extensions of the CPU. SEL may be NULL, which stands for an unknown
- constant. Note that additional permutations representing whole-vector shifts
- may also be handled via the vec_shr optab, but only where the second input
- vector is entirely constant zeroes; this case is not dealt with here. */
-
-bool
-can_vec_perm_p (machine_mode mode, bool variable,
- const unsigned char *sel)
-{
- machine_mode qimode;
-
- /* If the target doesn't implement a vector mode for the vector type,
- then no operations are supported. */
- if (!VECTOR_MODE_P (mode))
- return false;
-
- if (!variable)
- {
- if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing
- && (sel == NULL
- || targetm.vectorize.vec_perm_const_ok == NULL
- || targetm.vectorize.vec_perm_const_ok (mode, sel)))
- return true;
- }
-
- if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
- return true;
-
- /* We allow fallback to a QI vector mode, and adjust the mask. */
- if (GET_MODE_INNER (mode) == QImode)
- return false;
- qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
- if (!VECTOR_MODE_P (qimode))
- return false;
-
- /* ??? For completeness, we ought to check the QImode version of
- vec_perm_const_optab. But all users of this implicit lowering
- feature implement the variable vec_perm_optab. */
- if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
- return false;
-
- /* In order to support the lowering of variable permutations,
- we need to support shifts and adds. */
- if (variable)
- {
- if (GET_MODE_UNIT_SIZE (mode) > 2
- && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
- && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
- return false;
- if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
- return false;
- }
-
- return true;
-}
-
/* Checks if vec_perm mask SEL is a constant equivalent to a shift of the first
vec_perm operand, assuming the second operand is a constant vector of zeroes.
Return the shift distance in bits if so, or NULL_RTX if the vec_perm is not a
@@ -6800,37 +5344,6 @@ expand_vec_perm (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target)
return tmp;
}
-/* Return insn code for a conditional operator with a comparison in
- mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */
-
-static inline enum insn_code
-get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns)
-{
- enum insn_code icode = CODE_FOR_nothing;
- if (uns)
- icode = convert_optab_handler (vcondu_optab, vmode, cmode);
- else
- icode = convert_optab_handler (vcond_optab, vmode, cmode);
- return icode;
-}
-
-/* Return TRUE iff, appropriate vector insns are available
- for vector cond expr with vector type VALUE_TYPE and a comparison
- with operand vector types in CMP_OP_TYPE. */
-
-bool
-expand_vec_cond_expr_p (tree value_type, tree cmp_op_type)
-{
- machine_mode value_mode = TYPE_MODE (value_type);
- machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
- if (GET_MODE_SIZE (value_mode) != GET_MODE_SIZE (cmp_op_mode)
- || GET_MODE_NUNITS (value_mode) != GET_MODE_NUNITS (cmp_op_mode)
- || get_vcond_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type),
- TYPE_UNSIGNED (cmp_op_type)) == CODE_FOR_nothing)
- return false;
- return true;
-}
-
/* Generate insns for a VEC_COND_EXPR, given its TYPE and its
three operands. */
@@ -6886,57 +5399,6 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
return ops[0].value;
}
-/* Return non-zero if a highpart multiply is supported of can be synthisized.
- For the benefit of expand_mult_highpart, the return value is 1 for direct,
- 2 for even/odd widening, and 3 for hi/lo widening. */
-
-int
-can_mult_highpart_p (machine_mode mode, bool uns_p)
-{
- optab op;
- unsigned char *sel;
- unsigned i, nunits;
-
- op = uns_p ? umul_highpart_optab : smul_highpart_optab;
- if (optab_handler (op, mode) != CODE_FOR_nothing)
- return 1;
-
- /* If the mode is an integral vector, synth from widening operations. */
- if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
- return 0;
-
- nunits = GET_MODE_NUNITS (mode);
- sel = XALLOCAVEC (unsigned char, nunits);
-
- op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
- if (optab_handler (op, mode) != CODE_FOR_nothing)
- {
- op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
- if (optab_handler (op, mode) != CODE_FOR_nothing)
- {
- for (i = 0; i < nunits; ++i)
- sel[i] = !BYTES_BIG_ENDIAN + (i & ~1) + ((i & 1) ? nunits : 0);
- if (can_vec_perm_p (mode, false, sel))
- return 2;
- }
- }
-
- op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
- if (optab_handler (op, mode) != CODE_FOR_nothing)
- {
- op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
- if (optab_handler (op, mode) != CODE_FOR_nothing)
- {
- for (i = 0; i < nunits; ++i)
- sel[i] = 2 * i + (BYTES_BIG_ENDIAN ? 0 : 1);
- if (can_vec_perm_p (mode, false, sel))
- return 3;
- }
- }
-
- return 0;
-}
-
/* Expand a highpart multiply. */
rtx
@@ -7008,89 +5470,7 @@ expand_mult_highpart (machine_mode mode, rtx op0, rtx op1,
return expand_vec_perm (mode, m1, m2, perm, target);
}
-
-/* Return true if target supports vector masked load/store for mode. */
-bool
-can_vec_mask_load_store_p (machine_mode mode, bool is_load)
-{
- optab op = is_load ? maskload_optab : maskstore_optab;
- machine_mode vmode;
- unsigned int vector_sizes;
-
- /* If mode is vector mode, check it directly. */
- if (VECTOR_MODE_P (mode))
- return optab_handler (op, mode) != CODE_FOR_nothing;
-
- /* Otherwise, return true if there is some vector mode with
- the mask load/store supported. */
-
- /* See if there is any chance the mask load or store might be
- vectorized. If not, punt. */
- vmode = targetm.vectorize.preferred_simd_mode (mode);
- if (!VECTOR_MODE_P (vmode))
- return false;
-
- if (optab_handler (op, vmode) != CODE_FOR_nothing)
- return true;
-
- vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
- while (vector_sizes != 0)
- {
- unsigned int cur = 1 << floor_log2 (vector_sizes);
- vector_sizes &= ~cur;
- if (cur <= GET_MODE_SIZE (mode))
- continue;
- vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode));
- if (VECTOR_MODE_P (vmode)
- && optab_handler (op, vmode) != CODE_FOR_nothing)
- return true;
- }
- return false;
-}
-/* Return true if there is a compare_and_swap pattern. */
-
-bool
-can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
-{
- enum insn_code icode;
-
- /* Check for __atomic_compare_and_swap. */
- icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
- if (icode != CODE_FOR_nothing)
- return true;
-
- /* Check for __sync_compare_and_swap. */
- icode = optab_handler (sync_compare_and_swap_optab, mode);
- if (icode != CODE_FOR_nothing)
- return true;
- if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
- return true;
-
- /* No inline compare and swap. */
- return false;
-}
-
-/* Return true if an atomic exchange can be performed. */
-
-bool
-can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
-{
- enum insn_code icode;
-
- /* Check for __atomic_exchange. */
- icode = direct_optab_handler (atomic_exchange_optab, mode);
- if (icode != CODE_FOR_nothing)
- return true;
-
- /* Don't check __sync_test_and_set, as on some platforms that
- has reduced functionality. Targets that really do support
- a proper exchange should simply be updated to the __atomics. */
-
- return can_compare_and_swap_p (mode, allow_libcall);
-}
-
-
/* Helper function to find the MODE_CC set in a sync_compare_and_swap
pattern. */
@@ -8412,225 +6792,3 @@ expand_jump_insn (enum insn_code icode, unsigned int nops,
if (!maybe_expand_jump_insn (icode, nops, ops))
gcc_unreachable ();
}
-
-/* Reduce conditional compilation elsewhere. */
-
-/* Enumerates the possible types of structure operand to an
- extraction_insn. */
-enum extraction_type { ET_unaligned_mem, ET_reg };
-
-/* Check whether insv, extv or extzv pattern ICODE can be used for an
- insertion or extraction of type TYPE on a structure of mode MODE.
- Return true if so and fill in *INSN accordingly. STRUCT_OP is the
- operand number of the structure (the first sign_extract or zero_extract
- operand) and FIELD_OP is the operand number of the field (the other
- side of the set from the sign_extract or zero_extract). */
-
-static bool
-get_traditional_extraction_insn (extraction_insn *insn,
- enum extraction_type type,
- machine_mode mode,
- enum insn_code icode,
- int struct_op, int field_op)
-{
- const struct insn_data_d *data = &insn_data[icode];
-
- machine_mode struct_mode = data->operand[struct_op].mode;
- if (struct_mode == VOIDmode)
- struct_mode = word_mode;
- if (mode != struct_mode)
- return false;
-
- machine_mode field_mode = data->operand[field_op].mode;
- if (field_mode == VOIDmode)
- field_mode = word_mode;
-
- machine_mode pos_mode = data->operand[struct_op + 2].mode;
- if (pos_mode == VOIDmode)
- pos_mode = word_mode;
-
- insn->icode = icode;
- insn->field_mode = field_mode;
- insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode);
- insn->pos_mode = pos_mode;
- return true;
-}
-
-/* Return true if an optab exists to perform an insertion or extraction
- of type TYPE in mode MODE. Describe the instruction in *INSN if so.
-
- REG_OPTAB is the optab to use for register structures and
- MISALIGN_OPTAB is the optab to use for misaligned memory structures.
- POS_OP is the operand number of the bit position. */
-
-static bool
-get_optab_extraction_insn (struct extraction_insn *insn,
- enum extraction_type type,
- machine_mode mode, direct_optab reg_optab,
- direct_optab misalign_optab, int pos_op)
-{
- direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
- enum insn_code icode = direct_optab_handler (optab, mode);
- if (icode == CODE_FOR_nothing)
- return false;
-
- const struct insn_data_d *data = &insn_data[icode];
-
- insn->icode = icode;
- insn->field_mode = mode;
- insn->struct_mode = (type == ET_unaligned_mem ? BLKmode : mode);
- insn->pos_mode = data->operand[pos_op].mode;
- if (insn->pos_mode == VOIDmode)
- insn->pos_mode = word_mode;
- return true;
-}
-
-/* Return true if an instruction exists to perform an insertion or
- extraction (PATTERN says which) of type TYPE in mode MODE.
- Describe the instruction in *INSN if so. */
-
-static bool
-get_extraction_insn (extraction_insn *insn,
- enum extraction_pattern pattern,
- enum extraction_type type,
- machine_mode mode)
-{
- switch (pattern)
- {
- case EP_insv:
- if (targetm.have_insv ()
- && get_traditional_extraction_insn (insn, type, mode,
- targetm.code_for_insv, 0, 3))
- return true;
- return get_optab_extraction_insn (insn, type, mode, insv_optab,
- insvmisalign_optab, 2);
-
- case EP_extv:
- if (targetm.have_extv ()
- && get_traditional_extraction_insn (insn, type, mode,
- targetm.code_for_extv, 1, 0))
- return true;
- return get_optab_extraction_insn (insn, type, mode, extv_optab,
- extvmisalign_optab, 3);
-
- case EP_extzv:
- if (targetm.have_extzv ()
- && get_traditional_extraction_insn (insn, type, mode,
- targetm.code_for_extzv, 1, 0))
- return true;
- return get_optab_extraction_insn (insn, type, mode, extzv_optab,
- extzvmisalign_optab, 3);
-
- default:
- gcc_unreachable ();
- }
-}
-
-/* Return true if an instruction exists to access a field of mode
- FIELDMODE in a structure that has STRUCT_BITS significant bits.
- Describe the "best" such instruction in *INSN if so. PATTERN and
- TYPE describe the type of insertion or extraction we want to perform.
-
- For an insertion, the number of significant structure bits includes
- all bits of the target. For an extraction, it need only include the
- most significant bit of the field. Larger widths are acceptable
- in both cases. */
-
-static bool
-get_best_extraction_insn (extraction_insn *insn,
- enum extraction_pattern pattern,
- enum extraction_type type,
- unsigned HOST_WIDE_INT struct_bits,
- machine_mode field_mode)
-{
- machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT);
- while (mode != VOIDmode)
- {
- if (get_extraction_insn (insn, pattern, type, mode))
- {
- while (mode != VOIDmode
- && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (field_mode)
- && !TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
- field_mode))
- {
- get_extraction_insn (insn, pattern, type, mode);
- mode = GET_MODE_WIDER_MODE (mode);
- }
- return true;
- }
- mode = GET_MODE_WIDER_MODE (mode);
- }
- return false;
-}
-
-/* Return true if an instruction exists to access a field of mode
- FIELDMODE in a register structure that has STRUCT_BITS significant bits.
- Describe the "best" such instruction in *INSN if so. PATTERN describes
- the type of insertion or extraction we want to perform.
-
- For an insertion, the number of significant structure bits includes
- all bits of the target. For an extraction, it need only include the
- most significant bit of the field. Larger widths are acceptable
- in both cases. */
-
-bool
-get_best_reg_extraction_insn (extraction_insn *insn,
- enum extraction_pattern pattern,
- unsigned HOST_WIDE_INT struct_bits,
- machine_mode field_mode)
-{
- return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
- field_mode);
-}
-
-/* Return true if an instruction exists to access a field of BITSIZE
- bits starting BITNUM bits into a memory structure. Describe the
- "best" such instruction in *INSN if so. PATTERN describes the type
- of insertion or extraction we want to perform and FIELDMODE is the
- natural mode of the extracted field.
-
- The instructions considered here only access bytes that overlap
- the bitfield; they do not touch any surrounding bytes. */
-
-bool
-get_best_mem_extraction_insn (extraction_insn *insn,
- enum extraction_pattern pattern,
- HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
- machine_mode field_mode)
-{
- unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
- + bitsize
- + BITS_PER_UNIT - 1);
- struct_bits -= struct_bits % BITS_PER_UNIT;
- return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
- struct_bits, field_mode);
-}
-
-/* Determine whether "1 << x" is relatively cheap in word_mode. */
-
-bool
-lshift_cheap_p (bool speed_p)
-{
- /* FIXME: This should be made target dependent via this "this_target"
- mechanism, similar to e.g. can_copy_init_p in gcse.c. */
- static bool init[2] = { false, false };
- static bool cheap[2] = { true, true };
-
- /* If the targer has no lshift in word_mode, the operation will most
- probably not be cheap. ??? Does GCC even work for such targets? */
- if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
- return false;
-
- if (!init[speed_p])
- {
- rtx reg = gen_raw_REG (word_mode, 10000);
- int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
- word_mode, speed_p);
- cheap[speed_p] = cost < COSTS_N_INSNS (3);
- init[speed_p] = true;
- }
-
- return cheap[speed_p];
-}
-
-#include "gt-optabs.h"