X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Foptabs.c;h=49e1c531c65dd95e0f0d040141952071d0d01a4f;hb=ff1bedacc81800f47632971f6474e4e2f9cfb86f;hp=7ee84c4348c96a49e3749581b889364680ed292b;hpb=79d652a570805345efea0ee370c0f7f07eada78c;p=gcc.git diff --git a/gcc/optabs.c b/gcc/optabs.c index 7ee84c4348c..49e1c531c65 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)); @@ -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; @@ -301,8 +320,8 @@ widened_mode (enum machine_mode to_mode, rtx op0, rtx op1) TO_MODE and a FROM_MODE. */ enum insn_code -widening_optab_handler (optab op, enum machine_mode to_mode, - enum machine_mode from_mode) +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) @@ -323,10 +342,10 @@ widening_optab_handler (optab op, enum machine_mode to_mode, 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) @@ -354,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; @@ -368,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 @@ -505,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) ? @@ -607,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. @@ -635,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); @@ -694,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]; @@ -716,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) { @@ -735,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) { @@ -748,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; @@ -858,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, @@ -934,7 +929,6 @@ expand_subword_shift (enum machine_mode op1_mode, optab binoptab, } -#ifdef HAVE_conditional_move /* Try implementing expand_doubleword_shift using conditional moves. The shift is by < BITS_PER_WORD if (CMP_CODE CMP1 CMP2) is true, otherwise it is by >= BITS_PER_WORD. SUBWORD_OP1 and SUPERWORD_OP1 @@ -942,7 +936,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, @@ -994,7 +988,6 @@ expand_doubleword_shift_condmove (enum machine_mode op1_mode, optab binoptab, return true; } -#endif /* Expand a doubleword shift (ashl, ashr or lshr) using word-mode shifts. OUTOF_INPUT and INTO_INPUT are the two word-sized halves of the first @@ -1026,14 +1019,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 @@ -1102,24 +1094,23 @@ expand_doubleword_shift (enum machine_mode op1_mode, optab binoptab, unsignedp, methods, shift_mask); } -#ifdef HAVE_conditional_move /* Try using conditional moves to generate straight-line code. */ - { - rtx start = get_last_insn (); - if (expand_doubleword_shift_condmove (op1_mode, binoptab, - cmp_code, cmp1, cmp2, - outof_input, into_input, - op1, superword_op1, - outof_target, into_target, - unsignedp, methods, shift_mask)) - return true; - delete_insns_since (start); - } -#endif + if (HAVE_conditional_move) + { + rtx_insn *start = get_last_insn (); + if (expand_doubleword_shift_condmove (op1_mode, binoptab, + cmp_code, cmp1, cmp2, + outof_input, into_input, + op1, superword_op1, + outof_target, into_target, + unsignedp, methods, shift_mask)) + return true; + delete_insns_since (start); + } /* 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, @@ -1201,7 +1192,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); @@ -1309,7 +1300,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) { @@ -1381,7 +1372,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 (); @@ -1409,22 +1400,21 @@ 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; + rtx_insn *pat; rtx xop0 = op0, xop1 = op1; - rtx swap; /* If it is a commutative operator and the modes would match if we would swap the operands, we can save the conversions. */ @@ -1432,11 +1422,7 @@ expand_binop_directly (enum machine_mode mode, optab binoptab, if (commutative_p && GET_MODE (xop0) != xmode0 && GET_MODE (xop1) != xmode1 && GET_MODE (xop0) == xmode1 && GET_MODE (xop1) == xmode1) - { - swap = xop0; - xop0 = xop1; - xop1 = swap; - } + std::swap (xop0, xop1); /* If we are optimizing, force expensive constants into a register. */ xop0 = avoid_expensive_constant (xmode0, binoptab, 0, xop0, unsignedp); @@ -1469,11 +1455,7 @@ expand_binop_directly (enum machine_mode mode, optab binoptab, Also try to make the last operand a constant. */ if (commutative_p && swap_commutative_operands_with_target (target, xop0, xop1)) - { - swap = xop1; - xop1 = xop0; - xop0 = swap; - } + std::swap (xop0, xop1); /* Now, if insn's predicates don't allow our operands, put them into pseudo regs. */ @@ -1506,7 +1488,8 @@ expand_binop_directly (enum machine_mode mode, optab binoptab, 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), + && ! add_equal_note (pat, ops[0].value, + optab_to_code (binoptab), ops[1].value, ops[2].value)) { delete_insns_since (last); @@ -1533,18 +1516,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); @@ -1727,11 +1710,7 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1, Also try to make the last operand a constant. */ if (commutative_optab_p (binoptab) && swap_commutative_operands_with_target (target, op0, op1)) - { - temp = op1; - op1 = op0; - op0 = temp; - } + std::swap (op0, op1); /* These can be done a word at a time. */ if ((binoptab == and_optab || binoptab == ior_optab || binoptab == xor_optab) @@ -1740,7 +1719,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. */ @@ -1790,7 +1769,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); @@ -1809,7 +1788,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; @@ -1861,7 +1840,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; @@ -2146,9 +2125,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 (); @@ -2268,7 +2247,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) { @@ -2331,11 +2310,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); @@ -2405,11 +2384,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); @@ -2425,8 +2404,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. */ @@ -2487,10 +2466,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. */ @@ -2527,7 +2506,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); @@ -2544,19 +2523,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 (); @@ -2586,14 +2566,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 @@ -2658,11 +2639,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; @@ -2703,7 +2685,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; @@ -2725,18 +2707,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 (); @@ -2771,9 +2754,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; @@ -2813,11 +2797,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) { @@ -2859,7 +2844,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); @@ -2892,8 +2877,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); @@ -2910,13 +2895,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; - 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); @@ -3006,15 +2992,15 @@ 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 pat; + rtx_insn *last = get_last_insn (); + rtx_insn *pat; create_output_operand (&ops[0], target, mode); create_convert_operand_from (&ops[1], op0, mode, unsignedp); @@ -3022,7 +3008,8 @@ expand_unop_direct (enum machine_mode mode, optab unoptab, rtx op0, rtx target, if (pat) { if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX - && ! add_equal_note (pat, ops[0].value, optab_to_code (unoptab), + && ! add_equal_note (pat, ops[0].value, + optab_to_code (unoptab), ops[1].value, NULL_RTX)) { delete_insns_since (last); @@ -3049,11 +3036,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; @@ -3098,7 +3085,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) { @@ -3156,7 +3144,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 @@ -3195,7 +3183,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); @@ -3273,10 +3261,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. */ @@ -3320,7 +3308,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 @@ -3403,7 +3391,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; @@ -3430,7 +3418,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); @@ -3470,10 +3458,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) @@ -3503,7 +3492,7 @@ expand_abs (enum machine_mode mode, rtx op0, rtx target, NO_DEFER_POP; do_compare_rtx_and_jump (target, CONST0_RTX (mode), GE, 0, mode, - NULL_RTX, NULL_RTX, op1, -1); + NULL_RTX, NULL, op1, -1); op0 = expand_unop (mode, result_unsignedp ? neg_optab : negv_optab, target, target, 0); @@ -3523,7 +3512,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; @@ -3534,7 +3523,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) @@ -3574,12 +3563,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; @@ -3657,12 +3647,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; + machine_mode imode; int word, nwords, i; - rtx temp, insns; + rtx temp; + rtx_insn *insns; if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD) { @@ -3754,7 +3745,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; @@ -3810,7 +3801,7 @@ maybe_emit_unop_insn (enum insn_code icode, rtx target, rtx op0, enum rtx_code code) { struct expand_operand ops[2]; - rtx pat; + rtx_insn *pat; create_output_operand (&ops[0], target, GET_MODE (target)); create_input_operand (&ops[1], op0, GET_MODE (op0)); @@ -3818,7 +3809,8 @@ 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) + if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX + && code != UNKNOWN) add_equal_note (pat, ops[0].value, code, ops[1].value, NULL_RTX); emit_insn (pat); @@ -3842,7 +3834,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; }; @@ -3894,11 +3887,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. */ @@ -3959,12 +3952,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); } @@ -3994,7 +3987,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 (insns), + target, result, equiv, false); } /* Nonzero if we can perform a comparison of mode MODE straightforwardly. @@ -4006,7 +4000,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; @@ -4055,11 +4049,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. */ @@ -4077,7 +4071,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, > COSTS_N_INSNS (1))) y = force_reg (mode, y); -#ifdef HAVE_cc0 +#if HAVE_cc0 /* Make sure if we have a canonical comparison. The RTL documentation states that canonical comparisons are required only for targets which have cc0. */ @@ -4094,7 +4088,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; @@ -4170,8 +4164,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; } @@ -4185,7 +4182,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 @@ -4213,7 +4210,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); @@ -4253,7 +4250,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); } @@ -4272,17 +4269,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; @@ -4292,12 +4292,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; @@ -4337,7 +4337,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; @@ -4371,14 +4371,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 (); @@ -4502,16 +4503,18 @@ 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 /* Emit a conditional move instruction if the machine supports one for that condition and machine mode. @@ -4529,10 +4532,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 comparison; + rtx_insn *last; enum insn_code icode; enum rtx_code reversed; @@ -4541,9 +4545,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, if (swap_commutative_operands_p (op0, op1)) { - tem = op0; - op0 = op1; - op1 = tem; + std::swap (op0, op1); code = swap_condition (code); } @@ -4562,9 +4564,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, && ((reversed = reversed_comparison_code_parts (code, op0, op1, NULL)) != UNKNOWN)) { - tem = op2; - op2 = op3; - op3 = tem; + std::swap (op2, op3); code = reversed; } @@ -4624,7 +4624,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; @@ -4632,8 +4632,6 @@ can_conditionally_move_p (enum machine_mode mode) return 0; } -#endif /* HAVE_conditional_move */ - /* Emit a conditional addition instruction if the machine supports one for that condition and machine mode. @@ -4650,10 +4648,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 comparison; + rtx_insn *last; enum insn_code icode; /* If one operand is constant, make it the second one. Only do this @@ -4661,9 +4660,7 @@ emit_conditional_add (rtx target, enum rtx_code code, rtx op0, rtx op1, if (swap_commutative_operands_p (op0, op1)) { - tem = op0; - op0 = op1; - op1 = tem; + std::swap (op0, op1); code = swap_condition (code); } @@ -4864,28 +4861,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; @@ -4902,8 +4884,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); @@ -4919,7 +4901,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; @@ -4950,7 +4932,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; @@ -4983,7 +4965,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); @@ -5024,7 +5006,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. */ @@ -5077,7 +5059,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; @@ -5101,7 +5083,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. */ @@ -5180,11 +5162,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)); @@ -5225,7 +5207,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 @@ -5246,7 +5228,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); @@ -5304,7 +5286,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); @@ -5360,7 +5344,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); @@ -5368,7 +5352,7 @@ expand_fix (rtx to, rtx from, int unsignedp) } else { - rtx insns; + rtx_insn *insns; rtx value; rtx libfunc; @@ -5405,12 +5389,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) @@ -5458,7 +5443,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 @@ -5473,7 +5458,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); @@ -5497,7 +5482,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) @@ -5520,7 +5505,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); @@ -5556,16 +5541,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); @@ -5575,7 +5564,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; @@ -5596,7 +5585,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; @@ -5608,7 +5597,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; @@ -5620,7 +5609,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; @@ -5631,7 +5620,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); @@ -5644,7 +5633,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); @@ -5664,7 +5653,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); @@ -5679,7 +5668,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); @@ -5694,7 +5683,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); @@ -5707,7 +5696,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); @@ -5720,7 +5709,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); @@ -5737,8 +5726,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; @@ -5809,8 +5798,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; @@ -5825,8 +5814,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); @@ -5840,8 +5829,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; @@ -5856,8 +5845,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; @@ -5872,7 +5861,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; @@ -5943,8 +5932,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; @@ -5972,8 +5961,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; @@ -6001,8 +5990,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; @@ -6020,8 +6009,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; @@ -6041,8 +6030,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; @@ -6061,8 +6050,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; @@ -6073,22 +6062,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 { - 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_decls; /* Build a decl for a libfunc named NAME. */ @@ -6116,18 +6108,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::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 @@ -6144,12 +6134,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); @@ -6159,7 +6148,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; @@ -6173,7 +6162,7 @@ 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 (); (*slot)->op = op; @@ -6186,8 +6175,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; @@ -6201,7 +6190,7 @@ 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 (); (*slot)->op = optab; @@ -6217,9 +6206,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::create_ggc (10); /* Fill in the optabs with the insns we support. */ init_all_optabs (this_fn_optabs); @@ -6317,7 +6306,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; @@ -6377,7 +6366,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); @@ -6393,8 +6382,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); @@ -6414,7 +6403,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; @@ -6456,7 +6445,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; @@ -6506,6 +6495,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 (); } @@ -6521,31 +6518,44 @@ vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1, { struct expand_operand ops[2]; rtx rtx_op0, rtx_op1; + machine_mode m0, m1; enum rtx_code rcode = get_rtx_code (tcode, unsignedp); gcc_assert (TREE_CODE_CLASS (tcode) == tcc_comparison); - /* Expand operands. */ + /* Expand operands. For vector types with scalar modes, e.g. where int64x1_t + has mode DImode, this can produce a constant RTX of mode VOIDmode; in such + cases, use the original mode. */ rtx_op0 = expand_expr (t_op0, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op0)), EXPAND_STACK_PARM); + m0 = GET_MODE (rtx_op0); + if (m0 == VOIDmode) + m0 = TYPE_MODE (TREE_TYPE (t_op0)); + rtx_op1 = expand_expr (t_op1, NULL_RTX, TYPE_MODE (TREE_TYPE (t_op1)), EXPAND_STACK_PARM); + m1 = GET_MODE (rtx_op1); + if (m1 == VOIDmode) + m1 = TYPE_MODE (TREE_TYPE (t_op1)); - create_input_operand (&ops[0], rtx_op0, GET_MODE (rtx_op0)); - create_input_operand (&ops[1], rtx_op1, GET_MODE (rtx_op1)); + create_input_operand (&ops[0], rtx_op0, m0); + create_input_operand (&ops[1], rtx_op1, m1); if (!maybe_legitimize_operands (icode, 4, 2, ops)) gcc_unreachable (); 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. */ @@ -6592,14 +6602,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); @@ -6620,6 +6658,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); } @@ -6632,10 +6681,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; @@ -6718,14 +6767,14 @@ 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); + NULL, 0, OPTAB_DIRECT); else sel = expand_simple_binop (selmode, ASHIFT, sel, GEN_INT (exact_log2 (u)), - sel, 0, OPTAB_DIRECT); + NULL, 0, OPTAB_DIRECT); gcc_assert (sel != NULL); /* Broadcast the low byte each element into each of its bytes. */ @@ -6766,7 +6815,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) @@ -6783,8 +6832,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), @@ -6803,8 +6852,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; @@ -6853,7 +6902,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; @@ -6902,13 +6951,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; @@ -6977,10 +7026,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. */ @@ -7017,7 +7066,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; @@ -7040,7 +7089,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; @@ -7084,8 +7133,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 @@ -7112,7 +7162,7 @@ expand_compare_and_swap_loop (rtx mem, rtx old_reg, rtx new_reg, rtx seq) success = NULL_RTX; oldval = cmp_reg; if (!expand_atomic_compare_and_swap (&success, &oldval, mem, old_reg, - new_reg, false, MEMMODEL_SEQ_CST, + new_reg, false, MEMMODEL_SYNC_SEQ_CST, MEMMODEL_RELAXED)) return false; @@ -7133,7 +7183,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. */ @@ -7163,9 +7213,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); @@ -7173,9 +7223,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val, exists, and the memory model is stronger than acquire, add a release barrier before the instruction. */ - if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST - || (model & MEMMODEL_MASK) == MEMMODEL_RELEASE - || (model & MEMMODEL_MASK) == MEMMODEL_ACQ_REL) + if (is_mm_seq_cst (model) || is_mm_release (model) || is_mm_acq_rel (model)) expand_mem_thread_fence (model); if (icode != CODE_FOR_nothing) @@ -7219,7 +7267,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)) { @@ -7244,7 +7292,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) @@ -7282,11 +7330,12 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val) rtx ret; /* Try an atomic_exchange first. */ - ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_ACQUIRE); + ret = maybe_emit_atomic_exchange (target, mem, val, MEMMODEL_SYNC_ACQUIRE); if (ret) return ret; - ret = maybe_emit_sync_lock_test_and_set (target, mem, val, MEMMODEL_ACQUIRE); + ret = maybe_emit_sync_lock_test_and_set (target, mem, val, + MEMMODEL_SYNC_ACQUIRE); if (ret) return ret; @@ -7297,7 +7346,7 @@ expand_sync_lock_test_and_set (rtx target, rtx mem, rtx val) /* If there are no other options, try atomic_test_and_set if the value being stored is 1. */ if (val == const1_rtx) - ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_ACQUIRE); + ret = maybe_emit_atomic_test_and_set (target, mem, MEMMODEL_SYNC_ACQUIRE); return ret; } @@ -7311,7 +7360,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); @@ -7352,7 +7401,10 @@ expand_atomic_test_and_set (rtx target, rtx mem, enum memmodel model) perform the operation. */ if (!ret) { - emit_move_insn (subtarget, mem); + /* If the result is ignored skip the move to target. */ + if (subtarget != const0_rtx) + emit_move_insn (subtarget, mem); + emit_move_insn (mem, trueval); ret = subtarget; } @@ -7403,7 +7455,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; @@ -7424,7 +7476,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 @@ -7537,21 +7589,12 @@ expand_asm_memory_barrier (void) /* This routine will either emit the mem_thread_fence pattern or issue a sync_synchronize to generate a fence for memory model MEMMODEL. */ -#ifndef HAVE_mem_thread_fence -# define HAVE_mem_thread_fence 0 -# define gen_mem_thread_fence(x) (gcc_unreachable (), NULL_RTX) -#endif -#ifndef HAVE_memory_barrier -# define HAVE_memory_barrier 0 -# define gen_memory_barrier() (gcc_unreachable (), NULL_RTX) -#endif - void expand_mem_thread_fence (enum memmodel model) { if (HAVE_mem_thread_fence) emit_insn (gen_mem_thread_fence (GEN_INT (model))); - else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED) + else if (!is_mm_relaxed (model)) { if (HAVE_memory_barrier) emit_insn (gen_memory_barrier ()); @@ -7565,17 +7608,12 @@ expand_mem_thread_fence (enum memmodel model) /* This routine will either emit the mem_signal_fence pattern or issue a sync_synchronize to generate a fence for memory model MEMMODEL. */ -#ifndef HAVE_mem_signal_fence -# define HAVE_mem_signal_fence 0 -# define gen_mem_signal_fence(x) (gcc_unreachable (), NULL_RTX) -#endif - void expand_mem_signal_fence (enum memmodel model) { if (HAVE_mem_signal_fence) emit_insn (gen_mem_signal_fence (GEN_INT (model))); - else if ((model & MEMMODEL_MASK) != MEMMODEL_RELAXED) + else if (!is_mm_relaxed (model)) { /* By default targets are coherent between a thread and the signal handler running on the same thread. Thus this really becomes a @@ -7594,7 +7632,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. */ @@ -7630,7 +7668,7 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model) target = gen_reg_rtx (mode); /* For SEQ_CST, emit a barrier before the load. */ - if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST) + if (is_mm_seq_cst (model)) expand_mem_thread_fence (model); emit_move_insn (target, mem); @@ -7650,7 +7688,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]; @@ -7676,7 +7714,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release) if (maybe_expand_insn (icode, 2, ops)) { /* lock_release is only a release barrier. */ - if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST) + if (is_mm_seq_cst (model)) expand_mem_thread_fence (model); return const0_rtx; } @@ -7703,7 +7741,7 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release) emit_move_insn (mem, val); /* For SEQ_CST, also emit a barrier after the store. */ - if ((model & MEMMODEL_MASK) == MEMMODEL_SEQ_CST) + if (is_mm_seq_cst (model)) expand_mem_thread_fence (model); return const0_rtx; @@ -7845,7 +7883,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; @@ -7915,7 +7953,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); @@ -8004,7 +8042,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); @@ -8076,7 +8114,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 (); @@ -8135,7 +8173,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); @@ -8169,8 +8207,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); @@ -8194,7 +8232,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; @@ -8283,7 +8321,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 (); @@ -8301,13 +8339,13 @@ maybe_legitimize_operands (enum insn_code icode, unsigned int opno, and emit any necessary set-up code. Return null and emit no code on failure. */ -rtx +rtx_insn * maybe_gen_insn (enum insn_code icode, unsigned int nops, struct expand_operand *ops) { gcc_assert (nops == (unsigned int) insn_data[(int) icode].n_generator_args); if (!maybe_legitimize_operands (icode, 0, nops, ops)) - return NULL_RTX; + return NULL; switch (nops) { @@ -8422,23 +8460,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; @@ -8459,7 +8497,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); @@ -8486,7 +8524,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) { @@ -8534,9 +8572,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)) @@ -8570,7 +8608,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); @@ -8589,7 +8627,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 @@ -8599,4 +8637,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"