Mercurial > hg > CbC > CbC_gcc
diff gcc/config/spu/spu.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
line wrap: on
line diff
--- a/gcc/config/spu/spu.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/config/spu/spu.c Tue Mar 22 17:18:12 2011 +0900 @@ -35,7 +35,7 @@ #include "output.h" #include "basic-block.h" #include "integrate.h" -#include "toplev.h" +#include "diagnostic-core.h" #include "ggc.h" #include "hashtab.h" #include "tm_p.h" @@ -46,7 +46,6 @@ #include "cfglayout.h" #include "sched-int.h" #include "params.h" -#include "assert.h" #include "machmode.h" #include "gimple.h" #include "tm-constrs.h" @@ -148,10 +147,13 @@ char regs_ever_allocated[FIRST_PSEUDO_REGISTER]; /* Prototypes and external defs. */ +static void spu_option_override (void); +static void spu_option_init_struct (struct gcc_options *opts); +static void spu_option_default_params (void); static void spu_init_builtins (void); static tree spu_builtin_decl (unsigned, bool); -static unsigned char spu_scalar_mode_supported_p (enum machine_mode mode); -static unsigned char spu_vector_mode_supported_p (enum machine_mode mode); +static bool spu_scalar_mode_supported_p (enum machine_mode mode); +static bool spu_vector_mode_supported_p (enum machine_mode mode); static bool spu_legitimate_address_p (enum machine_mode, rtx, bool); static bool spu_addr_space_legitimate_address_p (enum machine_mode, rtx, bool, addr_space_t); @@ -180,13 +182,17 @@ static int spu_sched_reorder (FILE *, int, rtx *, int *, int); static tree spu_handle_fndecl_attribute (tree * node, tree name, tree args, int flags, - unsigned char *no_add_attrs); + bool *no_add_attrs); static tree spu_handle_vector_attribute (tree * node, tree name, tree args, int flags, - unsigned char *no_add_attrs); + bool *no_add_attrs); static int spu_naked_function_p (tree func); -static unsigned char spu_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode, - const_tree type, unsigned char named); +static bool spu_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode, + const_tree type, bool named); +static rtx spu_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, + const_tree type, bool named); +static void spu_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, + const_tree type, bool named); static tree spu_build_builtin_va_list (void); static void spu_va_start (tree, rtx); static tree spu_gimplify_va_arg_expr (tree valist, tree type, @@ -196,9 +202,9 @@ static int reg_aligned_for_addr (rtx x); static bool spu_assemble_integer (rtx x, unsigned int size, int aligned_p); static void spu_asm_globalize_label (FILE * file, const char *name); -static unsigned char spu_rtx_costs (rtx x, int code, int outer_code, - int *total, bool speed); -static unsigned char spu_function_ok_for_sibcall (tree decl, tree exp); +static bool spu_rtx_costs (rtx x, int code, int outer_code, + int *total, bool speed); +static bool spu_function_ok_for_sibcall (tree decl, tree exp); static void spu_init_libfuncs (void); static bool spu_return_in_memory (const_tree type, const_tree fntype); static void fix_range (const char *); @@ -209,7 +215,7 @@ static tree spu_builtin_mul_widen_even (tree); static tree spu_builtin_mul_widen_odd (tree); static tree spu_builtin_mask_for_load (void); -static int spu_builtin_vectorization_cost (bool); +static int spu_builtin_vectorization_cost (enum vect_cost_for_stmt, tree, int); static bool spu_vector_alignment_reachable (const_tree, bool); static tree spu_builtin_vec_perm (tree, tree *); static enum machine_mode spu_addr_space_pointer_mode (addr_space_t); @@ -223,8 +229,8 @@ static void spu_unique_section (tree, int); static rtx spu_expand_load (rtx, rtx, rtx, int); static void spu_trampoline_init (rtx, tree, rtx); - -extern const char *reg_names[]; +static void spu_conditional_register_usage (void); +static bool spu_ref_may_alias_errno (ao_ref *); /* Which instruction set architecture to use. */ int spu_arch; @@ -390,6 +396,12 @@ #undef TARGET_PASS_BY_REFERENCE #define TARGET_PASS_BY_REFERENCE spu_pass_by_reference +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG spu_function_arg + +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE spu_function_arg_advance + #undef TARGET_MUST_PASS_IN_STACK #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size @@ -432,8 +444,8 @@ #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST spu_builtin_vectorization_cost -#undef TARGET_VECTOR_ALIGNMENT_REACHABLE -#define TARGET_VECTOR_ALIGNMENT_REACHABLE spu_vector_alignment_reachable +#undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE +#define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE spu_vector_alignment_reachable #undef TARGET_VECTORIZE_BUILTIN_VEC_PERM #define TARGET_VECTORIZE_BUILTIN_VEC_PERM spu_builtin_vec_perm @@ -465,31 +477,52 @@ #undef TARGET_TRAMPOLINE_INIT #define TARGET_TRAMPOLINE_INIT spu_trampoline_init +#undef TARGET_OPTION_OVERRIDE +#define TARGET_OPTION_OVERRIDE spu_option_override + +#undef TARGET_OPTION_INIT_STRUCT +#define TARGET_OPTION_INIT_STRUCT spu_option_init_struct + +#undef TARGET_OPTION_DEFAULT_PARAMS +#define TARGET_OPTION_DEFAULT_PARAMS spu_option_default_params + +#undef TARGET_EXCEPT_UNWIND_INFO +#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info + +#undef TARGET_CONDITIONAL_REGISTER_USAGE +#define TARGET_CONDITIONAL_REGISTER_USAGE spu_conditional_register_usage + +#undef TARGET_REF_MAY_ALIAS_ERRNO +#define TARGET_REF_MAY_ALIAS_ERRNO spu_ref_may_alias_errno + struct gcc_target targetm = TARGET_INITIALIZER; -void -spu_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED) +static void +spu_option_init_struct (struct gcc_options *opts) +{ + /* With so many registers this is better on by default. */ + opts->x_flag_rename_registers = 1; +} + +/* Implement TARGET_OPTION_DEFAULT_PARAMS. */ +static void +spu_option_default_params (void) { /* Override some of the default param values. With so many registers larger values are better for these params. */ - MAX_PENDING_LIST_LENGTH = 128; - - /* With so many registers this is better on by default. */ - flag_rename_registers = 1; -} - -/* Sometimes certain combinations of command options do not make sense - on a particular target machine. You can define a macro - OVERRIDE_OPTIONS to take account of this. This macro, if defined, is - executed once just after all the command options have been parsed. */ -void -spu_override_options (void) + set_default_param_value (PARAM_MAX_PENDING_LIST_LENGTH, 128); +} + +/* Implement TARGET_OPTION_OVERRIDE. */ +static void +spu_option_override (void) { /* Small loops will be unpeeled at -O3. For SPU it is more important to keep code small by default. */ - if (!flag_unroll_loops && !flag_peel_loops - && !PARAM_SET_P (PARAM_MAX_COMPLETELY_PEEL_TIMES)) - PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES) = 1; + if (!flag_unroll_loops && !flag_peel_loops) + maybe_set_param_value (PARAM_MAX_COMPLETELY_PEEL_TIMES, 4, + global_options.x_param_values, + global_options_set.x_param_values); flag_omit_frame_pointer = 1; @@ -512,7 +545,7 @@ else if (strcmp (&spu_arch_string[0], "celledp") == 0) spu_arch = PROCESSOR_CELLEDP; else - error ("Unknown architecture '%s'", &spu_arch_string[0]); + error ("bad value (%s) for -march= switch", spu_arch_string); } /* Determine processor to tune for. */ @@ -523,7 +556,7 @@ else if (strcmp (&spu_tune_string[0], "celledp") == 0) spu_tune = PROCESSOR_CELLEDP; else - error ("Unknown architecture '%s'", &spu_tune_string[0]); + error ("bad value (%s) for -mtune= switch", spu_tune_string); } /* Change defaults according to the processor architecture. */ @@ -722,9 +755,9 @@ HOST_WIDE_INT width = INTVAL (ops[1]); HOST_WIDE_INT start = INTVAL (ops[2]); HOST_WIDE_INT maskbits; - enum machine_mode dst_mode, src_mode; + enum machine_mode dst_mode; rtx dst = ops[0], src = ops[3]; - int dst_size, src_size; + int dst_size; rtx mask; rtx shift_reg; int shift; @@ -744,8 +777,6 @@ src = force_reg (m, convert_to_mode (m, src, 0)); } src = adjust_operand (src, 0); - src_mode = GET_MODE (src); - src_size = GET_MODE_BITSIZE (GET_MODE (src)); mask = gen_reg_rtx (dst_mode); shift_reg = gen_reg_rtx (dst_mode); @@ -1139,7 +1170,7 @@ if (eq_rtx == 0) abort (); emit_insn (eq_rtx); - ior_code = ior_optab->handlers[(int)comp_mode].insn_code; + ior_code = optab_handler (ior_optab, comp_mode); gcc_assert (ior_code != CODE_FOR_nothing); emit_insn (GEN_FCN (ior_code) (compare_result, compare_result, eq_result)); @@ -1696,8 +1727,6 @@ gcc_unreachable (); } -extern char call_used_regs[]; - /* For PIC mode we've reserved PIC_OFFSET_TABLE_REGNUM, which is a caller saved register. For leaf functions it is more efficient to use a volatile register because we won't need to save and restore the @@ -2061,6 +2090,8 @@ } } + if (flag_stack_usage) + current_function_static_stack_size = total_size; } void @@ -2239,6 +2270,7 @@ else new_insn = emit_insn_after (gen_lnop (), insn); recog_memoized (new_insn); + INSN_LOCATOR (new_insn) = INSN_LOCATOR (insn); } /* Insert nops in basic blocks to meet dual issue alignment @@ -2277,6 +2309,7 @@ prev_insn = emit_insn_before (gen_lnop (), insn); PUT_MODE (prev_insn, GET_MODE (insn)); PUT_MODE (insn, TImode); + INSN_LOCATOR (prev_insn) = INSN_LOCATOR (insn); length += 4; } } @@ -2333,7 +2366,7 @@ return; /* If we have a Basic block note, emit it after the basic block note. */ - if (NOTE_KIND (before) == NOTE_INSN_BASIC_BLOCK) + if (NOTE_INSN_BASIC_BLOCK_P (before)) before = NEXT_INSN (before); branch_label = gen_label_rtx (); @@ -2345,6 +2378,7 @@ hint = emit_insn_before (gen_hbr (branch_label, target), before); recog_memoized (hint); + INSN_LOCATOR (hint) = INSN_LOCATOR (branch); HINTED_P (branch) = 1; if (GET_CODE (target) == LABEL_REF) @@ -2365,7 +2399,9 @@ { /* Make sure the hint isn't scheduled any earlier than this point, which could make it too far for the branch offest to fit */ - recog_memoized (emit_insn_before (gen_blockage (), hint)); + insn = emit_insn_before (gen_blockage (), hint); + recog_memoized (insn); + INSN_LOCATOR (insn) = INSN_LOCATOR (hint); } else if (distance <= 8 * 4) { @@ -2377,14 +2413,21 @@ insn = emit_insn_after (gen_nopn_nv (gen_rtx_REG (SImode, 127)), hint); recog_memoized (insn); + INSN_LOCATOR (insn) = INSN_LOCATOR (hint); } /* Make sure any nops inserted aren't scheduled before the hint. */ - recog_memoized (emit_insn_after (gen_blockage (), hint)); + insn = emit_insn_after (gen_blockage (), hint); + recog_memoized (insn); + INSN_LOCATOR (insn) = INSN_LOCATOR (hint); /* Make sure any nops inserted aren't scheduled after the call. */ if (CALL_P (branch) && distance < 8 * 4) - recog_memoized (emit_insn_before (gen_blockage (), branch)); + { + insn = emit_insn_before (gen_blockage (), branch); + recog_memoized (insn); + INSN_LOCATOR (insn) = INSN_LOCATOR (branch); + } } } @@ -2569,6 +2612,7 @@ insn = emit_insn_before (gen_iprefetch (GEN_INT (1)), before_4); recog_memoized (insn); + INSN_LOCATOR (insn) = INSN_LOCATOR (before_4); INSN_ADDRESSES_NEW (insn, INSN_ADDRESSES (INSN_UID (before_4))); PUT_MODE (insn, GET_MODE (before_4)); @@ -2577,6 +2621,7 @@ { insn = emit_insn_before (gen_lnop (), before_4); recog_memoized (insn); + INSN_LOCATOR (insn) = INSN_LOCATOR (before_4); INSN_ADDRESSES_NEW (insn, INSN_ADDRESSES (INSN_UID (before_4))); PUT_MODE (insn, TImode); @@ -2588,6 +2633,7 @@ insn = emit_insn_before (gen_iprefetch (GEN_INT (2)), before_16); recog_memoized (insn); + INSN_LOCATOR (insn) = INSN_LOCATOR (before_16); INSN_ADDRESSES_NEW (insn, INSN_ADDRESSES (INSN_UID (before_16))); PUT_MODE (insn, GET_MODE (before_16)); @@ -2596,6 +2642,7 @@ { insn = emit_insn_before (gen_lnop (), before_16); recog_memoized (insn); + INSN_LOCATOR (insn) = INSN_LOCATOR (before_16); INSN_ADDRESSES_NEW (insn, INSN_ADDRESSES (INSN_UID (before_16))); @@ -2838,6 +2885,7 @@ /* The hints need to be scheduled, so call it again. */ schedule_insns (); + df_finish_pass (true); insert_hbrp (); @@ -3989,14 +4037,14 @@ return gen_rtx_REG (mode, FIRST_RETURN_REGNUM); } -rtx -spu_function_arg (CUMULATIVE_ARGS cum, +static rtx +spu_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, - tree type, int named ATTRIBUTE_UNUSED) + const_tree type, bool named ATTRIBUTE_UNUSED) { int byte_size; - if (cum >= MAX_REGISTER_ARGS) + if (*cum >= MAX_REGISTER_ARGS) return 0; byte_size = ((mode == BLKmode) @@ -4004,7 +4052,7 @@ /* The ABI does not allow parameters to be passed partially in reg and partially in stack. */ - if ((cum + (byte_size + 15) / 16) > MAX_REGISTER_ARGS) + if ((*cum + (byte_size + 15) / 16) > MAX_REGISTER_ARGS) return 0; /* Make sure small structs are left justified in a register. */ @@ -4017,12 +4065,25 @@ byte_size = 4; smode = smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT); gr_reg = gen_rtx_EXPR_LIST (VOIDmode, - gen_rtx_REG (smode, FIRST_ARG_REGNUM + cum), + gen_rtx_REG (smode, FIRST_ARG_REGNUM + *cum), const0_rtx); return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg)); } else - return gen_rtx_REG (mode, FIRST_ARG_REGNUM + cum); + return gen_rtx_REG (mode, FIRST_ARG_REGNUM + *cum); +} + +static void +spu_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode, + const_tree type, bool named ATTRIBUTE_UNUSED) +{ + *cum += (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST + ? 1 + : mode == BLKmode + ? ((int_size_in_bytes (type) + 15) / 16) + : mode == VOIDmode + ? 1 + : HARD_REGNO_NREGS (cum, mode)); } /* Variable sized types are passed by reference. */ @@ -4076,10 +4137,10 @@ DECL_ALIGN (f_skip) = 128; DECL_USER_ALIGN (f_skip) = 1; - TREE_CHAIN (record) = type_decl; + TYPE_STUB_DECL (record) = type_decl; TYPE_NAME (record) = type_decl; TYPE_FIELDS (record) = f_args; - TREE_CHAIN (f_args) = f_skip; + DECL_CHAIN (f_args) = f_skip; /* We know this is being padded and we want it too. It is an internal type so hide the warnings from the user. */ @@ -4114,9 +4175,9 @@ tree args, skip, t; f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); - f_skip = TREE_CHAIN (f_args); - - valist = build_va_arg_indirect_ref (valist); + f_skip = DECL_CHAIN (f_args); + + valist = build_simple_mem_ref (valist); args = build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); skip = @@ -4169,9 +4230,9 @@ bool pass_by_reference_p; f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); - f_skip = TREE_CHAIN (f_args); - - valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); + f_skip = DECL_CHAIN (f_args); + + valist = build_simple_mem_ref (valist); args = build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); skip = @@ -4233,7 +4294,7 @@ /* cum currently points to the last named argument, we want to start at the next argument. */ - FUNCTION_ARG_ADVANCE (ncum, mode, type, 1); + spu_function_arg_advance (&ncum, mode, type, true); offset = -STACK_POINTER_OFFSET; for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++) @@ -4249,7 +4310,7 @@ } } -void +static void spu_conditional_register_usage (void) { if (flag_pic) @@ -4488,8 +4549,7 @@ hit_ref, pc_rtx))); /* Say that this branch is very likely to happen. */ v = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100 - 1; - REG_NOTES (insn) - = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (v), REG_NOTES (insn)); + add_reg_note (insn, REG_BR_PROB, GEN_INT (v)); ea_load_store (mem, is_store, ea_addr, data_addr); cont_label = gen_label_rtx (); @@ -4571,7 +4631,13 @@ spu_expand_mov (rtx * ops, enum machine_mode mode) { if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0])) - abort (); + { + /* Perform the move in the destination SUBREG's inner mode. */ + ops[0] = SUBREG_REG (ops[0]); + mode = GET_MODE (ops[0]); + ops[1] = gen_lowpart_common (mode, ops[1]); + gcc_assert (ops[1]); + } if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1])) { @@ -4589,7 +4655,8 @@ if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (imode)) { - enum insn_code icode = convert_optab_handler (trunc_optab, mode, imode)->insn_code; + enum insn_code icode = convert_optab_handler (trunc_optab, + mode, imode); emit_insn (GEN_FCN (icode) (ops[0], from)); } else @@ -4936,6 +5003,7 @@ } } + gcc_assert (aform == 0 || aform == 1); reg = gen_reg_rtx (TImode); scalar = store_with_one_insn_p (ops[0]); @@ -5573,6 +5641,19 @@ set_conv_libfunc (ufloat_optab, DFmode, SImode, "__float_unssidf"); set_conv_libfunc (ufloat_optab, DFmode, DImode, "__float_unsdidf"); + set_optab_libfunc (addv_optab, SImode, "__addvsi3"); + set_optab_libfunc (subv_optab, SImode, "__subvsi3"); + set_optab_libfunc (smulv_optab, SImode, "__mulvsi3"); + set_optab_libfunc (sdivv_optab, SImode, "__divvsi3"); + set_optab_libfunc (negv_optab, SImode, "__negvsi2"); + set_optab_libfunc (absv_optab, SImode, "__absvsi2"); + set_optab_libfunc (addv_optab, DImode, "__addvdi3"); + set_optab_libfunc (subv_optab, DImode, "__subvdi3"); + set_optab_libfunc (smulv_optab, DImode, "__mulvdi3"); + set_optab_libfunc (sdivv_optab, DImode, "__divvdi3"); + set_optab_libfunc (negv_optab, DImode, "__negvdi2"); + set_optab_libfunc (absv_optab, DImode, "__absvdi2"); + set_optab_libfunc (smul_optab, TImode, "__multi3"); set_optab_libfunc (sdiv_optab, TImode, "__divti3"); set_optab_libfunc (smod_optab, TImode, "__modti3"); @@ -5617,12 +5698,14 @@ struct spu_builtin_description spu_builtins[] = { #define DEF_BUILTIN(fcode, icode, name, type, params) \ - {fcode, icode, name, type, params, NULL_TREE}, + {fcode, icode, name, type, params}, #include "spu-builtins.def" #undef DEF_BUILTIN }; -/* Returns the rs6000 builtin decl for CODE. */ +static GTY(()) tree spu_builtin_decls[NUM_SPU_BUILTINS]; + +/* Returns the spu builtin decl for CODE. */ static tree spu_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) @@ -5630,7 +5713,7 @@ if (code >= NUM_SPU_BUILTINS) return error_mark_node; - return spu_builtins[code].fndecl; + return spu_builtin_decls[code]; } @@ -5708,14 +5791,13 @@ p = build_function_type (spu_builtin_types[d->parm[0]], p); sprintf (name, "__builtin_%s", d->name); - d->fndecl = - add_builtin_function (name, p, END_BUILTINS + i, BUILT_IN_MD, - NULL, NULL_TREE); + spu_builtin_decls[i] = + add_builtin_function (name, p, i, BUILT_IN_MD, NULL, NULL_TREE); if (d->fcode == SPU_MASK_FOR_LOAD) - TREE_READONLY (d->fndecl) = 1; + TREE_READONLY (spu_builtin_decls[i]) = 1; /* These builtins don't throw. */ - TREE_NOTHROW (d->fndecl) = 1; + TREE_NOTHROW (spu_builtin_decls[i]) = 1; } } @@ -6252,7 +6334,7 @@ { enum insn_code nor_code; rtx eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode); - nor_code = optab_handler (one_cmpl_optab, (int)dest_mode)->insn_code; + nor_code = optab_handler (one_cmpl_optab, dest_mode); gcc_assert (nor_code != CODE_FOR_nothing); emit_insn (GEN_FCN (nor_code) (mask, eq_rtx)); if (dmode != dest_mode) @@ -6287,7 +6369,7 @@ c_rtx = spu_emit_vector_compare (new_code, op0, op1, dest_mode); eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode); - ior_code = optab_handler (ior_optab, (int)dest_mode)->insn_code; + ior_code = optab_handler (ior_optab, dest_mode); gcc_assert (ior_code != CODE_FOR_nothing); emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx)); if (dmode != dest_mode) @@ -6385,7 +6467,7 @@ int range = p - SPU_BTI_7; if (!CONSTANT_P (op)) - error ("%s expects an integer literal in the range [%d, %d].", + error ("%s expects an integer literal in the range [%d, %d]", d->name, spu_builtin_range[range].low, spu_builtin_range[range].high); @@ -6405,8 +6487,7 @@ /* The default for v is 0 which is valid in every range. */ if (v < spu_builtin_range[range].low || v > spu_builtin_range[range].high) - error ("%s expects an integer literal in the range [%d, %d]. (" - HOST_WIDE_INT_PRINT_DEC ")", + error ("%s expects an integer literal in the range [%d, %d]. (%wd)", d->name, spu_builtin_range[range].low, spu_builtin_range[range].high, v); @@ -6435,7 +6516,7 @@ || (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (op)) || (v & ((1 << lsbits) - 1)) != 0) - warning (0, "%d least significant bits of %s are ignored.", lsbits, + warning (0, "%d least significant bits of %s are ignored", lsbits, d->name); } } @@ -6515,7 +6596,7 @@ /* get addr */ arg = CALL_EXPR_ARG (exp, 0); - gcc_assert (TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE); + gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg))); op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL); addr = memory_address (mode, op); @@ -6638,7 +6719,7 @@ int ignore ATTRIBUTE_UNUSED) { tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); - unsigned int fcode = DECL_FUNCTION_CODE (fndecl) - END_BUILTINS; + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); struct spu_builtin_description *d; if (fcode < NUM_SPU_BUILTINS) @@ -6658,9 +6739,9 @@ { case V8HImode: if (TYPE_UNSIGNED (type)) - return spu_builtins[SPU_MULE_0].fndecl; + return spu_builtin_decls[SPU_MULE_0]; else - return spu_builtins[SPU_MULE_1].fndecl; + return spu_builtin_decls[SPU_MULE_1]; break; default: return NULL_TREE; @@ -6675,9 +6756,9 @@ { case V8HImode: if (TYPE_UNSIGNED (type)) - return spu_builtins[SPU_MULO_1].fndecl; + return spu_builtin_decls[SPU_MULO_1]; else - return spu_builtins[SPU_MULO_0].fndecl; + return spu_builtin_decls[SPU_MULO_0]; break; default: return NULL_TREE; @@ -6688,24 +6769,43 @@ static tree spu_builtin_mask_for_load (void) { - struct spu_builtin_description *d = &spu_builtins[SPU_MASK_FOR_LOAD]; - gcc_assert (d); - return d->fndecl; + return spu_builtin_decls[SPU_MASK_FOR_LOAD]; } /* Implement targetm.vectorize.builtin_vectorization_cost. */ static int -spu_builtin_vectorization_cost (bool runtime_test) -{ - /* If the branch of the runtime test is taken - i.e. - the vectorized - version is skipped - this incurs a misprediction cost (because the - vectorized version is expected to be the fall-through). So we subtract - the latency of a mispredicted branch from the costs that are incurred - when the vectorized version is executed. */ - if (runtime_test) - return -19; - else - return 0; +spu_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, + tree vectype ATTRIBUTE_UNUSED, + int misalign ATTRIBUTE_UNUSED) +{ + switch (type_of_cost) + { + case scalar_stmt: + case vector_stmt: + case vector_load: + case vector_store: + case vec_to_scalar: + case scalar_to_vec: + case cond_branch_not_taken: + case vec_perm: + return 1; + + case scalar_store: + return 10; + + case scalar_load: + /* Load + rotate. */ + return 2; + + case unaligned_load: + return 2; + + case cond_branch_taken: + return 6; + + default: + gcc_unreachable (); + } } /* Return true iff, data reference of TYPE can reach vector alignment (16) @@ -6726,54 +6826,43 @@ tree spu_builtin_vec_perm (tree type, tree *mask_element_type) { - struct spu_builtin_description *d; - *mask_element_type = unsigned_char_type_node; switch (TYPE_MODE (type)) { case V16QImode: if (TYPE_UNSIGNED (type)) - d = &spu_builtins[SPU_SHUFFLE_0]; + return spu_builtin_decls[SPU_SHUFFLE_0]; else - d = &spu_builtins[SPU_SHUFFLE_1]; - break; + return spu_builtin_decls[SPU_SHUFFLE_1]; case V8HImode: if (TYPE_UNSIGNED (type)) - d = &spu_builtins[SPU_SHUFFLE_2]; + return spu_builtin_decls[SPU_SHUFFLE_2]; else - d = &spu_builtins[SPU_SHUFFLE_3]; - break; + return spu_builtin_decls[SPU_SHUFFLE_3]; case V4SImode: if (TYPE_UNSIGNED (type)) - d = &spu_builtins[SPU_SHUFFLE_4]; + return spu_builtin_decls[SPU_SHUFFLE_4]; else - d = &spu_builtins[SPU_SHUFFLE_5]; - break; + return spu_builtin_decls[SPU_SHUFFLE_5]; case V2DImode: if (TYPE_UNSIGNED (type)) - d = &spu_builtins[SPU_SHUFFLE_6]; + return spu_builtin_decls[SPU_SHUFFLE_6]; else - d = &spu_builtins[SPU_SHUFFLE_7]; - break; + return spu_builtin_decls[SPU_SHUFFLE_7]; case V4SFmode: - d = &spu_builtins[SPU_SHUFFLE_8]; - break; + return spu_builtin_decls[SPU_SHUFFLE_8]; case V2DFmode: - d = &spu_builtins[SPU_SHUFFLE_9]; - break; + return spu_builtin_decls[SPU_SHUFFLE_9]; default: return NULL_TREE; } - - gcc_assert (d); - return d->fndecl; } /* Return the appropriate mode for a named address pointer. */ @@ -6898,8 +6987,8 @@ rtx insn = g->nodes[i].insn; int p = get_pipe (insn) + 2; - assert (p >= 0); - assert (p < 4); + gcc_assert (p >= 0); + gcc_assert (p < 4); t[p]++; if (dump_file && INSN_P (insn)) @@ -6961,9 +7050,17 @@ asm_file_start (void) { /* Variable tracking should be run after all optimizations which - change order of insns. It also needs a valid CFG. */ - spu_flag_var_tracking = flag_var_tracking; - flag_var_tracking = 0; + change order of insns. It also needs a valid CFG. Therefore, + *if* we make nontrivial changes in machine-dependent reorg, + run variable tracking after those. However, if we do not run + our machine-dependent reorg pass, we must still run the normal + variable tracking pass (or else we will ICE in final since + debug insns have not been removed). */ + if (TARGET_BRANCH_HINTS && optimize) + { + spu_flag_var_tracking = flag_var_tracking; + flag_var_tracking = 0; + } default_file_start (); } @@ -7064,10 +7161,34 @@ } void -spu_function_profiler (FILE * file, int labelno) +spu_function_profiler (FILE * file, int labelno ATTRIBUTE_UNUSED) { fprintf (file, "# profile\n"); fprintf (file, "brsl $75, _mcount\n"); } +/* Implement targetm.ref_may_alias_errno. */ +static bool +spu_ref_may_alias_errno (ao_ref *ref) +{ + tree base = ao_ref_base (ref); + + /* With SPU newlib, errno is defined as something like + _impure_data._errno + The default implementation of this target macro does not + recognize such expressions, so special-code for it here. */ + + if (TREE_CODE (base) == VAR_DECL + && !TREE_STATIC (base) + && DECL_EXTERNAL (base) + && TREE_CODE (TREE_TYPE (base)) == RECORD_TYPE + && strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (base)), + "_impure_data") == 0 + /* _errno is the first member of _impure_data. */ + && ref->offset == 0) + return true; + + return default_ref_may_alias_errno (ref); +} + #include "gt-spu.h"