X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fconfig%2Frs6000%2Frs6000.c;h=dbf7e785a65567a044fb1ffccdbb13a04c7f0ac6;hp=67b7c86cda9b00e33a2ca198f9b675d265aa268d;hb=a9f1838b25e8f79987473955debea2146537d881;hpb=77e449dbd3a31843efcdf4a7c70f72e5fac60b2e diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 67b7c86cda9..dbf7e785a65 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -8,7 +8,7 @@ GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your + by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT @@ -17,9 +17,8 @@ License for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the - Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301, USA. */ + along with GCC; see the file COPYING3. If not see + . */ #include "config.h" #include "system.h" @@ -290,6 +289,11 @@ struct processor_costs { const int dmul; /* cost of DFmode multiplication (and fmadd). */ const int sdiv; /* cost of SFmode division (fdivs). */ const int ddiv; /* cost of DFmode division (fdiv). */ + const int cache_line_size; /* cache line size in bytes. */ + const int l1_cache_size; /* size of l1 cache, in kilobytes. */ + const int l2_cache_size; /* size of l2 cache, in kilobytes. */ + const int simultaneous_prefetches; /* number of parallel prefetch + operations. */ }; const struct processor_costs *rs6000_cost; @@ -309,6 +313,10 @@ struct processor_costs size32_cost = { COSTS_N_INSNS (1), /* dmul */ COSTS_N_INSNS (1), /* sdiv */ COSTS_N_INSNS (1), /* ddiv */ + 32, + 0, + 0, + 0, }; /* Instruction size costs on 64bit processors. */ @@ -324,6 +332,10 @@ struct processor_costs size64_cost = { COSTS_N_INSNS (1), /* dmul */ COSTS_N_INSNS (1), /* sdiv */ COSTS_N_INSNS (1), /* ddiv */ + 128, + 0, + 0, + 0, }; /* Instruction costs on RIOS1 processors. */ @@ -339,6 +351,10 @@ struct processor_costs rios1_cost = { COSTS_N_INSNS (2), /* dmul */ COSTS_N_INSNS (19), /* sdiv */ COSTS_N_INSNS (19), /* ddiv */ + 128, + 64, /* l1 cache */ + 512, /* l2 cache */ + 0, /* streams */ }; /* Instruction costs on RIOS2 processors. */ @@ -354,6 +370,10 @@ struct processor_costs rios2_cost = { COSTS_N_INSNS (2), /* dmul */ COSTS_N_INSNS (17), /* sdiv */ COSTS_N_INSNS (17), /* ddiv */ + 256, + 256, /* l1 cache */ + 1024, /* l2 cache */ + 0, /* streams */ }; /* Instruction costs on RS64A processors. */ @@ -369,6 +389,10 @@ struct processor_costs rs64a_cost = { COSTS_N_INSNS (4), /* dmul */ COSTS_N_INSNS (31), /* sdiv */ COSTS_N_INSNS (31), /* ddiv */ + 128, + 128, /* l1 cache */ + 2048, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on MPCCORE processors. */ @@ -384,6 +408,10 @@ struct processor_costs mpccore_cost = { COSTS_N_INSNS (5), /* dmul */ COSTS_N_INSNS (10), /* sdiv */ COSTS_N_INSNS (17), /* ddiv */ + 32, + 4, /* l1 cache */ + 16, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC403 processors. */ @@ -399,6 +427,10 @@ struct processor_costs ppc403_cost = { COSTS_N_INSNS (11), /* dmul */ COSTS_N_INSNS (11), /* sdiv */ COSTS_N_INSNS (11), /* ddiv */ + 32, + 4, /* l1 cache */ + 16, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC405 processors. */ @@ -414,6 +446,10 @@ struct processor_costs ppc405_cost = { COSTS_N_INSNS (11), /* dmul */ COSTS_N_INSNS (11), /* sdiv */ COSTS_N_INSNS (11), /* ddiv */ + 32, + 16, /* l1 cache */ + 128, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC440 processors. */ @@ -429,6 +465,10 @@ struct processor_costs ppc440_cost = { COSTS_N_INSNS (5), /* dmul */ COSTS_N_INSNS (19), /* sdiv */ COSTS_N_INSNS (33), /* ddiv */ + 32, + 32, /* l1 cache */ + 256, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC601 processors. */ @@ -444,6 +484,10 @@ struct processor_costs ppc601_cost = { COSTS_N_INSNS (5), /* dmul */ COSTS_N_INSNS (17), /* sdiv */ COSTS_N_INSNS (31), /* ddiv */ + 32, + 32, /* l1 cache */ + 256, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC603 processors. */ @@ -459,6 +503,10 @@ struct processor_costs ppc603_cost = { COSTS_N_INSNS (4), /* dmul */ COSTS_N_INSNS (18), /* sdiv */ COSTS_N_INSNS (33), /* ddiv */ + 32, + 8, /* l1 cache */ + 64, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC604 processors. */ @@ -474,6 +522,10 @@ struct processor_costs ppc604_cost = { COSTS_N_INSNS (3), /* dmul */ COSTS_N_INSNS (18), /* sdiv */ COSTS_N_INSNS (32), /* ddiv */ + 32, + 16, /* l1 cache */ + 512, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC604e processors. */ @@ -489,6 +541,10 @@ struct processor_costs ppc604e_cost = { COSTS_N_INSNS (3), /* dmul */ COSTS_N_INSNS (18), /* sdiv */ COSTS_N_INSNS (32), /* ddiv */ + 32, + 32, /* l1 cache */ + 1024, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC620 processors. */ @@ -504,6 +560,10 @@ struct processor_costs ppc620_cost = { COSTS_N_INSNS (3), /* dmul */ COSTS_N_INSNS (18), /* sdiv */ COSTS_N_INSNS (32), /* ddiv */ + 128, + 32, /* l1 cache */ + 1024, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC630 processors. */ @@ -519,6 +579,10 @@ struct processor_costs ppc630_cost = { COSTS_N_INSNS (3), /* dmul */ COSTS_N_INSNS (17), /* sdiv */ COSTS_N_INSNS (21), /* ddiv */ + 128, + 64, /* l1 cache */ + 1024, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on Cell processor. */ @@ -535,6 +599,10 @@ struct processor_costs ppccell_cost = { COSTS_N_INSNS (10/2), /* dmul */ COSTS_N_INSNS (74/2), /* sdiv */ COSTS_N_INSNS (74/2), /* ddiv */ + 128, + 32, /* l1 cache */ + 512, /* l2 cache */ + 6, /* streams */ }; /* Instruction costs on PPC750 and PPC7400 processors. */ @@ -550,6 +618,10 @@ struct processor_costs ppc750_cost = { COSTS_N_INSNS (3), /* dmul */ COSTS_N_INSNS (17), /* sdiv */ COSTS_N_INSNS (31), /* ddiv */ + 32, + 32, /* l1 cache */ + 512, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC7450 processors. */ @@ -565,6 +637,10 @@ struct processor_costs ppc7450_cost = { COSTS_N_INSNS (5), /* dmul */ COSTS_N_INSNS (21), /* sdiv */ COSTS_N_INSNS (35), /* ddiv */ + 32, + 32, /* l1 cache */ + 1024, /* l2 cache */ + 1, /* streams */ }; /* Instruction costs on PPC8540 processors. */ @@ -580,6 +656,10 @@ struct processor_costs ppc8540_cost = { COSTS_N_INSNS (4), /* dmul */ COSTS_N_INSNS (29), /* sdiv */ COSTS_N_INSNS (29), /* ddiv */ + 32, + 32, /* l1 cache */ + 256, /* l2 cache */ + 1, /* prefetch streams /*/ }; /* Instruction costs on POWER4 and POWER5 processors. */ @@ -595,6 +675,10 @@ struct processor_costs power4_cost = { COSTS_N_INSNS (3), /* dmul */ COSTS_N_INSNS (17), /* sdiv */ COSTS_N_INSNS (17), /* ddiv */ + 128, + 32, /* l1 cache */ + 1024, /* l2 cache */ + 8, /* prefetch streams /*/ }; /* Instruction costs on POWER6 processors. */ @@ -610,13 +694,16 @@ struct processor_costs power6_cost = { COSTS_N_INSNS (3), /* dmul */ COSTS_N_INSNS (13), /* sdiv */ COSTS_N_INSNS (16), /* ddiv */ + 128, + 64, /* l1 cache */ + 2048, /* l2 cache */ + 16, /* prefetch streams */ }; static bool rs6000_function_ok_for_sibcall (tree, tree); -static const char *rs6000_invalid_within_doloop (rtx); +static const char *rs6000_invalid_within_doloop (const_rtx); static rtx rs6000_generate_compare (enum rtx_code); -static void rs6000_maybe_dead (rtx); static void rs6000_emit_stack_tie (void); static void rs6000_frame_related (rtx, rtx, HOST_WIDE_INT, rtx, rtx); static rtx spe_synthesize_frame_save (rtx); @@ -631,7 +718,6 @@ static int toc_hash_eq (const void *, const void *); static int constant_pool_expr_1 (rtx, int *, int *); static bool constant_pool_expr_p (rtx); static bool legitimate_small_data_p (enum machine_mode, rtx); -static bool legitimate_indexed_address_p (rtx, int); static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int); static struct machine_function * rs6000_init_machine_status (void); static bool rs6000_assemble_integer (rtx, unsigned int, int); @@ -642,10 +728,10 @@ static void rs6000_assemble_visibility (tree, int); static int rs6000_ra_ever_killed (void); static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *); static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *); -static bool rs6000_ms_bitfield_layout_p (tree); +static bool rs6000_ms_bitfield_layout_p (const_tree); static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *); static void rs6000_eliminate_indexed_memrefs (rtx operands[2]); -static const char *rs6000_mangle_fundamental_type (tree); +static const char *rs6000_mangle_type (const_tree); extern const struct attribute_spec rs6000_attribute_table[]; static void rs6000_set_default_type_attributes (tree); static bool rs6000_reg_live_or_pic_offset_p (int); @@ -654,7 +740,7 @@ static void rs6000_output_function_epilogue (FILE *, HOST_WIDE_INT); static void rs6000_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); static rtx rs6000_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT); -static bool rs6000_return_in_memory (tree, tree); +static bool rs6000_return_in_memory (const_tree, const_tree); static void rs6000_file_start (void); #if TARGET_ELF static int rs6000_elf_reloc_rw_mask (void); @@ -667,7 +753,7 @@ static section *rs6000_elf_select_rtx_section (enum machine_mode, rtx, static void rs6000_elf_encode_section_info (tree, rtx, int) ATTRIBUTE_UNUSED; #endif -static bool rs6000_use_blocks_for_constant_p (enum machine_mode, rtx); +static bool rs6000_use_blocks_for_constant_p (enum machine_mode, const_rtx); #if TARGET_XCOFF static void rs6000_xcoff_asm_output_anchor (rtx); static void rs6000_xcoff_asm_globalize_label (FILE *, const char *); @@ -719,6 +805,7 @@ static tree rs6000_builtin_mul_widen_odd (tree); static tree rs6000_builtin_conversion (enum tree_code, tree); static void def_builtin (int, const char *, tree, int); +static bool rs6000_vector_alignment_reachable (const_tree, bool); static void rs6000_init_builtins (void); static rtx rs6000_expand_unop_builtin (enum insn_code, tree, rtx); static rtx rs6000_expand_binop_builtin (enum insn_code, tree, rtx); @@ -763,7 +850,7 @@ static void compute_save_world_info (rs6000_stack_t *info_ptr); static void is_altivec_return_reg (rtx, void *); static rtx generate_set_vrsave (rtx, rs6000_stack_t *, int); int easy_vector_constant (rtx, enum machine_mode); -static bool rs6000_is_opaque_type (tree); +static bool rs6000_is_opaque_type (const_tree); static rtx rs6000_dwarf_register_span (rtx); static void rs6000_init_dwarf_reg_sizes_extra (tree); static rtx rs6000_legitimize_tls_address (rtx, enum tls_model); @@ -784,19 +871,19 @@ static void rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *, HOST_WIDE_INT, rtx[], int *); static void rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *, - tree, HOST_WIDE_INT, - rtx[], int *); -static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, tree, int, bool); + const_tree, HOST_WIDE_INT, + rtx[], int *); +static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, const_tree, int, bool); static rtx rs6000_mixed_function_arg (enum machine_mode, tree, int); static void rs6000_move_block_from_reg (int regno, rtx x, int nregs); static void setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); static bool rs6000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, - tree, bool); + const_tree, bool); static int rs6000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, tree, bool); -static const char *invalid_arg_for_unprototyped_fn (tree, tree, tree); +static const char *invalid_arg_for_unprototyped_fn (const_tree, const_tree, const_tree); #if TARGET_MACHO static void macho_branch_islands (void); static int no_previous_def (tree function_name); @@ -806,7 +893,7 @@ static void rs6000_darwin_file_start (void); static tree rs6000_build_builtin_va_list (void); static tree rs6000_gimplify_va_arg (tree, tree, tree *, tree *); -static bool rs6000_must_pass_in_stack (enum machine_mode, tree); +static bool rs6000_must_pass_in_stack (enum machine_mode, const_tree); static bool rs6000_scalar_mode_supported_p (enum machine_mode); static bool rs6000_vector_mode_supported_p (enum machine_mode); static int get_vec_cmp_insn (enum rtx_code, enum machine_mode, @@ -986,14 +1073,17 @@ static const char alt_reg_names[][8] = #undef TARGET_VECTORIZE_BUILTIN_CONVERSION #define TARGET_VECTORIZE_BUILTIN_CONVERSION rs6000_builtin_conversion +#undef TARGET_VECTOR_ALIGNMENT_REACHABLE +#define TARGET_VECTOR_ALIGNMENT_REACHABLE rs6000_vector_alignment_reachable + #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS rs6000_init_builtins #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN rs6000_expand_builtin -#undef TARGET_MANGLE_FUNDAMENTAL_TYPE -#define TARGET_MANGLE_FUNDAMENTAL_TYPE rs6000_mangle_fundamental_type +#undef TARGET_MANGLE_TYPE +#define TARGET_MANGLE_TYPE rs6000_mangle_type #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS rs6000_init_libfuncs @@ -1010,7 +1100,7 @@ static const char alt_reg_names[][8] = #define TARGET_ASM_OUTPUT_MI_THUNK rs6000_output_mi_thunk #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK -#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true +#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true #undef TARGET_FUNCTION_OK_FOR_SIBCALL #define TARGET_FUNCTION_OK_FOR_SIBCALL rs6000_function_ok_for_sibcall @@ -1035,9 +1125,9 @@ static const char alt_reg_names[][8] = /* On rs6000, function arguments are promoted, as are function return values. */ #undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true +#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true #undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true +#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory @@ -1051,7 +1141,7 @@ static const char alt_reg_names[][8] = #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true #undef TARGET_SPLIT_COMPLEX_ARG -#define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true +#define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true #undef TARGET_MUST_PASS_IN_STACK #define TARGET_MUST_PASS_IN_STACK rs6000_must_pass_in_stack #undef TARGET_PASS_BY_REFERENCE @@ -1726,6 +1816,16 @@ rs6000_override_options (const char *default_cpu) default: gcc_unreachable (); } + + if (!PARAM_SET_P (PARAM_SIMULTANEOUS_PREFETCHES)) + set_param_value ("simultaneous-prefetches", + rs6000_cost->simultaneous_prefetches); + if (!PARAM_SET_P (PARAM_L1_CACHE_SIZE)) + set_param_value ("l1-cache-size", rs6000_cost->l1_cache_size); + if (!PARAM_SET_P (PARAM_L1_CACHE_LINE_SIZE)) + set_param_value ("l1-cache-line-size", rs6000_cost->cache_line_size); + if (!PARAM_SET_P (PARAM_L2_CACHE_SIZE)) + set_param_value ("l2-cache-size", rs6000_cost->l2_cache_size); } /* Implement targetm.vectorize.builtin_mask_for_load. */ @@ -1808,6 +1908,37 @@ rs6000_builtin_mul_widen_odd (tree type) } } + +/* Return true iff, data reference of TYPE can reach vector alignment (16) + after applying N number of iterations. This routine does not determine + how may iterations are required to reach desired alignment. */ + +static bool +rs6000_vector_alignment_reachable (const_tree type ATTRIBUTE_UNUSED, bool is_packed) +{ + if (is_packed) + return false; + + if (TARGET_32BIT) + { + if (rs6000_alignment_flags == MASK_ALIGN_NATURAL) + return true; + + if (rs6000_alignment_flags == MASK_ALIGN_POWER) + return true; + + return false; + } + else + { + if (TARGET_MACHO) + return false; + + /* Assuming that all other types are naturally aligned. CHECKME! */ + return true; + } +} + /* Handle generic options of the form -mfoo=yes/no. NAME is the option name. VALUE is the option value. @@ -2207,6 +2338,18 @@ rs6000_file_start (void) putc ('\n', file); } +#ifdef HAVE_AS_GNU_ATTRIBUTE + if (TARGET_32BIT && DEFAULT_ABI == ABI_V4) + { + fprintf (file, "\t.gnu_attribute 4, %d\n", + (TARGET_HARD_FLOAT && TARGET_FPRS) ? 1 : 2); + fprintf (file, "\t.gnu_attribute 8, %d\n", + (TARGET_ALTIVEC_ABI ? 2 + : TARGET_SPE_ABI ? 3 + : 1)); + } +#endif + if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2)) { switch_to_section (toc_section); @@ -3098,7 +3241,7 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict) return (offset < 0x10000) && (offset + extra < 0x10000); } -static bool +bool legitimate_indexed_address_p (rtx x, int strict) { rtx op0, op1; @@ -3454,15 +3597,12 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model) first = emit_insn (gen_load_toc_v4_PIC_1b (gsym)); emit_move_insn (tmp1, - gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)); + gen_rtx_REG (Pmode, LR_REGNO)); emit_move_insn (tmp2, mem); emit_insn (gen_addsi3 (tmp3, tmp1, tmp2)); last = emit_move_insn (got, tmp3); set_unique_reg_note (last, REG_EQUAL, gsym); - REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, - REG_NOTES (first)); - REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, - REG_NOTES (last)); + maybe_encapsulate_block (first, last, gsym); } } } @@ -3832,6 +3972,24 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict) && (TARGET_POWERPC64 || mode != DImode) && legitimate_indexed_address_p (x, reg_ok_strict)) return 1; + if (GET_CODE (x) == PRE_MODIFY + && mode != TImode + && mode != TFmode + && mode != TDmode + && ((TARGET_HARD_FLOAT && TARGET_FPRS) + || TARGET_POWERPC64 + || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode)) + && (TARGET_POWERPC64 || mode != DImode) + && !ALTIVEC_VECTOR_MODE (mode) + && !SPE_VECTOR_MODE (mode) + /* Restrict addressing for DI because of our SUBREG hackery. */ + && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode)) + && TARGET_UPDATE + && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict) + && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict) + || legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)) + && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0))) + return 1; if (legitimate_lo_sum_address_p (mode, x, reg_ok_strict)) return 1; return 0; @@ -3864,7 +4022,10 @@ rs6000_mode_dependent_address (rtx addr) case LO_SUM: return true; - /* Auto-increment cases are now treated generically in recog.c. */ + case PRE_INC: + case PRE_DEC: + case PRE_MODIFY: + return TARGET_UPDATE; default: break; @@ -4038,7 +4199,7 @@ rs6000_emit_set_const (rtx dest, enum machine_mode mode, return dest; case SImode: - result = no_new_pseudos ? dest : gen_reg_rtx (SImode); + result = !can_create_pseudo_p () ? dest : gen_reg_rtx (SImode); emit_insn (gen_rtx_SET (VOIDmode, copy_rtx (result), GEN_INT (INTVAL (source) @@ -4257,7 +4418,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) return; } - if (!no_new_pseudos && GET_CODE (operands[0]) == MEM + if (can_create_pseudo_p () && GET_CODE (operands[0]) == MEM && !gpc_reg_operand (operands[1], mode)) operands[1] = force_reg (mode, operands[1]); @@ -4280,7 +4441,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) if (FP_REGNO_P (regnum) || regnum >= FIRST_PSEUDO_REGISTER) { rtx newreg; - newreg = (no_new_pseudos ? copy_rtx (operands[1]) + newreg = (!can_create_pseudo_p () ? copy_rtx (operands[1]) : gen_reg_rtx (mode)); emit_insn (gen_aux_truncdfsf2 (newreg, operands[1])); operands[1] = newreg; @@ -4407,7 +4568,9 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) && GET_CODE (operands[1]) != HIGH && GET_CODE (operands[1]) != CONST_INT) { - rtx target = (no_new_pseudos ? operands[0] : gen_reg_rtx (mode)); + rtx target = (!can_create_pseudo_p () + ? operands[0] + : gen_reg_rtx (mode)); /* If this is a function address on -mcall-aixdesc, convert it to the address of the descriptor. */ @@ -4602,7 +4765,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) memory always. The cast to unsigned makes -1 > 8. */ static bool -rs6000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) +rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) { /* In the darwin64 abi, try to use registers for larger structs if possible. */ @@ -4724,7 +4887,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, /* Return true if TYPE must be passed on the stack and not in registers. */ static bool -rs6000_must_pass_in_stack (enum machine_mode mode, tree type) +rs6000_must_pass_in_stack (enum machine_mode mode, const_tree type) { if (DEFAULT_ABI == ABI_AIX || TARGET_64BIT) return must_pass_in_stack_var_size (mode, type); @@ -4742,7 +4905,7 @@ rs6000_must_pass_in_stack (enum machine_mode mode, tree type) argument slot. */ enum direction -function_arg_padding (enum machine_mode mode, tree type) +function_arg_padding (enum machine_mode mode, const_tree type) { #ifndef AGGREGATE_PADDING_FIXED #define AGGREGATE_PADDING_FIXED 0 @@ -5301,7 +5464,7 @@ rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *cum, /* Recursive workhorse for the following. */ static void -rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, tree type, +rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, const_tree type, HOST_WIDE_INT startbitpos, rtx rvec[], int *k) { @@ -5371,7 +5534,7 @@ rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, tree type, calling convention. */ static rtx -rs6000_darwin64_record_arg (CUMULATIVE_ARGS *orig_cum, tree type, +rs6000_darwin64_record_arg (CUMULATIVE_ARGS *orig_cum, const_tree type, int named, bool retval) { rtx rvec[FIRST_PSEUDO_REGISTER]; @@ -5829,7 +5992,7 @@ rs6000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, static bool rs6000_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, - enum machine_mode mode, tree type, + enum machine_mode mode, const_tree type, bool named ATTRIBUTE_UNUSED) { if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && mode == TFmode) @@ -5935,7 +6098,8 @@ setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, CUMULATIVE_ARGS next_cum; int reg_size = TARGET_32BIT ? 4 : 8; rtx save_area = NULL_RTX, mem; - int first_reg_offset, set; + int first_reg_offset; + alias_set_type set; /* Skip the last named argument. */ next_cum = *cum; @@ -6194,8 +6358,8 @@ rs6000_va_start (tree valist, rtx nextarg) /* Find the overflow area. */ t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx); if (words != 0) - t = build2 (PLUS_EXPR, TREE_TYPE (ovf), t, - build_int_cst (NULL_TREE, words * UNITS_PER_WORD)); + t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (ovf), t, + size_int (words * UNITS_PER_WORD)); t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t); TREE_SIDE_EFFECTS (t) = 1; expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); @@ -6211,8 +6375,8 @@ rs6000_va_start (tree valist, rtx nextarg) /* Find the register save area. */ t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx); if (cfun->machine->varargs_save_offset) - t = build2 (PLUS_EXPR, TREE_TYPE (sav), t, - build_int_cst (NULL_TREE, cfun->machine->varargs_save_offset)); + t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (sav), t, + size_int (cfun->machine->varargs_save_offset)); t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (sav), sav, t); TREE_SIDE_EFFECTS (t) = 1; expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); @@ -6331,7 +6495,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) { regalign = 1; u = build2 (BIT_AND_EXPR, TREE_TYPE (reg), reg, - size_int (n_reg - 1)); + build_int_cst (TREE_TYPE (reg), n_reg - 1)); u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, u); } /* _Decimal128 is passed in even/odd fpr pairs; the stored @@ -6351,12 +6515,13 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) t = sav; if (sav_ofs) - t = build2 (PLUS_EXPR, ptr_type_node, sav, size_int (sav_ofs)); + t = build2 (POINTER_PLUS_EXPR, ptr_type_node, sav, size_int (sav_ofs)); - u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, size_int (n_reg)); - u = build1 (CONVERT_EXPR, integer_type_node, u); - u = build2 (MULT_EXPR, integer_type_node, u, size_int (sav_scale)); - t = build2 (PLUS_EXPR, ptr_type_node, t, u); + u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, + build_int_cst (TREE_TYPE (reg), n_reg)); + u = fold_convert (sizetype, u); + u = build2 (MULT_EXPR, sizetype, u, size_int (sav_scale)); + t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t, u); t = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t); gimplify_and_add (t, pre_p); @@ -6382,16 +6547,18 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p) t = ovf; if (align != 1) { - t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (align - 1)); + t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (align - 1)); + t = fold_convert (sizetype, t); t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t, - build_int_cst (NULL_TREE, -align)); + size_int (-align)); + t = fold_convert (TREE_TYPE (ovf), t); } gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue); u = build2 (GIMPLE_MODIFY_STMT, void_type_node, addr, t); gimplify_and_add (u, pre_p); - t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (size)); + t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (t), t, size_int (size)); t = build2 (GIMPLE_MODIFY_STMT, TREE_TYPE (ovf), ovf, t); gimplify_and_add (t, pre_p); @@ -7570,13 +7737,13 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, tree arg0, arg1, arg2; enum machine_mode mode0, mode1, mode2; rtx pat, op0, op1, op2; - struct builtin_description *d; + const struct builtin_description *d; size_t i; *expandedp = false; /* Handle DST variants. */ - d = (struct builtin_description *) bdesc_dst; + d = bdesc_dst; for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++) if (d->code == fcode) { @@ -7729,8 +7896,8 @@ altivec_expand_vec_ext_builtin (tree exp, rtx target) static rtx altivec_expand_builtin (tree exp, rtx target, bool *expandedp) { - struct builtin_description *d; - struct builtin_description_predicates *dp; + const struct builtin_description *d; + const struct builtin_description_predicates *dp; size_t i; enum insn_code icode; tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); @@ -7859,13 +8026,13 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp) } /* Expand abs* operations. */ - d = (struct builtin_description *) bdesc_abs; + d = bdesc_abs; for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++) if (d->code == fcode) return altivec_expand_abs_builtin (d->icode, exp, target); /* Expand the AltiVec predicates. */ - dp = (struct builtin_description_predicates *) bdesc_altivec_preds; + dp = bdesc_altivec_preds; for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++) if (dp->code == fcode) return altivec_expand_predicate_builtin (dp->icode, dp->opcode, @@ -8240,7 +8407,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, { tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); unsigned int fcode = DECL_FUNCTION_CODE (fndecl); - struct builtin_description *d; + const struct builtin_description *d; size_t i; rtx ret; bool success; @@ -8325,7 +8492,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return rs6000_expand_binop_builtin (d->icode, exp, target); /* Handle simple ternary operations. */ - d = (struct builtin_description *) bdesc_3arg; + d = bdesc_3arg; for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++) if (d->code == fcode) return rs6000_expand_ternop_builtin (d->icode, exp, target); @@ -8700,8 +8867,8 @@ spe_init_builtins (void) static void altivec_init_builtins (void) { - struct builtin_description *d; - struct builtin_description_predicates *dp; + const struct builtin_description *d; + const struct builtin_description_predicates *dp; size_t i; tree ftype; @@ -8882,12 +9049,12 @@ altivec_init_builtins (void) def_builtin (MASK_ALTIVEC, "__builtin_vec_ctu", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTU); /* Add the DST variants. */ - d = (struct builtin_description *) bdesc_dst; + d = bdesc_dst; for (i = 0; i < ARRAY_SIZE (bdesc_dst); i++, d++) def_builtin (d->mask, d->name, void_ftype_pcvoid_int_int, d->code); /* Initialize the predicates. */ - dp = (struct builtin_description_predicates *) bdesc_altivec_preds; + dp = bdesc_altivec_preds; for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++) { enum machine_mode mode1; @@ -8925,7 +9092,7 @@ altivec_init_builtins (void) } /* Initialize the abs* operators. */ - d = (struct builtin_description *) bdesc_abs; + d = bdesc_abs; for (i = 0; i < ARRAY_SIZE (bdesc_abs); i++, d++) { enum machine_mode mode0; @@ -9056,7 +9223,7 @@ altivec_init_builtins (void) static void rs6000_common_init_builtins (void) { - struct builtin_description *d; + const struct builtin_description *d; size_t i; tree v4sf_ftype_v4sf_v4sf_v16qi @@ -9253,7 +9420,7 @@ rs6000_common_init_builtins (void) V8HI_type_node, V8HI_type_node, NULL_TREE); /* Add the simple ternary operators. */ - d = (struct builtin_description *) bdesc_3arg; + d = bdesc_3arg; for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++) { enum machine_mode mode0, mode1, mode2, mode3; @@ -9685,6 +9852,8 @@ expand_block_clear (rtx operands[]) clear_step = 16; else if (TARGET_POWERPC64 && align >= 32) clear_step = 8; + else if (TARGET_SPE && align >= 64) + clear_step = 8; else clear_step = 4; @@ -9703,10 +9872,15 @@ expand_block_clear (rtx operands[]) clear_bytes = 16; mode = V4SImode; } + else if (bytes >= 8 && TARGET_SPE && align >= 64) + { + clear_bytes = 8; + mode = V2SImode; + } else if (bytes >= 8 && TARGET_POWERPC64 - /* 64-bit loads and stores require word-aligned - displacements. */ - && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32))) + /* 64-bit loads and stores require word-aligned + displacements. */ + && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32))) { clear_bytes = 8; mode = DImode; @@ -9796,6 +9970,12 @@ expand_block_move (rtx operands[]) mode = V4SImode; gen_func.mov = gen_movv4si; } + else if (TARGET_SPE && bytes >= 8 && align >= 64) + { + move_bytes = 8; + mode = V2SImode; + gen_func.mov = gen_movv2si; + } else if (TARGET_STRING && bytes > 24 /* move up to 32 bytes at a time */ && ! fixed_regs[5] @@ -10465,8 +10645,9 @@ rs6000_got_register (rtx value ATTRIBUTE_UNUSED) /* The second flow pass currently (June 1999) can't update regs_ever_live without disturbing other parts of the compiler, so update it here to make the prolog/epilogue code happy. */ - if (no_new_pseudos && ! regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM]) - regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1; + if (!can_create_pseudo_p () + && !df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM)) + df_set_regs_ever_live (RS6000_PIC_OFFSET_TABLE_REGNUM, true); current_function_uses_pic_offset_table = 1; @@ -10833,6 +11014,9 @@ print_operand (FILE *file, rtx x, int code) || GET_CODE (XEXP (x, 0)) == PRE_DEC) output_address (plus_constant (XEXP (XEXP (x, 0), 0), UNITS_PER_WORD)); + else if (GET_CODE (XEXP (x, 0)) == PRE_MODIFY) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), + UNITS_PER_WORD)); else output_address (XEXP (adjust_address_nv (x, SImode, UNITS_PER_WORD), @@ -11002,10 +11186,10 @@ print_operand (FILE *file, rtx x, int code) case 'T': /* Print the symbolic name of a branch target register. */ - if (GET_CODE (x) != REG || (REGNO (x) != LINK_REGISTER_REGNUM - && REGNO (x) != COUNT_REGISTER_REGNUM)) + if (GET_CODE (x) != REG || (REGNO (x) != LR_REGNO + && REGNO (x) != CTR_REGNO)) output_operand_lossage ("invalid %%T value"); - else if (REGNO (x) == LINK_REGISTER_REGNUM) + else if (REGNO (x) == LR_REGNO) fputs (TARGET_NEW_MNEMONICS ? "lr" : "r", file); else fputs ("ctr", file); @@ -11033,7 +11217,8 @@ print_operand (FILE *file, rtx x, int code) /* Print `u' if this has an auto-increment or auto-decrement. */ if (GET_CODE (x) == MEM && (GET_CODE (XEXP (x, 0)) == PRE_INC - || GET_CODE (XEXP (x, 0)) == PRE_DEC)) + || GET_CODE (XEXP (x, 0)) == PRE_DEC + || GET_CODE (XEXP (x, 0)) == PRE_MODIFY)) putc ('u', file); return; @@ -11120,7 +11305,9 @@ print_operand (FILE *file, rtx x, int code) case 'X': if (GET_CODE (x) == MEM - && legitimate_indexed_address_p (XEXP (x, 0), 0)) + && (legitimate_indexed_address_p (XEXP (x, 0), 0) + || (GET_CODE (XEXP (x, 0)) == PRE_MODIFY + && legitimate_indexed_address_p (XEXP (XEXP (x, 0), 1), 0)))) putc ('x', file); return; @@ -11133,6 +11320,8 @@ print_operand (FILE *file, rtx x, int code) if (GET_CODE (XEXP (x, 0)) == PRE_INC || GET_CODE (XEXP (x, 0)) == PRE_DEC) output_address (plus_constant (XEXP (XEXP (x, 0), 0), 8)); + else if (GET_CODE (XEXP (x, 0)) == PRE_MODIFY) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), 8)); else output_address (XEXP (adjust_address_nv (x, SImode, 8), 0)); if (small_data_operand (x, GET_MODE (x))) @@ -11180,6 +11369,8 @@ print_operand (FILE *file, rtx x, int code) if (GET_CODE (XEXP (x, 0)) == PRE_INC || GET_CODE (XEXP (x, 0)) == PRE_DEC) output_address (plus_constant (XEXP (XEXP (x, 0), 0), 12)); + else if (GET_CODE (XEXP (x, 0)) == PRE_MODIFY) + output_address (plus_constant (XEXP (XEXP (x, 0), 0), 12)); else output_address (XEXP (adjust_address_nv (x, SImode, 12), 0)); if (small_data_operand (x, GET_MODE (x))) @@ -11260,6 +11451,8 @@ print_operand (FILE *file, rtx x, int code) else if (GET_CODE (XEXP (x, 0)) == PRE_DEC) fprintf (file, "%d(%s)", - GET_MODE_SIZE (GET_MODE (x)), reg_names[REGNO (XEXP (XEXP (x, 0), 0))]); + else if (GET_CODE (XEXP (x, 0)) == PRE_MODIFY) + output_address (XEXP (XEXP (x, 0), 1)); else output_address (XEXP (x, 0)); } @@ -12104,7 +12297,7 @@ rs6000_emit_vector_compare (enum rtx_code rcode, eq_rtx = rs6000_emit_vector_compare (rev_code, op0, op1, dest_mode); - nor_code = one_cmpl_optab->handlers[(int)dest_mode].insn_code; + nor_code = optab_handler (one_cmpl_optab, (int)dest_mode)->insn_code; gcc_assert (nor_code != CODE_FOR_nothing); emit_insn (GEN_FCN (nor_code) (mask, eq_rtx)); @@ -12154,7 +12347,7 @@ rs6000_emit_vector_compare (enum rtx_code rcode, eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1, dest_mode); - ior_code = ior_optab->handlers[(int)dest_mode].insn_code; + ior_code = optab_handler (ior_optab, (int)dest_mode)->insn_code; gcc_assert (ior_code != CODE_FOR_nothing); emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx)); if (dmode != dest_mode) @@ -13120,7 +13313,7 @@ first_reg_to_save (void) /* Find lowest numbered live register. */ for (first_reg = 13; first_reg <= 31; first_reg++) - if (regs_ever_live[first_reg] + if (df_regs_ever_live_p (first_reg) && (! call_used_regs[first_reg] || (first_reg == RS6000_PIC_OFFSET_TABLE_REGNUM && ((DEFAULT_ABI == ABI_V4 && flag_pic != 0) @@ -13147,7 +13340,7 @@ first_fp_reg_to_save (void) /* Find lowest numbered live register. */ for (first_reg = 14 + 32; first_reg <= 63; first_reg++) - if (regs_ever_live[first_reg]) + if (df_regs_ever_live_p (first_reg)) break; return first_reg; @@ -13173,7 +13366,7 @@ first_altivec_reg_to_save (void) /* Find lowest numbered live register. */ for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i) - if (regs_ever_live[i]) + if (df_regs_ever_live_p (i)) break; return i; @@ -13197,7 +13390,7 @@ compute_vrsave_mask (void) /* First, find out if we use _any_ altivec registers. */ for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i) - if (regs_ever_live[i]) + if (df_regs_ever_live_p (i)) mask |= ALTIVEC_REG_BIT (i); if (mask == 0) @@ -13458,13 +13651,13 @@ rs6000_stack_info (void) || rs6000_ra_ever_killed ()) { info_ptr->lr_save_p = 1; - regs_ever_live[LINK_REGISTER_REGNUM] = 1; + df_set_regs_ever_live (LR_REGNO, true); } /* Determine if we need to save the condition code registers. */ - if (regs_ever_live[CR2_REGNO] - || regs_ever_live[CR3_REGNO] - || regs_ever_live[CR4_REGNO]) + if (df_regs_ever_live_p (CR2_REGNO) + || df_regs_ever_live_p (CR3_REGNO) + || df_regs_ever_live_p (CR4_REGNO)) { info_ptr->cr_save_p = 1; if (DEFAULT_ABI == ABI_V4) @@ -13882,7 +14075,7 @@ rs6000_return_addr (int count, rtx frame) } cfun->machine->ra_need_lr = 1; - return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM); + return get_hard_reg_initial_val (Pmode, LR_REGNO); } /* Say whether a function is a candidate for sibcall handling or not. @@ -13908,7 +14101,8 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) } } if (DEFAULT_ABI == ABI_DARWIN - || (*targetm.binds_local_p) (decl)) + || ((*targetm.binds_local_p) (decl) + && (DEFAULT_ABI != ABI_AIX || !DECL_EXTERNAL (decl)))) { tree attr_list = TYPE_ATTRIBUTES (TREE_TYPE (decl)); @@ -13925,7 +14119,7 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) PowerPC uses the COUNT register for branch on table instructions. */ static const char * -rs6000_invalid_within_doloop (rtx insn) +rs6000_invalid_within_doloop (const_rtx insn) { if (CALL_P (insn)) return "Function call in the loop."; @@ -13967,7 +14161,7 @@ rs6000_ra_ever_killed (void) push_topmost_sequence (); top = get_insns (); pop_topmost_sequence (); - reg = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM); + reg = gen_rtx_REG (Pmode, LR_REGNO); for (insn = NEXT_INSN (top); insn != NULL_RTX; insn = NEXT_INSN (insn)) { @@ -13978,7 +14172,7 @@ rs6000_ra_ever_killed (void) if (!SIBLING_CALL_P (insn)) return 1; } - else if (find_regno_note (insn, REG_INC, LINK_REGISTER_REGNUM)) + else if (find_regno_note (insn, REG_INC, LR_REGNO)) return 1; else if (set_of (reg, insn) != NULL_RTX && !prologue_epilogue_contains (insn)) @@ -13988,15 +14182,6 @@ rs6000_ra_ever_killed (void) return 0; } -/* Add a REG_MAYBE_DEAD note to the insn. */ -static void -rs6000_maybe_dead (rtx insn) -{ - REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, - const0_rtx, - REG_NOTES (insn)); -} - /* Emit instructions needed to load the TOC register. This is only needed when TARGET_TOC, TARGET_MINIMAL_TOC, and there is a constant pool; or for SVR4 -fpic. */ @@ -14004,7 +14189,7 @@ rs6000_maybe_dead (rtx insn) void rs6000_emit_load_toc_table (int fromprolog) { - rtx dest, insn; + rtx dest; dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM); if (TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic) @@ -14024,29 +14209,16 @@ rs6000_emit_load_toc_table (int fromprolog) tmp1 = gen_reg_rtx (Pmode); tmp2 = gen_reg_rtx (Pmode); } - insn = emit_insn (gen_load_toc_v4_PIC_1 (lab)); - if (fromprolog) - rs6000_maybe_dead (insn); - insn = emit_move_insn (tmp1, - gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)); - if (fromprolog) - rs6000_maybe_dead (insn); - insn = emit_insn (gen_load_toc_v4_PIC_3b (tmp2, tmp1, got, lab)); - if (fromprolog) - rs6000_maybe_dead (insn); - insn = emit_insn (gen_load_toc_v4_PIC_3c (dest, tmp2, got, lab)); - if (fromprolog) - rs6000_maybe_dead (insn); + emit_insn (gen_load_toc_v4_PIC_1 (lab)); + emit_move_insn (tmp1, + gen_rtx_REG (Pmode, LR_REGNO)); + emit_insn (gen_load_toc_v4_PIC_3b (tmp2, tmp1, got, lab)); + emit_insn (gen_load_toc_v4_PIC_3c (dest, tmp2, got, lab)); } else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1) { - insn = emit_insn (gen_load_toc_v4_pic_si ()); - if (fromprolog) - rs6000_maybe_dead (insn); - insn = emit_move_insn (dest, - gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)); - if (fromprolog) - rs6000_maybe_dead (insn); + emit_insn (gen_load_toc_v4_pic_si ()); + emit_move_insn (dest, gen_rtx_REG (Pmode, LR_REGNO)); } else if (TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2) { @@ -14065,13 +14237,10 @@ rs6000_emit_load_toc_table (int fromprolog) ASM_GENERATE_INTERNAL_LABEL (buf, "LCL", rs6000_pic_labelno); symL = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); - rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_1 (symF))); - rs6000_maybe_dead (emit_move_insn (dest, - gen_rtx_REG (Pmode, - LINK_REGISTER_REGNUM))); - rs6000_maybe_dead (emit_insn (gen_load_toc_v4_PIC_2 (temp0, dest, - symL, - symF))); + emit_insn (gen_load_toc_v4_PIC_1 (symF)); + emit_move_insn (dest, + gen_rtx_REG (Pmode, LR_REGNO)); + emit_insn (gen_load_toc_v4_PIC_2 (temp0, dest, symL, symF)); } else { @@ -14080,12 +14249,10 @@ rs6000_emit_load_toc_table (int fromprolog) tocsym = gen_rtx_SYMBOL_REF (Pmode, toc_label_name); emit_insn (gen_load_toc_v4_PIC_1b (tocsym)); emit_move_insn (dest, - gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)); + gen_rtx_REG (Pmode, LR_REGNO)); emit_move_insn (temp0, gen_rtx_MEM (Pmode, dest)); } - insn = emit_insn (gen_addsi3 (dest, temp0, dest)); - if (fromprolog) - rs6000_maybe_dead (insn); + emit_insn (gen_addsi3 (dest, temp0, dest)); } else if (TARGET_ELF && !TARGET_AIX && flag_pic == 0 && TARGET_MINIMAL_TOC) { @@ -14095,23 +14262,17 @@ rs6000_emit_load_toc_table (int fromprolog) ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1); realsym = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)); - insn = emit_insn (gen_elf_high (dest, realsym)); - if (fromprolog) - rs6000_maybe_dead (insn); - insn = emit_insn (gen_elf_low (dest, dest, realsym)); - if (fromprolog) - rs6000_maybe_dead (insn); + emit_insn (gen_elf_high (dest, realsym)); + emit_insn (gen_elf_low (dest, dest, realsym)); } else { gcc_assert (DEFAULT_ABI == ABI_AIX); if (TARGET_32BIT) - insn = emit_insn (gen_load_toc_aix_si (dest)); + emit_insn (gen_load_toc_aix_si (dest)); else - insn = emit_insn (gen_load_toc_aix_di (dest)); - if (fromprolog) - rs6000_maybe_dead (insn); + emit_insn (gen_load_toc_aix_di (dest)); } } @@ -14149,12 +14310,12 @@ rs6000_emit_eh_reg_restore (rtx source, rtx scratch) emit_move_insn (tmp, operands[0]); } else - emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]); + emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), operands[0]); } -static GTY(()) int set = -1; +static GTY(()) alias_set_type set = -1; -int +alias_set_type get_TOC_alias_set (void) { if (set == -1) @@ -14197,8 +14358,8 @@ uses_TOC (void) rtx create_TOC_reference (rtx symbol) { - if (no_new_pseudos) - regs_ever_live[TOC_REGISTER] = 1; + if (!can_create_pseudo_p ()) + df_set_regs_ever_live (TOC_REGISTER, true); return gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, TOC_REGISTER), gen_rtx_CONST (Pmode, @@ -14641,7 +14802,7 @@ no_global_regs_above (int first_greg) static bool rs6000_reg_live_or_pic_offset_p (int reg) { - return ((regs_ever_live[reg] + return ((df_regs_ever_live_p (reg) && (!call_used_regs[reg] || (reg == RS6000_PIC_OFFSET_TABLE_REGNUM && TARGET_TOC && TARGET_MINIMAL_TOC))) @@ -14731,7 +14892,7 @@ rs6000_emit_prologue (void) if (info->lr_save_p) { insn = emit_move_insn (reg0, - gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)); + gen_rtx_REG (Pmode, LR_REGNO)); RTX_FRAME_RELATED_P (insn) = 1; } @@ -14764,7 +14925,7 @@ rs6000_emit_prologue (void) j = 0; RTVEC_ELT (p, j++) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, - LINK_REGISTER_REGNUM)); + LR_REGNO)); RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, "*save_world")); @@ -14839,7 +15000,7 @@ rs6000_emit_prologue (void) rtx addr, reg, mem; insn = emit_move_insn (gen_rtx_REG (Pmode, 0), - gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)); + gen_rtx_REG (Pmode, LR_REGNO)); RTX_FRAME_RELATED_P (insn) = 1; addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, @@ -14881,7 +15042,7 @@ rs6000_emit_prologue (void) { int i; for (i = 0; i < 64 - info->first_fp_reg_save; i++) - if ((regs_ever_live[info->first_fp_reg_save+i] + if ((df_regs_ever_live_p (info->first_fp_reg_save+i) && ! call_used_regs[info->first_fp_reg_save+i])) emit_frame_save (frame_reg_rtx, frame_ptr_rtx, DFmode, info->first_fp_reg_save + i, @@ -14898,7 +15059,7 @@ rs6000_emit_prologue (void) RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, - LINK_REGISTER_REGNUM)); + LR_REGNO)); sprintf (rname, "%s%d%s", SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX); alloc_rname = ggc_strdup (rname); @@ -14952,7 +15113,7 @@ rs6000_emit_prologue (void) int i; rtx spe_save_area_ptr; int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE - && regs_ever_live[STATIC_CHAIN_REGNUM] + && df_regs_ever_live_p (STATIC_CHAIN_REGNUM) && !call_used_regs[STATIC_CHAIN_REGNUM]); /* Determine whether we can address all of the registers that need @@ -15206,7 +15367,7 @@ rs6000_emit_prologue (void) if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0) || (DEFAULT_ABI == ABI_V4 && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT)) - && regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM])) + && df_regs_ever_live_p (RS6000_PIC_OFFSET_TABLE_REGNUM))) { /* If emit_load_toc_table will use the link register, we need to save it. We use R12 for this purpose because emit_load_toc_table @@ -15219,16 +15380,14 @@ rs6000_emit_prologue (void) && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0); if (save_LR_around_toc_setup) { - rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM); + rtx lr = gen_rtx_REG (Pmode, LR_REGNO); insn = emit_move_insn (frame_ptr_rtx, lr); - rs6000_maybe_dead (insn); RTX_FRAME_RELATED_P (insn) = 1; rs6000_emit_load_toc_table (TRUE); insn = emit_move_insn (lr, frame_ptr_rtx); - rs6000_maybe_dead (insn); RTX_FRAME_RELATED_P (insn) = 1; } else @@ -15239,22 +15398,21 @@ rs6000_emit_prologue (void) if (DEFAULT_ABI == ABI_DARWIN && flag_pic && current_function_uses_pic_offset_table) { - rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM); + rtx lr = gen_rtx_REG (Pmode, LR_REGNO); rtx src = machopic_function_base_sym (); /* Save and restore LR locally around this call (in R0). */ if (!info->lr_save_p) - rs6000_maybe_dead (emit_move_insn (gen_rtx_REG (Pmode, 0), lr)); + emit_move_insn (gen_rtx_REG (Pmode, 0), lr); - rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (src))); + emit_insn (gen_load_macho_picbase (src)); - insn = emit_move_insn (gen_rtx_REG (Pmode, - RS6000_PIC_OFFSET_TABLE_REGNUM), - lr); - rs6000_maybe_dead (insn); + emit_move_insn (gen_rtx_REG (Pmode, + RS6000_PIC_OFFSET_TABLE_REGNUM), + lr); if (!info->lr_save_p) - rs6000_maybe_dead (emit_move_insn (lr, gen_rtx_REG (Pmode, 0))); + emit_move_insn (lr, gen_rtx_REG (Pmode, 0)); } #endif } @@ -15396,7 +15554,7 @@ rs6000_emit_epilogue (int sibcall) RTVEC_ELT (p, j++) = gen_rtx_RETURN (VOIDmode); RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, - LINK_REGISTER_REGNUM)); + LR_REGNO)); RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, alloc_rname)); /* The instruction pattern requires a clobber here; @@ -15553,7 +15711,7 @@ rs6000_emit_epilogue (int sibcall) /* Set LR here to try to overlap restores below. */ if (info->lr_save_p) - emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), + emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), gen_rtx_REG (Pmode, 0)); /* Load exception handler data registers, if needed. */ @@ -15628,7 +15786,7 @@ rs6000_emit_epilogue (int sibcall) else { /* Make r11 point to the start of the SPE save area. We worried about - not clobbering it when we were saving registers in the prolgoue. + not clobbering it when we were saving registers in the prologue. There's no need to worry here because the static chain is passed anew to every function. */ spe_save_area_ptr = gen_rtx_REG (Pmode, 11); @@ -15673,7 +15831,7 @@ rs6000_emit_epilogue (int sibcall) /* Restore fpr's if we need to do it without calling a function. */ if (restoring_FPRs_inline) for (i = 0; i < 64 - info->first_fp_reg_save; i++) - if ((regs_ever_live[info->first_fp_reg_save+i] + if ((df_regs_ever_live_p (info->first_fp_reg_save+i) && ! call_used_regs[info->first_fp_reg_save+i])) { rtx addr, mem; @@ -15697,7 +15855,7 @@ rs6000_emit_epilogue (int sibcall) if (using_mtcr_multiple) { for (i = 0; i < 8; i++) - if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i]) + if (df_regs_ever_live_p (CR0_REGNO+i) && ! call_used_regs[CR0_REGNO+i]) count++; gcc_assert (count); } @@ -15711,7 +15869,7 @@ rs6000_emit_epilogue (int sibcall) ndx = 0; for (i = 0; i < 8; i++) - if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i]) + if (df_regs_ever_live_p (CR0_REGNO+i) && ! call_used_regs[CR0_REGNO+i]) { rtvec r = rtvec_alloc (2); RTVEC_ELT (r, 0) = r12_rtx; @@ -15726,7 +15884,7 @@ rs6000_emit_epilogue (int sibcall) } else for (i = 0; i < 8; i++) - if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i]) + if (df_regs_ever_live_p (CR0_REGNO+i) && ! call_used_regs[CR0_REGNO+i]) { emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode, CR0_REGNO+i), @@ -15775,7 +15933,7 @@ rs6000_emit_epilogue (int sibcall) RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode); RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, - LINK_REGISTER_REGNUM)); + LR_REGNO)); /* If we have to restore more than two FP registers, branch to the restore function. It will return to our caller. */ @@ -16147,7 +16305,6 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, reload_completed = 1; epilogue_completed = 1; - no_new_pseudos = 1; /* Mark the end of the (empty) prologue. */ emit_note (NOTE_INSN_PROLOGUE_END); @@ -16217,7 +16374,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, gen_rtx_USE (VOIDmode, const0_rtx), gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, - LINK_REGISTER_REGNUM)), + LR_REGNO)), gen_rtx_RETURN (VOIDmode)))); SIBLING_CALL_P (insn) = 1; emit_barrier (); @@ -16235,7 +16392,6 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, reload_completed = 0; epilogue_completed = 0; - no_new_pseudos = 0; } /* A quick summary of the various types of 'constant-pool tables' @@ -16867,7 +17023,7 @@ output_profile_hook (int labelno ATTRIBUTE_UNUSED) else if (DEFAULT_ABI == ABI_DARWIN) { const char *mcount_name = RS6000_MCOUNT; - int caller_addr_regno = LINK_REGISTER_REGNUM; + int caller_addr_regno = LR_REGNO; /* Be conservative and always set this, at least for now. */ current_function_uses_pic_offset_table = 1; @@ -17814,7 +17970,7 @@ rs6000_is_costly_dependence (dep_t dep, int cost, int distance) if (rs6000_sched_costly_dep == true_store_to_load_dep_costly && is_load_insn (next) && is_store_insn (insn) - && DEP_KIND (dep) == REG_DEP_TRUE) + && DEP_TYPE (dep) == REG_DEP_TRUE) /* Prevent load after store in the same group if it is a true dependence. */ return true; @@ -18290,15 +18446,15 @@ is_costly_group (rtx *group_insns, rtx next_insn) for (i = 0; i < issue_rate; i++) { - dep_link_t link; + sd_iterator_def sd_it; + dep_t dep; rtx insn = group_insns[i]; if (!insn) continue; - FOR_EACH_DEP_LINK (link, INSN_FORW_DEPS (insn)) + FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep) { - dep_t dep = DEP_LINK_DEP (link); rtx next = DEP_CON (dep); if (next == next_insn @@ -18847,8 +19003,14 @@ rs6000_handle_altivec_attribute (tree *node, elements; we must teach the compiler how to mangle them. */ static const char * -rs6000_mangle_fundamental_type (tree type) +rs6000_mangle_type (const_tree type) { + type = TYPE_MAIN_VARIANT (type); + + if (TREE_CODE (type) != VOID_TYPE && TREE_CODE (type) != BOOLEAN_TYPE + && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE) + return NULL; + if (type == bool_char_type_node) return "U6__boolc"; if (type == bool_short_type_node) return "U6__bools"; if (type == pixel_type_node) return "u7__pixel"; @@ -18971,7 +19133,7 @@ rs6000_handle_struct_attribute (tree *node, tree name, } static bool -rs6000_ms_bitfield_layout_p (tree record_type) +rs6000_ms_bitfield_layout_p (const_tree record_type) { return (TARGET_USE_MS_BITFIELD_LAYOUT && !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type))) @@ -19073,7 +19235,7 @@ rs6000_elf_encode_section_info (tree decl, rtx rtl, int first) } bool -rs6000_elf_in_small_data_p (tree decl) +rs6000_elf_in_small_data_p (const_tree decl) { if (rs6000_sdata == SDATA_NONE) return false; @@ -19117,7 +19279,7 @@ rs6000_elf_in_small_data_p (tree decl) /* Implement TARGET_USE_BLOCKS_FOR_CONSTANT_P. */ static bool -rs6000_use_blocks_for_constant_p (enum machine_mode mode, rtx x) +rs6000_use_blocks_for_constant_p (enum machine_mode mode, const_rtx x) { return !ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode); } @@ -19436,7 +19598,7 @@ rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, /* Use a different reg for the intermediate value, as it will be marked UNCHANGING. */ - reg_temp = no_new_pseudos ? reg : gen_reg_rtx (Pmode); + reg_temp = !can_create_pseudo_p () ? reg : gen_reg_rtx (Pmode); base = rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg_temp); offset = @@ -20149,10 +20311,15 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total) *total += COSTS_N_INSNS (2); return false; + case CTZ: case FFS: *total = COSTS_N_INSNS (4); return false; + case POPCOUNT: + *total = COSTS_N_INSNS (6); + return false; + case NOT: if (outer_code == AND || outer_code == IOR || outer_code == XOR) { @@ -20162,6 +20329,7 @@ rs6000_rtx_costs (rtx x, int code, int outer_code, int *total) /* FALLTHRU */ case AND: + case CLZ: case IOR: case XOR: case ZERO_EXTRACT: @@ -20594,7 +20762,7 @@ rs6000_complex_function_value (enum machine_mode mode) fp1, unless -msoft-float. */ rtx -rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED) +rs6000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) { enum machine_mode mode; unsigned int regno; @@ -20797,7 +20965,7 @@ rs6000_initial_elimination_offset (int from, int to) /* Return true if TYPE is a SPE or AltiVec opaque type. */ static bool -rs6000_is_opaque_type (tree type) +rs6000_is_opaque_type (const_tree type) { return (type == opaque_V2SI_type_node || type == opaque_V2SF_type_node @@ -20866,9 +21034,9 @@ rs6000_dbx_register_number (unsigned int regno) return regno; if (regno == MQ_REGNO) return 100; - if (regno == LINK_REGISTER_REGNUM) + if (regno == LR_REGNO) return 108; - if (regno == COUNT_REGISTER_REGNUM) + if (regno == CTR_REGNO) return 109; if (CR_REGNO_P (regno)) return regno - CR0_REGNO + 86; @@ -20924,7 +21092,7 @@ rs6000_vector_mode_supported_p (enum machine_mode mode) /* Target hook for invalid_arg_for_unprototyped_fn. */ static const char * -invalid_arg_for_unprototyped_fn (tree typelist, tree funcdecl, tree val) +invalid_arg_for_unprototyped_fn (const_tree typelist, const_tree funcdecl, const_tree val) { return (!rs6000_darwin64_abi && typelist == 0