Mercurial > hg > CbC > CbC_gcc
comparison 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 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
33 #include "except.h" | 33 #include "except.h" |
34 #include "function.h" | 34 #include "function.h" |
35 #include "output.h" | 35 #include "output.h" |
36 #include "basic-block.h" | 36 #include "basic-block.h" |
37 #include "integrate.h" | 37 #include "integrate.h" |
38 #include "toplev.h" | 38 #include "diagnostic-core.h" |
39 #include "ggc.h" | 39 #include "ggc.h" |
40 #include "hashtab.h" | 40 #include "hashtab.h" |
41 #include "tm_p.h" | 41 #include "tm_p.h" |
42 #include "target.h" | 42 #include "target.h" |
43 #include "target-def.h" | 43 #include "target-def.h" |
44 #include "langhooks.h" | 44 #include "langhooks.h" |
45 #include "reload.h" | 45 #include "reload.h" |
46 #include "cfglayout.h" | 46 #include "cfglayout.h" |
47 #include "sched-int.h" | 47 #include "sched-int.h" |
48 #include "params.h" | 48 #include "params.h" |
49 #include "assert.h" | |
50 #include "machmode.h" | 49 #include "machmode.h" |
51 #include "gimple.h" | 50 #include "gimple.h" |
52 #include "tm-constrs.h" | 51 #include "tm-constrs.h" |
53 #include "ddg.h" | 52 #include "ddg.h" |
54 #include "sbitmap.h" | 53 #include "sbitmap.h" |
146 | 145 |
147 /* Target specific attribute specifications. */ | 146 /* Target specific attribute specifications. */ |
148 char regs_ever_allocated[FIRST_PSEUDO_REGISTER]; | 147 char regs_ever_allocated[FIRST_PSEUDO_REGISTER]; |
149 | 148 |
150 /* Prototypes and external defs. */ | 149 /* Prototypes and external defs. */ |
150 static void spu_option_override (void); | |
151 static void spu_option_init_struct (struct gcc_options *opts); | |
152 static void spu_option_default_params (void); | |
151 static void spu_init_builtins (void); | 153 static void spu_init_builtins (void); |
152 static tree spu_builtin_decl (unsigned, bool); | 154 static tree spu_builtin_decl (unsigned, bool); |
153 static unsigned char spu_scalar_mode_supported_p (enum machine_mode mode); | 155 static bool spu_scalar_mode_supported_p (enum machine_mode mode); |
154 static unsigned char spu_vector_mode_supported_p (enum machine_mode mode); | 156 static bool spu_vector_mode_supported_p (enum machine_mode mode); |
155 static bool spu_legitimate_address_p (enum machine_mode, rtx, bool); | 157 static bool spu_legitimate_address_p (enum machine_mode, rtx, bool); |
156 static bool spu_addr_space_legitimate_address_p (enum machine_mode, rtx, | 158 static bool spu_addr_space_legitimate_address_p (enum machine_mode, rtx, |
157 bool, addr_space_t); | 159 bool, addr_space_t); |
158 static rtx adjust_operand (rtx op, HOST_WIDE_INT * start); | 160 static rtx adjust_operand (rtx op, HOST_WIDE_INT * start); |
159 static rtx get_pic_reg (void); | 161 static rtx get_pic_reg (void); |
178 static void spu_sched_init_global (FILE *, int, int); | 180 static void spu_sched_init_global (FILE *, int, int); |
179 static void spu_sched_init (FILE *, int, int); | 181 static void spu_sched_init (FILE *, int, int); |
180 static int spu_sched_reorder (FILE *, int, rtx *, int *, int); | 182 static int spu_sched_reorder (FILE *, int, rtx *, int *, int); |
181 static tree spu_handle_fndecl_attribute (tree * node, tree name, tree args, | 183 static tree spu_handle_fndecl_attribute (tree * node, tree name, tree args, |
182 int flags, | 184 int flags, |
183 unsigned char *no_add_attrs); | 185 bool *no_add_attrs); |
184 static tree spu_handle_vector_attribute (tree * node, tree name, tree args, | 186 static tree spu_handle_vector_attribute (tree * node, tree name, tree args, |
185 int flags, | 187 int flags, |
186 unsigned char *no_add_attrs); | 188 bool *no_add_attrs); |
187 static int spu_naked_function_p (tree func); | 189 static int spu_naked_function_p (tree func); |
188 static unsigned char spu_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 190 static bool spu_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
189 const_tree type, unsigned char named); | 191 const_tree type, bool named); |
192 static rtx spu_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, | |
193 const_tree type, bool named); | |
194 static void spu_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, | |
195 const_tree type, bool named); | |
190 static tree spu_build_builtin_va_list (void); | 196 static tree spu_build_builtin_va_list (void); |
191 static void spu_va_start (tree, rtx); | 197 static void spu_va_start (tree, rtx); |
192 static tree spu_gimplify_va_arg_expr (tree valist, tree type, | 198 static tree spu_gimplify_va_arg_expr (tree valist, tree type, |
193 gimple_seq * pre_p, gimple_seq * post_p); | 199 gimple_seq * pre_p, gimple_seq * post_p); |
194 static int store_with_one_insn_p (rtx mem); | 200 static int store_with_one_insn_p (rtx mem); |
195 static int mem_is_padded_component_ref (rtx x); | 201 static int mem_is_padded_component_ref (rtx x); |
196 static int reg_aligned_for_addr (rtx x); | 202 static int reg_aligned_for_addr (rtx x); |
197 static bool spu_assemble_integer (rtx x, unsigned int size, int aligned_p); | 203 static bool spu_assemble_integer (rtx x, unsigned int size, int aligned_p); |
198 static void spu_asm_globalize_label (FILE * file, const char *name); | 204 static void spu_asm_globalize_label (FILE * file, const char *name); |
199 static unsigned char spu_rtx_costs (rtx x, int code, int outer_code, | 205 static bool spu_rtx_costs (rtx x, int code, int outer_code, |
200 int *total, bool speed); | 206 int *total, bool speed); |
201 static unsigned char spu_function_ok_for_sibcall (tree decl, tree exp); | 207 static bool spu_function_ok_for_sibcall (tree decl, tree exp); |
202 static void spu_init_libfuncs (void); | 208 static void spu_init_libfuncs (void); |
203 static bool spu_return_in_memory (const_tree type, const_tree fntype); | 209 static bool spu_return_in_memory (const_tree type, const_tree fntype); |
204 static void fix_range (const char *); | 210 static void fix_range (const char *); |
205 static void spu_encode_section_info (tree, rtx, int); | 211 static void spu_encode_section_info (tree, rtx, int); |
206 static rtx spu_legitimize_address (rtx, rtx, enum machine_mode); | 212 static rtx spu_legitimize_address (rtx, rtx, enum machine_mode); |
207 static rtx spu_addr_space_legitimize_address (rtx, rtx, enum machine_mode, | 213 static rtx spu_addr_space_legitimize_address (rtx, rtx, enum machine_mode, |
208 addr_space_t); | 214 addr_space_t); |
209 static tree spu_builtin_mul_widen_even (tree); | 215 static tree spu_builtin_mul_widen_even (tree); |
210 static tree spu_builtin_mul_widen_odd (tree); | 216 static tree spu_builtin_mul_widen_odd (tree); |
211 static tree spu_builtin_mask_for_load (void); | 217 static tree spu_builtin_mask_for_load (void); |
212 static int spu_builtin_vectorization_cost (bool); | 218 static int spu_builtin_vectorization_cost (enum vect_cost_for_stmt, tree, int); |
213 static bool spu_vector_alignment_reachable (const_tree, bool); | 219 static bool spu_vector_alignment_reachable (const_tree, bool); |
214 static tree spu_builtin_vec_perm (tree, tree *); | 220 static tree spu_builtin_vec_perm (tree, tree *); |
215 static enum machine_mode spu_addr_space_pointer_mode (addr_space_t); | 221 static enum machine_mode spu_addr_space_pointer_mode (addr_space_t); |
216 static enum machine_mode spu_addr_space_address_mode (addr_space_t); | 222 static enum machine_mode spu_addr_space_address_mode (addr_space_t); |
217 static bool spu_addr_space_subset_p (addr_space_t, addr_space_t); | 223 static bool spu_addr_space_subset_p (addr_space_t, addr_space_t); |
221 static unsigned int spu_section_type_flags (tree, const char *, int); | 227 static unsigned int spu_section_type_flags (tree, const char *, int); |
222 static section *spu_select_section (tree, int, unsigned HOST_WIDE_INT); | 228 static section *spu_select_section (tree, int, unsigned HOST_WIDE_INT); |
223 static void spu_unique_section (tree, int); | 229 static void spu_unique_section (tree, int); |
224 static rtx spu_expand_load (rtx, rtx, rtx, int); | 230 static rtx spu_expand_load (rtx, rtx, rtx, int); |
225 static void spu_trampoline_init (rtx, tree, rtx); | 231 static void spu_trampoline_init (rtx, tree, rtx); |
226 | 232 static void spu_conditional_register_usage (void); |
227 extern const char *reg_names[]; | 233 static bool spu_ref_may_alias_errno (ao_ref *); |
228 | 234 |
229 /* Which instruction set architecture to use. */ | 235 /* Which instruction set architecture to use. */ |
230 int spu_arch; | 236 int spu_arch; |
231 /* Which cpu are we tuning for. */ | 237 /* Which cpu are we tuning for. */ |
232 int spu_tune; | 238 int spu_tune; |
388 #define TARGET_ASM_GLOBALIZE_LABEL spu_asm_globalize_label | 394 #define TARGET_ASM_GLOBALIZE_LABEL spu_asm_globalize_label |
389 | 395 |
390 #undef TARGET_PASS_BY_REFERENCE | 396 #undef TARGET_PASS_BY_REFERENCE |
391 #define TARGET_PASS_BY_REFERENCE spu_pass_by_reference | 397 #define TARGET_PASS_BY_REFERENCE spu_pass_by_reference |
392 | 398 |
399 #undef TARGET_FUNCTION_ARG | |
400 #define TARGET_FUNCTION_ARG spu_function_arg | |
401 | |
402 #undef TARGET_FUNCTION_ARG_ADVANCE | |
403 #define TARGET_FUNCTION_ARG_ADVANCE spu_function_arg_advance | |
404 | |
393 #undef TARGET_MUST_PASS_IN_STACK | 405 #undef TARGET_MUST_PASS_IN_STACK |
394 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size | 406 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size |
395 | 407 |
396 #undef TARGET_BUILD_BUILTIN_VA_LIST | 408 #undef TARGET_BUILD_BUILTIN_VA_LIST |
397 #define TARGET_BUILD_BUILTIN_VA_LIST spu_build_builtin_va_list | 409 #define TARGET_BUILD_BUILTIN_VA_LIST spu_build_builtin_va_list |
430 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD spu_builtin_mask_for_load | 442 #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD spu_builtin_mask_for_load |
431 | 443 |
432 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST | 444 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST |
433 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST spu_builtin_vectorization_cost | 445 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST spu_builtin_vectorization_cost |
434 | 446 |
435 #undef TARGET_VECTOR_ALIGNMENT_REACHABLE | 447 #undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE |
436 #define TARGET_VECTOR_ALIGNMENT_REACHABLE spu_vector_alignment_reachable | 448 #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE spu_vector_alignment_reachable |
437 | 449 |
438 #undef TARGET_VECTORIZE_BUILTIN_VEC_PERM | 450 #undef TARGET_VECTORIZE_BUILTIN_VEC_PERM |
439 #define TARGET_VECTORIZE_BUILTIN_VEC_PERM spu_builtin_vec_perm | 451 #define TARGET_VECTORIZE_BUILTIN_VEC_PERM spu_builtin_vec_perm |
440 | 452 |
441 #undef TARGET_LIBGCC_CMP_RETURN_MODE | 453 #undef TARGET_LIBGCC_CMP_RETURN_MODE |
463 #define TARGET_LEGITIMATE_ADDRESS_P spu_legitimate_address_p | 475 #define TARGET_LEGITIMATE_ADDRESS_P spu_legitimate_address_p |
464 | 476 |
465 #undef TARGET_TRAMPOLINE_INIT | 477 #undef TARGET_TRAMPOLINE_INIT |
466 #define TARGET_TRAMPOLINE_INIT spu_trampoline_init | 478 #define TARGET_TRAMPOLINE_INIT spu_trampoline_init |
467 | 479 |
480 #undef TARGET_OPTION_OVERRIDE | |
481 #define TARGET_OPTION_OVERRIDE spu_option_override | |
482 | |
483 #undef TARGET_OPTION_INIT_STRUCT | |
484 #define TARGET_OPTION_INIT_STRUCT spu_option_init_struct | |
485 | |
486 #undef TARGET_OPTION_DEFAULT_PARAMS | |
487 #define TARGET_OPTION_DEFAULT_PARAMS spu_option_default_params | |
488 | |
489 #undef TARGET_EXCEPT_UNWIND_INFO | |
490 #define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info | |
491 | |
492 #undef TARGET_CONDITIONAL_REGISTER_USAGE | |
493 #define TARGET_CONDITIONAL_REGISTER_USAGE spu_conditional_register_usage | |
494 | |
495 #undef TARGET_REF_MAY_ALIAS_ERRNO | |
496 #define TARGET_REF_MAY_ALIAS_ERRNO spu_ref_may_alias_errno | |
497 | |
468 struct gcc_target targetm = TARGET_INITIALIZER; | 498 struct gcc_target targetm = TARGET_INITIALIZER; |
469 | 499 |
470 void | 500 static void |
471 spu_optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED) | 501 spu_option_init_struct (struct gcc_options *opts) |
502 { | |
503 /* With so many registers this is better on by default. */ | |
504 opts->x_flag_rename_registers = 1; | |
505 } | |
506 | |
507 /* Implement TARGET_OPTION_DEFAULT_PARAMS. */ | |
508 static void | |
509 spu_option_default_params (void) | |
472 { | 510 { |
473 /* Override some of the default param values. With so many registers | 511 /* Override some of the default param values. With so many registers |
474 larger values are better for these params. */ | 512 larger values are better for these params. */ |
475 MAX_PENDING_LIST_LENGTH = 128; | 513 set_default_param_value (PARAM_MAX_PENDING_LIST_LENGTH, 128); |
476 | 514 } |
477 /* With so many registers this is better on by default. */ | 515 |
478 flag_rename_registers = 1; | 516 /* Implement TARGET_OPTION_OVERRIDE. */ |
479 } | 517 static void |
480 | 518 spu_option_override (void) |
481 /* Sometimes certain combinations of command options do not make sense | |
482 on a particular target machine. You can define a macro | |
483 OVERRIDE_OPTIONS to take account of this. This macro, if defined, is | |
484 executed once just after all the command options have been parsed. */ | |
485 void | |
486 spu_override_options (void) | |
487 { | 519 { |
488 /* Small loops will be unpeeled at -O3. For SPU it is more important | 520 /* Small loops will be unpeeled at -O3. For SPU it is more important |
489 to keep code small by default. */ | 521 to keep code small by default. */ |
490 if (!flag_unroll_loops && !flag_peel_loops | 522 if (!flag_unroll_loops && !flag_peel_loops) |
491 && !PARAM_SET_P (PARAM_MAX_COMPLETELY_PEEL_TIMES)) | 523 maybe_set_param_value (PARAM_MAX_COMPLETELY_PEEL_TIMES, 4, |
492 PARAM_VALUE (PARAM_MAX_COMPLETELY_PEEL_TIMES) = 1; | 524 global_options.x_param_values, |
525 global_options_set.x_param_values); | |
493 | 526 |
494 flag_omit_frame_pointer = 1; | 527 flag_omit_frame_pointer = 1; |
495 | 528 |
496 /* Functions must be 8 byte aligned so we correctly handle dual issue */ | 529 /* Functions must be 8 byte aligned so we correctly handle dual issue */ |
497 if (align_functions < 8) | 530 if (align_functions < 8) |
510 if (strcmp (&spu_arch_string[0], "cell") == 0) | 543 if (strcmp (&spu_arch_string[0], "cell") == 0) |
511 spu_arch = PROCESSOR_CELL; | 544 spu_arch = PROCESSOR_CELL; |
512 else if (strcmp (&spu_arch_string[0], "celledp") == 0) | 545 else if (strcmp (&spu_arch_string[0], "celledp") == 0) |
513 spu_arch = PROCESSOR_CELLEDP; | 546 spu_arch = PROCESSOR_CELLEDP; |
514 else | 547 else |
515 error ("Unknown architecture '%s'", &spu_arch_string[0]); | 548 error ("bad value (%s) for -march= switch", spu_arch_string); |
516 } | 549 } |
517 | 550 |
518 /* Determine processor to tune for. */ | 551 /* Determine processor to tune for. */ |
519 if (spu_tune_string) | 552 if (spu_tune_string) |
520 { | 553 { |
521 if (strcmp (&spu_tune_string[0], "cell") == 0) | 554 if (strcmp (&spu_tune_string[0], "cell") == 0) |
522 spu_tune = PROCESSOR_CELL; | 555 spu_tune = PROCESSOR_CELL; |
523 else if (strcmp (&spu_tune_string[0], "celledp") == 0) | 556 else if (strcmp (&spu_tune_string[0], "celledp") == 0) |
524 spu_tune = PROCESSOR_CELLEDP; | 557 spu_tune = PROCESSOR_CELLEDP; |
525 else | 558 else |
526 error ("Unknown architecture '%s'", &spu_tune_string[0]); | 559 error ("bad value (%s) for -mtune= switch", spu_tune_string); |
527 } | 560 } |
528 | 561 |
529 /* Change defaults according to the processor architecture. */ | 562 /* Change defaults according to the processor architecture. */ |
530 if (spu_arch == PROCESSOR_CELLEDP) | 563 if (spu_arch == PROCESSOR_CELLEDP) |
531 { | 564 { |
720 spu_expand_insv (rtx ops[]) | 753 spu_expand_insv (rtx ops[]) |
721 { | 754 { |
722 HOST_WIDE_INT width = INTVAL (ops[1]); | 755 HOST_WIDE_INT width = INTVAL (ops[1]); |
723 HOST_WIDE_INT start = INTVAL (ops[2]); | 756 HOST_WIDE_INT start = INTVAL (ops[2]); |
724 HOST_WIDE_INT maskbits; | 757 HOST_WIDE_INT maskbits; |
725 enum machine_mode dst_mode, src_mode; | 758 enum machine_mode dst_mode; |
726 rtx dst = ops[0], src = ops[3]; | 759 rtx dst = ops[0], src = ops[3]; |
727 int dst_size, src_size; | 760 int dst_size; |
728 rtx mask; | 761 rtx mask; |
729 rtx shift_reg; | 762 rtx shift_reg; |
730 int shift; | 763 int shift; |
731 | 764 |
732 | 765 |
742 enum machine_mode m = | 775 enum machine_mode m = |
743 (width <= 32 ? SImode : width <= 64 ? DImode : TImode); | 776 (width <= 32 ? SImode : width <= 64 ? DImode : TImode); |
744 src = force_reg (m, convert_to_mode (m, src, 0)); | 777 src = force_reg (m, convert_to_mode (m, src, 0)); |
745 } | 778 } |
746 src = adjust_operand (src, 0); | 779 src = adjust_operand (src, 0); |
747 src_mode = GET_MODE (src); | |
748 src_size = GET_MODE_BITSIZE (GET_MODE (src)); | |
749 | 780 |
750 mask = gen_reg_rtx (dst_mode); | 781 mask = gen_reg_rtx (dst_mode); |
751 shift_reg = gen_reg_rtx (dst_mode); | 782 shift_reg = gen_reg_rtx (dst_mode); |
752 shift = dst_size - start - width; | 783 shift = dst_size - start - width; |
753 | 784 |
1137 eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result, | 1168 eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result, |
1138 op0, op1); | 1169 op0, op1); |
1139 if (eq_rtx == 0) | 1170 if (eq_rtx == 0) |
1140 abort (); | 1171 abort (); |
1141 emit_insn (eq_rtx); | 1172 emit_insn (eq_rtx); |
1142 ior_code = ior_optab->handlers[(int)comp_mode].insn_code; | 1173 ior_code = optab_handler (ior_optab, comp_mode); |
1143 gcc_assert (ior_code != CODE_FOR_nothing); | 1174 gcc_assert (ior_code != CODE_FOR_nothing); |
1144 emit_insn (GEN_FCN (ior_code) | 1175 emit_insn (GEN_FCN (ior_code) |
1145 (compare_result, compare_result, eq_result)); | 1176 (compare_result, compare_result, eq_result)); |
1146 } | 1177 } |
1147 } | 1178 } |
1693 default: | 1724 default: |
1694 output_operand_lossage ("invalid %%xn code"); | 1725 output_operand_lossage ("invalid %%xn code"); |
1695 } | 1726 } |
1696 gcc_unreachable (); | 1727 gcc_unreachable (); |
1697 } | 1728 } |
1698 | |
1699 extern char call_used_regs[]; | |
1700 | 1729 |
1701 /* For PIC mode we've reserved PIC_OFFSET_TABLE_REGNUM, which is a | 1730 /* For PIC mode we've reserved PIC_OFFSET_TABLE_REGNUM, which is a |
1702 caller saved register. For leaf functions it is more efficient to | 1731 caller saved register. For leaf functions it is more efficient to |
1703 use a volatile register because we won't need to save and restore the | 1732 use a volatile register because we won't need to save and restore the |
1704 pic register. This routine is only valid after register allocation | 1733 pic register. This routine is only valid after register allocation |
2059 add_reg_note (insn, REG_FRAME_RELATED_EXPR, real); | 2088 add_reg_note (insn, REG_FRAME_RELATED_EXPR, real); |
2060 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY; | 2089 REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY; |
2061 } | 2090 } |
2062 } | 2091 } |
2063 | 2092 |
2093 if (flag_stack_usage) | |
2094 current_function_static_stack_size = total_size; | |
2064 } | 2095 } |
2065 | 2096 |
2066 void | 2097 void |
2067 spu_expand_epilogue (bool sibcall_p) | 2098 spu_expand_epilogue (bool sibcall_p) |
2068 { | 2099 { |
2237 PUT_MODE (insn, VOIDmode); | 2268 PUT_MODE (insn, VOIDmode); |
2238 } | 2269 } |
2239 else | 2270 else |
2240 new_insn = emit_insn_after (gen_lnop (), insn); | 2271 new_insn = emit_insn_after (gen_lnop (), insn); |
2241 recog_memoized (new_insn); | 2272 recog_memoized (new_insn); |
2273 INSN_LOCATOR (new_insn) = INSN_LOCATOR (insn); | |
2242 } | 2274 } |
2243 | 2275 |
2244 /* Insert nops in basic blocks to meet dual issue alignment | 2276 /* Insert nops in basic blocks to meet dual issue alignment |
2245 requirements. Also make sure hbrp and hint instructions are at least | 2277 requirements. Also make sure hbrp and hint instructions are at least |
2246 one cycle apart, possibly inserting a nop. */ | 2278 one cycle apart, possibly inserting a nop. */ |
2275 || (a1 - a0 == 4)) | 2307 || (a1 - a0 == 4)) |
2276 { | 2308 { |
2277 prev_insn = emit_insn_before (gen_lnop (), insn); | 2309 prev_insn = emit_insn_before (gen_lnop (), insn); |
2278 PUT_MODE (prev_insn, GET_MODE (insn)); | 2310 PUT_MODE (prev_insn, GET_MODE (insn)); |
2279 PUT_MODE (insn, TImode); | 2311 PUT_MODE (insn, TImode); |
2312 INSN_LOCATOR (prev_insn) = INSN_LOCATOR (insn); | |
2280 length += 4; | 2313 length += 4; |
2281 } | 2314 } |
2282 } | 2315 } |
2283 hbr_insn = insn; | 2316 hbr_insn = insn; |
2284 } | 2317 } |
2331 we need to enforce that here too */ | 2364 we need to enforce that here too */ |
2332 if (distance > 600) | 2365 if (distance > 600) |
2333 return; | 2366 return; |
2334 | 2367 |
2335 /* If we have a Basic block note, emit it after the basic block note. */ | 2368 /* If we have a Basic block note, emit it after the basic block note. */ |
2336 if (NOTE_KIND (before) == NOTE_INSN_BASIC_BLOCK) | 2369 if (NOTE_INSN_BASIC_BLOCK_P (before)) |
2337 before = NEXT_INSN (before); | 2370 before = NEXT_INSN (before); |
2338 | 2371 |
2339 branch_label = gen_label_rtx (); | 2372 branch_label = gen_label_rtx (); |
2340 LABEL_NUSES (branch_label)++; | 2373 LABEL_NUSES (branch_label)++; |
2341 LABEL_PRESERVE_P (branch_label) = 1; | 2374 LABEL_PRESERVE_P (branch_label) = 1; |
2343 branch_label = gen_rtx_LABEL_REF (VOIDmode, branch_label); | 2376 branch_label = gen_rtx_LABEL_REF (VOIDmode, branch_label); |
2344 SET_BIT (blocks, BLOCK_FOR_INSN (branch)->index); | 2377 SET_BIT (blocks, BLOCK_FOR_INSN (branch)->index); |
2345 | 2378 |
2346 hint = emit_insn_before (gen_hbr (branch_label, target), before); | 2379 hint = emit_insn_before (gen_hbr (branch_label, target), before); |
2347 recog_memoized (hint); | 2380 recog_memoized (hint); |
2381 INSN_LOCATOR (hint) = INSN_LOCATOR (branch); | |
2348 HINTED_P (branch) = 1; | 2382 HINTED_P (branch) = 1; |
2349 | 2383 |
2350 if (GET_CODE (target) == LABEL_REF) | 2384 if (GET_CODE (target) == LABEL_REF) |
2351 HINTED_P (XEXP (target, 0)) = 1; | 2385 HINTED_P (XEXP (target, 0)) = 1; |
2352 else if (tablejump_p (branch, 0, &table)) | 2386 else if (tablejump_p (branch, 0, &table)) |
2363 | 2397 |
2364 if (distance >= 588) | 2398 if (distance >= 588) |
2365 { | 2399 { |
2366 /* Make sure the hint isn't scheduled any earlier than this point, | 2400 /* Make sure the hint isn't scheduled any earlier than this point, |
2367 which could make it too far for the branch offest to fit */ | 2401 which could make it too far for the branch offest to fit */ |
2368 recog_memoized (emit_insn_before (gen_blockage (), hint)); | 2402 insn = emit_insn_before (gen_blockage (), hint); |
2403 recog_memoized (insn); | |
2404 INSN_LOCATOR (insn) = INSN_LOCATOR (hint); | |
2369 } | 2405 } |
2370 else if (distance <= 8 * 4) | 2406 else if (distance <= 8 * 4) |
2371 { | 2407 { |
2372 /* To guarantee at least 8 insns between the hint and branch we | 2408 /* To guarantee at least 8 insns between the hint and branch we |
2373 insert nops. */ | 2409 insert nops. */ |
2375 for (d = distance; d < 8 * 4; d += 4) | 2411 for (d = distance; d < 8 * 4; d += 4) |
2376 { | 2412 { |
2377 insn = | 2413 insn = |
2378 emit_insn_after (gen_nopn_nv (gen_rtx_REG (SImode, 127)), hint); | 2414 emit_insn_after (gen_nopn_nv (gen_rtx_REG (SImode, 127)), hint); |
2379 recog_memoized (insn); | 2415 recog_memoized (insn); |
2416 INSN_LOCATOR (insn) = INSN_LOCATOR (hint); | |
2380 } | 2417 } |
2381 | 2418 |
2382 /* Make sure any nops inserted aren't scheduled before the hint. */ | 2419 /* Make sure any nops inserted aren't scheduled before the hint. */ |
2383 recog_memoized (emit_insn_after (gen_blockage (), hint)); | 2420 insn = emit_insn_after (gen_blockage (), hint); |
2421 recog_memoized (insn); | |
2422 INSN_LOCATOR (insn) = INSN_LOCATOR (hint); | |
2384 | 2423 |
2385 /* Make sure any nops inserted aren't scheduled after the call. */ | 2424 /* Make sure any nops inserted aren't scheduled after the call. */ |
2386 if (CALL_P (branch) && distance < 8 * 4) | 2425 if (CALL_P (branch) && distance < 8 * 4) |
2387 recog_memoized (emit_insn_before (gen_blockage (), branch)); | 2426 { |
2427 insn = emit_insn_before (gen_blockage (), branch); | |
2428 recog_memoized (insn); | |
2429 INSN_LOCATOR (insn) = INSN_LOCATOR (branch); | |
2430 } | |
2388 } | 2431 } |
2389 } | 2432 } |
2390 | 2433 |
2391 /* Returns 0 if we don't want a hint for this branch. Otherwise return | 2434 /* Returns 0 if we don't want a hint for this branch. Otherwise return |
2392 the rtx for the branch target. */ | 2435 the rtx for the branch target. */ |
2567 if (hbrp_addr0 > 4 * 4) | 2610 if (hbrp_addr0 > 4 * 4) |
2568 { | 2611 { |
2569 insn = | 2612 insn = |
2570 emit_insn_before (gen_iprefetch (GEN_INT (1)), before_4); | 2613 emit_insn_before (gen_iprefetch (GEN_INT (1)), before_4); |
2571 recog_memoized (insn); | 2614 recog_memoized (insn); |
2615 INSN_LOCATOR (insn) = INSN_LOCATOR (before_4); | |
2572 INSN_ADDRESSES_NEW (insn, | 2616 INSN_ADDRESSES_NEW (insn, |
2573 INSN_ADDRESSES (INSN_UID (before_4))); | 2617 INSN_ADDRESSES (INSN_UID (before_4))); |
2574 PUT_MODE (insn, GET_MODE (before_4)); | 2618 PUT_MODE (insn, GET_MODE (before_4)); |
2575 PUT_MODE (before_4, TImode); | 2619 PUT_MODE (before_4, TImode); |
2576 if (insert_lnop_after & 1) | 2620 if (insert_lnop_after & 1) |
2577 { | 2621 { |
2578 insn = emit_insn_before (gen_lnop (), before_4); | 2622 insn = emit_insn_before (gen_lnop (), before_4); |
2579 recog_memoized (insn); | 2623 recog_memoized (insn); |
2624 INSN_LOCATOR (insn) = INSN_LOCATOR (before_4); | |
2580 INSN_ADDRESSES_NEW (insn, | 2625 INSN_ADDRESSES_NEW (insn, |
2581 INSN_ADDRESSES (INSN_UID (before_4))); | 2626 INSN_ADDRESSES (INSN_UID (before_4))); |
2582 PUT_MODE (insn, TImode); | 2627 PUT_MODE (insn, TImode); |
2583 } | 2628 } |
2584 } | 2629 } |
2586 && hbrp_addr1 > 16 * 4) | 2631 && hbrp_addr1 > 16 * 4) |
2587 { | 2632 { |
2588 insn = | 2633 insn = |
2589 emit_insn_before (gen_iprefetch (GEN_INT (2)), before_16); | 2634 emit_insn_before (gen_iprefetch (GEN_INT (2)), before_16); |
2590 recog_memoized (insn); | 2635 recog_memoized (insn); |
2636 INSN_LOCATOR (insn) = INSN_LOCATOR (before_16); | |
2591 INSN_ADDRESSES_NEW (insn, | 2637 INSN_ADDRESSES_NEW (insn, |
2592 INSN_ADDRESSES (INSN_UID (before_16))); | 2638 INSN_ADDRESSES (INSN_UID (before_16))); |
2593 PUT_MODE (insn, GET_MODE (before_16)); | 2639 PUT_MODE (insn, GET_MODE (before_16)); |
2594 PUT_MODE (before_16, TImode); | 2640 PUT_MODE (before_16, TImode); |
2595 if (insert_lnop_after & 2) | 2641 if (insert_lnop_after & 2) |
2596 { | 2642 { |
2597 insn = emit_insn_before (gen_lnop (), before_16); | 2643 insn = emit_insn_before (gen_lnop (), before_16); |
2598 recog_memoized (insn); | 2644 recog_memoized (insn); |
2645 INSN_LOCATOR (insn) = INSN_LOCATOR (before_16); | |
2599 INSN_ADDRESSES_NEW (insn, | 2646 INSN_ADDRESSES_NEW (insn, |
2600 INSN_ADDRESSES (INSN_UID | 2647 INSN_ADDRESSES (INSN_UID |
2601 (before_16))); | 2648 (before_16))); |
2602 PUT_MODE (insn, TImode); | 2649 PUT_MODE (insn, TImode); |
2603 } | 2650 } |
2836 /* We have to schedule to make sure alignment is ok. */ | 2883 /* We have to schedule to make sure alignment is ok. */ |
2837 FOR_EACH_BB (bb) bb->flags &= ~BB_DISABLE_SCHEDULE; | 2884 FOR_EACH_BB (bb) bb->flags &= ~BB_DISABLE_SCHEDULE; |
2838 | 2885 |
2839 /* The hints need to be scheduled, so call it again. */ | 2886 /* The hints need to be scheduled, so call it again. */ |
2840 schedule_insns (); | 2887 schedule_insns (); |
2888 df_finish_pass (true); | |
2841 | 2889 |
2842 insert_hbrp (); | 2890 insert_hbrp (); |
2843 | 2891 |
2844 pad_bb (); | 2892 pad_bb (); |
2845 | 2893 |
3987 return gen_rtx_PARALLEL (mode, v); | 4035 return gen_rtx_PARALLEL (mode, v); |
3988 } | 4036 } |
3989 return gen_rtx_REG (mode, FIRST_RETURN_REGNUM); | 4037 return gen_rtx_REG (mode, FIRST_RETURN_REGNUM); |
3990 } | 4038 } |
3991 | 4039 |
3992 rtx | 4040 static rtx |
3993 spu_function_arg (CUMULATIVE_ARGS cum, | 4041 spu_function_arg (CUMULATIVE_ARGS *cum, |
3994 enum machine_mode mode, | 4042 enum machine_mode mode, |
3995 tree type, int named ATTRIBUTE_UNUSED) | 4043 const_tree type, bool named ATTRIBUTE_UNUSED) |
3996 { | 4044 { |
3997 int byte_size; | 4045 int byte_size; |
3998 | 4046 |
3999 if (cum >= MAX_REGISTER_ARGS) | 4047 if (*cum >= MAX_REGISTER_ARGS) |
4000 return 0; | 4048 return 0; |
4001 | 4049 |
4002 byte_size = ((mode == BLKmode) | 4050 byte_size = ((mode == BLKmode) |
4003 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode)); | 4051 ? int_size_in_bytes (type) : GET_MODE_SIZE (mode)); |
4004 | 4052 |
4005 /* The ABI does not allow parameters to be passed partially in | 4053 /* The ABI does not allow parameters to be passed partially in |
4006 reg and partially in stack. */ | 4054 reg and partially in stack. */ |
4007 if ((cum + (byte_size + 15) / 16) > MAX_REGISTER_ARGS) | 4055 if ((*cum + (byte_size + 15) / 16) > MAX_REGISTER_ARGS) |
4008 return 0; | 4056 return 0; |
4009 | 4057 |
4010 /* Make sure small structs are left justified in a register. */ | 4058 /* Make sure small structs are left justified in a register. */ |
4011 if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type))) | 4059 if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type))) |
4012 && byte_size < UNITS_PER_WORD && byte_size > 0) | 4060 && byte_size < UNITS_PER_WORD && byte_size > 0) |
4015 rtx gr_reg; | 4063 rtx gr_reg; |
4016 if (byte_size < 4) | 4064 if (byte_size < 4) |
4017 byte_size = 4; | 4065 byte_size = 4; |
4018 smode = smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT); | 4066 smode = smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT); |
4019 gr_reg = gen_rtx_EXPR_LIST (VOIDmode, | 4067 gr_reg = gen_rtx_EXPR_LIST (VOIDmode, |
4020 gen_rtx_REG (smode, FIRST_ARG_REGNUM + cum), | 4068 gen_rtx_REG (smode, FIRST_ARG_REGNUM + *cum), |
4021 const0_rtx); | 4069 const0_rtx); |
4022 return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg)); | 4070 return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg)); |
4023 } | 4071 } |
4024 else | 4072 else |
4025 return gen_rtx_REG (mode, FIRST_ARG_REGNUM + cum); | 4073 return gen_rtx_REG (mode, FIRST_ARG_REGNUM + *cum); |
4074 } | |
4075 | |
4076 static void | |
4077 spu_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode, | |
4078 const_tree type, bool named ATTRIBUTE_UNUSED) | |
4079 { | |
4080 *cum += (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST | |
4081 ? 1 | |
4082 : mode == BLKmode | |
4083 ? ((int_size_in_bytes (type) + 15) / 16) | |
4084 : mode == VOIDmode | |
4085 ? 1 | |
4086 : HARD_REGNO_NREGS (cum, mode)); | |
4026 } | 4087 } |
4027 | 4088 |
4028 /* Variable sized types are passed by reference. */ | 4089 /* Variable sized types are passed by reference. */ |
4029 static bool | 4090 static bool |
4030 spu_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED, | 4091 spu_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED, |
4074 | 4135 |
4075 DECL_FIELD_CONTEXT (f_skip) = record; | 4136 DECL_FIELD_CONTEXT (f_skip) = record; |
4076 DECL_ALIGN (f_skip) = 128; | 4137 DECL_ALIGN (f_skip) = 128; |
4077 DECL_USER_ALIGN (f_skip) = 1; | 4138 DECL_USER_ALIGN (f_skip) = 1; |
4078 | 4139 |
4079 TREE_CHAIN (record) = type_decl; | 4140 TYPE_STUB_DECL (record) = type_decl; |
4080 TYPE_NAME (record) = type_decl; | 4141 TYPE_NAME (record) = type_decl; |
4081 TYPE_FIELDS (record) = f_args; | 4142 TYPE_FIELDS (record) = f_args; |
4082 TREE_CHAIN (f_args) = f_skip; | 4143 DECL_CHAIN (f_args) = f_skip; |
4083 | 4144 |
4084 /* We know this is being padded and we want it too. It is an internal | 4145 /* We know this is being padded and we want it too. It is an internal |
4085 type so hide the warnings from the user. */ | 4146 type so hide the warnings from the user. */ |
4086 owp = warn_padded; | 4147 owp = warn_padded; |
4087 warn_padded = false; | 4148 warn_padded = false; |
4112 { | 4173 { |
4113 tree f_args, f_skip; | 4174 tree f_args, f_skip; |
4114 tree args, skip, t; | 4175 tree args, skip, t; |
4115 | 4176 |
4116 f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); | 4177 f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); |
4117 f_skip = TREE_CHAIN (f_args); | 4178 f_skip = DECL_CHAIN (f_args); |
4118 | 4179 |
4119 valist = build_va_arg_indirect_ref (valist); | 4180 valist = build_simple_mem_ref (valist); |
4120 args = | 4181 args = |
4121 build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); | 4182 build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); |
4122 skip = | 4183 skip = |
4123 build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE); | 4184 build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE); |
4124 | 4185 |
4167 HOST_WIDE_INT size, rsize; | 4228 HOST_WIDE_INT size, rsize; |
4168 tree paddedsize, addr, tmp; | 4229 tree paddedsize, addr, tmp; |
4169 bool pass_by_reference_p; | 4230 bool pass_by_reference_p; |
4170 | 4231 |
4171 f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); | 4232 f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node)); |
4172 f_skip = TREE_CHAIN (f_args); | 4233 f_skip = DECL_CHAIN (f_args); |
4173 | 4234 |
4174 valist = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (valist)), valist); | 4235 valist = build_simple_mem_ref (valist); |
4175 args = | 4236 args = |
4176 build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); | 4237 build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE); |
4177 skip = | 4238 skip = |
4178 build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE); | 4239 build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE); |
4179 | 4240 |
4231 int offset; | 4292 int offset; |
4232 int ncum = *cum; | 4293 int ncum = *cum; |
4233 | 4294 |
4234 /* cum currently points to the last named argument, we want to | 4295 /* cum currently points to the last named argument, we want to |
4235 start at the next argument. */ | 4296 start at the next argument. */ |
4236 FUNCTION_ARG_ADVANCE (ncum, mode, type, 1); | 4297 spu_function_arg_advance (&ncum, mode, type, true); |
4237 | 4298 |
4238 offset = -STACK_POINTER_OFFSET; | 4299 offset = -STACK_POINTER_OFFSET; |
4239 for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++) | 4300 for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++) |
4240 { | 4301 { |
4241 tmp = gen_frame_mem (V4SImode, | 4302 tmp = gen_frame_mem (V4SImode, |
4247 } | 4308 } |
4248 *pretend_size = offset + STACK_POINTER_OFFSET; | 4309 *pretend_size = offset + STACK_POINTER_OFFSET; |
4249 } | 4310 } |
4250 } | 4311 } |
4251 | 4312 |
4252 void | 4313 static void |
4253 spu_conditional_register_usage (void) | 4314 spu_conditional_register_usage (void) |
4254 { | 4315 { |
4255 if (flag_pic) | 4316 if (flag_pic) |
4256 { | 4317 { |
4257 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; | 4318 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; |
4486 insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, | 4547 insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, |
4487 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, | 4548 gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp, |
4488 hit_ref, pc_rtx))); | 4549 hit_ref, pc_rtx))); |
4489 /* Say that this branch is very likely to happen. */ | 4550 /* Say that this branch is very likely to happen. */ |
4490 v = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100 - 1; | 4551 v = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100 - 1; |
4491 REG_NOTES (insn) | 4552 add_reg_note (insn, REG_BR_PROB, GEN_INT (v)); |
4492 = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (v), REG_NOTES (insn)); | |
4493 | 4553 |
4494 ea_load_store (mem, is_store, ea_addr, data_addr); | 4554 ea_load_store (mem, is_store, ea_addr, data_addr); |
4495 cont_label = gen_label_rtx (); | 4555 cont_label = gen_label_rtx (); |
4496 emit_jump_insn (gen_jump (cont_label)); | 4556 emit_jump_insn (gen_jump (cont_label)); |
4497 emit_barrier (); | 4557 emit_barrier (); |
4569 | 4629 |
4570 int | 4630 int |
4571 spu_expand_mov (rtx * ops, enum machine_mode mode) | 4631 spu_expand_mov (rtx * ops, enum machine_mode mode) |
4572 { | 4632 { |
4573 if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0])) | 4633 if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0])) |
4574 abort (); | 4634 { |
4635 /* Perform the move in the destination SUBREG's inner mode. */ | |
4636 ops[0] = SUBREG_REG (ops[0]); | |
4637 mode = GET_MODE (ops[0]); | |
4638 ops[1] = gen_lowpart_common (mode, ops[1]); | |
4639 gcc_assert (ops[1]); | |
4640 } | |
4575 | 4641 |
4576 if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1])) | 4642 if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1])) |
4577 { | 4643 { |
4578 rtx from = SUBREG_REG (ops[1]); | 4644 rtx from = SUBREG_REG (ops[1]); |
4579 enum machine_mode imode = int_mode_for_mode (GET_MODE (from)); | 4645 enum machine_mode imode = int_mode_for_mode (GET_MODE (from)); |
4587 if (imode != GET_MODE (from)) | 4653 if (imode != GET_MODE (from)) |
4588 from = gen_rtx_SUBREG (imode, from, 0); | 4654 from = gen_rtx_SUBREG (imode, from, 0); |
4589 | 4655 |
4590 if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (imode)) | 4656 if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (imode)) |
4591 { | 4657 { |
4592 enum insn_code icode = convert_optab_handler (trunc_optab, mode, imode)->insn_code; | 4658 enum insn_code icode = convert_optab_handler (trunc_optab, |
4659 mode, imode); | |
4593 emit_insn (GEN_FCN (icode) (ops[0], from)); | 4660 emit_insn (GEN_FCN (icode) (ops[0], from)); |
4594 } | 4661 } |
4595 else | 4662 else |
4596 emit_insn (gen_extend_insn (ops[0], from, mode, imode, 1)); | 4663 emit_insn (gen_extend_insn (ops[0], from, mode, imode, 1)); |
4597 return 1; | 4664 return 1; |
4934 p1_lo = gen_reg_rtx (SImode); | 5001 p1_lo = gen_reg_rtx (SImode); |
4935 emit_move_insn (p1_lo, addr); | 5002 emit_move_insn (p1_lo, addr); |
4936 } | 5003 } |
4937 } | 5004 } |
4938 | 5005 |
5006 gcc_assert (aform == 0 || aform == 1); | |
4939 reg = gen_reg_rtx (TImode); | 5007 reg = gen_reg_rtx (TImode); |
4940 | 5008 |
4941 scalar = store_with_one_insn_p (ops[0]); | 5009 scalar = store_with_one_insn_p (ops[0]); |
4942 if (!scalar) | 5010 if (!scalar) |
4943 { | 5011 { |
5571 set_optab_libfunc (parity_optab, DImode, "__paritydi2"); | 5639 set_optab_libfunc (parity_optab, DImode, "__paritydi2"); |
5572 | 5640 |
5573 set_conv_libfunc (ufloat_optab, DFmode, SImode, "__float_unssidf"); | 5641 set_conv_libfunc (ufloat_optab, DFmode, SImode, "__float_unssidf"); |
5574 set_conv_libfunc (ufloat_optab, DFmode, DImode, "__float_unsdidf"); | 5642 set_conv_libfunc (ufloat_optab, DFmode, DImode, "__float_unsdidf"); |
5575 | 5643 |
5644 set_optab_libfunc (addv_optab, SImode, "__addvsi3"); | |
5645 set_optab_libfunc (subv_optab, SImode, "__subvsi3"); | |
5646 set_optab_libfunc (smulv_optab, SImode, "__mulvsi3"); | |
5647 set_optab_libfunc (sdivv_optab, SImode, "__divvsi3"); | |
5648 set_optab_libfunc (negv_optab, SImode, "__negvsi2"); | |
5649 set_optab_libfunc (absv_optab, SImode, "__absvsi2"); | |
5650 set_optab_libfunc (addv_optab, DImode, "__addvdi3"); | |
5651 set_optab_libfunc (subv_optab, DImode, "__subvdi3"); | |
5652 set_optab_libfunc (smulv_optab, DImode, "__mulvdi3"); | |
5653 set_optab_libfunc (sdivv_optab, DImode, "__divvdi3"); | |
5654 set_optab_libfunc (negv_optab, DImode, "__negvdi2"); | |
5655 set_optab_libfunc (absv_optab, DImode, "__absvdi2"); | |
5656 | |
5576 set_optab_libfunc (smul_optab, TImode, "__multi3"); | 5657 set_optab_libfunc (smul_optab, TImode, "__multi3"); |
5577 set_optab_libfunc (sdiv_optab, TImode, "__divti3"); | 5658 set_optab_libfunc (sdiv_optab, TImode, "__divti3"); |
5578 set_optab_libfunc (smod_optab, TImode, "__modti3"); | 5659 set_optab_libfunc (smod_optab, TImode, "__modti3"); |
5579 set_optab_libfunc (udiv_optab, TImode, "__udivti3"); | 5660 set_optab_libfunc (udiv_optab, TImode, "__udivti3"); |
5580 set_optab_libfunc (umod_optab, TImode, "__umodti3"); | 5661 set_optab_libfunc (umod_optab, TImode, "__umodti3"); |
5615 | 5696 |
5616 extern GTY(()) struct spu_builtin_description spu_builtins[NUM_SPU_BUILTINS]; | 5697 extern GTY(()) struct spu_builtin_description spu_builtins[NUM_SPU_BUILTINS]; |
5617 | 5698 |
5618 struct spu_builtin_description spu_builtins[] = { | 5699 struct spu_builtin_description spu_builtins[] = { |
5619 #define DEF_BUILTIN(fcode, icode, name, type, params) \ | 5700 #define DEF_BUILTIN(fcode, icode, name, type, params) \ |
5620 {fcode, icode, name, type, params, NULL_TREE}, | 5701 {fcode, icode, name, type, params}, |
5621 #include "spu-builtins.def" | 5702 #include "spu-builtins.def" |
5622 #undef DEF_BUILTIN | 5703 #undef DEF_BUILTIN |
5623 }; | 5704 }; |
5624 | 5705 |
5625 /* Returns the rs6000 builtin decl for CODE. */ | 5706 static GTY(()) tree spu_builtin_decls[NUM_SPU_BUILTINS]; |
5707 | |
5708 /* Returns the spu builtin decl for CODE. */ | |
5626 | 5709 |
5627 static tree | 5710 static tree |
5628 spu_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) | 5711 spu_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED) |
5629 { | 5712 { |
5630 if (code >= NUM_SPU_BUILTINS) | 5713 if (code >= NUM_SPU_BUILTINS) |
5631 return error_mark_node; | 5714 return error_mark_node; |
5632 | 5715 |
5633 return spu_builtins[code].fndecl; | 5716 return spu_builtin_decls[code]; |
5634 } | 5717 } |
5635 | 5718 |
5636 | 5719 |
5637 static void | 5720 static void |
5638 spu_init_builtins (void) | 5721 spu_init_builtins (void) |
5706 p = tree_cons (NULL_TREE, spu_builtin_types[d->parm[--parm]], p); | 5789 p = tree_cons (NULL_TREE, spu_builtin_types[d->parm[--parm]], p); |
5707 | 5790 |
5708 p = build_function_type (spu_builtin_types[d->parm[0]], p); | 5791 p = build_function_type (spu_builtin_types[d->parm[0]], p); |
5709 | 5792 |
5710 sprintf (name, "__builtin_%s", d->name); | 5793 sprintf (name, "__builtin_%s", d->name); |
5711 d->fndecl = | 5794 spu_builtin_decls[i] = |
5712 add_builtin_function (name, p, END_BUILTINS + i, BUILT_IN_MD, | 5795 add_builtin_function (name, p, i, BUILT_IN_MD, NULL, NULL_TREE); |
5713 NULL, NULL_TREE); | |
5714 if (d->fcode == SPU_MASK_FOR_LOAD) | 5796 if (d->fcode == SPU_MASK_FOR_LOAD) |
5715 TREE_READONLY (d->fndecl) = 1; | 5797 TREE_READONLY (spu_builtin_decls[i]) = 1; |
5716 | 5798 |
5717 /* These builtins don't throw. */ | 5799 /* These builtins don't throw. */ |
5718 TREE_NOTHROW (d->fndecl) = 1; | 5800 TREE_NOTHROW (spu_builtin_decls[i]) = 1; |
5719 } | 5801 } |
5720 } | 5802 } |
5721 | 5803 |
5722 void | 5804 void |
5723 spu_restore_stack_block (rtx op0 ATTRIBUTE_UNUSED, rtx op1) | 5805 spu_restore_stack_block (rtx op0 ATTRIBUTE_UNUSED, rtx op1) |
6250 case NE: | 6332 case NE: |
6251 /* Treat A != B as ~(A==B). */ | 6333 /* Treat A != B as ~(A==B). */ |
6252 { | 6334 { |
6253 enum insn_code nor_code; | 6335 enum insn_code nor_code; |
6254 rtx eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode); | 6336 rtx eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode); |
6255 nor_code = optab_handler (one_cmpl_optab, (int)dest_mode)->insn_code; | 6337 nor_code = optab_handler (one_cmpl_optab, dest_mode); |
6256 gcc_assert (nor_code != CODE_FOR_nothing); | 6338 gcc_assert (nor_code != CODE_FOR_nothing); |
6257 emit_insn (GEN_FCN (nor_code) (mask, eq_rtx)); | 6339 emit_insn (GEN_FCN (nor_code) (mask, eq_rtx)); |
6258 if (dmode != dest_mode) | 6340 if (dmode != dest_mode) |
6259 { | 6341 { |
6260 rtx temp = gen_reg_rtx (dest_mode); | 6342 rtx temp = gen_reg_rtx (dest_mode); |
6285 } | 6367 } |
6286 | 6368 |
6287 c_rtx = spu_emit_vector_compare (new_code, op0, op1, dest_mode); | 6369 c_rtx = spu_emit_vector_compare (new_code, op0, op1, dest_mode); |
6288 eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode); | 6370 eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode); |
6289 | 6371 |
6290 ior_code = optab_handler (ior_optab, (int)dest_mode)->insn_code; | 6372 ior_code = optab_handler (ior_optab, dest_mode); |
6291 gcc_assert (ior_code != CODE_FOR_nothing); | 6373 gcc_assert (ior_code != CODE_FOR_nothing); |
6292 emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx)); | 6374 emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx)); |
6293 if (dmode != dest_mode) | 6375 if (dmode != dest_mode) |
6294 { | 6376 { |
6295 rtx temp = gen_reg_rtx (dest_mode); | 6377 rtx temp = gen_reg_rtx (dest_mode); |
6383 if (p >= SPU_BTI_7 && p <= SPU_BTI_U18) | 6465 if (p >= SPU_BTI_7 && p <= SPU_BTI_U18) |
6384 { | 6466 { |
6385 int range = p - SPU_BTI_7; | 6467 int range = p - SPU_BTI_7; |
6386 | 6468 |
6387 if (!CONSTANT_P (op)) | 6469 if (!CONSTANT_P (op)) |
6388 error ("%s expects an integer literal in the range [%d, %d].", | 6470 error ("%s expects an integer literal in the range [%d, %d]", |
6389 d->name, | 6471 d->name, |
6390 spu_builtin_range[range].low, spu_builtin_range[range].high); | 6472 spu_builtin_range[range].low, spu_builtin_range[range].high); |
6391 | 6473 |
6392 if (GET_CODE (op) == CONST | 6474 if (GET_CODE (op) == CONST |
6393 && (GET_CODE (XEXP (op, 0)) == PLUS | 6475 && (GET_CODE (XEXP (op, 0)) == PLUS |
6403 v = INTVAL (CONST_VECTOR_ELT (op, 0)); | 6485 v = INTVAL (CONST_VECTOR_ELT (op, 0)); |
6404 | 6486 |
6405 /* The default for v is 0 which is valid in every range. */ | 6487 /* The default for v is 0 which is valid in every range. */ |
6406 if (v < spu_builtin_range[range].low | 6488 if (v < spu_builtin_range[range].low |
6407 || v > spu_builtin_range[range].high) | 6489 || v > spu_builtin_range[range].high) |
6408 error ("%s expects an integer literal in the range [%d, %d]. (" | 6490 error ("%s expects an integer literal in the range [%d, %d]. (%wd)", |
6409 HOST_WIDE_INT_PRINT_DEC ")", | |
6410 d->name, | 6491 d->name, |
6411 spu_builtin_range[range].low, spu_builtin_range[range].high, | 6492 spu_builtin_range[range].low, spu_builtin_range[range].high, |
6412 v); | 6493 v); |
6413 | 6494 |
6414 switch (p) | 6495 switch (p) |
6433 | 6514 |
6434 if (GET_CODE (op) == LABEL_REF | 6515 if (GET_CODE (op) == LABEL_REF |
6435 || (GET_CODE (op) == SYMBOL_REF | 6516 || (GET_CODE (op) == SYMBOL_REF |
6436 && SYMBOL_REF_FUNCTION_P (op)) | 6517 && SYMBOL_REF_FUNCTION_P (op)) |
6437 || (v & ((1 << lsbits) - 1)) != 0) | 6518 || (v & ((1 << lsbits) - 1)) != 0) |
6438 warning (0, "%d least significant bits of %s are ignored.", lsbits, | 6519 warning (0, "%d least significant bits of %s are ignored", lsbits, |
6439 d->name); | 6520 d->name); |
6440 } | 6521 } |
6441 } | 6522 } |
6442 | 6523 |
6443 | 6524 |
6513 tree arg; | 6594 tree arg; |
6514 rtx addr, op, pat; | 6595 rtx addr, op, pat; |
6515 | 6596 |
6516 /* get addr */ | 6597 /* get addr */ |
6517 arg = CALL_EXPR_ARG (exp, 0); | 6598 arg = CALL_EXPR_ARG (exp, 0); |
6518 gcc_assert (TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE); | 6599 gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg))); |
6519 op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL); | 6600 op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL); |
6520 addr = memory_address (mode, op); | 6601 addr = memory_address (mode, op); |
6521 | 6602 |
6522 /* negate addr */ | 6603 /* negate addr */ |
6523 op = gen_reg_rtx (GET_MODE (addr)); | 6604 op = gen_reg_rtx (GET_MODE (addr)); |
6636 rtx subtarget ATTRIBUTE_UNUSED, | 6717 rtx subtarget ATTRIBUTE_UNUSED, |
6637 enum machine_mode mode ATTRIBUTE_UNUSED, | 6718 enum machine_mode mode ATTRIBUTE_UNUSED, |
6638 int ignore ATTRIBUTE_UNUSED) | 6719 int ignore ATTRIBUTE_UNUSED) |
6639 { | 6720 { |
6640 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); | 6721 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); |
6641 unsigned int fcode = DECL_FUNCTION_CODE (fndecl) - END_BUILTINS; | 6722 unsigned int fcode = DECL_FUNCTION_CODE (fndecl); |
6642 struct spu_builtin_description *d; | 6723 struct spu_builtin_description *d; |
6643 | 6724 |
6644 if (fcode < NUM_SPU_BUILTINS) | 6725 if (fcode < NUM_SPU_BUILTINS) |
6645 { | 6726 { |
6646 d = &spu_builtins[fcode]; | 6727 d = &spu_builtins[fcode]; |
6656 { | 6737 { |
6657 switch (TYPE_MODE (type)) | 6738 switch (TYPE_MODE (type)) |
6658 { | 6739 { |
6659 case V8HImode: | 6740 case V8HImode: |
6660 if (TYPE_UNSIGNED (type)) | 6741 if (TYPE_UNSIGNED (type)) |
6661 return spu_builtins[SPU_MULE_0].fndecl; | 6742 return spu_builtin_decls[SPU_MULE_0]; |
6662 else | 6743 else |
6663 return spu_builtins[SPU_MULE_1].fndecl; | 6744 return spu_builtin_decls[SPU_MULE_1]; |
6664 break; | 6745 break; |
6665 default: | 6746 default: |
6666 return NULL_TREE; | 6747 return NULL_TREE; |
6667 } | 6748 } |
6668 } | 6749 } |
6673 { | 6754 { |
6674 switch (TYPE_MODE (type)) | 6755 switch (TYPE_MODE (type)) |
6675 { | 6756 { |
6676 case V8HImode: | 6757 case V8HImode: |
6677 if (TYPE_UNSIGNED (type)) | 6758 if (TYPE_UNSIGNED (type)) |
6678 return spu_builtins[SPU_MULO_1].fndecl; | 6759 return spu_builtin_decls[SPU_MULO_1]; |
6679 else | 6760 else |
6680 return spu_builtins[SPU_MULO_0].fndecl; | 6761 return spu_builtin_decls[SPU_MULO_0]; |
6681 break; | 6762 break; |
6682 default: | 6763 default: |
6683 return NULL_TREE; | 6764 return NULL_TREE; |
6684 } | 6765 } |
6685 } | 6766 } |
6686 | 6767 |
6687 /* Implement targetm.vectorize.builtin_mask_for_load. */ | 6768 /* Implement targetm.vectorize.builtin_mask_for_load. */ |
6688 static tree | 6769 static tree |
6689 spu_builtin_mask_for_load (void) | 6770 spu_builtin_mask_for_load (void) |
6690 { | 6771 { |
6691 struct spu_builtin_description *d = &spu_builtins[SPU_MASK_FOR_LOAD]; | 6772 return spu_builtin_decls[SPU_MASK_FOR_LOAD]; |
6692 gcc_assert (d); | |
6693 return d->fndecl; | |
6694 } | 6773 } |
6695 | 6774 |
6696 /* Implement targetm.vectorize.builtin_vectorization_cost. */ | 6775 /* Implement targetm.vectorize.builtin_vectorization_cost. */ |
6697 static int | 6776 static int |
6698 spu_builtin_vectorization_cost (bool runtime_test) | 6777 spu_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, |
6699 { | 6778 tree vectype ATTRIBUTE_UNUSED, |
6700 /* If the branch of the runtime test is taken - i.e. - the vectorized | 6779 int misalign ATTRIBUTE_UNUSED) |
6701 version is skipped - this incurs a misprediction cost (because the | 6780 { |
6702 vectorized version is expected to be the fall-through). So we subtract | 6781 switch (type_of_cost) |
6703 the latency of a mispredicted branch from the costs that are incurred | 6782 { |
6704 when the vectorized version is executed. */ | 6783 case scalar_stmt: |
6705 if (runtime_test) | 6784 case vector_stmt: |
6706 return -19; | 6785 case vector_load: |
6707 else | 6786 case vector_store: |
6708 return 0; | 6787 case vec_to_scalar: |
6788 case scalar_to_vec: | |
6789 case cond_branch_not_taken: | |
6790 case vec_perm: | |
6791 return 1; | |
6792 | |
6793 case scalar_store: | |
6794 return 10; | |
6795 | |
6796 case scalar_load: | |
6797 /* Load + rotate. */ | |
6798 return 2; | |
6799 | |
6800 case unaligned_load: | |
6801 return 2; | |
6802 | |
6803 case cond_branch_taken: | |
6804 return 6; | |
6805 | |
6806 default: | |
6807 gcc_unreachable (); | |
6808 } | |
6709 } | 6809 } |
6710 | 6810 |
6711 /* Return true iff, data reference of TYPE can reach vector alignment (16) | 6811 /* Return true iff, data reference of TYPE can reach vector alignment (16) |
6712 after applying N number of iterations. This routine does not determine | 6812 after applying N number of iterations. This routine does not determine |
6713 how may iterations are required to reach desired alignment. */ | 6813 how may iterations are required to reach desired alignment. */ |
6724 | 6824 |
6725 /* Implement targetm.vectorize.builtin_vec_perm. */ | 6825 /* Implement targetm.vectorize.builtin_vec_perm. */ |
6726 tree | 6826 tree |
6727 spu_builtin_vec_perm (tree type, tree *mask_element_type) | 6827 spu_builtin_vec_perm (tree type, tree *mask_element_type) |
6728 { | 6828 { |
6729 struct spu_builtin_description *d; | |
6730 | |
6731 *mask_element_type = unsigned_char_type_node; | 6829 *mask_element_type = unsigned_char_type_node; |
6732 | 6830 |
6733 switch (TYPE_MODE (type)) | 6831 switch (TYPE_MODE (type)) |
6734 { | 6832 { |
6735 case V16QImode: | 6833 case V16QImode: |
6736 if (TYPE_UNSIGNED (type)) | 6834 if (TYPE_UNSIGNED (type)) |
6737 d = &spu_builtins[SPU_SHUFFLE_0]; | 6835 return spu_builtin_decls[SPU_SHUFFLE_0]; |
6738 else | 6836 else |
6739 d = &spu_builtins[SPU_SHUFFLE_1]; | 6837 return spu_builtin_decls[SPU_SHUFFLE_1]; |
6740 break; | |
6741 | 6838 |
6742 case V8HImode: | 6839 case V8HImode: |
6743 if (TYPE_UNSIGNED (type)) | 6840 if (TYPE_UNSIGNED (type)) |
6744 d = &spu_builtins[SPU_SHUFFLE_2]; | 6841 return spu_builtin_decls[SPU_SHUFFLE_2]; |
6745 else | 6842 else |
6746 d = &spu_builtins[SPU_SHUFFLE_3]; | 6843 return spu_builtin_decls[SPU_SHUFFLE_3]; |
6747 break; | |
6748 | 6844 |
6749 case V4SImode: | 6845 case V4SImode: |
6750 if (TYPE_UNSIGNED (type)) | 6846 if (TYPE_UNSIGNED (type)) |
6751 d = &spu_builtins[SPU_SHUFFLE_4]; | 6847 return spu_builtin_decls[SPU_SHUFFLE_4]; |
6752 else | 6848 else |
6753 d = &spu_builtins[SPU_SHUFFLE_5]; | 6849 return spu_builtin_decls[SPU_SHUFFLE_5]; |
6754 break; | |
6755 | 6850 |
6756 case V2DImode: | 6851 case V2DImode: |
6757 if (TYPE_UNSIGNED (type)) | 6852 if (TYPE_UNSIGNED (type)) |
6758 d = &spu_builtins[SPU_SHUFFLE_6]; | 6853 return spu_builtin_decls[SPU_SHUFFLE_6]; |
6759 else | 6854 else |
6760 d = &spu_builtins[SPU_SHUFFLE_7]; | 6855 return spu_builtin_decls[SPU_SHUFFLE_7]; |
6761 break; | |
6762 | 6856 |
6763 case V4SFmode: | 6857 case V4SFmode: |
6764 d = &spu_builtins[SPU_SHUFFLE_8]; | 6858 return spu_builtin_decls[SPU_SHUFFLE_8]; |
6765 break; | |
6766 | 6859 |
6767 case V2DFmode: | 6860 case V2DFmode: |
6768 d = &spu_builtins[SPU_SHUFFLE_9]; | 6861 return spu_builtin_decls[SPU_SHUFFLE_9]; |
6769 break; | |
6770 | 6862 |
6771 default: | 6863 default: |
6772 return NULL_TREE; | 6864 return NULL_TREE; |
6773 } | 6865 } |
6774 | |
6775 gcc_assert (d); | |
6776 return d->fndecl; | |
6777 } | 6866 } |
6778 | 6867 |
6779 /* Return the appropriate mode for a named address pointer. */ | 6868 /* Return the appropriate mode for a named address pointer. */ |
6780 static enum machine_mode | 6869 static enum machine_mode |
6781 spu_addr_space_pointer_mode (addr_space_t addrspace) | 6870 spu_addr_space_pointer_mode (addr_space_t addrspace) |
6896 for (i = 0; i < g->num_nodes; i++) | 6985 for (i = 0; i < g->num_nodes; i++) |
6897 { | 6986 { |
6898 rtx insn = g->nodes[i].insn; | 6987 rtx insn = g->nodes[i].insn; |
6899 int p = get_pipe (insn) + 2; | 6988 int p = get_pipe (insn) + 2; |
6900 | 6989 |
6901 assert (p >= 0); | 6990 gcc_assert (p >= 0); |
6902 assert (p < 4); | 6991 gcc_assert (p < 4); |
6903 | 6992 |
6904 t[p]++; | 6993 t[p]++; |
6905 if (dump_file && INSN_P (insn)) | 6994 if (dump_file && INSN_P (insn)) |
6906 fprintf (dump_file, "i%d %s %d %d\n", | 6995 fprintf (dump_file, "i%d %s %d %d\n", |
6907 INSN_UID (insn), | 6996 INSN_UID (insn), |
6959 * them. */ | 7048 * them. */ |
6960 static void | 7049 static void |
6961 asm_file_start (void) | 7050 asm_file_start (void) |
6962 { | 7051 { |
6963 /* Variable tracking should be run after all optimizations which | 7052 /* Variable tracking should be run after all optimizations which |
6964 change order of insns. It also needs a valid CFG. */ | 7053 change order of insns. It also needs a valid CFG. Therefore, |
6965 spu_flag_var_tracking = flag_var_tracking; | 7054 *if* we make nontrivial changes in machine-dependent reorg, |
6966 flag_var_tracking = 0; | 7055 run variable tracking after those. However, if we do not run |
7056 our machine-dependent reorg pass, we must still run the normal | |
7057 variable tracking pass (or else we will ICE in final since | |
7058 debug insns have not been removed). */ | |
7059 if (TARGET_BRANCH_HINTS && optimize) | |
7060 { | |
7061 spu_flag_var_tracking = flag_var_tracking; | |
7062 flag_var_tracking = 0; | |
7063 } | |
6967 | 7064 |
6968 default_file_start (); | 7065 default_file_start (); |
6969 } | 7066 } |
6970 | 7067 |
6971 /* Implement targetm.section_type_flags. */ | 7068 /* Implement targetm.section_type_flags. */ |
7062 emit_insn (gen_move_insn (op0, op1)); | 7159 emit_insn (gen_move_insn (op0, op1)); |
7063 } | 7160 } |
7064 } | 7161 } |
7065 | 7162 |
7066 void | 7163 void |
7067 spu_function_profiler (FILE * file, int labelno) | 7164 spu_function_profiler (FILE * file, int labelno ATTRIBUTE_UNUSED) |
7068 { | 7165 { |
7069 fprintf (file, "# profile\n"); | 7166 fprintf (file, "# profile\n"); |
7070 fprintf (file, "brsl $75, _mcount\n"); | 7167 fprintf (file, "brsl $75, _mcount\n"); |
7071 } | 7168 } |
7072 | 7169 |
7170 /* Implement targetm.ref_may_alias_errno. */ | |
7171 static bool | |
7172 spu_ref_may_alias_errno (ao_ref *ref) | |
7173 { | |
7174 tree base = ao_ref_base (ref); | |
7175 | |
7176 /* With SPU newlib, errno is defined as something like | |
7177 _impure_data._errno | |
7178 The default implementation of this target macro does not | |
7179 recognize such expressions, so special-code for it here. */ | |
7180 | |
7181 if (TREE_CODE (base) == VAR_DECL | |
7182 && !TREE_STATIC (base) | |
7183 && DECL_EXTERNAL (base) | |
7184 && TREE_CODE (TREE_TYPE (base)) == RECORD_TYPE | |
7185 && strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (base)), | |
7186 "_impure_data") == 0 | |
7187 /* _errno is the first member of _impure_data. */ | |
7188 && ref->offset == 0) | |
7189 return true; | |
7190 | |
7191 return default_ref_may_alias_errno (ref); | |
7192 } | |
7193 | |
7073 #include "gt-spu.h" | 7194 #include "gt-spu.h" |