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"