diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-08-29 12:37:05 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-08-29 12:37:05 +0000 |
commit | 12cb78d1cca1387a092ec0bd49c250340bff4afc (patch) | |
tree | 1eab97da96906e0a2786d51d9f25f20de02befcf /gcc/config/arm/arm.c | |
parent | 31879e18aea3222fe3e56f2c0319c9f230645ff3 (diff) | |
download | gcc-12cb78d1cca1387a092ec0bd49c250340bff4afc.tar.gz |
2012-08-29 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 190745 using svnmerge, notably
C++ conversion.
[gcc/]
2012-08-29 Basile Starynkevitch <basile@starynkevitch.net>
{{merging with trunk, converted to C++}}
* melt-runtime.h (MELT_FLEXIBLE_DIM): Set when C++.
* melt-runtime.c (melt_tempdir_path): Don't use choose_tmpdir from
libiberty.
(meltgc_start_module_by_index): Use address-of & on VEC_index.
(melt_really_initialize): When printing builtin settings, handle
GCC 4.8 as with implicit ENABLE_BUILD_WITH_CXX.
(meltgc_out_edge): Provide additional flag TDF_DETAILS for dump_edge_info.
(melt_val2passflag): Handle PROP_referenced_vars only when defined.
* melt-module.mk: Use GCCMELT_COMPILER instead of GCCMELT_CC.
* melt-build-script.tpl: Transmit GCCMELT_COMPILER on every make
using melt-module.mk and improve the error message.
* melt-build-script.sh: Regenerate.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@190778 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r-- | gcc/config/arm/arm.c | 684 |
1 files changed, 191 insertions, 493 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 6472b6147cd..2805b7c7bf3 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -55,6 +55,7 @@ #include "libfuncs.h" #include "params.h" #include "opts.h" +#include "dumpfile.h" /* Forward definitions of types. */ typedef struct minipool_node Mnode; @@ -86,7 +87,6 @@ inline static int thumb1_index_register_rtx_p (rtx, int); static bool arm_legitimate_address_p (enum machine_mode, rtx, bool); static int thumb_far_jump_used_p (void); static bool thumb_force_lr_save (void); -static rtx emit_sfm (int, int); static unsigned arm_size_return_regs (void); static bool arm_assemble_integer (rtx, unsigned int, int); static void arm_print_operand (FILE *, rtx, int); @@ -236,6 +236,7 @@ static int arm_issue_rate (void); static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED; static bool arm_output_addr_const_extra (FILE *, rtx); static bool arm_allocate_stack_slots_for_args (void); +static bool arm_warn_func_return (tree); static const char *arm_invalid_parameter_type (const_tree t); static const char *arm_invalid_return_type (const_tree t); static tree arm_promoted_type (const_tree t); @@ -254,6 +255,7 @@ static bool arm_array_mode_supported_p (enum machine_mode, unsigned HOST_WIDE_INT); static enum machine_mode arm_preferred_simd_mode (enum machine_mode); static bool arm_class_likely_spilled_p (reg_class_t); +static HOST_WIDE_INT arm_vector_alignment (const_tree type); static bool arm_vector_alignment_reachable (const_tree type, bool is_packed); static bool arm_builtin_support_vector_misalignment (enum machine_mode mode, const_tree type, @@ -458,6 +460,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_TRAMPOLINE_ADJUST_ADDRESS #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arm_trampoline_adjust_address +#undef TARGET_WARN_FUNC_RETURN +#define TARGET_WARN_FUNC_RETURN arm_warn_func_return + #undef TARGET_DEFAULT_SHORT_ENUMS #define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums @@ -602,6 +607,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_CLASS_LIKELY_SPILLED_P #define TARGET_CLASS_LIKELY_SPILLED_P arm_class_likely_spilled_p +#undef TARGET_VECTOR_ALIGNMENT +#define TARGET_VECTOR_ALIGNMENT arm_vector_alignment + #undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE \ arm_vector_alignment_reachable @@ -661,7 +669,7 @@ static int thumb_call_reg_needed; #define FL_STRONG (1 << 8) /* StrongARM */ #define FL_ARCH5E (1 << 9) /* DSP extensions to v5 */ #define FL_XSCALE (1 << 10) /* XScale */ -#define FL_CIRRUS (1 << 11) /* Cirrus/DSP. */ +/* spare (1 << 11) */ #define FL_ARCH6 (1 << 12) /* Architecture rel 6. Adds media instructions. */ #define FL_VFPV2 (1 << 13) /* Vector Floating Point V2. */ @@ -760,9 +768,6 @@ int arm_ld_sched = 0; /* Nonzero if this chip is a StrongARM. */ int arm_tune_strongarm = 0; -/* Nonzero if this chip is a Cirrus variant. */ -int arm_arch_cirrus = 0; - /* Nonzero if this chip supports Intel Wireless MMX technology. */ int arm_arch_iwmmxt = 0; @@ -878,7 +883,8 @@ const struct tune_params arm_slowmul_tune = 5, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, true, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ }; const struct tune_params arm_fastmul_tune = @@ -889,7 +895,8 @@ const struct tune_params arm_fastmul_tune = 5, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, true, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ }; /* StrongARM has early execution of branches, so a sequence that is worth @@ -903,7 +910,8 @@ const struct tune_params arm_strongarm_tune = 3, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, true, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ }; const struct tune_params arm_xscale_tune = @@ -914,7 +922,8 @@ const struct tune_params arm_xscale_tune = 3, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, true, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ }; const struct tune_params arm_9e_tune = @@ -925,7 +934,8 @@ const struct tune_params arm_9e_tune = 5, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, true, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ }; const struct tune_params arm_v6t2_tune = @@ -936,7 +946,8 @@ const struct tune_params arm_v6t2_tune = 5, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, false, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ }; /* Generic Cortex tuning. Use more specific tunings if appropriate. */ @@ -948,7 +959,20 @@ const struct tune_params arm_cortex_tune = 5, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, false, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ +}; + +const struct tune_params arm_cortex_a15_tune = +{ + arm_9e_rtx_costs, + NULL, + 1, /* Constant limit. */ + 5, /* Max cond insns. */ + ARM_PREFETCH_NOT_BENEFICIAL, + false, /* Prefer constant pool. */ + arm_default_branch_cost, + true /* Prefer LDRD/STRD. */ }; /* Branches can be dual-issued on Cortex-A5, so conditional execution is @@ -962,7 +986,8 @@ const struct tune_params arm_cortex_a5_tune = 1, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, false, /* Prefer constant pool. */ - arm_cortex_a5_branch_cost + arm_cortex_a5_branch_cost, + false /* Prefer LDRD/STRD. */ }; const struct tune_params arm_cortex_a9_tune = @@ -973,7 +998,8 @@ const struct tune_params arm_cortex_a9_tune = 5, /* Max cond insns. */ ARM_PREFETCH_BENEFICIAL(4,32,32), false, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ }; const struct tune_params arm_fa726te_tune = @@ -984,7 +1010,8 @@ const struct tune_params arm_fa726te_tune = 5, /* Max cond insns. */ ARM_PREFETCH_NOT_BENEFICIAL, true, /* Prefer constant pool. */ - arm_default_branch_cost + arm_default_branch_cost, + false /* Prefer LDRD/STRD. */ }; @@ -1714,7 +1741,6 @@ arm_option_override (void) arm_arch7em = (insn_flags & FL_ARCH7EM) != 0; arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0; arm_arch_xscale = (insn_flags & FL_XSCALE) != 0; - arm_arch_cirrus = (insn_flags & FL_CIRRUS) != 0; arm_ld_sched = (tune_flags & FL_LDSCHED) != 0; arm_tune_strongarm = (tune_flags & FL_STRONG) != 0; @@ -1774,10 +1800,7 @@ arm_option_override (void) #ifdef FPUTYPE_DEFAULT target_fpu_name = FPUTYPE_DEFAULT; #else - if (arm_arch_cirrus) - target_fpu_name = "maverick"; - else - target_fpu_name = "fpe2"; + target_fpu_name = "vfp"; #endif ok = opt_enum_arg_to_value (OPT_mfpu_, target_fpu_name, &arm_fpu_index, @@ -1789,19 +1812,6 @@ arm_option_override (void) switch (arm_fpu_desc->model) { - case ARM_FP_MODEL_FPA: - if (arm_fpu_desc->rev == 2) - arm_fpu_attr = FPU_FPE2; - else if (arm_fpu_desc->rev == 3) - arm_fpu_attr = FPU_FPE3; - else - arm_fpu_attr = FPU_FPA; - break; - - case ARM_FP_MODEL_MAVERICK: - arm_fpu_attr = FPU_MAVERICK; - break; - case ARM_FP_MODEL_VFP: arm_fpu_attr = FPU_VFP; break; @@ -1810,10 +1820,6 @@ arm_option_override (void) gcc_unreachable(); } - if (TARGET_AAPCS_BASED - && (arm_fpu_desc->model == ARM_FP_MODEL_FPA)) - error ("FPA is unsupported in the AAPCS"); - if (TARGET_AAPCS_BASED) { if (TARGET_CALLER_INTERWORKING) @@ -1823,11 +1829,6 @@ arm_option_override (void) error ("AAPCS does not support -mcallee-super-interworking"); } - /* FPA and iWMMXt are incompatible because the insn encodings overlap. - VFP and iWMMXt however can coexist. */ - if (TARGET_IWMMXT && TARGET_HARD_FLOAT && !TARGET_VFP) - error ("iWMMXt and non-VFP floating point unit are incompatible"); - /* iWMMXt and NEON are incompatible. */ if (TARGET_IWMMXT && TARGET_NEON) error ("iWMMXt and NEON are incompatible"); @@ -1866,11 +1867,9 @@ arm_option_override (void) arm_pcs_default = ARM_PCS_ATPCS; } - /* For arm2/3 there is no need to do any scheduling if there is only - a floating point emulator, or we are doing software floating-point. */ - if ((TARGET_SOFT_FLOAT - || (TARGET_FPA && arm_fpu_desc->rev)) - && (tune_flags & FL_MODE32) == 0) + /* For arm2/3 there is no need to do any scheduling if we are doing + software floating-point. */ + if (TARGET_SOFT_FLOAT && (tune_flags & FL_MODE32) == 0) flag_schedule_insns = flag_schedule_insns_after_reload = 0; /* Use the cp15 method if it is available. */ @@ -2040,6 +2039,11 @@ arm_option_override (void) global_options.x_param_values, global_options_set.x_param_values); + /* Use the alternative scheduling-pressure algorithm by default. */ + maybe_set_param_value (PARAM_SCHED_PRESSURE_ALGORITHM, 2, + global_options.x_param_values, + global_options_set.x_param_values); + /* Register global variables with the garbage collector. */ arm_add_gc_roots (); } @@ -2172,6 +2176,14 @@ arm_allocate_stack_slots_for_args (void) return !IS_NAKED (arm_current_func_type ()); } +static bool +arm_warn_func_return (tree decl) +{ + /* Naked functions are implemented entirely in assembly, including the + return sequence, so suppress warnings about this. */ + return lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) == NULL_TREE; +} + /* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. @@ -2362,14 +2374,8 @@ use_return_insn (int iscond, rtx sibling) if (saved_int_regs && !(saved_int_regs & (1 << LR_REGNUM))) return 0; - /* Can't be done if any of the FPA regs are pushed, + /* Can't be done if any of the VFP regs are pushed, since this also requires an insn. */ - if (TARGET_HARD_FLOAT && TARGET_FPA) - for (regno = FIRST_FPA_REGNUM; regno <= LAST_FPA_REGNUM; regno++) - if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) - return 0; - - /* Likewise VFP regs. */ if (TARGET_HARD_FLOAT && TARGET_VFP) for (regno = FIRST_VFP_REGNUM; regno <= LAST_VFP_REGNUM; regno++) if (df_regs_ever_live_p (regno) && !call_used_regs[regno]) @@ -2976,6 +2982,31 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond, return 1; } + /* On targets with UXTH/UBFX, we can deal with AND (2^N)-1 in a single + insn. */ + if (code == AND && (i = exact_log2 (remainder + 1)) > 0 + && (arm_arch_thumb2 || (i == 16 && arm_arch6 && mode == SImode))) + { + if (generate) + { + if (mode == SImode && i == 16) + /* Use UXTH in preference to UBFX, since on Thumb2 it's a + smaller insn. */ + emit_constant_insn (cond, + gen_zero_extendhisi2 + (target, gen_lowpart (HImode, source))); + else + /* Extz only supports SImode, but we can coerce the operands + into that mode. */ + emit_constant_insn (cond, + gen_extzv_t2 (gen_lowpart (SImode, target), + gen_lowpart (SImode, source), + GEN_INT (i), const0_rtx)); + } + + return 1; + } + /* Calculate a few attributes that may be useful for specific optimizations. */ /* Count number of leading zeros. */ @@ -3494,11 +3525,6 @@ arm_canonicalize_comparison (enum rtx_code code, rtx *op0, rtx *op1) { rtx tem; - /* To keep things simple, always use the Cirrus cfcmp64 if it is - available. */ - if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK) - return code; - if (code == GT || code == LE || (!TARGET_ARM && (code == GTU || code == LEU))) { @@ -3748,16 +3774,6 @@ arm_libcall_value_1 (enum machine_mode mode) { if (TARGET_AAPCS_BASED) return aapcs_libcall_value (mode); - else if (TARGET_32BIT - && TARGET_HARD_FLOAT_ABI - && TARGET_FPA - && GET_MODE_CLASS (mode) == MODE_FLOAT) - return gen_rtx_REG (mode, FIRST_FPA_REGNUM); - else if (TARGET_32BIT - && TARGET_HARD_FLOAT_ABI - && TARGET_MAVERICK - && GET_MODE_CLASS (mode) == MODE_FLOAT) - return gen_rtx_REG (mode, FIRST_CIRRUS_FP_REGNUM); else if (TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (mode)) return gen_rtx_REG (mode, FIRST_IWMMXT_REGNUM); @@ -3795,16 +3811,8 @@ arm_function_value_regno_p (const unsigned int regno) && TARGET_VFP && TARGET_HARD_FLOAT && regno == FIRST_VFP_REGNUM) - || (TARGET_32BIT - && TARGET_HARD_FLOAT_ABI - && TARGET_MAVERICK - && regno == FIRST_CIRRUS_FP_REGNUM) || (TARGET_IWMMXT_ABI - && regno == FIRST_IWMMXT_REGNUM) - || (TARGET_32BIT - && TARGET_HARD_FLOAT_ABI - && TARGET_FPA - && regno == FIRST_FPA_REGNUM)) + && regno == FIRST_IWMMXT_REGNUM)) return true; return false; @@ -3819,15 +3827,8 @@ arm_apply_result_size (void) if (TARGET_32BIT) { - if (TARGET_HARD_FLOAT_ABI) - { - if (TARGET_VFP) - size += 32; - if (TARGET_FPA) - size += 12; - if (TARGET_MAVERICK) - size += 8; - } + if (TARGET_HARD_FLOAT_ABI && TARGET_VFP) + size += 32; if (TARGET_IWMMXT_ABI) size += 8; } @@ -3978,28 +3979,6 @@ arm_return_in_memory (const_tree type, const_tree fntype) return true; } -/* Indicate whether or not words of a double are in big-endian order. */ - -int -arm_float_words_big_endian (void) -{ - if (TARGET_MAVERICK) - return 0; - - /* For FPA, float words are always big-endian. For VFP, floats words - follow the memory system mode. */ - - if (TARGET_FPA) - { - return 1; - } - - if (TARGET_VFP) - return (TARGET_BIG_END ? 1 : 0); - - return 1; -} - const struct pcs_attribute_arg { const char *arg; @@ -5879,9 +5858,8 @@ arm_legitimate_index_p (enum machine_mode mode, rtx index, RTX_CODE outer, /* Standard coprocessor addressing modes. */ if (TARGET_HARD_FLOAT - && (TARGET_VFP || TARGET_FPA || TARGET_MAVERICK) - && (mode == SFmode || mode == DFmode - || (TARGET_MAVERICK && mode == DImode))) + && TARGET_VFP + && (mode == SFmode || mode == DFmode)) return (code == CONST_INT && INTVAL (index) < 1024 && INTVAL (index) > -1024 && (INTVAL (index) & 3) == 0); @@ -6000,9 +5978,8 @@ thumb2_legitimate_index_p (enum machine_mode mode, rtx index, int strict_p) /* ??? Combine arm and thumb2 coprocessor addressing modes. */ /* Standard coprocessor addressing modes. */ if (TARGET_HARD_FLOAT - && (TARGET_VFP || TARGET_FPA || TARGET_MAVERICK) - && (mode == SFmode || mode == DFmode - || (TARGET_MAVERICK && mode == DImode))) + && TARGET_VFP + && (mode == SFmode || mode == DFmode)) return (code == CONST_INT && INTVAL (index) < 1024 /* Thumb-2 allows only > -256 index range for it's core register load/stores. Since we allow SF/DF in core registers, we have @@ -6715,9 +6692,8 @@ arm_legitimize_reload_address (rtx *p, /* Detect coprocessor load/stores. */ bool coproc_p = ((TARGET_HARD_FLOAT - && (TARGET_VFP || TARGET_FPA || TARGET_MAVERICK) - && (mode == SFmode || mode == DFmode - || (mode == DImode && TARGET_MAVERICK))) + && TARGET_VFP + && (mode == SFmode || mode == DFmode)) || (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode)) || (TARGET_NEON @@ -7701,6 +7677,17 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed) } return true; + case CONST_VECTOR: + if (TARGET_NEON + && TARGET_HARD_FLOAT + && outer == SET + && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode)) + && neon_immediate_valid_for_move (x, mode, NULL, NULL)) + *total = COSTS_N_INSNS (1); + else + *total = COSTS_N_INSNS (4); + return true; + default: *total = COSTS_N_INSNS (4); return false; @@ -8041,6 +8028,17 @@ arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, *total = COSTS_N_INSNS (4); return true; + case CONST_VECTOR: + if (TARGET_NEON + && TARGET_HARD_FLOAT + && outer_code == SET + && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode)) + && neon_immediate_valid_for_move (x, mode, NULL, NULL)) + *total = COSTS_N_INSNS (1); + else + *total = COSTS_N_INSNS (4); + return true; + case HIGH: case LO_SUM: /* We prefer constant pool entries to MOVW/MOVT pairs, so bump the @@ -8573,7 +8571,6 @@ fa726te_sched_adjust_cost (rtx insn, rtx link, rtx dep, int * cost) /* Implement TARGET_REGISTER_MOVE_COST. - Moves between FPA_REGS and GENERAL_REGS are two memory insns. Moves between VFP_REGS and GENERAL_REGS are a single insn, but it is typically more expensive than a single memory access. We set the cost to less than two memory accesses so that floating @@ -8585,20 +8582,14 @@ arm_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, { if (TARGET_32BIT) { - if ((from == FPA_REGS && to != FPA_REGS) - || (from != FPA_REGS && to == FPA_REGS)) - return 20; - else if ((IS_VFP_CLASS (from) && !IS_VFP_CLASS (to)) - || (!IS_VFP_CLASS (from) && IS_VFP_CLASS (to))) + if ((IS_VFP_CLASS (from) && !IS_VFP_CLASS (to)) + || (!IS_VFP_CLASS (from) && IS_VFP_CLASS (to))) return 15; else if ((from == IWMMXT_REGS && to != IWMMXT_REGS) || (from != IWMMXT_REGS && to == IWMMXT_REGS)) return 4; else if (from == IWMMXT_GR_REGS || to == IWMMXT_GR_REGS) return 20; - else if ((from == CIRRUS_REGS && to != CIRRUS_REGS) - || (from != CIRRUS_REGS && to == CIRRUS_REGS)) - return 20; else return 2; } @@ -8656,7 +8647,7 @@ arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost) return cost; } - /* XXX This is not strictly true for the FPA. */ + /* XXX Is this strictly true? */ if (REG_NOTE_KIND (link) == REG_DEP_ANTI || REG_NOTE_KIND (link) == REG_DEP_OUTPUT) return 0; @@ -8868,11 +8859,14 @@ vfp3_const_double_rtx (rtx x) vmov i64 17 aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh vmov f32 18 aBbbbbbc defgh000 00000000 00000000 + vmov f32 19 00000000 00000000 00000000 00000000 For case 18, B = !b. Representable values are exactly those accepted by vfp3_const_double_index, but are output as floating-point numbers rather than indices. + For case 19, we will change it to vmov.i32 when assembling. + Variants 0-5 (inclusive) may also be used as immediates for the second operand of VORR/VBIC instructions. @@ -8929,7 +8923,7 @@ neon_valid_immediate (rtx op, enum machine_mode mode, int inverse, rtx el0 = CONST_VECTOR_ELT (op, 0); REAL_VALUE_TYPE r0; - if (!vfp3_const_double_rtx (el0)) + if (!vfp3_const_double_rtx (el0) && el0 != CONST0_RTX (GET_MODE (el0))) return -1; REAL_VALUE_FROM_CONST_DOUBLE (r0, el0); @@ -8951,7 +8945,10 @@ neon_valid_immediate (rtx op, enum machine_mode mode, int inverse, if (elementwidth) *elementwidth = 0; - return 18; + if (el0 == CONST0_RTX (GET_MODE (el0))) + return 19; + else + return 18; } /* Splat vector constant out into a byte vector. */ @@ -9505,43 +9502,6 @@ neon_element_bits (enum machine_mode mode) /* Predicates for `match_operand' and `match_operator'. */ -/* Return nonzero if OP is a valid Cirrus memory address pattern. */ -int -cirrus_memory_offset (rtx op) -{ - /* Reject eliminable registers. */ - if (! (reload_in_progress || reload_completed) - && ( reg_mentioned_p (frame_pointer_rtx, op) - || reg_mentioned_p (arg_pointer_rtx, op) - || reg_mentioned_p (virtual_incoming_args_rtx, op) - || reg_mentioned_p (virtual_outgoing_args_rtx, op) - || reg_mentioned_p (virtual_stack_dynamic_rtx, op) - || reg_mentioned_p (virtual_stack_vars_rtx, op))) - return 0; - - if (GET_CODE (op) == MEM) - { - rtx ind; - - ind = XEXP (op, 0); - - /* Match: (mem (reg)). */ - if (GET_CODE (ind) == REG) - return 1; - - /* Match: - (mem (plus (reg) - (const))). */ - if (GET_CODE (ind) == PLUS - && GET_CODE (XEXP (ind, 0)) == REG - && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode) - && GET_CODE (XEXP (ind, 1)) == CONST_INT) - return 1; - } - - return 0; -} - /* Return TRUE if OP is a valid coprocessor memory address pattern. WB is true if full writeback address modes are allowed and is false if limited writeback address modes (POST_INC and PRE_DEC) are @@ -11641,8 +11601,6 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y) case LE: case GT: case GE: - if (TARGET_HARD_FLOAT && TARGET_MAVERICK) - return CCFPmode; return CCFPEmode; default: @@ -11747,11 +11705,6 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y) if (GET_MODE (x) == DImode || GET_MODE (y) == DImode) { - /* To keep things simple, always use the Cirrus cfcmp64 if it is - available. */ - if (TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK) - return CCmode; - switch (op) { case EQ: @@ -11819,7 +11772,6 @@ arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y, rtx scratch) cc_reg = gen_rtx_REG (mode, CC_REGNUM); if (dimode_comparison - && !(TARGET_HARD_FLOAT && TARGET_MAVERICK) && mode != CC_CZmode) { rtx clobber, set; @@ -13357,6 +13309,13 @@ thumb2_reorg (void) switch (GET_CODE (src)) { case PLUS: + /* Adding two registers and storing the result + in the first source is already a 16-bit + operation. */ + if (rtx_equal_p (dst, op0) + && register_operand (op1, SImode)) + break; + if (low_register_operand (op0, SImode)) { /* ADDS <Rd>,<Rn>,<Rm> */ @@ -13504,6 +13463,13 @@ arm_reorg (void) if (TARGET_THUMB2) thumb2_reorg (); + /* Ensure all insns that must be split have been split at this point. + Otherwise, the pool placement code below may compute incorrect + insn lengths. Note that when optimizing, all insns have already + been split at this point. */ + if (!optimize) + split_all_insns_noflow (); + minipool_fix_head = minipool_fix_tail = NULL; /* The first insn must always be a note, or the code below won't @@ -13962,47 +13928,6 @@ output_call_mem (rtx *operands) } -/* Output a move from arm registers to an fpa registers. - OPERANDS[0] is an fpa register. - OPERANDS[1] is the first registers of an arm register pair. */ -const char * -output_mov_long_double_fpa_from_arm (rtx *operands) -{ - int arm_reg0 = REGNO (operands[1]); - rtx ops[3]; - - gcc_assert (arm_reg0 != IP_REGNUM); - - ops[0] = gen_rtx_REG (SImode, arm_reg0); - ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0); - ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0); - - output_asm_insn ("stm%(fd%)\t%|sp!, {%0, %1, %2}", ops); - output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands); - - return ""; -} - -/* Output a move from an fpa register to arm registers. - OPERANDS[0] is the first registers of an arm register pair. - OPERANDS[1] is an fpa register. */ -const char * -output_mov_long_double_arm_from_fpa (rtx *operands) -{ - int arm_reg0 = REGNO (operands[0]); - rtx ops[3]; - - gcc_assert (arm_reg0 != IP_REGNUM); - - ops[0] = gen_rtx_REG (SImode, arm_reg0); - ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0); - ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0); - - output_asm_insn ("stf%?e\t%1, [%|sp, #-12]!", operands); - output_asm_insn ("ldm%(fd%)\t%|sp!, {%0, %1, %2}", ops); - return ""; -} - /* Output a move from arm registers to arm registers of a long double OPERANDS[0] is the destination. OPERANDS[1] is the source. */ @@ -14055,42 +13980,6 @@ arm_emit_movpair (rtx dest, rtx src) emit_set_insn (dest, gen_rtx_LO_SUM (SImode, dest, src)); } -/* Output a move from arm registers to an fpa registers. - OPERANDS[0] is an fpa register. - OPERANDS[1] is the first registers of an arm register pair. */ -const char * -output_mov_double_fpa_from_arm (rtx *operands) -{ - int arm_reg0 = REGNO (operands[1]); - rtx ops[2]; - - gcc_assert (arm_reg0 != IP_REGNUM); - - ops[0] = gen_rtx_REG (SImode, arm_reg0); - ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0); - output_asm_insn ("stm%(fd%)\t%|sp!, {%0, %1}", ops); - output_asm_insn ("ldf%?d\t%0, [%|sp], #8", operands); - return ""; -} - -/* Output a move from an fpa register to arm registers. - OPERANDS[0] is the first registers of an arm register pair. - OPERANDS[1] is an fpa register. */ -const char * -output_mov_double_arm_from_fpa (rtx *operands) -{ - int arm_reg0 = REGNO (operands[0]); - rtx ops[2]; - - gcc_assert (arm_reg0 != IP_REGNUM); - - ops[0] = gen_rtx_REG (SImode, arm_reg0); - ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0); - output_asm_insn ("stf%?d\t%1, [%|sp, #-8]!", operands); - output_asm_insn ("ldm%(fd%)\t%|sp!, {%0, %1}", ops); - return ""; -} - /* Output a move between double words. It must be REG<-MEM or MEM<-REG. */ const char * @@ -16133,68 +16022,7 @@ arm_size_return_regs (void) return GET_MODE_SIZE (mode); } -static rtx -emit_sfm (int base_reg, int count) -{ - rtx par; - rtx dwarf; - rtx tmp, reg; - int i; - - par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); - dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1)); - - reg = gen_rtx_REG (XFmode, base_reg++); - - XVECEXP (par, 0, 0) - = gen_rtx_SET (VOIDmode, - gen_frame_mem - (BLKmode, - gen_rtx_PRE_MODIFY (Pmode, - stack_pointer_rtx, - plus_constant - (Pmode, stack_pointer_rtx, - -12 * count)) - ), - gen_rtx_UNSPEC (BLKmode, - gen_rtvec (1, reg), - UNSPEC_PUSH_MULT)); - tmp = gen_rtx_SET (VOIDmode, - gen_frame_mem (XFmode, stack_pointer_rtx), reg); - RTX_FRAME_RELATED_P (tmp) = 1; - XVECEXP (dwarf, 0, 1) = tmp; - - for (i = 1; i < count; i++) - { - reg = gen_rtx_REG (XFmode, base_reg++); - XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg); - - tmp = gen_rtx_SET (VOIDmode, - gen_frame_mem (XFmode, - plus_constant (Pmode, - stack_pointer_rtx, - i * 12)), - reg); - RTX_FRAME_RELATED_P (tmp) = 1; - XVECEXP (dwarf, 0, i + 1) = tmp; - } - - tmp = gen_rtx_SET (VOIDmode, - stack_pointer_rtx, - plus_constant (Pmode, stack_pointer_rtx, -12 * count)); - - RTX_FRAME_RELATED_P (tmp) = 1; - XVECEXP (dwarf, 0, 0) = tmp; - - par = emit_insn (par); - add_reg_note (par, REG_FRAME_RELATED_EXPR, dwarf); - - return par; -} - - /* Return true if the current function needs to save/restore LR. */ - static bool thumb_force_lr_save (void) { @@ -16207,7 +16035,6 @@ thumb_force_lr_save (void) /* Return true if r3 is used by any of the tail call insns in the current function. */ - static bool any_sibcall_uses_r3 (void) { @@ -16345,17 +16172,10 @@ arm_get_frame_offsets (void) } func_type = arm_current_func_type (); - if (! IS_VOLATILE (func_type)) - { - /* Space for saved FPA registers. */ - for (regno = FIRST_FPA_REGNUM; regno <= LAST_FPA_REGNUM; regno++) - if (df_regs_ever_live_p (regno) && ! call_used_regs[regno]) - saved += 12; - - /* Space for saved VFP registers. */ - if (TARGET_HARD_FLOAT && TARGET_VFP) - saved += arm_get_vfp_saved_size (); - } + /* Space for saved VFP registers. */ + if (! IS_VOLATILE (func_type) + && TARGET_HARD_FLOAT && TARGET_VFP) + saved += arm_get_vfp_saved_size (); } else /* TARGET_THUMB1 */ { @@ -16406,7 +16226,11 @@ arm_get_frame_offsets (void) else for (i = 4; i <= (TARGET_THUMB1 ? LAST_LO_REGNUM : 11); i++) { - if ((offsets->saved_regs_mask & (1 << i)) == 0) + /* Avoid fixed registers; they may be changed at + arbitrary times so it's unsafe to restore them + during the epilogue. */ + if (!fixed_regs[i] + && (offsets->saved_regs_mask & (1 << i)) == 0) { reg = i; break; @@ -16551,55 +16375,6 @@ arm_save_coproc_regs(void) saved_size += 8; } - /* Save any floating point call-saved registers used by this - function. */ - if (TARGET_FPA_EMU2) - { - for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--) - if (df_regs_ever_live_p (reg) && !call_used_regs[reg]) - { - insn = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx); - insn = gen_rtx_MEM (XFmode, insn); - insn = emit_set_insn (insn, gen_rtx_REG (XFmode, reg)); - RTX_FRAME_RELATED_P (insn) = 1; - saved_size += 12; - } - } - else - { - start_reg = LAST_FPA_REGNUM; - - for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--) - { - if (df_regs_ever_live_p (reg) && !call_used_regs[reg]) - { - if (start_reg - reg == 3) - { - insn = emit_sfm (reg, 4); - RTX_FRAME_RELATED_P (insn) = 1; - saved_size += 48; - start_reg = reg - 1; - } - } - else - { - if (start_reg != reg) - { - insn = emit_sfm (reg + 1, start_reg - reg); - RTX_FRAME_RELATED_P (insn) = 1; - saved_size += (start_reg - reg) * 12; - } - start_reg = reg - 1; - } - } - - if (start_reg != reg) - { - insn = emit_sfm (reg + 1, start_reg - reg); - saved_size += (start_reg - reg) * 12; - RTX_FRAME_RELATED_P (insn) = 1; - } - } if (TARGET_HARD_FLOAT && TARGET_VFP) { start_reg = FIRST_VFP_REGNUM; @@ -17156,16 +16931,6 @@ arm_print_operand (FILE *stream, rtx x, int code) fprintf (stream, "%s", arithmetic_instr (x, 1)); return; - /* Truncate Cirrus shift counts. */ - case 's': - if (GET_CODE (x) == CONST_INT) - { - fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x3f); - return; - } - arm_print_operand (stream, x, 0); - return; - case 'I': fprintf (stream, "%s", arithmetic_instr (x, 0)); return; @@ -17352,44 +17117,15 @@ arm_print_operand (FILE *stream, rtx x, int code) stream); return; - /* Cirrus registers can be accessed in a variety of ways: - single floating point (f) - double floating point (d) - 32bit integer (fx) - 64bit integer (dx). */ - case 'W': /* Cirrus register in F mode. */ - case 'X': /* Cirrus register in D mode. */ - case 'Y': /* Cirrus register in FX mode. */ - case 'Z': /* Cirrus register in DX mode. */ - gcc_assert (GET_CODE (x) == REG - && REGNO_REG_CLASS (REGNO (x)) == CIRRUS_REGS); - - fprintf (stream, "mv%s%s", - code == 'W' ? "f" - : code == 'X' ? "d" - : code == 'Y' ? "fx" : "dx", reg_names[REGNO (x)] + 2); - - return; - - /* Print cirrus register in the mode specified by the register's mode. */ + case 's': case 'V': - { - int mode = GET_MODE (x); - - if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS) - { - output_operand_lossage ("invalid operand for code '%c'", code); - return; - } - - fprintf (stream, "mv%s%s", - mode == DFmode ? "d" - : mode == SImode ? "fx" - : mode == DImode ? "dx" - : "f", reg_names[REGNO (x)] + 2); - - return; - } + case 'W': + case 'X': + case 'Y': + case 'Z': + /* Former Maverick support, removed after GCC-4.7. */ + output_operand_lossage ("obsolete Maverick format code '%c'", code); + return; case 'U': if (GET_CODE (x) != REG @@ -17732,7 +17468,7 @@ arm_print_operand_address (FILE *stream, rtx x) int is_minus = GET_CODE (x) == MINUS; if (GET_CODE (x) == REG) - asm_fprintf (stream, "[%r, #0]", REGNO (x)); + asm_fprintf (stream, "[%r]", REGNO (x)); else if (GET_CODE (x) == PLUS || is_minus) { rtx base = XEXP (x, 0); @@ -18074,9 +17810,7 @@ maybe_get_arm_condition_code (rtx comparison) case CCFPEmode: case CCFPmode: - /* These encodings assume that AC=1 in the FPA system control - byte. This allows us to handle all cases except UNEQ and - LTGT. */ + /* We can handle all cases except UNEQ and LTGT. */ switch (comp_code) { case GE: return ARM_GE; @@ -18576,15 +18310,6 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) start of an even numbered register pair. */ return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM); - if (TARGET_HARD_FLOAT && TARGET_MAVERICK - && IS_CIRRUS_REGNUM (regno)) - /* We have outlawed SI values in Cirrus registers because they - reside in the lower 32 bits, but SF values reside in the - upper 32 bits. This causes gcc all sorts of grief. We can't - even split the registers into pairs because Cirrus SI values - get sign extended to 64bits-- aldyh. */ - return (GET_MODE_CLASS (mode) == MODE_FLOAT) || (mode == DImode); - if (TARGET_HARD_FLOAT && TARGET_VFP && IS_VFP_REGNUM (regno)) { @@ -18634,12 +18359,7 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode) /* We only allow integers in the fake hard registers. */ return GET_MODE_CLASS (mode) == MODE_INT; - /* The only registers left are the FPA registers - which we only allow to hold FP values. */ - return (TARGET_HARD_FLOAT && TARGET_FPA - && GET_MODE_CLASS (mode) == MODE_FLOAT - && regno >= FIRST_FPA_REGNUM - && regno <= LAST_FPA_REGNUM); + return FALSE; } /* Implement MODES_TIEABLE_P. */ @@ -18693,9 +18413,6 @@ arm_regno_class (int regno) if (regno == CC_REGNUM || regno == VFPCC_REGNUM) return TARGET_THUMB2 ? CC_REG : NO_REGS; - if (IS_CIRRUS_REGNUM (regno)) - return CIRRUS_REGS; - if (IS_VFP_REGNUM (regno)) { if (regno <= D7_VFP_REGNUM) @@ -18712,7 +18429,7 @@ arm_regno_class (int regno) if (IS_IWMMXT_GR_REGNUM (regno)) return IWMMXT_GR_REGS; - return FPA_REGS; + return NO_REGS; } /* Handle a special case when computing the offset @@ -23645,10 +23362,7 @@ arm_file_start (void) if (TARGET_SOFT_FLOAT) { - if (TARGET_VFP) - fpu_name = "softvfp"; - else - fpu_name = "softfpa"; + fpu_name = "softvfp"; } else { @@ -24060,7 +23774,12 @@ arm_early_load_addr_dep (rtx producer, rtx consumer) if (GET_CODE (addr) == COND_EXEC) addr = COND_EXEC_CODE (addr); if (GET_CODE (addr) == PARALLEL) - addr = XVECEXP (addr, 0, 0); + { + if (GET_CODE (XVECEXP (addr, 0, 0)) == RETURN) + addr = XVECEXP (addr, 0, 1); + else + addr = XVECEXP (addr, 0, 0); + } addr = XEXP (addr, 1); return reg_overlap_mentioned_p (value, addr); @@ -24550,11 +24269,6 @@ arm_dbx_register_number (unsigned int regno) if (regno < 16) return regno; - /* TODO: Legacy targets output FPA regs as registers 16-23 for backwards - compatibility. The EABI defines them as registers 96-103. */ - if (IS_FPA_REGNUM (regno)) - return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM; - if (IS_VFP_REGNUM (regno)) { /* See comment in arm_dwarf_register_span. */ @@ -24656,12 +24370,6 @@ arm_unwind_emit_sequence (FILE * asm_out_file, rtx p) reg_size = 8; fprintf (asm_out_file, "\t.vsave {"); } - else if (reg >= FIRST_FPA_REGNUM && reg <= LAST_FPA_REGNUM) - { - /* FPA registers are done differently. */ - asm_fprintf (asm_out_file, "\t.save %r, %wd\n", reg, nregs); - return; - } else /* Unknown register type. */ abort (); @@ -25358,7 +25066,7 @@ arm_mangle_type (const_tree type) static const int thumb_core_reg_alloc_order[] = { 3, 2, 1, 0, 4, 5, 6, 7, - 14, 12, 8, 9, 10, 11, 13, 15 + 14, 12, 8, 9, 10, 11 }; /* Adjust register allocation order when compiling for Thumb. */ @@ -25391,6 +25099,18 @@ arm_have_conditional_execution (void) return !TARGET_THUMB1; } +/* The AAPCS sets the maximum alignment of a vector to 64 bits. */ +static HOST_WIDE_INT +arm_vector_alignment (const_tree type) +{ + HOST_WIDE_INT align = tree_low_cst (TYPE_SIZE (type), 0); + + if (TARGET_AAPCS_BASED) + align = MIN (align, 64); + + return align; +} + static unsigned int arm_autovectorize_vector_sizes (void) { @@ -25441,13 +25161,6 @@ arm_conditional_register_usage (void) { int regno; - if (TARGET_SOFT_FLOAT || TARGET_THUMB1 || !TARGET_FPA) - { - for (regno = FIRST_FPA_REGNUM; - regno <= LAST_FPA_REGNUM; ++regno) - fixed_regs[regno] = call_used_regs[regno] = 1; - } - if (TARGET_THUMB1 && optimize_size) { /* When optimizing for size on Thumb-1, it's better not @@ -25464,32 +25177,17 @@ arm_conditional_register_usage (void) if (TARGET_THUMB1) fixed_regs[LR_REGNUM] = call_used_regs[LR_REGNUM] = 1; - if (TARGET_32BIT && TARGET_HARD_FLOAT) + if (TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP) { - if (TARGET_MAVERICK) - { - for (regno = FIRST_FPA_REGNUM; - regno <= LAST_FPA_REGNUM; ++ regno) - fixed_regs[regno] = call_used_regs[regno] = 1; - for (regno = FIRST_CIRRUS_FP_REGNUM; - regno <= LAST_CIRRUS_FP_REGNUM; ++ regno) - { - fixed_regs[regno] = 0; - call_used_regs[regno] = regno < FIRST_CIRRUS_FP_REGNUM + 4; - } - } - if (TARGET_VFP) + /* VFPv3 registers are disabled when earlier VFP + versions are selected due to the definition of + LAST_VFP_REGNUM. */ + for (regno = FIRST_VFP_REGNUM; + regno <= LAST_VFP_REGNUM; ++ regno) { - /* VFPv3 registers are disabled when earlier VFP - versions are selected due to the definition of - LAST_VFP_REGNUM. */ - for (regno = FIRST_VFP_REGNUM; - regno <= LAST_VFP_REGNUM; ++ regno) - { - fixed_regs[regno] = 0; - call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16 - || regno >= FIRST_VFP_REGNUM + 32; - } + fixed_regs[regno] = 0; + call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16 + || regno >= FIRST_VFP_REGNUM + 32; } } |