diff options
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r-- | gcc/optabs.c | 915 |
1 files changed, 513 insertions, 402 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c index 5359257665..e9dc7981c6 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -1,5 +1,5 @@ /* Expand the basic unary and binary arithmetic operations, for GNU compiler. - Copyright (C) 1987-2014 Free Software Foundation, Inc. + Copyright (C) 1987-2015 Free Software Foundation, Inc. This file is part of GCC. @@ -28,20 +28,45 @@ along with GCC; see the file COPYING3. If not see is properly defined. */ #include "insn-config.h" #include "rtl.h" +#include "hash-set.h" +#include "machmode.h" +#include "vec.h" +#include "double-int.h" +#include "input.h" +#include "alias.h" +#include "symtab.h" +#include "wide-int.h" +#include "inchash.h" #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 "hard-reg-set.h" #include "function.h" #include "except.h" +#include "hashtab.h" +#include "statistics.h" +#include "real.h" +#include "fixed-value.h" +#include "expmed.h" +#include "dojump.h" +#include "explow.h" +#include "calls.h" +#include "emit-rtl.h" +#include "stmt.h" #include "expr.h" +#include "insn-codes.h" #include "optabs.h" #include "libfuncs.h" #include "recog.h" #include "reload.h" #include "ggc.h" +#include "predict.h" +#include "dominance.h" +#include "cfg.h" #include "basic-block.h" #include "target.h" @@ -57,9 +82,9 @@ struct target_libfuncs *this_target_libfuncs = &default_target_libfuncs; (this_target_libfuncs->x_libfunc_hash) static void prepare_float_lib_cmp (rtx, rtx, enum rtx_code, rtx *, - enum machine_mode *); -static rtx expand_unop_direct (enum machine_mode, optab, rtx, rtx, int); -static void emit_libcall_block_1 (rtx, rtx, rtx, rtx, bool); + machine_mode *); +static rtx expand_unop_direct (machine_mode, optab, rtx, rtx, int); +static void emit_libcall_block_1 (rtx_insn *, rtx, rtx, rtx, bool); /* Debug facility for use in GDB. */ void debug_optab_libfuncs (void); @@ -73,20 +98,17 @@ void debug_optab_libfuncs (void); /* Used for libfunc_hash. */ -static hashval_t -hash_libfunc (const void *p) +hashval_t +libfunc_hasher::hash (libfunc_entry *e) { - const struct libfunc_entry *const e = (const struct libfunc_entry *) p; return ((e->mode1 + e->mode2 * NUM_MACHINE_MODES) ^ e->op); } /* Used for libfunc_hash. */ -static int -eq_libfunc (const void *p, const void *q) +bool +libfunc_hasher::equal (libfunc_entry *e1, libfunc_entry *e2) { - const struct libfunc_entry *const e1 = (const struct libfunc_entry *) p; - const struct libfunc_entry *const e2 = (const struct libfunc_entry *) q; return e1->op == e2->op && e1->mode1 == e2->mode1 && e1->mode2 == e2->mode2; } @@ -94,8 +116,8 @@ eq_libfunc (const void *p, const void *q) from MODE2 to MODE1. Trigger lazy initialization if needed, return NULL if no libfunc is available. */ rtx -convert_optab_libfunc (convert_optab optab, enum machine_mode mode1, - enum machine_mode mode2) +convert_optab_libfunc (convert_optab optab, machine_mode mode1, + machine_mode mode2) { struct libfunc_entry e; struct libfunc_entry **slot; @@ -109,8 +131,7 @@ convert_optab_libfunc (convert_optab optab, enum machine_mode mode1, e.op = optab; e.mode1 = mode1; e.mode2 = mode2; - slot = (struct libfunc_entry **) - htab_find_slot (libfunc_hash, &e, NO_INSERT); + slot = libfunc_hash->find_slot (&e, NO_INSERT); if (!slot) { const struct convert_optab_libcall_d *d @@ -120,8 +141,7 @@ convert_optab_libfunc (convert_optab optab, enum machine_mode mode1, return NULL; d->libcall_gen (optab, d->libcall_basename, mode1, mode2); - slot = (struct libfunc_entry **) - htab_find_slot (libfunc_hash, &e, NO_INSERT); + slot = libfunc_hash->find_slot (&e, NO_INSERT); if (!slot) return NULL; } @@ -132,7 +152,7 @@ convert_optab_libfunc (convert_optab optab, enum machine_mode mode1, Trigger lazy initialization if needed, return NULL if no libfunc is available. */ rtx -optab_libfunc (optab optab, enum machine_mode mode) +optab_libfunc (optab optab, machine_mode mode) { struct libfunc_entry e; struct libfunc_entry **slot; @@ -146,8 +166,7 @@ optab_libfunc (optab optab, enum machine_mode mode) e.op = optab; e.mode1 = mode; e.mode2 = VOIDmode; - slot = (struct libfunc_entry **) - htab_find_slot (libfunc_hash, &e, NO_INSERT); + slot = libfunc_hash->find_slot (&e, NO_INSERT); if (!slot) { const struct optab_libcall_d *d @@ -157,8 +176,7 @@ optab_libfunc (optab optab, enum machine_mode mode) return NULL; d->libcall_gen (optab, d->libcall_basename, d->libcall_suffix, mode); - slot = (struct libfunc_entry **) - htab_find_slot (libfunc_hash, &e, NO_INSERT); + slot = libfunc_hash->find_slot (&e, NO_INSERT); if (!slot) return NULL; } @@ -177,9 +195,10 @@ optab_libfunc (optab optab, enum machine_mode mode) try again, ensuring that TARGET is not one of the operands. */ static int -add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) +add_equal_note (rtx_insn *insns, rtx target, enum rtx_code code, rtx op0, rtx op1) { - rtx last_insn, set; + rtx_insn *last_insn; + rtx set; rtx note; gcc_assert (insns && INSN_P (insns) && NEXT_INSN (insns)); @@ -228,7 +247,7 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) return 0; } - set = single_set (last_insn); + set = set_for_reg_notes (last_insn); if (set == NULL_RTX) return 1; @@ -277,12 +296,12 @@ add_equal_note (rtx insns, rtx target, enum rtx_code code, rtx op0, rtx op1) for a widening operation would be. In most cases this would be OP0, but if that's a constant it'll be VOIDmode, which isn't useful. */ -static enum machine_mode -widened_mode (enum machine_mode to_mode, rtx op0, rtx op1) +static machine_mode +widened_mode (machine_mode to_mode, rtx op0, rtx op1) { - enum machine_mode m0 = GET_MODE (op0); - enum machine_mode m1 = GET_MODE (op1); - enum machine_mode result; + machine_mode m0 = GET_MODE (op0); + machine_mode m1 = GET_MODE (op1); + machine_mode result; if (m0 == VOIDmode && m1 == VOIDmode) return to_mode; @@ -297,6 +316,25 @@ widened_mode (enum 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. @@ -304,10 +342,10 @@ widened_mode (enum machine_mode to_mode, rtx op0, rtx op1) non-widening optabs also. */ enum insn_code -find_widening_optab_handler_and_mode (optab op, enum machine_mode to_mode, - enum machine_mode from_mode, +find_widening_optab_handler_and_mode (optab op, machine_mode to_mode, + machine_mode from_mode, int permit_non_widening, - enum machine_mode *found_mode) + machine_mode *found_mode) { for (; (permit_non_widening || from_mode != to_mode) && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode) @@ -335,7 +373,7 @@ find_widening_optab_handler_and_mode (optab op, enum machine_mode to_mode, of logical operations, but not right shifts. */ static rtx -widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode, +widen_operand (rtx op, machine_mode mode, machine_mode oldmode, int unsignedp, int no_extend) { rtx result; @@ -349,7 +387,7 @@ widen_operand (rtx op, enum machine_mode mode, enum machine_mode oldmode, a promoted object differs from our extension. */ if (! no_extend || (GET_CODE (op) == SUBREG && SUBREG_PROMOTED_VAR_P (op) - && SUBREG_PROMOTED_UNSIGNED_P (op) == unsignedp)) + && SUBREG_CHECK_PROMOTED_SIGN (op, unsignedp))) return convert_modes (mode, oldmode, op, unsignedp); /* If MODE is no wider than a single word, we return a lowpart or paradoxical @@ -465,6 +503,9 @@ optab_for_tree_code (enum tree_code code, const_tree type, 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) @@ -483,19 +524,15 @@ optab_for_tree_code (enum tree_code code, const_tree type, return fma_optab; case REDUC_MAX_EXPR: - return TYPE_UNSIGNED (type) ? reduc_umax_optab : reduc_smax_optab; + return TYPE_UNSIGNED (type) + ? reduc_umax_scal_optab : reduc_smax_scal_optab; case REDUC_MIN_EXPR: - return TYPE_UNSIGNED (type) ? reduc_umin_optab : reduc_smin_optab; + return TYPE_UNSIGNED (type) + ? reduc_umin_scal_optab : reduc_smin_scal_optab; case REDUC_PLUS_EXPR: - return TYPE_UNSIGNED (type) ? reduc_uplus_optab : reduc_splus_optab; - - case VEC_LSHIFT_EXPR: - return vec_shl_optab; - - case VEC_RSHIFT_EXPR: - return vec_shr_optab; + return reduc_plus_scal_optab; case VEC_WIDEN_MULT_HI_EXPR: return TYPE_UNSIGNED (type) ? @@ -585,7 +622,26 @@ optab_for_tree_code (enum tree_code code, const_tree type, 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. @@ -613,7 +669,7 @@ expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op, { struct expand_operand eops[4]; tree oprnd0, oprnd1, oprnd2; - enum machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode; + machine_mode wmode = VOIDmode, tmode0, tmode1 = VOIDmode; optab widen_pattern_optab; enum insn_code icode; int nops = TREE_CODE_LENGTH (ops->code); @@ -672,7 +728,7 @@ expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op, this may or may not be TARGET. */ rtx -expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0, +expand_ternary_op (machine_mode mode, optab ternary_optab, rtx op0, rtx op1, rtx op2, rtx target, int unsignedp) { struct expand_operand ops[4]; @@ -694,7 +750,7 @@ expand_ternary_op (enum machine_mode mode, optab ternary_optab, rtx op0, otherwise the same as for expand_binop. */ rtx -simplify_expand_binop (enum machine_mode mode, optab binoptab, +simplify_expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods) { @@ -713,7 +769,7 @@ simplify_expand_binop (enum machine_mode mode, optab binoptab, Return true if the expansion succeeded. */ bool -force_expand_binop (enum machine_mode mode, optab binoptab, +force_expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods) { @@ -726,51 +782,12 @@ force_expand_binop (enum machine_mode mode, optab binoptab, return true; } -/* Generate insns for VEC_LSHIFT_EXPR, VEC_RSHIFT_EXPR. */ - -rtx -expand_vec_shift_expr (sepops ops, rtx target) -{ - struct expand_operand eops[3]; - enum insn_code icode; - rtx rtx_op1, rtx_op2; - enum machine_mode mode = TYPE_MODE (ops->type); - tree vec_oprnd = ops->op0; - tree shift_oprnd = ops->op1; - optab shift_optab; - - switch (ops->code) - { - case VEC_RSHIFT_EXPR: - shift_optab = vec_shr_optab; - break; - case VEC_LSHIFT_EXPR: - shift_optab = vec_shl_optab; - break; - default: - gcc_unreachable (); - } - - icode = optab_handler (shift_optab, mode); - gcc_assert (icode != CODE_FOR_nothing); - - rtx_op1 = expand_normal (vec_oprnd); - rtx_op2 = expand_normal (shift_oprnd); - - create_output_operand (&eops[0], target, mode); - create_input_operand (&eops[1], rtx_op1, GET_MODE (rtx_op1)); - create_convert_operand_from_type (&eops[2], rtx_op2, TREE_TYPE (shift_oprnd)); - expand_insn (icode, 3, eops); - - return eops[0].value; -} - /* Create a new vector value in VMODE with all elements set to OP. The mode of OP must be the element mode of VMODE. If OP is a constant, then the return value will be a constant. */ static rtx -expand_vector_broadcast (enum machine_mode vmode, rtx op) +expand_vector_broadcast (machine_mode vmode, rtx op) { enum insn_code icode; rtvec vec; @@ -836,7 +853,7 @@ expand_superword_shift (optab binoptab, rtx outof_input, rtx superword_op1, value are the same as for the parent routine. */ static bool -expand_subword_shift (enum machine_mode op1_mode, optab binoptab, +expand_subword_shift (machine_mode op1_mode, optab binoptab, rtx outof_input, rtx into_input, rtx op1, rtx outof_target, rtx into_target, int unsignedp, enum optab_methods methods, @@ -854,7 +871,8 @@ expand_subword_shift (enum machine_mode op1_mode, optab binoptab, if (CONSTANT_P (op1) || shift_mask >= BITS_PER_WORD) { carries = outof_input; - tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode); + tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD, + op1_mode), op1_mode); tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1, 0, true, methods); } @@ -869,13 +887,15 @@ expand_subword_shift (enum machine_mode op1_mode, optab binoptab, outof_input, const1_rtx, 0, unsignedp, methods); if (shift_mask == BITS_PER_WORD - 1) { - tmp = immed_double_const (-1, -1, op1_mode); + tmp = immed_wide_int_const + (wi::minus_one (GET_MODE_PRECISION (op1_mode)), op1_mode); tmp = simplify_expand_binop (op1_mode, xor_optab, op1, tmp, 0, true, methods); } else { - tmp = immed_double_const (BITS_PER_WORD - 1, 0, op1_mode); + tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD - 1, + op1_mode), op1_mode); tmp = simplify_expand_binop (op1_mode, sub_optab, tmp, op1, 0, true, methods); } @@ -917,7 +937,7 @@ expand_subword_shift (enum machine_mode op1_mode, optab binoptab, arguments are the same as the parent routine. */ static bool -expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab, +expand_doubleword_shift_condmove (machine_mode op1_mode, optab binoptab, enum rtx_code cmp_code, rtx cmp1, rtx cmp2, rtx outof_input, rtx into_input, rtx subword_op1, rtx superword_op1, @@ -1001,14 +1021,13 @@ expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab, Return true if the shift could be successfully synthesized. */ static bool -expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab, +expand_doubleword_shift (machine_mode op1_mode, optab binoptab, rtx outof_input, rtx into_input, rtx op1, rtx outof_target, rtx into_target, int unsignedp, enum optab_methods methods, unsigned HOST_WIDE_INT shift_mask) { rtx superword_op1, tmp, cmp1, cmp2; - rtx subword_label, done_label; enum rtx_code cmp_code; /* See if word-mode shifts by BITS_PER_WORD...BITS_PER_WORD * 2 - 1 will @@ -1038,7 +1057,7 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab, is true when the effective shift value is less than BITS_PER_WORD. Set SUPERWORD_OP1 to the shift count that should be used to shift OUTOF_INPUT into INTO_TARGET when the condition is false. */ - tmp = immed_double_const (BITS_PER_WORD, 0, op1_mode); + tmp = immed_wide_int_const (wi::shwi (BITS_PER_WORD, op1_mode), op1_mode); if (!CONSTANT_P (op1) && shift_mask == BITS_PER_WORD - 1) { /* Set CMP1 to OP1 & BITS_PER_WORD. The result is zero iff OP1 @@ -1080,7 +1099,7 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab, #ifdef HAVE_conditional_move /* Try using conditional moves to generate straight-line code. */ { - rtx start = get_last_insn (); + rtx_insn *start = get_last_insn (); if (expand_doubleword_shift_condmove (op1_mode, binoptab, cmp_code, cmp1, cmp2, outof_input, into_input, @@ -1093,8 +1112,8 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab, #endif /* As a last resort, use branches to select the correct alternative. */ - subword_label = gen_label_rtx (); - done_label = gen_label_rtx (); + rtx_code_label *subword_label = gen_label_rtx (); + rtx_code_label *done_label = gen_label_rtx (); NO_DEFER_POP; do_compare_rtx_and_jump (cmp1, cmp2, cmp_code, false, op1_mode, @@ -1176,7 +1195,7 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab, the 0 or -1. */ static rtx -expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, +expand_doubleword_mult (machine_mode mode, rtx op0, rtx op1, rtx target, bool umulp, enum optab_methods methods) { int low = (WORDS_BIG_ENDIAN ? 1 : 0); @@ -1284,7 +1303,7 @@ expand_doubleword_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, the operation to perform, not an optab pointer. All other arguments are the same. */ rtx -expand_simple_binop (enum machine_mode mode, enum rtx_code code, rtx op0, +expand_simple_binop (machine_mode mode, enum rtx_code code, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods) { @@ -1356,7 +1375,7 @@ commutative_optab_p (optab binoptab) register. Return X otherwise. UNSIGNEDP says whether X is unsigned. */ static rtx -avoid_expensive_constant (enum machine_mode mode, optab binoptab, +avoid_expensive_constant (machine_mode mode, optab binoptab, int opn, rtx x, bool unsignedp) { bool speed = optimize_insn_for_speed_p (); @@ -1384,17 +1403,17 @@ avoid_expensive_constant (enum machine_mode mode, optab binoptab, is an insn that directly implements the indicated operation. Returns null if this is not possible. */ static rtx -expand_binop_directly (enum machine_mode mode, optab binoptab, +expand_binop_directly (machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods, - rtx last) + rtx_insn *last) { - enum machine_mode from_mode = widened_mode (mode, op0, op1); + machine_mode from_mode = widened_mode (mode, op0, op1); enum insn_code icode = find_widening_optab_handler (binoptab, mode, from_mode, 1); - enum machine_mode xmode0 = insn_data[(int) icode].operand[1].mode; - enum machine_mode xmode1 = insn_data[(int) icode].operand[2].mode; - enum machine_mode mode0, mode1, tmp_mode; + machine_mode xmode0 = insn_data[(int) icode].operand[1].mode; + machine_mode xmode1 = insn_data[(int) icode].operand[2].mode; + machine_mode mode0, mode1, tmp_mode; struct expand_operand ops[3]; bool commutative_p; rtx pat; @@ -1480,8 +1499,9 @@ expand_binop_directly (enum machine_mode mode, optab binoptab, /* If PAT is composed of more than one insn, try to add an appropriate REG_EQUAL note to it. If we can't because TEMP conflicts with an operand, call expand_binop again, this time without a target. */ - if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX - && ! add_equal_note (pat, ops[0].value, optab_to_code (binoptab), + if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX + && ! add_equal_note (as_a <rtx_insn *> (pat), ops[0].value, + optab_to_code (binoptab), ops[1].value, ops[2].value)) { delete_insns_since (last); @@ -1508,18 +1528,18 @@ expand_binop_directly (enum machine_mode mode, optab binoptab, this may or may not be TARGET. */ rtx -expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, +expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods) { enum optab_methods next_methods = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN ? OPTAB_WIDEN : methods); enum mode_class mclass; - enum machine_mode wider_mode; + machine_mode wider_mode; rtx libfunc; rtx temp; - rtx entry_last = get_last_insn (); - rtx last; + rtx_insn *entry_last = get_last_insn (); + rtx_insn *last; mclass = GET_MODE_CLASS (mode); @@ -1715,7 +1735,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, && optab_handler (binoptab, word_mode) != CODE_FOR_nothing) { int i; - rtx insns; + rtx_insn *insns; /* If TARGET is the same as one of the operands, the REG_EQUAL note won't be accurate, so use a new target. */ @@ -1765,7 +1785,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing) { unsigned HOST_WIDE_INT shift_mask, double_shift_mask; - enum machine_mode op1_mode; + machine_mode op1_mode; double_shift_mask = targetm.shift_truncation_mask (mode); shift_mask = targetm.shift_truncation_mask (word_mode); @@ -1784,7 +1804,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, || (shift_mask == BITS_PER_WORD - 1 && double_shift_mask == BITS_PER_WORD * 2 - 1)) { - rtx insns; + rtx_insn *insns; rtx into_target, outof_target; rtx into_input, outof_input; int left_shift, outof_word; @@ -1836,7 +1856,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, && optab_handler (ashl_optab, word_mode) != CODE_FOR_nothing && optab_handler (lshr_optab, word_mode) != CODE_FOR_nothing) { - rtx insns; + rtx_insn *insns; rtx into_target, outof_target; rtx into_input, outof_input; rtx inter; @@ -2121,9 +2141,9 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, if (libfunc && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN)) { - rtx insns; + rtx_insn *insns; rtx op1x = op1; - enum machine_mode op1_mode = mode; + machine_mode op1_mode = mode; rtx value; start_sequence (); @@ -2243,7 +2263,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, of an unsigned wider operation, since the result would be the same. */ rtx -sign_expand_binop (enum machine_mode mode, optab uoptab, optab soptab, +sign_expand_binop (machine_mode mode, optab uoptab, optab soptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods) { @@ -2306,11 +2326,11 @@ int expand_twoval_unop (optab unoptab, rtx op0, rtx targ0, rtx targ1, int unsignedp) { - enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1); + machine_mode mode = GET_MODE (targ0 ? targ0 : targ1); enum mode_class mclass; - enum machine_mode wider_mode; - rtx entry_last = get_last_insn (); - rtx last; + machine_mode wider_mode; + rtx_insn *entry_last = get_last_insn (); + rtx_insn *last; mclass = GET_MODE_CLASS (mode); @@ -2380,11 +2400,11 @@ int expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1, int unsignedp) { - enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1); + machine_mode mode = GET_MODE (targ0 ? targ0 : targ1); enum mode_class mclass; - enum machine_mode wider_mode; - rtx entry_last = get_last_insn (); - rtx last; + machine_mode wider_mode; + rtx_insn *entry_last = get_last_insn (); + rtx_insn *last; mclass = GET_MODE_CLASS (mode); @@ -2400,8 +2420,8 @@ expand_twoval_binop (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1, { struct expand_operand ops[4]; enum insn_code icode = optab_handler (binoptab, mode); - enum machine_mode mode0 = insn_data[icode].operand[1].mode; - enum machine_mode mode1 = insn_data[icode].operand[2].mode; + machine_mode mode0 = insn_data[icode].operand[1].mode; + machine_mode mode1 = insn_data[icode].operand[2].mode; rtx xop0 = op0, xop1 = op1; /* If we are optimizing, force expensive constants into a register. */ @@ -2462,10 +2482,10 @@ bool expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1, rtx targ0, rtx targ1, enum rtx_code code) { - enum machine_mode mode; - enum machine_mode libval_mode; + machine_mode mode; + machine_mode libval_mode; rtx libval; - rtx insns; + rtx_insn *insns; rtx libfunc; /* Exactly one of TARG0 or TARG1 should be non-NULL. */ @@ -2502,7 +2522,7 @@ expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1, the operation to perform, not an optab pointer. All other arguments are the same. */ rtx -expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0, +expand_simple_unop (machine_mode mode, enum rtx_code code, rtx op0, rtx target, int unsignedp) { optab unop = code_to_optab (code); @@ -2519,19 +2539,20 @@ expand_simple_unop (enum machine_mode mode, enum rtx_code code, rtx op0, A similar operation can be used for clrsb. UNOPTAB says which operation we are trying to expand. */ static rtx -widen_leading (enum machine_mode mode, rtx op0, rtx target, optab unoptab) +widen_leading (machine_mode mode, rtx op0, rtx target, optab unoptab) { enum mode_class mclass = GET_MODE_CLASS (mode); if (CLASS_HAS_WIDER_MODES_P (mclass)) { - enum machine_mode wider_mode; + machine_mode wider_mode; for (wider_mode = GET_MODE_WIDER_MODE (mode); wider_mode != VOIDmode; wider_mode = GET_MODE_WIDER_MODE (wider_mode)) { if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) { - rtx xop0, temp, last; + rtx xop0, temp; + rtx_insn *last; last = get_last_insn (); @@ -2561,14 +2582,15 @@ widen_leading (enum machine_mode mode, rtx op0, rtx target, optab unoptab) /* Try calculating clz of a double-word quantity as two clz's of word-sized quantities, choosing which based on whether the high word is nonzero. */ static rtx -expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target) +expand_doubleword_clz (machine_mode mode, rtx op0, rtx target) { rtx xop0 = force_reg (mode, op0); rtx subhi = gen_highpart (word_mode, xop0); rtx sublo = gen_lowpart (word_mode, xop0); - rtx hi0_label = gen_label_rtx (); - rtx after_label = gen_label_rtx (); - rtx seq, temp, result; + rtx_code_label *hi0_label = gen_label_rtx (); + rtx_code_label *after_label = gen_label_rtx (); + rtx_insn *seq; + rtx temp, result; /* If we were not given a target, use a word_mode register, not a 'mode' register. The result will fit, and nobody is expecting @@ -2633,11 +2655,12 @@ expand_doubleword_clz (enum machine_mode mode, rtx op0, rtx target) as (lshiftrt:wide (bswap:wide x) ((width wide) - (width narrow))). */ static rtx -widen_bswap (enum machine_mode mode, rtx op0, rtx target) +widen_bswap (machine_mode mode, rtx op0, rtx target) { enum mode_class mclass = GET_MODE_CLASS (mode); - enum machine_mode wider_mode; - rtx x, last; + machine_mode wider_mode; + rtx x; + rtx_insn *last; if (!CLASS_HAS_WIDER_MODES_P (mclass)) return NULL_RTX; @@ -2678,7 +2701,7 @@ widen_bswap (enum machine_mode mode, rtx op0, rtx target) /* Try calculating bswap as two bswaps of two word-sized operands. */ static rtx -expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target) +expand_doubleword_bswap (machine_mode mode, rtx op, rtx target) { rtx t0, t1; @@ -2700,18 +2723,19 @@ expand_doubleword_bswap (enum machine_mode mode, rtx op, rtx target) /* Try calculating (parity x) as (and (popcount x) 1), where popcount can also be done in a wider mode. */ static rtx -expand_parity (enum machine_mode mode, rtx op0, rtx target) +expand_parity (machine_mode mode, rtx op0, rtx target) { enum mode_class mclass = GET_MODE_CLASS (mode); if (CLASS_HAS_WIDER_MODES_P (mclass)) { - enum machine_mode wider_mode; + machine_mode wider_mode; for (wider_mode = mode; wider_mode != VOIDmode; wider_mode = GET_MODE_WIDER_MODE (wider_mode)) { if (optab_handler (popcount_optab, wider_mode) != CODE_FOR_nothing) { - rtx xop0, temp, last; + rtx xop0, temp; + rtx_insn *last; last = get_last_insn (); @@ -2746,9 +2770,10 @@ expand_parity (enum machine_mode mode, rtx op0, rtx target) less convenient for expand_ffs anyway. */ static rtx -expand_ctz (enum machine_mode mode, rtx op0, rtx target) +expand_ctz (machine_mode mode, rtx op0, rtx target) { - rtx seq, temp; + rtx_insn *seq; + rtx temp; if (optab_handler (clz_optab, mode) == CODE_FOR_nothing) return 0; @@ -2788,11 +2813,12 @@ expand_ctz (enum machine_mode mode, rtx op0, rtx target) may have an undefined value in that case. If they do not give us a convenient value, we have to generate a test and branch. */ static rtx -expand_ffs (enum machine_mode mode, rtx op0, rtx target) +expand_ffs (machine_mode mode, rtx op0, rtx target) { HOST_WIDE_INT val = 0; bool defined_at_zero = false; - rtx temp, seq; + rtx temp; + rtx_insn *seq; if (optab_handler (ctz_optab, mode) != CODE_FOR_nothing) { @@ -2834,7 +2860,7 @@ expand_ffs (enum machine_mode mode, rtx op0, rtx target) the operation sets condition codes that can be recycled for this. (This is true on i386, for instance.) */ - rtx nonzero_label = gen_label_rtx (); + rtx_code_label *nonzero_label = gen_label_rtx (); emit_cmp_and_jump_insns (op0, CONST0_RTX (mode), NE, 0, mode, true, nonzero_label); @@ -2867,8 +2893,8 @@ expand_ffs (enum machine_mode mode, rtx op0, rtx target) register will work around the situation. */ static rtx -lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val, - enum machine_mode imode) +lowpart_subreg_maybe_copy (machine_mode omode, rtx val, + machine_mode imode) { rtx ret; ret = lowpart_subreg (omode, val, imode); @@ -2885,14 +2911,14 @@ lowpart_subreg_maybe_copy (enum machine_mode omode, rtx val, logical operation on the sign bit. */ static rtx -expand_absneg_bit (enum rtx_code code, enum machine_mode mode, +expand_absneg_bit (enum rtx_code code, machine_mode mode, rtx op0, rtx target) { const struct real_format *fmt; int bitpos, word, nwords, i; - enum machine_mode imode; - double_int mask; - rtx temp, insns; + machine_mode imode; + rtx temp; + rtx_insn *insns; /* The format has to have a simple sign bit. */ fmt = REAL_MODE_FORMAT (mode); @@ -2927,7 +2953,7 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode, nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD; } - mask = double_int_zero.set_bit (bitpos); + wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode)); if (code == ABS) mask = ~mask; @@ -2949,7 +2975,7 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode, { temp = expand_binop (imode, code == ABS ? and_optab : xor_optab, op0_piece, - immed_double_int_const (mask, imode), + immed_wide_int_const (mask, imode), targ_piece, 1, OPTAB_LIB_WIDEN); if (temp != targ_piece) emit_move_insn (targ_piece, temp); @@ -2967,7 +2993,7 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode, { temp = expand_binop (imode, code == ABS ? and_optab : xor_optab, gen_lowpart (imode, op0), - immed_double_int_const (mask, imode), + immed_wide_int_const (mask, imode), gen_lowpart (imode, target), 1, OPTAB_LIB_WIDEN); target = lowpart_subreg_maybe_copy (mode, temp, imode); @@ -2982,14 +3008,14 @@ expand_absneg_bit (enum rtx_code code, enum machine_mode mode, /* As expand_unop, but will fail rather than attempt the operation in a different mode or with a libcall. */ static rtx -expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target, +expand_unop_direct (machine_mode mode, optab unoptab, rtx op0, rtx target, int unsignedp) { if (optab_handler (unoptab, mode) != CODE_FOR_nothing) { struct expand_operand ops[2]; enum insn_code icode = optab_handler (unoptab, mode); - rtx last = get_last_insn (); + rtx_insn *last = get_last_insn (); rtx pat; create_output_operand (&ops[0], target, mode); @@ -2997,8 +3023,9 @@ expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target, pat = maybe_gen_insn (icode, 2, ops); if (pat) { - if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX - && ! add_equal_note (pat, ops[0].value, optab_to_code (unoptab), + if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX + && ! add_equal_note (as_a <rtx_insn *> (pat), ops[0].value, + optab_to_code (unoptab), ops[1].value, NULL_RTX)) { delete_insns_since (last); @@ -3025,11 +3052,11 @@ expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target, this may or may not be TARGET. */ rtx -expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, +expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target, int unsignedp) { enum mode_class mclass = GET_MODE_CLASS (mode); - enum machine_mode wider_mode; + machine_mode wider_mode; rtx temp; rtx libfunc; @@ -3074,7 +3101,8 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, be always more efficient than the other fallback methods. */ if (mode == HImode) { - rtx last, temp1, temp2; + rtx_insn *last; + rtx temp1, temp2; if (optab_handler (rotl_optab, mode) != CODE_FOR_nothing) { @@ -3132,7 +3160,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, if (optab_handler (unoptab, wider_mode) != CODE_FOR_nothing) { rtx xop0 = op0; - rtx last = get_last_insn (); + rtx_insn *last = get_last_insn (); /* For certain operations, we need not actually extend the narrow operand, as long as we will truncate the @@ -3171,7 +3199,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, && optab_handler (unoptab, word_mode) != CODE_FOR_nothing) { int i; - rtx insns; + rtx_insn *insns; if (target == 0 || target == op0 || !valid_multiword_target_p (target)) target = gen_reg_rtx (mode); @@ -3249,10 +3277,10 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, libfunc = optab_libfunc (unoptab, mode); if (libfunc) { - rtx insns; + rtx_insn *insns; rtx value; rtx eq_value; - enum machine_mode outmode = mode; + machine_mode outmode = mode; /* All of these functions return small values. Thus we choose to have them return something that isn't a double-word. */ @@ -3296,7 +3324,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, || optab_libfunc (unoptab, wider_mode)) { rtx xop0 = op0; - rtx last = get_last_insn (); + rtx_insn *last = get_last_insn (); /* For certain operations, we need not actually extend the narrow operand, as long as we will truncate the @@ -3379,7 +3407,7 @@ expand_unop (enum machine_mode mode, optab unoptab, rtx op0, rtx target, */ rtx -expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target, +expand_abs_nojump (machine_mode mode, rtx op0, rtx target, int result_unsignedp) { rtx temp; @@ -3406,7 +3434,7 @@ expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target, if (optab_handler (smax_optab, mode) != CODE_FOR_nothing && !HONOR_SIGNED_ZEROS (mode)) { - rtx last = get_last_insn (); + rtx_insn *last = get_last_insn (); temp = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab, op0, NULL_RTX, 0); @@ -3446,10 +3474,11 @@ expand_abs_nojump (enum machine_mode mode, rtx op0, rtx target, } rtx -expand_abs (enum machine_mode mode, rtx op0, rtx target, +expand_abs (machine_mode mode, rtx op0, rtx target, int result_unsignedp, int safe) { - rtx temp, op1; + rtx temp; + rtx_code_label *op1; if (GET_MODE_CLASS (mode) != MODE_INT || ! flag_trapv) @@ -3499,7 +3528,7 @@ expand_abs (enum machine_mode mode, rtx op0, rtx target, different but can be deduced from MODE. */ rtx -expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target) +expand_one_cmpl_abs_nojump (machine_mode mode, rtx op0, rtx target) { rtx temp; @@ -3510,7 +3539,7 @@ expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target) /* If we have a MAX insn, we can do this as MAX (x, ~x). */ if (optab_handler (smax_optab, mode) != CODE_FOR_nothing) { - rtx last = get_last_insn (); + rtx_insn *last = get_last_insn (); temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0); if (temp != 0) @@ -3550,12 +3579,13 @@ expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target) and not playing with subregs so much, will help the register allocator. */ static rtx -expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target, +expand_copysign_absneg (machine_mode mode, rtx op0, rtx op1, rtx target, int bitpos, bool op0_is_abs) { - enum machine_mode imode; + machine_mode imode; enum insn_code icode; - rtx sign, label; + rtx sign; + rtx_code_label *label; if (target == op1) target = NULL_RTX; @@ -3571,8 +3601,6 @@ expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target, } else { - double_int mask; - if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) { imode = int_mode_for_mode (mode); @@ -3593,10 +3621,9 @@ expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target, op1 = operand_subword_force (op1, word, mode); } - mask = double_int_zero.set_bit (bitpos); - + wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode)); sign = expand_binop (imode, and_optab, op1, - immed_double_int_const (mask, imode), + immed_wide_int_const (mask, imode), NULL_RTX, 1, OPTAB_LIB_WIDEN); } @@ -3636,13 +3663,13 @@ expand_copysign_absneg (enum machine_mode mode, rtx op0, rtx op1, rtx target, is true if op0 is known to have its sign bit clear. */ static rtx -expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target, +expand_copysign_bit (machine_mode mode, rtx op0, rtx op1, rtx target, int bitpos, bool op0_is_abs) { - enum machine_mode imode; - double_int mask; + machine_mode imode; int word, nwords, i; - rtx temp, insns; + rtx temp; + rtx_insn *insns; if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) { @@ -3664,7 +3691,7 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target, nwords = (GET_MODE_BITSIZE (mode) + BITS_PER_WORD - 1) / BITS_PER_WORD; } - mask = double_int_zero.set_bit (bitpos); + wide_int mask = wi::set_bit_in_zero (bitpos, GET_MODE_PRECISION (imode)); if (target == 0 || target == op0 @@ -3686,12 +3713,11 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target, if (!op0_is_abs) op0_piece = expand_binop (imode, and_optab, op0_piece, - immed_double_int_const (~mask, imode), + immed_wide_int_const (~mask, imode), NULL_RTX, 1, OPTAB_LIB_WIDEN); - op1 = expand_binop (imode, and_optab, operand_subword_force (op1, i, mode), - immed_double_int_const (mask, imode), + immed_wide_int_const (mask, imode), NULL_RTX, 1, OPTAB_LIB_WIDEN); temp = expand_binop (imode, ior_optab, op0_piece, op1, @@ -3711,13 +3737,13 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target, else { op1 = expand_binop (imode, and_optab, gen_lowpart (imode, op1), - immed_double_int_const (mask, imode), + immed_wide_int_const (mask, imode), NULL_RTX, 1, OPTAB_LIB_WIDEN); op0 = gen_lowpart (imode, op0); if (!op0_is_abs) op0 = expand_binop (imode, and_optab, op0, - immed_double_int_const (~mask, imode), + immed_wide_int_const (~mask, imode), NULL_RTX, 1, OPTAB_LIB_WIDEN); temp = expand_binop (imode, ior_optab, op0, op1, @@ -3735,7 +3761,7 @@ expand_copysign_bit (enum machine_mode mode, rtx op0, rtx op1, rtx target, rtx expand_copysign (rtx op0, rtx op1, rtx target) { - enum machine_mode mode = GET_MODE (op0); + machine_mode mode = GET_MODE (op0); const struct real_format *fmt; bool op0_is_abs; rtx temp; @@ -3799,8 +3825,10 @@ maybe_emit_unop_insn (enum insn_code icode, rtx target, rtx op0, if (!pat) return false; - if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX && code != UNKNOWN) - add_equal_note (pat, ops[0].value, code, ops[1].value, NULL_RTX); + if (INSN_P (pat) && NEXT_INSN (as_a <rtx_insn *> (pat)) != NULL_RTX + && code != UNKNOWN) + add_equal_note (as_a <rtx_insn *> (pat), ops[0].value, code, ops[1].value, + NULL_RTX); emit_insn (pat); @@ -3823,7 +3851,8 @@ emit_unop_insn (enum insn_code icode, rtx target, rtx op0, enum rtx_code code) struct no_conflict_data { - rtx target, first, insn; + rtx target; + rtx_insn *first, *insn; bool must_stay; }; @@ -3875,11 +3904,11 @@ no_conflict_move_test (rtx dest, const_rtx set, void *p0) note with an operand of EQUIV. */ static void -emit_libcall_block_1 (rtx insns, rtx target, rtx result, rtx equiv, +emit_libcall_block_1 (rtx_insn *insns, rtx target, rtx result, rtx equiv, bool equiv_may_trap) { rtx final_dest = target; - rtx next, last, insn; + rtx_insn *next, *last, *insn; /* If this is a reg with REG_USERVAR_P set, then it could possibly turn into a MEM later. Protect the libcall block from this change. */ @@ -3940,12 +3969,12 @@ emit_libcall_block_1 (rtx insns, rtx target, rtx result, rtx equiv, if (! data.must_stay) { if (PREV_INSN (insn)) - NEXT_INSN (PREV_INSN (insn)) = next; + SET_NEXT_INSN (PREV_INSN (insn)) = next; else insns = next; if (next) - PREV_INSN (next) = PREV_INSN (insn); + SET_PREV_INSN (next) = PREV_INSN (insn); add_insn (insn); } @@ -3975,7 +4004,8 @@ emit_libcall_block_1 (rtx insns, rtx target, rtx result, rtx equiv, void emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv) { - emit_libcall_block_1 (insns, target, result, equiv, false); + emit_libcall_block_1 (safe_as_a <rtx_insn *> (insns), + target, result, equiv, false); } /* Nonzero if we can perform a comparison of mode MODE straightforwardly. @@ -3987,7 +4017,7 @@ emit_libcall_block (rtx insns, rtx target, rtx result, rtx equiv) required to implement all (or any) of the unordered bcc operations. */ int -can_compare_p (enum rtx_code code, enum machine_mode mode, +can_compare_p (enum rtx_code code, machine_mode mode, enum can_compare_purpose purpose) { rtx test; @@ -4036,11 +4066,11 @@ can_compare_p (enum rtx_code code, enum machine_mode mode, static void prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, int unsignedp, enum optab_methods methods, - rtx *ptest, enum machine_mode *pmode) + rtx *ptest, machine_mode *pmode) { - enum machine_mode mode = *pmode; + machine_mode mode = *pmode; rtx libfunc, test; - enum machine_mode cmp_mode; + machine_mode cmp_mode; enum mode_class mclass; /* The other methods are not needed. */ @@ -4075,7 +4105,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, if (mode == BLKmode) { - enum machine_mode result_mode; + machine_mode result_mode; enum insn_code cmp_code; tree length_type; rtx libfunc; @@ -4151,8 +4181,11 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, if (GET_MODE_CLASS (mode) == MODE_CC) { - gcc_assert (can_compare_p (comparison, CCmode, ccp_jump)); - *ptest = gen_rtx_fmt_ee (comparison, VOIDmode, x, y); + enum insn_code icode = optab_handler (cbranch_optab, CCmode); + test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y); + gcc_assert (icode != CODE_FOR_nothing + && insn_operand_matches (icode, 0, test)); + *ptest = test; return; } @@ -4166,7 +4199,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, if (icode != CODE_FOR_nothing && insn_operand_matches (icode, 0, test)) { - rtx last = get_last_insn (); + rtx_insn *last = get_last_insn (); rtx op0 = prepare_operand (icode, x, 1, mode, cmp_mode, unsignedp); rtx op1 = prepare_operand (icode, y, 2, mode, cmp_mode, unsignedp); if (op0 && op1 @@ -4194,7 +4227,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, if (!SCALAR_FLOAT_MODE_P (mode)) { rtx result; - enum machine_mode ret_mode; + machine_mode ret_mode; /* Handle a libcall just for the mode we are using. */ libfunc = optab_libfunc (cmp_optab, mode); @@ -4234,7 +4267,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, y = const0_rtx; } - *pmode = word_mode; + *pmode = ret_mode; prepare_cmp_insn (x, y, comparison, NULL_RTX, unsignedp, methods, ptest, pmode); } @@ -4253,17 +4286,20 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, that it is accepted by the operand predicate. Return the new value. */ rtx -prepare_operand (enum insn_code icode, rtx x, int opnum, enum machine_mode mode, - enum machine_mode wider_mode, int unsignedp) +prepare_operand (enum insn_code icode, rtx x, int opnum, machine_mode mode, + machine_mode wider_mode, int unsignedp) { if (mode != wider_mode) x = convert_modes (wider_mode, mode, x, unsignedp); if (!insn_operand_matches (icode, opnum, x)) { + machine_mode op_mode = insn_data[(int) icode].operand[opnum].mode; if (reload_completed) return NULL_RTX; - x = copy_to_mode_reg (insn_data[(int) icode].operand[opnum].mode, x); + if (GET_MODE (x) != op_mode && GET_MODE (x) != VOIDmode) + return NULL_RTX; + x = copy_to_mode_reg (op_mode, x); } return x; @@ -4273,12 +4309,12 @@ prepare_operand (enum insn_code icode, rtx x, int opnum, enum machine_mode mode, we can do the branch. */ static void -emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label, int prob) +emit_cmp_and_jump_insn_1 (rtx test, machine_mode mode, rtx label, int prob) { - enum machine_mode optab_mode; + machine_mode optab_mode; enum mode_class mclass; enum insn_code icode; - rtx insn; + rtx_insn *insn; mclass = GET_MODE_CLASS (mode); optab_mode = (mclass == MODE_CC) ? CCmode : mode; @@ -4318,7 +4354,7 @@ emit_cmp_and_jump_insn_1 (rtx test, enum machine_mode mode, rtx label, int prob) void emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size, - enum machine_mode mode, int unsignedp, rtx label, + machine_mode mode, int unsignedp, rtx label, int prob) { rtx op0 = x, op1 = y; @@ -4352,14 +4388,15 @@ emit_cmp_and_jump_insns (rtx x, rtx y, enum rtx_code comparison, rtx size, static void prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison, - rtx *ptest, enum machine_mode *pmode) + rtx *ptest, machine_mode *pmode) { enum rtx_code swapped = swap_condition (comparison); enum rtx_code reversed = reverse_condition_maybe_unordered (comparison); - enum machine_mode orig_mode = GET_MODE (x); - enum machine_mode mode, cmp_mode; + machine_mode orig_mode = GET_MODE (x); + machine_mode mode, cmp_mode; rtx true_rtx, false_rtx; - rtx value, target, insns, equiv; + rtx value, target, equiv; + rtx_insn *insns; rtx libfunc = 0; bool reversed_p = false; cmp_mode = targetm.libgcc_cmp_return_mode (); @@ -4483,13 +4520,16 @@ prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison, /* Generate code to indirectly jump to a location given in the rtx LOC. */ void -emit_indirect_jump (rtx loc) +emit_indirect_jump (rtx loc ATTRIBUTE_UNUSED) { +#ifndef HAVE_indirect_jump + sorry ("indirect jumps are not available on this target"); +#else struct expand_operand ops[1]; - create_address_operand (&ops[0], loc); expand_jump_insn (CODE_FOR_indirect_jump, 1, ops); emit_barrier (); +#endif } #ifdef HAVE_conditional_move @@ -4510,10 +4550,11 @@ emit_indirect_jump (rtx loc) rtx emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, - enum machine_mode cmode, rtx op2, rtx op3, - enum machine_mode mode, int unsignedp) + machine_mode cmode, rtx op2, rtx op3, + machine_mode mode, int unsignedp) { - rtx tem, comparison, last; + rtx tem, comparison; + rtx_insn *last; enum insn_code icode; enum rtx_code reversed; @@ -4605,7 +4646,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, comparisons, and vice versa. How do we handle them? */ int -can_conditionally_move_p (enum machine_mode mode) +can_conditionally_move_p (machine_mode mode) { if (direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing) return 1; @@ -4631,10 +4672,11 @@ can_conditionally_move_p (enum machine_mode mode) rtx emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1, - enum machine_mode cmode, rtx op2, rtx op3, - enum machine_mode mode, int unsignedp) + machine_mode cmode, rtx op2, rtx op3, + machine_mode mode, int unsignedp) { - rtx tem, comparison, last; + rtx tem, comparison; + rtx_insn *last; enum insn_code icode; /* If one operand is constant, make it the second one. Only do this @@ -4845,28 +4887,13 @@ have_sub2_insn (rtx x, rtx y) return 1; } - -/* Generate the body of an instruction to copy Y into X. - It may be a list of insns, if one insn isn't enough. */ - -rtx -gen_move_insn (rtx x, rtx y) -{ - rtx seq; - - start_sequence (); - emit_move_insn_1 (x, y); - seq = get_insns (); - end_sequence (); - return seq; -} /* 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 (enum machine_mode to_mode, enum machine_mode from_mode, +can_extend_p (machine_mode to_mode, machine_mode from_mode, int unsignedp) { convert_optab tab; @@ -4883,8 +4910,8 @@ can_extend_p (enum machine_mode to_mode, enum machine_mode from_mode, into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */ rtx -gen_extend_insn (rtx x, rtx y, enum machine_mode mto, - enum machine_mode mfrom, int unsignedp) +gen_extend_insn (rtx x, rtx y, machine_mode mto, + machine_mode mfrom, int unsignedp) { enum insn_code icode = can_extend_p (mto, mfrom, unsignedp); return GEN_FCN (icode) (x, y); @@ -4900,7 +4927,7 @@ gen_extend_insn (rtx x, rtx y, enum machine_mode mto, an explicit FTRUNC insn before the fix insn; otherwise 0. */ static enum insn_code -can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode, +can_fix_p (machine_mode fixmode, machine_mode fltmode, int unsignedp, int *truncp_ptr) { convert_optab tab; @@ -4931,7 +4958,7 @@ can_fix_p (enum machine_mode fixmode, enum machine_mode fltmode, } enum insn_code -can_float_p (enum machine_mode fltmode, enum machine_mode fixmode, +can_float_p (machine_mode fltmode, machine_mode fixmode, int unsignedp) { convert_optab tab; @@ -4964,7 +4991,7 @@ supportable_convert_operation (enum tree_code code, tree vectype_out, tree vectype_in, tree *decl, enum tree_code *code1) { - enum machine_mode m1,m2; + machine_mode m1,m2; int truncp; m1 = TYPE_MODE (vectype_out); @@ -5005,7 +5032,7 @@ expand_float (rtx to, rtx from, int unsignedp) { enum insn_code icode; rtx target = to; - enum machine_mode fmode, imode; + machine_mode fmode, imode; bool can_do_signed = false; /* Crash now, because we won't be able to decide which mode to use. */ @@ -5058,7 +5085,7 @@ expand_float (rtx to, rtx from, int unsignedp) then unconditionally adjust the result. */ if (unsignedp && can_do_signed) { - rtx label = gen_label_rtx (); + rtx_code_label *label = gen_label_rtx (); rtx temp; REAL_VALUE_TYPE offset; @@ -5082,7 +5109,7 @@ expand_float (rtx to, rtx from, int unsignedp) < GET_MODE_PRECISION (GET_MODE (from))) { rtx temp1; - rtx neglabel = gen_label_rtx (); + rtx_code_label *neglabel = gen_label_rtx (); /* Don't use TARGET if it isn't a register, is a hard register, or is the wrong mode. */ @@ -5161,11 +5188,11 @@ expand_float (rtx to, rtx from, int unsignedp) /* No hardware instruction available; call a library routine. */ { rtx libfunc; - rtx insns; + rtx_insn *insns; rtx value; convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab; - if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode)) + if (GET_MODE_PRECISION (GET_MODE (from)) < GET_MODE_PRECISION (SImode)) from = convert_to_mode (SImode, from, unsignedp); libfunc = convert_optab_libfunc (tab, GET_MODE (to), GET_MODE (from)); @@ -5206,7 +5233,7 @@ expand_fix (rtx to, rtx from, int unsignedp) { enum insn_code icode; rtx target = to; - enum machine_mode fmode, imode; + machine_mode fmode, imode; int must_trunc = 0; /* We first try to find a pair of modes, one real and one integer, at @@ -5227,7 +5254,7 @@ expand_fix (rtx to, rtx from, int unsignedp) if (icode != CODE_FOR_nothing) { - rtx last = get_last_insn (); + rtx_insn *last = get_last_insn (); if (fmode != GET_MODE (from)) from = convert_to_mode (fmode, from, 0); @@ -5285,7 +5312,9 @@ expand_fix (rtx to, rtx from, int unsignedp) { int bitsize; REAL_VALUE_TYPE offset; - rtx limit, lab1, lab2, insn; + rtx limit; + rtx_code_label *lab1, *lab2; + rtx_insn *insn; bitsize = GET_MODE_PRECISION (GET_MODE (to)); real_2expN (&offset, bitsize - 1, fmode); @@ -5341,7 +5370,7 @@ expand_fix (rtx to, rtx from, int unsignedp) that the mode of TO is at least as wide as SImode, since those are the only library calls we know about. */ - if (GET_MODE_SIZE (GET_MODE (to)) < GET_MODE_SIZE (SImode)) + if (GET_MODE_PRECISION (GET_MODE (to)) < GET_MODE_PRECISION (SImode)) { target = gen_reg_rtx (SImode); @@ -5349,7 +5378,7 @@ expand_fix (rtx to, rtx from, int unsignedp) } else { - rtx insns; + rtx_insn *insns; rtx value; rtx libfunc; @@ -5386,12 +5415,13 @@ expand_fix (rtx to, rtx from, int unsignedp) void expand_fixed_convert (rtx to, rtx from, int uintp, int satp) { - enum machine_mode to_mode = GET_MODE (to); - enum machine_mode from_mode = GET_MODE (from); + machine_mode to_mode = GET_MODE (to); + machine_mode from_mode = GET_MODE (from); convert_optab tab; enum rtx_code this_code; enum insn_code code; - rtx insns, value; + rtx_insn *insns; + rtx value; rtx libfunc; if (to_mode == from_mode) @@ -5439,7 +5469,7 @@ expand_sfix_optab (rtx to, rtx from, convert_optab tab) { enum insn_code icode; rtx target = to; - enum machine_mode fmode, imode; + machine_mode fmode, imode; /* 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 @@ -5454,7 +5484,7 @@ expand_sfix_optab (rtx to, rtx from, convert_optab tab) icode = convert_optab_handler (tab, imode, fmode); if (icode != CODE_FOR_nothing) { - rtx last = get_last_insn (); + rtx_insn *last = get_last_insn (); if (fmode != GET_MODE (from)) from = convert_to_mode (fmode, from, 0); @@ -5478,7 +5508,7 @@ expand_sfix_optab (rtx to, rtx from, convert_optab tab) /* Report whether we have an instruction to perform the operation specified by CODE on operands of mode MODE. */ int -have_insn_for (enum rtx_code code, enum machine_mode mode) +have_insn_for (enum rtx_code code, machine_mode mode) { return (code_to_optab (code) && (optab_handler (code_to_optab (code), mode) @@ -5501,7 +5531,7 @@ have_insn_for (enum rtx_code code, enum machine_mode mode) static void gen_libfunc (optab optable, const char *opname, int suffix, - enum machine_mode mode) + machine_mode mode) { unsigned opname_len = strlen (opname); const char *mname = GET_MODE_NAME (mode); @@ -5537,16 +5567,20 @@ gen_libfunc (optab optable, const char *opname, int suffix, void gen_int_libfunc (optab optable, const char *opname, char suffix, - enum machine_mode mode) + 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 (GET_MODE_CLASS (mode) != MODE_INT - || GET_MODE_BITSIZE (mode) < BITS_PER_WORD + 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); @@ -5556,7 +5590,7 @@ gen_int_libfunc (optab optable, const char *opname, char suffix, void gen_fp_libfunc (optab optable, const char *opname, char suffix, - enum machine_mode mode) + machine_mode mode) { char *dec_opname; @@ -5577,7 +5611,7 @@ gen_fp_libfunc (optab optable, const char *opname, char suffix, void gen_fixed_libfunc (optab optable, const char *opname, char suffix, - enum machine_mode mode) + machine_mode mode) { if (!ALL_FIXED_POINT_MODE_P (mode)) return; @@ -5589,7 +5623,7 @@ gen_fixed_libfunc (optab optable, const char *opname, char suffix, void gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix, - enum machine_mode mode) + machine_mode mode) { if (!SIGNED_FIXED_POINT_MODE_P (mode)) return; @@ -5601,7 +5635,7 @@ gen_signed_fixed_libfunc (optab optable, const char *opname, char suffix, void gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix, - enum machine_mode mode) + machine_mode mode) { if (!UNSIGNED_FIXED_POINT_MODE_P (mode)) return; @@ -5612,7 +5646,7 @@ gen_unsigned_fixed_libfunc (optab optable, const char *opname, char suffix, void gen_int_fp_libfunc (optab optable, const char *name, char suffix, - enum machine_mode mode) + machine_mode mode) { if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT) gen_fp_libfunc (optable, name, suffix, mode); @@ -5625,7 +5659,7 @@ gen_int_fp_libfunc (optab optable, const char *name, char suffix, void gen_intv_fp_libfunc (optab optable, const char *name, char suffix, - enum machine_mode mode) + machine_mode mode) { if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT) gen_fp_libfunc (optable, name, suffix, mode); @@ -5645,7 +5679,7 @@ gen_intv_fp_libfunc (optab optable, const char *name, char suffix, void gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix, - enum machine_mode mode) + machine_mode mode) { if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT) gen_fp_libfunc (optable, name, suffix, mode); @@ -5660,7 +5694,7 @@ gen_int_fp_fixed_libfunc (optab optable, const char *name, char suffix, void gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix, - enum machine_mode mode) + machine_mode mode) { if (DECIMAL_FLOAT_MODE_P (mode) || GET_MODE_CLASS (mode) == MODE_FLOAT) gen_fp_libfunc (optable, name, suffix, mode); @@ -5675,7 +5709,7 @@ gen_int_fp_signed_fixed_libfunc (optab optable, const char *name, char suffix, void gen_int_fixed_libfunc (optab optable, const char *name, char suffix, - enum machine_mode mode) + machine_mode mode) { if (INTEGRAL_MODE_P (mode)) gen_int_libfunc (optable, name, suffix, mode); @@ -5688,7 +5722,7 @@ gen_int_fixed_libfunc (optab optable, const char *name, char suffix, void gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix, - enum machine_mode mode) + machine_mode mode) { if (INTEGRAL_MODE_P (mode)) gen_int_libfunc (optable, name, suffix, mode); @@ -5701,7 +5735,7 @@ gen_int_signed_fixed_libfunc (optab optable, const char *name, char suffix, void gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix, - enum machine_mode mode) + machine_mode mode) { if (INTEGRAL_MODE_P (mode)) gen_int_libfunc (optable, name, suffix, mode); @@ -5718,8 +5752,8 @@ gen_int_unsigned_fixed_libfunc (optab optable, const char *name, char suffix, void gen_interclass_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { size_t opname_len = strlen (opname); size_t mname_len = 0; @@ -5790,8 +5824,8 @@ gen_interclass_conv_libfunc (convert_optab tab, void gen_int_to_fp_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (GET_MODE_CLASS (fmode) != MODE_INT) return; @@ -5806,8 +5840,8 @@ gen_int_to_fp_conv_libfunc (convert_optab tab, void gen_ufloat_conv_libfunc (convert_optab tab, const char *opname ATTRIBUTE_UNUSED, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (DECIMAL_FLOAT_MODE_P (tmode)) gen_int_to_fp_conv_libfunc (tab, "floatuns", tmode, fmode); @@ -5821,8 +5855,8 @@ gen_ufloat_conv_libfunc (convert_optab tab, void gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (GET_MODE_CLASS (fmode) != MODE_INT) return; @@ -5837,8 +5871,8 @@ gen_int_to_fp_nondecimal_conv_libfunc (convert_optab tab, void gen_fp_to_int_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (GET_MODE_CLASS (fmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (fmode)) return; @@ -5853,7 +5887,7 @@ gen_fp_to_int_conv_libfunc (convert_optab tab, void gen_intraclass_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, enum machine_mode fmode) + machine_mode tmode, machine_mode fmode) { size_t opname_len = strlen (opname); size_t mname_len = 0; @@ -5924,8 +5958,8 @@ gen_intraclass_conv_libfunc (convert_optab tab, const char *opname, void gen_trunc_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode)) return; @@ -5953,8 +5987,8 @@ gen_trunc_conv_libfunc (convert_optab tab, void gen_extend_conv_libfunc (convert_optab tab, const char *opname ATTRIBUTE_UNUSED, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (GET_MODE_CLASS (tmode) != MODE_FLOAT && !DECIMAL_FLOAT_MODE_P (tmode)) return; @@ -5982,8 +6016,8 @@ gen_extend_conv_libfunc (convert_optab tab, void gen_fract_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (tmode == fmode) return; @@ -6001,8 +6035,8 @@ gen_fract_conv_libfunc (convert_optab tab, void gen_fractuns_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (tmode == fmode) return; @@ -6022,8 +6056,8 @@ gen_fractuns_conv_libfunc (convert_optab tab, void gen_satfract_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (tmode == fmode) return; @@ -6042,8 +6076,8 @@ gen_satfract_conv_libfunc (convert_optab tab, void gen_satfractuns_conv_libfunc (convert_optab tab, const char *opname, - enum machine_mode tmode, - enum machine_mode fmode) + machine_mode tmode, + machine_mode fmode) { if (tmode == fmode) return; @@ -6054,22 +6088,25 @@ gen_satfractuns_conv_libfunc (convert_optab tab, gen_interclass_conv_libfunc (tab, opname, tmode, fmode); } -/* A table of previously-created libfuncs, hashed by name. */ -static GTY ((param_is (union tree_node))) htab_t libfunc_decls; - /* Hashtable callbacks for libfunc_decls. */ -static hashval_t -libfunc_decl_hash (const void *entry) +struct libfunc_decl_hasher : ggc_hasher<tree> { - return IDENTIFIER_HASH_VALUE (DECL_NAME ((const_tree) entry)); -} + static hashval_t + hash (tree entry) + { + return IDENTIFIER_HASH_VALUE (DECL_NAME (entry)); + } -static int -libfunc_decl_eq (const void *entry1, const void *entry2) -{ - return DECL_NAME ((const_tree) entry1) == (const_tree) entry2; -} + 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. */ @@ -6097,18 +6134,16 @@ rtx init_one_libfunc (const char *name) { tree id, decl; - void **slot; hashval_t hash; if (libfunc_decls == NULL) - libfunc_decls = htab_create_ggc (37, libfunc_decl_hash, - libfunc_decl_eq, 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); - slot = htab_find_slot_with_hash (libfunc_decls, id, hash, INSERT); - decl = (tree) *slot; + 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 @@ -6125,12 +6160,11 @@ rtx set_user_assembler_libfunc (const char *name, const char *asmspec) { tree id, decl; - void **slot; hashval_t hash; id = get_identifier (name); hash = IDENTIFIER_HASH_VALUE (id); - slot = htab_find_slot_with_hash (libfunc_decls, id, hash, NO_INSERT); + tree *slot = libfunc_decls->find_slot_with_hash (id, hash, NO_INSERT); gcc_assert (slot); decl = (tree) *slot; set_user_assembler_name (decl, asmspec); @@ -6140,7 +6174,7 @@ set_user_assembler_libfunc (const char *name, const char *asmspec) /* 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, enum machine_mode mode, const char *name) +set_optab_libfunc (optab op, machine_mode mode, const char *name) { rtx val; struct libfunc_entry e; @@ -6154,9 +6188,9 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name) val = init_one_libfunc (name); else val = 0; - slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT); + slot = libfunc_hash->find_slot (&e, INSERT); if (*slot == NULL) - *slot = ggc_alloc_libfunc_entry (); + *slot = ggc_alloc<libfunc_entry> (); (*slot)->op = op; (*slot)->mode1 = mode; (*slot)->mode2 = VOIDmode; @@ -6167,8 +6201,8 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name) (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, enum machine_mode tmode, - enum machine_mode fmode, const char *name) +set_conv_libfunc (convert_optab optab, machine_mode tmode, + machine_mode fmode, const char *name) { rtx val; struct libfunc_entry e; @@ -6182,9 +6216,9 @@ set_conv_libfunc (convert_optab optab, enum machine_mode tmode, val = init_one_libfunc (name); else val = 0; - slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT); + slot = libfunc_hash->find_slot (&e, INSERT); if (*slot == NULL) - *slot = ggc_alloc_libfunc_entry (); + *slot = ggc_alloc<libfunc_entry> (); (*slot)->op = optab; (*slot)->mode1 = tmode; (*slot)->mode2 = fmode; @@ -6198,9 +6232,9 @@ void init_optabs (void) { if (libfunc_hash) - htab_empty (libfunc_hash); + libfunc_hash->empty (); else - libfunc_hash = htab_create_ggc (10, hash_libfunc, eq_libfunc, NULL); + libfunc_hash = hash_table<libfunc_hasher>::create_ggc (10); /* Fill in the optabs with the insns we support. */ init_all_optabs (this_fn_optabs); @@ -6277,8 +6311,7 @@ init_tree_optimization_optabs (tree optnode) if (tmp_optabs) memset (tmp_optabs, 0, sizeof (struct target_optabs)); else - tmp_optabs = (struct target_optabs *) - ggc_alloc_atomic (sizeof (struct target_optabs)); + tmp_optabs = ggc_alloc<target_optabs> (); /* Generate a new set of optabs into tmp_optabs. */ init_all_optabs (tmp_optabs); @@ -6299,7 +6332,7 @@ init_tree_optimization_optabs (tree optnode) static void init_sync_libfuncs_1 (optab tab, const char *base, int max) { - enum machine_mode mode; + machine_mode mode; char buf[64]; size_t len = strlen (base); int i; @@ -6359,7 +6392,7 @@ debug_optab_libfuncs (void) for (i = FIRST_NORM_OPTAB; i <= LAST_NORMLIB_OPTAB; ++i) for (j = 0; j < NUM_MACHINE_MODES; ++j) { - rtx l = optab_libfunc ((optab) i, (enum machine_mode) j); + rtx l = optab_libfunc ((optab) i, (machine_mode) j); if (l) { gcc_assert (GET_CODE (l) == SYMBOL_REF); @@ -6375,8 +6408,8 @@ debug_optab_libfuncs (void) for (j = 0; j < NUM_MACHINE_MODES; ++j) for (k = 0; k < NUM_MACHINE_MODES; ++k) { - rtx l = convert_optab_libfunc ((optab) i, (enum machine_mode) j, - (enum machine_mode) k); + rtx l = convert_optab_libfunc ((optab) i, (machine_mode) j, + (machine_mode) k); if (l) { gcc_assert (GET_CODE (l) == SYMBOL_REF); @@ -6396,7 +6429,7 @@ debug_optab_libfuncs (void) rtx gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode) { - enum machine_mode mode = GET_MODE (op1); + machine_mode mode = GET_MODE (op1); enum insn_code icode; rtx insn; rtx trap_rtx; @@ -6438,7 +6471,7 @@ gen_cond_trap (enum rtx_code code, rtx op1, rtx op2, rtx tcode) /* Return rtx code for TCODE. Use UNSIGNEDP to select signed or unsigned operation code. */ -static enum rtx_code +enum rtx_code get_rtx_code (enum tree_code tcode, bool unsignedp) { enum rtx_code code; @@ -6488,6 +6521,14 @@ get_rtx_code (enum tree_code tcode, bool unsignedp) code = LTGT; break; + case BIT_AND_EXPR: + code = AND; + break; + + case BIT_IOR_EXPR: + code = IOR; + break; + default: gcc_unreachable (); } @@ -6520,14 +6561,17 @@ 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 can be expanded using SIMD extensions - of the CPU. SEL may be NULL, which stands for an unknown constant. */ +/* 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 (enum machine_mode mode, bool variable, +can_vec_perm_p (machine_mode mode, bool variable, const unsigned char *sel) { - enum machine_mode qimode; + machine_mode qimode; /* If the target doesn't implement a vector mode for the vector type, then no operations are supported. */ @@ -6574,14 +6618,42 @@ can_vec_perm_p (enum machine_mode mode, bool variable, 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 + shift. */ +static rtx +shift_amt_for_vec_perm_mask (rtx sel) +{ + unsigned int i, first, nelt = GET_MODE_NUNITS (GET_MODE (sel)); + unsigned int bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (GET_MODE (sel))); + + if (GET_CODE (sel) != CONST_VECTOR) + return NULL_RTX; + + first = INTVAL (CONST_VECTOR_ELT (sel, 0)); + if (first >= 2*nelt) + return NULL_RTX; + for (i = 1; i < nelt; i++) + { + int idx = INTVAL (CONST_VECTOR_ELT (sel, i)); + unsigned int expected = (i + first) & (2 * nelt - 1); + /* Indices into the second vector are all equivalent. */ + if (idx < 0 || (MIN (nelt, (unsigned) idx) != MIN (nelt, expected))) + return NULL_RTX; + } + + return GEN_INT (first * bitsize); +} + /* A subroutine of expand_vec_perm for expanding one vec_perm insn. */ static rtx expand_vec_perm_1 (enum insn_code icode, rtx target, rtx v0, rtx v1, rtx sel) { - enum machine_mode tmode = GET_MODE (target); - enum machine_mode smode = GET_MODE (sel); + machine_mode tmode = GET_MODE (target); + machine_mode smode = GET_MODE (sel); struct expand_operand ops[4]; create_output_operand (&ops[0], target, tmode); @@ -6602,6 +6674,17 @@ expand_vec_perm_1 (enum insn_code icode, rtx target, else { create_input_operand (&ops[1], v0, tmode); + /* See if this can be handled with a vec_shr. We only do this if the + second vector is all zeroes. */ + enum insn_code shift_code = optab_handler (vec_shr_optab, GET_MODE (v0)); + if (v1 == CONST0_RTX (GET_MODE (v1)) && shift_code) + if (rtx shift_amt = shift_amt_for_vec_perm_mask (sel)) + { + create_convert_operand_from_type (&ops[2], shift_amt, + sizetype_tab[(int) stk_sizetype]); + if (maybe_expand_insn (shift_code, 3, ops)) + return ops[0].value; + } create_input_operand (&ops[2], v1, tmode); } @@ -6614,10 +6697,10 @@ expand_vec_perm_1 (enum insn_code icode, rtx target, and three operands. */ rtx -expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) +expand_vec_perm (machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) { enum insn_code icode; - enum machine_mode qimode; + machine_mode qimode; unsigned int i, w, e, u; rtx tmp, sel_qi = NULL; rtvec vec; @@ -6700,7 +6783,7 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) if (sel_qi == NULL) { /* Multiply each element by its byte size. */ - enum machine_mode selmode = GET_MODE (sel); + machine_mode selmode = GET_MODE (sel); if (u == 2) sel = expand_simple_binop (selmode, PLUS, sel, sel, sel, 0, OPTAB_DIRECT); @@ -6748,7 +6831,7 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */ static inline enum insn_code -get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns) +get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns) { enum insn_code icode = CODE_FOR_nothing; if (uns) @@ -6765,8 +6848,8 @@ get_vcond_icode (enum machine_mode vmode, enum machine_mode cmode, bool uns) bool expand_vec_cond_expr_p (tree value_type, tree cmp_op_type) { - enum machine_mode value_mode = TYPE_MODE (value_type); - enum machine_mode cmp_op_mode = TYPE_MODE (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), @@ -6785,8 +6868,8 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2, struct expand_operand ops[6]; enum insn_code icode; rtx comparison, rtx_op1, rtx_op2; - enum machine_mode mode = TYPE_MODE (vec_cond_type); - enum machine_mode cmp_op_mode; + machine_mode mode = TYPE_MODE (vec_cond_type); + machine_mode cmp_op_mode; bool unsignedp; tree op0a, op0b; enum tree_code tcode; @@ -6835,7 +6918,7 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2, 2 for even/odd widening, and 3 for hi/lo widening. */ int -can_mult_highpart_p (enum machine_mode mode, bool uns_p) +can_mult_highpart_p (machine_mode mode, bool uns_p) { optab op; unsigned char *sel; @@ -6884,13 +6967,13 @@ can_mult_highpart_p (enum machine_mode mode, bool uns_p) /* Expand a highpart multiply. */ rtx -expand_mult_highpart (enum machine_mode mode, rtx op0, rtx op1, +expand_mult_highpart (machine_mode mode, rtx op0, rtx op1, rtx target, bool uns_p) { struct expand_operand eops[3]; enum insn_code icode; int method, i, nunits; - enum machine_mode wmode; + machine_mode wmode; rtx m1, m2, perm; optab tab1, tab2; rtvec v; @@ -6959,10 +7042,10 @@ expand_mult_highpart (enum machine_mode mode, rtx op0, rtx op1, /* Return true if target supports vector masked load/store for mode. */ bool -can_vec_mask_load_store_p (enum machine_mode mode, bool is_load) +can_vec_mask_load_store_p (machine_mode mode, bool is_load) { optab op = is_load ? maskload_optab : maskstore_optab; - enum machine_mode vmode; + machine_mode vmode; unsigned int vector_sizes; /* If mode is vector mode, check it directly. */ @@ -6999,7 +7082,7 @@ can_vec_mask_load_store_p (enum machine_mode mode, bool is_load) /* Return true if there is a compare_and_swap pattern. */ bool -can_compare_and_swap_p (enum machine_mode mode, bool allow_libcall) +can_compare_and_swap_p (machine_mode mode, bool allow_libcall) { enum insn_code icode; @@ -7022,7 +7105,7 @@ can_compare_and_swap_p (enum machine_mode mode, bool allow_libcall) /* Return true if an atomic exchange can be performed. */ bool -can_atomic_exchange_p (enum machine_mode mode, bool allow_libcall) +can_atomic_exchange_p (machine_mode mode, bool allow_libcall) { enum insn_code icode; @@ -7066,8 +7149,9 @@ find_cc_set (rtx x, const_rtx pat, void *data) static bool expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq) { - enum machine_mode mode = GET_MODE (mem); - rtx label, cmp_reg, success, oldval; + machine_mode mode = GET_MODE (mem); + rtx_code_label *label; + rtx cmp_reg, success, oldval; /* The loop we want to generate looks like @@ -7115,7 +7199,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq) static rtx maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); enum insn_code icode; /* If the target supports the exchange directly, great. */ @@ -7145,9 +7229,9 @@ static rtx maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val, enum memmodel model) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); enum insn_code icode; - rtx last_insn = get_last_insn (); + rtx_insn *last_insn = get_last_insn (); icode = optab_handler (sync_lock_test_and_set_optab, mode); @@ -7201,7 +7285,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val, static rtx maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); if (can_compare_and_swap_p (mode, true)) { @@ -7226,7 +7310,7 @@ maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val) static rtx maybe_emit_atomic_test_and_set (rtx target, rtx mem, enum memmodel model) { - enum machine_mode pat_bool_mode; + machine_mode pat_bool_mode; struct expand_operand ops[3]; if (!HAVE_atomic_test_and_set) @@ -7293,7 +7377,7 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val) rtx expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); rtx ret, trueval, subtarget; ret = maybe_emit_atomic_test_and_set (target, mem, model); @@ -7388,7 +7472,7 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval, bool is_weak, enum memmodel succ_model, enum memmodel fail_model) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); struct expand_operand ops[8]; enum insn_code icode; rtx target_oval, target_bool = NULL_RTX; @@ -7409,7 +7493,7 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval, icode = direct_optab_handler (atomic_compare_and_swap_optab, mode); if (icode != CODE_FOR_nothing) { - enum machine_mode bool_mode = insn_data[icode].operand[0].mode; + machine_mode bool_mode = insn_data[icode].operand[0].mode; /* Make sure we always have a place for the bool operand. */ if (ptarget_bool == NULL @@ -7579,7 +7663,7 @@ expand_mem_signal_fence (enum memmodel model) rtx expand_atomic_load (rtx target, rtx mem, enum memmodel model) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); enum insn_code icode; /* If the target supports the load directly, great. */ @@ -7635,7 +7719,7 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model) rtx expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); enum insn_code icode; struct expand_operand ops[3]; @@ -7830,7 +7914,7 @@ static rtx maybe_emit_op (const struct atomic_op_functions *optab, rtx target, rtx mem, rtx val, bool use_memmodel, enum memmodel model, bool after) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); struct expand_operand ops[4]; enum insn_code icode; int op_counter = 0; @@ -7900,7 +7984,7 @@ expand_atomic_fetch_op_no_fallback (rtx target, rtx mem, rtx val, enum rtx_code code, enum memmodel model, bool after) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); struct atomic_op_functions optab; rtx result; bool unused_result = (target == const0_rtx); @@ -7989,7 +8073,7 @@ rtx expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code, enum memmodel model, bool after) { - enum machine_mode mode = GET_MODE (mem); + machine_mode mode = GET_MODE (mem); rtx result; bool unused_result = (target == const0_rtx); @@ -8061,7 +8145,7 @@ expand_atomic_fetch_op (rtx target, rtx mem, rtx val, enum rtx_code code, /* If nothing else has succeeded, default to a compare and swap loop. */ if (can_compare_and_swap_p (mode, true)) { - rtx insn; + rtx_insn *insn; rtx t0 = gen_reg_rtx (mode), t1; start_sequence (); @@ -8120,7 +8204,7 @@ insn_operand_matches (enum insn_code icode, unsigned int opno, rtx operand) bool valid_multiword_target_p (rtx target) { - enum machine_mode mode; + machine_mode mode; int i; mode = GET_MODE (target); @@ -8154,8 +8238,8 @@ maybe_legitimize_operand_same_code (enum insn_code icode, unsigned int opno, if (!(REG_P (addr) && REGNO (addr) > LAST_VIRTUAL_REGISTER) && !side_effects_p (addr)) { - rtx last; - enum machine_mode mode; + rtx_insn *last; + machine_mode mode; last = get_last_insn (); mode = get_address_mode (mem); @@ -8179,7 +8263,7 @@ static bool maybe_legitimize_operand (enum insn_code icode, unsigned int opno, struct expand_operand *op) { - enum machine_mode mode, imode; + machine_mode mode, imode; bool old_volatile_ok, result; mode = op->mode; @@ -8268,7 +8352,7 @@ bool maybe_legitimize_operands (enum insn_code icode, unsigned int opno, unsigned int nops, struct expand_operand *ops) { - rtx last; + rtx_insn *last; unsigned int i; last = get_last_insn (); @@ -8407,23 +8491,23 @@ enum extraction_type { ET_unaligned_mem, ET_reg }; static bool get_traditional_extraction_insn (extraction_insn *insn, enum extraction_type type, - enum machine_mode mode, + machine_mode mode, enum insn_code icode, int struct_op, int field_op) { const struct insn_data_d *data = &insn_data[icode]; - enum machine_mode struct_mode = data->operand[struct_op].mode; + machine_mode struct_mode = data->operand[struct_op].mode; if (struct_mode == VOIDmode) struct_mode = word_mode; if (mode != struct_mode) return false; - enum machine_mode field_mode = data->operand[field_op].mode; + machine_mode field_mode = data->operand[field_op].mode; if (field_mode == VOIDmode) field_mode = word_mode; - enum machine_mode pos_mode = data->operand[struct_op + 2].mode; + machine_mode pos_mode = data->operand[struct_op + 2].mode; if (pos_mode == VOIDmode) pos_mode = word_mode; @@ -8444,7 +8528,7 @@ get_traditional_extraction_insn (extraction_insn *insn, static bool get_optab_extraction_insn (struct extraction_insn *insn, enum extraction_type type, - enum machine_mode mode, direct_optab reg_optab, + 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); @@ -8471,7 +8555,7 @@ static bool get_extraction_insn (extraction_insn *insn, enum extraction_pattern pattern, enum extraction_type type, - enum machine_mode mode) + machine_mode mode) { switch (pattern) { @@ -8519,9 +8603,9 @@ get_best_extraction_insn (extraction_insn *insn, enum extraction_pattern pattern, enum extraction_type type, unsigned HOST_WIDE_INT struct_bits, - enum machine_mode field_mode) + machine_mode field_mode) { - enum machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT); + machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT); while (mode != VOIDmode) { if (get_extraction_insn (insn, pattern, type, mode)) @@ -8555,7 +8639,7 @@ bool get_best_reg_extraction_insn (extraction_insn *insn, enum extraction_pattern pattern, unsigned HOST_WIDE_INT struct_bits, - enum machine_mode field_mode) + machine_mode field_mode) { return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits, field_mode); @@ -8574,7 +8658,7 @@ bool get_best_mem_extraction_insn (extraction_insn *insn, enum extraction_pattern pattern, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum, - enum machine_mode field_mode) + machine_mode field_mode) { unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT + bitsize @@ -8584,4 +8668,31 @@ get_best_mem_extraction_insn (extraction_insn *insn, 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), + speed_p); + cheap[speed_p] = cost < COSTS_N_INSNS (3); + init[speed_p] = true; + } + + return cheap[speed_p]; +} + #include "gt-optabs.h" |