diff options
author | kan <kan@FreeBSD.org> | 2004-07-28 03:36:15 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2004-07-28 03:36:15 +0000 |
commit | a8af68176bc97f1aaf1b1fe3fbc63e7d3b1060fa (patch) | |
tree | 3a42ef9639df1cf775ca0695799e9af1137c9687 /contrib/gcc/config | |
parent | fbaf45f3c243ef423c218b7c44fc622ecff27c1f (diff) | |
download | FreeBSD-src-a8af68176bc97f1aaf1b1fe3fbc63e7d3b1060fa.zip FreeBSD-src-a8af68176bc97f1aaf1b1fe3fbc63e7d3b1060fa.tar.gz |
Use stock GCC versions on these files.
Diffstat (limited to 'contrib/gcc/config')
-rw-r--r-- | contrib/gcc/config/alpha/alpha.c | 2906 | ||||
-rw-r--r-- | contrib/gcc/config/i386/i386.md | 5228 |
2 files changed, 4493 insertions, 3641 deletions
diff --git a/contrib/gcc/config/alpha/alpha.c b/contrib/gcc/config/alpha/alpha.c index 42b57e1..0086968 100644 --- a/contrib/gcc/config/alpha/alpha.c +++ b/contrib/gcc/config/alpha/alpha.c @@ -1,28 +1,30 @@ /* Subroutines used for code generation on the DEC Alpha. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify +GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. -GNU CC is distributed in the hope that it will be useful, +GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to +along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "rtl.h" #include "tree.h" #include "regs.h" @@ -48,6 +50,8 @@ Boston, MA 02111-1307, USA. */ #include "target-def.h" #include "debug.h" #include "langhooks.h" +#include <splay-tree.h> +#include "cfglayout.h" /* Specify which cpu to schedule for. */ @@ -103,110 +107,70 @@ static int alpha_function_needs_gp; /* The alias set for prologue/epilogue register save/restore. */ -static int alpha_sr_alias_set; +static GTY(()) int alpha_sr_alias_set; /* The assembler name of the current function. */ static const char *alpha_fnname; /* The next explicit relocation sequence number. */ +extern GTY(()) int alpha_next_sequence_number; int alpha_next_sequence_number = 1; /* The literal and gpdisp sequence numbers for this insn, as printed by %# and %* respectively. */ +extern GTY(()) int alpha_this_literal_sequence_number; +extern GTY(()) int alpha_this_gpdisp_sequence_number; int alpha_this_literal_sequence_number; int alpha_this_gpdisp_sequence_number; -/* Declarations of static functions. */ -static int tls_symbolic_operand_1 - PARAMS ((rtx, enum machine_mode, int, int)); -static enum tls_model tls_symbolic_operand_type - PARAMS ((rtx)); -static bool decl_in_text_section - PARAMS ((tree)); -static bool alpha_in_small_data_p - PARAMS ((tree)); -static void alpha_encode_section_info - PARAMS ((tree, int)); -static const char *alpha_strip_name_encoding - PARAMS ((const char *)); -static int some_small_symbolic_operand_1 - PARAMS ((rtx *, void *)); -static int split_small_symbolic_operand_1 - PARAMS ((rtx *, void *)); -static void alpha_set_memflags_1 - PARAMS ((rtx, int, int, int)); -static rtx alpha_emit_set_const_1 - PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT, int)); -static void alpha_expand_unaligned_load_words - PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); -static void alpha_expand_unaligned_store_words - PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs)); -static void alpha_init_builtins - PARAMS ((void)); -static rtx alpha_expand_builtin - PARAMS ((tree, rtx, rtx, enum machine_mode, int)); -static void alpha_sa_mask - PARAMS ((unsigned long *imaskP, unsigned long *fmaskP)); -static int find_lo_sum_using_gp - PARAMS ((rtx *, void *)); -static int alpha_does_function_need_gp - PARAMS ((void)); -static int alpha_ra_ever_killed - PARAMS ((void)); -static const char *get_trap_mode_suffix - PARAMS ((void)); -static const char *get_round_mode_suffix - PARAMS ((void)); -static const char *get_some_local_dynamic_name - PARAMS ((void)); -static int get_some_local_dynamic_name_1 - PARAMS ((rtx *, void *)); -static rtx set_frame_related_p - PARAMS ((void)); -static const char *alpha_lookup_xfloating_lib_func - PARAMS ((enum rtx_code)); -static int alpha_compute_xfloating_mode_arg - PARAMS ((enum rtx_code, enum alpha_fp_rounding_mode)); -static void alpha_emit_xfloating_libcall - PARAMS ((const char *, rtx, rtx[], int, rtx)); -static rtx alpha_emit_xfloating_compare - PARAMS ((enum rtx_code, rtx, rtx)); -static void alpha_output_function_end_prologue - PARAMS ((FILE *)); -static int alpha_adjust_cost - PARAMS ((rtx, rtx, rtx, int)); -static int alpha_issue_rate - PARAMS ((void)); -static int alpha_use_dfa_pipeline_interface - PARAMS ((void)); -static int alpha_multipass_dfa_lookahead - PARAMS ((void)); - -#ifdef OBJECT_FORMAT_ELF -static void alpha_elf_select_rtx_section - PARAMS ((enum machine_mode, rtx, unsigned HOST_WIDE_INT)); -#endif - -#if TARGET_ABI_OPEN_VMS -static bool alpha_linkage_symbol_p - PARAMS ((const char *symname)); -static void alpha_write_linkage - PARAMS ((FILE *, const char *, tree)); -#endif - -#if TARGET_ABI_OSF -static void alpha_output_mi_thunk_osf - PARAMS ((FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree)); -#endif +/* Costs of various operations on the different architectures. */ -static struct machine_function * alpha_init_machine_status - PARAMS ((void)); +struct alpha_rtx_cost_data +{ + unsigned char fp_add; + unsigned char fp_mult; + unsigned char fp_div_sf; + unsigned char fp_div_df; + unsigned char int_mult_si; + unsigned char int_mult_di; + unsigned char int_shift; + unsigned char int_cmov; +}; -static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *)); -static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP)); -static void unicosmk_output_ssib PARAMS ((FILE *, const char *)); -static int unicosmk_need_dex PARAMS ((rtx)); +static struct alpha_rtx_cost_data const alpha_rtx_cost_data[PROCESSOR_MAX] = +{ + { /* EV4 */ + COSTS_N_INSNS (6), /* fp_add */ + COSTS_N_INSNS (6), /* fp_mult */ + COSTS_N_INSNS (34), /* fp_div_sf */ + COSTS_N_INSNS (63), /* fp_div_df */ + COSTS_N_INSNS (23), /* int_mult_si */ + COSTS_N_INSNS (23), /* int_mult_di */ + COSTS_N_INSNS (2), /* int_shift */ + COSTS_N_INSNS (2), /* int_cmov */ + }, + { /* EV5 */ + COSTS_N_INSNS (4), /* fp_add */ + COSTS_N_INSNS (4), /* fp_mult */ + COSTS_N_INSNS (15), /* fp_div_sf */ + COSTS_N_INSNS (22), /* fp_div_df */ + COSTS_N_INSNS (8), /* int_mult_si */ + COSTS_N_INSNS (12), /* int_mult_di */ + COSTS_N_INSNS (1) + 1, /* int_shift */ + COSTS_N_INSNS (1), /* int_cmov */ + }, + { /* EV6 */ + COSTS_N_INSNS (4), /* fp_add */ + COSTS_N_INSNS (4), /* fp_mult */ + COSTS_N_INSNS (12), /* fp_div_sf */ + COSTS_N_INSNS (15), /* fp_div_df */ + COSTS_N_INSNS (7), /* int_mult_si */ + COSTS_N_INSNS (7), /* int_mult_di */ + COSTS_N_INSNS (1), /* int_shift */ + COSTS_N_INSNS (2), /* int_cmov */ + }, +}; /* Get the number of args of a function in one of two ways. */ #if TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK @@ -217,99 +181,24 @@ static int unicosmk_need_dex PARAMS ((rtx)); #define REG_PV 27 #define REG_RA 26 - -/* Initialize the GCC target structure. */ -#if TARGET_ABI_OPEN_VMS -const struct attribute_spec vms_attribute_table[]; -static unsigned int vms_section_type_flags PARAMS ((tree, const char *, int)); -static void vms_asm_named_section PARAMS ((const char *, unsigned int)); -static void vms_asm_out_constructor PARAMS ((rtx, int)); -static void vms_asm_out_destructor PARAMS ((rtx, int)); -# undef TARGET_ATTRIBUTE_TABLE -# define TARGET_ATTRIBUTE_TABLE vms_attribute_table -# undef TARGET_SECTION_TYPE_FLAGS -# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags -#endif - -#undef TARGET_IN_SMALL_DATA_P -#define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p -#undef TARGET_ENCODE_SECTION_INFO -#define TARGET_ENCODE_SECTION_INFO alpha_encode_section_info -#undef TARGET_STRIP_NAME_ENCODING -#define TARGET_STRIP_NAME_ENCODING alpha_strip_name_encoding - -#if TARGET_ABI_UNICOSMK -static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int)); -static void unicosmk_insert_attributes PARAMS ((tree, tree *)); -static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *, - int)); -static void unicosmk_unique_section PARAMS ((tree, int)); -# undef TARGET_INSERT_ATTRIBUTES -# define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes -# undef TARGET_SECTION_TYPE_FLAGS -# define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags -# undef TARGET_ASM_UNIQUE_SECTION -# define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section -# undef TARGET_ASM_GLOBALIZE_LABEL -# define TARGET_ASM_GLOBALIZE_LABEL hook_FILEptr_constcharptr_void -#endif - -#undef TARGET_ASM_ALIGNED_HI_OP -#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" -#undef TARGET_ASM_ALIGNED_DI_OP -#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t" -/* Default unaligned ops are provided for ELF systems. To get unaligned - data for non-ELF systems, we have to turn off auto alignment. */ -#ifndef OBJECT_FORMAT_ELF -#undef TARGET_ASM_UNALIGNED_HI_OP -#define TARGET_ASM_UNALIGNED_HI_OP "\t.align 0\n\t.word\t" -#undef TARGET_ASM_UNALIGNED_SI_OP -#define TARGET_ASM_UNALIGNED_SI_OP "\t.align 0\n\t.long\t" -#undef TARGET_ASM_UNALIGNED_DI_OP -#define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t" -#endif - -#ifdef OBJECT_FORMAT_ELF -#undef TARGET_ASM_SELECT_RTX_SECTION -#define TARGET_ASM_SELECT_RTX_SECTION alpha_elf_select_rtx_section -#endif - -#undef TARGET_ASM_FUNCTION_END_PROLOGUE -#define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue - -#undef TARGET_SCHED_ADJUST_COST -#define TARGET_SCHED_ADJUST_COST alpha_adjust_cost -#undef TARGET_SCHED_ISSUE_RATE -#define TARGET_SCHED_ISSUE_RATE alpha_issue_rate -#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE -#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \ - alpha_use_dfa_pipeline_interface -#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD -#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ - alpha_multipass_dfa_lookahead - -#undef TARGET_HAVE_TLS -#define TARGET_HAVE_TLS HAVE_AS_TLS - -#undef TARGET_INIT_BUILTINS -#define TARGET_INIT_BUILTINS alpha_init_builtins -#undef TARGET_EXPAND_BUILTIN -#define TARGET_EXPAND_BUILTIN alpha_expand_builtin +/* Declarations of static functions. */ +static struct machine_function *alpha_init_machine_status (void); +static rtx alpha_emit_xfloating_compare (enum rtx_code, rtx, rtx); -#if TARGET_ABI_OSF -#undef TARGET_ASM_OUTPUT_MI_THUNK -#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf -#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK -#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true +#if TARGET_ABI_OPEN_VMS +static void alpha_write_linkage (FILE *, const char *, tree); #endif -struct gcc_target targetm = TARGET_INITIALIZER; +static void unicosmk_output_deferred_case_vectors (FILE *); +static void unicosmk_gen_dsib (unsigned long *); +static void unicosmk_output_ssib (FILE *, const char *); +static int unicosmk_need_dex (rtx); /* Parse target option strings. */ void -override_options () +override_options (void) { int i; static const struct cpu_table { @@ -344,7 +233,7 @@ override_options () flag_pic = 0; } - /* On Unicos/Mk, the native compiler consistenly generates /d suffices for + /* On Unicos/Mk, the native compiler consistently generates /d suffices for floating-point instructions. Make that the default for this target. */ if (TARGET_ABI_UNICOSMK) alpha_fprm = ALPHA_FPRM_DYN; @@ -501,6 +390,9 @@ override_options () warning ("trap mode not supported for VAX floats"); alpha_fptm = ALPHA_FPTM_SU; } + if (target_flags_explicit & MASK_LONG_DOUBLE_128) + warning ("128-bit long double not supported for VAX floats"); + target_flags &= ~MASK_LONG_DOUBLE_128; } { @@ -583,17 +475,16 @@ override_options () /* Tell the compiler when we're using VAX floating point. */ if (TARGET_FLOAT_VAX) { - real_format_for_mode[SFmode - QFmode] = &vax_f_format; - real_format_for_mode[DFmode - QFmode] = &vax_g_format; - real_format_for_mode[TFmode - QFmode] = NULL; + REAL_MODE_FORMAT (SFmode) = &vax_f_format; + REAL_MODE_FORMAT (DFmode) = &vax_g_format; + REAL_MODE_FORMAT (TFmode) = NULL; } } /* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */ int -zap_mask (value) - HOST_WIDE_INT value; +zap_mask (HOST_WIDE_INT value) { int i; @@ -609,9 +500,7 @@ zap_mask (value) register, it must be in the proper mode unless MODE is VOIDmode. */ int -reg_or_0_operand (op, mode) - register rtx op; - enum machine_mode mode; +reg_or_0_operand (rtx op, enum machine_mode mode) { return op == CONST0_RTX (mode) || register_operand (op, mode); } @@ -620,9 +509,7 @@ reg_or_0_operand (op, mode) any register. */ int -reg_or_6bit_operand (op, mode) - register rtx op; - enum machine_mode mode; +reg_or_6bit_operand (rtx op, enum machine_mode mode) { return ((GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) INTVAL (op) < 64) @@ -633,9 +520,7 @@ reg_or_6bit_operand (op, mode) /* Return 1 if OP is an 8-bit constant or any register. */ int -reg_or_8bit_operand (op, mode) - register rtx op; - enum machine_mode mode; +reg_or_8bit_operand (rtx op, enum machine_mode mode) { return ((GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100) @@ -645,9 +530,7 @@ reg_or_8bit_operand (op, mode) /* Return 1 if OP is a constant or any register. */ int -reg_or_const_int_operand (op, mode) - register rtx op; - enum machine_mode mode; +reg_or_const_int_operand (rtx op, enum machine_mode mode) { return GET_CODE (op) == CONST_INT || register_operand (op, mode); } @@ -655,9 +538,7 @@ reg_or_const_int_operand (op, mode) /* Return 1 if OP is an 8-bit constant. */ int -cint8_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +cint8_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return ((GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)); @@ -666,9 +547,7 @@ cint8_operand (op, mode) /* Return 1 if the operand is a valid second operand to an add insn. */ int -add_operand (op, mode) - register rtx op; - enum machine_mode mode; +add_operand (rtx op, enum machine_mode mode) { if (GET_CODE (op) == CONST_INT) /* Constraints I, J, O and P are covered by K. */ @@ -682,9 +561,7 @@ add_operand (op, mode) add insn. */ int -sext_add_operand (op, mode) - register rtx op; - enum machine_mode mode; +sext_add_operand (rtx op, enum machine_mode mode) { if (GET_CODE (op) == CONST_INT) return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I') @@ -696,9 +573,7 @@ sext_add_operand (op, mode) /* Return 1 if OP is the constant 4 or 8. */ int -const48_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +const48_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == CONST_INT && (INTVAL (op) == 4 || INTVAL (op) == 8)); @@ -707,9 +582,7 @@ const48_operand (op, mode) /* Return 1 if OP is a valid first operand to an AND insn. */ int -and_operand (op, mode) - register rtx op; - enum machine_mode mode; +and_operand (rtx op, enum machine_mode mode) { if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode) return (zap_mask (CONST_DOUBLE_LOW (op)) @@ -726,9 +599,7 @@ and_operand (op, mode) /* Return 1 if OP is a valid first operand to an IOR or XOR insn. */ int -or_operand (op, mode) - register rtx op; - enum machine_mode mode; +or_operand (rtx op, enum machine_mode mode) { if (GET_CODE (op) == CONST_INT) return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100 @@ -741,9 +612,7 @@ or_operand (op, mode) mode smaller than DImode. */ int -mode_width_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +mode_width_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == CONST_INT && (INTVAL (op) == 8 || INTVAL (op) == 16 @@ -754,9 +623,7 @@ mode_width_operand (op, mode) smaller than an integer. */ int -mode_mask_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +mode_mask_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { if (GET_CODE (op) == CONST_INT) { @@ -783,9 +650,7 @@ mode_mask_operand (op, mode) /* Return 1 if OP is a multiple of 8 less than 64. */ int -mul8_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +mul8_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == CONST_INT && (unsigned HOST_WIDE_INT) INTVAL (op) < 64 @@ -795,9 +660,7 @@ mul8_operand (op, mode) /* Return 1 if OP is the zero constant for MODE. */ int -const0_operand (op, mode) - register rtx op; - enum machine_mode mode; +const0_operand (rtx op, enum machine_mode mode) { return op == CONST0_RTX (mode); } @@ -805,9 +668,7 @@ const0_operand (op, mode) /* Return 1 if OP is a hard floating-point register. */ int -hard_fp_register_operand (op, mode) - register rtx op; - enum machine_mode mode; +hard_fp_register_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -820,9 +681,7 @@ hard_fp_register_operand (op, mode) /* Return 1 if OP is a hard general register. */ int -hard_int_register_operand (op, mode) - register rtx op; - enum machine_mode mode; +hard_int_register_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -836,9 +695,7 @@ hard_int_register_operand (op, mode) int -reg_or_cint_operand (op, mode) - register rtx op; - enum machine_mode mode; +reg_or_cint_operand (rtx op, enum machine_mode mode) { return (GET_CODE (op) == CONST_INT || register_operand (op, mode)); @@ -848,9 +705,7 @@ reg_or_cint_operand (op, mode) if it is a MEM, it need not be valid. */ int -some_operand (op, mode) - register rtx op; - enum machine_mode mode; +some_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -881,9 +736,7 @@ some_operand (op, mode) /* Likewise, but don't accept constants. */ int -some_ni_operand (op, mode) - register rtx op; - enum machine_mode mode; +some_ni_operand (rtx op, enum machine_mode mode) { if (GET_MODE (op) != mode && mode != VOIDmode) return 0; @@ -897,9 +750,7 @@ some_ni_operand (op, mode) /* Return 1 if OP is a valid operand for the source of a move insn. */ int -input_operand (op, mode) - register rtx op; - enum machine_mode mode; +input_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -964,60 +815,89 @@ input_operand (op, mode) file, and in the same section as the current function. */ int -current_file_function_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +samegp_function_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { if (GET_CODE (op) != SYMBOL_REF) - return 0; + return false; /* Easy test for recursion. */ if (op == XEXP (DECL_RTL (current_function_decl), 0)) - return 1; + return true; - /* Otherwise, we need the DECL for the SYMBOL_REF, which we can't get. - So SYMBOL_REF_FLAG has been declared to imply that the function is - in the default text section. So we must also check that the current - function is also in the text section. */ - if (SYMBOL_REF_FLAG (op) && decl_in_text_section (current_function_decl)) - return 1; + /* Functions that are not local can be overridden, and thus may + not share the same gp. */ + if (! SYMBOL_REF_LOCAL_P (op)) + return false; - return 0; + /* If -msmall-data is in effect, assume that there is only one GP + for the module, and so any local symbol has this property. We + need explicit relocations to be able to enforce this for symbols + not defined in this unit of translation, however. */ + if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA) + return true; + + /* Functions that are not external are defined in this UoT, + and thus must share the same gp. */ + return ! SYMBOL_REF_EXTERNAL_P (op); } /* Return 1 if OP is a SYMBOL_REF for which we can make a call via bsr. */ int -direct_call_operand (op, mode) - rtx op; - enum machine_mode mode; +direct_call_operand (rtx op, enum machine_mode mode) { - /* Must be defined in this file. */ - if (! current_file_function_operand (op, mode)) - return 0; + tree op_decl, cfun_sec, op_sec; + + /* Must share the same GP. */ + if (!samegp_function_operand (op, mode)) + return false; /* If profiling is implemented via linker tricks, we can't jump - to the nogp alternate entry point. */ + to the nogp alternate entry point. Note that current_function_profile + would not be correct, since that doesn't indicate if the target + function uses profiling. */ /* ??? TARGET_PROFILING_NEEDS_GP isn't really the right test, but is approximately correct for the OSF ABIs. Don't know what to do for VMS, NT, or UMK. */ - if (! TARGET_PROFILING_NEEDS_GP - && ! current_function_profile) - return 0; + if (!TARGET_PROFILING_NEEDS_GP && profile_flag) + return false; - return 1; + /* Must be a function. In some cases folks create thunks in static + data structures and then make calls to them. If we allow the + direct call, we'll get an error from the linker about !samegp reloc + against a symbol without a .prologue directive. */ + if (!SYMBOL_REF_FUNCTION_P (op)) + return false; + + /* Must be "near" so that the branch is assumed to reach. With + -msmall-text, this is assumed true of all local symbols. Since + we've already checked samegp, locality is already assured. */ + if (TARGET_SMALL_TEXT) + return true; + + /* Otherwise, a decl is "near" if it is defined in the same section. */ + if (flag_function_sections) + return false; + + op_decl = SYMBOL_REF_DECL (op); + if (DECL_ONE_ONLY (current_function_decl) + || (op_decl && DECL_ONE_ONLY (op_decl))) + return false; + + cfun_sec = DECL_SECTION_NAME (current_function_decl); + op_sec = op_decl ? DECL_SECTION_NAME (op_decl) : NULL; + return ((!cfun_sec && !op_sec) + || (cfun_sec && op_sec + && strcmp (TREE_STRING_POINTER (cfun_sec), + TREE_STRING_POINTER (op_sec)) == 0)); } /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing a (non-tls) variable known to be defined in this file. */ int -local_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; +local_symbolic_operand (rtx op, enum machine_mode mode) { - const char *str; - if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -1032,38 +912,15 @@ local_symbolic_operand (op, mode) if (GET_CODE (op) != SYMBOL_REF) return 0; - /* Easy pickings. */ - if (CONSTANT_POOL_ADDRESS_P (op) || STRING_POOL_ADDRESS_P (op)) - return 1; - - /* ??? SYMBOL_REF_FLAG is set for local function symbols, but we - run into problems with the rtl inliner in that the symbol was - once external, but is local after inlining, which results in - unrecognizable insns. */ - - str = XSTR (op, 0); - - /* If @[LS], then alpha_encode_section_info sez it's local. */ - if (str[0] == '@' && (str[1] == 'L' || str[1] == 'S')) - return 1; - - /* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */ - if (str[0] == '*' && str[1] == '$') - return 1; - - return 0; + return SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op); } /* Return true if OP is a SYMBOL_REF or CONST referencing a variable known to be defined in this file in the small data area. */ int -small_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +small_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { - const char *str; - if (! TARGET_SMALL_DATA) return 0; @@ -1078,25 +935,22 @@ small_symbolic_operand (op, mode) if (GET_CODE (op) != SYMBOL_REF) return 0; + /* ??? There's no encode_section_info equivalent for the rtl + constant pool, so SYMBOL_FLAG_SMALL never gets set. */ if (CONSTANT_POOL_ADDRESS_P (op)) - return GET_MODE_SIZE (get_pool_mode (op)) <= (unsigned) g_switch_value; - else - { - str = XSTR (op, 0); - return str[0] == '@' && str[1] == 'S'; - } + return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value; + + return (SYMBOL_REF_LOCAL_P (op) + && SYMBOL_REF_SMALL_P (op) + && SYMBOL_REF_TLS_MODEL (op) == 0); } /* Return true if OP is a SYMBOL_REF or CONST referencing a variable not known (or known not) to be defined in this file. */ int -global_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; +global_symbolic_operand (rtx op, enum machine_mode mode) { - const char *str; - if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -1108,20 +962,13 @@ global_symbolic_operand (op, mode) if (GET_CODE (op) != SYMBOL_REF) return 0; - if (local_symbolic_operand (op, mode)) - return 0; - - /* Also verify that it's not a TLS symbol. */ - str = XSTR (op, 0); - return str[0] != '%' && str[0] != '@'; + return !SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op); } /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ int -call_operand (op, mode) - rtx op; - enum machine_mode mode; +call_operand (rtx op, enum machine_mode mode) { if (mode != Pmode) return 0; @@ -1130,7 +977,7 @@ call_operand (op, mode) { if (TARGET_ABI_OSF) { - /* Disallow virtual registers to cope with pathalogical test cases + /* Disallow virtual registers to cope with pathological test cases such as compile/930117-1.c in which the virtual reg decomposes to the frame pointer. Which is a hard reg that is not $27. */ return (REGNO (op) == 27 || REGNO (op) > LAST_VIRTUAL_REGISTER); @@ -1150,9 +997,7 @@ call_operand (op, mode) possibly with an offset. */ int -symbolic_operand (op, mode) - register rtx op; - enum machine_mode mode; +symbolic_operand (rtx op, enum machine_mode mode) { if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -1169,14 +1014,8 @@ symbolic_operand (op, mode) /* Return true if OP is valid for a particular TLS relocation. */ static int -tls_symbolic_operand_1 (op, mode, size, unspec) - rtx op; - enum machine_mode mode; - int size, unspec; +tls_symbolic_operand_1 (rtx op, enum machine_mode mode, int size, int unspec) { - const char *str; - int letter; - if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) return 0; @@ -1190,32 +1029,35 @@ tls_symbolic_operand_1 (op, mode, size, unspec) if (GET_CODE (op) != SYMBOL_REF) return 0; - str = XSTR (op, 0); - if (str[0] == '%') + if (SYMBOL_REF_LOCAL_P (op)) { - if (size != 64) + if (alpha_tls_size > size) return 0; } - else if (str[0] == '@') + else { - if (alpha_tls_size > size) + if (size != 64) return 0; } - else - return 0; - - letter = (unspec == UNSPEC_DTPREL ? 'D' : 'T'); - return str[1] == letter; + switch (SYMBOL_REF_TLS_MODEL (op)) + { + case TLS_MODEL_LOCAL_DYNAMIC: + return unspec == UNSPEC_DTPREL; + case TLS_MODEL_INITIAL_EXEC: + return unspec == UNSPEC_TPREL && size == 64; + case TLS_MODEL_LOCAL_EXEC: + return unspec == UNSPEC_TPREL; + default: + abort (); + } } /* Return true if OP is valid for 16-bit DTP relative relocations. */ int -dtp16_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; +dtp16_symbolic_operand (rtx op, enum machine_mode mode) { return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_DTPREL); } @@ -1223,9 +1065,7 @@ dtp16_symbolic_operand (op, mode) /* Return true if OP is valid for 32-bit DTP relative relocations. */ int -dtp32_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; +dtp32_symbolic_operand (rtx op, enum machine_mode mode) { return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_DTPREL); } @@ -1233,9 +1073,7 @@ dtp32_symbolic_operand (op, mode) /* Return true if OP is valid for 64-bit DTP relative relocations. */ int -gotdtp_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; +gotdtp_symbolic_operand (rtx op, enum machine_mode mode) { return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_DTPREL); } @@ -1243,9 +1081,7 @@ gotdtp_symbolic_operand (op, mode) /* Return true if OP is valid for 16-bit TP relative relocations. */ int -tp16_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; +tp16_symbolic_operand (rtx op, enum machine_mode mode) { return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_TPREL); } @@ -1253,9 +1089,7 @@ tp16_symbolic_operand (op, mode) /* Return true if OP is valid for 32-bit TP relative relocations. */ int -tp32_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; +tp32_symbolic_operand (rtx op, enum machine_mode mode) { return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_TPREL); } @@ -1263,9 +1097,7 @@ tp32_symbolic_operand (op, mode) /* Return true if OP is valid for 64-bit TP relative relocations. */ int -gottp_symbolic_operand (op, mode) - rtx op; - enum machine_mode mode; +gottp_symbolic_operand (rtx op, enum machine_mode mode) { return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_TPREL); } @@ -1274,9 +1106,7 @@ gottp_symbolic_operand (op, mode) comparisons are valid in which insn. */ int -alpha_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; +alpha_comparison_operator (rtx op, enum machine_mode mode) { enum rtx_code code = GET_CODE (op); @@ -1291,9 +1121,7 @@ alpha_comparison_operator (op, mode) Here we know which comparisons are valid in which insn. */ int -alpha_zero_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; +alpha_zero_comparison_operator (rtx op, enum machine_mode mode) { enum rtx_code code = GET_CODE (op); @@ -1307,9 +1135,7 @@ alpha_zero_comparison_operator (op, mode) /* Return 1 if OP is a valid Alpha swapped comparison operator. */ int -alpha_swapped_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; +alpha_swapped_comparison_operator (rtx op, enum machine_mode mode) { enum rtx_code code = GET_CODE (op); @@ -1325,9 +1151,7 @@ alpha_swapped_comparison_operator (op, mode) /* Return 1 if OP is a signed comparison operation. */ int -signed_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +signed_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { enum rtx_code code = GET_CODE (op); @@ -1343,9 +1167,7 @@ signed_comparison_operator (op, mode) Here we know which comparisons are valid in which insn. */ int -alpha_fp_comparison_operator (op, mode) - register rtx op; - enum machine_mode mode; +alpha_fp_comparison_operator (rtx op, enum machine_mode mode) { enum rtx_code code = GET_CODE (op); @@ -1358,20 +1180,21 @@ alpha_fp_comparison_operator (op, mode) /* Return 1 if this is a divide or modulus operator. */ int -divmod_operator (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +divmod_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { - switch (GET_CODE (op)) - { - case DIV: case MOD: case UDIV: case UMOD: - return 1; + enum rtx_code code = GET_CODE (op); - default: - break; - } + return (code == DIV || code == MOD || code == UDIV || code == UMOD); +} - return 0; +/* Return 1 if this is a float->int conversion operator. */ + +int +fix_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +{ + enum rtx_code code = GET_CODE (op); + + return (code == FIX || code == UNSIGNED_FIX); } /* Return 1 if this memory address is a known aligned register plus @@ -1381,9 +1204,7 @@ divmod_operator (op, mode) Take into account what reload will do. */ int -aligned_memory_operand (op, mode) - register rtx op; - enum machine_mode mode; +aligned_memory_operand (rtx op, enum machine_mode mode) { rtx base; @@ -1401,9 +1222,10 @@ aligned_memory_operand (op, mode) } } - if (GET_CODE (op) != MEM - || GET_MODE (op) != mode) + if (GET_CODE (op) != MEM) return 0; + if (MEM_ALIGN (op) >= 32) + return 1; op = XEXP (op, 0); /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo) @@ -1425,9 +1247,7 @@ aligned_memory_operand (op, mode) /* Similar, but return 1 if OP is a MEM which is not alignable. */ int -unaligned_memory_operand (op, mode) - register rtx op; - enum machine_mode mode; +unaligned_memory_operand (rtx op, enum machine_mode mode) { rtx base; @@ -1445,8 +1265,9 @@ unaligned_memory_operand (op, mode) } } - if (GET_CODE (op) != MEM - || GET_MODE (op) != mode) + if (GET_CODE (op) != MEM) + return 0; + if (MEM_ALIGN (op) >= 32) return 0; op = XEXP (op, 0); @@ -1469,9 +1290,7 @@ unaligned_memory_operand (op, mode) /* Return 1 if OP is either a register or an unaligned memory location. */ int -reg_or_unaligned_mem_operand (op, mode) - rtx op; - enum machine_mode mode; +reg_or_unaligned_mem_operand (rtx op, enum machine_mode mode) { return register_operand (op, mode) || unaligned_memory_operand (op, mode); } @@ -1479,9 +1298,7 @@ reg_or_unaligned_mem_operand (op, mode) /* Return 1 if OP is any memory location. During reload a pseudo matches. */ int -any_memory_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +any_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { return (GET_CODE (op) == MEM || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG) @@ -1504,9 +1321,7 @@ any_memory_operand (op, mode) preventing combine from making the optimization. */ int -reg_not_elim_operand (op, mode) - register rtx op; - enum machine_mode mode; +reg_not_elim_operand (rtx op, enum machine_mode mode) { rtx inner = op; if (GET_CODE (op) == SUBREG) @@ -1522,9 +1337,7 @@ reg_not_elim_operand (op, mode) will do. */ int -normal_memory_operand (op, mode) - register rtx op; - enum machine_mode mode ATTRIBUTE_UNUSED; +normal_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) { if (reload_in_progress) { @@ -1551,9 +1364,7 @@ normal_memory_operand (op, mode) int->fp conversion. */ int -reg_no_subreg_operand (op, mode) - register rtx op; - enum machine_mode mode; +reg_no_subreg_operand (rtx op, enum machine_mode mode) { if (GET_CODE (op) != REG) return 0; @@ -1565,9 +1376,7 @@ reg_no_subreg_operand (op, mode) elimination. */ int -addition_operation (op, mode) - register rtx op; - enum machine_mode mode; +addition_operation (rtx op, enum machine_mode mode) { if (GET_MODE (op) != mode && mode != VOIDmode) return 0; @@ -1583,9 +1392,7 @@ addition_operation (op, mode) the range defined for C in [I-P]. */ bool -alpha_const_ok_for_letter_p (value, c) - HOST_WIDE_INT value; - int c; +alpha_const_ok_for_letter_p (HOST_WIDE_INT value, int c) { switch (c) { @@ -1624,9 +1431,7 @@ alpha_const_ok_for_letter_p (value, c) matches for C in [GH]. */ bool -alpha_const_double_ok_for_letter_p (value, c) - rtx value; - int c; +alpha_const_double_ok_for_letter_p (rtx value, int c) { switch (c) { @@ -1650,9 +1455,7 @@ alpha_const_double_ok_for_letter_p (value, c) matches for C. */ bool -alpha_extra_constraint (value, c) - rtx value; - int c; +alpha_extra_constraint (rtx value, int c) { switch (c) { @@ -1678,7 +1481,7 @@ alpha_extra_constraint (value, c) /* Return 1 if this function can directly return via $26. */ int -direct_return () +direct_return (void) { return (! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK && reload_completed @@ -1691,8 +1494,7 @@ direct_return () /* Return the ADDR_VEC associated with a tablejump insn. */ rtx -alpha_tablejump_addr_vec (insn) - rtx insn; +alpha_tablejump_addr_vec (rtx insn) { rtx tmp; @@ -1711,8 +1513,7 @@ alpha_tablejump_addr_vec (insn) /* Return the label of the predicted edge, or CONST0_RTX if we don't know. */ rtx -alpha_tablejump_best_label (insn) - rtx insn; +alpha_tablejump_best_label (rtx insn) { rtx jump_table = alpha_tablejump_addr_vec (insn); rtx best_label = NULL_RTX; @@ -1746,77 +1547,58 @@ alpha_tablejump_best_label (insn) /* Return the TLS model to use for SYMBOL. */ static enum tls_model -tls_symbolic_operand_type (symbol) - rtx symbol; +tls_symbolic_operand_type (rtx symbol) { - const char *str; + enum tls_model model; if (GET_CODE (symbol) != SYMBOL_REF) return 0; - str = XSTR (symbol, 0); + model = SYMBOL_REF_TLS_MODEL (symbol); - if (str[0] == '%') - { - /* ??? Be prepared for -ftls-model=local-dynamic. Perhaps we shouldn't - have separately encoded local-ness. On well, maybe the user will use - attribute visibility next time. At least we don't crash... */ - if (str[1] == 'G' || str[1] == 'D') - return TLS_MODEL_GLOBAL_DYNAMIC; - if (str[1] == 'T') - return TLS_MODEL_INITIAL_EXEC; - } - else if (str[0] == '@') - { - if (str[1] == 'D') - { - /* Local dynamic is a waste if we're not going to combine - the __tls_get_addr calls. So avoid it if not optimizing. */ - if (optimize) - return TLS_MODEL_LOCAL_DYNAMIC; - else - return TLS_MODEL_GLOBAL_DYNAMIC; - } - if (str[1] == 'T') - { - /* 64-bit local exec is the same as initial exec except without - the dynamic relocation. In either case we use a got entry. */ - if (alpha_tls_size == 64) - return TLS_MODEL_INITIAL_EXEC; - else - return TLS_MODEL_LOCAL_EXEC; - } - } + /* Local-exec with a 64-bit size is the same code as initial-exec. */ + if (model == TLS_MODEL_LOCAL_EXEC && alpha_tls_size == 64) + model = TLS_MODEL_INITIAL_EXEC; - return 0; + return model; } - -/* Return true if the function DECL will be placed in the default text - section. */ -/* ??? Ideally we'd be able to always move from a SYMBOL_REF back to the - decl, as that would allow us to determine if two functions are in the - same section, which is what we really want to know. */ +/* Return true if the function DECL will share the same GP as any + function in the current unit of translation. */ static bool -decl_in_text_section (decl) - tree decl; +decl_has_samegp (tree decl) { - return (DECL_SECTION_NAME (decl) == NULL_TREE - && ! (flag_function_sections - || (targetm.have_named_sections - && DECL_ONE_ONLY (decl)))); + /* Functions that are not local can be overridden, and thus may + not share the same gp. */ + if (!(*targetm.binds_local_p) (decl)) + return false; + + /* If -msmall-data is in effect, assume that there is only one GP + for the module, and so any local symbol has this property. We + need explicit relocations to be able to enforce this for symbols + not defined in this unit of translation, however. */ + if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA) + return true; + + /* Functions that are not external are defined in this UoT. */ + /* ??? Irritatingly, static functions not yet emitted are still + marked "external". Apply this to non-static functions only. */ + return !TREE_PUBLIC (decl) || !DECL_EXTERNAL (decl); } /* Return true if EXP should be placed in the small data section. */ static bool -alpha_in_small_data_p (exp) - tree exp; +alpha_in_small_data_p (tree exp) { /* We want to merge strings, so we never consider them small data. */ if (TREE_CODE (exp) == STRING_CST) return false; + /* Functions are never in the small data area. Duh. */ + if (TREE_CODE (exp) == FUNCTION_DECL) + return false; + if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp)) { const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp)); @@ -1830,136 +1612,16 @@ alpha_in_small_data_p (exp) /* If this is an incomplete type with size 0, then we can't put it in sdata because it might be too big when completed. */ - if (size > 0 && size <= g_switch_value) + if (size > 0 && (unsigned HOST_WIDE_INT) size <= g_switch_value) return true; } return false; } -/* If we are referencing a function that is static, make the SYMBOL_REF - special. We use this to see indicate we can branch to this function - without setting PV or restoring GP. - - If this is a variable that is known to be defined locally, add "@v" - to the name. If in addition the variable is to go in .sdata/.sbss, - then add "@s" instead. */ - -static void -alpha_encode_section_info (decl, first) - tree decl; - int first ATTRIBUTE_UNUSED; -{ - const char *symbol_str; - bool is_local; - char encoding = 0; - rtx rtl, symbol; - - rtl = DECL_P (decl) ? DECL_RTL (decl) : TREE_CST_RTL (decl); - - /* Careful not to prod global register variables. */ - if (GET_CODE (rtl) != MEM) - return; - symbol = XEXP (rtl, 0); - if (GET_CODE (symbol) != SYMBOL_REF) - return; - - if (TREE_CODE (decl) == FUNCTION_DECL) - { - /* We mark public functions once they are emitted; otherwise we - don't know that they exist in this unit of translation. */ - if (TREE_PUBLIC (decl)) - return; - - /* Do not mark functions that are not in .text; otherwise we - don't know that they are near enough for a direct branch. */ - if (! decl_in_text_section (decl)) - return; - - SYMBOL_REF_FLAG (symbol) = 1; - return; - } - - /* Early out if we're not going to do anything with this data. */ - if (! TARGET_EXPLICIT_RELOCS) - return; - - symbol_str = XSTR (symbol, 0); - - /* A variable is considered "local" if it is defined in this module. */ - is_local = (*targetm.binds_local_p) (decl); - - /* Care for TLS variables. */ - if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) - { - switch (decl_tls_model (decl)) - { - case TLS_MODEL_GLOBAL_DYNAMIC: - encoding = 'G'; - break; - case TLS_MODEL_LOCAL_DYNAMIC: - encoding = 'D'; - break; - case TLS_MODEL_INITIAL_EXEC: - case TLS_MODEL_LOCAL_EXEC: - encoding = 'T'; - break; - } - } - else if (is_local) - { - /* Determine if DECL will wind up in .sdata/.sbss. */ - if (alpha_in_small_data_p (decl)) - encoding = 'S'; - else - encoding = 'L'; - } - - /* Finally, encode this into the symbol string. */ - if (encoding) - { - char *newstr; - size_t len; - char want_prefix = (is_local ? '@' : '%'); - char other_prefix = (is_local ? '%' : '@'); - - if (symbol_str[0] == want_prefix) - { - if (symbol_str[1] == encoding) - return; - symbol_str += 2; - } - else if (symbol_str[0] == other_prefix) - symbol_str += 2; - - len = strlen (symbol_str) + 1; - newstr = alloca (len + 2); - - newstr[0] = want_prefix; - newstr[1] = encoding; - memcpy (newstr + 2, symbol_str, len); - - XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2 - 1); - } -} - -/* Undo the effects of the above. */ - -static const char * -alpha_strip_name_encoding (str) - const char *str; -{ - if (str[0] == '@' || str[0] == '%') - str += 2; - if (str[0] == '*') - str++; - return str; -} - #if TARGET_ABI_OPEN_VMS static bool -alpha_linkage_symbol_p (symname) - const char *symname; +alpha_linkage_symbol_p (const char *symname) { int symlen = strlen (symname); @@ -1988,10 +1650,7 @@ alpha_linkage_symbol_p (symname) low-order three bits; this is an "unaligned" access. */ bool -alpha_legitimate_address_p (mode, x, strict) - enum machine_mode mode; - rtx x; - int strict; +alpha_legitimate_address_p (enum machine_mode mode, rtx x, int strict) { /* If this is an ldq_u type address, discard the outer AND. */ if (mode == DImode @@ -2087,14 +1746,24 @@ alpha_legitimate_address_p (mode, x, strict) return false; } +/* Build the SYMBOL_REF for __tls_get_addr. */ + +static GTY(()) rtx tls_get_addr_libfunc; + +static rtx +get_tls_get_addr (void) +{ + if (!tls_get_addr_libfunc) + tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr"); + return tls_get_addr_libfunc; +} + /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. */ rtx -alpha_legitimize_address (x, scratch, mode) - rtx x; - rtx scratch; - enum machine_mode mode ATTRIBUTE_UNUSED; +alpha_legitimize_address (rtx x, rtx scratch, + enum machine_mode mode ATTRIBUTE_UNUSED) { HOST_WIDE_INT addend; @@ -2154,7 +1823,7 @@ alpha_legitimize_address (x, scratch, mode) r0 = gen_rtx_REG (Pmode, 0); r16 = gen_rtx_REG (Pmode, 16); - tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr"); + tga = get_tls_get_addr (); dest = gen_reg_rtx (Pmode); seq = GEN_INT (alpha_next_sequence_number++); @@ -2175,7 +1844,7 @@ alpha_legitimize_address (x, scratch, mode) r0 = gen_rtx_REG (Pmode, 0); r16 = gen_rtx_REG (Pmode, 16); - tga = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_addr"); + tga = get_tls_get_addr (); scratch = gen_reg_rtx (Pmode); seq = GEN_INT (alpha_next_sequence_number++); @@ -2278,23 +1947,30 @@ alpha_legitimize_address (x, scratch, mode) } } +/* We do not allow indirect calls to be optimized into sibling calls, nor + can we allow a call to a function with a different GP to be optimized + into a sibcall. */ + +static bool +alpha_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) +{ + /* Can't do indirect tail calls, since we don't know if the target + uses the same GP. */ + if (!decl) + return false; + + /* Otherwise, we can make a tail call if the target function shares + the same GP. */ + return decl_has_samegp (decl); +} + /* For TARGET_EXPLICIT_RELOCS, we don't obfuscate a SYMBOL_REF to a small symbolic operand until after reload. At which point we need to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref)) so that sched2 has the proper dependency information. */ -int -some_small_symbolic_operand (x, mode) - rtx x; - enum machine_mode mode ATTRIBUTE_UNUSED; -{ - return for_each_rtx (&x, some_small_symbolic_operand_1, NULL); -} - static int -some_small_symbolic_operand_1 (px, data) - rtx *px; - void *data ATTRIBUTE_UNUSED; +some_small_symbolic_operand_1 (rtx *px, void *data ATTRIBUTE_UNUSED) { rtx x = *px; @@ -2305,19 +1981,14 @@ some_small_symbolic_operand_1 (px, data) return small_symbolic_operand (x, Pmode) != 0; } -rtx -split_small_symbolic_operand (x) - rtx x; +int +some_small_symbolic_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED) { - x = copy_insn (x); - for_each_rtx (&x, split_small_symbolic_operand_1, NULL); - return x; + return for_each_rtx (&x, some_small_symbolic_operand_1, NULL); } static int -split_small_symbolic_operand_1 (px, data) - rtx *px; - void *data ATTRIBUTE_UNUSED; +split_small_symbolic_operand_1 (rtx *px, void *data ATTRIBUTE_UNUSED) { rtx x = *px; @@ -2335,16 +2006,48 @@ split_small_symbolic_operand_1 (px, data) return 0; } +rtx +split_small_symbolic_operand (rtx x) +{ + x = copy_insn (x); + for_each_rtx (&x, split_small_symbolic_operand_1, NULL); + return x; +} + +/* Indicate that INSN cannot be duplicated. This is true for any insn + that we've marked with gpdisp relocs, since those have to stay in + 1-1 correspondence with one another. + + Technically we could copy them if we could set up a mapping from one + sequence number to another, across the set of insns to be duplicated. + This seems overly complicated and error-prone since interblock motion + from sched-ebb could move one of the pair of insns to a different block. + + Also cannot allow jsr insns to be duplicated. If they throw exceptions, + then they'll be in a different block from their ldgp. Which could lead + the bb reorder code to think that it would be ok to copy just the block + containing the call and branch to the block containing the ldgp. */ + +static bool +alpha_cannot_copy_insn_p (rtx insn) +{ + if (!reload_completed || !TARGET_EXPLICIT_RELOCS) + return false; + if (recog_memoized (insn) >= 0) + return get_attr_cannot_copy (insn); + else + return false; +} + + /* Try a machine-dependent way of reloading an illegitimate address operand. If we find one, push the reload and return the new rtx. */ rtx -alpha_legitimize_reload_address (x, mode, opnum, type, ind_levels) - rtx x; - enum machine_mode mode ATTRIBUTE_UNUSED; - int opnum; - int type; - int ind_levels ATTRIBUTE_UNUSED; +alpha_legitimize_reload_address (rtx x, + enum machine_mode mode ATTRIBUTE_UNUSED, + int opnum, int type, + int ind_levels ATTRIBUTE_UNUSED) { /* We must recognize output that we have already generated ourselves. */ if (GET_CODE (x) == PLUS @@ -2393,15 +2096,154 @@ alpha_legitimize_reload_address (x, mode, opnum, type, ind_levels) return NULL_RTX; } +/* Compute a (partial) cost for rtx X. Return true if the complete + cost has been computed, and false if subexpressions should be + scanned. In either case, *TOTAL contains the cost result. */ + +static bool +alpha_rtx_costs (rtx x, int code, int outer_code, int *total) +{ + enum machine_mode mode = GET_MODE (x); + bool float_mode_p = FLOAT_MODE_P (mode); + + switch (code) + { + /* If this is an 8-bit constant, return zero since it can be used + nearly anywhere with no cost. If it is a valid operand for an + ADD or AND, likewise return 0 if we know it will be used in that + context. Otherwise, return 2 since it might be used there later. + All other constants take at least two insns. */ + case CONST_INT: + if (INTVAL (x) >= 0 && INTVAL (x) < 256) + { + *total = 0; + return true; + } + /* FALLTHRU */ + + case CONST_DOUBLE: + if (x == CONST0_RTX (mode)) + *total = 0; + else if ((outer_code == PLUS && add_operand (x, VOIDmode)) + || (outer_code == AND && and_operand (x, VOIDmode))) + *total = 0; + else if (add_operand (x, VOIDmode) || and_operand (x, VOIDmode)) + *total = 2; + else + *total = COSTS_N_INSNS (2); + return true; + + case CONST: + case SYMBOL_REF: + case LABEL_REF: + if (TARGET_EXPLICIT_RELOCS && small_symbolic_operand (x, VOIDmode)) + *total = COSTS_N_INSNS (outer_code != MEM); + else if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, VOIDmode)) + *total = COSTS_N_INSNS (1 + (outer_code != MEM)); + else if (tls_symbolic_operand_type (x)) + /* Estimate of cost for call_pal rduniq. */ + *total = COSTS_N_INSNS (15); + else + /* Otherwise we do a load from the GOT. */ + *total = COSTS_N_INSNS (alpha_memory_latency); + return true; + + case PLUS: + case MINUS: + if (float_mode_p) + *total = alpha_rtx_cost_data[alpha_cpu].fp_add; + else if (GET_CODE (XEXP (x, 0)) == MULT + && const48_operand (XEXP (XEXP (x, 0), 1), VOIDmode)) + { + *total = (rtx_cost (XEXP (XEXP (x, 0), 0), outer_code) + + rtx_cost (XEXP (x, 1), outer_code) + 2); + return true; + } + return false; + + case MULT: + if (float_mode_p) + *total = alpha_rtx_cost_data[alpha_cpu].fp_mult; + else if (mode == DImode) + *total = alpha_rtx_cost_data[alpha_cpu].int_mult_di; + else + *total = alpha_rtx_cost_data[alpha_cpu].int_mult_si; + return false; + + case ASHIFT: + if (GET_CODE (XEXP (x, 1)) == CONST_INT + && INTVAL (XEXP (x, 1)) <= 3) + { + *total = COSTS_N_INSNS (1); + return false; + } + /* FALLTHRU */ + + case ASHIFTRT: + case LSHIFTRT: + *total = alpha_rtx_cost_data[alpha_cpu].int_shift; + return false; + + case IF_THEN_ELSE: + if (float_mode_p) + *total = alpha_rtx_cost_data[alpha_cpu].fp_add; + else + *total = alpha_rtx_cost_data[alpha_cpu].int_cmov; + return false; + + case DIV: + case UDIV: + case MOD: + case UMOD: + if (!float_mode_p) + *total = COSTS_N_INSNS (70); /* ??? */ + else if (mode == SFmode) + *total = alpha_rtx_cost_data[alpha_cpu].fp_div_sf; + else + *total = alpha_rtx_cost_data[alpha_cpu].fp_div_df; + return false; + + case MEM: + *total = COSTS_N_INSNS (alpha_memory_latency); + return true; + + case NEG: + if (! float_mode_p) + { + *total = COSTS_N_INSNS (1); + return false; + } + /* FALLTHRU */ + + case ABS: + if (! float_mode_p) + { + *total = COSTS_N_INSNS (1) + alpha_rtx_cost_data[alpha_cpu].int_cmov; + return false; + } + /* FALLTHRU */ + + case FLOAT: + case UNSIGNED_FLOAT: + case FIX: + case UNSIGNED_FIX: + case FLOAT_EXTEND: + case FLOAT_TRUNCATE: + *total = alpha_rtx_cost_data[alpha_cpu].fp_add; + return false; + + default: + return false; + } +} + /* REF is an alignable memory location. Place an aligned SImode reference into *PALIGNED_MEM and the number of bits to shift into *PBITNUM. SCRATCH is a free register for use in reloading out of range stack slots. */ void -get_aligned_mem (ref, paligned_mem, pbitnum) - rtx ref; - rtx *paligned_mem, *pbitnum; +get_aligned_mem (rtx ref, rtx *paligned_mem, rtx *pbitnum) { rtx base; HOST_WIDE_INT offset = 0; @@ -2439,9 +2281,7 @@ get_aligned_mem (ref, paligned_mem, pbitnum) Add EXTRA_OFFSET to the address we return. */ rtx -get_unaligned_address (ref, extra_offset) - rtx ref; - int extra_offset; +get_unaligned_address (rtx ref, int extra_offset) { rtx base; HOST_WIDE_INT offset = 0; @@ -2474,9 +2314,7 @@ get_unaligned_address (ref, extra_offset) symbolic constants cannot be dropped to memory. */ enum reg_class -alpha_preferred_reload_class(x, class) - rtx x; - enum reg_class class; +alpha_preferred_reload_class(rtx x, enum reg_class class) { /* Zero is present in any register class. */ if (x == CONST0_RTX (GET_MODE (x))) @@ -2513,11 +2351,8 @@ alpha_preferred_reload_class(x, class) from register elimination into a DImode fp register. */ enum reg_class -secondary_reload_class (class, mode, x, in) - enum reg_class class; - enum machine_mode mode; - rtx x; - int in; +secondary_reload_class (enum reg_class class, enum machine_mode mode, + rtx x, int in) { if ((mode == QImode || mode == HImode) && ! TARGET_BWX) { @@ -2555,9 +2390,7 @@ secondary_reload_class (class, mode, x, in) found in part of X. */ static void -alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) - rtx x; - int in_struct_p, volatile_p, unchanging_p; +alpha_set_memflags_1 (rtx x, int in_struct_p, int volatile_p, int unchanging_p) { int i; @@ -2607,9 +2440,7 @@ alpha_set_memflags_1 (x, in_struct_p, volatile_p, unchanging_p) a MEM, don't do anything. */ void -alpha_set_memflags (insn, ref) - rtx insn; - rtx ref; +alpha_set_memflags (rtx insn, rtx ref) { int in_struct_p, volatile_p, unchanging_p; @@ -2629,62 +2460,11 @@ alpha_set_memflags (insn, ref) alpha_set_memflags_1 (insn, in_struct_p, volatile_p, unchanging_p); } -/* Try to output insns to set TARGET equal to the constant C if it can be - done in less than N insns. Do all computations in MODE. Returns the place - where the output has been placed if it can be done and the insns have been - emitted. If it would take more than N insns, zero is returned and no - insns and emitted. */ - -rtx -alpha_emit_set_const (target, mode, c, n) - rtx target; - enum machine_mode mode; - HOST_WIDE_INT c; - int n; -{ - rtx result = 0; - rtx orig_target = target; - int i; - - /* If we can't make any pseudos, TARGET is an SImode hard register, we - can't load this constant in one insn, do this in DImode. */ - if (no_new_pseudos && mode == SImode - && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER - && (result = alpha_emit_set_const_1 (target, mode, c, 1)) == 0) - { - target = gen_lowpart (DImode, target); - mode = DImode; - } - - /* Try 1 insn, then 2, then up to N. */ - for (i = 1; i <= n; i++) - { - result = alpha_emit_set_const_1 (target, mode, c, i); - if (result) - { - rtx insn = get_last_insn (); - rtx set = single_set (insn); - if (! CONSTANT_P (SET_SRC (set))) - set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (c)); - break; - } - } - - /* Allow for the case where we changed the mode of TARGET. */ - if (result == target) - result = orig_target; - - return result; -} - -/* Internal routine for the above to check for N or below insns. */ +/* Internal routine for alpha_emit_set_const to check for N or below insns. */ static rtx -alpha_emit_set_const_1 (target, mode, c, n) - rtx target; - enum machine_mode mode; - HOST_WIDE_INT c; - int n; +alpha_emit_set_const_1 (rtx target, enum machine_mode mode, + HOST_WIDE_INT c, int n) { HOST_WIDE_INT new; int i, bits; @@ -2730,7 +2510,14 @@ alpha_emit_set_const_1 (target, mode, c, n) } else if (n >= 2 + (extra != 0)) { - temp = copy_to_suggested_reg (GEN_INT (high << 16), subtarget, mode); + if (no_new_pseudos) + { + emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (high << 16))); + temp = target; + } + else + temp = copy_to_suggested_reg (GEN_INT (high << 16), + subtarget, mode); /* As of 2002-02-23, addsi3 is only available when not optimizing. This means that if we go through expand_binop, we'll try to @@ -2866,15 +2653,58 @@ alpha_emit_set_const_1 (target, mode, c, n) return 0; } +/* Try to output insns to set TARGET equal to the constant C if it can be + done in less than N insns. Do all computations in MODE. Returns the place + where the output has been placed if it can be done and the insns have been + emitted. If it would take more than N insns, zero is returned and no + insns and emitted. */ + +rtx +alpha_emit_set_const (rtx target, enum machine_mode mode, + HOST_WIDE_INT c, int n) +{ + rtx result = 0; + rtx orig_target = target; + int i; + + /* If we can't make any pseudos, TARGET is an SImode hard register, we + can't load this constant in one insn, do this in DImode. */ + if (no_new_pseudos && mode == SImode + && GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER + && (result = alpha_emit_set_const_1 (target, mode, c, 1)) == 0) + { + target = gen_lowpart (DImode, target); + mode = DImode; + } + + /* Try 1 insn, then 2, then up to N. */ + for (i = 1; i <= n; i++) + { + result = alpha_emit_set_const_1 (target, mode, c, i); + if (result) + { + rtx insn = get_last_insn (); + rtx set = single_set (insn); + if (! CONSTANT_P (SET_SRC (set))) + set_unique_reg_note (get_last_insn (), REG_EQUAL, GEN_INT (c)); + break; + } + } + + /* Allow for the case where we changed the mode of TARGET. */ + if (result == target) + result = orig_target; + + return result; +} + /* Having failed to find a 3 insn sequence in alpha_emit_set_const, fall back to a straight forward decomposition. We do this to avoid exponential run times encountered when looking for longer sequences with alpha_emit_set_const. */ rtx -alpha_emit_set_long_const (target, c1, c2) - rtx target; - HOST_WIDE_INT c1, c2; +alpha_emit_set_long_const (rtx target, HOST_WIDE_INT c1, HOST_WIDE_INT c2) { HOST_WIDE_INT d1, d2, d3, d4; @@ -2931,9 +2761,7 @@ alpha_emit_set_long_const (target, c1, c2) We don't handle non-bwx subword loads here. */ bool -alpha_expand_mov (mode, operands) - enum machine_mode mode; - rtx *operands; +alpha_expand_mov (enum machine_mode mode, rtx *operands) { /* If the output is not a register, the input must be. */ if (GET_CODE (operands[0]) == MEM @@ -2949,8 +2777,12 @@ alpha_expand_mov (mode, operands) compiled at the end of compilation. In the meantime, someone can re-encode-section-info on some symbol changing it e.g. from global to local-not-small. If this happens, we'd have emitted a plain - load rather than a high+losum load and not recognize the insn. */ - if (TARGET_EXPLICIT_RELOCS + load rather than a high+losum load and not recognize the insn. + + So if rtl inlining is in effect, we delay the global/not-global + decision until rest_of_compilation by wrapping it in an + UNSPEC_SYMBOL. */ + if (TARGET_EXPLICIT_RELOCS && flag_inline_functions && rtx_equal_function_value_matters && global_symbolic_operand (operands[1], mode)) { @@ -3027,9 +2859,7 @@ alpha_expand_mov (mode, operands) return true if all work is done. */ bool -alpha_expand_mov_nobwx (mode, operands) - enum machine_mode mode; - rtx *operands; +alpha_expand_mov_nobwx (enum machine_mode mode, rtx *operands) { /* If the output is not a register, the input must be. */ if (GET_CODE (operands[0]) == MEM) @@ -3062,13 +2892,24 @@ alpha_expand_mov_nobwx (mode, operands) { rtx aligned_mem, bitnum; rtx scratch = gen_reg_rtx (SImode); + rtx subtarget; + bool copyout; get_aligned_mem (operands[1], &aligned_mem, &bitnum); + subtarget = operands[0]; + if (GET_CODE (subtarget) == REG) + subtarget = gen_lowpart (DImode, subtarget), copyout = false; + else + subtarget = gen_reg_rtx (DImode), copyout = true; + emit_insn ((mode == QImode ? gen_aligned_loadqi : gen_aligned_loadhi) - (operands[0], aligned_mem, bitnum, scratch)); + (subtarget, aligned_mem, bitnum, scratch)); + + if (copyout) + emit_move_insn (operands[0], gen_lowpart (mode, subtarget)); } } else @@ -3077,16 +2918,28 @@ alpha_expand_mov_nobwx (mode, operands) code depend on parameter evaluation order which will cause bootstrap failures. */ - rtx temp1 = gen_reg_rtx (DImode); - rtx temp2 = gen_reg_rtx (DImode); - rtx seq = ((mode == QImode - ? gen_unaligned_loadqi - : gen_unaligned_loadhi) - (operands[0], get_unaligned_address (operands[1], 0), - temp1, temp2)); + rtx temp1, temp2, seq, subtarget; + bool copyout; + temp1 = gen_reg_rtx (DImode); + temp2 = gen_reg_rtx (DImode); + + subtarget = operands[0]; + if (GET_CODE (subtarget) == REG) + subtarget = gen_lowpart (DImode, subtarget), copyout = false; + else + subtarget = gen_reg_rtx (DImode), copyout = true; + + seq = ((mode == QImode + ? gen_unaligned_loadqi + : gen_unaligned_loadhi) + (subtarget, get_unaligned_address (operands[1], 0), + temp1, temp2)); alpha_set_memflags (seq, operands[1]); emit_insn (seq); + + if (copyout) + emit_move_insn (operands[0], gen_lowpart (mode, subtarget)); } return true; } @@ -3182,8 +3035,7 @@ alpha_expand_mov_nobwx (mode, operands) much lower minimum execution time. */ void -alpha_emit_floatuns (operands) - rtx operands[2]; +alpha_emit_floatuns (rtx operands[2]) { rtx neglab, donelab, i0, i1, f0, in, out; enum machine_mode mode; @@ -3217,8 +3069,7 @@ alpha_emit_floatuns (operands) /* Generate the comparison for a conditional branch. */ rtx -alpha_emit_conditional_branch (code) - enum rtx_code code; +alpha_emit_conditional_branch (enum rtx_code code) { enum rtx_code cmp_code, branch_code; enum machine_mode cmp_mode, branch_mode = VOIDmode; @@ -3374,8 +3225,7 @@ alpha_emit_conditional_branch (code) valid. Return the final comparison, or NULL if we can't work. */ rtx -alpha_emit_setcc (code) - enum rtx_code code; +alpha_emit_setcc (enum rtx_code code) { enum rtx_code cmp_code; rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1; @@ -3486,10 +3336,9 @@ alpha_emit_setcc (code) If both of the operands that set cc0 are nonzero we must emit an insn to perform the compare (it can't be done within the conditional move). */ + rtx -alpha_emit_conditional_move (cmp, mode) - rtx cmp; - enum machine_mode mode; +alpha_emit_conditional_move (rtx cmp, enum machine_mode mode) { enum rtx_code code = GET_CODE (cmp); enum rtx_code cmov_code = NE; @@ -3624,9 +3473,8 @@ alpha_emit_conditional_move (cmp, mode) cases we wouldn't have before cse. */ int -alpha_split_conditional_move (code, dest, cond, t_rtx, f_rtx) - enum rtx_code code; - rtx dest, cond, t_rtx, f_rtx; +alpha_split_conditional_move (enum rtx_code code, rtx dest, rtx cond, + rtx t_rtx, rtx f_rtx) { HOST_WIDE_INT t, f, diff; enum machine_mode mode; @@ -3659,7 +3507,7 @@ alpha_split_conditional_move (code, dest, cond, t_rtx, f_rtx) be shared. */ if (f == 0 && exact_log2 (diff) > 0 - /* On EV6, we've got enough shifters to make non-arithmatic shifts + /* On EV6, we've got enough shifters to make non-arithmetic shifts viable over a longer latency cmove. On EV5, the E0 slot is a scarce resource, and on EV4 shift has the same latency as a cmove. */ && (diff <= 8 || alpha_cpu == PROCESSOR_EV6)) @@ -3711,8 +3559,7 @@ alpha_split_conditional_move (code, dest, cond, t_rtx, f_rtx) given operation. */ static const char * -alpha_lookup_xfloating_lib_func (code) - enum rtx_code code; +alpha_lookup_xfloating_lib_func (enum rtx_code code) { struct xfloating_op { @@ -3798,9 +3645,8 @@ alpha_lookup_xfloating_lib_func (code) Compute that here. */ static int -alpha_compute_xfloating_mode_arg (code, round) - enum rtx_code code; - enum alpha_fp_rounding_mode round; +alpha_compute_xfloating_mode_arg (enum rtx_code code, + enum alpha_fp_rounding_mode round) { int mode; @@ -3844,12 +3690,8 @@ alpha_compute_xfloating_mode_arg (code, round) */ static void -alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv) - const char *func; - rtx target; - rtx operands[]; - int noperands; - rtx equiv; +alpha_emit_xfloating_libcall (const char *func, rtx target, rtx operands[], + int noperands, rtx equiv) { rtx usage = NULL_RTX, tmp, reg; int regno = 16, i; @@ -3902,7 +3744,7 @@ alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv) abort (); } - tmp = gen_rtx_MEM (QImode, gen_rtx_SYMBOL_REF (Pmode, (char *) func)); + tmp = gen_rtx_MEM (QImode, init_one_libfunc (func)); tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx, const0_rtx, const0_rtx)); CALL_INSN_FUNCTION_USAGE (tmp) = usage; @@ -3916,9 +3758,7 @@ alpha_emit_xfloating_libcall (func, target, operands, noperands, equiv) /* Emit an X_floating library function call for arithmetic (+,-,*,/). */ void -alpha_emit_xfloating_arith (code, operands) - enum rtx_code code; - rtx operands[]; +alpha_emit_xfloating_arith (enum rtx_code code, rtx operands[]) { const char *func; int mode; @@ -3938,9 +3778,7 @@ alpha_emit_xfloating_arith (code, operands) /* Emit an X_floating library function call for a comparison. */ static rtx -alpha_emit_xfloating_compare (code, op0, op1) - enum rtx_code code; - rtx op0, op1; +alpha_emit_xfloating_compare (enum rtx_code code, rtx op0, rtx op1) { const char *func; rtx out, operands[2]; @@ -3962,13 +3800,15 @@ alpha_emit_xfloating_compare (code, op0, op1) /* Emit an X_floating library function call for a conversion. */ void -alpha_emit_xfloating_cvt (code, operands) - enum rtx_code code; - rtx operands[]; +alpha_emit_xfloating_cvt (enum rtx_code orig_code, rtx operands[]) { int noperands = 1, mode; rtx out_operands[2]; const char *func; + enum rtx_code code = orig_code; + + if (code == UNSIGNED_FIX) + code = FIX; func = alpha_lookup_xfloating_lib_func (code); @@ -3991,7 +3831,8 @@ alpha_emit_xfloating_cvt (code, operands) } alpha_emit_xfloating_libcall (func, operands[0], out_operands, noperands, - gen_rtx_fmt_e (code, GET_MODE (operands[0]), + gen_rtx_fmt_e (orig_code, + GET_MODE (operands[0]), operands[1])); } @@ -4000,8 +3841,7 @@ alpha_emit_xfloating_cvt (code, operands) little-endian. */ void -alpha_split_tfmode_pair (operands) - rtx operands[4]; +alpha_split_tfmode_pair (rtx operands[4]) { if (GET_CODE (operands[1]) == REG) { @@ -4037,9 +3877,7 @@ alpha_split_tfmode_pair (operands) logical operation to be performed. */ void -alpha_split_tfmode_frobsign (operands, operation) - rtx operands[3]; - rtx (*operation) PARAMS ((rtx, rtx, rtx)); +alpha_split_tfmode_frobsign (rtx operands[3], rtx (*operation) (rtx, rtx, rtx)) { rtx high_bit = operands[2]; rtx scratch; @@ -4106,10 +3944,8 @@ alpha_split_tfmode_frobsign (operands, operation) */ void -alpha_expand_unaligned_load (tgt, mem, size, ofs, sign) - rtx tgt, mem; - HOST_WIDE_INT size, ofs; - int sign; +alpha_expand_unaligned_load (rtx tgt, rtx mem, HOST_WIDE_INT size, + HOST_WIDE_INT ofs, int sign) { rtx meml, memh, addr, extl, exth, tmp, mema; enum machine_mode mode; @@ -4232,9 +4068,8 @@ alpha_expand_unaligned_load (tgt, mem, size, ofs, sign) /* Similarly, use ins and msk instructions to perform unaligned stores. */ void -alpha_expand_unaligned_store (dst, src, size, ofs) - rtx dst, src; - HOST_WIDE_INT size, ofs; +alpha_expand_unaligned_store (rtx dst, rtx src, + HOST_WIDE_INT size, HOST_WIDE_INT ofs) { rtx dstl, dsth, addr, insl, insh, meml, memh, dsta; @@ -4377,10 +4212,8 @@ alpha_expand_unaligned_store (dst, src, size, ofs) /* Load an integral number of consecutive unaligned quadwords. */ static void -alpha_expand_unaligned_load_words (out_regs, smem, words, ofs) - rtx *out_regs; - rtx smem; - HOST_WIDE_INT words, ofs; +alpha_expand_unaligned_load_words (rtx *out_regs, rtx smem, + HOST_WIDE_INT words, HOST_WIDE_INT ofs) { rtx const im8 = GEN_INT (-8); rtx const i64 = GEN_INT (64); @@ -4461,10 +4294,8 @@ alpha_expand_unaligned_load_words (out_regs, smem, words, ofs) may be NULL to store zeros. */ static void -alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) - rtx *data_regs; - rtx dmem; - HOST_WIDE_INT words, ofs; +alpha_expand_unaligned_store_words (rtx *data_regs, rtx dmem, + HOST_WIDE_INT words, HOST_WIDE_INT ofs) { rtx const im8 = GEN_INT (-8); rtx const i64 = GEN_INT (64); @@ -4578,8 +4409,7 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs) operands[3] is the alignment. */ int -alpha_expand_block_move (operands) - rtx operands[]; +alpha_expand_block_move (rtx operands[]) { rtx bytes_rtx = operands[2]; rtx align_rtx = operands[3]; @@ -4653,7 +4483,8 @@ alpha_expand_block_move (operands) is held in the register. Nor if there is not a mode that handles the exact size. */ mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 1); - if (mode != BLKmode + if (GET_CODE (tmp) == REG + && mode != BLKmode && GET_MODE_SIZE (GET_MODE (tmp)) >= bytes) { if (mode == TImode) @@ -4773,7 +4604,7 @@ alpha_expand_block_move (operands) tmp = XEXP (XEXP (orig_dst, 0), 0); mode = mode_for_size (orig_bytes * BITS_PER_UNIT, MODE_INT, 1); - if (GET_MODE (tmp) == mode) + if (GET_CODE (tmp) == REG && GET_MODE (tmp) == mode) { if (nregs == 1) { @@ -4915,8 +4746,7 @@ alpha_expand_block_move (operands) } int -alpha_expand_block_clear (operands) - rtx operands[]; +alpha_expand_block_clear (rtx operands[]) { rtx bytes_rtx = operands[1]; rtx align_rtx = operands[2]; @@ -5206,8 +5036,7 @@ alpha_expand_block_clear (operands) /* Returns a mask so that zap(x, value) == x & mask. */ rtx -alpha_expand_zap_mask (value) - HOST_WIDE_INT value; +alpha_expand_zap_mask (HOST_WIDE_INT value) { rtx result; int i; @@ -5252,10 +5081,9 @@ alpha_expand_zap_mask (value) } void -alpha_expand_builtin_vector_binop (gen, mode, op0, op1, op2) - rtx (*gen) PARAMS ((rtx, rtx, rtx)); - enum machine_mode mode; - rtx op0, op1, op2; +alpha_expand_builtin_vector_binop (rtx (*gen) (rtx, rtx, rtx), + enum machine_mode mode, + rtx op0, rtx op1, rtx op2) { op0 = gen_lowpart (mode, op0); @@ -5276,11 +5104,7 @@ alpha_expand_builtin_vector_binop (gen, mode, op0, op1, op2) a dependency LINK or INSN on DEP_INSN. COST is the current cost. */ static int -alpha_adjust_cost (insn, link, dep_insn, cost) - rtx insn; - rtx link; - rtx dep_insn; - int cost; +alpha_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost) { enum attr_type insn_type, dep_insn_type; @@ -5311,13 +5135,13 @@ alpha_adjust_cost (insn, link, dep_insn, cost) /* The number of instructions that can be issued per cycle. */ static int -alpha_issue_rate () +alpha_issue_rate (void) { return (alpha_cpu == PROCESSOR_EV4 ? 2 : 4); } static int -alpha_use_dfa_pipeline_interface () +alpha_use_dfa_pipeline_interface (void) { return true; } @@ -5328,10 +5152,10 @@ alpha_use_dfa_pipeline_interface () For EV4, loads can be issued to either IB0 or IB1, thus we have 2 alternative schedules. For EV5, we can choose between E0/E1 and - FA/FM. For EV6, an arithmatic insn can be issued to U0/U1/L0/L1. */ + FA/FM. For EV6, an arithmetic insn can be issued to U0/U1/L0/L1. */ static int -alpha_multipass_dfa_lookahead () +alpha_multipass_dfa_lookahead (void) { return (alpha_cpu == PROCESSOR_EV6 ? 4 : 2); } @@ -5340,7 +5164,7 @@ alpha_multipass_dfa_lookahead () struct machine_function GTY(()) { - /* For unicosmk. */ + /* For unicosmk. */ /* List of call information words for calls from this function. */ struct rtx_def *first_ciw; struct rtx_def *last_ciw; @@ -5349,14 +5173,14 @@ struct machine_function GTY(()) /* List of deferred case vectors. */ struct rtx_def *addr_list; - /* For OSF. */ + /* For OSF. */ const char *some_ld_name; }; /* How to allocate a 'struct machine_function'. */ static struct machine_function * -alpha_init_machine_status () +alpha_init_machine_status (void) { return ((struct machine_function *) ggc_alloc_cleared (sizeof (struct machine_function))); @@ -5367,9 +5191,7 @@ alpha_init_machine_status () /* Start the ball rolling with RETURN_ADDR_RTX. */ rtx -alpha_return_addr (count, frame) - int count; - rtx frame ATTRIBUTE_UNUSED; +alpha_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) { if (count != 0) return const0_rtx; @@ -5381,7 +5203,7 @@ alpha_return_addr (count, frame) function. Needed only if TARGET_LD_BUGGY_LDGP. */ rtx -alpha_gp_save_rtx () +alpha_gp_save_rtx (void) { rtx r = get_hard_reg_initial_val (DImode, 29); if (GET_CODE (r) != MEM) @@ -5390,7 +5212,7 @@ alpha_gp_save_rtx () } static int -alpha_ra_ever_killed () +alpha_ra_ever_killed (void) { rtx top; @@ -5409,7 +5231,7 @@ alpha_ra_ever_killed () instruction, or NULL. */ static const char * -get_trap_mode_suffix () +get_trap_mode_suffix (void) { enum attr_trap_suffix s = get_attr_trap_suffix (current_output_insn); @@ -5476,7 +5298,7 @@ get_trap_mode_suffix () instruction, or NULL. */ static const char * -get_round_mode_suffix () +get_round_mode_suffix (void) { enum attr_round_suffix s = get_attr_round_suffix (current_output_insn); @@ -5507,8 +5329,23 @@ get_round_mode_suffix () /* Locate some local-dynamic symbol still in use by this function so that we can print its name in some movdi_er_tlsldm pattern. */ +static int +get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED) +{ + rtx x = *px; + + if (GET_CODE (x) == SYMBOL_REF + && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC) + { + cfun->machine->some_ld_name = XSTR (x, 0); + return 1; + } + + return 0; +} + static const char * -get_some_local_dynamic_name () +get_some_local_dynamic_name (void) { rtx insn; @@ -5523,33 +5360,10 @@ get_some_local_dynamic_name () abort (); } -static int -get_some_local_dynamic_name_1 (px, data) - rtx *px; - void *data ATTRIBUTE_UNUSED; -{ - rtx x = *px; - - if (GET_CODE (x) == SYMBOL_REF) - { - const char *str = XSTR (x, 0); - if (str[0] == '@' && str[1] == 'D') - { - cfun->machine->some_ld_name = str; - return 1; - } - } - - return 0; -} - /* Print an operand. Recognize special options, documented below. */ void -print_operand (file, x, code) - FILE *file; - rtx x; - int code; +print_operand (FILE *file, rtx x, int code) { int i; @@ -5585,6 +5399,13 @@ print_operand (file, x, code) fputc ((TARGET_FLOAT_VAX ? 'g' : 't'), file); break; + case '+': + /* Generates a nop after a noreturn call at the very end of the + function. */ + if (next_real_insn (current_output_insn) == 0) + fprintf (file, "\n\tnop"); + break; + case '#': if (alpha_this_literal_sequence_number == 0) alpha_this_literal_sequence_number = alpha_next_sequence_number++; @@ -5894,9 +5715,7 @@ print_operand (file, x, code) } void -print_operand_address (file, addr) - FILE *file; - rtx addr; +print_operand_address (FILE *file, rtx addr) { int basereg = 31; HOST_WIDE_INT offset = 0; @@ -5944,10 +5763,7 @@ print_operand_address (file, addr) } if (offset) - { - fputc ('+', file); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset); - } + fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC, offset); addr = XEXP (addr, 0); if (GET_CODE (addr) == REG) @@ -5981,7 +5797,7 @@ print_operand_address (file, addr) && GET_CODE (XEXP (addr, 0)) == PLUS && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF) { - fprintf (file, "%s+%d", + fprintf (file, "%s+" HOST_WIDE_INT_PRINT_DEC, XSTR (XEXP (XEXP (addr, 0), 0), 0), INTVAL (XEXP (XEXP (addr, 0), 1))); return; @@ -5991,8 +5807,7 @@ print_operand_address (file, addr) else abort (); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset); - fprintf (file, "($%d)", basereg); + fprintf (file, HOST_WIDE_INT_PRINT_DEC "($%d)", offset, basereg); } /* Emit RTL insns to initialize the variable parts of a trampoline at @@ -6009,9 +5824,8 @@ print_operand_address (file, addr) Note that the hint field is PC (new) + 4 * bits 13:0. */ void -alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs) - rtx tramp, fnaddr, cxt; - int fnofs, cxtofs, jmpofs; +alpha_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt, + int fnofs, int cxtofs, int jmpofs) { rtx temp, temp1, addr; /* VMS really uses DImode pointers in memory at this point. */ @@ -6050,8 +5864,8 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs) emit_move_insn (gen_rtx_MEM (SImode, addr), temp1); } -#ifdef TRANSFER_FROM_TRAMPOLINE - emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"), +#ifdef ENABLE_EXECUTE_STACK + emit_library_call (init_one_libfunc ("__enable_execute_stack"), 0, VOIDmode, 1, tramp, Pmode); #endif @@ -6076,23 +5890,31 @@ alpha_initialize_trampoline (tramp, fnaddr, cxt, fnofs, cxtofs, jmpofs) and the rest are pushed. */ rtx -function_arg (cum, mode, type, named) - CUMULATIVE_ARGS cum; - enum machine_mode mode; - tree type; - int named ATTRIBUTE_UNUSED; +function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode, tree type, + int named ATTRIBUTE_UNUSED) { int basereg; int num_args; - /* Set up defaults for FP operands passed in FP registers, and - integral operands passed in integer registers. */ - if (TARGET_FPREGS - && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT - || GET_MODE_CLASS (mode) == MODE_FLOAT)) - basereg = 32 + 16; - else + /* Don't get confused and pass small structures in FP registers. */ + if (type && AGGREGATE_TYPE_P (type)) basereg = 16; + else + { +#ifdef ENABLE_CHECKING + /* With alpha_split_complex_arg, we shouldn't see any raw complex + values here. */ + if (COMPLEX_MODE_P (mode)) + abort (); +#endif + + /* Set up defaults for FP operands passed in FP registers, and + integral operands passed in integer registers. */ + if (TARGET_FPREGS && GET_MODE_CLASS (mode) == MODE_FLOAT) + basereg = 32 + 16; + else + basereg = 16; + } /* ??? Irritatingly, the definition of CUMULATIVE_ARGS is different for the three platforms, so we can't avoid conditional compilation. */ @@ -6105,8 +5927,7 @@ function_arg (cum, mode, type, named) if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type)) return NULL_RTX; } -#else -#if TARGET_ABI_UNICOSMK +#elif TARGET_ABI_UNICOSMK { int size; @@ -6170,7 +5991,7 @@ function_arg (cum, mode, type, named) } } } -#else +#elif TARGET_ABI_OSF { if (cum >= 6) return NULL_RTX; @@ -6184,16 +6005,133 @@ function_arg (cum, mode, type, named) else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named)) basereg = 16; } -#endif /* TARGET_ABI_UNICOSMK */ -#endif /* TARGET_ABI_OPEN_VMS */ +#else +#error Unhandled ABI +#endif return gen_rtx_REG (mode, num_args + basereg); } -tree -alpha_build_va_list () +/* Return true if TYPE must be returned in memory, instead of in registers. */ + +static bool +alpha_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED) +{ + enum machine_mode mode = VOIDmode; + int size; + + if (type) + { + mode = TYPE_MODE (type); + + /* All aggregates are returned in memory. */ + if (AGGREGATE_TYPE_P (type)) + return true; + } + + size = GET_MODE_SIZE (mode); + switch (GET_MODE_CLASS (mode)) + { + case MODE_VECTOR_FLOAT: + /* Pass all float vectors in memory, like an aggregate. */ + return true; + + case MODE_COMPLEX_FLOAT: + /* We judge complex floats on the size of their element, + not the size of the whole type. */ + size = GET_MODE_UNIT_SIZE (mode); + break; + + case MODE_INT: + case MODE_FLOAT: + case MODE_COMPLEX_INT: + case MODE_VECTOR_INT: + break; + + default: + /* ??? We get called on all sorts of random stuff from + aggregate_value_p. We can't abort, but it's not clear + what's safe to return. Pretend it's a struct I guess. */ + return true; + } + + /* Otherwise types must fit in one register. */ + return size > UNITS_PER_WORD; +} + +/* Define how to find the value returned by a function. VALTYPE is the + data type of the value (as a tree). If the precise function being + called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0. + MODE is set instead of VALTYPE for libcalls. + + On Alpha the value is found in $0 for integer functions and + $f0 for floating-point functions. */ + +rtx +function_value (tree valtype, tree func ATTRIBUTE_UNUSED, + enum machine_mode mode) +{ + unsigned int regnum; + enum mode_class class; + +#ifdef ENABLE_CHECKING + if (valtype && alpha_return_in_memory (valtype, func)) + abort (); +#endif + + if (valtype) + mode = TYPE_MODE (valtype); + + class = GET_MODE_CLASS (mode); + switch (class) + { + case MODE_INT: + /* Do the same thing as PROMOTE_MODE. */ + mode = DImode; + /* FALLTHRU */ + + case MODE_COMPLEX_INT: + case MODE_VECTOR_INT: + regnum = 0; + break; + + case MODE_FLOAT: + regnum = 32; + break; + + case MODE_COMPLEX_FLOAT: + { + enum machine_mode cmode = GET_MODE_INNER (mode); + + return gen_rtx_PARALLEL + (VOIDmode, + gen_rtvec (2, + gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 32), + GEN_INT (0)), + gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (cmode, 33), + GEN_INT (GET_MODE_SIZE (cmode))))); + } + + default: + abort (); + } + + return gen_rtx_REG (mode, regnum); +} + +/* TCmode complex values are passed by invisible reference. We + should not split these values. */ + +static bool +alpha_split_complex_arg (tree type) { - tree base, ofs, record, type_decl; + return TYPE_MODE (type) != TCmode; +} + +static tree +alpha_build_builtin_va_list (void) +{ + tree base, ofs, space, record, type_decl; if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK) return ptr_type_node; @@ -6205,9 +6143,16 @@ alpha_build_va_list () /* C++? SET_IS_AGGR_TYPE (record, 1); */ + /* Dummy field to prevent alignment warnings. */ + space = build_decl (FIELD_DECL, NULL_TREE, integer_type_node); + DECL_FIELD_CONTEXT (space) = record; + DECL_ARTIFICIAL (space) = 1; + DECL_IGNORED_P (space) = 1; + ofs = build_decl (FIELD_DECL, get_identifier ("__offset"), integer_type_node); DECL_FIELD_CONTEXT (ofs) = record; + TREE_CHAIN (ofs) = space; base = build_decl (FIELD_DECL, get_identifier ("__base"), ptr_type_node); @@ -6220,10 +6165,87 @@ alpha_build_va_list () return record; } +/* Perform any needed actions needed for a function that is receiving a + variable number of arguments. */ + +static void +alpha_setup_incoming_varargs (CUMULATIVE_ARGS *pcum, + enum machine_mode mode ATTRIBUTE_UNUSED, + tree type ATTRIBUTE_UNUSED, + int *pretend_size, int no_rtl) +{ +#if TARGET_ABI_UNICOSMK + /* On Unicos/Mk, the standard subroutine __T3E_MISMATCH stores all register + arguments on the stack. Unfortunately, it doesn't always store the first + one (i.e. the one that arrives in $16 or $f16). This is not a problem + with stdargs as we always have at least one named argument there. */ + int num_reg_words = pcum->num_reg_words; + if (num_reg_words < 6) + { + if (!no_rtl) + { + emit_insn (gen_umk_mismatch_args (GEN_INT (num_reg_words + 1))); + emit_insn (gen_arg_home_umk ()); + } + *pretend_size = 0; + } +#elif TARGET_ABI_OPEN_VMS + /* For VMS, we allocate space for all 6 arg registers plus a count. + + However, if NO registers need to be saved, don't allocate any space. + This is not only because we won't need the space, but because AP + includes the current_pretend_args_size and we don't want to mess up + any ap-relative addresses already made. */ + if (pcum->num_args < 6) + { + if (!no_rtl) + { + emit_move_insn (gen_rtx_REG (DImode, 1), virtual_incoming_args_rtx); + emit_insn (gen_arg_home ()); + } + *pretend_size = 7 * UNITS_PER_WORD; + } +#else + /* On OSF/1 and friends, we allocate space for all 12 arg registers, but + only push those that are remaining. However, if NO registers need to + be saved, don't allocate any space. This is not only because we won't + need the space, but because AP includes the current_pretend_args_size + and we don't want to mess up any ap-relative addresses already made. + + If we are not to use the floating-point registers, save the integer + registers where we would put the floating-point registers. This is + not the most efficient way to implement varargs with just one register + class, but it isn't worth doing anything more efficient in this rare + case. */ + CUMULATIVE_ARGS cum = *pcum; + + if (cum >= 6) + return; + + if (!no_rtl) + { + int set = get_varargs_alias_set (); + rtx tmp; + + tmp = gen_rtx_MEM (BLKmode, + plus_constant (virtual_incoming_args_rtx, + (cum + 6) * UNITS_PER_WORD)); + set_mem_alias_set (tmp, set); + move_block_from_reg (16 + cum, tmp, 6 - cum); + + tmp = gen_rtx_MEM (BLKmode, + plus_constant (virtual_incoming_args_rtx, + cum * UNITS_PER_WORD)); + set_mem_alias_set (tmp, set); + move_block_from_reg (16 + (TARGET_FPREGS ? 32 : 0) + cum, tmp, + 6 - cum); + } + *pretend_size = 12 * UNITS_PER_WORD; +#endif +} + void -alpha_va_start (valist, nextarg) - tree valist; - rtx nextarg ATTRIBUTE_UNUSED; +alpha_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) { HOST_WIDE_INT offset; tree t, offset_field, base_field; @@ -6285,8 +6307,7 @@ alpha_va_start (valist, nextarg) } rtx -alpha_va_arg (valist, type) - tree valist, type; +alpha_va_arg (tree valist, tree type) { rtx addr; tree t, type_size, rounded_size; @@ -6339,7 +6360,27 @@ alpha_va_arg (valist, type) indirect = 1; rounded_size = size_int (UNITS_PER_WORD); } - else if (FLOAT_TYPE_P (type)) + else if (TREE_CODE (type) == COMPLEX_TYPE) + { + rtx real_part, imag_part, value, tmp; + + real_part = alpha_va_arg (valist, TREE_TYPE (type)); + imag_part = alpha_va_arg (valist, TREE_TYPE (type)); + + /* ??? Most irritatingly, we're not returning the value here, + but the address. Since real_part and imag_part are not + necessarily contiguous, we must copy to local storage. */ + + real_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), real_part); + imag_part = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (type)), imag_part); + value = gen_rtx_CONCAT (TYPE_MODE (type), real_part, imag_part); + + tmp = assign_temp (type, 0, 1, 0); + emit_move_insn (tmp, value); + + return XEXP (tmp, 0); + } + else if (TREE_CODE (type) == REAL_TYPE) { tree fpaddend, cond; @@ -6546,7 +6587,7 @@ static struct alpha_builtin_def const two_arg_builtins[] = { }; static void -alpha_init_builtins () +alpha_init_builtins (void) { const struct alpha_builtin_def *p; tree ftype; @@ -6597,12 +6638,10 @@ alpha_init_builtins () IGNORE is nonzero if the value is to be ignored. */ static rtx -alpha_expand_builtin (exp, target, subtarget, mode, ignore) - tree exp; - rtx target; - rtx subtarget ATTRIBUTE_UNUSED; - enum machine_mode mode ATTRIBUTE_UNUSED; - int ignore ATTRIBUTE_UNUSED; +alpha_expand_builtin (tree exp, rtx target, + rtx subtarget ATTRIBUTE_UNUSED, + enum machine_mode mode ATTRIBUTE_UNUSED, + int ignore ATTRIBUTE_UNUSED) { #define MAX_ARGS 2 @@ -6686,7 +6725,7 @@ alpha_expand_builtin (exp, target, subtarget, mode, ignore) /* These variables are used for communication between the following functions. They indicate various things about the current function being compiled that are used to tell what kind of prologue, epilogue and procedure - descriptior to generate. */ + descriptor to generate. */ /* Nonzero if we need a stack procedure. */ enum alpha_procedure_types {PT_NULL = 0, PT_REGISTER = 1, PT_STACK = 2}; @@ -6706,21 +6745,16 @@ static int vms_base_regno; /* Compute register masks for saved registers. */ static void -alpha_sa_mask (imaskP, fmaskP) - unsigned long *imaskP; - unsigned long *fmaskP; +alpha_sa_mask (unsigned long *imaskP, unsigned long *fmaskP) { unsigned long imask = 0; unsigned long fmask = 0; unsigned int i; - /* Irritatingly, there are two kinds of thunks -- those created with - TARGET_ASM_OUTPUT_MI_THUNK and those with DECL_THUNK_P that go - through the regular part of the compiler. In the - TARGET_ASM_OUTPUT_MI_THUNK case we don't have valid register life - info, but assemble_start_function wants to output .frame and - .mask directives. */ - if (current_function_is_thunk && !no_new_pseudos) + /* When outputting a thunk, we don't have valid register life info, + but assemble_start_function wants to output .frame and .mask + directives. */ + if (current_function_is_thunk) { *imaskP = 0; *fmaskP = 0; @@ -6728,7 +6762,7 @@ alpha_sa_mask (imaskP, fmaskP) } if (TARGET_ABI_OPEN_VMS && alpha_procedure_type == PT_STACK) - imask |= (1L << HARD_FRAME_POINTER_REGNUM); + imask |= (1UL << HARD_FRAME_POINTER_REGNUM); /* One for every register we have to save. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) @@ -6737,9 +6771,9 @@ alpha_sa_mask (imaskP, fmaskP) && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM)) { if (i < 32) - imask |= (1L << i); + imask |= (1UL << i); else - fmask |= (1L << (i - 32)); + fmask |= (1UL << (i - 32)); } /* We need to restore these for the handler. */ @@ -6750,7 +6784,7 @@ alpha_sa_mask (imaskP, fmaskP) unsigned regno = EH_RETURN_DATA_REGNO (i); if (regno == INVALID_REGNUM) break; - imask |= 1L << regno; + imask |= 1UL << regno; } /* Glibc likes to use $31 as an unwind stopper for crt0. To @@ -6758,19 +6792,19 @@ alpha_sa_mask (imaskP, fmaskP) zero in the prologue of _Unwind_RaiseException et al. */ imask |= 1UL << 31; } - + /* If any register spilled, then spill the return address also. */ /* ??? This is required by the Digital stack unwind specification and isn't needed if we're doing Dwarf2 unwinding. */ if (imask || fmask || alpha_ra_ever_killed ()) - imask |= (1L << REG_RA); + imask |= (1UL << REG_RA); *imaskP = imask; *fmaskP = fmask; } int -alpha_sa_size () +alpha_sa_size (void) { unsigned long mask[2]; int sa_size = 0; @@ -6872,15 +6906,39 @@ alpha_sa_size () return sa_size * 8; } +/* Define the offset between two registers, one to be eliminated, + and the other its replacement, at the start of a routine. */ + +HOST_WIDE_INT +alpha_initial_elimination_offset (unsigned int from, + unsigned int to ATTRIBUTE_UNUSED) +{ + HOST_WIDE_INT ret; + + ret = alpha_sa_size (); + ret += ALPHA_ROUND (current_function_outgoing_args_size); + + if (from == FRAME_POINTER_REGNUM) + ; + else if (from == ARG_POINTER_REGNUM) + ret += (ALPHA_ROUND (get_frame_size () + + current_function_pretend_args_size) + - current_function_pretend_args_size); + else + abort (); + + return ret; +} + int -alpha_pv_save_size () +alpha_pv_save_size (void) { alpha_sa_size (); return alpha_procedure_type == PT_STACK ? 8 : 0; } int -alpha_using_fp () +alpha_using_fp (void) { alpha_sa_size (); return vms_unwind_regno == HARD_FRAME_POINTER_REGNUM; @@ -6900,22 +6958,19 @@ const struct attribute_spec vms_attribute_table[] = #endif static int -find_lo_sum_using_gp (px, data) - rtx *px; - void *data ATTRIBUTE_UNUSED; +find_lo_sum_using_gp (rtx *px, void *data ATTRIBUTE_UNUSED) { return GET_CODE (*px) == LO_SUM && XEXP (*px, 0) == pic_offset_table_rtx; } int -alpha_find_lo_sum_using_gp (insn) - rtx insn; +alpha_find_lo_sum_using_gp (rtx insn) { return for_each_rtx (&PATTERN (insn), find_lo_sum_using_gp, NULL) > 0; } static int -alpha_does_function_need_gp () +alpha_does_function_need_gp (void) { rtx insn; @@ -6923,12 +6978,21 @@ alpha_does_function_need_gp () if (! TARGET_ABI_OSF) return 0; + /* We need the gp to load the address of __mcount. */ if (TARGET_PROFILING_NEEDS_GP && current_function_profile) return 1; + /* The code emitted by alpha_output_mi_thunk_osf uses the gp. */ if (current_function_is_thunk) return 1; + /* The nonlocal receiver pattern assumes that the gp is valid for + the nested function. Reasonable because it's almost always set + correctly already. For the cases where that's wrong, make sure + the nested function loads its gp on entry. */ + if (current_function_has_nonlocal_goto) + return 1; + /* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first. Even if we are a static function, we still need to do this in case our address is taken and passed to something like qsort. */ @@ -6947,27 +7011,12 @@ alpha_does_function_need_gp () return 0; } -/* Write a version stamp. Don't write anything if we are running as a - cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */ - -#ifdef HAVE_STAMP_H -#include <stamp.h> -#endif - -void -alpha_write_verstamp (file) - FILE *file ATTRIBUTE_UNUSED; -{ -#ifdef MS_STAMP - fprintf (file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP); -#endif -} /* Helper function to set RTX_FRAME_RELATED_P on instructions, including sequences. */ static rtx -set_frame_related_p () +set_frame_related_p (void) { rtx seq = get_insns (); rtx insn; @@ -7015,7 +7064,7 @@ set_frame_related_p () simply allocate stack without saving registers. */ void -alpha_expand_prologue () +alpha_expand_prologue (void) { /* Registers to save. */ unsigned long imask = 0; @@ -7143,15 +7192,14 @@ alpha_expand_prologue () and subtract it to sp. Yes, that's correct -- we have to reload the whole constant - into a temporary via ldah+lda then subtract from sp. To - ensure we get ldah+lda, we use a special pattern. */ + into a temporary via ldah+lda then subtract from sp. */ HOST_WIDE_INT lo, hi; lo = ((frame_size & 0xffff) ^ 0x8000) - 0x8000; hi = frame_size - lo; emit_move_insn (ptr, GEN_INT (hi)); - emit_insn (gen_nt_lda (ptr, GEN_INT (lo))); + emit_insn (gen_adddi3 (ptr, ptr, GEN_INT (lo))); seq = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx, ptr)); } @@ -7203,18 +7251,18 @@ alpha_expand_prologue () } /* Save register RA next. */ - if (imask & (1L << REG_RA)) + if (imask & (1UL << REG_RA)) { mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); set_mem_alias_set (mem, alpha_sr_alias_set); FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA))); - imask &= ~(1L << REG_RA); + imask &= ~(1UL << REG_RA); reg_offset += 8; } /* Now save any other registers required to be saved. */ for (i = 0; i < 31; i++) - if (imask & (1L << i)) + if (imask & (1UL << i)) { mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); set_mem_alias_set (mem, alpha_sr_alias_set); @@ -7224,24 +7272,24 @@ alpha_expand_prologue () /* Store a zero if requested for unwinding. */ if (imask & (1UL << 31)) - { - rtx insn, t; - - mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); - set_mem_alias_set (mem, alpha_sr_alias_set); - insn = emit_move_insn (mem, const0_rtx); - - RTX_FRAME_RELATED_P (insn) = 1; - t = gen_rtx_REG (Pmode, 31); - t = gen_rtx_SET (VOIDmode, mem, t); - t = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, t, REG_NOTES (insn)); - REG_NOTES (insn) = t; - - reg_offset += 8; - } - + { + rtx insn, t; + + mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset)); + set_mem_alias_set (mem, alpha_sr_alias_set); + insn = emit_move_insn (mem, const0_rtx); + + RTX_FRAME_RELATED_P (insn) = 1; + t = gen_rtx_REG (Pmode, 31); + t = gen_rtx_SET (VOIDmode, mem, t); + t = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, t, REG_NOTES (insn)); + REG_NOTES (insn) = t; + + reg_offset += 8; + } + for (i = 0; i < 31; i++) - if (fmask & (1L << i)) + if (fmask & (1UL << i)) { mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset)); set_mem_alias_set (mem, alpha_sr_alias_set); @@ -7257,7 +7305,7 @@ alpha_expand_prologue () reg_offset = -56; for (i = 9; i < 15; i++) - if (imask & (1L << i)) + if (imask & (1UL << i)) { mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx, reg_offset)); @@ -7266,7 +7314,7 @@ alpha_expand_prologue () reg_offset -= 8; } for (i = 2; i < 10; i++) - if (fmask & (1L << i)) + if (fmask & (1UL << i)) { mem = gen_rtx_MEM (DFmode, plus_constant (hard_frame_pointer_rtx, reg_offset)); @@ -7294,11 +7342,31 @@ alpha_expand_prologue () /* If we have to allocate space for outgoing args, do it now. */ if (current_function_outgoing_args_size != 0) - FRP (emit_move_insn - (stack_pointer_rtx, - plus_constant (hard_frame_pointer_rtx, - - (ALPHA_ROUND - (current_function_outgoing_args_size))))); + { + rtx seq + = emit_move_insn (stack_pointer_rtx, + plus_constant + (hard_frame_pointer_rtx, + - (ALPHA_ROUND + (current_function_outgoing_args_size)))); + + /* Only set FRAME_RELATED_P on the stack adjustment we just emitted + if ! frame_pointer_needed. Setting the bit will change the CFA + computation rule to use sp again, which would be wrong if we had + frame_pointer_needed, as this means sp might move unpredictably + later on. + + Also, note that + frame_pointer_needed + => vms_unwind_regno == HARD_FRAME_POINTER_REGNUM + and + current_function_outgoing_args_size != 0 + => alpha_procedure_type != PT_NULL, + + so when we are not setting the bit here, we are guaranteed to + have emitted an FRP frame pointer update just before. */ + RTX_FRAME_RELATED_P (seq) = ! frame_pointer_needed; + } } else if (!TARGET_ABI_UNICOSMK) { @@ -7332,17 +7400,15 @@ alpha_expand_prologue () /* Output the textual info surrounding the prologue. */ void -alpha_start_function (file, fnname, decl) - FILE *file; - const char *fnname; - tree decl ATTRIBUTE_UNUSED; +alpha_start_function (FILE *file, const char *fnname, + tree decl ATTRIBUTE_UNUSED) { unsigned long imask = 0; unsigned long fmask = 0; /* Stack space needed for pushing registers clobbered by us. */ HOST_WIDE_INT sa_size; /* Complete stack size needed. */ - HOST_WIDE_INT frame_size; + unsigned HOST_WIDE_INT frame_size; /* Offset from base reg to register save area. */ HOST_WIDE_INT reg_offset; char *entry_label = (char *) alloca (strlen (fnname) + 6); @@ -7400,7 +7466,7 @@ alpha_start_function (file, fnname, decl) #ifdef ASM_OUTPUT_SOURCE_LINE if (debug_info_level != DINFO_LEVEL_TERSE) ASM_OUTPUT_SOURCE_LINE (file, - DECL_SOURCE_LINE (current_function_decl)); + DECL_SOURCE_LINE (current_function_decl), 0); #endif } @@ -7458,23 +7524,17 @@ alpha_start_function (file, fnname, decl) if (TARGET_ABI_UNICOSMK) ; else if (TARGET_ABI_OPEN_VMS) - { - fprintf (file, "\t.frame $%d,", vms_unwind_regno); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - frame_size >= ((HOST_WIDE_INT) 1 << 31) ? 0 : frame_size); - fputs (",$26,", file); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, reg_offset); - fputs ("\n", file); - } + fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26," + HOST_WIDE_INT_PRINT_DEC "\n", + vms_unwind_regno, + frame_size >= (1UL << 31) ? 0 : frame_size, + reg_offset); else if (!flag_inhibit_size_directive) - { - fprintf (file, "\t.frame $%d,", - (frame_pointer_needed - ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM)); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - frame_size >= (1l << 31) ? 0 : frame_size); - fprintf (file, ",$26,%d\n", current_function_pretend_args_size); - } + fprintf (file, "\t.frame $%d," HOST_WIDE_INT_PRINT_DEC ",$26,%d\n", + (frame_pointer_needed + ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM), + frame_size >= (1UL << 31) ? 0 : frame_size, + current_function_pretend_args_size); /* Describe which registers were spilled. */ if (TARGET_ABI_UNICOSMK) @@ -7484,7 +7544,7 @@ alpha_start_function (file, fnname, decl) if (imask) /* ??? Does VMS care if mask contains ra? The old code didn't set it, so I don't here. */ - fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA)); + fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1UL << REG_RA)); if (fmask) fprintf (file, "\t.fmask 0x%lx,0\n", fmask); if (alpha_procedure_type == PT_REGISTER) @@ -7494,23 +7554,17 @@ alpha_start_function (file, fnname, decl) { if (imask) { - fprintf (file, "\t.mask 0x%lx,", imask); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - frame_size >= (1l << 31) ? 0 : reg_offset - frame_size); - putc ('\n', file); + fprintf (file, "\t.mask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", imask, + frame_size >= (1UL << 31) ? 0 : reg_offset - frame_size); for (i = 0; i < 32; ++i) - if (imask & (1L << i)) + if (imask & (1UL << i)) reg_offset += 8; } if (fmask) - { - fprintf (file, "\t.fmask 0x%lx,", fmask); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, - frame_size >= (1l << 31) ? 0 : reg_offset - frame_size); - putc ('\n', file); - } + fprintf (file, "\t.fmask 0x%lx," HOST_WIDE_INT_PRINT_DEC "\n", fmask, + frame_size >= (1UL << 31) ? 0 : reg_offset - frame_size); } #if TARGET_ABI_OPEN_VMS @@ -7529,8 +7583,7 @@ alpha_start_function (file, fnname, decl) /* Emit the .prologue note at the scheduled end of the prologue. */ static void -alpha_output_function_end_prologue (file) - FILE *file; +alpha_output_function_end_prologue (FILE *file) { if (TARGET_ABI_UNICOSMK) ; @@ -7552,7 +7605,7 @@ alpha_output_function_end_prologue (file) #define FRP(exp) exp void -alpha_expand_epilogue () +alpha_expand_epilogue (void) { /* Registers to save. */ unsigned long imask = 0; @@ -7644,10 +7697,10 @@ alpha_expand_epilogue () FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem)); reg_offset += 8; - imask &= ~(1L << REG_RA); + imask &= ~(1UL << REG_RA); for (i = 0; i < 31; ++i) - if (imask & (1L << i)) + if (imask & (1UL << i)) { if (i == HARD_FRAME_POINTER_REGNUM && fp_is_frame_pointer) fp_offset = reg_offset; @@ -7664,7 +7717,7 @@ alpha_expand_epilogue () reg_offset += 8; for (i = 0; i < 31; ++i) - if (fmask & (1L << i)) + if (fmask & (1UL << i)) { mem = gen_rtx_MEM (DFmode, plus_constant(sa_reg, reg_offset)); set_mem_alias_set (mem, alpha_sr_alias_set); @@ -7679,7 +7732,7 @@ alpha_expand_epilogue () reg_offset = -56; for (i = 9; i < 15; i++) - if (imask & (1L << i)) + if (imask & (1UL << i)) { mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx, reg_offset)); @@ -7689,7 +7742,7 @@ alpha_expand_epilogue () } for (i = 2; i < 10; i++) - if (fmask & (1L << i)) + if (fmask & (1UL << i)) { mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx, reg_offset)); @@ -7810,46 +7863,10 @@ alpha_expand_epilogue () } } -#if TARGET_ABI_OPEN_VMS -#include <splay-tree.h> - -/* Structure to collect function names for final output - in link section. */ - -enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN}; -enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR}; - -struct alpha_funcs -{ - int num; - splay_tree links; -}; - -struct alpha_links -{ - int num; - rtx linkage; - enum links_kind lkind; - enum reloc_kind rkind; -}; - -static splay_tree alpha_funcs_tree; -static splay_tree alpha_links_tree; - -static int mark_alpha_links_node PARAMS ((splay_tree_node, void *)); -static void mark_alpha_links PARAMS ((void *)); -static int alpha_write_one_linkage PARAMS ((splay_tree_node, void *)); - -static int alpha_funcs_num; -#endif - /* Output the rest of the textual info surrounding the epilogue. */ void -alpha_end_function (file, fnname, decl) - FILE *file; - const char *fnname; - tree decl; +alpha_end_function (FILE *file, const char *fnname, tree decl ATTRIBUTE_UNUSED) { /* End the function. */ if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive) @@ -7864,17 +7881,6 @@ alpha_end_function (file, fnname, decl) alpha_write_linkage (file, fnname, decl); #endif - /* Show that we know this function if it is called again. - - Do this only for functions whose symbols bind locally. - - Don't do this for functions not defined in the .text section, as - otherwise it's not unlikely that the destination is out of range - for a direct branch. */ - - if ((*targetm.binds_local_p) (decl) && decl_in_text_section (decl)) - SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1; - /* Output jump tables and the static subroutine information block. */ if (TARGET_ABI_UNICOSMK) { @@ -7894,23 +7900,20 @@ alpha_end_function (file, fnname, decl) Not sure why this idea hasn't been explored before... */ static void -alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, vcall_offset, function) - FILE *file; - tree thunk_fndecl ATTRIBUTE_UNUSED; - HOST_WIDE_INT delta; - HOST_WIDE_INT vcall_offset; - tree function; +alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, + tree function) { HOST_WIDE_INT hi, lo; rtx this, insn, funexp; /* We always require a valid GP. */ emit_insn (gen_prologue_ldgp ()); - emit_note (NULL, NOTE_INSN_PROLOGUE_END); + emit_note (NOTE_INSN_PROLOGUE_END); /* Find the "this" pointer. If the function returns a structure, the structure return pointer is in $16. */ - if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)))) + if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) this = gen_rtx_REG (Pmode, 17); else this = gen_rtx_REG (Pmode, 16); @@ -7980,6 +7983,7 @@ alpha_output_mi_thunk_osf (file, thunk_fndecl, delta, vcall_offset, function) instruction scheduling worth while. Note that use_thunk calls assemble_start_function and assemble_end_function. */ insn = get_insns (); + insn_locators_initialize (); shorten_branches (insn); final_start_function (insn, file, 1); final (insn, file, 1, 0); @@ -8016,9 +8020,7 @@ long alpha_auto_offset; /* Emit a new filename to a stream. */ void -alpha_output_filename (stream, name) - FILE *stream; - const char *name; +alpha_output_filename (FILE *stream, const char *name) { static int first_time = TRUE; char ltext_label_name[100]; @@ -8059,13 +8061,11 @@ alpha_output_filename (stream, name) fprintf (stream, "\n"); } } - + /* Emit a linenumber to a stream. */ void -alpha_output_lineno (stream, line) - FILE *stream; - int line; +alpha_output_lineno (FILE *stream, int line) { if (write_symbols == DBX_DEBUG) { @@ -8089,18 +8089,12 @@ struct shadow_summary } used, defd; }; -static void summarize_insn PARAMS ((rtx, struct shadow_summary *, int)); -static void alpha_handle_trap_shadows PARAMS ((rtx)); - /* Summary the effects of expression X on the machine. Update SUM, a pointer to the summary structure. SET is nonzero if the insn is setting the object, otherwise zero. */ static void -summarize_insn (x, sum, set) - rtx x; - struct shadow_summary *sum; - int set; +summarize_insn (rtx x, struct shadow_summary *sum, int set) { const char *format_ptr; int i, j; @@ -8254,8 +8248,7 @@ summarize_insn (x, sum, set) (d) The trap shadow may not include any branch instructions. */ static void -alpha_handle_trap_shadows (insns) - rtx insns; +alpha_handle_trap_shadows (void) { struct shadow_summary shadow; int trap_pending, exception_nesting; @@ -8268,7 +8261,7 @@ alpha_handle_trap_shadows (insns) shadow.used.mem = 0; shadow.defd = shadow.used; - for (i = insns; i ; i = NEXT_INSN (i)) + for (i = get_insns (); i ; i = NEXT_INSN (i)) { if (GET_CODE (i) == NOTE) { @@ -8388,7 +8381,7 @@ alpha_handle_trap_shadows (insns) } /* Alpha can only issue instruction groups simultaneously if they are - suitibly aligned. This is very processor-specific. */ + suitably aligned. This is very processor-specific. */ enum alphaev4_pipe { EV4_STOP = 0, @@ -8408,19 +8401,8 @@ enum alphaev5_pipe { EV5_FM = 64 }; -static enum alphaev4_pipe alphaev4_insn_pipe PARAMS ((rtx)); -static enum alphaev5_pipe alphaev5_insn_pipe PARAMS ((rtx)); -static rtx alphaev4_next_group PARAMS ((rtx, int *, int *)); -static rtx alphaev5_next_group PARAMS ((rtx, int *, int *)); -static rtx alphaev4_next_nop PARAMS ((int *)); -static rtx alphaev5_next_nop PARAMS ((int *)); - -static void alpha_align_insns - PARAMS ((rtx, unsigned int, rtx (*)(rtx, int *, int *), rtx (*)(int *))); - static enum alphaev4_pipe -alphaev4_insn_pipe (insn) - rtx insn; +alphaev4_insn_pipe (rtx insn) { if (recog_memoized (insn) < 0) return EV4_STOP; @@ -8462,8 +8444,7 @@ alphaev4_insn_pipe (insn) } static enum alphaev5_pipe -alphaev5_insn_pipe (insn) - rtx insn; +alphaev5_insn_pipe (rtx insn) { if (recog_memoized (insn) < 0) return EV5_STOP; @@ -8518,9 +8499,7 @@ alphaev5_insn_pipe (insn) LEN is, of course, the length of the group in bytes. */ static rtx -alphaev4_next_group (insn, pin_use, plen) - rtx insn; - int *pin_use, *plen; +alphaev4_next_group (rtx insn, int *pin_use, int *plen) { int len, in_use; @@ -8618,9 +8597,7 @@ alphaev4_next_group (insn, pin_use, plen) LEN is, of course, the length of the group in bytes. */ static rtx -alphaev5_next_group (insn, pin_use, plen) - rtx insn; - int *pin_use, *plen; +alphaev5_next_group (rtx insn, int *pin_use, int *plen) { int len, in_use; @@ -8745,8 +8722,7 @@ alphaev5_next_group (insn, pin_use, plen) } static rtx -alphaev4_next_nop (pin_use) - int *pin_use; +alphaev4_next_nop (int *pin_use) { int in_use = *pin_use; rtx nop; @@ -8774,8 +8750,7 @@ alphaev4_next_nop (pin_use) } static rtx -alphaev5_next_nop (pin_use) - int *pin_use; +alphaev5_next_nop (int *pin_use) { int in_use = *pin_use; rtx nop; @@ -8805,11 +8780,9 @@ alphaev5_next_nop (pin_use) /* The instruction group alignment main loop. */ static void -alpha_align_insns (insns, max_align, next_group, next_nop) - rtx insns; - unsigned int max_align; - rtx (*next_group) PARAMS ((rtx, int *, int *)); - rtx (*next_nop) PARAMS ((int *)); +alpha_align_insns (unsigned int max_align, + rtx (*next_group) (rtx, int *, int *), + rtx (*next_nop) (int *)) { /* ALIGN is the known alignment for the insn group. */ unsigned int align; @@ -8819,7 +8792,7 @@ alpha_align_insns (insns, max_align, next_group, next_nop) rtx i, next; /* Let shorten branches care for assigning alignments to code labels. */ - shorten_branches (insns); + shorten_branches (get_insns ()); if (align_functions < 4) align = 4; @@ -8829,7 +8802,7 @@ alpha_align_insns (insns, max_align, next_group, next_nop) align = max_align; ofs = prev_in_use = 0; - i = insns; + i = get_insns (); if (GET_CODE (i) == NOTE) i = next_nonnote_insn (i); @@ -8900,7 +8873,7 @@ alpha_align_insns (insns, max_align, next_group, next_nop) int nop_count = (align - ofs) / 4; rtx where; - /* Insert nops before labels, branches, and calls to truely merge + /* Insert nops before labels, branches, and calls to truly merge the execution of the nops with the previous instruction group. */ where = prev_nonnote_insn (i); if (where) @@ -8931,12 +8904,11 @@ alpha_align_insns (insns, max_align, next_group, next_nop) /* Machine dependent reorg pass. */ -void -alpha_reorg (insns) - rtx insns; +static void +alpha_reorg (void) { if (alpha_tp != ALPHA_TP_PROG || flag_exceptions) - alpha_handle_trap_shadows (insns); + alpha_handle_trap_shadows (); /* Due to the number of extra trapb insns, don't bother fixing up alignment when trap precision is instruction. Moreover, we can @@ -8946,25 +8918,60 @@ alpha_reorg (insns) && flag_schedule_insns_after_reload) { if (alpha_cpu == PROCESSOR_EV4) - alpha_align_insns (insns, 8, alphaev4_next_group, alphaev4_next_nop); + alpha_align_insns (8, alphaev4_next_group, alphaev4_next_nop); else if (alpha_cpu == PROCESSOR_EV5) - alpha_align_insns (insns, 16, alphaev5_next_group, alphaev5_next_nop); + alpha_align_insns (16, alphaev5_next_group, alphaev5_next_nop); } } +#if !TARGET_ABI_UNICOSMK + +#ifdef HAVE_STAMP_H +#include <stamp.h> +#endif + +static void +alpha_file_start (void) +{ +#ifdef OBJECT_FORMAT_ELF + /* If emitting dwarf2 debug information, we cannot generate a .file + directive to start the file, as it will conflict with dwarf2out + file numbers. So it's only useful when emitting mdebug output. */ + targetm.file_start_file_directive = (write_symbols == DBX_DEBUG); +#endif + + default_file_start (); +#ifdef MS_STAMP + fprintf (asm_out_file, "\t.verstamp %d %d\n", MS_STAMP, LS_STAMP); +#endif + + fputs ("\t.set noreorder\n", asm_out_file); + fputs ("\t.set volatile\n", asm_out_file); + if (!TARGET_ABI_OPEN_VMS) + fputs ("\t.set noat\n", asm_out_file); + if (TARGET_EXPLICIT_RELOCS) + fputs ("\t.set nomacro\n", asm_out_file); + if (TARGET_SUPPORT_ARCH | TARGET_BWX | TARGET_MAX | TARGET_FIX | TARGET_CIX) + fprintf (asm_out_file, + "\t.arch %s\n", + TARGET_CPU_EV6 ? "ev6" + : (TARGET_CPU_EV5 + ? (TARGET_MAX ? "pca56" : TARGET_BWX ? "ev56" : "ev5") + : "ev4")); +} +#endif + #ifdef OBJECT_FORMAT_ELF /* Switch to the section to which we should output X. The only thing special we do here is to honor small data. */ static void -alpha_elf_select_rtx_section (mode, x, align) - enum machine_mode mode; - rtx x; - unsigned HOST_WIDE_INT align; +alpha_elf_select_rtx_section (enum machine_mode mode, rtx x, + unsigned HOST_WIDE_INT align) { if (TARGET_SMALL_DATA && GET_MODE_SIZE (mode) <= g_switch_value) - /* ??? Consider using mergable sdata sections. */ + /* ??? Consider using mergeable sdata sections. */ sdata_section (); else default_elf_select_rtx_section (mode, x, align); @@ -8972,13 +8979,40 @@ alpha_elf_select_rtx_section (mode, x, align) #endif /* OBJECT_FORMAT_ELF */ +/* Structure to collect function names for final output in link section. */ +/* Note that items marked with GTY can't be ifdef'ed out. */ + +enum links_kind {KIND_UNUSED, KIND_LOCAL, KIND_EXTERN}; +enum reloc_kind {KIND_LINKAGE, KIND_CODEADDR}; + +struct alpha_links GTY(()) +{ + int num; + rtx linkage; + enum links_kind lkind; + enum reloc_kind rkind; +}; + +struct alpha_funcs GTY(()) +{ + int num; + splay_tree GTY ((param1_is (char *), param2_is (struct alpha_links *))) + links; +}; + +static GTY ((param1_is (char *), param2_is (struct alpha_links *))) + splay_tree alpha_links_tree; +static GTY ((param1_is (tree), param2_is (struct alpha_funcs *))) + splay_tree alpha_funcs_tree; + +static GTY(()) int alpha_funcs_num; + #if TARGET_ABI_OPEN_VMS /* Return the VMS argument type corresponding to MODE. */ enum avms_arg_type -alpha_arg_type (mode) - enum machine_mode mode; +alpha_arg_type (enum machine_mode mode) { switch (mode) { @@ -8995,8 +9029,7 @@ alpha_arg_type (mode) register value. */ rtx -alpha_arg_info_reg_val (cum) - CUMULATIVE_ARGS cum; +alpha_arg_info_reg_val (CUMULATIVE_ARGS cum) { unsigned HOST_WIDE_INT regval = cum.num_args; int i; @@ -9007,26 +9040,6 @@ alpha_arg_info_reg_val (cum) return GEN_INT (regval); } -/* Protect alpha_links from garbage collection. */ - -static int -mark_alpha_links_node (node, data) - splay_tree_node node; - void *data ATTRIBUTE_UNUSED; -{ - struct alpha_links *links = (struct alpha_links *) node->value; - ggc_mark_rtx (links->linkage); - return 0; -} - -static void -mark_alpha_links (ptr) - void *ptr; -{ - splay_tree tree = *(splay_tree *) ptr; - splay_tree_foreach (tree, mark_alpha_links_node, NULL); -} - /* Make (or fake) .linkage entry for function call. IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. @@ -9034,25 +9047,23 @@ mark_alpha_links (ptr) Return an SYMBOL_REF rtx for the linkage. */ rtx -alpha_need_linkage (name, is_local) - const char *name; - int is_local; +alpha_need_linkage (const char *name, int is_local) { splay_tree_node node; struct alpha_links *al; - struct alpha_funcs *cfaf; if (name[0] == '*') name++; if (is_local) { - alpha_funcs_tree = splay_tree_new - ((splay_tree_compare_fn) splay_tree_compare_pointers, - (splay_tree_delete_key_fn) free, - (splay_tree_delete_key_fn) free); + struct alpha_funcs *cfaf; + + if (!alpha_funcs_tree) + alpha_funcs_tree = splay_tree_new_ggc ((splay_tree_compare_fn) + splay_tree_compare_pointers); - cfaf = (struct alpha_funcs *) xmalloc (sizeof (struct alpha_funcs)); + cfaf = (struct alpha_funcs *) ggc_alloc (sizeof (struct alpha_funcs)); cfaf->links = 0; cfaf->num = ++alpha_funcs_num; @@ -9060,7 +9071,6 @@ alpha_need_linkage (name, is_local) splay_tree_insert (alpha_funcs_tree, (splay_tree_key) current_function_decl, (splay_tree_value) cfaf); - } if (alpha_links_tree) @@ -9087,17 +9097,10 @@ alpha_need_linkage (name, is_local) } } else - { - alpha_links_tree = splay_tree_new - ((splay_tree_compare_fn) strcmp, - (splay_tree_delete_key_fn) free, - (splay_tree_delete_key_fn) free); + alpha_links_tree = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp); - ggc_add_root (&alpha_links_tree, 1, 1, mark_alpha_links); - } - - al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); - name = xstrdup (name); + al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links)); + name = ggc_strdup (name); /* Assume external if no definition. */ al->lkind = (is_local ? KIND_UNUSED : KIND_EXTERN); @@ -9123,11 +9126,7 @@ alpha_need_linkage (name, is_local) } rtx -alpha_use_linkage (linkage, cfundecl, lflag, rflag) - rtx linkage; - tree cfundecl; - int lflag; - int rflag; +alpha_use_linkage (rtx linkage, tree cfundecl, int lflag, int rflag) { splay_tree_node cfunnode; struct alpha_funcs *cfaf; @@ -9151,13 +9150,7 @@ alpha_use_linkage (linkage, cfundecl, lflag, rflag) al = (struct alpha_links *) lnode->value; } else - { - cfaf->links = splay_tree_new - ((splay_tree_compare_fn) strcmp, - (splay_tree_delete_key_fn) free, - (splay_tree_delete_key_fn) free); - ggc_add_root (&cfaf->links, 1, 1, mark_alpha_links); - } + cfaf->links = splay_tree_new_ggc ((splay_tree_compare_fn) strcmp); if (!al) { @@ -9173,7 +9166,7 @@ alpha_use_linkage (linkage, cfundecl, lflag, rflag) name_len = strlen (name); - al = (struct alpha_links *) xmalloc (sizeof (struct alpha_links)); + al = (struct alpha_links *) ggc_alloc (sizeof (struct alpha_links)); al->num = cfaf->num; node = splay_tree_lookup (alpha_links_tree, (splay_tree_key) name); @@ -9207,9 +9200,7 @@ alpha_use_linkage (linkage, cfundecl, lflag, rflag) } static int -alpha_write_one_linkage (node, data) - splay_tree_node node; - void *data; +alpha_write_one_linkage (splay_tree_node node, void *data) { const char *const name = (const char *) node->key; struct alpha_links *link = (struct alpha_links *) node->value; @@ -9248,10 +9239,7 @@ alpha_write_one_linkage (node, data) } static void -alpha_write_linkage (stream, funname, fundecl) - FILE *stream; - const char *funname; - tree fundecl; +alpha_write_linkage (FILE *stream, const char *funname, tree fundecl) { splay_tree_node node; struct alpha_funcs *func; @@ -9286,10 +9274,7 @@ alpha_write_linkage (stream, funname, fundecl) #define SECTION_VMS_INITIALIZE (SECTION_VMS_GLOBAL << 1) static unsigned int -vms_section_type_flags (decl, name, reloc) - tree decl; - const char *name; - int reloc; +vms_section_type_flags (tree decl, const char *name, int reloc) { unsigned int flags = default_section_type_flags (decl, name, reloc); @@ -9311,9 +9296,7 @@ vms_section_type_flags (decl, name, reloc) the section; 0 if the default should be used. */ static void -vms_asm_named_section (name, flags) - const char *name; - unsigned int flags; +vms_asm_named_section (const char *name, unsigned int flags) { fputc ('\n', asm_out_file); fprintf (asm_out_file, ".section\t%s", name); @@ -9339,9 +9322,7 @@ vms_asm_named_section (name, flags) used by a normal pointer. */ static void -vms_asm_out_constructor (symbol, priority) - rtx symbol; - int priority ATTRIBUTE_UNUSED; +vms_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED) { ctors_section (); assemble_align (BITS_PER_WORD); @@ -9349,9 +9330,7 @@ vms_asm_out_constructor (symbol, priority) } static void -vms_asm_out_destructor (symbol, priority) - rtx symbol; - int priority ATTRIBUTE_UNUSED; +vms_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED) { dtors_section (); assemble_align (BITS_PER_WORD); @@ -9360,19 +9339,17 @@ vms_asm_out_destructor (symbol, priority) #else rtx -alpha_need_linkage (name, is_local) - const char *name ATTRIBUTE_UNUSED; - int is_local ATTRIBUTE_UNUSED; +alpha_need_linkage (const char *name ATTRIBUTE_UNUSED, + int is_local ATTRIBUTE_UNUSED) { return NULL_RTX; } rtx -alpha_use_linkage (linkage, cfundecl, lflag, rflag) - rtx linkage ATTRIBUTE_UNUSED; - tree cfundecl ATTRIBUTE_UNUSED; - int lflag ATTRIBUTE_UNUSED; - int rflag ATTRIBUTE_UNUSED; +alpha_use_linkage (rtx linkage ATTRIBUTE_UNUSED, + tree cfundecl ATTRIBUTE_UNUSED, + int lflag ATTRIBUTE_UNUSED, + int rflag ATTRIBUTE_UNUSED) { return NULL_RTX; } @@ -9381,21 +9358,11 @@ alpha_use_linkage (linkage, cfundecl, lflag, rflag) #if TARGET_ABI_UNICOSMK -static void unicosmk_output_module_name PARAMS ((FILE *)); -static void unicosmk_output_default_externs PARAMS ((FILE *)); -static void unicosmk_output_dex PARAMS ((FILE *)); -static void unicosmk_output_externs PARAMS ((FILE *)); -static void unicosmk_output_addr_vec PARAMS ((FILE *, rtx)); -static const char *unicosmk_ssib_name PARAMS ((void)); -static int unicosmk_special_name PARAMS ((const char *)); - /* Define the offset between two registers, one to be eliminated, and the other its replacement, at the start of a routine. */ int -unicosmk_initial_elimination_offset (from, to) - int from; - int to; +unicosmk_initial_elimination_offset (int from, int to) { int fixed_size; @@ -9423,112 +9390,27 @@ unicosmk_initial_elimination_offset (from, to) or '$'. */ static void -unicosmk_output_module_name (file) - FILE *file; +unicosmk_output_module_name (FILE *file) { - const char *name; - - /* Strip directories. */ - - name = strrchr (main_input_filename, '/'); - if (name) - ++name; - else - name = main_input_filename; - + const char *name = lbasename (main_input_filename); + unsigned len = strlen (name); + char *clean_name = alloca (len + 2); + char *ptr = clean_name; + /* CAM only accepts module names that start with a letter or '$'. We prefix the module name with a '$' if necessary. */ if (!ISALPHA (*name)) - putc ('$', file); - output_clean_symbol_name (file, name); -} - -/* Output text that to appear at the beginning of an assembler file. */ - -void -unicosmk_asm_file_start (file) - FILE *file; -{ - int i; - - fputs ("\t.ident\t", file); - unicosmk_output_module_name (file); - fputs ("\n\n", file); - - /* The Unicos/Mk assembler uses different register names. Instead of trying - to support them, we simply use micro definitions. */ - - /* CAM has different register names: rN for the integer register N and fN - for the floating-point register N. Instead of trying to use these in - alpha.md, we define the symbols $N and $fN to refer to the appropriate - register. */ - - for (i = 0; i < 32; ++i) - fprintf (file, "$%d <- r%d\n", i, i); - - for (i = 0; i < 32; ++i) - fprintf (file, "$f%d <- f%d\n", i, i); - - putc ('\n', file); - - /* The .align directive fill unused space with zeroes which does not work - in code sections. We define the macro 'gcc@code@align' which uses nops - instead. Note that it assumes that code sections always have the - biggest possible alignment since . refers to the current offset from - the beginning of the section. */ - - fputs ("\t.macro gcc@code@align n\n", file); - fputs ("gcc@n@bytes = 1 << n\n", file); - fputs ("gcc@here = . % gcc@n@bytes\n", file); - fputs ("\t.if ne, gcc@here, 0\n", file); - fputs ("\t.repeat (gcc@n@bytes - gcc@here) / 4\n", file); - fputs ("\tbis r31,r31,r31\n", file); - fputs ("\t.endr\n", file); - fputs ("\t.endif\n", file); - fputs ("\t.endm gcc@code@align\n\n", file); - - /* Output extern declarations which should always be visible. */ - unicosmk_output_default_externs (file); - - /* Open a dummy section. We always need to be inside a section for the - section-switching code to work correctly. - ??? This should be a module id or something like that. I still have to - figure out what the rules for those are. */ - fputs ("\n\t.psect\t$SG00000,data\n", file); -} - -/* Output text to appear at the end of an assembler file. This includes all - pending extern declarations and DEX expressions. */ - -void -unicosmk_asm_file_end (file) - FILE *file; -{ - fputs ("\t.endp\n\n", file); - - /* Output all pending externs. */ - - unicosmk_output_externs (file); - - /* Output dex definitions used for functions whose names conflict with - register names. */ - - unicosmk_output_dex (file); - - fputs ("\t.end\t", file); - unicosmk_output_module_name (file); - putc ('\n', file); + *ptr++ = '$'; + memcpy (ptr, name, len + 1); + clean_symbol_name (clean_name); + fputs (clean_name, file); } /* Output the definition of a common variable. */ void -unicosmk_output_common (file, name, size, align) - FILE *file; - const char *name; - int size; - int align; +unicosmk_output_common (FILE *file, const char *name, int size, int align) { tree name_tree; printf ("T3E__: common %s\n", name); @@ -9549,10 +9431,8 @@ unicosmk_output_common (file, name, size, align) static int current_section_align; static unsigned int -unicosmk_section_type_flags (decl, name, reloc) - tree decl; - const char *name; - int reloc ATTRIBUTE_UNUSED; +unicosmk_section_type_flags (tree decl, const char *name, + int reloc ATTRIBUTE_UNUSED) { unsigned int flags = default_section_type_flags (decl, name, reloc); @@ -9581,9 +9461,7 @@ unicosmk_section_type_flags (decl, name, reloc) declaration. */ static void -unicosmk_unique_section (decl, reloc) - tree decl; - int reloc ATTRIBUTE_UNUSED; +unicosmk_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED) { const char *name; int len; @@ -9592,7 +9470,7 @@ unicosmk_unique_section (decl, reloc) abort (); name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - name = alpha_strip_name_encoding (name); + name = default_strip_name_encoding (name); len = strlen (name); if (TREE_CODE (decl) == FUNCTION_DECL) @@ -9624,9 +9502,7 @@ unicosmk_unique_section (decl, reloc) the section; 0 if the default should be used. */ static void -unicosmk_asm_named_section (name, flags) - const char *name; - unsigned int flags; +unicosmk_asm_named_section (const char *name, unsigned int flags) { const char *kind; @@ -9654,9 +9530,7 @@ unicosmk_asm_named_section (name, flags) } static void -unicosmk_insert_attributes (decl, attr_ptr) - tree decl; - tree *attr_ptr ATTRIBUTE_UNUSED; +unicosmk_insert_attributes (tree decl, tree *attr_ptr ATTRIBUTE_UNUSED) { if (DECL_P (decl) && (TREE_PUBLIC (decl) || TREE_CODE (decl) == FUNCTION_DECL)) @@ -9667,9 +9541,7 @@ unicosmk_insert_attributes (decl, attr_ptr) in code sections because .align fill unused space with zeroes. */ void -unicosmk_output_align (file, align) - FILE *file; - int align; +unicosmk_output_align (FILE *file, int align) { if (inside_function) fprintf (file, "\tgcc@code@align\t%d\n", align); @@ -9682,9 +9554,7 @@ unicosmk_output_align (file, align) does not allow data definitions in code sections. */ void -unicosmk_defer_case_vector (lab, vec) - rtx lab; - rtx vec; +unicosmk_defer_case_vector (rtx lab, rtx vec) { struct machine_function *machine = cfun->machine; @@ -9696,16 +9566,14 @@ unicosmk_defer_case_vector (lab, vec) /* Output a case vector. */ static void -unicosmk_output_addr_vec (file, vec) - FILE *file; - rtx vec; +unicosmk_output_addr_vec (FILE *file, rtx vec) { rtx lab = XEXP (vec, 0); rtx body = XEXP (vec, 1); int vlen = XVECLEN (body, 0); int idx; - ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (lab)); + (*targetm.asm_out.internal_label) (file, "L", CODE_LABEL_NUMBER (lab)); for (idx = 0; idx < vlen; idx++) { @@ -9717,8 +9585,7 @@ unicosmk_output_addr_vec (file, vec) /* Output current function's deferred case vectors. */ static void -unicosmk_output_deferred_case_vectors (file) - FILE *file; +unicosmk_output_deferred_case_vectors (FILE *file) { struct machine_function *machine = cfun->machine; rtx t; @@ -9731,13 +9598,48 @@ unicosmk_output_deferred_case_vectors (file) unicosmk_output_addr_vec (file, XEXP (t, 0)); } +/* Generate the name of the SSIB section for the current function. */ + +#define SSIB_PREFIX "__SSIB_" +#define SSIB_PREFIX_LEN 7 + +static const char * +unicosmk_ssib_name (void) +{ + /* This is ok since CAM won't be able to deal with names longer than that + anyway. */ + + static char name[256]; + + rtx x; + const char *fnname; + int len; + + x = DECL_RTL (cfun->decl); + if (GET_CODE (x) != MEM) + abort (); + x = XEXP (x, 0); + if (GET_CODE (x) != SYMBOL_REF) + abort (); + fnname = XSTR (x, 0); + + len = strlen (fnname); + if (len + SSIB_PREFIX_LEN > 255) + len = 255 - SSIB_PREFIX_LEN; + + strcpy (name, SSIB_PREFIX); + strncpy (name + SSIB_PREFIX_LEN, fnname, len); + name[len + SSIB_PREFIX_LEN] = 0; + + return name; +} + /* Set up the dynamic subprogram information block (DSIB) and update the frame pointer register ($15) for subroutines which have a frame. If the subroutine doesn't have a frame, simply increment $15. */ static void -unicosmk_gen_dsib (imaskP) - unsigned long * imaskP; +unicosmk_gen_dsib (unsigned long *imaskP) { if (alpha_procedure_type == PT_STACK) { @@ -9755,14 +9657,14 @@ unicosmk_gen_dsib (imaskP) mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 56)); set_mem_alias_set (mem, alpha_sr_alias_set); FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA))); - (*imaskP) &= ~(1L << REG_RA); + (*imaskP) &= ~(1UL << REG_RA); /* Save the old frame pointer. */ mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 48)); set_mem_alias_set (mem, alpha_sr_alias_set); FRP (emit_move_insn (mem, hard_frame_pointer_rtx)); - (*imaskP) &= ~(1L << HARD_FRAME_POINTER_REGNUM); + (*imaskP) &= ~(1UL << HARD_FRAME_POINTER_REGNUM); emit_insn (gen_blockage ()); @@ -9800,49 +9702,11 @@ unicosmk_gen_dsib (imaskP) } } -#define SSIB_PREFIX "__SSIB_" -#define SSIB_PREFIX_LEN 7 - -/* Generate the name of the SSIB section for the current function. */ - -static const char * -unicosmk_ssib_name () -{ - /* This is ok since CAM won't be able to deal with names longer than that - anyway. */ - - static char name[256]; - - rtx x; - const char *fnname; - int len; - - x = DECL_RTL (cfun->decl); - if (GET_CODE (x) != MEM) - abort (); - x = XEXP (x, 0); - if (GET_CODE (x) != SYMBOL_REF) - abort (); - fnname = alpha_strip_name_encoding (XSTR (x, 0)); - - len = strlen (fnname); - if (len + SSIB_PREFIX_LEN > 255) - len = 255 - SSIB_PREFIX_LEN; - - strcpy (name, SSIB_PREFIX); - strncpy (name + SSIB_PREFIX_LEN, fnname, len); - name[len + SSIB_PREFIX_LEN] = 0; - - return name; -} - /* Output the static subroutine information block for the current function. */ static void -unicosmk_output_ssib (file, fnname) - FILE *file; - const char *fnname; +unicosmk_output_ssib (FILE *file, const char *fnname) { int len; int i; @@ -9889,14 +9753,12 @@ unicosmk_output_ssib (file, fnname) for (x = machine->first_ciw; x; x = XEXP (x, 1)) { ciw = XEXP (x, 0); - fprintf (file, "\t.quad\t"); #if HOST_BITS_PER_WIDE_INT == 32 - fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX, + fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_DOUBLE_HEX "\n", CONST_DOUBLE_HIGH (ciw), CONST_DOUBLE_LOW (ciw)); #else - fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (ciw)); + fprintf (file, "\t.quad\t" HOST_WIDE_INT_PRINT_HEX "\n", INTVAL (ciw)); #endif - fprintf (file, "\n"); } } @@ -9906,8 +9768,7 @@ unicosmk_output_ssib (file, fnname) X is a CONST_INT or CONST_DOUBLE representing the CIW. */ rtx -unicosmk_add_call_info_word (x) - rtx x; +unicosmk_add_call_info_word (rtx x) { rtx node; struct machine_function *machine = cfun->machine; @@ -9922,13 +9783,13 @@ unicosmk_add_call_info_word (x) ++machine->ciw_count; return GEN_INT (machine->ciw_count - + strlen (current_function_name)/8 + 5); + + strlen (current_function_name ())/8 + 5); } static char unicosmk_section_buf[100]; char * -unicosmk_text_section () +unicosmk_text_section (void) { static int count = 0; sprintf (unicosmk_section_buf, "\t.endp\n\n\t.psect\tgcc@text___%d,code", @@ -9937,7 +9798,7 @@ unicosmk_text_section () } char * -unicosmk_data_section () +unicosmk_data_section (void) { static int count = 1; sprintf (unicosmk_section_buf, "\t.endp\n\n\t.psect\tgcc@data___%d,data", @@ -9953,6 +9814,7 @@ unicosmk_data_section () /* List of identifiers for which an extern declaration might have to be emitted. */ +/* FIXME: needs to use GC, so it can be saved and restored for PCH. */ struct unicosmk_extern_list { @@ -9965,8 +9827,7 @@ static struct unicosmk_extern_list *unicosmk_extern_head = 0; /* Output extern declarations which are required for every asm file. */ static void -unicosmk_output_default_externs (file) - FILE *file; +unicosmk_output_default_externs (FILE *file) { static const char *const externs[] = { "__T3E_MISMATCH" }; @@ -9984,8 +9845,7 @@ unicosmk_output_default_externs (file) referenced but not defined. */ static void -unicosmk_output_externs (file) - FILE *file; +unicosmk_output_externs (FILE *file) { struct unicosmk_extern_list *p; const char *real_name; @@ -9998,7 +9858,7 @@ unicosmk_output_externs (file) /* We have to strip the encoding and possibly remove user_label_prefix from the identifier in order to handle -fleading-underscore and explicit asm names correctly (cf. gcc.dg/asm-names-1.c). */ - real_name = alpha_strip_name_encoding (p->name); + real_name = default_strip_name_encoding (p->name); if (len && p->name[0] == '*' && !memcmp (real_name, user_label_prefix, len)) real_name += len; @@ -10017,8 +9877,7 @@ unicosmk_output_externs (file) /* Record an extern. */ void -unicosmk_add_extern (name) - const char *name; +unicosmk_add_extern (const char *name) { struct unicosmk_extern_list *p; @@ -10035,6 +9894,7 @@ unicosmk_add_extern (name) /* Structure to collect identifiers which have been replaced by DEX expressions. */ +/* FIXME: needs to use GC, so it can be saved and restored for PCH. */ struct unicosmk_dex { struct unicosmk_dex *next; @@ -10053,8 +9913,7 @@ static int unicosmk_dex_count = 0; /* Check if NAME must be replaced by a DEX expression. */ static int -unicosmk_special_name (name) - const char *name; +unicosmk_special_name (const char *name) { if (name[0] == '*') ++name; @@ -10083,8 +9942,7 @@ unicosmk_special_name (name) otherwise. */ static int -unicosmk_need_dex (x) - rtx x; +unicosmk_need_dex (rtx x) { struct unicosmk_dex *dex; const char *name; @@ -10117,8 +9975,7 @@ unicosmk_need_dex (x) /* Output the DEX definitions for this file. */ static void -unicosmk_output_dex (file) - FILE *file; +unicosmk_output_dex (FILE *file) { struct unicosmk_dex *dex; int i; @@ -10140,39 +9997,264 @@ unicosmk_output_dex (file) fprintf (file, "\t.dexend\n"); } +/* Output text that to appear at the beginning of an assembler file. */ + +static void +unicosmk_file_start (void) +{ + int i; + + fputs ("\t.ident\t", asm_out_file); + unicosmk_output_module_name (asm_out_file); + fputs ("\n\n", asm_out_file); + + /* The Unicos/Mk assembler uses different register names. Instead of trying + to support them, we simply use micro definitions. */ + + /* CAM has different register names: rN for the integer register N and fN + for the floating-point register N. Instead of trying to use these in + alpha.md, we define the symbols $N and $fN to refer to the appropriate + register. */ + + for (i = 0; i < 32; ++i) + fprintf (asm_out_file, "$%d <- r%d\n", i, i); + + for (i = 0; i < 32; ++i) + fprintf (asm_out_file, "$f%d <- f%d\n", i, i); + + putc ('\n', asm_out_file); + + /* The .align directive fill unused space with zeroes which does not work + in code sections. We define the macro 'gcc@code@align' which uses nops + instead. Note that it assumes that code sections always have the + biggest possible alignment since . refers to the current offset from + the beginning of the section. */ + + fputs ("\t.macro gcc@code@align n\n", asm_out_file); + fputs ("gcc@n@bytes = 1 << n\n", asm_out_file); + fputs ("gcc@here = . % gcc@n@bytes\n", asm_out_file); + fputs ("\t.if ne, gcc@here, 0\n", asm_out_file); + fputs ("\t.repeat (gcc@n@bytes - gcc@here) / 4\n", asm_out_file); + fputs ("\tbis r31,r31,r31\n", asm_out_file); + fputs ("\t.endr\n", asm_out_file); + fputs ("\t.endif\n", asm_out_file); + fputs ("\t.endm gcc@code@align\n\n", asm_out_file); + + /* Output extern declarations which should always be visible. */ + unicosmk_output_default_externs (asm_out_file); + + /* Open a dummy section. We always need to be inside a section for the + section-switching code to work correctly. + ??? This should be a module id or something like that. I still have to + figure out what the rules for those are. */ + fputs ("\n\t.psect\t$SG00000,data\n", asm_out_file); +} + +/* Output text to appear at the end of an assembler file. This includes all + pending extern declarations and DEX expressions. */ + +static void +unicosmk_file_end (void) +{ + fputs ("\t.endp\n\n", asm_out_file); + + /* Output all pending externs. */ + + unicosmk_output_externs (asm_out_file); + + /* Output dex definitions used for functions whose names conflict with + register names. */ + + unicosmk_output_dex (asm_out_file); + + fputs ("\t.end\t", asm_out_file); + unicosmk_output_module_name (asm_out_file); + putc ('\n', asm_out_file); +} + #else static void -unicosmk_output_deferred_case_vectors (file) - FILE *file ATTRIBUTE_UNUSED; +unicosmk_output_deferred_case_vectors (FILE *file ATTRIBUTE_UNUSED) {} static void -unicosmk_gen_dsib (imaskP) - unsigned long * imaskP ATTRIBUTE_UNUSED; +unicosmk_gen_dsib (unsigned long *imaskP ATTRIBUTE_UNUSED) {} static void -unicosmk_output_ssib (file, fnname) - FILE * file ATTRIBUTE_UNUSED; - const char * fnname ATTRIBUTE_UNUSED; +unicosmk_output_ssib (FILE * file ATTRIBUTE_UNUSED, + const char * fnname ATTRIBUTE_UNUSED) {} rtx -unicosmk_add_call_info_word (x) - rtx x ATTRIBUTE_UNUSED; +unicosmk_add_call_info_word (rtx x ATTRIBUTE_UNUSED) { return NULL_RTX; } static int -unicosmk_need_dex (x) - rtx x ATTRIBUTE_UNUSED; +unicosmk_need_dex (rtx x ATTRIBUTE_UNUSED) { return 0; } #endif /* TARGET_ABI_UNICOSMK */ +static void +alpha_init_libfuncs (void) +{ + if (TARGET_ABI_UNICOSMK) + { + /* Prevent gcc from generating calls to __divsi3. */ + set_optab_libfunc (sdiv_optab, SImode, 0); + set_optab_libfunc (udiv_optab, SImode, 0); + + /* Use the functions provided by the system library + for DImode integer division. */ + set_optab_libfunc (sdiv_optab, DImode, "$sldiv"); + set_optab_libfunc (udiv_optab, DImode, "$uldiv"); + } + else if (TARGET_ABI_OPEN_VMS) + { + /* Use the VMS runtime library functions for division and + remainder. */ + set_optab_libfunc (sdiv_optab, SImode, "OTS$DIV_I"); + set_optab_libfunc (sdiv_optab, DImode, "OTS$DIV_L"); + set_optab_libfunc (udiv_optab, SImode, "OTS$DIV_UI"); + set_optab_libfunc (udiv_optab, DImode, "OTS$DIV_UL"); + set_optab_libfunc (smod_optab, SImode, "OTS$REM_I"); + set_optab_libfunc (smod_optab, DImode, "OTS$REM_L"); + set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI"); + set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL"); + } +} + + +/* Initialize the GCC target structure. */ +#if TARGET_ABI_OPEN_VMS +# undef TARGET_ATTRIBUTE_TABLE +# define TARGET_ATTRIBUTE_TABLE vms_attribute_table +# undef TARGET_SECTION_TYPE_FLAGS +# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags +#endif + +#undef TARGET_IN_SMALL_DATA_P +#define TARGET_IN_SMALL_DATA_P alpha_in_small_data_p + +#if TARGET_ABI_UNICOSMK +# undef TARGET_INSERT_ATTRIBUTES +# define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes +# undef TARGET_SECTION_TYPE_FLAGS +# define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags +# undef TARGET_ASM_UNIQUE_SECTION +# define TARGET_ASM_UNIQUE_SECTION unicosmk_unique_section +# undef TARGET_ASM_GLOBALIZE_LABEL +# define TARGET_ASM_GLOBALIZE_LABEL hook_void_FILEptr_constcharptr +#endif + +#undef TARGET_ASM_ALIGNED_HI_OP +#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" +#undef TARGET_ASM_ALIGNED_DI_OP +#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t" + +/* Default unaligned ops are provided for ELF systems. To get unaligned + data for non-ELF systems, we have to turn off auto alignment. */ +#ifndef OBJECT_FORMAT_ELF +#undef TARGET_ASM_UNALIGNED_HI_OP +#define TARGET_ASM_UNALIGNED_HI_OP "\t.align 0\n\t.word\t" +#undef TARGET_ASM_UNALIGNED_SI_OP +#define TARGET_ASM_UNALIGNED_SI_OP "\t.align 0\n\t.long\t" +#undef TARGET_ASM_UNALIGNED_DI_OP +#define TARGET_ASM_UNALIGNED_DI_OP "\t.align 0\n\t.quad\t" +#endif + +#ifdef OBJECT_FORMAT_ELF +#undef TARGET_ASM_SELECT_RTX_SECTION +#define TARGET_ASM_SELECT_RTX_SECTION alpha_elf_select_rtx_section +#endif + +#undef TARGET_ASM_FUNCTION_END_PROLOGUE +#define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue + +#undef TARGET_INIT_LIBFUNCS +#define TARGET_INIT_LIBFUNCS alpha_init_libfuncs + +#if TARGET_ABI_UNICOSMK +#undef TARGET_ASM_FILE_START +#define TARGET_ASM_FILE_START unicosmk_file_start +#undef TARGET_ASM_FILE_END +#define TARGET_ASM_FILE_END unicosmk_file_end +#else +#undef TARGET_ASM_FILE_START +#define TARGET_ASM_FILE_START alpha_file_start +#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE +#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true +#endif + +#undef TARGET_SCHED_ADJUST_COST +#define TARGET_SCHED_ADJUST_COST alpha_adjust_cost +#undef TARGET_SCHED_ISSUE_RATE +#define TARGET_SCHED_ISSUE_RATE alpha_issue_rate +#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE +#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \ + alpha_use_dfa_pipeline_interface +#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD +#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ + alpha_multipass_dfa_lookahead + +#undef TARGET_HAVE_TLS +#define TARGET_HAVE_TLS HAVE_AS_TLS + +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS alpha_init_builtins +#undef TARGET_EXPAND_BUILTIN +#define TARGET_EXPAND_BUILTIN alpha_expand_builtin + +#undef TARGET_FUNCTION_OK_FOR_SIBCALL +#define TARGET_FUNCTION_OK_FOR_SIBCALL alpha_function_ok_for_sibcall +#undef TARGET_CANNOT_COPY_INSN_P +#define TARGET_CANNOT_COPY_INSN_P alpha_cannot_copy_insn_p + +#if TARGET_ABI_OSF +#undef TARGET_ASM_OUTPUT_MI_THUNK +#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf +#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK +#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true +#endif + +#undef TARGET_RTX_COSTS +#define TARGET_RTX_COSTS alpha_rtx_costs +#undef TARGET_ADDRESS_COST +#define TARGET_ADDRESS_COST hook_int_rtx_0 + +#undef TARGET_MACHINE_DEPENDENT_REORG +#define TARGET_MACHINE_DEPENDENT_REORG alpha_reorg + +#undef TARGET_PROMOTE_FUNCTION_ARGS +#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true +#undef TARGET_PROMOTE_FUNCTION_RETURN +#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true +#undef TARGET_PROMOTE_PROTOTYPES +#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_false +#undef TARGET_STRUCT_VALUE_RTX +#define TARGET_STRUCT_VALUE_RTX hook_rtx_tree_int_null +#undef TARGET_RETURN_IN_MEMORY +#define TARGET_RETURN_IN_MEMORY alpha_return_in_memory +#undef TARGET_SETUP_INCOMING_VARARGS +#define TARGET_SETUP_INCOMING_VARARGS alpha_setup_incoming_varargs +#undef TARGET_STRICT_ARGUMENT_NAMING +#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true +#undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED +#define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true +#undef TARGET_SPLIT_COMPLEX_ARG +#define TARGET_SPLIT_COMPLEX_ARG alpha_split_complex_arg + +#undef TARGET_BUILD_BUILTIN_VA_LIST +#define TARGET_BUILD_BUILTIN_VA_LIST alpha_build_builtin_va_list + +struct gcc_target targetm = TARGET_INITIALIZER; + + #include "gt-alpha.h" diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md index e4377a5..a190d23 100644 --- a/contrib/gcc/config/i386/i386.md +++ b/contrib/gcc/config/i386/i386.md @@ -1,24 +1,24 @@ ;; GCC machine description for IA-32 and x86-64. ;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -;; 2001, 2002, 2003 +;; 2001, 2002, 2003, 2004 ;; Free Software Foundation, Inc. ;; Mostly by William Schelter. ;; x86_64 support added by Jan Hubicka ;; -;; This file is part of GNU CC. +;; This file is part of GCC. ;; -;; GNU CC is free software; you can redistribute it and/or modify +;; GCC is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; -;; GNU CC is distributed in the hope that it will be useful, +;; GCC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to +;; along with GCC; see the file COPYING. If not, write to ;; the Free Software Foundation, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. */ ;; @@ -27,9 +27,6 @@ ;; ;; See file "rtl.def" for documentation on define_insn, match_*, et. al. ;; -;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code -;; updates for most instructions. -;; ;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register ;; constraint letters. ;; @@ -66,7 +63,6 @@ (UNSPEC_INDNTPOFF 8) ; Prologue support - (UNSPEC_STACK_PROBE 10) (UNSPEC_STACK_ALLOC 11) (UNSPEC_SET_GOT 12) (UNSPEC_SSE_PROLOGUE_SAVE 13) @@ -80,7 +76,6 @@ (UNSPEC_SCAS 20) (UNSPEC_SIN 21) (UNSPEC_COS 22) - (UNSPEC_BSF 23) (UNSPEC_FNSTSW 24) (UNSPEC_SAHF 25) (UNSPEC_FSTCW 26) @@ -117,16 +112,28 @@ (UNSPEC_MOVSLDUP 75) (UNSPEC_LDQQU 76) (UNSPEC_MOVDDUP 77) + + ; x87 Floating point + (UNSPEC_FPATAN 65) + (UNSPEC_FYL2X 66) + (UNSPEC_FSCALE 67) + (UNSPEC_FRNDINT 68) + (UNSPEC_F2XM1 69) + + ; REP instruction + (UNSPEC_REP 75) ]) (define_constants [(UNSPECV_BLOCKAGE 0) + (UNSPECV_STACK_PROBE 10) (UNSPECV_EH_RETURN 13) (UNSPECV_EMMS 31) (UNSPECV_LDMXCSR 37) (UNSPECV_STMXCSR 40) (UNSPECV_FEMMS 46) (UNSPECV_CLFLUSH 57) + (UNSPECV_ALIGN 68) (UNSPECV_MONITOR 69) (UNSPECV_MWAIT 70) ]) @@ -142,8 +149,8 @@ ;; Processor type. This attribute must exactly match the processor_type ;; enumeration in i386.h. -(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4" - (const (symbol_ref "ix86_cpu"))) +(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8" + (const (symbol_ref "ix86_tune"))) ;; A basic instruction type. Refinements due to arguments to be ;; provided in other attributes. @@ -152,17 +159,17 @@ alu,alu1,negnot,imov,imovx,lea, incdec,ishift,ishift1,rotate,rotate1,imul,idiv, icmp,test,ibr,setcc,icmov, - push,pop,call,callv, + push,pop,call,callv,leave, str,cld, fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp, sselog,sseiadd,sseishft,sseimul, - sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,ssediv, + sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv, mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft" (const_string "other")) ;; Main data type used by the insn (define_attr "mode" - "unknown,none,QI,HI,SI,DI,unknownfp,SF,DF,XF,TI,V4SF,V2DF,V2SF" + "unknown,none,QI,HI,SI,DI,SF,DF,XF,TI,V4SF,V2DF,V2SF" (const_string "unknown")) ;; The CPU unit operations uses. @@ -170,7 +177,7 @@ (cond [(eq_attr "type" "fmov,fop,fsgn,fmul,fdiv,fpspc,fcmov,fcmp,fxch,fistp") (const_string "i387") (eq_attr "type" "sselog,sseiadd,sseishft,sseimul, - sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,ssediv") + sse,ssemov,sseadd,ssemul,ssecmp,ssecomi,ssecvt,sseicvt,ssediv") (const_string "sse") (eq_attr "type" "mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft") (const_string "mmx") @@ -180,7 +187,7 @@ ;; The (bounding maximum) length of an instruction immediate. (define_attr "length_immediate" "" - (cond [(eq_attr "type" "incdec,setcc,icmov,str,cld,lea,other,multi,idiv") + (cond [(eq_attr "type" "incdec,setcc,icmov,str,cld,lea,other,multi,idiv,leave") (const_int 0) (eq_attr "unit" "i387,sse,mmx") (const_int 0) @@ -234,17 +241,29 @@ ;; Set when 0f opcode prefix is used. (define_attr "prefix_0f" "" (if_then_else - (eq_attr "type" - "imovx,setcc,icmov, - sselog,sseiadd,sseishft,sseimul, - sse,ssemov,sseadd,ssemul,ssecmp,ssecvt,ssediv, - mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft") + (ior (eq_attr "type" "imovx,setcc,icmov") + (eq_attr "unit" "sse,mmx")) (const_int 1) (const_int 0))) +;; Set when 0f opcode prefix is used. +(define_attr "prefix_rex" "" + (cond [(and (eq_attr "mode" "DI") + (eq_attr "type" "!push,pop,call,callv,leave,ibr")) + (const_int 1) + (and (eq_attr "mode" "QI") + (ne (symbol_ref "x86_extended_QIreg_mentioned_p (insn)") + (const_int 0))) + (const_int 1) + (ne (symbol_ref "x86_extended_reg_mentioned_p (insn)") + (const_int 0)) + (const_int 1) + ] + (const_int 0))) + ;; Set when modrm byte is used. (define_attr "modrm" "" - (cond [(eq_attr "type" "str,cld") + (cond [(eq_attr "type" "str,cld,leave") (const_int 0) (eq_attr "unit" "i387") (const_int 0) @@ -285,7 +304,8 @@ (attr "length_address")))] (plus (plus (attr "modrm") (plus (attr "prefix_0f") - (const_int 1))) + (plus (attr "prefix_rex") + (const_int 1)))) (plus (attr "prefix_rep") (plus (attr "prefix_data16") (plus (attr "length_immediate") @@ -300,17 +320,21 @@ (const_string "unknown") (eq_attr "type" "lea,fcmov,fpspc,cld") (const_string "none") - (eq_attr "type" "fistp") + (eq_attr "type" "fistp,leave") (const_string "both") (eq_attr "type" "push") (if_then_else (match_operand 1 "memory_operand" "") (const_string "both") (const_string "store")) - (eq_attr "type" "pop,setcc") + (eq_attr "type" "pop") (if_then_else (match_operand 0 "memory_operand" "") (const_string "both") (const_string "load")) - (eq_attr "type" "icmp,test,ssecmp,mmxcmp,fcmp") + (eq_attr "type" "setcc") + (if_then_else (match_operand 0 "memory_operand" "") + (const_string "store") + (const_string "none")) + (eq_attr "type" "icmp,test,ssecmp,ssecomi,mmxcmp,fcmp") (if_then_else (ior (match_operand 0 "memory_operand" "") (match_operand 1 "memory_operand" "")) (const_string "load") @@ -327,7 +351,7 @@ (if_then_else (match_operand 1 "constant_call_address_operand" "") (const_string "none") (const_string "load")) - (and (eq_attr "type" "alu1,negnot") + (and (eq_attr "type" "alu1,negnot,ishift1") (match_operand 1 "memory_operand" "")) (const_string "both") (and (match_operand 0 "memory_operand" "") @@ -338,10 +362,10 @@ (match_operand 1 "memory_operand" "") (const_string "load") (and (eq_attr "type" - "!alu1,negnot, + "!alu1,negnot,ishift1, imov,imovx,icmp,test, fmov,fcmp,fsgn, - sse,ssemov,ssecmp,ssecvt, + sse,ssemov,ssecmp,ssecomi,ssecvt,sseicvt, mmx,mmxmov,mmxcmp,mmxcvt") (match_operand 2 "memory_operand" "")) (const_string "load") @@ -692,17 +716,6 @@ [(set (reg:CC 17) (compare:CC (match_operand:XF 0 "cmp_fp_expander_operand" "") (match_operand:XF 1 "cmp_fp_expander_operand" "")))] - "!TARGET_64BIT && TARGET_80387" -{ - ix86_compare_op0 = operands[0]; - ix86_compare_op1 = operands[1]; - DONE; -}) - -(define_expand "cmptf" - [(set (reg:CC 17) - (compare:CC (match_operand:TF 0 "cmp_fp_expander_operand" "") - (match_operand:TF 1 "cmp_fp_expander_operand" "")))] "TARGET_80387" { ix86_compare_op0 = operands[0]; @@ -766,7 +779,13 @@ return "ftst\;fnstsw\t%0"; } [(set_attr "type" "multi") - (set_attr "mode" "unknownfp")]) + (set (attr "mode") + (cond [(match_operand:SF 1 "" "") + (const_string "SF") + (match_operand:DF 1 "" "") + (const_string "DF") + ] + (const_string "XF")))]) ;; We may not use "#" to split and emit these, since the REG_DEAD notes ;; used to manage the reg stack popping would not be preserved. @@ -820,16 +839,6 @@ (compare:CCFP (match_operand:XF 0 "register_operand" "f") (match_operand:XF 1 "register_operand" "f")))] - "!TARGET_64BIT && TARGET_80387" - "* return output_fp_compare (insn, operands, 0, 0);" - [(set_attr "type" "fcmp") - (set_attr "mode" "XF")]) - -(define_insn "*cmpfp_2_tf" - [(set (reg:CCFP 18) - (compare:CCFP - (match_operand:TF 0 "register_operand" "f") - (match_operand:TF 1 "register_operand" "f")))] "TARGET_80387" "* return output_fp_compare (insn, operands, 0, 0);" [(set_attr "type" "fcmp") @@ -842,18 +851,6 @@ (match_operand:XF 1 "register_operand" "f") (match_operand:XF 2 "register_operand" "f"))] UNSPEC_FNSTSW))] - "!TARGET_64BIT && TARGET_80387" - "* return output_fp_compare (insn, operands, 2, 0);" - [(set_attr "type" "multi") - (set_attr "mode" "XF")]) - -(define_insn "*cmpfp_2_tf_1" - [(set (match_operand:HI 0 "register_operand" "=a") - (unspec:HI - [(compare:CCFP - (match_operand:TF 1 "register_operand" "f") - (match_operand:TF 2 "register_operand" "f"))] - UNSPEC_FNSTSW))] "TARGET_80387" "* return output_fp_compare (insn, operands, 2, 0);" [(set_attr "type" "multi") @@ -869,7 +866,13 @@ && GET_MODE (operands[0]) == GET_MODE (operands[1])" "* return output_fp_compare (insn, operands, 0, 1);" [(set_attr "type" "fcmp") - (set_attr "mode" "unknownfp")]) + (set (attr "mode") + (cond [(match_operand:SF 1 "" "") + (const_string "SF") + (match_operand:DF 1 "" "") + (const_string "DF") + ] + (const_string "XF")))]) (define_insn "*cmpfp_2u_1" [(set (match_operand:HI 0 "register_operand" "=a") @@ -883,7 +886,13 @@ && GET_MODE (operands[1]) == GET_MODE (operands[2])" "* return output_fp_compare (insn, operands, 2, 1);" [(set_attr "type" "multi") - (set_attr "mode" "unknownfp")]) + (set (attr "mode") + (cond [(match_operand:SF 1 "" "") + (const_string "SF") + (match_operand:DF 1 "" "") + (const_string "DF") + ] + (const_string "XF")))]) ;; Patterns to match the SImode-in-memory ficom instructions. ;; @@ -923,7 +932,7 @@ ;; FP compares, step 2 ;; Move the fpsw to ax. -(define_insn "x86_fnstsw_1" +(define_insn "*x86_fnstsw_1" [(set (match_operand:HI 0 "register_operand" "=a") (unspec:HI [(reg 18)] UNSPEC_FNSTSW))] "TARGET_80387" @@ -958,7 +967,13 @@ && GET_MODE (operands[0]) == GET_MODE (operands[0])" "* return output_fp_compare (insn, operands, 1, 0);" [(set_attr "type" "fcmp") - (set_attr "mode" "unknownfp") + (set (attr "mode") + (cond [(match_operand:SF 1 "" "") + (const_string "SF") + (match_operand:DF 1 "" "") + (const_string "DF") + ] + (const_string "XF"))) (set_attr "athlon_decode" "vector")]) (define_insn "*cmpfp_i_sse" @@ -969,8 +984,11 @@ && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[0])" "* return output_fp_compare (insn, operands, 1, 0);" - [(set_attr "type" "fcmp,ssecmp") - (set_attr "mode" "unknownfp") + [(set_attr "type" "fcmp,ssecomi") + (set (attr "mode") + (if_then_else (match_operand:SF 1 "" "") + (const_string "SF") + (const_string "DF"))) (set_attr "athlon_decode" "vector")]) (define_insn "*cmpfp_i_sse_only" @@ -980,8 +998,11 @@ "SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[0])" "* return output_fp_compare (insn, operands, 1, 0);" - [(set_attr "type" "ssecmp") - (set_attr "mode" "unknownfp") + [(set_attr "type" "ssecomi") + (set (attr "mode") + (if_then_else (match_operand:SF 1 "" "") + (const_string "SF") + (const_string "DF"))) (set_attr "athlon_decode" "vector")]) (define_insn "*cmpfp_iu" @@ -994,7 +1015,13 @@ && GET_MODE (operands[0]) == GET_MODE (operands[1])" "* return output_fp_compare (insn, operands, 1, 1);" [(set_attr "type" "fcmp") - (set_attr "mode" "unknownfp") + (set (attr "mode") + (cond [(match_operand:SF 1 "" "") + (const_string "SF") + (match_operand:DF 1 "" "") + (const_string "DF") + ] + (const_string "XF"))) (set_attr "athlon_decode" "vector")]) (define_insn "*cmpfp_iu_sse" @@ -1005,8 +1032,11 @@ && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" "* return output_fp_compare (insn, operands, 1, 1);" - [(set_attr "type" "fcmp,ssecmp") - (set_attr "mode" "unknownfp") + [(set_attr "type" "fcmp,ssecomi") + (set (attr "mode") + (if_then_else (match_operand:SF 1 "" "") + (const_string "SF") + (const_string "DF"))) (set_attr "athlon_decode" "vector")]) (define_insn "*cmpfp_iu_sse_only" @@ -1016,8 +1046,11 @@ "SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" "* return output_fp_compare (insn, operands, 1, 1);" - [(set_attr "type" "ssecmp") - (set_attr "mode" "unknownfp") + [(set_attr "type" "ssecomi") + (set (attr "mode") + (if_then_else (match_operand:SF 1 "" "") + (const_string "SF") + (const_string "DF"))) (set_attr "athlon_decode" "vector")]) ;; Move instructions. @@ -1095,13 +1128,13 @@ [(set_attr "type" "alu1") (set_attr "mode" "SI") (set_attr "length_immediate" "0")]) - + (define_insn "*movsi_or" [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "immediate_operand" "i")) (clobber (reg:CC 17))] - "reload_completed && GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) == -1 + "reload_completed + && operands[1] == constm1_rtx && (TARGET_PENTIUM || optimize_size)" { operands[1] = constm1_rtx; @@ -1112,9 +1145,49 @@ (set_attr "length_immediate" "1")]) (define_insn "*movsi_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!rm,!*y,!*Y,!*Y,!rm") - (match_operand:SI 1 "general_operand" "rinm,rin,rm,*y,*y,*Y,rm,*Y"))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!rm,!*y,!*Y,!rm,!*Y") + (match_operand:SI 1 "general_operand" "rinm,rin,*y,*y,rm,*Y,*Y,rm"))] + "(TARGET_INTER_UNIT_MOVES || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (get_attr_type (insn)) + { + case TYPE_SSEMOV: + if (get_attr_mode (insn) == MODE_TI) + return "movdqa\t{%1, %0|%0, %1}"; + return "movd\t{%1, %0|%0, %1}"; + + case TYPE_MMXMOV: + if (get_attr_mode (insn) == MODE_DI) + return "movq\t{%1, %0|%0, %1}"; + return "movd\t{%1, %0|%0, %1}"; + + case TYPE_LEA: + return "lea{l}\t{%1, %0|%0, %1}"; + + default: + if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1])) + abort(); + return "mov{l}\t{%1, %0|%0, %1}"; + } +} + [(set (attr "type") + (cond [(eq_attr "alternative" "2,3,4") + (const_string "mmxmov") + (eq_attr "alternative" "5,6,7") + (const_string "ssemov") + (and (ne (symbol_ref "flag_pic") (const_int 0)) + (match_operand:SI 1 "symbolic_operand" "")) + (const_string "lea") + ] + (const_string "imov"))) + (set_attr "mode" "SI,SI,DI,SI,SI,TI,SI,SI")]) + +(define_insn "*movsi_1_nointernunit" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m,!*y,!m,!*y,!*Y,!m,!*Y") + (match_operand:SI 1 "general_operand" "rinm,rin,*y,*y,m,*Y,*Y,m"))] + "(!TARGET_INTER_UNIT_MOVES && !optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { switch (get_attr_type (insn)) { @@ -1147,9 +1220,9 @@ (const_string "lea") ] (const_string "imov"))) - (set_attr "mode" "SI,SI,SI,SI,DI,TI,SI,SI")]) + (set_attr "mode" "SI,SI,DI,SI,SI,TI,SI,SI")]) -;; Stores and loads of ax to arbitary constant address. +;; Stores and loads of ax to arbitrary constant address. ;; We fake an second form of instruction to force reload to load address ;; into register when rax is not available (define_insn "*movabssi_1_rex64" @@ -1268,7 +1341,7 @@ ] (const_string "HI")))]) -;; Stores and loads of ax to arbitary constant address. +;; Stores and loads of ax to arbitrary constant address. ;; We fake an second form of instruction to force reload to load address ;; into register when rax is not available (define_insn "*movabshi_1_rex64" @@ -1586,7 +1659,7 @@ (const_string "SI") (const_string "QI")))]) -;; Stores and loads of ax to arbitary constant address. +;; Stores and loads of ax to arbitrary constant address. ;; We fake an second form of instruction to force reload to load address ;; into register when rax is not available (define_insn "*movabsqi_1_rex64" @@ -1690,11 +1763,11 @@ [(set_attr "type" "imov") (set_attr "mode" "QI")]) -(define_insn "*movsi_insv_1_rex64" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q") +(define_insn "movdi_insv_1_rex64" + [(set (zero_extract:DI (match_operand 0 "ext_register_operand" "+Q") (const_int 8) (const_int 8)) - (match_operand:SI 1 "nonmemory_operand" "Qn"))] + (match_operand:DI 1 "nonmemory_operand" "Qn"))] "TARGET_64BIT" "mov{b}\t{%b1, %h0|%h0, %b1}" [(set_attr "type" "imov") @@ -1704,9 +1777,8 @@ [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q") (const_int 8) (const_int 8)) - (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "Q") - (const_int 8)) - (const_int 255)))] + (lshiftrt:SI (match_operand:SI 1 "register_operand" "Q") + (const_int 8)))] "" "mov{b}\t{%h1, %h0|%h0, %h1}" [(set_attr "type" "imov") @@ -1824,8 +1896,7 @@ (clobber (reg:CC 17))] "TARGET_64BIT && (TARGET_PENTIUM || optimize_size) && reload_completed - && GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) == -1" + && operands[1] == constm1_rtx" { operands[1] = constm1_rtx; return "or{q}\t{%1, %0|%0, %1}"; @@ -1869,19 +1940,23 @@ "ix86_split_long_move (operands); DONE;") (define_insn "*movdi_1_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,mr,!mr,!m*y,!*y,!*Y,!m,!*Y") - (match_operand:DI 1 "general_operand" "Z,rem,i,re,n,*y,m,*Y,*Y,*m"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,mr,!mr,!*y,!rm,!*y,!*Y,!rm,!*Y") + (match_operand:DI 1 "general_operand" "Z,rem,i,re,n,*y,*y,rm,*Y,*Y,rm"))] "TARGET_64BIT + && (TARGET_INTER_UNIT_MOVES || optimize_size) && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { switch (get_attr_type (insn)) { case TYPE_SSEMOV: - if (register_operand (operands[0], DImode) - && register_operand (operands[1], DImode)) + if (get_attr_mode (insn) == MODE_TI) return "movdqa\t{%1, %0|%0, %1}"; /* FALLTHRU */ case TYPE_MMXMOV: + /* Moves from and into integer register is done using movd opcode with + REX prefix. */ + if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) + return "movd\t{%1, %0|%0, %1}"; return "movq\t{%1, %0|%0, %1}"; case TYPE_MULTI: return "#"; @@ -1899,9 +1974,9 @@ } } [(set (attr "type") - (cond [(eq_attr "alternative" "5,6") + (cond [(eq_attr "alternative" "5,6,7") (const_string "mmxmov") - (eq_attr "alternative" "7,8,9") + (eq_attr "alternative" "8,9,10") (const_string "ssemov") (eq_attr "alternative" "4") (const_string "multi") @@ -1910,11 +1985,57 @@ (const_string "lea") ] (const_string "imov"))) - (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*") - (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*") - (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,TI,DI")]) + (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*") + (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*") + (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,TI,DI,DI")]) -;; Stores and loads of ax to arbitary constant address. +(define_insn "*movdi_1_rex64_nointerunit" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,mr,!mr,!*y,!m,!*y,!*Y,!m,!*Y") + (match_operand:DI 1 "general_operand" "Z,rem,i,re,n,*y,*y,m,*Y,*Y,m"))] + "TARGET_64BIT + && (!TARGET_INTER_UNIT_MOVES && !optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (get_attr_type (insn)) + { + case TYPE_SSEMOV: + if (get_attr_mode (insn) == MODE_TI) + return "movdqa\t{%1, %0|%0, %1}"; + /* FALLTHRU */ + case TYPE_MMXMOV: + return "movq\t{%1, %0|%0, %1}"; + case TYPE_MULTI: + return "#"; + case TYPE_LEA: + return "lea{q}\t{%a1, %0|%0, %a1}"; + default: + if (flag_pic && !LEGITIMATE_PIC_OPERAND_P (operands[1])) + abort (); + if (get_attr_mode (insn) == MODE_SI) + return "mov{l}\t{%k1, %k0|%k0, %k1}"; + else if (which_alternative == 2) + return "movabs{q}\t{%1, %0|%0, %1}"; + else + return "mov{q}\t{%1, %0|%0, %1}"; + } +} + [(set (attr "type") + (cond [(eq_attr "alternative" "5,6,7") + (const_string "mmxmov") + (eq_attr "alternative" "8,9,10") + (const_string "ssemov") + (eq_attr "alternative" "4") + (const_string "multi") + (and (ne (symbol_ref "flag_pic") (const_int 0)) + (match_operand:DI 1 "symbolic_operand" "")) + (const_string "lea") + ] + (const_string "imov"))) + (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*") + (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*") + (set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,TI,DI,DI")]) + +;; Stores and loads of ax to arbitrary constant address. ;; We fake an second form of instruction to force reload to load address ;; into register when rax is not available (define_insn "*movabsdi_1_rex64" @@ -2007,22 +2128,11 @@ { switch (which_alternative) { - case 0: - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (SFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (4); - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{l}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{l}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - case 1: return "push{l}\t%1"; - case 2: - return "#"; default: + /* This insn should be already split before reg-stack. */ abort (); } } @@ -2036,23 +2146,11 @@ { switch (which_alternative) { - case 0: - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (SFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (8); - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{q}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{q}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - case 1: return "push{q}\t%q1"; - case 2: - return "#"; - default: + /* This insn should be already split before reg-stack. */ abort (); } } @@ -2089,7 +2187,8 @@ (define_insn "*movsf_1" [(set (match_operand:SF 0 "nonimmediate_operand" "=f#xr,m,f#xr,r#xf,m,x#rf,x#rf,x#rf,m,!*y,!rm,!*y") (match_operand:SF 1 "general_operand" "fm#rx,f#rx,G,rmF#fx,Fr#fx,C,x,xm#rf,x#rf,rm,*y,*y"))] - "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + "(TARGET_INTER_UNIT_MOVES || optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && (reload_in_progress || reload_completed || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || GET_CODE (operands[1]) != CONST_DOUBLE @@ -2113,25 +2212,117 @@ return "fst%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } + return standard_80387_constant_opcode (operands[1]); + + case 3: + case 4: + return "mov{l}\t{%1, %0|%0, %1}"; + case 5: + if (get_attr_mode (insn) == MODE_TI) + return "pxor\t%0, %0"; + else + return "xorps\t%0, %0"; + case 6: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movss\t{%1, %0|%0, %1}"; + case 7: + case 8: + return "movss\t{%1, %0|%0, %1}"; + + case 9: + case 10: + return "movd\t{%1, %0|%0, %1}"; + + case 11: + return "movq\t{%1, %0|%0, %1}"; + + default: abort(); + } +} + [(set_attr "type" "fmov,fmov,fmov,imov,imov,ssemov,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov") + (set (attr "mode") + (cond [(eq_attr "alternative" "3,4,9,10") + (const_string "SI") + (eq_attr "alternative" "5") + (if_then_else + (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") + (const_int 0)) + (ne (symbol_ref "TARGET_SSE2") + (const_int 0))) + (eq (symbol_ref "optimize_size") + (const_int 0))) + (const_string "TI") + (const_string "V4SF")) + /* For architectures resolving dependencies on + whole SSE registers use APS move to break dependency + chains, otherwise use short move to avoid extra work. + + Do the same for architectures resolving dependencies on + the parts. While in DF mode it is better to always handle + just register parts, the SF mode is different due to lack + of instructions to load just part of the register. It is + better to maintain the whole registers in single format + to avoid problems on using packed logical operations. */ + (eq_attr "alternative" "6") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") + (const_int 0)) + (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS") + (const_int 0))) + (const_string "V4SF") + (const_string "SF")) + (eq_attr "alternative" "11") + (const_string "DI")] + (const_string "SF")))]) + +(define_insn "*movsf_1_nointerunit" + [(set (match_operand:SF 0 "nonimmediate_operand" "=f#xr,m,f#xr,r#xf,m,x#rf,x#rf,x#rf,m,!*y,!m,!*y") + (match_operand:SF 1 "general_operand" "fm#rx,f#rx,G,rmF#fx,Fr#fx,C,x,xm#rf,x#rf,m,*y,*y"))] + "(!TARGET_INTER_UNIT_MOVES && !optimize_size) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + && (reload_in_progress || reload_completed + || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) + || GET_CODE (operands[1]) != CONST_DOUBLE + || memory_operand (operands[0], SFmode))" +{ + switch (which_alternative) + { + case 0: + if (REG_P (operands[1]) + && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + { + if (REGNO (operands[0]) == FIRST_STACK_REG + && TARGET_USE_FFREEP) + return "ffreep\t%y0"; + return "fstp\t%y0"; + } + else if (STACK_TOP_P (operands[0])) + return "fld%z1\t%y1"; + else + return "fst\t%y0"; + + case 1: + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return "fstp%z0\t%y0"; + else + return "fst%z0\t%y0"; + + case 2: + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "mov{l}\t{%1, %0|%0, %1}"; case 5: - if (TARGET_SSE2 && !TARGET_ATHLON) + if (get_attr_mode (insn) == MODE_TI) return "pxor\t%0, %0"; else return "xorps\t%0, %0"; case 6: - if (TARGET_PARTIAL_REG_DEPENDENCY) + if (get_attr_mode (insn) == MODE_V4SF) return "movaps\t{%1, %0|%0, %1}"; else return "movss\t{%1, %0|%0, %1}"; @@ -2151,7 +2342,40 @@ } } [(set_attr "type" "fmov,fmov,fmov,imov,imov,ssemov,ssemov,ssemov,ssemov,mmxmov,mmxmov,mmxmov") - (set_attr "mode" "SF,SF,SF,SI,SI,TI,SF,SF,SF,SI,SI,DI")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "3,4,9,10") + (const_string "SI") + (eq_attr "alternative" "5") + (if_then_else + (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") + (const_int 0)) + (ne (symbol_ref "TARGET_SSE2") + (const_int 0))) + (eq (symbol_ref "optimize_size") + (const_int 0))) + (const_string "TI") + (const_string "V4SF")) + /* For architectures resolving dependencies on + whole SSE registers use APS move to break dependency + chains, otherwise use short move to avoid extra work. + + Do the same for architectures resolving dependencies on + the parts. While in DF mode it is better to always handle + just register parts, the SF mode is different due to lack + of instructions to load just part of the register. It is + better to maintain the whole registers in single format + to avoid problems on using packed logical operations. */ + (eq_attr "alternative" "6") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") + (const_int 0)) + (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS") + (const_int 0))) + (const_string "V4SF") + (const_string "SF")) + (eq_attr "alternative" "11") + (const_string "DI")] + (const_string "SF")))]) (define_insn "*swapsf" [(set (match_operand:SF 0 "register_operand" "+f") @@ -2175,7 +2399,7 @@ "ix86_expand_move (DFmode, operands); DONE;") ;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size. -;; Size of pushdf using integer insturctions is 2+2*memory operand size +;; Size of pushdf using integer instructions is 2+2*memory operand size ;; On the average, pushdf using integers can be still shorter. Allow this ;; pattern for optimize_size too. @@ -2184,26 +2408,8 @@ (match_operand:DF 1 "general_no_elim_operand" "f#Y,Fo#fY,*r#fY,Y#f"))] "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES" { - switch (which_alternative) - { - case 0: - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (DFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (8); - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{l}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{l}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - - case 1: - case 2: - case 3: - return "#"; - - default: - abort (); - } + /* This insn should be already split before reg-stack. */ + abort (); } [(set_attr "type" "multi") (set_attr "mode" "DF,SI,SI,DF")]) @@ -2213,32 +2419,8 @@ (match_operand:DF 1 "general_no_elim_operand" "f#rY,rFo#fY,Y#rf"))] "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES" { - switch (which_alternative) - { - case 0: - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (DFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (8); - if (TARGET_64BIT) - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{q}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{q}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - else - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{l}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{l}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - - - case 1: - case 2: - return "#"; - - default: - abort (); - } + /* This insn should be already split before reg-stack. */ + abort (); } [(set_attr "type" "multi") (set_attr "mode" "DF,SI,DF")]) @@ -2275,7 +2457,7 @@ [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,m,f#Y,*r,o,Y#f,Y#f,Y#f,m") (match_operand:DF 1 "general_operand" "fm#Y,f#Y,G,*roF,F*r,C,Y#f,YHm#f,Y#f"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - && (optimize_size || !TARGET_INTEGER_DFMODE_MOVES) + && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT) && (reload_in_progress || reload_completed || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || GET_CODE (operands[1]) != CONST_DOUBLE @@ -2286,7 +2468,12 @@ case 0: if (REG_P (operands[1]) && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; + { + if (REGNO (operands[0]) == FIRST_STACK_REG + && TARGET_USE_FFREEP) + return "ffreep\t%y0"; + return "fstp\t%y0"; + } else if (STACK_TOP_P (operands[0])) return "fld%z1\t%y1"; else @@ -2299,44 +2486,90 @@ return "fst%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - abort(); + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "#"; case 5: - if (TARGET_ATHLON) - return "xorpd\t%0, %0"; - else - return "pxor\t%0, %0"; + switch (get_attr_mode (insn)) + { + case MODE_V4SF: + return "xorps\t%0, %0"; + case MODE_V2DF: + return "xorpd\t%0, %0"; + case MODE_TI: + return "pxor\t%0, %0"; + default: + abort (); + } case 6: - if (TARGET_PARTIAL_REG_DEPENDENCY) - return "movapd\t{%1, %0|%0, %1}"; + switch (get_attr_mode (insn)) + { + case MODE_V4SF: + return "movaps\t{%1, %0|%0, %1}"; + case MODE_V2DF: + return "movapd\t{%1, %0|%0, %1}"; + case MODE_DF: + return "movsd\t{%1, %0|%0, %1}"; + default: + abort (); + } + case 7: + if (get_attr_mode (insn) == MODE_V2DF) + return "movlpd\t{%1, %0|%0, %1}"; else return "movsd\t{%1, %0|%0, %1}"; - case 7: case 8: - return "movsd\t{%1, %0|%0, %1}"; + return "movsd\t{%1, %0|%0, %1}"; default: abort(); } } [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov") - (set_attr "mode" "DF,DF,DF,SI,SI,TI,DF,DF,DF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "3,4") + (const_string "SI") + /* xorps is one byte shorter. */ + (eq_attr "alternative" "5") + (cond [(ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") + (const_int 0)) + (const_string "TI")] + (const_string "V2DF")) + /* For architectures resolving dependencies on + whole SSE registers use APD move to break dependency + chains, otherwise use short move to avoid extra work. + + movaps encodes one byte shorter. */ + (eq_attr "alternative" "6") + (cond + [(ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") + (const_int 0)) + (const_string "V2DF")] + (const_string "DF")) + /* For architectures resolving dependencies on register + parts we may avoid extra work to zero out upper part + of register. */ + (eq_attr "alternative" "7") + (if_then_else + (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS") + (const_int 0)) + (const_string "V2DF") + (const_string "DF"))] + (const_string "DF")))]) (define_insn "*movdf_integer" [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Yr,m,f#Yr,r#Yf,o,Y#rf,Y#rf,Y#rf,m") (match_operand:DF 1 "general_operand" "fm#Yr,f#Yr,G,roF#Yf,Fr#Yf,C,Y#rf,Ym#rf,Y#rf"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - && !optimize_size && TARGET_INTEGER_DFMODE_MOVES + && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT) && (reload_in_progress || reload_completed || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) || GET_CODE (operands[1]) != CONST_DOUBLE @@ -2347,7 +2580,12 @@ case 0: if (REG_P (operands[1]) && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; + { + if (REGNO (operands[0]) == FIRST_STACK_REG + && TARGET_USE_FFREEP) + return "ffreep\t%y0"; + return "fstp\t%y0"; + } else if (STACK_TOP_P (operands[0])) return "fld%z1\t%y1"; else @@ -2360,30 +2598,41 @@ return "fst%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - abort(); + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "#"; case 5: - if (TARGET_ATHLON) - return "xorpd\t%0, %0"; - else - return "pxor\t%0, %0"; + switch (get_attr_mode (insn)) + { + case MODE_V4SF: + return "xorps\t%0, %0"; + case MODE_V2DF: + return "xorpd\t%0, %0"; + case MODE_TI: + return "pxor\t%0, %0"; + default: + abort (); + } case 6: - if (TARGET_PARTIAL_REG_DEPENDENCY) - return "movapd\t{%1, %0|%0, %1}"; + switch (get_attr_mode (insn)) + { + case MODE_V4SF: + return "movaps\t{%1, %0|%0, %1}"; + case MODE_V2DF: + return "movapd\t{%1, %0|%0, %1}"; + case MODE_DF: + return "movsd\t{%1, %0|%0, %1}"; + default: + abort (); + } + case 7: + if (get_attr_mode (insn) == MODE_V2DF) + return "movlpd\t{%1, %0|%0, %1}"; else return "movsd\t{%1, %0|%0, %1}"; - case 7: case 8: return "movsd\t{%1, %0|%0, %1}"; @@ -2392,7 +2641,42 @@ } } [(set_attr "type" "fmov,fmov,fmov,multi,multi,ssemov,ssemov,ssemov,ssemov") - (set_attr "mode" "DF,DF,DF,SI,SI,TI,DF,DF,DF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "3,4") + (const_string "SI") + /* xorps is one byte shorter. */ + (eq_attr "alternative" "5") + (cond [(ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") + (const_int 0)) + (const_string "TI")] + (const_string "V2DF")) + /* For architectures resolving dependencies on + whole SSE registers use APD move to break dependency + chains, otherwise use short move to avoid extra work. + + movaps encodes one byte shorter. */ + (eq_attr "alternative" "6") + (cond + [(ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (ne (symbol_ref "TARGET_SSE_PARTIAL_REG_DEPENDENCY") + (const_int 0)) + (const_string "V2DF")] + (const_string "DF")) + /* For architectures resolving dependencies on register + parts we may avoid extra work to zero out upper part + of register. */ + (eq_attr "alternative" "7") + (if_then_else + (ne (symbol_ref "TARGET_SSE_PARTIAL_REGS") + (const_int 0)) + (const_string "V2DF") + (const_string "DF"))] + (const_string "DF")))]) (define_split [(set (match_operand:DF 0 "nonimmediate_operand" "") @@ -2426,17 +2710,11 @@ (define_expand "movxf" [(set (match_operand:XF 0 "nonimmediate_operand" "") (match_operand:XF 1 "general_operand" ""))] - "!TARGET_64BIT" - "ix86_expand_move (XFmode, operands); DONE;") - -(define_expand "movtf" - [(set (match_operand:TF 0 "nonimmediate_operand" "") - (match_operand:TF 1 "general_operand" ""))] "" - "ix86_expand_move (TFmode, operands); DONE;") + "ix86_expand_move (XFmode, operands); DONE;") ;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size. -;; Size of pushdf using integer insturctions is 3+3*memory operand size +;; Size of pushdf using integer instructions is 3+3*memory operand size ;; Pushing using integer instructions is longer except for constants ;; and direct memory references. ;; (assuming that any given constant is pushed only once, but this ought to be @@ -2445,55 +2723,10 @@ (define_insn "*pushxf_nointeger" [(set (match_operand:XF 0 "push_operand" "=X,X,X") (match_operand:XF 1 "general_no_elim_operand" "f,Fo,*r"))] - "!TARGET_64BIT && optimize_size" -{ - switch (which_alternative) - { - case 0: - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (12); - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{l}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{l}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - - case 1: - case 2: - return "#"; - - default: - abort (); - } -} - [(set_attr "type" "multi") - (set_attr "mode" "XF,SI,SI")]) - -(define_insn "*pushtf_nointeger" - [(set (match_operand:TF 0 "push_operand" "=<,<,<") - (match_operand:TF 1 "general_no_elim_operand" "f,Fo,*r"))] "optimize_size" { - switch (which_alternative) - { - case 0: - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (16); - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{l}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{l}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - - case 1: - case 2: - return "#"; - - default: - abort (); - } + /* This insn should be already split before reg-stack. */ + abort (); } [(set_attr "type" "multi") (set_attr "mode" "XF,SI,SI")]) @@ -2501,59 +2734,10 @@ (define_insn "*pushxf_integer" [(set (match_operand:XF 0 "push_operand" "=<,<") (match_operand:XF 1 "general_no_elim_operand" "f#r,ro#f"))] - "!TARGET_64BIT && !optimize_size" -{ - switch (which_alternative) - { - case 0: - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (12); - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{l}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{l}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - - case 1: - return "#"; - - default: - abort (); - } -} - [(set_attr "type" "multi") - (set_attr "mode" "XF,SI")]) - -(define_insn "*pushtf_integer" - [(set (match_operand:TF 0 "push_operand" "=<,<") - (match_operand:TF 1 "general_no_elim_operand" "f#r,rFo#f"))] "!optimize_size" { - switch (which_alternative) - { - case 0: - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (16); - if (TARGET_64BIT) - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{q}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{q}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - else - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "sub{l}\t{%3, %2|%2, %3}\;fstp%z0\t%y0"; - else - return "sub{l}\t{%3, %2|%2, %3}\;fst%z0\t%y0"; - - case 1: - return "#"; - - default: - abort (); - } + /* This insn should be already split before reg-stack. */ + abort (); } [(set_attr "type" "multi") (set_attr "mode" "XF,SI")]) @@ -2563,7 +2747,6 @@ (match_operand 1 "general_operand" ""))] "reload_completed && (GET_MODE (operands[0]) == XFmode - || GET_MODE (operands[0]) == TFmode || GET_MODE (operands[0]) == DFmode) && !ANY_FP_REG_P (operands[1])" [(const_int 0)] @@ -2573,29 +2756,23 @@ [(set (match_operand:XF 0 "push_operand" "") (match_operand:XF 1 "any_fp_register_operand" ""))] "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12))) - (set (mem:XF (reg:SI 7)) (match_dup 1))]) - -(define_split - [(set (match_operand:TF 0 "push_operand" "") - (match_operand:TF 1 "any_fp_register_operand" ""))] - "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:TF (reg:SI 7)) (match_dup 1))]) + [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2))) + (set (mem:XF (reg:SI 7)) (match_dup 1))] + "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split - [(set (match_operand:TF 0 "push_operand" "") - (match_operand:TF 1 "any_fp_register_operand" ""))] + [(set (match_operand:XF 0 "push_operand" "") + (match_operand:XF 1 "any_fp_register_operand" ""))] "TARGET_64BIT" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16))) - (set (mem:TF (reg:DI 7)) (match_dup 1))]) + [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2))) + (set (mem:XF (reg:DI 7)) (match_dup 1))] + "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") ;; Do not use integer registers when optimizing for size (define_insn "*movxf_nointeger" [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o") (match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))] - "!TARGET_64BIT - && optimize_size + "optimize_size && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && (reload_in_progress || reload_completed || GET_CODE (operands[1]) != CONST_DOUBLE @@ -2606,54 +2783,12 @@ case 0: if (REG_P (operands[1]) && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; - - case 1: - /* There is no non-popping store to memory for XFmode. So if - we need one, follow the store with a load. */ - if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0\;fld%z0\t%y0"; - else - return "fstp%z0\t%y0"; - - case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; + { + if (REGNO (operands[0]) == FIRST_STACK_REG + && TARGET_USE_FFREEP) + return "ffreep\t%y0"; + return "fstp\t%y0"; } - break; - - case 3: case 4: - return "#"; - } - abort(); -} - [(set_attr "type" "fmov,fmov,fmov,multi,multi") - (set_attr "mode" "XF,XF,XF,SI,SI")]) - -(define_insn "*movtf_nointeger" - [(set (match_operand:TF 0 "nonimmediate_operand" "=f,m,f,*r,o") - (match_operand:TF 1 "general_operand" "fm,f,G,*roF,F*r"))] - "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - && optimize_size - && (reload_in_progress || reload_completed - || GET_CODE (operands[1]) != CONST_DOUBLE - || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || memory_operand (operands[0], TFmode))" -{ - switch (which_alternative) - { - case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; else if (STACK_TOP_P (operands[0])) return "fld%z1\t%y1"; else @@ -2668,14 +2803,7 @@ return "fstp%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - break; + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "#"; @@ -2688,8 +2816,7 @@ (define_insn "*movxf_integer" [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o") (match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))] - "!TARGET_64BIT - && !optimize_size + "!optimize_size && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && (reload_in_progress || reload_completed || GET_CODE (operands[1]) != CONST_DOUBLE @@ -2700,54 +2827,12 @@ case 0: if (REG_P (operands[1]) && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; - - case 1: - /* There is no non-popping store to memory for XFmode. So if - we need one, follow the store with a load. */ - if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0\;fld%z0\t%y0"; - else - return "fstp%z0\t%y0"; - - case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; + { + if (REGNO (operands[0]) == FIRST_STACK_REG + && TARGET_USE_FFREEP) + return "ffreep\t%y0"; + return "fstp\t%y0"; } - break; - - case 3: case 4: - return "#"; - } - abort(); -} - [(set_attr "type" "fmov,fmov,fmov,multi,multi") - (set_attr "mode" "XF,XF,XF,SI,SI")]) - -(define_insn "*movtf_integer" - [(set (match_operand:TF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o") - (match_operand:TF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))] - "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - && !optimize_size - && (reload_in_progress || reload_completed - || GET_CODE (operands[1]) != CONST_DOUBLE - || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) - || memory_operand (operands[0], TFmode))" -{ - switch (which_alternative) - { - case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; else if (STACK_TOP_P (operands[0])) return "fld%z1\t%y1"; else @@ -2762,14 +2847,7 @@ return "fstp%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - break; + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "#"; @@ -2784,7 +2862,7 @@ (match_operand 1 "general_operand" ""))] "reload_completed && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - && (GET_MODE (operands[0]) == XFmode || GET_MODE (operands[0]) == TFmode) + && GET_MODE (operands[0]) == XFmode && ! (ANY_FP_REG_P (operands[0]) || (GET_CODE (operands[0]) == SUBREG && ANY_FP_REG_P (SUBREG_REG (operands[0])))) @@ -2799,21 +2877,33 @@ (match_operand 1 "memory_operand" ""))] "reload_completed && GET_CODE (operands[1]) == MEM - && (GET_MODE (operands[0]) == XFmode || GET_MODE (operands[0]) == TFmode + && (GET_MODE (operands[0]) == XFmode || GET_MODE (operands[0]) == SFmode || GET_MODE (operands[0]) == DFmode) && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF - && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)) - && (!(SSE_REG_P (operands[0]) || - (GET_CODE (operands[0]) == SUBREG - && SSE_REG_P (SUBREG_REG (operands[0])))) - || standard_sse_constant_p (get_pool_constant (XEXP (operands[1], 0)))) - && (!(FP_REG_P (operands[0]) || - (GET_CODE (operands[0]) == SUBREG - && FP_REG_P (SUBREG_REG (operands[0])))) - || standard_80387_constant_p (get_pool_constant (XEXP (operands[1], 0))))" - [(set (match_dup 0) - (match_dup 1))] - "operands[1] = get_pool_constant (XEXP (operands[1], 0));") + && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))" + [(set (match_dup 0) (match_dup 1))] +{ + rtx c = get_pool_constant (XEXP (operands[1], 0)); + rtx r = operands[0]; + + if (GET_CODE (r) == SUBREG) + r = SUBREG_REG (r); + + if (SSE_REG_P (r)) + { + if (!standard_sse_constant_p (c)) + FAIL; + } + else if (FP_REG_P (r)) + { + if (!standard_80387_constant_p (c)) + FAIL; + } + else if (MMX_REG_P (r)) + FAIL; + + operands[1] = c; +}) (define_insn "swapxf" [(set (match_operand:XF 0 "register_operand" "+f") @@ -2829,21 +2919,6 @@ } [(set_attr "type" "fxch") (set_attr "mode" "XF")]) - -(define_insn "swaptf" - [(set (match_operand:TF 0 "register_operand" "+f") - (match_operand:TF 1 "register_operand" "+f")) - (set (match_dup 1) - (match_dup 0))] - "" -{ - if (STACK_TOP_P (operands[0])) - return "fxch\t%1"; - else - return "fxch\t%0"; -} - [(set_attr "type" "fxch") - (set_attr "mode" "XF")]) ;; Zero extension instructions @@ -3040,22 +3115,56 @@ ") (define_insn "zero_extendsidi2_32" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r"))) + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,!?y,!?Y") + (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,m,m"))) (clobber (reg:CC 17))] - "!TARGET_64BIT" - "#" - [(set_attr "mode" "SI")]) + "!TARGET_64BIT && !TARGET_INTER_UNIT_MOVES" + "@ + # + # + # + movd\t{%1, %0|%0, %1} + movd\t{%1, %0|%0, %1}" + [(set_attr "mode" "SI,SI,SI,DI,TI") + (set_attr "type" "multi,multi,multi,mmxmov,ssemov")]) + +(define_insn "*zero_extendsidi2_32_1" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o,!?y,!?Y") + (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,rm,r,rm,rm"))) + (clobber (reg:CC 17))] + "!TARGET_64BIT && TARGET_INTER_UNIT_MOVES" + "@ + # + # + # + movd\t{%1, %0|%0, %1} + movd\t{%1, %0|%0, %1}" + [(set_attr "mode" "SI,SI,SI,DI,TI") + (set_attr "type" "multi,multi,multi,mmxmov,ssemov")]) (define_insn "zero_extendsidi2_rex64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o") - (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0")))] - "TARGET_64BIT" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,!?y,!?Y") + (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,m,m")))] + "TARGET_64BIT && !TARGET_INTER_UNIT_MOVES" "@ mov\t{%k1, %k0|%k0, %k1} - #" - [(set_attr "type" "imovx,imov") - (set_attr "mode" "SI,DI")]) + # + movd\t{%1, %0|%0, %1} + movd\t{%1, %0|%0, %1}" + [(set_attr "type" "imovx,imov,mmxmov,ssemov") + (set_attr "mode" "SI,DI,DI,TI")]) + +(define_insn "*zero_extendsidi2_rex64_1" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,!?y,!*?") + (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm,0,rm,rm")))] + "TARGET_64BIT && TARGET_INTER_UNIT_MOVES" + "@ + mov\t{%k1, %k0|%k0, %k1} + # + movd\t{%1, %0|%0, %1} + movd\t{%1, %0|%0, %1}" + [(set_attr "type" "imovx,imov,mmxmov,ssemov") + (set_attr "mode" "SI,DI,SI,SI")]) (define_split [(set (match_operand:DI 0 "memory_operand" "") @@ -3077,7 +3186,8 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "") (zero_extend:DI (match_operand:SI 1 "general_operand" ""))) (clobber (reg:CC 17))] - "!TARGET_64BIT && reload_completed" + "!TARGET_64BIT && reload_completed + && !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])" [(set (match_dup 3) (match_dup 1)) (set (match_dup 4) (const_int 0))] "split_di (&operands[0], 1, &operands[3], &operands[4]);") @@ -3359,62 +3469,34 @@ (define_split [(set (match_operand:XF 0 "push_operand" "") (float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))] - "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12))) - (set (mem:XF (reg:SI 7)) (float_extend:XF (match_dup 1)))]) - -(define_insn "*dummy_extendsftf2" - [(set (match_operand:TF 0 "push_operand" "=<") - (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "f")))] - "0" - "#") - -(define_split - [(set (match_operand:TF 0 "push_operand" "") - (float_extend:TF (match_operand:SF 1 "fp_register_operand" "")))] - "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:TF (reg:SI 7)) (float_extend:TF (match_dup 1)))]) + "" + [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2))) + (set (mem:XF (reg:SI 7)) (float_extend:XF (match_dup 1)))] + "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split - [(set (match_operand:TF 0 "push_operand" "") - (float_extend:TF (match_operand:SF 1 "fp_register_operand" "")))] + [(set (match_operand:XF 0 "push_operand" "") + (float_extend:XF (match_operand:SF 1 "fp_register_operand" "")))] "TARGET_64BIT" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16))) - (set (mem:DF (reg:DI 7)) (float_extend:TF (match_dup 1)))]) - -(define_insn "*dummy_extenddfxf2" - [(set (match_operand:XF 0 "push_operand" "=<") - (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "f")))] - "0" - "#") + [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2))) + (set (mem:DF (reg:DI 7)) (float_extend:XF (match_dup 1)))] + "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split [(set (match_operand:XF 0 "push_operand" "") (float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))] - "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12))) - (set (mem:DF (reg:SI 7)) (float_extend:XF (match_dup 1)))]) - -(define_insn "*dummy_extenddftf2" - [(set (match_operand:TF 0 "push_operand" "=<") - (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "f")))] - "0" - "#") - -(define_split - [(set (match_operand:TF 0 "push_operand" "") - (float_extend:TF (match_operand:DF 1 "fp_register_operand" "")))] - "!TARGET_64BIT" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:TF (reg:SI 7)) (float_extend:XF (match_dup 1)))]) + "" + [(set (reg:SI 7) (plus:SI (reg:SI 7) (match_dup 2))) + (set (mem:DF (reg:SI 7)) (float_extend:XF (match_dup 1)))] + "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_split - [(set (match_operand:TF 0 "push_operand" "") - (float_extend:TF (match_operand:DF 1 "fp_register_operand" "")))] + [(set (match_operand:XF 0 "push_operand" "") + (float_extend:XF (match_operand:DF 1 "fp_register_operand" "")))] "TARGET_64BIT" - [(set (reg:DI 7) (plus:DI (reg:DI 7) (const_int -16))) - (set (mem:TF (reg:DI 7)) (float_extend:TF (match_dup 1)))]) + [(set (reg:DI 7) (plus:DI (reg:DI 7) (match_dup 2))) + (set (mem:XF (reg:DI 7)) (float_extend:XF (match_dup 1)))] + "operands[2] = GEN_INT (TARGET_128BIT_LONG_DOUBLE ? -16 : -12);") (define_expand "extendsfdf2" [(set (match_operand:DF 0 "nonimmediate_operand" "") @@ -3474,7 +3556,7 @@ (define_expand "extendsfxf2" [(set (match_operand:XF 0 "nonimmediate_operand" "") (float_extend:XF (match_operand:SF 1 "general_operand" "")))] - "!TARGET_64BIT && TARGET_80387" + "TARGET_80387" { /* ??? Needed for compress_float_constant since all fp constants are LEGITIMATE_CONSTANT_P. */ @@ -3487,51 +3569,6 @@ (define_insn "*extendsfxf2_1" [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m") (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))] - "!TARGET_64BIT && TARGET_80387 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; - - case 1: - /* There is no non-popping store to memory for XFmode. So if - we need one, follow the store with a load. */ - if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0\n\tfld%z0\t%y0"; - else - return "fstp%z0\t%y0"; - - default: - abort (); - } -} - [(set_attr "type" "fmov") - (set_attr "mode" "SF,XF")]) - -(define_expand "extendsftf2" - [(set (match_operand:TF 0 "nonimmediate_operand" "") - (float_extend:TF (match_operand:SF 1 "general_operand" "")))] - "TARGET_80387" -{ - /* ??? Needed for compress_float_constant since all fp constants - are LEGITIMATE_CONSTANT_P. */ - if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[1] = force_reg (SFmode, operands[1]); -}) - -(define_insn "*extendsftf2_1" - [(set (match_operand:TF 0 "nonimmediate_operand" "=f,m") - (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))] "TARGET_80387 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { @@ -3564,7 +3601,7 @@ (define_expand "extenddfxf2" [(set (match_operand:XF 0 "nonimmediate_operand" "") (float_extend:XF (match_operand:DF 1 "general_operand" "")))] - "!TARGET_64BIT && TARGET_80387" + "TARGET_80387" { /* ??? Needed for compress_float_constant since all fp constants are LEGITIMATE_CONSTANT_P. */ @@ -3577,51 +3614,6 @@ (define_insn "*extenddfxf2_1" [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m") (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))] - "!TARGET_64BIT && TARGET_80387 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" -{ - switch (which_alternative) - { - case 0: - if (REG_P (operands[1]) - && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp\t%y0"; - else if (STACK_TOP_P (operands[0])) - return "fld%z1\t%y1"; - else - return "fst\t%y0"; - - case 1: - /* There is no non-popping store to memory for XFmode. So if - we need one, follow the store with a load. */ - if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0\n\tfld%z0\t%y0"; - else - return "fstp%z0\t%y0"; - - default: - abort (); - } -} - [(set_attr "type" "fmov") - (set_attr "mode" "DF,XF")]) - -(define_expand "extenddftf2" - [(set (match_operand:TF 0 "nonimmediate_operand" "") - (float_extend:TF (match_operand:DF 1 "general_operand" "")))] - "TARGET_80387" -{ - /* ??? Needed for compress_float_constant since all fp constants - are LEGITIMATE_CONSTANT_P. */ - if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = validize_mem (force_const_mem (DFmode, operands[1])); - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[1] = force_reg (DFmode, operands[1]); -}) - -(define_insn "*extenddftf2_1" - [(set (match_operand:TF 0 "nonimmediate_operand" "=f,m") - (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))] "TARGET_80387 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { @@ -3695,11 +3687,11 @@ (set_attr "mode" "SF,SF,SF,SF")]) (define_insn "*truncdfsf2_1_sse" - [(set (match_operand:SF 0 "nonimmediate_operand" "=*!m,?f#rx,?r#fx,?x#rf,Y") + [(set (match_operand:SF 0 "nonimmediate_operand" "=*!m#fxr,?f#xr,?r#fx,?x#fr,Y#fr") (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "f,f,f,f,mY"))) + (match_operand:DF 1 "nonimmediate_operand" "f#Y,f#Y,f#Y,f#Y,mY#f"))) (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m,X"))] - "TARGET_80387 && TARGET_SSE2" + "TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" { switch (which_alternative) { @@ -3709,7 +3701,30 @@ else return "fst%z0\t%y0"; case 4: - return "cvtsd2ss\t{%1, %0|%0, %1}"; + return "#"; + default: + abort (); + } +} + [(set_attr "type" "fmov,multi,multi,multi,ssecvt") + (set_attr "mode" "SF,SF,SF,SF,DF")]) + +(define_insn "*truncdfsf2_1_sse_nooverlap" + [(set (match_operand:SF 0 "nonimmediate_operand" "=*!m,?f#rx,?r#fx,?x#rf,&Y") + (float_truncate:SF + (match_operand:DF 1 "nonimmediate_operand" "f#Y,f#Y,f#Y,f#Y,mY#f"))) + (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m,X"))] + "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" +{ + switch (which_alternative) + { + case 0: + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return "fstp%z0\t%y0"; + else + return "fst%z0\t%y0"; + case 4: + return "#"; default: abort (); } @@ -3718,16 +3733,41 @@ (set_attr "mode" "SF,SF,SF,SF,DF")]) (define_insn "*truncdfsf2_2" - [(set (match_operand:SF 0 "nonimmediate_operand" "=Y,!m") + [(set (match_operand:SF 0 "nonimmediate_operand" "=Y,Y,!m") (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "mY,f")))] - "TARGET_80387 && TARGET_SSE2 + (match_operand:DF 1 "nonimmediate_operand" "Y,mY,f#Y")))] + "TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { switch (which_alternative) { case 0: + case 1: return "cvtsd2ss\t{%1, %0|%0, %1}"; + case 2: + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return "fstp%z0\t%y0"; + else + return "fst%z0\t%y0"; + default: + abort (); + } +} + [(set_attr "type" "ssecvt,ssecvt,fmov") + (set_attr "athlon_decode" "vector,double,*") + (set_attr "mode" "SF,SF,SF")]) + +(define_insn "*truncdfsf2_2_nooverlap" + [(set (match_operand:SF 0 "nonimmediate_operand" "=&Y,!m") + (float_truncate:SF + (match_operand:DF 1 "nonimmediate_operand" "mY,f")))] + "TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (which_alternative) + { + case 0: + return "#"; case 1: if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) return "fstp%z0\t%y0"; @@ -3740,7 +3780,7 @@ [(set_attr "type" "ssecvt,fmov") (set_attr "mode" "DF,SF")]) -(define_insn "truncdfsf2_3" +(define_insn "*truncdfsf2_3" [(set (match_operand:SF 0 "memory_operand" "=m") (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] @@ -3755,12 +3795,22 @@ (set_attr "mode" "SF")]) (define_insn "truncdfsf2_sse_only" - [(set (match_operand:SF 0 "register_operand" "=Y") + [(set (match_operand:SF 0 "register_operand" "=Y,Y") (float_truncate:SF - (match_operand:DF 1 "nonimmediate_operand" "mY")))] - "!TARGET_80387 && TARGET_SSE2" + (match_operand:DF 1 "nonimmediate_operand" "Y,mY")))] + "!TARGET_80387 && TARGET_SSE2 && !TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" "cvtsd2ss\t{%1, %0|%0, %1}" [(set_attr "type" "ssecvt") + (set_attr "athlon_decode" "vector,double") + (set_attr "mode" "SF")]) + +(define_insn "*truncdfsf2_sse_only_nooverlap" + [(set (match_operand:SF 0 "register_operand" "=&Y") + (float_truncate:SF + (match_operand:DF 1 "nonimmediate_operand" "mY")))] + "!TARGET_80387 && TARGET_SSE2 && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" + "#" + [(set_attr "type" "ssecvt") (set_attr "mode" "DF")]) (define_split @@ -3772,100 +3822,79 @@ [(set (match_dup 0) (float_truncate:SF (match_dup 1)))] "") +; Avoid possible reformatting penalty on the destination by first +; zeroing it out (define_split - [(set (match_operand:SF 0 "nonimmediate_operand" "") + [(set (match_operand:SF 0 "register_operand" "") (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" ""))) (clobber (match_operand 2 "" ""))] "TARGET_80387 && reload_completed - && !FP_REG_P (operands[0]) && !FP_REG_P (operands[1])" - [(set (match_dup 0) (float_truncate:SF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float_truncate:SF - (match_operand:DF 1 "fp_register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) (float_truncate:SF (match_dup 1))) - (set (match_dup 0) (match_dup 2))] - "") - -(define_expand "truncxfsf2" - [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") - (float_truncate:SF - (match_operand:XF 1 "register_operand" ""))) - (clobber (match_dup 2))])] - "!TARGET_64BIT && TARGET_80387" - "operands[2] = assign_386_stack_local (SFmode, 0);") - -(define_insn "*truncxfsf2_1" - [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf") - (float_truncate:SF - (match_operand:XF 1 "register_operand" "f,f,f,f"))) - (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))] - "!TARGET_64BIT && TARGET_80387" + && SSE_REG_P (operands[0]) + && !STACK_REG_P (operands[1])" + [(const_int 0)] { - switch (which_alternative) + rtx src, dest; + if (!TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS) + emit_insn (gen_truncdfsf2_sse_only (operands[0], operands[1])); + else { - case 0: - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; - default: - abort(); + dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); + src = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0); + /* simplify_gen_subreg refuses to widen memory references. */ + if (GET_CODE (src) == SUBREG) + alter_subreg (&src); + if (reg_overlap_mentioned_p (operands[0], operands[1])) + abort (); + emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode))); + emit_insn (gen_cvtsd2ss (dest, dest, src)); } -} - [(set_attr "type" "fmov,multi,multi,multi") - (set_attr "mode" "SF")]) - -(define_insn "*truncxfsf2_2" - [(set (match_operand:SF 0 "memory_operand" "=m") - (float_truncate:SF - (match_operand:XF 1 "register_operand" "f")))] - "!TARGET_64BIT && TARGET_80387" -{ - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; -} - [(set_attr "type" "fmov") - (set_attr "mode" "SF")]) + DONE; +}) (define_split - [(set (match_operand:SF 0 "memory_operand" "") + [(set (match_operand:SF 0 "register_operand" "") (float_truncate:SF - (match_operand:XF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387" - [(set (match_dup 0) (float_truncate:SF (match_dup 1)))] - "") + (match_operand:DF 1 "nonimmediate_operand" "")))] + "TARGET_80387 && reload_completed + && SSE_REG_P (operands[0]) && TARGET_SSE_PARTIAL_REGS_FOR_CVTSD2SS" + [(const_int 0)] +{ + rtx src, dest; + dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); + src = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0); + /* simplify_gen_subreg refuses to widen memory references. */ + if (GET_CODE (src) == SUBREG) + alter_subreg (&src); + if (reg_overlap_mentioned_p (operands[0], operands[1])) + abort (); + emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode))); + emit_insn (gen_cvtsd2ss (dest, dest, src)); + DONE; +}) (define_split [(set (match_operand:SF 0 "register_operand" "") (float_truncate:SF - (match_operand:XF 1 "register_operand" ""))) + (match_operand:DF 1 "fp_register_operand" ""))) (clobber (match_operand:SF 2 "memory_operand" ""))] "TARGET_80387 && reload_completed" [(set (match_dup 2) (float_truncate:SF (match_dup 1))) (set (match_dup 0) (match_dup 2))] "") -(define_expand "trunctfsf2" +(define_expand "truncxfsf2" [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") (float_truncate:SF - (match_operand:TF 1 "register_operand" ""))) + (match_operand:XF 1 "register_operand" ""))) (clobber (match_dup 2))])] "TARGET_80387" "operands[2] = assign_386_stack_local (SFmode, 0);") -(define_insn "*trunctfsf2_1" +(define_insn "*truncxfsf2_1" [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf") (float_truncate:SF - (match_operand:TF 1 "register_operand" "f,f,f,f"))) + (match_operand:XF 1 "register_operand" "f,f,f,f"))) (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))] "TARGET_80387" { @@ -3883,10 +3912,10 @@ [(set_attr "type" "fmov,multi,multi,multi") (set_attr "mode" "SF")]) -(define_insn "*trunctfsf2_2" +(define_insn "*truncxfsf2_2" [(set (match_operand:SF 0 "memory_operand" "=m") (float_truncate:SF - (match_operand:TF 1 "register_operand" "f")))] + (match_operand:XF 1 "register_operand" "f")))] "TARGET_80387" { if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) @@ -3900,7 +3929,7 @@ (define_split [(set (match_operand:SF 0 "memory_operand" "") (float_truncate:SF - (match_operand:TF 1 "register_operand" ""))) + (match_operand:XF 1 "register_operand" ""))) (clobber (match_operand:SF 2 "memory_operand" ""))] "TARGET_80387" [(set (match_dup 0) (float_truncate:SF (match_dup 1)))] @@ -3909,20 +3938,19 @@ (define_split [(set (match_operand:SF 0 "register_operand" "") (float_truncate:SF - (match_operand:TF 1 "register_operand" ""))) + (match_operand:XF 1 "register_operand" ""))) (clobber (match_operand:SF 2 "memory_operand" ""))] "TARGET_80387 && reload_completed" [(set (match_dup 2) (float_truncate:SF (match_dup 1))) (set (match_dup 0) (match_dup 2))] "") - (define_expand "truncxfdf2" [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "") (float_truncate:DF (match_operand:XF 1 "register_operand" ""))) (clobber (match_dup 2))])] - "!TARGET_64BIT && TARGET_80387" + "TARGET_80387" "operands[2] = assign_386_stack_local (DFmode, 0);") (define_insn "*truncxfdf2_1" @@ -3930,7 +3958,7 @@ (float_truncate:DF (match_operand:XF 1 "register_operand" "f,f,f,f"))) (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))] - "!TARGET_64BIT && TARGET_80387" + "TARGET_80387" { switch (which_alternative) { @@ -3951,7 +3979,7 @@ [(set (match_operand:DF 0 "memory_operand" "=m") (float_truncate:DF (match_operand:XF 1 "register_operand" "f")))] - "!TARGET_64BIT && TARGET_80387" + "TARGET_80387" { if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) return "fstp%z0\t%y0"; @@ -3980,69 +4008,6 @@ (set (match_dup 0) (match_dup 2))] "") -(define_expand "trunctfdf2" - [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "") - (float_truncate:DF - (match_operand:TF 1 "register_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (DFmode, 0);") - -(define_insn "*trunctfdf2_1" - [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf") - (float_truncate:DF - (match_operand:TF 1 "register_operand" "f,f,f,f"))) - (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))] - "TARGET_80387" -{ - switch (which_alternative) - { - case 0: - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; - default: - abort(); - } - abort (); -} - [(set_attr "type" "fmov,multi,multi,multi") - (set_attr "mode" "DF")]) - - (define_insn "*trunctfdf2_2" - [(set (match_operand:DF 0 "memory_operand" "=m") - (float_truncate:DF - (match_operand:TF 1 "register_operand" "f")))] - "TARGET_80387" -{ - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return "fstp%z0\t%y0"; - else - return "fst%z0\t%y0"; -} - [(set_attr "type" "fmov") - (set_attr "mode" "DF")]) - -(define_split - [(set (match_operand:DF 0 "memory_operand" "") - (float_truncate:DF - (match_operand:TF 1 "register_operand" ""))) - (clobber (match_operand:DF 2 "memory_operand" ""))] - "TARGET_80387" - [(set (match_dup 0) (float_truncate:DF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float_truncate:DF - (match_operand:TF 1 "register_operand" ""))) - (clobber (match_operand:DF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) (float_truncate:DF (match_dup 1))) - (set (match_dup 0) (match_dup 2))] - "") - ;; %%% Break up all these bad boys. @@ -4051,12 +4016,6 @@ (define_expand "fix_truncxfdi2" [(set (match_operand:DI 0 "nonimmediate_operand" "") (fix:DI (match_operand:XF 1 "register_operand" "")))] - "!TARGET_64BIT && TARGET_80387" - "") - -(define_expand "fix_trunctfdi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (fix:DI (match_operand:TF 1 "register_operand" "")))] "TARGET_80387" "") @@ -4102,6 +4061,7 @@ "&& 1" [(const_int 0)] { + ix86_optimize_mode_switching = 1; operands[2] = assign_386_stack_local (HImode, 1); operands[3] = assign_386_stack_local (HImode, 2); if (memory_operand (operands[0], VOIDmode)) @@ -4116,7 +4076,8 @@ } DONE; } - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "DI")]) (define_insn "fix_truncdi_nomemory" [(set (match_operand:DI 0 "nonimmediate_operand" "=m,?r") @@ -4128,7 +4089,8 @@ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)" "#" - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "DI")]) (define_insn "fix_truncdi_memory" [(set (match_operand:DI 0 "memory_operand" "=m") @@ -4139,7 +4101,8 @@ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && (!SSE_FLOAT_MODE_P (GET_MODE (operands[1])) || !TARGET_64BIT)" "* operands[5] = operands[4]; return output_fix_trunc (insn, operands);" - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "DI")]) (define_split [(set (match_operand:DI 0 "register_operand" "") @@ -4172,30 +4135,48 @@ ;; When SSE available, it is always faster to use it! (define_insn "fix_truncsfdi_sse" - [(set (match_operand:DI 0 "register_operand" "=r") - (fix:DI (match_operand:SF 1 "nonimmediate_operand" "xm")))] + [(set (match_operand:DI 0 "register_operand" "=r,r") + (fix:DI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))] "TARGET_64BIT && TARGET_SSE" "cvttss2si{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt")]) + [(set_attr "type" "sseicvt") + (set_attr "mode" "SF") + (set_attr "athlon_decode" "double,vector")]) + +;; Avoid vector decoded form of the instruction. +(define_peephole2 + [(match_scratch:SF 2 "x") + (set (match_operand:DI 0 "register_operand" "") + (fix:DI (match_operand:SF 1 "memory_operand" "")))] + "TARGET_K8 && !optimize_size" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (fix:DI (match_dup 2)))] + "") (define_insn "fix_truncdfdi_sse" - [(set (match_operand:DI 0 "register_operand" "=r") - (fix:DI (match_operand:DF 1 "nonimmediate_operand" "Ym")))] + [(set (match_operand:DI 0 "register_operand" "=r,r") + (fix:DI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))] "TARGET_64BIT && TARGET_SSE2" "cvttsd2si{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt")]) + [(set_attr "type" "sseicvt,sseicvt") + (set_attr "mode" "DF") + (set_attr "athlon_decode" "double,vector")]) + +;; Avoid vector decoded form of the instruction. +(define_peephole2 + [(match_scratch:DF 2 "Y") + (set (match_operand:DI 0 "register_operand" "") + (fix:DI (match_operand:DF 1 "memory_operand" "")))] + "TARGET_K8 && !optimize_size" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (fix:DI (match_dup 2)))] + "") ;; Signed conversion to SImode. (define_expand "fix_truncxfsi2" [(set (match_operand:SI 0 "nonimmediate_operand" "") (fix:SI (match_operand:XF 1 "register_operand" "")))] - "!TARGET_64BIT && TARGET_80387" - "") - -(define_expand "fix_trunctfsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (fix:SI (match_operand:TF 1 "register_operand" "")))] "TARGET_80387" "") @@ -4241,6 +4222,7 @@ "&& 1" [(const_int 0)] { + ix86_optimize_mode_switching = 1; operands[2] = assign_386_stack_local (HImode, 1); operands[3] = assign_386_stack_local (HImode, 2); if (memory_operand (operands[0], VOIDmode)) @@ -4255,7 +4237,8 @@ } DONE; } - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "SI")]) (define_insn "fix_truncsi_nomemory" [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?r") @@ -4266,7 +4249,8 @@ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))" "#" - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "SI")]) (define_insn "fix_truncsi_memory" [(set (match_operand:SI 0 "memory_operand" "=m") @@ -4276,22 +4260,47 @@ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))" "* return output_fix_trunc (insn, operands);" - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "SI")]) ;; When SSE available, it is always faster to use it! (define_insn "fix_truncsfsi_sse" - [(set (match_operand:SI 0 "register_operand" "=r") - (fix:SI (match_operand:SF 1 "nonimmediate_operand" "xm")))] + [(set (match_operand:SI 0 "register_operand" "=r,r") + (fix:SI (match_operand:SF 1 "nonimmediate_operand" "x,xm")))] "TARGET_SSE" "cvttss2si\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt")]) + [(set_attr "type" "sseicvt") + (set_attr "mode" "DF") + (set_attr "athlon_decode" "double,vector")]) + +;; Avoid vector decoded form of the instruction. +(define_peephole2 + [(match_scratch:SF 2 "x") + (set (match_operand:SI 0 "register_operand" "") + (fix:SI (match_operand:SF 1 "memory_operand" "")))] + "TARGET_K8 && !optimize_size" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (fix:SI (match_dup 2)))] + "") (define_insn "fix_truncdfsi_sse" - [(set (match_operand:SI 0 "register_operand" "=r") - (fix:SI (match_operand:DF 1 "nonimmediate_operand" "Ym")))] + [(set (match_operand:SI 0 "register_operand" "=r,r") + (fix:SI (match_operand:DF 1 "nonimmediate_operand" "Y,Ym")))] "TARGET_SSE2" "cvttsd2si\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt")]) + [(set_attr "type" "sseicvt") + (set_attr "mode" "DF") + (set_attr "athlon_decode" "double,vector")]) + +;; Avoid vector decoded form of the instruction. +(define_peephole2 + [(match_scratch:DF 2 "Y") + (set (match_operand:SI 0 "register_operand" "") + (fix:SI (match_operand:DF 1 "memory_operand" "")))] + "TARGET_K8 && !optimize_size" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (fix:SI (match_dup 2)))] + "") (define_split [(set (match_operand:SI 0 "register_operand" "") @@ -4323,12 +4332,6 @@ (define_expand "fix_truncxfhi2" [(set (match_operand:HI 0 "nonimmediate_operand" "") (fix:HI (match_operand:XF 1 "register_operand" "")))] - "!TARGET_64BIT && TARGET_80387" - "") - -(define_expand "fix_trunctfhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (fix:HI (match_operand:TF 1 "register_operand" "")))] "TARGET_80387" "") @@ -4356,6 +4359,7 @@ "" [(const_int 0)] { + ix86_optimize_mode_switching = 1; operands[2] = assign_386_stack_local (HImode, 1); operands[3] = assign_386_stack_local (HImode, 2); if (memory_operand (operands[0], VOIDmode)) @@ -4370,7 +4374,8 @@ } DONE; } - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "HI")]) (define_insn "fix_trunchi_nomemory" [(set (match_operand:HI 0 "nonimmediate_operand" "=m,?r") @@ -4381,7 +4386,8 @@ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))" "#" - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "HI")]) (define_insn "fix_trunchi_memory" [(set (match_operand:HI 0 "memory_operand" "=m") @@ -4391,7 +4397,8 @@ "TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[1])) && !SSE_FLOAT_MODE_P (GET_MODE (operands[1]))" "* return output_fix_trunc (insn, operands);" - [(set_attr "type" "fistp")]) + [(set_attr "type" "fistp") + (set_attr "mode" "HI")]) (define_split [(set (match_operand:HI 0 "memory_operand" "") @@ -4446,10 +4453,23 @@ ;; Even though we only accept memory inputs, the backend _really_ ;; wants to be able to do this between registers. -(define_insn "floathisf2" +(define_expand "floathisf2" + [(set (match_operand:SF 0 "register_operand" "") + (float:SF (match_operand:HI 1 "nonimmediate_operand" "")))] + "TARGET_SSE || TARGET_80387" +{ + if (TARGET_SSE && TARGET_SSE_MATH) + { + emit_insn (gen_floatsisf2 (operands[0], + convert_to_mode (SImode, operands[1], 0))); + DONE; + } +}) + +(define_insn "*floathisf2_1" [(set (match_operand:SF 0 "register_operand" "=f,f") (float:SF (match_operand:HI 1 "nonimmediate_operand" "m,r")))] - "TARGET_80387 && !TARGET_SSE" + "TARGET_80387 && (!TARGET_SSE || !TARGET_SSE_MATH)" "@ fild%z1\t%1 #" @@ -4464,26 +4484,45 @@ "") (define_insn "*floatsisf2_i387" - [(set (match_operand:SF 0 "register_operand" "=f,?f,x") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,mr")))] + [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f") + (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))] "TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)" "@ fild%z1\t%1 # + cvtsi2ss\t{%1, %0|%0, %1} cvtsi2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,ssecvt") + [(set_attr "type" "fmov,multi,sseicvt,sseicvt") (set_attr "mode" "SF") + (set_attr "athlon_decode" "*,*,vector,double") (set_attr "fp_int_src" "true")]) (define_insn "*floatsisf2_sse" - [(set (match_operand:SF 0 "register_operand" "=x") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "mr")))] + [(set (match_operand:SF 0 "register_operand" "=x,x") + (float:SF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))] "TARGET_SSE" "cvtsi2ss\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") (set_attr "mode" "SF") + (set_attr "athlon_decode" "vector,double") (set_attr "fp_int_src" "true")]) +; Avoid possible reformatting penalty on the destination by first +; zeroing it out +(define_split + [(set (match_operand:SF 0 "register_operand" "") + (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))] + "TARGET_80387 && reload_completed && TARGET_SSE_PARTIAL_REGS + && SSE_REG_P (operands[0])" + [(const_int 0)] +{ + rtx dest; + dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); + emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode))); + emit_insn (gen_cvtsi2ss (dest, dest, operands[1])); + DONE; +}) + (define_expand "floatdisf2" [(set (match_operand:SF 0 "register_operand" "") (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))] @@ -4502,30 +4541,62 @@ (set_attr "fp_int_src" "true")]) (define_insn "*floatdisf2_i387" - [(set (match_operand:SF 0 "register_operand" "=f,?f,x") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,mr")))] + [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f") + (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))] "TARGET_64BIT && TARGET_80387 && (!TARGET_SSE || TARGET_MIX_SSE_I387)" "@ fild%z1\t%1 # + cvtsi2ss{q}\t{%1, %0|%0, %1} cvtsi2ss{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,ssecvt") + [(set_attr "type" "fmov,multi,sseicvt,sseicvt") (set_attr "mode" "SF") + (set_attr "athlon_decode" "*,*,vector,double") (set_attr "fp_int_src" "true")]) (define_insn "*floatdisf2_sse" - [(set (match_operand:SF 0 "register_operand" "=x") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "mr")))] + [(set (match_operand:SF 0 "register_operand" "=x,x") + (float:SF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))] "TARGET_64BIT && TARGET_SSE" "cvtsi2ss{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") (set_attr "mode" "SF") + (set_attr "athlon_decode" "vector,double") (set_attr "fp_int_src" "true")]) -(define_insn "floathidf2" +; Avoid possible reformatting penalty on the destination by first +; zeroing it out +(define_split + [(set (match_operand:SF 0 "register_operand" "") + (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))] + "TARGET_80387 && reload_completed && TARGET_SSE_PARTIAL_REGS + && SSE_REG_P (operands[0])" + [(const_int 0)] +{ + rtx dest; + dest = simplify_gen_subreg (V4SFmode, operands[0], SFmode, 0); + emit_insn (gen_sse_clrv4sf (dest, CONST0_RTX (V4SFmode))); + emit_insn (gen_cvtsi2ssq (dest, dest, operands[1])); + DONE; +}) + +(define_expand "floathidf2" + [(set (match_operand:DF 0 "register_operand" "") + (float:DF (match_operand:HI 1 "nonimmediate_operand" "")))] + "TARGET_SSE2 || TARGET_80387" +{ + if (TARGET_SSE && TARGET_SSE_MATH) + { + emit_insn (gen_floatsidf2 (operands[0], + convert_to_mode (SImode, operands[1], 0))); + DONE; + } +}) + +(define_insn "*floathidf2_1" [(set (match_operand:DF 0 "register_operand" "=f,f") (float:DF (match_operand:HI 1 "nonimmediate_operand" "m,r")))] - "TARGET_80387 && !TARGET_SSE2" + "TARGET_80387 && (!TARGET_SSE2 || !TARGET_SSE_MATH)" "@ fild%z1\t%1 #" @@ -4540,24 +4611,27 @@ "") (define_insn "*floatsidf2_i387" - [(set (match_operand:DF 0 "register_operand" "=f,?f,Y") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,mr")))] + [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f") + (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))] "TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)" "@ fild%z1\t%1 # + cvtsi2sd\t{%1, %0|%0, %1} cvtsi2sd\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,ssecvt") + [(set_attr "type" "fmov,multi,sseicvt,sseicvt") (set_attr "mode" "DF") + (set_attr "athlon_decode" "*,*,double,direct") (set_attr "fp_int_src" "true")]) (define_insn "*floatsidf2_sse" - [(set (match_operand:DF 0 "register_operand" "=Y") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "mr")))] + [(set (match_operand:DF 0 "register_operand" "=Y,Y") + (float:DF (match_operand:SI 1 "nonimmediate_operand" "r,mr")))] "TARGET_SSE2" "cvtsi2sd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") (set_attr "mode" "DF") + (set_attr "athlon_decode" "double,direct") (set_attr "fp_int_src" "true")]) (define_expand "floatdidf2" @@ -4578,40 +4652,32 @@ (set_attr "fp_int_src" "true")]) (define_insn "*floatdidf2_i387" - [(set (match_operand:DF 0 "register_operand" "=f,?f,Y") - (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,mr")))] + [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f") + (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))] "TARGET_64BIT && TARGET_80387 && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)" "@ fild%z1\t%1 # + cvtsi2sd{q}\t{%1, %0|%0, %1} cvtsi2sd{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "fmov,multi,ssecvt") + [(set_attr "type" "fmov,multi,sseicvt,sseicvt") (set_attr "mode" "DF") + (set_attr "athlon_decode" "*,*,double,direct") (set_attr "fp_int_src" "true")]) (define_insn "*floatdidf2_sse" - [(set (match_operand:DF 0 "register_operand" "=Y") - (float:DF (match_operand:DI 1 "nonimmediate_operand" "mr")))] + [(set (match_operand:DF 0 "register_operand" "=Y,Y") + (float:DF (match_operand:DI 1 "nonimmediate_operand" "r,mr")))] "TARGET_SSE2" "cvtsi2sd{q}\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") (set_attr "mode" "DF") + (set_attr "athlon_decode" "double,direct") (set_attr "fp_int_src" "true")]) (define_insn "floathixf2" [(set (match_operand:XF 0 "register_operand" "=f,f") (float:XF (match_operand:HI 1 "nonimmediate_operand" "m,r")))] - "!TARGET_64BIT && TARGET_80387" - "@ - fild%z1\t%1 - #" - [(set_attr "type" "fmov,multi") - (set_attr "mode" "XF") - (set_attr "fp_int_src" "true")]) - -(define_insn "floathitf2" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (float:TF (match_operand:HI 1 "nonimmediate_operand" "m,r")))] "TARGET_80387" "@ fild%z1\t%1 @@ -4623,17 +4689,6 @@ (define_insn "floatsixf2" [(set (match_operand:XF 0 "register_operand" "=f,f") (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,r")))] - "!TARGET_64BIT && TARGET_80387" - "@ - fild%z1\t%1 - #" - [(set_attr "type" "fmov,multi") - (set_attr "mode" "XF") - (set_attr "fp_int_src" "true")]) - -(define_insn "floatsitf2" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (float:TF (match_operand:SI 1 "nonimmediate_operand" "m,r")))] "TARGET_80387" "@ fild%z1\t%1 @@ -4645,17 +4700,6 @@ (define_insn "floatdixf2" [(set (match_operand:XF 0 "register_operand" "=f,f") (float:XF (match_operand:DI 1 "nonimmediate_operand" "m,r")))] - "!TARGET_64BIT && TARGET_80387" - "@ - fild%z1\t%1 - #" - [(set_attr "type" "fmov,multi") - (set_attr "mode" "XF") - (set_attr "fp_int_src" "true")]) - -(define_insn "floatditf2" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (float:TF (match_operand:DI 1 "nonimmediate_operand" "m,r")))] "TARGET_80387" "@ fild%z1\t%1 @@ -4677,6 +4721,189 @@ ix86_free_from_memory (GET_MODE (operands[1])); DONE; }) + +(define_expand "floatunssisf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:SI 1 "register_operand" ""))] + "TARGET_SSE && TARGET_SSE_MATH && !TARGET_64BIT" + "x86_emit_floatuns (operands); DONE;") + +(define_expand "floatunsdisf2" + [(use (match_operand:SF 0 "register_operand" "")) + (use (match_operand:DI 1 "register_operand" ""))] + "TARGET_SSE && TARGET_SSE_MATH && TARGET_64BIT" + "x86_emit_floatuns (operands); DONE;") + +(define_expand "floatunsdidf2" + [(use (match_operand:DF 0 "register_operand" "")) + (use (match_operand:DI 1 "register_operand" ""))] + "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_64BIT" + "x86_emit_floatuns (operands); DONE;") + +;; SSE extract/set expanders + +(define_expand "vec_setv2df" + [(match_operand:V2DF 0 "register_operand" "") + (match_operand:DF 1 "register_operand" "") + (match_operand 2 "const_int_operand" "")] + "TARGET_SSE2" +{ + switch (INTVAL (operands[2])) + { + case 0: + emit_insn (gen_sse2_movsd (operands[0], operands[0], + simplify_gen_subreg (V2DFmode, operands[1], + DFmode, 0))); + break; + case 1: + { + rtx op1 = simplify_gen_subreg (V2DFmode, operands[1], DFmode, 0); + + emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], op1)); + } + break; + default: + abort (); + } + DONE; +}) + +(define_expand "vec_extractv2df" + [(match_operand:DF 0 "register_operand" "") + (match_operand:V2DF 1 "register_operand" "") + (match_operand 2 "const_int_operand" "")] + "TARGET_SSE2" +{ + switch (INTVAL (operands[2])) + { + case 0: + emit_move_insn (operands[0], gen_lowpart (DFmode, operands[1])); + break; + case 1: + { + rtx dest = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); + + emit_insn (gen_sse2_unpckhpd (dest, operands[1], operands[1])); + } + break; + default: + abort (); + } + DONE; +}) + +(define_expand "vec_initv2df" + [(match_operand:V2DF 0 "register_operand" "") + (match_operand 1 "" "")] + "TARGET_SSE2" +{ + ix86_expand_vector_init (operands[0], operands[1]); + DONE; +}) + +(define_expand "vec_setv4sf" + [(match_operand:V4SF 0 "register_operand" "") + (match_operand:SF 1 "register_operand" "") + (match_operand 2 "const_int_operand" "")] + "TARGET_SSE" +{ + switch (INTVAL (operands[2])) + { + case 0: + emit_insn (gen_sse_movss (operands[0], operands[0], + simplify_gen_subreg (V4SFmode, operands[1], + SFmode, 0))); + break; + case 1: + { + rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); + rtx tmp = gen_reg_rtx (V4SFmode); + + emit_move_insn (tmp, operands[0]); + emit_insn (gen_sse_unpcklps (operands[0], operands[0], operands[0])); + emit_insn (gen_sse_movss (operands[0], operands[0], op1)); + emit_insn (gen_sse_shufps (operands[0], operands[0], tmp, + GEN_INT (1 + (0<<2) + (2<<4) + (3<<6)))); + } + case 2: + { + rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); + rtx tmp = gen_reg_rtx (V4SFmode); + + emit_move_insn (tmp, operands[0]); + emit_insn (gen_sse_movss (tmp, tmp, op1)); + emit_insn (gen_sse_shufps (operands[0], operands[0], tmp, + GEN_INT (0 + (1<<2) + (0<<4) + (3<<6)))); + } + break; + case 3: + { + rtx op1 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); + rtx tmp = gen_reg_rtx (V4SFmode); + + emit_move_insn (tmp, operands[0]); + emit_insn (gen_sse_movss (tmp, tmp, op1)); + emit_insn (gen_sse_shufps (operands[0], operands[0], tmp, + GEN_INT (0 + (1<<2) + (2<<4) + (0<<6)))); + } + break; + default: + abort (); + } + DONE; +}) + +(define_expand "vec_extractv4sf" + [(match_operand:SF 0 "register_operand" "") + (match_operand:V4SF 1 "register_operand" "") + (match_operand 2 "const_int_operand" "")] + "TARGET_SSE" +{ + switch (INTVAL (operands[2])) + { + case 0: + emit_move_insn (operands[0], gen_lowpart (SFmode, operands[1])); + break; + case 1: + { + rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); + rtx tmp = gen_reg_rtx (V4SFmode); + + emit_move_insn (tmp, operands[1]); + emit_insn (gen_sse_shufps (op0, tmp, tmp, + GEN_INT (1))); + } + case 2: + { + rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); + rtx tmp = gen_reg_rtx (V4SFmode); + + emit_move_insn (tmp, operands[1]); + emit_insn (gen_sse_unpckhps (op0, tmp, tmp)); + } + case 3: + { + rtx op0 = simplify_gen_subreg (V4SFmode, operands[1], SFmode, 0); + rtx tmp = gen_reg_rtx (V4SFmode); + + emit_move_insn (tmp, operands[1]); + emit_insn (gen_sse_shufps (op0, tmp, tmp, + GEN_INT (3))); + } + default: + abort (); + } + DONE; +}) + +(define_expand "vec_initv4sf" + [(match_operand:V4SF 0 "register_operand" "") + (match_operand 1 "" "")] + "TARGET_SSE" +{ + ix86_expand_vector_init (operands[0], operands[1]); + DONE; +}) ;; Add instructions @@ -4719,9 +4946,9 @@ split_di (operands+1, 1, operands+1, operands+4); split_di (operands+2, 1, operands+2, operands+5);") -(define_insn "*adddi3_carry_rex64" +(define_insn "adddi3_carry_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") - (plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0)) + (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") (match_operand:DI 1 "nonimmediate_operand" "%0,0")) (match_operand:DI 2 "x86_64_general_operand" "re,rm"))) (clobber (reg:CC 17))] @@ -4744,9 +4971,35 @@ [(set_attr "type" "alu") (set_attr "mode" "DI")]) -(define_insn "*addsi3_carry" +(define_insn "addqi3_carry" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") + (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") + (match_operand:QI 1 "nonimmediate_operand" "%0,0")) + (match_operand:QI 2 "general_operand" "qi,qm"))) + (clobber (reg:CC 17))] + "ix86_binary_operator_ok (PLUS, QImode, operands)" + "adc{b}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") + (set_attr "mode" "QI") + (set_attr "ppro_uops" "few")]) + +(define_insn "addhi3_carry" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") + (match_operand:HI 1 "nonimmediate_operand" "%0,0")) + (match_operand:HI 2 "general_operand" "ri,rm"))) + (clobber (reg:CC 17))] + "ix86_binary_operator_ok (PLUS, HImode, operands)" + "adc{w}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") + (set_attr "mode" "HI") + (set_attr "ppro_uops" "few")]) + +(define_insn "addsi3_carry" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 1 "nonimmediate_operand" "%0,0")) (match_operand:SI 2 "general_operand" "ri,rm"))) (clobber (reg:CC 17))] @@ -4760,7 +5013,7 @@ (define_insn "*addsi3_carry_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 1 "nonimmediate_operand" "%0")) (match_operand:SI 2 "general_operand" "rim")))) (clobber (reg:CC 17))] @@ -4805,7 +5058,7 @@ (define_insn "*lea_1" [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:SI 1 "address_operand" "p"))] + (match_operand:SI 1 "no_seg_address_operand" "p"))] "!TARGET_64BIT" "lea{l}\t{%a1, %0|%0, %a1}" [(set_attr "type" "lea") @@ -4813,7 +5066,7 @@ (define_insn "*lea_1_rex64" [(set (match_operand:SI 0 "register_operand" "=r") - (subreg:SI (match_operand:DI 1 "address_operand" "p") 0))] + (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))] "TARGET_64BIT" "lea{l}\t{%a1, %0|%0, %a1}" [(set_attr "type" "lea") @@ -4821,7 +5074,8 @@ (define_insn "*lea_1_zext" [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (subreg:SI (match_operand:DI 1 "address_operand" "p") 0)))] + (zero_extend:DI + (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0)))] "TARGET_64BIT" "lea{l}\t{%a1, %k0|%k0, %a1}" [(set_attr "type" "lea") @@ -4829,7 +5083,7 @@ (define_insn "*lea_2_rex64" [(set (match_operand:DI 0 "register_operand" "=r") - (match_operand:DI 1 "address_operand" "p"))] + (match_operand:DI 1 "no_seg_address_operand" "p"))] "TARGET_64BIT" "lea{q}\t{%a1, %0|%0, %a1}" [(set_attr "type" "lea") @@ -5093,7 +5347,7 @@ if (! rtx_equal_p (operands[0], operands[1])) abort (); /* ???? We ought to handle there the 32bit case too - - do we need new constrant? */ + - do we need new constraint? */ /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (GET_CODE (operands[2]) == CONST_INT @@ -5143,7 +5397,7 @@ if (! rtx_equal_p (operands[0], operands[1])) abort (); /* ???? We ought to handle there the 32bit case too - - do we need new constrant? */ + - do we need new constraint? */ /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. Exceptions: -128 encodes smaller than 128, so swap sign and op. */ if (GET_CODE (operands[2]) == CONST_INT @@ -5403,7 +5657,7 @@ (plus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonmemory_operand" "")))) (clobber (reg:CC 17))] - "reload_completed + "TARGET_64BIT && reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" [(set (match_dup 0) (zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))] @@ -5593,7 +5847,7 @@ (const_string "alu"))) (set_attr "mode" "SI")]) -; For comparisons agains 1, -1 and 128, we may generate better code +; For comparisons against 1, -1 and 128, we may generate better code ; by converting cmp to add, inc or dec as done by peephole2. This pattern ; is matched then. We can't accept general immediate, because for ; case of overflows, the result is messed up. @@ -6053,7 +6307,7 @@ if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0) { - operands[2] = GEN_INT (-INTVAL (operands[2])); + operands[1] = GEN_INT (-INTVAL (operands[1])); return "sub{b}\t{%1, %0|%0, %1}"; } return "add{b}\t{%1, %0|%0, %1}"; @@ -6311,13 +6565,6 @@ [(set (match_operand:XF 0 "register_operand" "") (plus:XF (match_operand:XF 1 "register_operand" "") (match_operand:XF 2 "register_operand" "")))] - "!TARGET_64BIT && TARGET_80387" - "") - -(define_expand "addtf3" - [(set (match_operand:TF 0 "register_operand" "") - (plus:TF (match_operand:TF 1 "register_operand" "") - (match_operand:TF 2 "register_operand" "")))] "TARGET_80387" "") @@ -6375,7 +6622,7 @@ (define_insn "subdi3_carry_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r") (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0") - (plus:DI (ltu:DI (reg:CC 17) (const_int 0)) + (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "") (match_operand:DI 2 "x86_64_general_operand" "re,rm")))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" @@ -6421,11 +6668,36 @@ [(set_attr "type" "alu") (set_attr "mode" "DI")]) +(define_insn "subqi3_carry" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") + (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") + (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "") + (match_operand:QI 2 "general_operand" "qi,qm")))) + (clobber (reg:CC 17))] + "ix86_binary_operator_ok (MINUS, QImode, operands)" + "sbb{b}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") + (set_attr "ppro_uops" "few") + (set_attr "mode" "QI")]) + +(define_insn "subhi3_carry" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") + (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "") + (match_operand:HI 2 "general_operand" "ri,rm")))) + (clobber (reg:CC 17))] + "ix86_binary_operator_ok (MINUS, HImode, operands)" + "sbb{w}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "pent_pair" "pu") + (set_attr "ppro_uops" "few") + (set_attr "mode" "HI")]) (define_insn "subsi3_carry" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 2 "general_operand" "ri,rm")))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (MINUS, SImode, operands)" @@ -6439,7 +6711,7 @@ [(set (match_operand:DI 0 "register_operand" "=rm,r") (zero_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "0,0") - (plus:SI (ltu:SI (reg:CC 17) (const_int 0)) + (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "") (match_operand:SI 2 "general_operand" "ri,rm"))))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" @@ -6522,7 +6794,7 @@ (define_insn "*subsi_3_zext" [(set (reg 17) - (compare (match_operand:SI 1 "nonimmediate_operand" "0") + (compare (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "rim"))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI @@ -6639,13 +6911,6 @@ [(set (match_operand:XF 0 "register_operand" "") (minus:XF (match_operand:XF 1 "register_operand" "") (match_operand:XF 2 "register_operand" "")))] - "!TARGET_64BIT && TARGET_80387" - "") - -(define_expand "subtf3" - [(set (match_operand:TF 0 "register_operand" "") - (minus:TF (match_operand:TF 1 "register_operand" "") - (match_operand:TF 2 "register_operand" "")))] "TARGET_80387" "") @@ -6675,7 +6940,7 @@ (define_insn "*muldi3_1_rex64" [(set (match_operand:DI 0 "register_operand" "=r,r,r") - (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,0,0") + (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:DI 2 "x86_64_general_operand" "K,e,mr"))) (clobber (reg:CC 17))] "TARGET_64BIT @@ -6686,6 +6951,15 @@ imul{q}\t{%2, %0|%0, %2}" [(set_attr "type" "imul") (set_attr "prefix_0f" "0,0,1") + (set (attr "athlon_decode") + (cond [(eq_attr "cpu" "athlon") + (const_string "vector") + (eq_attr "alternative" "1") + (const_string "vector") + (and (eq_attr "alternative" "2") + (match_operand 1 "memory_operand" "")) + (const_string "vector")] + (const_string "direct"))) (set_attr "mode" "DI")]) (define_expand "mulsi3" @@ -6698,56 +6972,50 @@ (define_insn "*mulsi3_1" [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,0,0") + (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:SI 2 "general_operand" "K,i,mr"))) (clobber (reg:CC 17))] "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM" - ; For the {r,0,i} alternative (i.e., register <- register * immediate), - ; there are two ways of writing the exact same machine instruction - ; in assembly language. One, for example, is: - ; - ; imul $12, %eax - ; - ; while the other is: - ; - ; imul $12, %eax, %eax - ; - ; The first is simply short-hand for the latter. But, some assemblers, - ; like the SCO OSR5 COFF assembler, don't handle the first form. "@ imul{l}\t{%2, %1, %0|%0, %1, %2} imul{l}\t{%2, %1, %0|%0, %1, %2} imul{l}\t{%2, %0|%0, %2}" [(set_attr "type" "imul") (set_attr "prefix_0f" "0,0,1") + (set (attr "athlon_decode") + (cond [(eq_attr "cpu" "athlon") + (const_string "vector") + (eq_attr "alternative" "1") + (const_string "vector") + (and (eq_attr "alternative" "2") + (match_operand 1 "memory_operand" "")) + (const_string "vector")] + (const_string "direct"))) (set_attr "mode" "SI")]) (define_insn "*mulsi3_1_zext" [(set (match_operand:DI 0 "register_operand" "=r,r,r") (zero_extend:DI - (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,0,0") + (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:SI 2 "general_operand" "K,i,mr")))) (clobber (reg:CC 17))] "TARGET_64BIT && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" - ; For the {r,0,i} alternative (i.e., register <- register * immediate), - ; there are two ways of writing the exact same machine instruction - ; in assembly language. One, for example, is: - ; - ; imul $12, %eax - ; - ; while the other is: - ; - ; imul $12, %eax, %eax - ; - ; The first is simply short-hand for the latter. But, some assemblers, - ; like the SCO OSR5 COFF assembler, don't handle the first form. "@ imul{l}\t{%2, %1, %k0|%k0, %1, %2} imul{l}\t{%2, %1, %k0|%k0, %1, %2} imul{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "imul") (set_attr "prefix_0f" "0,0,1") + (set (attr "athlon_decode") + (cond [(eq_attr "cpu" "athlon") + (const_string "vector") + (eq_attr "alternative" "1") + (const_string "vector") + (and (eq_attr "alternative" "2") + (match_operand 1 "memory_operand" "")) + (const_string "vector")] + (const_string "direct"))) (set_attr "mode" "SI")]) (define_expand "mulhi3" @@ -6760,18 +7028,22 @@ (define_insn "*mulhi3_1" [(set (match_operand:HI 0 "register_operand" "=r,r,r") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,0,0") + (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%rm,rm,0") (match_operand:HI 2 "general_operand" "K,i,mr"))) (clobber (reg:CC 17))] "GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM" - ; %%% There was a note about "Assembler has weird restrictions", - ; concerning alternative 1 when op1 == op0. True? "@ imul{w}\t{%2, %1, %0|%0, %1, %2} imul{w}\t{%2, %1, %0|%0, %1, %2} imul{w}\t{%2, %0|%0, %2}" [(set_attr "type" "imul") (set_attr "prefix_0f" "0,0,1") + (set (attr "athlon_decode") + (cond [(eq_attr "cpu" "athlon") + (const_string "vector") + (eq_attr "alternative" "1,2") + (const_string "vector")] + (const_string "direct"))) (set_attr "mode" "HI")]) (define_expand "mulqi3" @@ -6792,6 +7064,10 @@ "mul{b}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "direct"))) (set_attr "mode" "QI")]) (define_expand "umulqihi3" @@ -6814,6 +7090,10 @@ "mul{b}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "direct"))) (set_attr "mode" "QI")]) (define_expand "mulqihi3" @@ -6834,6 +7114,10 @@ "imul{b}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "direct"))) (set_attr "mode" "QI")]) (define_expand "umulditi3" @@ -6857,6 +7141,10 @@ [(set_attr "type" "imul") (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "DI")]) ;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers @@ -6881,6 +7169,10 @@ [(set_attr "type" "imul") (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "SI")]) (define_expand "mulditi3" @@ -6903,6 +7195,10 @@ "imul{q}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "DI")]) (define_expand "mulsidi3" @@ -6925,6 +7221,10 @@ "imul{l}\t%2" [(set_attr "type" "imul") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "SI")]) (define_expand "umuldi3_highpart" @@ -6958,6 +7258,10 @@ [(set_attr "type" "imul") (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "DI")]) (define_expand "umulsi3_highpart" @@ -6990,6 +7294,10 @@ [(set_attr "type" "imul") (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "SI")]) (define_insn "*umulsi3_highpart_zext" @@ -7009,6 +7317,10 @@ [(set_attr "type" "imul") (set_attr "ppro_uops" "few") (set_attr "length_immediate" "0") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "SI")]) (define_expand "smuldi3_highpart" @@ -7041,6 +7353,10 @@ "imul{q}\t%2" [(set_attr "type" "imul") (set_attr "ppro_uops" "few") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "DI")]) (define_expand "smulsi3_highpart" @@ -7072,6 +7388,10 @@ "imul{l}\t%2" [(set_attr "type" "imul") (set_attr "ppro_uops" "few") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "SI")]) (define_insn "*smulsi3_highpart_zext" @@ -7090,6 +7410,10 @@ "imul{l}\t%2" [(set_attr "type" "imul") (set_attr "ppro_uops" "few") + (set (attr "athlon_decode") + (if_then_else (eq_attr "cpu" "athlon") + (const_string "vector") + (const_string "double"))) (set_attr "mode" "SI")]) ;; The patterns that match these are at the end of this file. @@ -7098,13 +7422,6 @@ [(set (match_operand:XF 0 "register_operand" "") (mult:XF (match_operand:XF 1 "register_operand" "") (match_operand:XF 2 "register_operand" "")))] - "!TARGET_64BIT && TARGET_80387" - "") - -(define_expand "multf3" - [(set (match_operand:TF 0 "register_operand" "") - (mult:TF (match_operand:TF 1 "register_operand" "") - (match_operand:TF 2 "register_operand" "")))] "TARGET_80387" "") @@ -7152,13 +7469,6 @@ [(set (match_operand:XF 0 "register_operand" "") (div:XF (match_operand:XF 1 "register_operand" "") (match_operand:XF 2 "register_operand" "")))] - "!TARGET_64BIT && TARGET_80387" - "") - -(define_expand "divtf3" - [(set (match_operand:TF 0 "register_operand" "") - (div:TF (match_operand:TF 1 "register_operand" "") - (match_operand:TF 2 "register_operand" "")))] "TARGET_80387" "") @@ -7189,7 +7499,7 @@ "") ;; Allow to come the parameter in eax or edx to avoid extra moves. -;; Penalize eax case sligthly because it results in worse scheduling +;; Penalize eax case slightly because it results in worse scheduling ;; of code. (define_insn "*divmoddi4_nocltd_rex64" [(set (match_operand:DI 0 "register_operand" "=&a,?a") @@ -7274,7 +7584,7 @@ "") ;; Allow to come the parameter in eax or edx to avoid extra moves. -;; Penalize eax case sligthly because it results in worse scheduling +;; Penalize eax case slightly because it results in worse scheduling ;; of code. (define_insn "*divmodsi4_nocltd" [(set (match_operand:SI 0 "register_operand" "=&a,?a") @@ -7502,10 +7812,11 @@ (define_insn "*testdi_1_rex64" [(set (reg 17) (compare - (and:DI (match_operand:DI 0 "nonimmediate_operand" "%*a,r,*a,r,rm") - (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,Z,e,e,re")) + (and:DI (match_operand:DI 0 "nonimmediate_operand" "%!*a,r,!*a,r,rm") + (match_operand:DI 1 "x86_64_szext_general_operand" "Z,Z,e,e,re")) (const_int 0)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" + "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "@ test{l}\t{%k1, %k0|%k0, %k1} test{l}\t{%k1, %k0|%k0, %k1} @@ -7520,10 +7831,11 @@ (define_insn "testsi_1" [(set (reg 17) (compare - (and:SI (match_operand:SI 0 "nonimmediate_operand" "%*a,r,rm") - (match_operand:SI 1 "nonmemory_operand" "in,in,rin")) + (and:SI (match_operand:SI 0 "nonimmediate_operand" "%!*a,r,rm") + (match_operand:SI 1 "general_operand" "in,in,rin")) (const_int 0)))] - "ix86_match_ccmode (insn, CCNOmode)" + "ix86_match_ccmode (insn, CCNOmode) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "test{l}\t{%1, %0|%0, %1}" [(set_attr "type" "test") (set_attr "modrm" "0,1,1") @@ -7541,10 +7853,11 @@ (define_insn "*testhi_1" [(set (reg 17) - (compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%*a,r,rm") - (match_operand:HI 1 "nonmemory_operand" "n,n,rn")) + (compare (and:HI (match_operand:HI 0 "nonimmediate_operand" "%!*a,r,rm") + (match_operand:HI 1 "general_operand" "n,n,rn")) (const_int 0)))] - "ix86_match_ccmode (insn, CCNOmode)" + "ix86_match_ccmode (insn, CCNOmode) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "test{w}\t{%1, %0|%0, %1}" [(set_attr "type" "test") (set_attr "modrm" "0,1,1") @@ -7561,10 +7874,11 @@ (define_insn "*testqi_1" [(set (reg 17) - (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%*a,q,qm,r") - (match_operand:QI 1 "nonmemory_operand" "n,n,qn,n")) + (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%!*a,q,qm,r") + (match_operand:QI 1 "general_operand" "n,n,qn,n")) (const_int 0)))] - "ix86_match_ccmode (insn, CCNOmode)" + "ix86_match_ccmode (insn, CCNOmode) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { if (which_alternative == 3) { @@ -7619,9 +7933,10 @@ (const_int 8) (const_int 8)) (zero_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "Qm"))) + (match_operand:QI 1 "general_operand" "Qm"))) (const_int 0)))] - "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)" + "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" "test{b}\t{%1, %h0|%h0, %1}" [(set_attr "type" "test") (set_attr "mode" "QI")]) @@ -7747,7 +8062,7 @@ ;; Convert HImode/SImode test instructions with immediate to QImode ones. ;; i386 does not allow to encode test with 8bit sign extended immediate, so ;; this is relatively important trick. -;; Do the converison only post-reload to avoid limiting of the register class +;; Do the conversion only post-reload to avoid limiting of the register class ;; to QI regs. (define_split [(set (reg 17) @@ -8211,7 +8526,7 @@ ;; Convert wide AND instructions with immediate operand to shorter QImode ;; equivalents when possible. -;; Don't do the splitting with memory operands, since it intoduces risc +;; Don't do the splitting with memory operands, since it introduces risk ;; of memory mismatch stalls. We may want to do the splitting for optimizing ;; for size, but that can (should?) be handled by generic code instead. (define_split @@ -9265,12 +9580,15 @@ in register. */ rtx reg = gen_reg_rtx (SFmode); rtx dest = operands[0]; + rtx imm = gen_lowpart (SFmode, gen_int_mode (0x80000000, SImode)); operands[1] = force_reg (SFmode, operands[1]); operands[0] = force_reg (SFmode, operands[0]); - emit_move_insn (reg, - gen_lowpart (SFmode, - gen_int_mode (0x80000000, SImode))); + reg = force_reg (V4SFmode, + gen_rtx_CONST_VECTOR (V4SFmode, + gen_rtvec (4, imm, CONST0_RTX (SFmode), + CONST0_RTX (SFmode), + CONST0_RTX (SFmode)))); emit_insn (gen_negsf2_ifs (operands[0], operands[1], reg)); if (dest != operands[0]) emit_move_insn (dest, operands[0]); @@ -9289,7 +9607,7 @@ (define_insn "negsf2_ifs" [(set (match_operand:SF 0 "nonimmediate_operand" "=x#fr,x#fr,f#xr,rm#xf") (neg:SF (match_operand:SF 1 "nonimmediate_operand" "0,x#fr,0,0"))) - (use (match_operand:SF 2 "nonmemory_operand" "x,0#x,*g#x,*g#x")) + (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,xm*r,xm*r")) (clobber (reg:CC 17))] "TARGET_SSE && (reload_in_progress || reload_completed @@ -9310,7 +9628,7 @@ (define_split [(set (match_operand:SF 0 "register_operand" "") (neg:SF (match_operand:SF 1 "register_operand" ""))) - (use (match_operand:SF 2 "" "")) + (use (match_operand:V4SF 2 "" "")) (clobber (reg:CC 17))] "reload_completed && !SSE_REG_P (operands[0])" [(parallel [(set (match_dup 0) @@ -9320,13 +9638,15 @@ (define_split [(set (match_operand:SF 0 "register_operand" "") (neg:SF (match_operand:SF 1 "register_operand" ""))) - (use (match_operand:SF 2 "register_operand" "")) + (use (match_operand:V4SF 2 "nonimmediate_operand" "")) (clobber (reg:CC 17))] "reload_completed && SSE_REG_P (operands[0])" [(set (subreg:TI (match_dup 0) 0) - (xor:TI (subreg:TI (match_dup 1) 0) - (subreg:TI (match_dup 2) 0)))] + (xor:TI (match_dup 1) + (match_dup 2)))] { + operands[1] = simplify_gen_subreg (TImode, operands[1], SFmode, 0); + operands[2] = simplify_gen_subreg (TImode, operands[2], V4SFmode, 0); if (operands_match_p (operands[0], operands[2])) { rtx tmp; @@ -9365,7 +9685,7 @@ [(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1))) (clobber (reg:CC 17))])] "operands[1] = gen_int_mode (0x80000000, SImode); - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));") + operands[0] = gen_lowpart (SImode, operands[0]);") (define_split [(set (match_operand 0 "memory_operand" "") @@ -9377,8 +9697,7 @@ { int size = GET_MODE_SIZE (GET_MODE (operands[1])); - /* XFmode's size is 12, TFmode 16, but only 10 bytes are used. */ - if (size >= 12) + if (GET_MODE (operands[1]) == XFmode) size = 10; operands[0] = adjust_address (operands[0], QImode, size - 1); operands[1] = gen_int_mode (0x80, QImode); @@ -9399,7 +9718,7 @@ { /* Using SSE is tricky, since we need bitwise negation of -0 in register. */ - rtx reg = gen_reg_rtx (DFmode); + rtx reg; #if HOST_BITS_PER_WIDE_INT >= 64 rtx imm = gen_int_mode (((HOST_WIDE_INT)1) << 63, DImode); #else @@ -9409,7 +9728,10 @@ operands[1] = force_reg (DFmode, operands[1]); operands[0] = force_reg (DFmode, operands[0]); - emit_move_insn (reg, gen_lowpart (DFmode, imm)); + imm = gen_lowpart (DFmode, imm); + reg = force_reg (V2DFmode, + gen_rtx_CONST_VECTOR (V2DFmode, + gen_rtvec (2, imm, CONST0_RTX (DFmode)))); emit_insn (gen_negdf2_ifs (operands[0], operands[1], reg)); if (dest != operands[0]) emit_move_insn (dest, operands[0]); @@ -9428,7 +9750,7 @@ (define_insn "negdf2_ifs" [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,f#Yr,rm#Yf") (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0,0"))) - (use (match_operand:DF 2 "nonmemory_operand" "Y,0,*g#Y,*g#Y")) + (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r,Ym*r")) (clobber (reg:CC 17))] "!TARGET_64BIT && TARGET_SSE2 && (reload_in_progress || reload_completed @@ -9438,8 +9760,8 @@ (define_insn "*negdf2_ifs_rex64" [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#f,Y#f,fm#Y") - (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#f,0"))) - (use (match_operand:DF 2 "general_operand" "Y,0,*g#Y*r")) + (neg:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0"))) + (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r")) (clobber (reg:CC 17))] "TARGET_64BIT && TARGET_SSE2 && (reload_in_progress || reload_completed @@ -9450,7 +9772,7 @@ (define_split [(set (match_operand:DF 0 "memory_operand" "") (neg:DF (match_operand:DF 1 "memory_operand" ""))) - (use (match_operand:DF 2 "" "")) + (use (match_operand:V2DF 2 "" "")) (clobber (reg:CC 17))] "" [(parallel [(set (match_dup 0) @@ -9460,7 +9782,7 @@ (define_split [(set (match_operand:DF 0 "register_operand" "") (neg:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:DF 2 "" "")) + (use (match_operand:V2DF 2 "" "")) (clobber (reg:CC 17))] "reload_completed && !SSE_REG_P (operands[0]) && (!TARGET_64BIT || FP_REG_P (operands[0]))" @@ -9471,7 +9793,7 @@ (define_split [(set (match_operand:DF 0 "register_operand" "") (neg:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:DF 2 "" "")) + (use (match_operand:V2DF 2 "" "")) (clobber (reg:CC 17))] "TARGET_64BIT && reload_completed && GENERAL_REG_P (operands[0])" [(parallel [(set (match_dup 0) @@ -9484,13 +9806,19 @@ (define_split [(set (match_operand:DF 0 "register_operand" "") (neg:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:DF 2 "register_operand" "")) + (use (match_operand:V2DF 2 "nonimmediate_operand" "")) (clobber (reg:CC 17))] "reload_completed && SSE_REG_P (operands[0])" [(set (subreg:TI (match_dup 0) 0) - (xor:TI (subreg:TI (match_dup 1) 0) - (subreg:TI (match_dup 2) 0)))] + (xor:TI (match_dup 1) + (match_dup 2)))] { + operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); + operands[1] = simplify_gen_subreg (TImode, operands[1], DFmode, 0); + operands[2] = simplify_gen_subreg (TImode, operands[2], V2DFmode, 0); + /* Avoid possible reformatting on the operands. */ + if (TARGET_SSE_PARTIAL_REGS && !optimize_size) + emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], operands[0])); if (operands_match_p (operands[0], operands[2])) { rtx tmp; @@ -9546,15 +9874,8 @@ [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "") (neg:XF (match_operand:XF 1 "nonimmediate_operand" ""))) (clobber (reg:CC 17))])] - "!TARGET_64BIT && TARGET_80387" - "ix86_expand_unary_operator (NEG, XFmode, operands); DONE;") - -(define_expand "negtf2" - [(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "") - (neg:TF (match_operand:TF 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] "TARGET_80387" - "ix86_expand_unary_operator (NEG, TFmode, operands); DONE;") + "ix86_expand_unary_operator (NEG, XFmode, operands); DONE;") ;; Keep 'f' and 'r' in separate alternatives to avoid reload problems ;; because of secondary memory needed to reload from class FLOAT_INT_REGS @@ -9563,7 +9884,7 @@ [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,rm#f") (neg:XF (match_operand:XF 1 "nonimmediate_operand" "0,0"))) (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_80387 + "TARGET_80387 && ix86_unary_operator_ok (NEG, XFmode, operands)" "#") @@ -9587,37 +9908,7 @@ operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]) + (TARGET_64BIT ? 1 : 2));") -;; Keep 'f' and 'r' in separate alternatives to avoid reload problems -;; because of secondary memory needed to reload from class FLOAT_INT_REGS -;; to itself. -(define_insn "*negtf2_if" - [(set (match_operand:TF 0 "nonimmediate_operand" "=f#r,rm#f") - (neg:TF (match_operand:TF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "TARGET_80387 && ix86_unary_operator_ok (NEG, TFmode, operands)" - "#") - -(define_split - [(set (match_operand:TF 0 "fp_register_operand" "") - (neg:TF (match_operand:TF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (neg:TF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:TF 0 "register_and_not_fp_reg_operand" "") - (neg:TF (match_operand:TF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(parallel [(set (match_dup 0) (xor:SI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] - "operands[1] = GEN_INT (0x8000); - operands[0] = gen_rtx_REG (SImode, - true_regnum (operands[0]) + (TARGET_64BIT ? 1 : 2));") - -;; Conditionize these after reload. If they matches before reload, we +;; Conditionalize these after reload. If they matches before reload, we ;; lose the clobber and ability to use integer instructions. (define_insn "*negsf2_1" @@ -9651,7 +9942,7 @@ (define_insn "*negxf2_1" [(set (match_operand:XF 0 "register_operand" "=f") (neg:XF (match_operand:XF 1 "register_operand" "0")))] - "!TARGET_64BIT && TARGET_80387 && reload_completed" + "TARGET_80387 && reload_completed" "fchs" [(set_attr "type" "fsgn") (set_attr "mode" "XF") @@ -9661,7 +9952,7 @@ [(set (match_operand:XF 0 "register_operand" "=f") (neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] - "!TARGET_64BIT && TARGET_80387" + "TARGET_80387" "fchs" [(set_attr "type" "fsgn") (set_attr "mode" "XF") @@ -9671,35 +9962,6 @@ [(set (match_operand:XF 0 "register_operand" "=f") (neg:XF (float_extend:XF (match_operand:SF 1 "register_operand" "0"))))] - "!TARGET_64BIT && TARGET_80387" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF") - (set_attr "ppro_uops" "few")]) - -(define_insn "*negtf2_1" - [(set (match_operand:TF 0 "register_operand" "=f") - (neg:TF (match_operand:TF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF") - (set_attr "ppro_uops" "few")]) - -(define_insn "*negextenddftf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (neg:TF (float_extend:TF - (match_operand:DF 1 "register_operand" "0"))))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF") - (set_attr "ppro_uops" "few")]) - -(define_insn "*negextendsftf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (neg:TF (float_extend:TF - (match_operand:SF 1 "register_operand" "0"))))] "TARGET_80387" "fchs" [(set_attr "type" "fsgn") @@ -9723,14 +9985,18 @@ { /* Using SSE is tricky, since we need bitwise negation of -0 in register. */ - rtx reg = gen_reg_rtx (SFmode); + rtx reg = gen_reg_rtx (V4SFmode); rtx dest = operands[0]; + rtx imm; operands[1] = force_reg (SFmode, operands[1]); operands[0] = force_reg (SFmode, operands[0]); - emit_move_insn (reg, - gen_lowpart (SFmode, - gen_int_mode (0x80000000, SImode))); + imm = gen_lowpart (SFmode, gen_int_mode(~0x80000000, SImode)); + reg = force_reg (V4SFmode, + gen_rtx_CONST_VECTOR (V4SFmode, + gen_rtvec (4, imm, CONST0_RTX (SFmode), + CONST0_RTX (SFmode), + CONST0_RTX (SFmode)))); emit_insn (gen_abssf2_ifs (operands[0], operands[1], reg)); if (dest != operands[0]) emit_move_insn (dest, operands[0]); @@ -9747,20 +10013,20 @@ "#") (define_insn "abssf2_ifs" - [(set (match_operand:SF 0 "nonimmediate_operand" "=x#fr,f#xr,rm#xf") - (abs:SF (match_operand:SF 1 "nonimmediate_operand" "x,0,0"))) - (use (match_operand:SF 2 "nonmemory_operand" "*0#x,*g#x,*g#x")) + [(set (match_operand:SF 0 "nonimmediate_operand" "=x#fr,x#fr,f#xr,rm#xf") + (abs:SF (match_operand:SF 1 "nonimmediate_operand" "0,x#fr,0,0"))) + (use (match_operand:V4SF 2 "nonimmediate_operand" "xm,0,xm*r,xm*r")) (clobber (reg:CC 17))] "TARGET_SSE && (reload_in_progress || reload_completed || (register_operand (operands[0], VOIDmode) - && register_operand (operands[1], VOIDmode)))" + && register_operand (operands[1], VOIDmode)))" "#") (define_split [(set (match_operand:SF 0 "memory_operand" "") (abs:SF (match_operand:SF 1 "memory_operand" ""))) - (use (match_operand:SF 2 "" "")) + (use (match_operand:V4SF 2 "" "")) (clobber (reg:CC 17))] "" [(parallel [(set (match_dup 0) @@ -9770,7 +10036,7 @@ (define_split [(set (match_operand:SF 0 "register_operand" "") (abs:SF (match_operand:SF 1 "register_operand" ""))) - (use (match_operand:SF 2 "" "")) + (use (match_operand:V4SF 2 "" "")) (clobber (reg:CC 17))] "reload_completed && !SSE_REG_P (operands[0])" [(parallel [(set (match_dup 0) @@ -9780,12 +10046,23 @@ (define_split [(set (match_operand:SF 0 "register_operand" "") (abs:SF (match_operand:SF 1 "register_operand" ""))) - (use (match_operand:SF 2 "register_operand" "")) + (use (match_operand:V4SF 2 "nonimmediate_operand" "")) (clobber (reg:CC 17))] "reload_completed && SSE_REG_P (operands[0])" [(set (subreg:TI (match_dup 0) 0) - (and:TI (not:TI (subreg:TI (match_dup 2) 0)) - (subreg:TI (match_dup 1) 0)))]) + (and:TI (match_dup 1) + (match_dup 2)))] +{ + operands[1] = simplify_gen_subreg (TImode, operands[1], SFmode, 0); + operands[2] = simplify_gen_subreg (TImode, operands[2], V4SFmode, 0); + if (operands_match_p (operands[0], operands[2])) + { + rtx tmp; + tmp = operands[1]; + operands[1] = operands[2]; + operands[2] = tmp; + } +}) ;; Keep 'f' and 'r' in separate alternatives to avoid reload problems ;; because of secondary memory needed to reload from class FLOAT_INT_REGS @@ -9801,7 +10078,7 @@ [(set (match_operand:SF 0 "fp_register_operand" "") (abs:SF (match_operand:SF 1 "register_operand" ""))) (clobber (reg:CC 17))] - "TARGET_80387" + "TARGET_80387 && reload_completed" [(set (match_dup 0) (abs:SF (match_dup 1)))] "") @@ -9814,7 +10091,7 @@ [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1))) (clobber (reg:CC 17))])] "operands[1] = gen_int_mode (~0x80000000, SImode); - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));") + operands[0] = gen_lowpart (SImode, operands[0]);") (define_split [(set (match_operand 0 "memory_operand" "") @@ -9826,8 +10103,7 @@ { int size = GET_MODE_SIZE (GET_MODE (operands[1])); - /* XFmode's size is 12, TFmode 16, but only 10 bytes are used. */ - if (size >= 12) + if (GET_MODE (operands[1]) == XFmode) size = 10; operands[0] = adjust_address (operands[0], QImode, size - 1); operands[1] = gen_int_mode (~0x80, QImode); @@ -9848,17 +10124,22 @@ { /* Using SSE is tricky, since we need bitwise negation of -0 in register. */ - rtx reg = gen_reg_rtx (DFmode); + rtx reg = gen_reg_rtx (V2DFmode); #if HOST_BITS_PER_WIDE_INT >= 64 - rtx imm = gen_int_mode (((HOST_WIDE_INT)1) << 63, DImode); + rtx imm = gen_int_mode (~(((HOST_WIDE_INT)1) << 63), DImode); #else - rtx imm = immed_double_const (0, 0x80000000, DImode); + rtx imm = immed_double_const (~0, ~0x80000000, DImode); #endif rtx dest = operands[0]; operands[1] = force_reg (DFmode, operands[1]); operands[0] = force_reg (DFmode, operands[0]); - emit_move_insn (reg, gen_lowpart (DFmode, imm)); + + /* Produce LONG_DOUBLE with the proper immediate argument. */ + imm = gen_lowpart (DFmode, imm); + reg = force_reg (V2DFmode, + gen_rtx_CONST_VECTOR (V2DFmode, + gen_rtvec (2, imm, CONST0_RTX (DFmode)))); emit_insn (gen_absdf2_ifs (operands[0], operands[1], reg)); if (dest != operands[0]) emit_move_insn (dest, operands[0]); @@ -9875,9 +10156,9 @@ "#") (define_insn "absdf2_ifs" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,mf#Yr,mr#Yf") - (abs:DF (match_operand:DF 1 "nonimmediate_operand" "Y,0,0"))) - (use (match_operand:DF 2 "nonmemory_operand" "*0#Y,*g#Y,*g#Y")) + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,mf#Yr,mr#Yf") + (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0,0"))) + (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r,Ym*r")) (clobber (reg:CC 17))] "!TARGET_64BIT && TARGET_SSE2 && (reload_in_progress || reload_completed @@ -9886,9 +10167,9 @@ "#") (define_insn "*absdf2_ifs_rex64" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,mf#Yr") - (abs:DF (match_operand:DF 1 "nonimmediate_operand" "Y,0"))) - (use (match_operand:DF 2 "nonmemory_operand" "*0#Y,*g#Y")) + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#fr,Y#fr,mf#Yr") + (abs:DF (match_operand:DF 1 "nonimmediate_operand" "0,Y#fr,0"))) + (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,Ym*r")) (clobber (reg:CC 17))] "TARGET_64BIT && TARGET_SSE2 && (reload_in_progress || reload_completed @@ -9899,7 +10180,7 @@ (define_split [(set (match_operand:DF 0 "memory_operand" "") (abs:DF (match_operand:DF 1 "memory_operand" ""))) - (use (match_operand:DF 2 "" "")) + (use (match_operand:V2DF 2 "" "")) (clobber (reg:CC 17))] "" [(parallel [(set (match_dup 0) @@ -9909,7 +10190,7 @@ (define_split [(set (match_operand:DF 0 "register_operand" "") (abs:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:DF 2 "" "")) + (use (match_operand:V2DF 2 "" "")) (clobber (reg:CC 17))] "reload_completed && !SSE_REG_P (operands[0])" [(parallel [(set (match_dup 0) @@ -9919,12 +10200,27 @@ (define_split [(set (match_operand:DF 0 "register_operand" "") (abs:DF (match_operand:DF 1 "register_operand" ""))) - (use (match_operand:DF 2 "register_operand" "")) + (use (match_operand:V2DF 2 "nonimmediate_operand" "")) (clobber (reg:CC 17))] "reload_completed && SSE_REG_P (operands[0])" [(set (subreg:TI (match_dup 0) 0) - (and:TI (not:TI (subreg:TI (match_dup 2) 0)) - (subreg:TI (match_dup 1) 0)))]) + (and:TI (match_dup 1) + (match_dup 2)))] +{ + operands[0] = simplify_gen_subreg (V2DFmode, operands[0], DFmode, 0); + operands[1] = simplify_gen_subreg (TImode, operands[1], DFmode, 0); + operands[2] = simplify_gen_subreg (TImode, operands[2], V2DFmode, 0); + /* Avoid possible reformatting on the operands. */ + if (TARGET_SSE_PARTIAL_REGS && !optimize_size) + emit_insn (gen_sse2_unpcklpd (operands[0], operands[0], operands[0])); + if (operands_match_p (operands[0], operands[2])) + { + rtx tmp; + tmp = operands[1]; + operands[1] = operands[2]; + operands[2] = tmp; + } +}) ;; Keep 'f' and 'r' in separate alternatives to avoid reload problems @@ -9973,15 +10269,8 @@ [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "") (neg:XF (match_operand:XF 1 "nonimmediate_operand" ""))) (clobber (reg:CC 17))])] - "!TARGET_64BIT && TARGET_80387" - "ix86_expand_unary_operator (ABS, XFmode, operands); DONE;") - -(define_expand "abstf2" - [(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "") - (neg:TF (match_operand:TF 1 "nonimmediate_operand" ""))) - (clobber (reg:CC 17))])] "TARGET_80387" - "ix86_expand_unary_operator (ABS, TFmode, operands); DONE;") + "ix86_expand_unary_operator (ABS, XFmode, operands); DONE;") ;; Keep 'f' and 'r' in separate alternatives to avoid reload problems ;; because of secondary memory needed to reload from class FLOAT_INT_REGS @@ -9990,7 +10279,7 @@ [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,rm#f") (abs:XF (match_operand:XF 1 "nonimmediate_operand" "0,0"))) (clobber (reg:CC 17))] - "!TARGET_64BIT && TARGET_80387 + "TARGET_80387 && ix86_unary_operator_ok (ABS, XFmode, operands)" "#") @@ -10014,33 +10303,6 @@ operands[0] = gen_rtx_REG (SImode, true_regnum (operands[0]) + (TARGET_64BIT ? 1 : 2));") -(define_insn "*abstf2_if" - [(set (match_operand:TF 0 "nonimmediate_operand" "=f#r,rm#f") - (abs:TF (match_operand:TF 1 "nonimmediate_operand" "0,0"))) - (clobber (reg:CC 17))] - "TARGET_80387 && ix86_unary_operator_ok (ABS, TFmode, operands)" - "#") - -(define_split - [(set (match_operand:TF 0 "fp_register_operand" "") - (abs:TF (match_operand:TF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (abs:TF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:TF 0 "register_and_not_any_fp_reg_operand" "") - (abs:TF (match_operand:TF 1 "register_operand" ""))) - (clobber (reg:CC 17))] - "TARGET_80387 && reload_completed" - [(parallel [(set (match_dup 0) (and:SI (match_dup 0) (match_dup 1))) - (clobber (reg:CC 17))])] - "operands[1] = GEN_INT (~0x8000); - operands[0] = gen_rtx_REG (SImode, - true_regnum (operands[0]) + (TARGET_64BIT ? 1 : 2));") - (define_insn "*abssf2_1" [(set (match_operand:SF 0 "register_operand" "=f") (abs:SF (match_operand:SF 1 "register_operand" "0")))] @@ -10069,7 +10331,7 @@ (define_insn "*absxf2_1" [(set (match_operand:XF 0 "register_operand" "=f") (abs:XF (match_operand:XF 1 "register_operand" "0")))] - "!TARGET_64BIT && TARGET_80387 && reload_completed" + "TARGET_80387 && reload_completed" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "DF")]) @@ -10078,7 +10340,7 @@ [(set (match_operand:XF 0 "register_operand" "=f") (abs:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] - "!TARGET_64BIT && TARGET_80387" + "TARGET_80387" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "XF")]) @@ -10087,32 +10349,6 @@ [(set (match_operand:XF 0 "register_operand" "=f") (abs:XF (float_extend:XF (match_operand:SF 1 "register_operand" "0"))))] - "!TARGET_64BIT && TARGET_80387" - "fabs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF")]) - -(define_insn "*abstf2_1" - [(set (match_operand:TF 0 "register_operand" "=f") - (abs:TF (match_operand:TF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" - "fabs" - [(set_attr "type" "fsgn") - (set_attr "mode" "DF")]) - -(define_insn "*absextenddftf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (abs:TF (float_extend:TF - (match_operand:DF 1 "register_operand" "0"))))] - "TARGET_80387" - "fabs" - [(set_attr "type" "fsgn") - (set_attr "mode" "XF")]) - -(define_insn "*absextendsftf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (abs:TF (float_extend:TF - (match_operand:SF 1 "register_operand" "0"))))] "TARGET_80387" "fabs" [(set_attr "type" "fsgn") @@ -10697,9 +10933,11 @@ (zero_extend:DI (ashift (match_operand 1 "register_operand" "") (match_operand:QI 2 "const_int_operand" "")))) (clobber (reg:CC 17))] - "reload_completed + "TARGET_64BIT && reload_completed && true_regnum (operands[0]) != true_regnum (operands[1])" - [(set (match_dup 0) (zero_extend:DI (subreg:SI (mult:SI (match_dup 1) (match_dup 2)) 0)))] + [(set (match_dup 0) (zero_extend:DI + (subreg:SI (mult:SI (match_dup 1) + (match_dup 2)) 0)))] { operands[1] = gen_lowpart (Pmode, operands[1]); operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode); @@ -11112,7 +11350,7 @@ (define_insn "*ashrdi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11142,7 +11380,7 @@ [(set (reg 17) (compare (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (ashiftrt:DI (match_dup 1) (match_dup 2)))] @@ -11301,7 +11539,7 @@ (define_insn "*ashrsi3_1_one_bit" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ASHIFTRT, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11315,7 +11553,7 @@ (define_insn "*ashrsi3_1_one_bit_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")))) + (match_operand:QI 2 "const1_operand" "")))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11354,7 +11592,7 @@ [(set (reg 17) (compare (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (ashiftrt:SI (match_dup 1) (match_dup 2)))] @@ -11372,7 +11610,7 @@ [(set (reg 17) (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))] @@ -11425,7 +11663,7 @@ (define_insn "*ashrhi3_1_one_bit" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ASHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11455,7 +11693,7 @@ [(set (reg 17) (compare (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashiftrt:HI (match_dup 1) (match_dup 2)))] @@ -11497,7 +11735,7 @@ (define_insn "*ashrqi3_1_one_bit" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ASHIFTRT, QImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11511,7 +11749,7 @@ (define_insn "*ashrqi3_1_one_bit_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (ashiftrt:QI (match_dup 0) - (match_operand:QI 1 "const_int_1_operand" ""))) + (match_operand:QI 1 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ASHIFTRT, QImode, operands) && (! TARGET_PARTIAL_REG_STALL || optimize_size) @@ -11555,7 +11793,7 @@ [(set (reg 17) (compare (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "I")) + (match_operand:QI 2 "const1_operand" "I")) (const_int 0))) (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (ashiftrt:QI (match_dup 1) (match_dup 2)))] @@ -11609,7 +11847,7 @@ (define_insn "*lshrdi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11639,7 +11877,7 @@ [(set (reg 17) (compare (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (lshiftrt:DI (match_dup 1) (match_dup 2)))] @@ -11719,7 +11957,7 @@ (define_insn "*lshrsi3_1_one_bit" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (LSHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11733,7 +11971,7 @@ (define_insn "*lshrsi3_1_one_bit_zext" [(set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0")) - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11773,7 +12011,7 @@ [(set (reg 17) (compare (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (lshiftrt:SI (match_dup 1) (match_dup 2)))] @@ -11791,7 +12029,7 @@ [(set (reg 17) (compare (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))] @@ -11844,7 +12082,7 @@ (define_insn "*lshrhi3_1_one_bit" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (LSHIFTRT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11874,7 +12112,7 @@ [(set (reg 17) (compare (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (lshiftrt:HI (match_dup 1) (match_dup 2)))] @@ -11916,7 +12154,7 @@ (define_insn "*lshrqi3_1_one_bit" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (LSHIFTRT, QImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -11930,7 +12168,7 @@ (define_insn "*lshrqi3_1_one_bit_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (lshiftrt:QI (match_dup 0) - (match_operand:QI 1 "const_int_1_operand" ""))) + (match_operand:QI 1 "const1_operand" ""))) (clobber (reg:CC 17))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (TARGET_SHIFT1 || optimize_size)" @@ -11973,7 +12211,7 @@ [(set (reg 17) (compare (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")) + (match_operand:QI 2 "const1_operand" "")) (const_int 0))) (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (lshiftrt:QI (match_dup 1) (match_dup 2)))] @@ -12017,7 +12255,7 @@ (define_insn "*rotlsi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12051,7 +12289,7 @@ (define_insn "*rotlsi3_1_one_bit" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATE, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12066,7 +12304,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (rotate:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")))) + (match_operand:QI 2 "const1_operand" "")))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12110,7 +12348,7 @@ (define_insn "*rotlhi3_1_one_bit" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATE, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12144,7 +12382,7 @@ (define_insn "*rotlqi3_1_one_bit_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (rotate:QI (match_dup 0) - (match_operand:QI 1 "const_int_1_operand" ""))) + (match_operand:QI 1 "const1_operand" ""))) (clobber (reg:CC 17))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (TARGET_SHIFT1 || optimize_size)" @@ -12158,7 +12396,7 @@ (define_insn "*rotlqi3_1_one_bit" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATE, QImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12205,7 +12443,7 @@ (define_insn "*rotrdi3_1_one_bit_rex64" [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12239,7 +12477,7 @@ (define_insn "*rotrsi3_1_one_bit" [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATERT, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12254,7 +12492,7 @@ [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (rotatert:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_1_operand" "")))) + (match_operand:QI 2 "const1_operand" "")))) (clobber (reg:CC 17))] "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12301,7 +12539,7 @@ (define_insn "*rotrhi3_one_bit" [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATERT, HImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12335,7 +12573,7 @@ (define_insn "*rotrqi3_1_one_bit" [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "const_int_1_operand" ""))) + (match_operand:QI 2 "const1_operand" ""))) (clobber (reg:CC 17))] "ix86_binary_operator_ok (ROTATERT, QImode, operands) && (TARGET_SHIFT1 || optimize_size)" @@ -12349,7 +12587,7 @@ (define_insn "*rotrqi3_1_one_bit_slp" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm")) (rotatert:QI (match_dup 0) - (match_operand:QI 1 "const_int_1_operand" ""))) + (match_operand:QI 1 "const1_operand" ""))) (clobber (reg:CC 17))] "(! TARGET_PARTIAL_REG_STALL || optimize_size) && (TARGET_SHIFT1 || optimize_size)" @@ -12422,10 +12660,10 @@ }) (define_expand "insv" - [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "") - (match_operand:SI 1 "immediate_operand" "") - (match_operand:SI 2 "immediate_operand" "")) - (match_operand:SI 3 "register_operand" ""))] + [(set (zero_extract (match_operand 0 "ext_register_operand" "") + (match_operand 1 "immediate_operand" "") + (match_operand 2 "immediate_operand" "")) + (match_operand 3 "register_operand" ""))] "" { /* Handle extractions from %ah et al. */ @@ -12436,6 +12674,13 @@ matches the predicate, so check it again here. */ if (! register_operand (operands[0], VOIDmode)) FAIL; + + if (TARGET_64BIT) + emit_insn (gen_movdi_insv_1_rex64 (operands[0], operands[3])); + else + emit_insn (gen_movsi_insv_1 (operands[0], operands[3])); + + DONE; }) ;; %%% bts, btr, btc, bt. @@ -12648,7 +12893,7 @@ ;; The SSE store flag instructions saves 0 or 0xffffffff to the result. ;; subsequent logical operations are used to imitate conditional moves. ;; 0xffffffff is NaN, but not in normalized form, so we can't represent -;; it directly. Futher holding this value in pseudo register might bring +;; it directly. Further holding this value in pseudo register might bring ;; problem in implicit normalization in spill code. ;; So we don't define FLOAT_STORE_FLAG_VALUE and create these ;; instructions after reload by splitting the conditional move patterns. @@ -13321,7 +13566,7 @@ (match_dup 2))] { operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17); - operands[5] = gen_rtx_REG (QImode, REGNO (operands[3])); + operands[5] = gen_lowpart (QImode, operands[3]); ix86_expand_clear (operands[3]); }) @@ -13343,7 +13588,7 @@ (match_dup 2))] { operands[4] = gen_rtx_REG (GET_MODE (operands[0]), 17); - operands[5] = gen_rtx_REG (QImode, REGNO (operands[3])); + operands[5] = gen_lowpart (QImode, operands[3]); ix86_expand_clear (operands[3]); }) @@ -13363,7 +13608,7 @@ (match_operand:SI 3 "" "")))])] "!TARGET_64BIT" { - ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3]); + ix86_expand_call (NULL, operands[0], operands[1], operands[2], operands[3], 0); DONE; }) @@ -13408,7 +13653,17 @@ (use (match_operand 2 "" ""))] "" { - ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL); + ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 0); + DONE; +}) + +(define_expand "sibcall" + [(call (match_operand:QI 0 "" "") + (match_operand 1 "" "")) + (use (match_operand 2 "" ""))] + "" +{ + ix86_expand_call (NULL, operands[0], operands[1], operands[2], NULL, 1); DONE; }) @@ -13427,41 +13682,51 @@ (define_insn "*call_1" [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "rsm")) (match_operand 1 "" ""))] - "!TARGET_64BIT" + "!SIBLING_CALL_P (insn) && !TARGET_64BIT" { if (constant_call_address_operand (operands[0], QImode)) - { - if (SIBLING_CALL_P (insn)) - return "jmp\t%P0"; - else - return "call\t%P0"; - } - if (SIBLING_CALL_P (insn)) - return "jmp\t%A0"; - else - return "call\t%A0"; + return "call\t%P0"; + return "call\t%A0"; +} + [(set_attr "type" "call")]) + +(define_insn "*sibcall_1" + [(call (mem:QI (match_operand:SI 0 "sibcall_insn_operand" "s,c,d,a")) + (match_operand 1 "" ""))] + "SIBLING_CALL_P (insn) && !TARGET_64BIT" +{ + if (constant_call_address_operand (operands[0], QImode)) + return "jmp\t%P0"; + return "jmp\t%A0"; } [(set_attr "type" "call")]) (define_insn "*call_1_rex64" [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rsm")) (match_operand 1 "" ""))] - "TARGET_64BIT" + "!SIBLING_CALL_P (insn) && TARGET_64BIT" { if (constant_call_address_operand (operands[0], QImode)) - { - if (SIBLING_CALL_P (insn)) - return "jmp\t%P0"; - else - return "call\t%P0"; - } - if (SIBLING_CALL_P (insn)) - return "jmp\t%A0"; - else - return "call\t%A0"; + return "call\t%P0"; + return "call\t%A0"; } [(set_attr "type" "call")]) +(define_insn "*sibcall_1_rex64" + [(call (mem:QI (match_operand:DI 0 "constant_call_address_operand" "")) + (match_operand 1 "" ""))] + "SIBLING_CALL_P (insn) && TARGET_64BIT" + "jmp\t%P0" + [(set_attr "type" "call")]) + +(define_insn "*sibcall_1_rex64_v" + [(call (mem:QI (reg:DI 40)) + (match_operand 0 "" ""))] + "SIBLING_CALL_P (insn) && TARGET_64BIT" + "jmp\t*%%r11" + [(set_attr "type" "call")]) + + ;; Call subroutine, returning value in operand 0 (define_expand "call_value_pop" @@ -13474,7 +13739,7 @@ "!TARGET_64BIT" { ix86_expand_call (operands[0], operands[1], operands[2], - operands[3], operands[4]); + operands[3], operands[4], 0); DONE; }) @@ -13486,7 +13751,19 @@ ;; Operand 2 not used on the i386. "" { - ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL); + ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 0); + DONE; +}) + +(define_expand "sibcall_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "" "") + (match_operand:SI 2 "" ""))) + (use (match_operand:SI 3 "" ""))] + ;; Operand 2 not used on the i386. + "" +{ + ix86_expand_call (operands[0], operands[1], operands[2], operands[3], NULL, 1); DONE; }) @@ -13509,7 +13786,7 @@ ix86_expand_call ((TARGET_FLOAT_RETURNS_IN_80387 ? gen_rtx_REG (XCmode, FIRST_FLOAT_REG) : NULL), operands[0], const0_rtx, GEN_INT (SSE_REGPARM_MAX - 1), - NULL); + NULL, 0); for (i = 0; i < XVECLEN (operands[2], 0); i++) { @@ -13561,6 +13838,19 @@ (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) +;; Used by x86_machine_dependent_reorg to avoid penalty on single byte RET +;; instruction Athlon and K8 have. + +(define_insn "return_internal_long" + [(return) + (unspec [(const_int 0)] UNSPEC_REP)] + "reload_completed" + "rep {;} ret" + [(set_attr "length" "1") + (set_attr "length_immediate" "0") + (set_attr "prefix_rep" "1") + (set_attr "modrm" "0")]) + (define_insn "return_pop_internal" [(return) (use (match_operand:SI 0 "const_int_operand" ""))] @@ -13587,6 +13877,26 @@ (set_attr "modrm" "0") (set_attr "ppro_uops" "one")]) +;; Align to 16-byte boundary, max skip in op0. Used to avoid +;; branch prediction penalty for the third jump in a 16-byte +;; block on K8. + +(define_insn "align" + [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_ALIGN)] + "" +{ +#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN + ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0])); +#else + /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that. + The align insn is used to avoid 3 jump instructions in the row to improve + branch prediction and the benefits hardly outweight the cost of extra 8 + nops on the average inserted by full alignment pseudo operation. */ +#endif + return ""; +} + [(set_attr "length" "16")]) + (define_expand "prologue" [(const_int 1)] "" @@ -13657,11 +13967,7 @@ (clobber (mem:BLK (scratch)))] "!TARGET_64BIT" "leave" - [(set_attr "length_immediate" "0") - (set_attr "length" "1") - (set_attr "modrm" "0") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + [(set_attr "type" "leave")]) (define_insn "leave_rex64" [(set (reg:DI 7) (plus:DI (reg:DI 6) (const_int 8))) @@ -13669,111 +13975,100 @@ (clobber (mem:BLK (scratch)))] "TARGET_64BIT" "leave" - [(set_attr "length_immediate" "0") - (set_attr "length" "1") - (set_attr "modrm" "0") - (set_attr "athlon_decode" "vector") - (set_attr "ppro_uops" "few")]) + [(set_attr "type" "leave")]) (define_expand "ffssi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "")))] + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (ffs:SI (match_operand:SI 1 "nonimmediate_operand" ""))) + (clobber (match_scratch:SI 2 "")) + (clobber (reg:CC 17))])] "" -{ - rtx out = gen_reg_rtx (SImode), tmp = gen_reg_rtx (SImode); - rtx in = operands[1]; + "") - if (TARGET_CMOVE) - { - emit_move_insn (tmp, constm1_rtx); - emit_insn (gen_ffssi_1 (out, in)); - emit_insn (gen_rtx_SET (VOIDmode, out, - gen_rtx_IF_THEN_ELSE (SImode, - gen_rtx_EQ (VOIDmode, gen_rtx_REG (CCZmode, FLAGS_REG), - const0_rtx), - tmp, - out))); - emit_insn (gen_addsi3 (out, out, const1_rtx)); - emit_move_insn (operands[0], out); - } +(define_insn_and_split "*ffs_cmove" + [(set (match_operand:SI 0 "register_operand" "=r") + (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) + (clobber (match_scratch:SI 2 "=&r")) + (clobber (reg:CC 17))] + "TARGET_CMOVE" + "#" + "&& reload_completed" + [(set (match_dup 2) (const_int -1)) + (parallel [(set (reg:CCZ 17) (compare:CCZ (match_dup 1) (const_int 0))) + (set (match_dup 0) (ctz:SI (match_dup 1)))]) + (set (match_dup 0) (if_then_else:SI + (eq (reg:CCZ 17) (const_int 0)) + (match_dup 2) + (match_dup 0))) + (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))) + (clobber (reg:CC 17))])] + "") - /* Pentium bsf instruction is extremly slow. The following code is - recommended by the Intel Optimizing Manual as a reasonable replacement: - TEST EAX,EAX - JZ SHORT BS2 - XOR ECX,ECX - MOV DWORD PTR [TEMP+4],ECX - SUB ECX,EAX - AND EAX,ECX - MOV DWORD PTR [TEMP],EAX - FILD QWORD PTR [TEMP] - FSTP QWORD PTR [TEMP] - WAIT ; WAIT only needed for compatibility with - ; earlier processors - MOV ECX, DWORD PTR [TEMP+4] - SHR ECX,20 - SUB ECX,3FFH - TEST EAX,EAX ; clear zero flag - BS2: - Following piece of code expand ffs to similar beast. - */ - - else if (TARGET_PENTIUM && !optimize_size && TARGET_80387) - { - rtx label = gen_label_rtx (); - rtx lo, hi; - rtx mem = assign_386_stack_local (DImode, 0); - rtx fptmp = gen_reg_rtx (DFmode); - split_di (&mem, 1, &lo, &hi); - - emit_move_insn (out, const0_rtx); - - emit_cmp_and_jump_insns (in, const0_rtx, EQ, 0, SImode, 1, label); - - emit_move_insn (hi, out); - emit_insn (gen_subsi3 (out, out, in)); - emit_insn (gen_andsi3 (out, out, in)); - emit_move_insn (lo, out); - emit_insn (gen_floatdidf2 (fptmp,mem)); - emit_move_insn (gen_rtx_MEM (DFmode, XEXP (mem, 0)), fptmp); - emit_move_insn (out, hi); - emit_insn (gen_lshrsi3 (out, out, GEN_INT (20))); - emit_insn (gen_subsi3 (out, out, GEN_INT (0x3ff - 1))); - - emit_label (label); - LABEL_NUSES (label) = 1; - - emit_move_insn (operands[0], out); - } - else - { - emit_move_insn (tmp, const0_rtx); - emit_insn (gen_ffssi_1 (out, in)); - emit_insn (gen_rtx_SET (VOIDmode, - gen_rtx_STRICT_LOW_PART (VOIDmode, gen_lowpart (QImode, tmp)), - gen_rtx_EQ (QImode, gen_rtx_REG (CCZmode, FLAGS_REG), - const0_rtx))); - emit_insn (gen_negsi2 (tmp, tmp)); - emit_insn (gen_iorsi3 (out, out, tmp)); - emit_insn (gen_addsi3 (out, out, const1_rtx)); - emit_move_insn (operands[0], out); - } - DONE; +(define_insn_and_split "*ffs_no_cmove" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r") + (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) + (clobber (match_scratch:SI 2 "=&q")) + (clobber (reg:CC 17))] + "" + "#" + "reload_completed" + [(parallel [(set (reg:CCZ 17) (compare:CCZ (match_dup 1) (const_int 0))) + (set (match_dup 0) (ctz:SI (match_dup 1)))]) + (set (strict_low_part (match_dup 3)) + (eq:QI (reg:CCZ 17) (const_int 0))) + (parallel [(set (match_dup 2) (neg:SI (match_dup 2))) + (clobber (reg:CC 17))]) + (parallel [(set (match_dup 0) (ior:SI (match_dup 0) (match_dup 2))) + (clobber (reg:CC 17))]) + (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))) + (clobber (reg:CC 17))])] +{ + operands[3] = gen_lowpart (QImode, operands[2]); + ix86_expand_clear (operands[2]); }) -(define_insn "ffssi_1" +(define_insn "*ffssi_1" [(set (reg:CCZ 17) - (compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm") + (compare:CCZ (match_operand:SI 1 "nonimmediate_operand" "rm") (const_int 0))) (set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_dup 1)] UNSPEC_BSF))] + (ctz:SI (match_dup 1)))] + "" + "bsf{l}\t{%1, %0|%0, %1}" + [(set_attr "prefix_0f" "1") + (set_attr "ppro_uops" "few")]) + +(define_insn "ctzsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (ctz:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))) + (clobber (reg:CC 17))] "" "bsf{l}\t{%1, %0|%0, %1}" [(set_attr "prefix_0f" "1") (set_attr "ppro_uops" "few")]) -;; ffshi2 is not useful -- 4 word prefix ops are needed, which is larger -;; and slower than the two-byte movzx insn needed to do the work in SImode. +(define_expand "clzsi2" + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (minus:SI (const_int 31) + (clz:SI (match_operand:SI 1 "nonimmediate_operand" "")))) + (clobber (reg:CC 17))]) + (parallel + [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 31))) + (clobber (reg:CC 17))])] + "" + "") + +(define_insn "*bsr" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (const_int 31) + (clz:SI (match_operand:SI 1 "nonimmediate_operand" "rm")))) + (clobber (reg:CC 17))] + "" + "bsr{l}\t{%1, %0|%0, %1}" + [(set_attr "prefix_0f" "1") + (set_attr "ppro_uops" "few")]) ;; Thread-local storage patterns for ELF. ;; @@ -13941,6 +14236,56 @@ (clobber (match_dup 5)) (clobber (reg:CC 17))])] "") + +;; Load and add the thread base pointer from %gs:0. + +(define_insn "*load_tp_si" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(const_int 0)] UNSPEC_TP))] + "!TARGET_64BIT" + "mov{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}" + [(set_attr "type" "imov") + (set_attr "modrm" "0") + (set_attr "length" "7") + (set_attr "memory" "load") + (set_attr "imm_disp" "false")]) + +(define_insn "*add_tp_si" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP) + (match_operand:SI 1 "register_operand" "0"))) + (clobber (reg:CC 17))] + "!TARGET_64BIT" + "add{l}\t{%%gs:0, %0|%0, DWORD PTR %%gs:0}" + [(set_attr "type" "alu") + (set_attr "modrm" "0") + (set_attr "length" "7") + (set_attr "memory" "load") + (set_attr "imm_disp" "false")]) + +(define_insn "*load_tp_di" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(const_int 0)] UNSPEC_TP))] + "TARGET_64BIT" + "mov{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}" + [(set_attr "type" "imov") + (set_attr "modrm" "0") + (set_attr "length" "7") + (set_attr "memory" "load") + (set_attr "imm_disp" "false")]) + +(define_insn "*add_tp_di" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (unspec:DI [(const_int 0)] UNSPEC_TP) + (match_operand:DI 1 "register_operand" "0"))) + (clobber (reg:CC 17))] + "TARGET_64BIT" + "add{q}\t{%%fs:0, %0|%0, QWORD PTR %%fs:0}" + [(set_attr "type" "alu") + (set_attr "modrm" "0") + (set_attr "length" "7") + (set_attr "memory" "load") + (set_attr "imm_disp" "false")]) ;; These patterns match the binary 387 instructions for addM3, subM3, ;; mulM3 and divM3. There are three patterns for each of DFmode and @@ -14054,7 +14399,7 @@ (match_operator:XF 3 "binary_fp_operator" [(match_operand:XF 1 "register_operand" "%0") (match_operand:XF 2 "register_operand" "f")]))] - "!TARGET_64BIT && TARGET_80387 + "TARGET_80387 && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'" "* return output_387_binary_op (insn, operands);" [(set (attr "type") @@ -14063,19 +14408,6 @@ (const_string "fop"))) (set_attr "mode" "XF")]) -(define_insn "*fop_tf_comm" - [(set (match_operand:TF 0 "register_operand" "=f") - (match_operator:TF 3 "binary_fp_operator" - [(match_operand:TF 1 "register_operand" "%0") - (match_operand:TF 2 "register_operand" "f")]))] - "TARGET_80387 && GET_RTX_CLASS (GET_CODE (operands[3])) == 'c'" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (if_then_else (match_operand:TF 3 "mult_operator" "") - (const_string "fmul") - (const_string "fop"))) - (set_attr "mode" "XF")]) - (define_insn "*fop_sf_1_nosse" [(set (match_operand:SF 0 "register_operand" "=f,f") (match_operator:SF 3 "binary_fp_operator" @@ -14307,35 +14639,36 @@ (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_xf_1" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (match_operator:XF 3 "binary_fp_operator" - [(match_operand:XF 1 "register_operand" "0,f") - (match_operand:XF 2 "register_operand" "f,0")]))] - "!TARGET_64BIT && TARGET_80387 - && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'" +(define_insn "*fop_df_6" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (match_operator:DF 3 "binary_fp_operator" + [(float_extend:DF + (match_operand:SF 1 "register_operand" "0,f")) + (float_extend:DF + (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] + "TARGET_80387 && !(TARGET_SSE2 && TARGET_SSE_MATH)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (cond [(match_operand:XF 3 "mult_operator" "") + (cond [(match_operand:DF 3 "mult_operator" "") (const_string "fmul") - (match_operand:XF 3 "div_operator" "") + (match_operand:DF 3 "div_operator" "") (const_string "fdiv") ] (const_string "fop"))) - (set_attr "mode" "XF")]) + (set_attr "mode" "SF")]) -(define_insn "*fop_tf_1" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (match_operator:TF 3 "binary_fp_operator" - [(match_operand:TF 1 "register_operand" "0,f") - (match_operand:TF 2 "register_operand" "f,0")]))] +(define_insn "*fop_xf_1" + [(set (match_operand:XF 0 "register_operand" "=f,f") + (match_operator:XF 3 "binary_fp_operator" + [(match_operand:XF 1 "register_operand" "0,f") + (match_operand:XF 2 "register_operand" "f,0")]))] "TARGET_80387 && GET_RTX_CLASS (GET_CODE (operands[3])) != 'c'" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (cond [(match_operand:TF 3 "mult_operator" "") + (cond [(match_operand:XF 3 "mult_operator" "") (const_string "fmul") - (match_operand:TF 3 "div_operator" "") + (match_operand:XF 3 "div_operator" "") (const_string "fdiv") ] (const_string "fop"))) @@ -14346,7 +14679,7 @@ (match_operator:XF 3 "binary_fp_operator" [(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,?r")) (match_operand:XF 2 "register_operand" "0,0")]))] - "!TARGET_64BIT && TARGET_80387 && TARGET_USE_FIOP" + "TARGET_80387 && TARGET_USE_FIOP" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -14359,30 +14692,12 @@ (set_attr "mode" "SI") (set_attr "ppro_uops" "many")]) -(define_insn "*fop_tf_2" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (match_operator:TF 3 "binary_fp_operator" - [(float:TF (match_operand:SI 1 "nonimmediate_operand" "m,?r")) - (match_operand:TF 2 "register_operand" "0,0")]))] - "TARGET_80387 && TARGET_USE_FIOP" - "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:TF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:TF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "fp_int_src" "true") - (set_attr "mode" "SI") - (set_attr "ppro_uops" "many")]) - (define_insn "*fop_xf_3" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" [(match_operand:XF 1 "register_operand" "0,0") (float:XF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))] - "!TARGET_64BIT && TARGET_80387 && TARGET_USE_FIOP" + "TARGET_80387 && TARGET_USE_FIOP" "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -14395,30 +14710,12 @@ (set_attr "mode" "SI") (set_attr "ppro_uops" "many")]) -(define_insn "*fop_tf_3" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (match_operator:TF 3 "binary_fp_operator" - [(match_operand:TF 1 "register_operand" "0,0") - (float:TF (match_operand:SI 2 "nonimmediate_operand" "m,?r"))]))] - "TARGET_80387 && TARGET_USE_FIOP" - "* return which_alternative ? \"#\" : output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:TF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:TF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "fp_int_src" "true") - (set_attr "mode" "SI") - (set_attr "ppro_uops" "many")]) - (define_insn "*fop_xf_4" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" - [(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) + [(float_extend:XF (match_operand 1 "nonimmediate_operand" "fm,0")) (match_operand:XF 2 "register_operand" "0,f")]))] - "!TARGET_64BIT && TARGET_80387" + "TARGET_80387" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -14429,29 +14726,13 @@ (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_tf_4" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (match_operator:TF 3 "binary_fp_operator" - [(float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) - (match_operand:TF 2 "register_operand" "0,f")]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:TF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:TF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "mode" "SF")]) - (define_insn "*fop_xf_5" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" [(match_operand:XF 1 "register_operand" "0,f") (float_extend:XF - (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] - "!TARGET_64BIT && TARGET_80387" + (match_operand 2 "nonimmediate_operand" "fm,0"))]))] + "TARGET_80387" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -14462,62 +14743,14 @@ (const_string "fop"))) (set_attr "mode" "SF")]) -(define_insn "*fop_tf_5" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (match_operator:TF 3 "binary_fp_operator" - [(match_operand:TF 1 "register_operand" "0,f") - (float_extend:TF - (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:TF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:TF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "mode" "SF")]) - (define_insn "*fop_xf_6" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_fp_operator" - [(float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,0")) - (match_operand:XF 2 "register_operand" "0,f")]))] - "!TARGET_64BIT && TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:XF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:XF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_tf_6" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (match_operator:TF 3 "binary_fp_operator" - [(float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "fm,0")) - (match_operand:TF 2 "register_operand" "0,f")]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:TF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:TF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_xf_7" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (match_operator:XF 3 "binary_fp_operator" - [(match_operand:XF 1 "register_operand" "0,f") + [(float_extend:XF + (match_operand 1 "register_operand" "0,f")) (float_extend:XF - (match_operand:DF 2 "nonimmediate_operand" "fm,0"))]))] - "!TARGET_64BIT && TARGET_80387" + (match_operand 2 "nonimmediate_operand" "fm,0"))]))] + "TARGET_80387" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(match_operand:XF 3 "mult_operator" "") @@ -14526,24 +14759,7 @@ (const_string "fdiv") ] (const_string "fop"))) - (set_attr "mode" "DF")]) - -(define_insn "*fop_tf_7" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (match_operator:TF 3 "binary_fp_operator" - [(match_operand:TF 1 "register_operand" "0,f") - (float_extend:TF - (match_operand:DF 2 "nonimmediate_operand" "fm,0"))]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:TF 3 "mult_operator" "") - (const_string "fmul") - (match_operand:TF 3 "div_operator" "") - (const_string "fdiv") - ] - (const_string "fop"))) - (set_attr "mode" "DF")]) + (set_attr "mode" "SF")]) (define_split [(set (match_operand 0 "register_operand" "") @@ -14682,17 +14898,7 @@ (define_insn "sqrtxf2" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (match_operand:XF 1 "register_operand" "0")))] - "!TARGET_64BIT && TARGET_80387 && !TARGET_NO_FANCY_MATH_387 - && (TARGET_IEEE_FP || flag_unsafe_math_optimizations) " - "fsqrt" - [(set_attr "type" "fpspc") - (set_attr "mode" "XF") - (set_attr "athlon_decode" "direct")]) - -(define_insn "sqrttf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (sqrt:TF (match_operand:TF 1 "register_operand" "0")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_80387 && !TARGET_NO_FANCY_MATH_387 && (TARGET_IEEE_FP || flag_unsafe_math_optimizations) " "fsqrt" [(set_attr "type" "fpspc") @@ -14703,17 +14909,7 @@ [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] - "!TARGET_64BIT && TARGET_80387 && !TARGET_NO_FANCY_MATH_387" - "fsqrt" - [(set_attr "type" "fpspc") - (set_attr "mode" "XF") - (set_attr "athlon_decode" "direct")]) - -(define_insn "*sqrtextenddftf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (sqrt:TF (float_extend:TF - (match_operand:DF 1 "register_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" + "TARGET_80387 && !TARGET_NO_FANCY_MATH_387" "fsqrt" [(set_attr "type" "fpspc") (set_attr "mode" "XF") @@ -14723,17 +14919,7 @@ [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF (match_operand:SF 1 "register_operand" "0"))))] - "!TARGET_64BIT && TARGET_80387 && !TARGET_NO_FANCY_MATH_387" - "fsqrt" - [(set_attr "type" "fpspc") - (set_attr "mode" "XF") - (set_attr "athlon_decode" "direct")]) - -(define_insn "*sqrtextendsftf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (sqrt:TF (float_extend:TF - (match_operand:SF 1 "register_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" + "TARGET_80387 && !TARGET_NO_FANCY_MATH_387" "fsqrt" [(set_attr "type" "fpspc") (set_attr "mode" "XF") @@ -14771,16 +14957,7 @@ (define_insn "sinxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_SIN))] - "!TARGET_64BIT && TARGET_80387 && !TARGET_NO_FANCY_MATH_387 - && flag_unsafe_math_optimizations" - "fsin" - [(set_attr "type" "fpspc") - (set_attr "mode" "XF")]) - -(define_insn "sintf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (unspec:TF [(match_operand:TF 1 "register_operand" "0")] UNSPEC_SIN))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "TARGET_80387 && !TARGET_NO_FANCY_MATH_387 && flag_unsafe_math_optimizations" "fsin" [(set_attr "type" "fpspc") @@ -14818,20 +14995,333 @@ (define_insn "cosxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] UNSPEC_COS))] - "!TARGET_64BIT && ! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" "fcos" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) -(define_insn "costf2" - [(set (match_operand:TF 0 "register_operand" "=f") - (unspec:TF [(match_operand:TF 1 "register_operand" "0")] UNSPEC_COS))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 +(define_insn "atan2df3_1" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(match_operand:DF 2 "register_operand" "0") + (match_operand:DF 1 "register_operand" "u")] + UNSPEC_FPATAN)) + (clobber (match_scratch:DF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" - "fcos" + "fpatan" + [(set_attr "type" "fpspc") + (set_attr "mode" "DF")]) + +(define_expand "atan2df3" + [(use (match_operand:DF 0 "register_operand" "=f")) + (use (match_operand:DF 2 "register_operand" "0")) + (use (match_operand:DF 1 "register_operand" "u"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx copy = gen_reg_rtx (DFmode); + emit_move_insn (copy, operands[1]); + emit_insn (gen_atan2df3_1 (operands[0], copy, operands[2])); + DONE; +}) + +(define_insn "atan2sf3_1" + [(set (match_operand:SF 0 "register_operand" "=f") + (unspec:SF [(match_operand:SF 2 "register_operand" "0") + (match_operand:SF 1 "register_operand" "u")] + UNSPEC_FPATAN)) + (clobber (match_scratch:SF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fpatan" + [(set_attr "type" "fpspc") + (set_attr "mode" "SF")]) + +(define_expand "atan2sf3" + [(use (match_operand:SF 0 "register_operand" "=f")) + (use (match_operand:SF 2 "register_operand" "0")) + (use (match_operand:SF 1 "register_operand" "u"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx copy = gen_reg_rtx (SFmode); + emit_move_insn (copy, operands[1]); + emit_insn (gen_atan2sf3_1 (operands[0], copy, operands[2])); + DONE; +}) + +(define_insn "atan2xf3_1" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 1 "register_operand" "u")] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fpatan" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +(define_expand "atan2xf3" + [(use (match_operand:XF 0 "register_operand" "=f")) + (use (match_operand:XF 2 "register_operand" "0")) + (use (match_operand:XF 1 "register_operand" "u"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx copy = gen_reg_rtx (XFmode); + emit_move_insn (copy, operands[1]); + emit_insn (gen_atan2xf3_1 (operands[0], copy, operands[2])); + DONE; +}) + +(define_insn "*fyl2x_sfxf3" + [(set (match_operand:SF 0 "register_operand" "=f") + (unspec:SF [(match_operand:SF 2 "register_operand" "0") + (match_operand:XF 1 "register_operand" "u")] + UNSPEC_FYL2X)) + (clobber (match_scratch:SF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fyl2x" + [(set_attr "type" "fpspc") + (set_attr "mode" "SF")]) + +(define_insn "*fyl2x_dfxf3" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(match_operand:DF 2 "register_operand" "0") + (match_operand:XF 1 "register_operand" "u")] + UNSPEC_FYL2X)) + (clobber (match_scratch:DF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fyl2x" + [(set_attr "type" "fpspc") + (set_attr "mode" "DF")]) + +(define_insn "*fyl2x_xf3" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 1 "register_operand" "u")] + UNSPEC_FYL2X)) + (clobber (match_scratch:XF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fyl2x" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +(define_expand "logsf2" + [(parallel [(set (match_operand:SF 0 "register_operand" "") + (unspec:SF [(match_operand:SF 1 "register_operand" "") + (match_dup 2)] UNSPEC_FYL2X)) + (clobber (match_scratch:SF 3 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx temp; + + operands[2] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (4); /* fldln2 */ + emit_move_insn (operands[2], temp); +}) + +(define_expand "logdf2" + [(parallel [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(match_operand:DF 1 "register_operand" "") + (match_dup 2)] UNSPEC_FYL2X)) + (clobber (match_scratch:DF 3 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx temp; + + operands[2] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (4); /* fldln2 */ + emit_move_insn (operands[2], temp); +}) + +(define_expand "logxf2" + [(parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_operand:XF 1 "register_operand" "") + (match_dup 2)] UNSPEC_FYL2X)) + (clobber (match_scratch:XF 3 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx temp; + + operands[2] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (4); /* fldln2 */ + emit_move_insn (operands[2], temp); +}) + +(define_insn "*fscale_sfxf3" + [(set (match_operand:SF 0 "register_operand" "=f") + (unspec:SF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 1 "register_operand" "u")] + UNSPEC_FSCALE)) + (clobber (match_scratch:SF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fscale\;fstp\t%y1" + [(set_attr "type" "fpspc") + (set_attr "mode" "SF")]) + +(define_insn "*fscale_dfxf3" + [(set (match_operand:DF 0 "register_operand" "=f") + (unspec:DF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 1 "register_operand" "u")] + UNSPEC_FSCALE)) + (clobber (match_scratch:DF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fscale\;fstp\t%y1" + [(set_attr "type" "fpspc") + (set_attr "mode" "DF")]) + +(define_insn "*fscale_xf3" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 1 "register_operand" "u")] + UNSPEC_FSCALE)) + (clobber (match_scratch:XF 3 "=1"))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fscale\;fstp\t%y1" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) + +(define_insn "*frndintxf2" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_FRNDINT))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "frndint" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +(define_insn "*f2xm1xf2" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 1 "register_operand" "0")] + UNSPEC_F2XM1))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "f2xm1" + [(set_attr "type" "fpspc") + (set_attr "mode" "XF")]) + +(define_expand "expsf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:SF 1 "register_operand" ""))) + (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT)) + (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) + (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) + (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) + (parallel [(set (match_operand:SF 0 "register_operand" "") + (unspec:SF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE)) + (clobber (match_scratch:SF 5 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx temp; + int i; + + for (i=2; i<10; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (5); /* fldl2e */ + emit_move_insn (operands[3], temp); + emit_move_insn (operands[8], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "expdf2" + [(set (match_dup 2) + (float_extend:XF (match_operand:DF 1 "register_operand" ""))) + (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3))) + (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT)) + (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) + (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) + (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) + (parallel [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE)) + (clobber (match_scratch:DF 5 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx temp; + int i; + + for (i=2; i<10; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (5); /* fldl2e */ + emit_move_insn (operands[3], temp); + emit_move_insn (operands[8], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "expxf2" + [(set (match_dup 3) (mult:XF (match_operand:XF 1 "register_operand" "") + (match_dup 2))) + (set (match_dup 4) (unspec:XF [(match_dup 3)] UNSPEC_FRNDINT)) + (set (match_dup 5) (minus:XF (match_dup 3) (match_dup 4))) + (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1)) + (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7))) + (parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 8) (match_dup 4)] UNSPEC_FSCALE)) + (clobber (match_scratch:XF 5 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + rtx temp; + int i; + + for (i=2; i<9; i++) + operands[i] = gen_reg_rtx (XFmode); + temp = standard_80387_constant_rtx (5); /* fldl2e */ + emit_move_insn (operands[2], temp); + emit_move_insn (operands[7], CONST1_RTX (XFmode)); /* fld1 */ +}) + +(define_expand "atansf2" + [(parallel [(set (match_operand:SF 0 "register_operand" "") + (unspec:SF [(match_dup 2) + (match_operand:SF 1 "register_operand" "")] + UNSPEC_FPATAN)) + (clobber (match_scratch:SF 3 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (SFmode); + emit_move_insn (operands[2], CONST1_RTX (SFmode)); /* fld1 */ +}) + +(define_expand "atandf2" + [(parallel [(set (match_operand:DF 0 "register_operand" "") + (unspec:DF [(match_dup 2) + (match_operand:DF 1 "register_operand" "")] + UNSPEC_FPATAN)) + (clobber (match_scratch:DF 3 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (DFmode); + emit_move_insn (operands[2], CONST1_RTX (DFmode)); /* fld1 */ +}) + +(define_expand "atanxf2" + [(parallel [(set (match_operand:XF 0 "register_operand" "") + (unspec:XF [(match_dup 2) + (match_operand:XF 1 "register_operand" "")] + UNSPEC_FPATAN)) + (clobber (match_scratch:XF 3 ""))])] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" +{ + operands[2] = gen_reg_rtx (XFmode); + emit_move_insn (operands[2], CONST1_RTX (XFmode)); /* fld1 */ +}) ;; Block operation instructions @@ -14846,7 +15336,7 @@ (use (match_operand:BLK 1 "memory_operand" "")) (use (match_operand:SI 2 "nonmemory_operand" "")) (use (match_operand:SI 3 "const_int_operand" ""))] - "" + "! optimize_size" { if (ix86_expand_movstr (operands[0], operands[1], operands[2], operands[3])) DONE; @@ -14870,170 +15360,45 @@ ;; Most CPUs don't like single string operations ;; Handle this case here to simplify previous expander. -(define_expand "strmovdi_rex64" - [(set (match_dup 2) - (mem:DI (match_operand:DI 1 "register_operand" ""))) - (set (mem:DI (match_operand:DI 0 "register_operand" "")) - (match_dup 2)) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 8))) +(define_expand "strmov" + [(set (match_dup 4) (match_operand 3 "memory_operand" "")) + (set (match_operand 1 "memory_operand" "") (match_dup 4)) + (parallel [(set (match_operand 0 "register_operand" "") (match_dup 5)) (clobber (reg:CC 17))]) - (parallel [(set (match_dup 1) (plus:DI (match_dup 1) (const_int 8))) - (clobber (reg:CC 17))])] - "TARGET_64BIT" -{ - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strmovdi_rex_1 (operands[0], operands[1], operands[0], - operands[1])); - DONE; - } - else - operands[2] = gen_reg_rtx (DImode); -}) - - -(define_expand "strmovsi" - [(set (match_dup 2) - (mem:SI (match_operand:SI 1 "register_operand" ""))) - (set (mem:SI (match_operand:SI 0 "register_operand" "")) - (match_dup 2)) - (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 4))) - (clobber (reg:CC 17))]) - (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 4))) + (parallel [(set (match_operand 2 "register_operand" "") (match_dup 6)) (clobber (reg:CC 17))])] "" { - if (TARGET_64BIT) - { - emit_insn (gen_strmovsi_rex64 (operands[0], operands[1])); - DONE; - } - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strmovsi_1 (operands[0], operands[1], operands[0], - operands[1])); - DONE; - } - else - operands[2] = gen_reg_rtx (SImode); -}) + rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1]))); -(define_expand "strmovsi_rex64" - [(set (match_dup 2) - (mem:SI (match_operand:DI 1 "register_operand" ""))) - (set (mem:SI (match_operand:DI 0 "register_operand" "")) - (match_dup 2)) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 4))) - (clobber (reg:CC 17))]) - (parallel [(set (match_dup 1) (plus:DI (match_dup 1) (const_int 4))) - (clobber (reg:CC 17))])] - "TARGET_64BIT" -{ - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strmovsi_rex_1 (operands[0], operands[1], operands[0], - operands[1])); - DONE; - } - else - operands[2] = gen_reg_rtx (SImode); -}) + /* If .md ever supports :P for Pmode, these can be directly + in the pattern above. */ + operands[5] = gen_rtx_PLUS (Pmode, operands[0], adjust); + operands[6] = gen_rtx_PLUS (Pmode, operands[2], adjust); -(define_expand "strmovhi" - [(set (match_dup 2) - (mem:HI (match_operand:SI 1 "register_operand" ""))) - (set (mem:HI (match_operand:SI 0 "register_operand" "")) - (match_dup 2)) - (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 2))) - (clobber (reg:CC 17))]) - (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 2))) - (clobber (reg:CC 17))])] - "" -{ - if (TARGET_64BIT) - { - emit_insn (gen_strmovhi_rex64 (operands[0], operands[1])); - DONE; - } if (TARGET_SINGLE_STRINGOP || optimize_size) { - emit_insn (gen_strmovhi_1 (operands[0], operands[1], operands[0], - operands[1])); + emit_insn (gen_strmov_singleop (operands[0], operands[1], + operands[2], operands[3], + operands[5], operands[6])); DONE; } - else - operands[2] = gen_reg_rtx (HImode); -}) -(define_expand "strmovhi_rex64" - [(set (match_dup 2) - (mem:HI (match_operand:DI 1 "register_operand" ""))) - (set (mem:HI (match_operand:DI 0 "register_operand" "")) - (match_dup 2)) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 2))) - (clobber (reg:CC 17))]) - (parallel [(set (match_dup 1) (plus:DI (match_dup 1) (const_int 2))) - (clobber (reg:CC 17))])] - "TARGET_64BIT" -{ - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strmovhi_rex_1 (operands[0], operands[1], operands[0], - operands[1])); - DONE; - } - else - operands[2] = gen_reg_rtx (HImode); + operands[4] = gen_reg_rtx (GET_MODE (operands[1])); }) -(define_expand "strmovqi" - [(set (match_dup 2) - (mem:QI (match_operand:SI 1 "register_operand" ""))) - (set (mem:QI (match_operand:SI 0 "register_operand" "")) - (match_dup 2)) - (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))) - (clobber (reg:CC 17))]) - (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 1))) - (clobber (reg:CC 17))])] - "" -{ - if (TARGET_64BIT) - { - emit_insn (gen_strmovqi_rex64 (operands[0], operands[1])); - DONE; - } - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strmovqi_1 (operands[0], operands[1], operands[0], - operands[1])); - DONE; - } - else - operands[2] = gen_reg_rtx (QImode); -}) - -(define_expand "strmovqi_rex64" - [(set (match_dup 2) - (mem:QI (match_operand:DI 1 "register_operand" ""))) - (set (mem:QI (match_operand:DI 0 "register_operand" "")) - (match_dup 2)) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1))) - (clobber (reg:CC 17))]) - (parallel [(set (match_dup 1) (plus:DI (match_dup 1) (const_int 1))) - (clobber (reg:CC 17))])] - "TARGET_64BIT" -{ - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strmovqi_rex_1 (operands[0], operands[1], operands[0], - operands[1])); - DONE; - } - else - operands[2] = gen_reg_rtx (QImode); -}) +(define_expand "strmov_singleop" + [(parallel [(set (match_operand 1 "memory_operand" "") + (match_operand 3 "memory_operand" "")) + (set (match_operand 0 "register_operand" "") + (match_operand 4 "" "")) + (set (match_operand 2 "register_operand" "") + (match_operand 5 "" "")) + (use (reg:SI 19))])] + "TARGET_SINGLE_STRINGOP || optimize_size" + "") -(define_insn "strmovdi_rex_1" +(define_insn "*strmovdi_rex_1" [(set (mem:DI (match_operand:DI 2 "register_operand" "0")) (mem:DI (match_operand:DI 3 "register_operand" "1"))) (set (match_operand:DI 0 "register_operand" "=D") @@ -15049,7 +15414,7 @@ (set_attr "mode" "DI") (set_attr "memory" "both")]) -(define_insn "strmovsi_1" +(define_insn "*strmovsi_1" [(set (mem:SI (match_operand:SI 2 "register_operand" "0")) (mem:SI (match_operand:SI 3 "register_operand" "1"))) (set (match_operand:SI 0 "register_operand" "=D") @@ -15065,7 +15430,7 @@ (set_attr "mode" "SI") (set_attr "memory" "both")]) -(define_insn "strmovsi_rex_1" +(define_insn "*strmovsi_rex_1" [(set (mem:SI (match_operand:DI 2 "register_operand" "0")) (mem:SI (match_operand:DI 3 "register_operand" "1"))) (set (match_operand:DI 0 "register_operand" "=D") @@ -15081,7 +15446,7 @@ (set_attr "mode" "SI") (set_attr "memory" "both")]) -(define_insn "strmovhi_1" +(define_insn "*strmovhi_1" [(set (mem:HI (match_operand:SI 2 "register_operand" "0")) (mem:HI (match_operand:SI 3 "register_operand" "1"))) (set (match_operand:SI 0 "register_operand" "=D") @@ -15097,7 +15462,7 @@ (set_attr "memory" "both") (set_attr "mode" "HI")]) -(define_insn "strmovhi_rex_1" +(define_insn "*strmovhi_rex_1" [(set (mem:HI (match_operand:DI 2 "register_operand" "0")) (mem:HI (match_operand:DI 3 "register_operand" "1"))) (set (match_operand:DI 0 "register_operand" "=D") @@ -15113,7 +15478,7 @@ (set_attr "memory" "both") (set_attr "mode" "HI")]) -(define_insn "strmovqi_1" +(define_insn "*strmovqi_1" [(set (mem:QI (match_operand:SI 2 "register_operand" "0")) (mem:QI (match_operand:SI 3 "register_operand" "1"))) (set (match_operand:SI 0 "register_operand" "=D") @@ -15129,7 +15494,7 @@ (set_attr "memory" "both") (set_attr "mode" "QI")]) -(define_insn "strmovqi_rex_1" +(define_insn "*strmovqi_rex_1" [(set (mem:QI (match_operand:DI 2 "register_operand" "0")) (mem:QI (match_operand:DI 3 "register_operand" "1"))) (set (match_operand:DI 0 "register_operand" "=D") @@ -15145,7 +15510,20 @@ (set_attr "memory" "both") (set_attr "mode" "QI")]) -(define_insn "rep_movdi_rex64" +(define_expand "rep_mov" + [(parallel [(set (match_operand 4 "register_operand" "") (const_int 0)) + (set (match_operand 0 "register_operand" "") + (match_operand 5 "" "")) + (set (match_operand 2 "register_operand" "") + (match_operand 6 "" "")) + (set (match_operand 1 "memory_operand" "") + (match_operand 3 "memory_operand" "")) + (use (match_dup 4)) + (use (reg:SI 19))])] + "" + "") + +(define_insn "*rep_movdi_rex64" [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0)) (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2") @@ -15165,7 +15543,7 @@ (set_attr "memory" "both") (set_attr "mode" "DI")]) -(define_insn "rep_movsi" +(define_insn "*rep_movsi" [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0)) (set (match_operand:SI 0 "register_operand" "=D") (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2") @@ -15185,7 +15563,7 @@ (set_attr "memory" "both") (set_attr "mode" "SI")]) -(define_insn "rep_movsi_rex64" +(define_insn "*rep_movsi_rex64" [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0)) (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (ashift:DI (match_operand:DI 5 "register_operand" "2") @@ -15205,7 +15583,7 @@ (set_attr "memory" "both") (set_attr "mode" "SI")]) -(define_insn "rep_movqi" +(define_insn "*rep_movqi" [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0)) (set (match_operand:SI 0 "register_operand" "=D") (plus:SI (match_operand:SI 3 "register_operand" "0") @@ -15223,7 +15601,7 @@ (set_attr "memory" "both") (set_attr "mode" "SI")]) -(define_insn "rep_movqi_rex64" +(define_insn "*rep_movqi_rex64" [(set (match_operand:DI 2 "register_operand" "=c") (const_int 0)) (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (match_operand:DI 3 "register_operand" "0") @@ -15268,120 +15646,40 @@ ;; Most CPUs don't like single string operations ;; Handle this case here to simplify previous expander. -(define_expand "strsetdi_rex64" - [(set (mem:DI (match_operand:DI 0 "register_operand" "")) - (match_operand:DI 1 "register_operand" "")) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 8))) - (clobber (reg:CC 17))])] - "TARGET_64BIT" -{ - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strsetdi_rex_1 (operands[0], operands[0], operands[1])); - DONE; - } -}) - -(define_expand "strsetsi" - [(set (mem:SI (match_operand:SI 0 "register_operand" "")) - (match_operand:SI 1 "register_operand" "")) - (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 4))) - (clobber (reg:CC 17))])] - "" -{ - if (TARGET_64BIT) - { - emit_insn (gen_strsetsi_rex64 (operands[0], operands[1])); - DONE; - } - else if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strsetsi_1 (operands[0], operands[0], operands[1])); - DONE; - } -}) - -(define_expand "strsetsi_rex64" - [(set (mem:SI (match_operand:DI 0 "register_operand" "")) - (match_operand:SI 1 "register_operand" "")) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 4))) - (clobber (reg:CC 17))])] - "TARGET_64BIT" -{ - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strsetsi_rex_1 (operands[0], operands[0], operands[1])); - DONE; - } -}) - -(define_expand "strsethi" - [(set (mem:HI (match_operand:SI 0 "register_operand" "")) - (match_operand:HI 1 "register_operand" "")) - (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 2))) +(define_expand "strset" + [(set (match_operand 1 "memory_operand" "") + (match_operand 2 "register_operand" "")) + (parallel [(set (match_operand 0 "register_operand" "") + (match_dup 3)) (clobber (reg:CC 17))])] "" { - if (TARGET_64BIT) - { - emit_insn (gen_strsethi_rex64 (operands[0], operands[1])); - DONE; - } - else if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strsethi_1 (operands[0], operands[0], operands[1])); - DONE; - } -}) - -(define_expand "strsethi_rex64" - [(set (mem:HI (match_operand:DI 0 "register_operand" "")) - (match_operand:HI 1 "register_operand" "")) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 2))) - (clobber (reg:CC 17))])] - "TARGET_64BIT" -{ + if (GET_MODE (operands[1]) != GET_MODE (operands[2])) + operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0); + + /* If .md ever supports :P for Pmode, this can be directly + in the pattern above. */ + operands[3] = gen_rtx_PLUS (Pmode, operands[0], + GEN_INT (GET_MODE_SIZE (GET_MODE + (operands[2])))); if (TARGET_SINGLE_STRINGOP || optimize_size) { - emit_insn (gen_strsethi_rex_1 (operands[0], operands[0], operands[1])); - DONE; - } -}) - -(define_expand "strsetqi" - [(set (mem:QI (match_operand:SI 0 "register_operand" "")) - (match_operand:QI 1 "register_operand" "")) - (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))) - (clobber (reg:CC 17))])] - "" -{ - if (TARGET_64BIT) - { - emit_insn (gen_strsetqi_rex64 (operands[0], operands[1])); - DONE; - } - else if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strsetqi_1 (operands[0], operands[0], operands[1])); + emit_insn (gen_strset_singleop (operands[0], operands[1], operands[2], + operands[3])); DONE; } }) -(define_expand "strsetqi_rex64" - [(set (mem:QI (match_operand:DI 0 "register_operand" "")) - (match_operand:QI 1 "register_operand" "")) - (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (const_int 1))) - (clobber (reg:CC 17))])] - "TARGET_64BIT" -{ - if (TARGET_SINGLE_STRINGOP || optimize_size) - { - emit_insn (gen_strsetqi_rex_1 (operands[0], operands[0], operands[1])); - DONE; - } -}) +(define_expand "strset_singleop" + [(parallel [(set (match_operand 1 "memory_operand" "") + (match_operand 2 "register_operand" "")) + (set (match_operand 0 "register_operand" "") + (match_operand 3 "" "")) + (use (reg:SI 19))])] + "TARGET_SINGLE_STRINGOP || optimize_size" + "") -(define_insn "strsetdi_rex_1" +(define_insn "*strsetdi_rex_1" [(set (mem:SI (match_operand:DI 1 "register_operand" "0")) (match_operand:SI 2 "register_operand" "a")) (set (match_operand:DI 0 "register_operand" "=D") @@ -15394,7 +15692,7 @@ (set_attr "memory" "store") (set_attr "mode" "DI")]) -(define_insn "strsetsi_1" +(define_insn "*strsetsi_1" [(set (mem:SI (match_operand:SI 1 "register_operand" "0")) (match_operand:SI 2 "register_operand" "a")) (set (match_operand:SI 0 "register_operand" "=D") @@ -15407,7 +15705,7 @@ (set_attr "memory" "store") (set_attr "mode" "SI")]) -(define_insn "strsetsi_rex_1" +(define_insn "*strsetsi_rex_1" [(set (mem:SI (match_operand:DI 1 "register_operand" "0")) (match_operand:SI 2 "register_operand" "a")) (set (match_operand:DI 0 "register_operand" "=D") @@ -15420,7 +15718,7 @@ (set_attr "memory" "store") (set_attr "mode" "SI")]) -(define_insn "strsethi_1" +(define_insn "*strsethi_1" [(set (mem:HI (match_operand:SI 1 "register_operand" "0")) (match_operand:HI 2 "register_operand" "a")) (set (match_operand:SI 0 "register_operand" "=D") @@ -15433,7 +15731,7 @@ (set_attr "memory" "store") (set_attr "mode" "HI")]) -(define_insn "strsethi_rex_1" +(define_insn "*strsethi_rex_1" [(set (mem:HI (match_operand:DI 1 "register_operand" "0")) (match_operand:HI 2 "register_operand" "a")) (set (match_operand:DI 0 "register_operand" "=D") @@ -15446,7 +15744,7 @@ (set_attr "memory" "store") (set_attr "mode" "HI")]) -(define_insn "strsetqi_1" +(define_insn "*strsetqi_1" [(set (mem:QI (match_operand:SI 1 "register_operand" "0")) (match_operand:QI 2 "register_operand" "a")) (set (match_operand:SI 0 "register_operand" "=D") @@ -15459,7 +15757,7 @@ (set_attr "memory" "store") (set_attr "mode" "QI")]) -(define_insn "strsetqi_rex_1" +(define_insn "*strsetqi_rex_1" [(set (mem:QI (match_operand:DI 1 "register_operand" "0")) (match_operand:QI 2 "register_operand" "a")) (set (match_operand:DI 0 "register_operand" "=D") @@ -15472,7 +15770,18 @@ (set_attr "memory" "store") (set_attr "mode" "QI")]) -(define_insn "rep_stosdi_rex64" +(define_expand "rep_stos" + [(parallel [(set (match_operand 1 "register_operand" "") (const_int 0)) + (set (match_operand 0 "register_operand" "") + (match_operand 4 "" "")) + (set (match_operand 2 "memory_operand" "") (const_int 0)) + (use (match_operand 3 "register_operand" "")) + (use (match_dup 1)) + (use (reg:SI 19))])] + "" + "") + +(define_insn "*rep_stosdi_rex64" [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0)) (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1") @@ -15490,7 +15799,7 @@ (set_attr "memory" "store") (set_attr "mode" "DI")]) -(define_insn "rep_stossi" +(define_insn "*rep_stossi" [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0)) (set (match_operand:SI 0 "register_operand" "=D") (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1") @@ -15508,7 +15817,7 @@ (set_attr "memory" "store") (set_attr "mode" "SI")]) -(define_insn "rep_stossi_rex64" +(define_insn "*rep_stossi_rex64" [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0)) (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (ashift:DI (match_operand:DI 4 "register_operand" "1") @@ -15526,7 +15835,7 @@ (set_attr "memory" "store") (set_attr "mode" "SI")]) -(define_insn "rep_stosqi" +(define_insn "*rep_stosqi" [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0)) (set (match_operand:SI 0 "register_operand" "=D") (plus:SI (match_operand:SI 3 "register_operand" "0") @@ -15543,7 +15852,7 @@ (set_attr "memory" "store") (set_attr "mode" "QI")]) -(define_insn "rep_stosqi_rex64" +(define_insn "*rep_stosqi_rex64" [(set (match_operand:DI 1 "register_operand" "=c") (const_int 0)) (set (match_operand:DI 0 "register_operand" "=D") (plus:DI (match_operand:DI 3 "register_operand" "0") @@ -15552,7 +15861,7 @@ (const_int 0)) (use (match_operand:QI 2 "register_operand" "a")) (use (match_dup 4)) - (use (reg:DI 19))] + (use (reg:SI 19))] "TARGET_64BIT" "{rep\;stosb|rep stosb}" [(set_attr "type" "str") @@ -15566,17 +15875,25 @@ (match_operand:BLK 2 "general_operand" ""))) (use (match_operand 3 "general_operand" "")) (use (match_operand 4 "immediate_operand" ""))] - "" + "! optimize_size || TARGET_INLINE_ALL_STRINGOPS" { rtx addr1, addr2, out, outlow, count, countreg, align; + /* Can't use this if the user has appropriated esi or edi. */ + if (global_regs[4] || global_regs[5]) + FAIL; + out = operands[0]; if (GET_CODE (out) != REG) out = gen_reg_rtx (SImode); addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0)); - + if (addr1 != XEXP (operands[1], 0)) + operands[1] = replace_equiv_address_nv (operands[1], addr1); + if (addr2 != XEXP (operands[2], 0)) + operands[2] = replace_equiv_address_nv (operands[2], addr2); + count = operands[3]; countreg = ix86_zero_extend_to_Pmode (count); @@ -15593,27 +15910,17 @@ emit_move_insn (operands[0], const0_rtx); DONE; } - if (TARGET_64BIT) - emit_insn (gen_cmpstrqi_nz_rex_1 (addr1, addr2, countreg, align, - addr1, addr2, countreg)); - else - emit_insn (gen_cmpstrqi_nz_1 (addr1, addr2, countreg, align, - addr1, addr2, countreg)); + emit_insn (gen_cmpstrqi_nz_1 (addr1, addr2, countreg, align, + operands[1], operands[2])); } else { if (TARGET_64BIT) - { - emit_insn (gen_cmpdi_1_rex64 (countreg, countreg)); - emit_insn (gen_cmpstrqi_rex_1 (addr1, addr2, countreg, align, - addr1, addr2, countreg)); - } + emit_insn (gen_cmpdi_1_rex64 (countreg, countreg)); else - { - emit_insn (gen_cmpsi_1 (countreg, countreg)); - emit_insn (gen_cmpstrqi_1 (addr1, addr2, countreg, align, - addr1, addr2, countreg)); - } + emit_insn (gen_cmpsi_1 (countreg, countreg)); + emit_insn (gen_cmpstrqi_1 (addr1, addr2, countreg, align, + operands[1], operands[2])); } outlow = gen_lowpart (QImode, out); @@ -15644,7 +15951,20 @@ ;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is ;; zero. Emit extra code to make sure that a zero-length compare is EQ. -(define_insn "cmpstrqi_nz_1" +(define_expand "cmpstrqi_nz_1" + [(parallel [(set (reg:CC 17) + (compare:CC (match_operand 4 "memory_operand" "") + (match_operand 5 "memory_operand" ""))) + (use (match_operand 2 "register_operand" "")) + (use (match_operand:SI 3 "immediate_operand" "")) + (use (reg:SI 19)) + (clobber (match_operand 0 "register_operand" "")) + (clobber (match_operand 1 "register_operand" "")) + (clobber (match_dup 2))])] + "" + "") + +(define_insn "*cmpstrqi_nz_1" [(set (reg:CC 17) (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0")) (mem:BLK (match_operand:SI 5 "register_operand" "1")))) @@ -15660,7 +15980,7 @@ (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -(define_insn "cmpstrqi_nz_rex_1" +(define_insn "*cmpstrqi_nz_rex_1" [(set (reg:CC 17) (compare:CC (mem:BLK (match_operand:DI 4 "register_operand" "0")) (mem:BLK (match_operand:DI 5 "register_operand" "1")))) @@ -15678,7 +15998,23 @@ ;; The same, but the count is not known to not be zero. -(define_insn "cmpstrqi_1" +(define_expand "cmpstrqi_1" + [(parallel [(set (reg:CC 17) + (if_then_else:CC (ne (match_operand 2 "register_operand" "") + (const_int 0)) + (compare:CC (match_operand 4 "memory_operand" "") + (match_operand 5 "memory_operand" "")) + (const_int 0))) + (use (match_operand:SI 3 "immediate_operand" "")) + (use (reg:CC 17)) + (use (reg:SI 19)) + (clobber (match_operand 0 "register_operand" "")) + (clobber (match_operand 1 "register_operand" "")) + (clobber (match_dup 2))])] + "" + "") + +(define_insn "*cmpstrqi_1" [(set (reg:CC 17) (if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2") (const_int 0)) @@ -15697,7 +16033,7 @@ (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -(define_insn "cmpstrqi_rex_1" +(define_insn "*cmpstrqi_rex_1" [(set (reg:CC 17) (if_then_else:CC (ne (match_operand:DI 6 "register_operand" "2") (const_int 0)) @@ -15742,7 +16078,15 @@ FAIL; }) -(define_insn "strlenqi_1" +(define_expand "strlenqi_1" + [(parallel [(set (match_operand 0 "register_operand" "") (match_operand 2 "" "")) + (use (reg:SI 19)) + (clobber (match_operand 1 "register_operand" "")) + (clobber (reg:CC 17))])] + "" + "") + +(define_insn "*strlenqi_1" [(set (match_operand:SI 0 "register_operand" "=&c") (unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1")) (match_operand:QI 2 "register_operand" "a") @@ -15757,7 +16101,7 @@ (set_attr "mode" "QI") (set_attr "prefix_rep" "1")]) -(define_insn "strlenqi_rex_1" +(define_insn "*strlenqi_rex_1" [(set (match_operand:DI 0 "register_operand" "=&c") (unspec:DI [(mem:BLK (match_operand:DI 5 "register_operand" "1")) (match_operand:QI 2 "register_operand" "a") @@ -15869,7 +16213,7 @@ (define_insn "x86_movdicc_0_m1_rex64" [(set (match_operand:DI 0 "register_operand" "=r") - (if_then_else:DI (ltu (reg:CC 17) (const_int 0)) + (if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "") (const_int -1) (const_int 0))) (clobber (reg:CC 17))] @@ -15884,7 +16228,7 @@ (set_attr "mode" "DI") (set_attr "length_immediate" "0")]) -(define_insn "*movdicc_c_rex64" +(define_insn "movdicc_c_rex64" [(set (match_operand:DI 0 "register_operand" "=r,r") (if_then_else:DI (match_operator 1 "ix86_comparison_operator" [(reg 17) (const_int 0)]) @@ -15912,7 +16256,7 @@ (define_insn "x86_movsicc_0_m1" [(set (match_operand:SI 0 "register_operand" "=r") - (if_then_else:SI (ltu (reg:CC 17) (const_int 0)) + (if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "") (const_int -1) (const_int 0))) (clobber (reg:CC 17))] @@ -15944,9 +16288,9 @@ (define_expand "movhicc" [(set (match_operand:HI 0 "register_operand" "") (if_then_else:HI (match_operand 1 "comparison_operator" "") - (match_operand:HI 2 "nonimmediate_operand" "") - (match_operand:HI 3 "nonimmediate_operand" "")))] - "TARGET_CMOVE && TARGET_HIMODE_MATH" + (match_operand:HI 2 "general_operand" "") + (match_operand:HI 3 "general_operand" "")))] + "TARGET_HIMODE_MATH" "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;") (define_insn "*movhicc_noc" @@ -15963,6 +16307,33 @@ [(set_attr "type" "icmov") (set_attr "mode" "HI")]) +(define_expand "movqicc" + [(set (match_operand:QI 0 "register_operand" "") + (if_then_else:QI (match_operand 1 "comparison_operator" "") + (match_operand:QI 2 "general_operand" "") + (match_operand:QI 3 "general_operand" "")))] + "TARGET_QIMODE_MATH" + "if (!ix86_expand_int_movcc (operands)) FAIL; DONE;") + +(define_insn_and_split "*movqicc_noc" + [(set (match_operand:QI 0 "register_operand" "=r,r") + (if_then_else:QI (match_operator 1 "ix86_comparison_operator" + [(match_operand 4 "flags_reg_operand" "") (const_int 0)]) + (match_operand:QI 2 "register_operand" "r,0") + (match_operand:QI 3 "register_operand" "0,r")))] + "TARGET_CMOVE && !TARGET_PARTIAL_REG_STALL" + "#" + "&& reload_completed" + [(set (match_dup 0) + (if_then_else:SI (match_op_dup 1 [(match_dup 4) (const_int 0)]) + (match_dup 2) + (match_dup 3)))] + "operands[0] = gen_lowpart (SImode, operands[0]); + operands[2] = gen_lowpart (SImode, operands[2]); + operands[3] = gen_lowpart (SImode, operands[3]);" + [(set_attr "type" "icmov") + (set_attr "mode" "SI")]) + (define_expand "movsfcc" [(set (match_operand:SF 0 "register_operand" "") (if_then_else:SF (match_operand 1 "comparison_operator" "") @@ -15972,11 +16343,11 @@ "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") (define_insn "*movsfcc_1" - [(set (match_operand:SF 0 "register_operand" "=f,f,r,r") + [(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f") (if_then_else:SF (match_operator 1 "fcmov_comparison_operator" [(reg 17) (const_int 0)]) - (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0") - (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))] + (match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0") + (match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))] "TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ @@ -15996,11 +16367,11 @@ "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") (define_insn "*movdfcc_1" - [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r") + [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" [(reg 17) (const_int 0)]) - (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0") - (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))] + (match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0") + (match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))] "!TARGET_64BIT && TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ @@ -16012,11 +16383,11 @@ (set_attr "mode" "DF")]) (define_insn "*movdfcc_1_rex64" - [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r") + [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,r#f,r#f") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" [(reg 17) (const_int 0)]) - (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0") - (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))] + (match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f") + (match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))] "TARGET_64BIT && TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ @@ -16030,7 +16401,7 @@ (define_split [(set (match_operand:DF 0 "register_and_not_any_fp_reg_operand" "") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" - [(match_operand 4 "" "") (const_int 0)]) + [(match_operand 4 "flags_reg_operand" "") (const_int 0)]) (match_operand:DF 2 "nonimmediate_operand" "") (match_operand:DF 3 "nonimmediate_operand" "")))] "!TARGET_64BIT && reload_completed" @@ -16051,14 +16422,6 @@ (if_then_else:XF (match_operand 1 "comparison_operator" "") (match_operand:XF 2 "register_operand" "") (match_operand:XF 3 "register_operand" "")))] - "!TARGET_64BIT && TARGET_CMOVE" - "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") - -(define_expand "movtfcc" - [(set (match_operand:TF 0 "register_operand" "") - (if_then_else:TF (match_operand 1 "comparison_operator" "") - (match_operand:TF 2 "register_operand" "") - (match_operand:TF 3 "register_operand" "")))] "TARGET_CMOVE" "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") @@ -16068,19 +16431,6 @@ [(reg 17) (const_int 0)]) (match_operand:XF 2 "register_operand" "f,0") (match_operand:XF 3 "register_operand" "0,f")))] - "!TARGET_64BIT && TARGET_CMOVE" - "@ - fcmov%F1\t{%2, %0|%0, %2} - fcmov%f1\t{%3, %0|%0, %3}" - [(set_attr "type" "fcmov") - (set_attr "mode" "XF")]) - -(define_insn "*movtfcc_1" - [(set (match_operand:TF 0 "register_operand" "=f,f") - (if_then_else:TF (match_operator 1 "fcmov_comparison_operator" - [(reg 17) (const_int 0)]) - (match_operand:TF 2 "register_operand" "f,0") - (match_operand:TF 3 "register_operand" "0,f")))] "TARGET_CMOVE" "@ fcmov%F1\t{%2, %0|%0, %2} @@ -16138,6 +16488,39 @@ (match_dup 1) (match_dup 2)))]) +;; Conditional addition patterns +(define_expand "addqicc" + [(match_operand:QI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:QI 2 "register_operand" "") + (match_operand:QI 3 "const_int_operand" "")] + "" + "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") + +(define_expand "addhicc" + [(match_operand:HI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:HI 2 "register_operand" "") + (match_operand:HI 3 "const_int_operand" "")] + "" + "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") + +(define_expand "addsicc" + [(match_operand:SI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "const_int_operand" "")] + "" + "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") + +(define_expand "adddicc" + [(match_operand:DI 0 "register_operand" "") + (match_operand 1 "comparison_operator" "") + (match_operand:DI 2 "register_operand" "") + (match_operand:DI 3 "const_int_operand" "")] + "TARGET_64BIT" + "if (!ix86_expand_int_addcc (operands)) FAIL; DONE;") + ;; We can't represent the LT test directly. Do this by swapping the operands. (define_split @@ -16236,7 +16619,7 @@ && operands_match_p (operands[2], operands[3])))" [(set (reg:CCFP 17) (compare:CCFP (match_dup 2) - (match_dup 2))) + (match_dup 1))) (set (match_dup 0) (if_then_else:DF (ge (reg:CCFP 17) (const_int 0)) (match_dup 1) @@ -16426,23 +16809,7 @@ ;; [(set (mem (plus (reg ebp) (const_int -160000))) (const_int 0))] ;; ;; in proper program order. -(define_expand "pro_epilogue_adjust_stack" - [(parallel [(set (match_operand:SI 0 "register_operand" "=r,r") - (plus:SI (match_operand:SI 1 "register_operand" "0,r") - (match_operand:SI 2 "immediate_operand" "i,i"))) - (clobber (reg:CC 17)) - (clobber (mem:BLK (scratch)))])] - "" -{ - if (TARGET_64BIT) - { - emit_insn (gen_pro_epilogue_adjust_stack_rex64 - (operands[0], operands[1], operands[2])); - DONE; - } -}) - -(define_insn "*pro_epilogue_adjust_stack_1" +(define_insn "pro_epilogue_adjust_stack_1" [(set (match_operand:SI 0 "register_operand" "=r,r") (plus:SI (match_operand:SI 1 "register_operand" "0,r") (match_operand:SI 2 "immediate_operand" "i,i"))) @@ -16498,6 +16865,8 @@ case TYPE_ALU: if (GET_CODE (operands[2]) == CONST_INT + /* Avoid overflows. */ + && ((INTVAL (operands[2]) & ((((unsigned int) 1) << 31) - 1))) && (INTVAL (operands[2]) == 128 || (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) != -128))) @@ -16524,6 +16893,30 @@ (const_string "lea"))) (set_attr "mode" "DI")]) +(define_insn "pro_epilogue_adjust_stack_rex64_2" + [(set (match_operand:DI 0 "register_operand" "=r,r") + (plus:DI (match_operand:DI 1 "register_operand" "0,r") + (match_operand:DI 3 "immediate_operand" "i,i"))) + (use (match_operand:DI 2 "register_operand" "r,r")) + (clobber (reg:CC 17)) + (clobber (mem:BLK (scratch)))] + "TARGET_64BIT" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + return "add{q}\t{%2, %0|%0, %2}"; + + case TYPE_LEA: + operands[2] = gen_rtx_PLUS (DImode, operands[1], operands[2]); + return "lea{q}\t{%a2, %0|%0, %a2}"; + + default: + abort (); + } +} + [(set_attr "type" "alu,lea") + (set_attr "mode" "DI")]) ;; Placeholder for the conditional moves. This one is split either to SSE ;; based moves emulation or to usual cmove sequence. Little bit unfortunate @@ -16544,6 +16937,12 @@ (clobber (reg:CC 17))] "TARGET_SSE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM) + /* Avoid combine from being smart and converting min/max + instruction patterns into conditional moves. */ + && ((GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != GT + && GET_CODE (operands[1]) != UNLE && GET_CODE (operands[1]) != UNGE) + || !rtx_equal_p (operands[4], operands[2]) + || !rtx_equal_p (operands[5], operands[3])) && (!TARGET_IEEE_FP || (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE))" "#") @@ -16571,6 +16970,12 @@ (clobber (reg:CC 17))] "TARGET_SSE2 && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM) + /* Avoid combine from being smart and converting min/max + instruction patterns into conditional moves. */ + && ((GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != GT + && GET_CODE (operands[1]) != UNLE && GET_CODE (operands[1]) != UNGE) + || !rtx_equal_p (operands[4], operands[2]) + || !rtx_equal_p (operands[5], operands[3])) && (!TARGET_IEEE_FP || (GET_CODE (operands[1]) != EQ && GET_CODE (operands[1]) != NE))" "#") @@ -16609,7 +17014,7 @@ DONE; }) -;; Split SSE based conditional move into seqence: +;; Split SSE based conditional move into sequence: ;; cmpCC op0, op4 - set op0 to 0 or ffffffff depending on the comparison ;; and op2, op0 - zero op2 if comparison was false ;; nand op0, op3 - load op3 to op0 if comparison was false @@ -16632,10 +17037,22 @@ (set (subreg:TI (match_dup 0) 0) (ior:TI (subreg:TI (match_dup 6) 0) (subreg:TI (match_dup 7) 0)))] { - /* If op2 == op3, op3 will be clobbered before it is used. - This should be optimized out though. */ + if (GET_MODE (operands[2]) == DFmode + && TARGET_SSE_PARTIAL_REGS && !optimize_size) + { + rtx op = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0); + emit_insn (gen_sse2_unpcklpd (op, op, op)); + op = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0); + emit_insn (gen_sse2_unpcklpd (op, op, op)); + } + + /* If op2 == op3, op3 would be clobbered before it is used. */ if (operands_match_p (operands[2], operands[3])) - abort (); + { + emit_move_insn (operands[0], operands[2]); + DONE; + } + PUT_MODE (operands[1], GET_MODE (operands[0])); if (operands_match_p (operands[0], operands[4])) operands[6] = operands[4], operands[7] = operands[2]; @@ -16643,7 +17060,7 @@ operands[6] = operands[2], operands[7] = operands[4]; }) -;; Special case of conditional move we can handle effectivly. +;; Special case of conditional move we can handle effectively. ;; Do not brother with the integer/floating point case, since these are ;; bot considerably slower, unlike in the generic case. (define_insn "*sse_movsfcc_const0_1" @@ -16738,8 +17155,22 @@ || const0_operand (operands[3], GET_MODE (operands[0])))" [(set (match_dup 0) (match_op_dup 1 [(match_dup 0) (match_dup 5)])) (set (subreg:TI (match_dup 0) 0) (and:TI (match_dup 6) - (subreg:TI (match_dup 7) 0)))] + (match_dup 7)))] { + if (TARGET_SSE_PARTIAL_REGS && !optimize_size + && GET_MODE (operands[2]) == DFmode) + { + if (REG_P (operands[2])) + { + rtx op = simplify_gen_subreg (V2DFmode, operands[2], DFmode, 0); + emit_insn (gen_sse2_unpcklpd (op, op, op)); + } + if (REG_P (operands[3])) + { + rtx op = simplify_gen_subreg (V2DFmode, operands[3], DFmode, 0); + emit_insn (gen_sse2_unpcklpd (op, op, op)); + } + } PUT_MODE (operands[1], GET_MODE (operands[0])); if (!sse_comparison_operator (operands[1], VOIDmode) || !rtx_equal_p (operands[0], operands[4])) @@ -16762,39 +17193,71 @@ operands[7] = operands[2]; operands[6] = gen_rtx_SUBREG (TImode, operands[0], 0); } + operands[7] = simplify_gen_subreg (TImode, operands[7], + GET_MODE (operands[7]), 0); }) (define_expand "allocate_stack_worker" [(match_operand:SI 0 "register_operand" "")] "TARGET_STACK_PROBE" { - if (TARGET_64BIT) - emit_insn (gen_allocate_stack_worker_rex64 (operands[0])); + if (reload_completed) + { + if (TARGET_64BIT) + emit_insn (gen_allocate_stack_worker_rex64_postreload (operands[0])); + else + emit_insn (gen_allocate_stack_worker_postreload (operands[0])); + } else - emit_insn (gen_allocate_stack_worker_1 (operands[0])); + { + if (TARGET_64BIT) + emit_insn (gen_allocate_stack_worker_rex64 (operands[0])); + else + emit_insn (gen_allocate_stack_worker_1 (operands[0])); + } DONE; }) (define_insn "allocate_stack_worker_1" - [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] UNSPEC_STACK_PROBE) + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")] + UNSPECV_STACK_PROBE) (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0))) - (clobber (match_dup 0)) + (clobber (match_scratch:SI 1 "=0")) (clobber (reg:CC 17))] "!TARGET_64BIT && TARGET_STACK_PROBE" "call\t__alloca" [(set_attr "type" "multi") (set_attr "length" "5")]) +(define_expand "allocate_stack_worker_postreload" + [(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")] + UNSPECV_STACK_PROBE) + (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0))) + (clobber (match_dup 0)) + (clobber (reg:CC 17))])] + "" + "") + (define_insn "allocate_stack_worker_rex64" - [(unspec:DI [(match_operand:DI 0 "register_operand" "a")] UNSPEC_STACK_PROBE) + [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")] + UNSPECV_STACK_PROBE) (set (reg:DI 7) (minus:DI (reg:DI 7) (match_dup 0))) - (clobber (match_dup 0)) + (clobber (match_scratch:DI 1 "=0")) (clobber (reg:CC 17))] "TARGET_64BIT && TARGET_STACK_PROBE" "call\t__alloca" [(set_attr "type" "multi") (set_attr "length" "5")]) +(define_expand "allocate_stack_worker_rex64_postreload" + [(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")] + UNSPECV_STACK_PROBE) + (set (reg:DI 7) (minus:DI (reg:DI 7) (match_dup 0))) + (clobber (match_dup 0)) + (clobber (reg:CC 17))])] + "" + "") + (define_expand "allocate_stack" [(parallel [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (reg:SI 7) @@ -17025,7 +17488,7 @@ [(parallel [(set (match_dup 2) (const_int 0)) (clobber (reg:CC 17))]) (set (match_dup 0) (match_dup 1))] - "operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));") + "operands[2] = gen_lowpart (SImode, operands[1]);") (define_peephole2 [(match_scratch:QI 1 "q") @@ -17039,7 +17502,7 @@ [(parallel [(set (match_dup 2) (const_int 0)) (clobber (reg:CC 17))]) (set (match_dup 0) (match_dup 1))] - "operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));") + "operands[2] = gen_lowpart (SImode, operands[1]);") (define_peephole2 [(match_scratch:SI 2 "r") @@ -17085,7 +17548,7 @@ ;; NOT is not pairable on Pentium, while XOR is, but one byte longer. ;; Don't split NOTs with a displacement operand, because resulting XOR -;; will not be pariable anyway. +;; will not be pairable anyway. ;; ;; On AMD K6, NOT is vector decoded with memory operand that can not be ;; represented using a modRM byte. The XOR replacement is long decoded, @@ -17294,8 +17757,8 @@ && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (const_int 0)) (clobber (reg:CC 17))])] - "operands[0] = gen_rtx_REG (GET_MODE (operands[0]) == DImode ? DImode : SImode, - true_regnum (operands[0]));") + "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode, + operands[0]);") (define_peephole2 [(set (strict_low_part (match_operand 0 "register_operand" "")) @@ -17318,8 +17781,8 @@ && peep2_regno_dead_p (0, FLAGS_REG)" [(parallel [(set (match_dup 0) (const_int -1)) (clobber (reg:CC 17))])] - "operands[0] = gen_rtx_REG (GET_MODE (operands[0]) == DImode ? DImode : SImode, - true_regnum (operands[0]));") + "operands[0] = gen_lowpart (GET_MODE (operands[0]) == DImode ? DImode : SImode, + operands[0]);") ;; Attempt to convert simple leas to adds. These can be created by ;; move expanders. @@ -17693,6 +18156,102 @@ (set (reg:DI 7) (plus:DI (reg:DI 7) (const_int 8)))])] "") +;; Imul $32bit_imm, mem, reg is vector decoded, while +;; imul $32bit_imm, reg, reg is direct decoded. +(define_peephole2 + [(match_scratch:DI 3 "r") + (parallel [(set (match_operand:DI 0 "register_operand" "") + (mult:DI (match_operand:DI 1 "memory_operand" "") + (match_operand:DI 2 "immediate_operand" ""))) + (clobber (reg:CC 17))])] + "TARGET_K8 && !optimize_size + && (GET_CODE (operands[2]) != CONST_INT + || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + [(set (match_dup 3) (match_dup 1)) + (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2))) + (clobber (reg:CC 17))])] +"") + +(define_peephole2 + [(match_scratch:SI 3 "r") + (parallel [(set (match_operand:SI 0 "register_operand" "") + (mult:SI (match_operand:SI 1 "memory_operand" "") + (match_operand:SI 2 "immediate_operand" ""))) + (clobber (reg:CC 17))])] + "TARGET_K8 && !optimize_size + && (GET_CODE (operands[2]) != CONST_INT + || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + [(set (match_dup 3) (match_dup 1)) + (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2))) + (clobber (reg:CC 17))])] +"") + +(define_peephole2 + [(match_scratch:SI 3 "r") + (parallel [(set (match_operand:DI 0 "register_operand" "") + (zero_extend:DI + (mult:SI (match_operand:SI 1 "memory_operand" "") + (match_operand:SI 2 "immediate_operand" "")))) + (clobber (reg:CC 17))])] + "TARGET_K8 && !optimize_size + && (GET_CODE (operands[2]) != CONST_INT + || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + [(set (match_dup 3) (match_dup 1)) + (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2)))) + (clobber (reg:CC 17))])] +"") + +;; imul $8/16bit_imm, regmem, reg is vector decoded. +;; Convert it into imul reg, reg +;; It would be better to force assembler to encode instruction using long +;; immediate, but there is apparently no way to do so. +(define_peephole2 + [(parallel [(set (match_operand:DI 0 "register_operand" "") + (mult:DI (match_operand:DI 1 "nonimmediate_operand" "") + (match_operand:DI 2 "const_int_operand" ""))) + (clobber (reg:CC 17))]) + (match_scratch:DI 3 "r")] + "TARGET_K8 && !optimize_size + && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')" + [(set (match_dup 3) (match_dup 2)) + (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3))) + (clobber (reg:CC 17))])] +{ + if (!rtx_equal_p (operands[0], operands[1])) + emit_move_insn (operands[0], operands[1]); +}) + +(define_peephole2 + [(parallel [(set (match_operand:SI 0 "register_operand" "") + (mult:SI (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "const_int_operand" ""))) + (clobber (reg:CC 17))]) + (match_scratch:SI 3 "r")] + "TARGET_K8 && !optimize_size + && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')" + [(set (match_dup 3) (match_dup 2)) + (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3))) + (clobber (reg:CC 17))])] +{ + if (!rtx_equal_p (operands[0], operands[1])) + emit_move_insn (operands[0], operands[1]); +}) + +(define_peephole2 + [(parallel [(set (match_operand:HI 0 "register_operand" "") + (mult:HI (match_operand:HI 1 "nonimmediate_operand" "") + (match_operand:HI 2 "immediate_operand" ""))) + (clobber (reg:CC 17))]) + (match_scratch:HI 3 "r")] + "TARGET_K8 && !optimize_size" + [(set (match_dup 3) (match_dup 2)) + (parallel [(set (match_dup 0) (mult:HI (match_dup 0) (match_dup 3))) + (clobber (reg:CC 17))])] +{ + if (!rtx_equal_p (operands[0], operands[1])) + emit_move_insn (operands[0], operands[1]); +}) + ;; Call-value patterns last so that the wildcard operand does not ;; disrupt insn-recog's switch tables. @@ -17763,19 +18322,23 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:SI 1 "call_insn_operand" "rsm")) (match_operand:SI 2 "" "")))] - "!TARGET_64BIT" + "!SIBLING_CALL_P (insn) && !TARGET_64BIT" { if (constant_call_address_operand (operands[1], QImode)) - { - if (SIBLING_CALL_P (insn)) - return "jmp\t%P1"; - else - return "call\t%P1"; - } - if (SIBLING_CALL_P (insn)) - return "jmp\t%*%1"; - else - return "call\t%*%1"; + return "call\t%P1"; + return "call\t%*%1"; +} + [(set_attr "type" "callv")]) + +(define_insn "*sibcall_value_1" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:SI 1 "sibcall_insn_operand" "s,c,d,a")) + (match_operand:SI 2 "" "")))] + "SIBLING_CALL_P (insn) && !TARGET_64BIT" +{ + if (constant_call_address_operand (operands[1], QImode)) + return "jmp\t%P1"; + return "jmp\t%*%1"; } [(set_attr "type" "callv")]) @@ -17783,21 +18346,29 @@ [(set (match_operand 0 "" "") (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rsm")) (match_operand:DI 2 "" "")))] - "TARGET_64BIT" + "!SIBLING_CALL_P (insn) && TARGET_64BIT" { if (constant_call_address_operand (operands[1], QImode)) - { - if (SIBLING_CALL_P (insn)) - return "jmp\t%P1"; - else - return "call\t%P1"; - } - if (SIBLING_CALL_P (insn)) - return "jmp\t%A1"; - else - return "call\t%A1"; + return "call\t%P1"; + return "call\t%A1"; } [(set_attr "type" "callv")]) + +(define_insn "*sibcall_value_1_rex64" + [(set (match_operand 0 "" "") + (call (mem:QI (match_operand:DI 1 "constant_call_address_operand" "")) + (match_operand:DI 2 "" "")))] + "SIBLING_CALL_P (insn) && TARGET_64BIT" + "jmp\t%P1" + [(set_attr "type" "callv")]) + +(define_insn "*sibcall_value_1_rex64_v" + [(set (match_operand 0 "" "") + (call (mem:QI (reg:DI 40)) + (match_operand:DI 1 "" "")))] + "SIBLING_CALL_P (insn) && TARGET_64BIT" + "jmp\t*%%r11" + [(set_attr "type" "callv")]) (define_insn "trap" [(trap_if (const_int 1) (const_int 5))] @@ -17842,7 +18413,7 @@ { operands[2] = gen_label_rtx (); output_asm_insn ("j%c0\t%l2\; int\t%1", operands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (operands[2])); RET; }) @@ -17855,37 +18426,120 @@ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m") (match_operand:V4SF 1 "vector_move_operand" "C,xm,x"))] "TARGET_SSE" - ;; @@@ let's try to use movaps here. "@ - xorps\t%0, %0 - movaps\t{%1, %0|%0, %1} - movaps\t{%1, %0|%0, %1}" + xorps\t%0, %0 + movaps\t{%1, %0|%0, %1} + movaps\t{%1, %0|%0, %1}" [(set_attr "type" "ssemov") (set_attr "mode" "V4SF")]) +(define_split + [(set (match_operand:V4SF 0 "register_operand" "") + (match_operand:V4SF 1 "zero_extended_scalar_load_operand" ""))] + "TARGET_SSE" + [(set (match_dup 0) + (vec_merge:V4SF + (vec_duplicate:V4SF (match_dup 1)) + (match_dup 2) + (const_int 1)))] +{ + operands[1] = simplify_gen_subreg (SFmode, operands[1], V4SFmode, 0); + operands[2] = CONST0_RTX (V4SFmode); +}) + (define_insn "movv4si_internal" [(set (match_operand:V4SI 0 "nonimmediate_operand" "=x,x,m") (match_operand:V4SI 1 "vector_move_operand" "C,xm,x"))] "TARGET_SSE" - ;; @@@ let's try to use movaps here. - "@ - xorps\t%0, %0 - movaps\t{%1, %0|%0, %1} - movaps\t{%1, %0|%0, %1}" +{ + switch (which_alternative) + { + case 0: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 1: + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + abort (); + } +} [(set_attr "type" "ssemov") - (set_attr "mode" "V4SF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "0,1") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "2") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "TI"))] + (const_string "TI")))]) (define_insn "movv2di_internal" [(set (match_operand:V2DI 0 "nonimmediate_operand" "=x,x,m") (match_operand:V2DI 1 "vector_move_operand" "C,xm,x"))] "TARGET_SSE" - ;; @@@ let's try to use movaps here. - "@ - pxor\t%0, %0 - movdqa\t{%1, %0|%0, %1} - movdqa\t{%1, %0|%0, %1}" +{ + switch (which_alternative) + { + case 0: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 1: + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + abort (); + } +} [(set_attr "type" "ssemov") - (set_attr "mode" "V4SF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "0,1") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "2") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "TI"))] + (const_string "TI")))]) + +(define_split + [(set (match_operand:V2DF 0 "register_operand" "") + (match_operand:V2DF 1 "zero_extended_scalar_load_operand" ""))] + "TARGET_SSE2" + [(set (match_dup 0) + (vec_merge:V2DF + (vec_duplicate:V2DF (match_dup 1)) + (match_dup 2) + (const_int 1)))] +{ + operands[1] = simplify_gen_subreg (DFmode, operands[1], V2DFmode, 0); + operands[2] = CONST0_RTX (V2DFmode); +}) (define_insn "movv8qi_internal" [(set (match_operand:V8QI 0 "nonimmediate_operand" "=y,y,m") @@ -17947,41 +18601,140 @@ DONE; }) +(define_expand "movtf" + [(set (match_operand:TF 0 "nonimmediate_operand" "") + (match_operand:TF 1 "nonimmediate_operand" ""))] + "TARGET_64BIT" +{ + if (TARGET_64BIT) + ix86_expand_move (TFmode, operands); + else + ix86_expand_vector_move (TFmode, operands); + DONE; +}) + (define_insn "movv2df_internal" [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m") (match_operand:V2DF 1 "vector_move_operand" "C,xm,x"))] "TARGET_SSE2 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - xorpd\t%0, %0 - movapd\t{%1, %0|%0, %1} - movapd\t{%1, %0|%0, %1}" +{ + switch (which_alternative) + { + case 0: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "xorpd\t%0, %0"; + case 1: + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movapd\t{%1, %0|%0, %1}"; + default: + abort (); + } +} [(set_attr "type" "ssemov") - (set_attr "mode" "V2DF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "0,1") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "V2DF")) + (eq_attr "alternative" "2") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "V2DF"))] + (const_string "V2DF")))]) (define_insn "movv8hi_internal" [(set (match_operand:V8HI 0 "nonimmediate_operand" "=x,x,m") (match_operand:V8HI 1 "vector_move_operand" "C,xm,x"))] "TARGET_SSE2 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - xorps\t%0, %0 - movaps\t{%1, %0|%0, %1} - movaps\t{%1, %0|%0, %1}" +{ + switch (which_alternative) + { + case 0: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 1: + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + abort (); + } +} [(set_attr "type" "ssemov") - (set_attr "mode" "V4SF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "0,1") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "2") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "TI"))] + (const_string "TI")))]) (define_insn "movv16qi_internal" [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,x,m") - (match_operand:V16QI 1 "vector_move_operand" "C,xm,x"))] + (match_operand:V16QI 1 "nonimmediate_operand" "C,xm,x"))] "TARGET_SSE2 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - xorps\t%0, %0 - movaps\t{%1, %0|%0, %1} - movaps\t{%1, %0|%0, %1}" +{ + switch (which_alternative) + { + case 0: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 1: + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + abort (); + } +} [(set_attr "type" "ssemov") - (set_attr "mode" "V4SF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "0,1") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "2") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "TI"))] + (const_string "TI")))]) (define_expand "movv2df" [(set (match_operand:V2DF 0 "nonimmediate_operand" "") @@ -18073,6 +18826,12 @@ DONE; }) +(define_insn "*pushti" + [(set (match_operand:TI 0 "push_operand" "=<") + (match_operand:TI 1 "register_operand" "x"))] + "TARGET_SSE" + "#") + (define_insn "*pushv2df" [(set (match_operand:V2DF 0 "push_operand" "=<") (match_operand:V2DF 1 "register_operand" "x"))] @@ -18156,152 +18915,132 @@ operands[3] = GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0])));") -(define_insn_and_split "*pushti" - [(set (match_operand:TI 0 "push_operand" "=<") - (match_operand:TI 1 "nonmemory_operand" "x"))] - "TARGET_SSE" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:TI (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "multi")]) - -(define_insn_and_split "*pushv2df" - [(set (match_operand:V2DF 0 "push_operand" "=<") - (match_operand:V2DF 1 "nonmemory_operand" "x"))] - "TARGET_SSE2" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:V2DF (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "multi")]) - -(define_insn_and_split "*pushv2di" - [(set (match_operand:V2DI 0 "push_operand" "=<") - (match_operand:V2DI 1 "nonmemory_operand" "x"))] - "TARGET_SSE2" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:V2DI (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "multi")]) - -(define_insn_and_split "*pushv8hi" - [(set (match_operand:V8HI 0 "push_operand" "=<") - (match_operand:V8HI 1 "nonmemory_operand" "x"))] - "TARGET_SSE2" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:V8HI (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "multi")]) - -(define_insn_and_split "*pushv16qi" - [(set (match_operand:V16QI 0 "push_operand" "=<") - (match_operand:V16QI 1 "nonmemory_operand" "x"))] - "TARGET_SSE2" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:V16QI (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "multi")]) - -(define_insn_and_split "*pushv4sf" - [(set (match_operand:V4SF 0 "push_operand" "=<") - (match_operand:V4SF 1 "nonmemory_operand" "x"))] - "TARGET_SSE" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:V4SF (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "multi")]) - -(define_insn_and_split "*pushv4si" - [(set (match_operand:V4SI 0 "push_operand" "=<") - (match_operand:V4SI 1 "nonmemory_operand" "x"))] - "TARGET_SSE" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -16))) - (set (mem:V4SI (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "multi")]) - -(define_insn_and_split "*pushv2si" - [(set (match_operand:V2SI 0 "push_operand" "=<") - (match_operand:V2SI 1 "nonmemory_operand" "y"))] - "TARGET_MMX" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) - (set (mem:V2SI (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "mmx")]) - -(define_insn_and_split "*pushv4hi" - [(set (match_operand:V4HI 0 "push_operand" "=<") - (match_operand:V4HI 1 "nonmemory_operand" "y"))] - "TARGET_MMX" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) - (set (mem:V4HI (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "mmx")]) - -(define_insn_and_split "*pushv8qi" - [(set (match_operand:V8QI 0 "push_operand" "=<") - (match_operand:V8QI 1 "nonmemory_operand" "y"))] - "TARGET_MMX" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) - (set (mem:V8QI (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "mmx")]) - -(define_insn_and_split "*pushv2sf" - [(set (match_operand:V2SF 0 "push_operand" "=<") - (match_operand:V2SF 1 "nonmemory_operand" "y"))] - "TARGET_3DNOW" - "#" - "" - [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) - (set (mem:V2SF (reg:SI 7)) (match_dup 1))] - "" - [(set_attr "type" "mmx")]) - (define_insn "movti_internal" [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m") (match_operand:TI 1 "vector_move_operand" "C,xm,x"))] "TARGET_SSE && !TARGET_64BIT && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - xorps\t%0, %0 - movaps\t{%1, %0|%0, %1} - movaps\t{%1, %0|%0, %1}" +{ + switch (which_alternative) + { + case 0: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 1: + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + abort (); + } +} [(set_attr "type" "ssemov,ssemov,ssemov") - (set_attr "mode" "V4SF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "0,1") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "2") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI"))] + (const_string "TI")))]) (define_insn "*movti_rex64" - [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,mx,x") - (match_operand:TI 1 "general_operand" "riFo,riF,C,x,m"))] + [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o,x,x,xm") + (match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))] "TARGET_64BIT && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "@ - # - # - xorps\t%0, %0 - movaps\\t{%1, %0|%0, %1} - movaps\\t{%1, %0|%0, %1}" +{ + switch (which_alternative) + { + case 0: + case 1: + return "#"; + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 3: + case 4: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + abort (); + } +} [(set_attr "type" "*,*,ssemov,ssemov,ssemov") - (set_attr "mode" "V4SF")]) + (set (attr "mode") + (cond [(eq_attr "alternative" "2,3") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "4") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "TI"))] + (const_string "DI")))]) + +(define_insn "*movtf_rex64" + [(set (match_operand:TF 0 "nonimmediate_operand" "=r,o,x,x,xm") + (match_operand:TF 1 "general_operand" "riFo,riF,C,xm,x"))] + "TARGET_64BIT + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" +{ + switch (which_alternative) + { + case 0: + case 1: + return "#"; + case 2: + if (get_attr_mode (insn) == MODE_V4SF) + return "xorps\t%0, %0"; + else + return "pxor\t%0, %0"; + case 3: + case 4: + if (get_attr_mode (insn) == MODE_V4SF) + return "movaps\t{%1, %0|%0, %1}"; + else + return "movdqa\t{%1, %0|%0, %1}"; + default: + abort (); + } +} + [(set_attr "type" "*,*,ssemov,ssemov,ssemov") + (set (attr "mode") + (cond [(eq_attr "alternative" "2,3") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")) + (eq_attr "alternative" "4") + (if_then_else + (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES") + (const_int 0)) + (ne (symbol_ref "optimize_size") + (const_int 0))) + (const_string "V4SF") + (const_string "TI"))] + (const_string "DI")))]) (define_split [(set (match_operand:TI 0 "nonimmediate_operand" "") @@ -18311,6 +19050,14 @@ [(const_int 0)] "ix86_split_long_move (operands); DONE;") +(define_split + [(set (match_operand:TF 0 "nonimmediate_operand" "") + (match_operand:TF 1 "general_operand" ""))] + "reload_completed && !SSE_REG_P (operands[0]) + && !SSE_REG_P (operands[1])" + [(const_int 0)] + "ix86_split_long_move (operands); DONE;") + ;; These two patterns are useful for specifying exactly whether to use ;; movaps or movups (define_expand "sse_movaps" @@ -18690,14 +19437,14 @@ ;; on integral types. We deal with this by representing the floating point ;; logical as logical on arguments casted to TImode as this is what hardware ;; really does. Unfortunately hardware requires the type information to be -;; present and thus we must avoid subregs from being simplified and elliminated +;; present and thus we must avoid subregs from being simplified and eliminated ;; in later compilation phases. ;; ;; We have following variants from each instruction: ;; sse_andsf3 - the operation taking V4SF vector operands ;; and doing TImode cast on them ;; *sse_andsf3_memory - the operation taking one memory operand casted to -;; TImode, since backend insist on elliminating casts +;; TImode, since backend insist on eliminating casts ;; on memory operands ;; sse_andti3_sf_1 - the operation taking SF scalar operands. ;; We can not accept memory operand here as instruction reads @@ -18705,7 +19452,7 @@ ;; scalar float operations that expands to logicals (fabs) ;; sse_andti3_sf_2 - the operation taking SF scalar input and TImode ;; memory operand. Eventually combine can be able -;; to synthetize these using splitter. +;; to synthesize these using splitter. ;; sse2_anddf3, *sse2_anddf3_memory ;; ;; @@ -18963,7 +19710,7 @@ (define_insn "sse2_nandv2di3" [(set (match_operand:V2DI 0 "register_operand" "=x") - (and:V2DI (not:V2DI (match_operand:V2DI 1 "nonimmediate_operand" "0")) + (and:V2DI (not:V2DI (match_operand:V2DI 1 "register_operand" "0")) (match_operand:V2DI 2 "nonimmediate_operand" "xm")))] "TARGET_SSE2 && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" @@ -19015,12 +19762,26 @@ ;; this insn. (define_insn "sse_clrv4sf" [(set (match_operand:V4SF 0 "register_operand" "=x") - (unspec:V4SF [(const_int 0)] UNSPEC_NOP))] + (match_operand:V4SF 1 "const0_operand" "X"))] "TARGET_SSE" - "xorps\t{%0, %0|%0, %0}" +{ + if (get_attr_mode (insn) == MODE_TI) + return "pxor\t{%0, %0|%0, %0}"; + else + return "xorps\t{%0, %0|%0, %0}"; +} [(set_attr "type" "sselog") (set_attr "memory" "none") - (set_attr "mode" "V4SF")]) + (set (attr "mode") + (if_then_else + (and (and (ne (symbol_ref "TARGET_SSE_LOAD0_BY_PXOR") + (const_int 0)) + (ne (symbol_ref "TARGET_SSE2") + (const_int 0))) + (eq (symbol_ref "optimize_size") + (const_int 0))) + (const_string "TI") + (const_string "V4SF")))]) ;; Use xor, but don't show input operands so they aren't live before ;; this insn. @@ -19103,7 +19864,7 @@ (parallel [(const_int 0)]))))] "TARGET_SSE" "comiss\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecmp") + [(set_attr "type" "ssecomi") (set_attr "mode" "SF")]) (define_insn "sse_ucomi" @@ -19116,7 +19877,7 @@ (parallel [(const_int 0)]))))] "TARGET_SSE" "ucomiss\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecmp") + [(set_attr "type" "ssecomi") (set_attr "mode" "SF")]) @@ -19241,15 +20002,16 @@ (set_attr "mode" "SF")]) (define_insn "cvtsi2ss" - [(set (match_operand:V4SF 0 "register_operand" "=x") + [(set (match_operand:V4SF 0 "register_operand" "=x,x") (vec_merge:V4SF - (match_operand:V4SF 1 "register_operand" "0") + (match_operand:V4SF 1 "register_operand" "0,0") (vec_duplicate:V4SF - (float:SF (match_operand:SI 2 "nonimmediate_operand" "rm"))) + (float:SF (match_operand:SI 2 "nonimmediate_operand" "r,rm"))) (const_int 14)))] "TARGET_SSE" "cvtsi2ss\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "vector,double") (set_attr "mode" "SF")]) (define_insn "cvtsi2ssq" @@ -19261,19 +20023,20 @@ (const_int 14)))] "TARGET_SSE && TARGET_64BIT" "cvtsi2ssq\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "athlon_decode" "vector,vector") + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "vector,double") (set_attr "mode" "SF")]) (define_insn "cvtss2si" - [(set (match_operand:SI 0 "register_operand" "=r") + [(set (match_operand:SI 0 "register_operand" "=r,r") (vec_select:SI - (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")) + (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "x,m")) (parallel [(const_int 0)])))] "TARGET_SSE" "cvtss2si\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "SF")]) + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "double,vector") + (set_attr "mode" "SI")]) (define_insn "cvtss2siq" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -19282,20 +20045,21 @@ (parallel [(const_int 0)])))] "TARGET_SSE" "cvtss2siq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "athlon_decode" "vector,vector") - (set_attr "mode" "SF")]) + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "double,vector") + (set_attr "mode" "DI")]) (define_insn "cvttss2si" - [(set (match_operand:SI 0 "register_operand" "=r") + [(set (match_operand:SI 0 "register_operand" "=r,r") (vec_select:SI - (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] + (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "x,xm")] UNSPEC_FIX) (parallel [(const_int 0)])))] "TARGET_SSE" "cvttss2si\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "SF")]) + [(set_attr "type" "sseicvt") + (set_attr "mode" "SF") + (set_attr "athlon_decode" "double,vector")]) (define_insn "cvttss2siq" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -19305,9 +20069,9 @@ (parallel [(const_int 0)])))] "TARGET_SSE && TARGET_64BIT" "cvttss2siq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") (set_attr "mode" "SF") - (set_attr "athlon_decode" "vector,vector")]) + (set_attr "athlon_decode" "double,vector")]) ;; MMX insns @@ -19639,7 +20403,7 @@ (vec_merge:V4HI (match_operand:V4HI 1 "register_operand" "0") (vec_duplicate:V4HI (truncate:HI (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (match_operand:SI 3 "immediate_operand" "i")))] + (match_operand:SI 3 "const_0_to_15_operand" "N")))] "TARGET_SSE || TARGET_3DNOW_A" "pinsrw\t{%3, %2, %0|%0, %2, %3}" [(set_attr "type" "mmxcvt") @@ -19649,7 +20413,7 @@ [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (vec_select:HI (match_operand:V4HI 1 "register_operand" "y") (parallel - [(match_operand:SI 2 "immediate_operand" "i")]))))] + [(match_operand:SI 2 "const_0_to_3_operand" "N")]))))] "TARGET_SSE || TARGET_3DNOW_A" "pextrw\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "mmxcvt") @@ -20100,7 +20864,7 @@ output_asm_insn (\"rex\", operands); output_asm_insn (\"movaps\\t{%5, %4|%4, %5}\", operands); } - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[3])); RET; } @@ -20330,7 +21094,7 @@ [(set_attr "type" "mmxshft") (set_attr "mode" "TI")]) -;; 3DNow reciprical and sqrt +;; 3DNow reciprocal and sqrt (define_insn "pfrcpv2sf2" [(set (match_operand:V2SF 0 "register_operand" "=y") @@ -20724,7 +21488,7 @@ (parallel [(const_int 0)]))))] "TARGET_SSE2" "comisd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecmp") + [(set_attr "type" "ssecomi") (set_attr "mode" "DF")]) (define_insn "sse2_ucomi" @@ -20737,7 +21501,7 @@ (parallel [(const_int 0)]))))] "TARGET_SSE2" "ucomisd\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecmp") + [(set_attr "type" "ssecomi") (set_attr "mode" "DF")]) ;; SSE Strange Moves. @@ -20901,31 +21665,34 @@ ;; Conversions between SI and DF (define_insn "cvtsd2si" - [(set (match_operand:SI 0 "register_operand" "=r") - (fix:SI (vec_select:DF (match_operand:V2DF 1 "register_operand" "xm") + [(set (match_operand:SI 0 "register_operand" "=r,r") + (fix:SI (vec_select:DF (match_operand:V2DF 1 "register_operand" "x,m") (parallel [(const_int 0)]))))] "TARGET_SSE2" "cvtsd2si\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "double,vector") (set_attr "mode" "SI")]) (define_insn "cvtsd2siq" - [(set (match_operand:DI 0 "register_operand" "=r") - (fix:DI (vec_select:DF (match_operand:V2DF 1 "register_operand" "xm") + [(set (match_operand:DI 0 "register_operand" "=r,r") + (fix:DI (vec_select:DF (match_operand:V2DF 1 "register_operand" "x,m") (parallel [(const_int 0)]))))] "TARGET_SSE2 && TARGET_64BIT" "cvtsd2siq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "SI")]) + [(set_attr "type" "sseicvt") + (set_attr "athlon_decode" "double,vector") + (set_attr "mode" "DI")]) (define_insn "cvttsd2si" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "xm") + [(set (match_operand:SI 0 "register_operand" "=r,r") + (unspec:SI [(vec_select:DF (match_operand:V2DF 1 "register_operand" "x,xm") (parallel [(const_int 0)]))] UNSPEC_FIX))] "TARGET_SSE2" "cvttsd2si\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "SI")]) + [(set_attr "type" "sseicvt") + (set_attr "mode" "SI") + (set_attr "athlon_decode" "double,vector")]) (define_insn "cvttsd2siq" [(set (match_operand:DI 0 "register_operand" "=r,r") @@ -20933,21 +21700,22 @@ (parallel [(const_int 0)]))] UNSPEC_FIX))] "TARGET_SSE2 && TARGET_64BIT" "cvttsd2siq\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") (set_attr "mode" "DI") - (set_attr "athlon_decode" "vector,vector")]) + (set_attr "athlon_decode" "double,vector")]) (define_insn "cvtsi2sd" - [(set (match_operand:V2DF 0 "register_operand" "=x") - (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0") + [(set (match_operand:V2DF 0 "register_operand" "=x,x") + (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0,0") (vec_duplicate:V2DF (float:DF - (match_operand:SI 2 "nonimmediate_operand" "rm"))) + (match_operand:SI 2 "nonimmediate_operand" "r,rm"))) (const_int 2)))] "TARGET_SSE2" "cvtsi2sd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "DF")]) + [(set_attr "type" "sseicvt") + (set_attr "mode" "DF") + (set_attr "athlon_decode" "double,direct")]) (define_insn "cvtsi2sdq" [(set (match_operand:V2DF 0 "register_operand" "=x,x") @@ -20958,22 +21726,23 @@ (const_int 2)))] "TARGET_SSE2 && TARGET_64BIT" "cvtsi2sdq\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") + [(set_attr "type" "sseicvt") (set_attr "mode" "DF") - (set_attr "athlon_decode" "vector,direct")]) + (set_attr "athlon_decode" "double,direct")]) ;; Conversions between SF and DF (define_insn "cvtsd2ss" - [(set (match_operand:V4SF 0 "register_operand" "=x") - (vec_merge:V4SF (match_operand:V4SF 1 "register_operand" "0") + [(set (match_operand:V4SF 0 "register_operand" "=x,x") + (vec_merge:V4SF (match_operand:V4SF 1 "register_operand" "0,0") (vec_duplicate:V4SF (float_truncate:V2SF - (match_operand:V2DF 2 "register_operand" "xm"))) + (match_operand:V2DF 2 "nonimmediate_operand" "x,xm"))) (const_int 14)))] "TARGET_SSE2" "cvtsd2ss\t{%2, %0|%0, %2}" [(set_attr "type" "ssecvt") + (set_attr "athlon_decode" "vector,double") (set_attr "mode" "SF")]) (define_insn "cvtss2sd" @@ -20981,7 +21750,7 @@ (vec_merge:V2DF (match_operand:V2DF 1 "register_operand" "0") (float_extend:V2DF (vec_select:V2SF - (match_operand:V4SF 2 "register_operand" "xm") + (match_operand:V4SF 2 "nonimmediate_operand" "xm") (parallel [(const_int 0) (const_int 1)]))) (const_int 2)))] @@ -21257,10 +22026,20 @@ (define_insn "sse2_clrti" [(set (match_operand:TI 0 "register_operand" "=x") (const_int 0))] "TARGET_SSE2" - "pxor\t{%0, %0|%0, %0}" - [(set_attr "type" "sseiadd") +{ + if (get_attr_mode (insn) == MODE_TI) + return "pxor\t%0, %0"; + else + return "xorps\t%0, %0"; +} + [(set_attr "type" "ssemov") (set_attr "memory" "none") - (set_attr "mode" "TI")]) + (set (attr "mode") + (if_then_else + (ne (symbol_ref "optimize_size") + (const_int 0)) + (const_string "V4SF") + (const_string "TI")))]) ;; MMX unsigned averages/sum of absolute differences @@ -21320,7 +22099,7 @@ (vec_duplicate:V8HI (truncate:HI (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (match_operand:SI 3 "immediate_operand" "i")))] + (match_operand:SI 3 "const_0_to_255_operand" "N")))] "TARGET_SSE2" "pinsrw\t{%3, %2, %0|%0, %2, %3}" [(set_attr "type" "ssecvt") @@ -21331,7 +22110,7 @@ (zero_extend:SI (vec_select:HI (match_operand:V8HI 1 "register_operand" "x") (parallel - [(match_operand:SI 2 "immediate_operand" "i")]))))] + [(match_operand:SI 2 "const_0_to_7_operand" "N")]))))] "TARGET_SSE2" "pextrw\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "ssecvt") @@ -21468,7 +22247,7 @@ (define_insn "ashrv8hi3" [(set (match_operand:V8HI 0 "register_operand" "=x") (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:TI 2 "nonmemory_operand" "xi")))] + (match_operand:SI 2 "nonmemory_operand" "xi")))] "TARGET_SSE2" "psraw\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21477,7 +22256,7 @@ (define_insn "ashrv4si3" [(set (match_operand:V4SI 0 "register_operand" "=x") (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:TI 2 "nonmemory_operand" "xi")))] + (match_operand:SI 2 "nonmemory_operand" "xi")))] "TARGET_SSE2" "psrad\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21486,7 +22265,7 @@ (define_insn "lshrv8hi3" [(set (match_operand:V8HI 0 "register_operand" "=x") (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:TI 2 "nonmemory_operand" "xi")))] + (match_operand:SI 2 "nonmemory_operand" "xi")))] "TARGET_SSE2" "psrlw\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21495,7 +22274,7 @@ (define_insn "lshrv4si3" [(set (match_operand:V4SI 0 "register_operand" "=x") (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:TI 2 "nonmemory_operand" "xi")))] + (match_operand:SI 2 "nonmemory_operand" "xi")))] "TARGET_SSE2" "psrld\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21504,7 +22283,7 @@ (define_insn "lshrv2di3" [(set (match_operand:V2DI 0 "register_operand" "=x") (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0") - (match_operand:TI 2 "nonmemory_operand" "xi")))] + (match_operand:SI 2 "nonmemory_operand" "xi")))] "TARGET_SSE2" "psrlq\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21513,7 +22292,7 @@ (define_insn "ashlv8hi3" [(set (match_operand:V8HI 0 "register_operand" "=x") (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0") - (match_operand:TI 2 "nonmemory_operand" "xi")))] + (match_operand:SI 2 "nonmemory_operand" "xi")))] "TARGET_SSE2" "psllw\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21522,7 +22301,7 @@ (define_insn "ashlv4si3" [(set (match_operand:V4SI 0 "register_operand" "=x") (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0") - (match_operand:TI 2 "nonmemory_operand" "xi")))] + (match_operand:SI 2 "nonmemory_operand" "xi")))] "TARGET_SSE2" "pslld\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21531,7 +22310,7 @@ (define_insn "ashlv2di3" [(set (match_operand:V2DI 0 "register_operand" "=x") (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0") - (match_operand:TI 2 "nonmemory_operand" "xi")))] + (match_operand:SI 2 "nonmemory_operand" "xi")))] "TARGET_SSE2" "psllq\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21540,7 +22319,7 @@ (define_insn "ashrv8hi3_ti" [(set (match_operand:V8HI 0 "register_operand" "=x") (ashiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] + (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] "TARGET_SSE2" "psraw\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21549,7 +22328,7 @@ (define_insn "ashrv4si3_ti" [(set (match_operand:V4SI 0 "register_operand" "=x") (ashiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] + (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] "TARGET_SSE2" "psrad\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21558,7 +22337,7 @@ (define_insn "lshrv8hi3_ti" [(set (match_operand:V8HI 0 "register_operand" "=x") (lshiftrt:V8HI (match_operand:V8HI 1 "register_operand" "0") - (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] + (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] "TARGET_SSE2" "psrlw\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21567,7 +22346,7 @@ (define_insn "lshrv4si3_ti" [(set (match_operand:V4SI 0 "register_operand" "=x") (lshiftrt:V4SI (match_operand:V4SI 1 "register_operand" "0") - (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] + (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] "TARGET_SSE2" "psrld\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21576,7 +22355,7 @@ (define_insn "lshrv2di3_ti" [(set (match_operand:V2DI 0 "register_operand" "=x") (lshiftrt:V2DI (match_operand:V2DI 1 "register_operand" "0") - (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] + (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] "TARGET_SSE2" "psrlq\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21585,7 +22364,7 @@ (define_insn "ashlv8hi3_ti" [(set (match_operand:V8HI 0 "register_operand" "=x") (ashift:V8HI (match_operand:V8HI 1 "register_operand" "0") - (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] + (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] "TARGET_SSE2" "psllw\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21594,7 +22373,7 @@ (define_insn "ashlv4si3_ti" [(set (match_operand:V4SI 0 "register_operand" "=x") (ashift:V4SI (match_operand:V4SI 1 "register_operand" "0") - (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] + (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] "TARGET_SSE2" "pslld\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21603,7 +22382,7 @@ (define_insn "ashlv2di3_ti" [(set (match_operand:V2DI 0 "register_operand" "=x") (ashift:V2DI (match_operand:V2DI 1 "register_operand" "0") - (subreg:TI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] + (subreg:SI (match_operand:V2DI 2 "nonmemory_operand" "xi") 0)))] "TARGET_SSE2" "psllq\t{%2, %0|%0, %2}" [(set_attr "type" "sseishft") @@ -21640,26 +22419,26 @@ (define_insn "sse2_unpckhpd" [(set (match_operand:V2DF 0 "register_operand" "=x") (vec_concat:V2DF - (vec_select:V2DF (match_operand:V2DF 1 "register_operand" "0") - (parallel [(const_int 1)])) - (vec_select:V2DF (match_operand:V2DF 2 "register_operand" "x") - (parallel [(const_int 0)]))))] + (vec_select:DF (match_operand:V2DF 1 "register_operand" "0") + (parallel [(const_int 1)])) + (vec_select:DF (match_operand:V2DF 2 "register_operand" "x") + (parallel [(const_int 1)]))))] "TARGET_SSE2" "unpckhpd\t{%2, %0|%0, %2}" [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) + (set_attr "mode" "V2DF")]) (define_insn "sse2_unpcklpd" [(set (match_operand:V2DF 0 "register_operand" "=x") (vec_concat:V2DF - (vec_select:V2DF (match_operand:V2DF 1 "register_operand" "0") - (parallel [(const_int 0)])) - (vec_select:V2DF (match_operand:V2DF 2 "register_operand" "x") - (parallel [(const_int 1)]))))] + (vec_select:DF (match_operand:V2DF 1 "register_operand" "0") + (parallel [(const_int 0)])) + (vec_select:DF (match_operand:V2DF 2 "register_operand" "x") + (parallel [(const_int 0)]))))] "TARGET_SSE2" "unpcklpd\t{%2, %0|%0, %2}" [(set_attr "type" "ssecvt") - (set_attr "mode" "TI")]) + (set_attr "mode" "V2DF")]) ;; MMX pack/unpack insns. @@ -21975,17 +22754,6 @@ [(set_attr "type" "ssecvt") (set_attr "mode" "V2DF")]) -(define_insn "sse2_movlpd" - [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m") - (vec_merge:V2DF - (match_operand:V2DF 1 "nonimmediate_operand" "0,0") - (match_operand:V2DF 2 "nonimmediate_operand" "m,x") - (const_int 1)))] - "TARGET_SSE2 && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)" - "movlpd\t{%2, %0|%0, %2}" - [(set_attr "type" "ssecvt") - (set_attr "mode" "V2DF")]) - (define_expand "sse2_loadsd" [(match_operand:V2DF 0 "register_operand" "") (match_operand:DF 1 "memory_operand" "")] @@ -22008,15 +22776,17 @@ (set_attr "mode" "DF")]) (define_insn "sse2_movsd" - [(set (match_operand:V2DF 0 "register_operand" "=x") + [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m") (vec_merge:V2DF - (match_operand:V2DF 1 "register_operand" "0") - (match_operand:V2DF 2 "register_operand" "x") + (match_operand:V2DF 1 "nonimmediate_operand" "0,0,0") + (match_operand:V2DF 2 "nonimmediate_operand" "x,m,x") (const_int 1)))] - "TARGET_SSE2" - "movsd\t{%2, %0|%0, %2}" + "TARGET_SSE2 && ix86_binary_operator_ok (UNKNOWN, V2DFmode, operands)" + "@movsd\t{%2, %0|%0, %2} + movlpd\t{%2, %0|%0, %2} + movlpd\t{%2, %0|%0, %2}" [(set_attr "type" "ssecvt") - (set_attr "mode" "DF")]) + (set_attr "mode" "DF,V2DF,V2DF")]) (define_insn "sse2_storesd" [(set (match_operand:DF 0 "memory_operand" "=m") @@ -22082,13 +22852,13 @@ [(set_attr "type" "sse") (set_attr "memory" "unknown")]) -;; PNI +;; SSE3 (define_insn "mwait" [(unspec_volatile [(match_operand:SI 0 "register_operand" "a") (match_operand:SI 1 "register_operand" "c")] UNSPECV_MWAIT)] - "TARGET_PNI" + "TARGET_SSE3" "mwait\t%0, %1" [(set_attr "length" "3")]) @@ -22097,18 +22867,18 @@ (match_operand:SI 1 "register_operand" "c") (match_operand:SI 2 "register_operand" "d")] UNSPECV_MONITOR)] - "TARGET_PNI" + "TARGET_SSE3" "monitor\t%0, %1, %2" [(set_attr "length" "3")]) -;; PNI arithmetic +;; SSE3 arithmetic (define_insn "addsubv4sf3" [(set (match_operand:V4SF 0 "register_operand" "=x") (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0") (match_operand:V4SF 2 "nonimmediate_operand" "xm")] UNSPEC_ADDSUB))] - "TARGET_PNI" + "TARGET_SSE3" "addsubps\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") (set_attr "mode" "V4SF")]) @@ -22118,7 +22888,7 @@ (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0") (match_operand:V2DF 2 "nonimmediate_operand" "xm")] UNSPEC_ADDSUB))] - "TARGET_PNI" + "TARGET_SSE3" "addsubpd\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") (set_attr "mode" "V2DF")]) @@ -22128,7 +22898,7 @@ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0") (match_operand:V4SF 2 "nonimmediate_operand" "xm")] UNSPEC_HADD))] - "TARGET_PNI" + "TARGET_SSE3" "haddps\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") (set_attr "mode" "V4SF")]) @@ -22138,7 +22908,7 @@ (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0") (match_operand:V2DF 2 "nonimmediate_operand" "xm")] UNSPEC_HADD))] - "TARGET_PNI" + "TARGET_SSE3" "haddpd\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") (set_attr "mode" "V2DF")]) @@ -22148,7 +22918,7 @@ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0") (match_operand:V4SF 2 "nonimmediate_operand" "xm")] UNSPEC_HSUB))] - "TARGET_PNI" + "TARGET_SSE3" "hsubps\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") (set_attr "mode" "V4SF")]) @@ -22158,7 +22928,7 @@ (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0") (match_operand:V2DF 2 "nonimmediate_operand" "xm")] UNSPEC_HSUB))] - "TARGET_PNI" + "TARGET_SSE3" "hsubpd\t{%2, %0|%0, %2}" [(set_attr "type" "sseadd") (set_attr "mode" "V2DF")]) @@ -22167,7 +22937,7 @@ [(set (match_operand:V4SF 0 "register_operand" "=x") (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_MOVSHDUP))] - "TARGET_PNI" + "TARGET_SSE3" "movshdup\t{%1, %0|%0, %1}" [(set_attr "type" "sse") (set_attr "mode" "V4SF")]) @@ -22176,7 +22946,7 @@ [(set (match_operand:V4SF 0 "register_operand" "=x") (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_MOVSLDUP))] - "TARGET_PNI" + "TARGET_SSE3" "movsldup\t{%1, %0|%0, %1}" [(set_attr "type" "sse") (set_attr "mode" "V4SF")]) @@ -22185,7 +22955,7 @@ [(set (match_operand:V16QI 0 "register_operand" "=x") (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "m")] UNSPEC_LDQQU))] - "TARGET_PNI" + "TARGET_SSE3" "lddqu\t{%1, %0|%0, %1}" [(set_attr "type" "ssecvt") (set_attr "mode" "TI")]) @@ -22193,7 +22963,7 @@ (define_insn "loadddup" [(set (match_operand:V2DF 0 "register_operand" "=x") (vec_duplicate:V2DF (match_operand:DF 1 "memory_operand" "m")))] - "TARGET_PNI" + "TARGET_SSE3" "movddup\t{%1, %0|%0, %1}" [(set_attr "type" "ssecvt") (set_attr "mode" "DF")]) @@ -22203,7 +22973,7 @@ (vec_duplicate:V2DF (vec_select:DF (match_operand:V2DF 1 "register_operand" "x") (parallel [(const_int 0)]))))] - "TARGET_PNI" + "TARGET_SSE3" "movddup\t{%1, %0|%0, %1}" [(set_attr "type" "ssecvt") (set_attr "mode" "DF")]) |