X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Frs6000%2Frs6000.c;h=ab48e82d9fc7ab16246df71a18a503b751d29385;hb=a2456fc3b00f4d52114e837cc5540031fcbb0209;hp=61140a28fb16720b933941448d0266461c03ec94;hpb=d33dc3b0e10fd8302004e98fd638da8df63c3244;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 61140a28fb1..ab48e82d9fc 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -115,16 +115,14 @@ typedef struct rs6000_stack { This is added to the cfun structure. */ typedef struct GTY(()) machine_function { + /* Flags if __builtin_return_address (n) with n >= 1 was used. */ + int ra_needs_full_frame; /* Some local-dynamic symbol. */ const char *some_ld_name; /* Whether the instruction chain has been scanned already. */ int insn_chain_scanned_p; - /* Flags if __builtin_return_address (n) with n >= 1 was used. */ - int ra_needs_full_frame; /* Flags if __builtin_return_address (0) was used. */ int ra_need_lr; - /* Cache lr_save_p after expansion of builtin_eh_return. */ - int lr_save_state; /* Offset from virtual_stack_vars_rtx to the start of the ABI_V4 varargs save area. */ HOST_WIDE_INT varargs_save_offset; @@ -883,6 +881,7 @@ static bool spe_func_has_64bit_regs_p (void); static void emit_frame_save (rtx, rtx, enum machine_mode, unsigned int, int, HOST_WIDE_INT); static rtx gen_frame_mem_offset (enum machine_mode, rtx, int); +static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int, int); static unsigned rs6000_hash_constant (rtx); static unsigned toc_hash_function (const void *); static int toc_hash_eq (const void *, const void *); @@ -898,7 +897,6 @@ static bool no_global_regs_above (int, bool); static void rs6000_assemble_visibility (tree, int); #endif static int rs6000_ra_ever_killed (void); -static bool rs6000_attribute_takes_identifier_p (const_tree); static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *); static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *); static bool rs6000_ms_bitfield_layout_p (const_tree); @@ -911,7 +909,7 @@ static rtx rs6000_emit_stack_reset (rs6000_stack_t *, rtx, rtx, int, bool); static rtx rs6000_make_savres_rtx (rs6000_stack_t *, rtx, int, enum machine_mode, bool, bool, bool); static bool rs6000_reg_live_or_pic_offset_p (int); -static tree rs6000_builtin_vectorized_function (tree, tree, tree); +static tree rs6000_builtin_vectorized_function (unsigned int, tree, tree); static int rs6000_savres_strategy (rs6000_stack_t *, bool, int, int); static void rs6000_restore_saved_cr (rtx, int); static void rs6000_output_function_prologue (FILE *, HOST_WIDE_INT); @@ -992,7 +990,7 @@ static tree rs6000_builtin_reciprocal (unsigned int, bool, bool); static tree rs6000_builtin_mask_for_load (void); static tree rs6000_builtin_mul_widen_even (tree); static tree rs6000_builtin_mul_widen_odd (tree); -static tree rs6000_builtin_conversion (unsigned int, tree, tree); +static tree rs6000_builtin_conversion (unsigned int, tree); static tree rs6000_builtin_vec_perm (tree, tree *); static bool rs6000_builtin_support_vector_misalignment (enum machine_mode, @@ -1119,9 +1117,9 @@ rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode, int, int, int, int *) = rs6000_legitimize_reload_address; -static bool rs6000_mode_dependent_address (const_rtx); -static bool rs6000_debug_mode_dependent_address (const_rtx); -bool (*rs6000_mode_dependent_address_ptr) (const_rtx) +static bool rs6000_mode_dependent_address (rtx); +static bool rs6000_debug_mode_dependent_address (rtx); +bool (*rs6000_mode_dependent_address_ptr) (rtx) = rs6000_mode_dependent_address; static enum reg_class rs6000_secondary_reload_class (enum reg_class, @@ -1281,8 +1279,6 @@ static const struct attribute_spec rs6000_attribute_table[] = #define TARGET_ATTRIBUTE_TABLE rs6000_attribute_table #undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES #define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES rs6000_set_default_type_attributes -#undef TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P -#define TARGET_ATTRIBUTE_TAKES_IDENTIFIER_P rs6000_attribute_takes_identifier_p #undef TARGET_ASM_ALIGNED_DI_OP #define TARGET_ASM_ALIGNED_DI_OP DOUBLE_INT_ASM_OP @@ -2887,24 +2883,24 @@ rs6000_builtin_mask_for_load (void) /* Implement targetm.vectorize.builtin_conversion. Returns a decl of a function that implements conversion of an integer vector - into a floating-point vector, or vice-versa. DEST_TYPE is the - destination type and SRC_TYPE the source type of the conversion. + into a floating-point vector, or vice-versa. TYPE is the type of the integer + side of the conversion. Return NULL_TREE if it is not available. */ static tree -rs6000_builtin_conversion (unsigned int tcode, tree dest_type, tree src_type) +rs6000_builtin_conversion (unsigned int tcode, tree type) { enum tree_code code = (enum tree_code) tcode; switch (code) { case FIX_TRUNC_EXPR: - switch (TYPE_MODE (dest_type)) + switch (TYPE_MODE (type)) { case V2DImode: if (!VECTOR_UNIT_VSX_P (V2DFmode)) return NULL_TREE; - return TYPE_UNSIGNED (dest_type) + return TYPE_UNSIGNED (type) ? rs6000_builtin_decls[VSX_BUILTIN_XVCVDPUXDS_UNS] : rs6000_builtin_decls[VSX_BUILTIN_XVCVDPSXDS]; @@ -2912,7 +2908,7 @@ rs6000_builtin_conversion (unsigned int tcode, tree dest_type, tree src_type) if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode)) return NULL_TREE; - return TYPE_UNSIGNED (dest_type) + return TYPE_UNSIGNED (type) ? rs6000_builtin_decls[VECTOR_BUILTIN_FIXUNS_V4SF_V4SI] : rs6000_builtin_decls[VECTOR_BUILTIN_FIX_V4SF_V4SI]; @@ -2921,13 +2917,13 @@ rs6000_builtin_conversion (unsigned int tcode, tree dest_type, tree src_type) } case FLOAT_EXPR: - switch (TYPE_MODE (src_type)) + switch (TYPE_MODE (type)) { case V2DImode: if (!VECTOR_UNIT_VSX_P (V2DFmode)) return NULL_TREE; - return TYPE_UNSIGNED (src_type) + return TYPE_UNSIGNED (type) ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDDP] : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDDP]; @@ -2935,7 +2931,7 @@ rs6000_builtin_conversion (unsigned int tcode, tree dest_type, tree src_type) if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode)) return NULL_TREE; - return TYPE_UNSIGNED (src_type) + return TYPE_UNSIGNED (type) ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF] : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF]; @@ -3183,17 +3179,15 @@ rs6000_parse_fpu_option (const char *option) if it is not available. */ static tree -rs6000_builtin_vectorized_function (tree fndecl, tree type_out, +rs6000_builtin_vectorized_function (unsigned int fn, tree type_out, tree type_in) { enum machine_mode in_mode, out_mode; int in_n, out_n; - enum built_in_function fn = DECL_FUNCTION_CODE (fndecl); if (TREE_CODE (type_out) != VECTOR_TYPE || TREE_CODE (type_in) != VECTOR_TYPE - || !TARGET_VECTORIZE_BUILTINS - || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL) + || !TARGET_VECTORIZE_BUILTINS) return NULL_TREE; out_mode = TYPE_MODE (TREE_TYPE (type_out)); @@ -4187,7 +4181,7 @@ paired_emit_vector_compare (enum rtx_code rcode, rtx cc_op0, rtx cc_op1) { rtx tmp = gen_reg_rtx (V2SFmode); - rtx tmp1, max, min; + rtx tmp1, max, min, equal_zero; gcc_assert (TARGET_PAIRED_FLOAT); gcc_assert (GET_MODE (op0) == GET_MODE (op1)); @@ -4214,8 +4208,8 @@ paired_emit_vector_compare (enum rtx_code rcode, tmp1 = gen_reg_rtx (V2SFmode); max = gen_reg_rtx (V2SFmode); min = gen_reg_rtx (V2SFmode); - gen_reg_rtx (V2SFmode); - + equal_zero = gen_reg_rtx (V2SFmode); + emit_insn (gen_subv2sf3 (tmp, cc_op0, cc_op1)); emit_insn (gen_selv2sf4 (max, tmp, cc_op0, cc_op1, CONST0_RTX (SFmode))); @@ -5416,14 +5410,14 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model) else { rtx tmp3, mem; - rtx last; + rtx first, last; tmp1 = gen_reg_rtx (Pmode); tmp2 = gen_reg_rtx (Pmode); tmp3 = gen_reg_rtx (Pmode); mem = gen_const_mem (Pmode, tmp1); - emit_insn (gen_load_toc_v4_PIC_1b (gsym)); + first = emit_insn (gen_load_toc_v4_PIC_1b (gsym)); emit_move_insn (tmp1, gen_rtx_REG (Pmode, LR_REGNO)); emit_move_insn (tmp2, mem); @@ -5897,7 +5891,7 @@ rs6000_debug_legitimate_address_p (enum machine_mode mode, rtx x, sub-words of a TFmode operand, which is what we had before. */ static bool -rs6000_mode_dependent_address (const_rtx addr) +rs6000_mode_dependent_address (rtx addr) { switch (GET_CODE (addr)) { @@ -5937,7 +5931,7 @@ rs6000_mode_dependent_address (const_rtx addr) /* Debug version of rs6000_mode_dependent_address. */ static bool -rs6000_debug_mode_dependent_address (const_rtx addr) +rs6000_debug_mode_dependent_address (rtx addr) { bool ret = rs6000_mode_dependent_address (addr); @@ -10152,7 +10146,7 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); tree arg0, arg1, arg2; - enum machine_mode mode0, mode1; + enum machine_mode mode0, mode1, mode2; rtx pat, op0, op1, op2; const struct builtin_description *d; size_t i; @@ -10172,6 +10166,7 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, op2 = expand_normal (arg2); mode0 = insn_data[d->icode].operand[0].mode; mode1 = insn_data[d->icode].operand[1].mode; + mode2 = insn_data[d->icode].operand[2].mode; /* Invalid arguments, bail out before generating bad rtl. */ if (arg0 == error_mark_node @@ -16837,16 +16832,6 @@ rs6000_split_multireg_move (rtx dst, rtx src) { rtx basereg = XEXP (XEXP (dst, 0), 0); rtx offsetreg = XEXP (XEXP (dst, 0), 1); - gcc_assert (GET_CODE (XEXP (dst, 0)) == PLUS - && REG_P (basereg) - && REG_P (offsetreg) - && REGNO (basereg) != REGNO (offsetreg)); - if (REGNO (basereg) == 0) - { - rtx tmp = offsetreg; - offsetreg = basereg; - basereg = tmp; - } emit_insn (gen_add3_insn (basereg, basereg, offsetreg)); restore_basereg = gen_sub3_insn (basereg, basereg, offsetreg); dst = replace_equiv_address (dst, basereg); @@ -17730,9 +17715,6 @@ rs6000_ra_ever_killed (void) if (cfun->is_thunk) return 0; - if (cfun->machine->lr_save_state) - return cfun->machine->lr_save_state - 1; - /* regs_ever_live has LR marked as used if any sibcalls are present, but this should not force saving and restoring in the pro/epilogue. Likewise, reg_set_between_p thinks a sibcall @@ -17902,12 +17884,6 @@ rs6000_emit_eh_reg_restore (rtx source, rtx scratch) } else emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), operands[0]); - - /* Freeze lr_save_p. We've just emitted rtl that depends on the - state of lr_save_p so any change from here on would be a bug. In - particular, stop rs6000_ra_ever_killed from considering the SET - of lr we may have added just above. */ - cfun->machine->lr_save_state = info->lr_save_p + 1; } static GTY(()) alias_set_type set = -1; @@ -18034,11 +18010,13 @@ rs6000_emit_stack_tie (void) } /* Emit the correct code for allocating stack space, as insns. - If COPY_REG, make sure a copy of the old frame is left there. + If COPY_R12, make sure a copy of the old frame is left in r12. + If COPY_R11, make sure a copy of the old frame is left in r11, + in preference to r12 if COPY_R12. The generated code may use hard register 0 as a temporary. */ static void -rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg) +rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12, int copy_r11) { rtx insn; rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM); @@ -18081,8 +18059,11 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, rtx copy_reg) warning (0, "stack limit expression is not supported"); } - if (copy_reg) - emit_move_insn (copy_reg, stack_reg); + if (copy_r12 || copy_r11) + emit_move_insn (copy_r11 + ? gen_rtx_REG (Pmode, 11) + : gen_rtx_REG (Pmode, 12), + stack_reg); if (size > 32767) { @@ -18768,33 +18749,20 @@ rs6000_emit_prologue (void) ? (!saving_GPRs_inline && info->spe_64bit_regs_used == 0) : (!saving_FPRs_inline || !saving_GPRs_inline)); - rtx copy_reg = need_r11 ? gen_rtx_REG (Pmode, 11) : NULL; - if (info->total_size < 32767) sp_offset = info->total_size; - else if (need_r11) - frame_reg_rtx = copy_reg; - else if (info->cr_save_p - || info->lr_save_p - || info->first_fp_reg_save < 64 - || info->first_gp_reg_save < 32 - || info->altivec_size != 0 - || info->vrsave_mask != 0 - || crtl->calls_eh_return) - { - copy_reg = frame_ptr_rtx; - frame_reg_rtx = copy_reg; - } else - { - /* The prologue won't be saving any regs so there is no need - to set up a frame register to access any frame save area. - We also won't be using sp_offset anywhere below, but set - the correct value anyway to protect against future - changes to this function. */ - sp_offset = info->total_size; - } - rs6000_emit_allocate_stack (info->total_size, copy_reg); + frame_reg_rtx = (need_r11 + ? gen_rtx_REG (Pmode, 11) + : frame_ptr_rtx); + rs6000_emit_allocate_stack (info->total_size, + (frame_reg_rtx != sp_reg_rtx + && (info->cr_save_p + || info->lr_save_p + || info->first_fp_reg_save < 64 + || info->first_gp_reg_save < 32 + )), + need_r11); if (frame_reg_rtx != sp_reg_rtx) rs6000_emit_stack_tie (); } @@ -19229,19 +19197,16 @@ rs6000_emit_prologue (void) if (!WORLD_SAVE_P (info) && info->push_p && !(DEFAULT_ABI == ABI_V4 || crtl->calls_eh_return)) { - rtx copy_reg = NULL; - if (info->total_size < 32767) - sp_offset = info->total_size; - else if (info->altivec_size != 0 - || info->vrsave_mask != 0) - { - copy_reg = frame_ptr_rtx; - frame_reg_rtx = copy_reg; - } + sp_offset = info->total_size; else - sp_offset = info->total_size; - rs6000_emit_allocate_stack (info->total_size, copy_reg); + frame_reg_rtx = frame_ptr_rtx; + rs6000_emit_allocate_stack (info->total_size, + (frame_reg_rtx != sp_reg_rtx + && ((info->altivec_size != 0) + || (info->vrsave_mask != 0) + )), + FALSE); if (frame_reg_rtx != sp_reg_rtx) rs6000_emit_stack_tie (); } @@ -23344,15 +23309,6 @@ rs6000_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt) } -/* Returns TRUE iff the target attribute indicated by ATTR_ID takes a plain - identifier as an argument, so the front end shouldn't look it up. */ - -static bool -rs6000_attribute_takes_identifier_p (const_tree attr_id) -{ - return is_attribute_p ("altivec", attr_id); -} - /* Handle the "altivec" attribute. The attribute may have arguments as follows: