diff --git a/.cvsignore b/.cvsignore index 12497ff..133dcdc 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1 +1 @@ -gcc-4.4.0-20090319.tar.bz2 +gcc-4.4.1-20090818.tar.bz2 diff --git a/gcc44-atom.patch b/gcc44-atom.patch deleted file mode 100644 index e122e46..0000000 --- a/gcc44-atom.patch +++ /dev/null @@ -1,2832 +0,0 @@ -2009-02-05 Joey Ye - Xuepeng Guo - H.J. Lu - - Atom pipeline model, tuning and insn selection. - * rtlanal.c (reg_mentioned_by_mem_p_1): New function. - (reg_mentioned_by_mem_p): New function. - (reg_dep_by_addr_p): New function. - - * rtl.h (reg_mentioned_by_mem_p): Declare new function. - (reg_dep_by_addr_p): Likewise. - - * config.gcc (atom): Add atom config options and target. - - * config/i386/i386.h (TARGET_ATOM): New target macro. - (X86_TUNE_OPT_AGU): New tuning flag. - (TARGET_OPT_AGU): New target option. - (TARGET_CPU_DEFAULT_atom): New CPU default. - (PROCESSOR_ATOM): New processor. - - * config/i386/i386-c.c (ix86_target_macros_internal): New case - PROCESSOR_ATOM. - (ix86_target_macros_internal): Likewise. - - * config/i386/i386-protos.h (ix86_lea_for_add_ok): Declare new - function. - (ix86_dep_by_shift_count): Likewise. - (ix86_agi_dependent): Likewise. - - * config/i386/i386.c (atom_cost): New cost. - (m_ATOM): New macro flag. - (initial_ix86_tune_fe): Set m_ATOM. - (x86_accumulate_outgoing_args): Likewise. - (x86_arch_always_fancy_math_387): Likewise. - (processor_target): Add Atom cost. - (cpu_names): Add Atom cpu name. - (override_options): Set Atom ISA. - (LEA_SEARCH_THRESHOLD): New macro. - (distance_non_agu_define): New function. - (distance_agu_use): Likewise. - (ix86_lea_for_add_ok): Likewise. - (ix86_dep_by_shift_count): Likewise. - (ix86_agi_dependent): Make it global. - (ix86_issue_rate): New case PROCESSOR_ATOM. - (ix86_adjust_cost): Likewise. - - * config/i386/i386.md (cpu): Add new value "atom". - (atom.md): Include atom.md. - (use_carry, movu): New attr. - (adddi3_carry_rex64): Set attr "use_carry". - (addqi3_carry): Likewise. - (addhi3_carry): Likewise. - (addsi3_carry): Likewise. - (*addsi3_carry_zext): Likewise. - (subdi3_carry_rex64): Likewise. - (subqi3_carry): Likewise. - (subhi3_carry): Likewise. - (subsi3_carry): Likewise. - (x86_movdicc_0_m1_rex64): Likewise. - (*x86_movdicc_0_m1_se): Likewise. - (x86_movsicc_0_m1): Likewise. - (*x86_movsicc_0_m1_se): Likewise. - (*adddi_1_rex64): Emit add insn as much as possible. - (*addsi_1): Likewise. - (return_internal): Set atom_unit. - (return_internal_long): Likewise. - (return_pop_internal): Likewise. - (*rcpsf2_sse): Set atom_sse_attr attr. - (*qrt2_sse): Likewise. - (*prefetch_sse): Likewise. - - * config/i386/sse.md (cpu): Set attr "atom_sse_attr". - (*prefetch_sse_rex): Likewise. - (sse_rcpv4sf2): Likewise. - (sse_vmrcpv4sf2): Likewise. - (sse_sqrtv4sf2): Likewise. - (_vmsqrt2): Likewise. - (sse_ldmxcsr): Likewise. - (sse_stmxcsr): Likewise. - (*sse_sfence): Likewise. - (sse2_clflush): Likewise. - (*sse2_mfence): Likewise. - (*sse2_lfence): Likewise. - (avx_movup): Set attr "movu". - (_movup): Likewise. - (avx_movdqu): Likewise. - (avx_lddqu): Likewise. - (sse2_movntv2di): Change attr "type" to "ssemov". - (sse2_movntsi): Likewise. - (rsqrtv8sf2): Change attr "type" to "sseadd". - (sse3_addsubv2df3): Set attr "atom_unit". - (sse3_hv4sf3): Likewise. - (*sse2_pmaddwd): Likewise. - (*vec_extractv2di_1_rex64): Likewise. - (*vec_extractv2di_1_avx): Likewise. - (sse2_psadbw): Likewise. - (ssse3_phaddwv8hi3): Likewise. - (ssse3_phaddwv4hi3): Likewise. - (ssse3_phadddv4si3): Likewise. - (ssse3_phadddv2si3): Likewise. - (ssse3_phaddswv8hi3): Likewise. - (ssse3_phaddswv4hi3): Likewise. - (ssse3_phsubwv8hi3): Likewise. - (ssse3_phsubwv4hi3): Likewise. - (ssse3_phsubdv4si3): Likewise. - (ssse3_phsubdv2si3): Likewise. - (ssse3_phsubswv8hi3): Likewise. - (ssse3_phsubswv4hi3): Likewise. - (ssse3_pmaddubsw128): Likewise. - (sse3_pmaddubsw: Likewise. - (ssse3_palignrti): Likewise. - (ssse3_palignrdi): Likewise. - - * config/i386/atom.md: New. - -2009-02-05 H.J. Lu - - * config/i386/i386.c (ix86_agi_dependent): Remove the third - argument. Swap the first 2 arguments. - (ix86_adjust_cost): Updated. - -2009-01-30 Vladimir Makarov - - * genautomata.c: Add a new year to the copyright. Add a new - reference. - (struct insn_reserv_decl): Add comments for member bypass_list. - (find_bypass): Remove. - (insert_bypass): New. - (process_decls): Use insert_bypass. - (output_internal_insn_latency_func): Output all bypasses with the - same input insn in one switch case. - - * rtl.def (define_bypass): Describe bypass choice. - * doc/md.texi (define_bypass): Ditto. - ---- gcc/doc/md.texi (.../trunk) (revision 144460) -+++ gcc/doc/md.texi (.../branches/ix86/atom) (revision 144601) -@@ -7506,6 +7506,11 @@ be ignored for this case. The additiona - recognize complicated bypasses, e.g.@: when the consumer is only an address - of insn @samp{store} (not a stored value). - -+If there are more one bypass with the same output and input insns, the -+chosen bypass is the first bypass with a guard in description whose -+guard function returns nonzero. If there is no such bypass, then -+bypass without the guard function is chosen. -+ - @findex exclusion_set - @findex presence_set - @findex final_presence_set ---- gcc/rtlanal.c (.../trunk) (revision 144460) -+++ gcc/rtlanal.c (.../branches/ix86/atom) (revision 144601) -@@ -728,6 +728,129 @@ reg_mentioned_p (const_rtx reg, const_rt - } - return 0; - } -+ -+static int -+reg_mentioned_by_mem_p_1 (const_rtx reg, const_rtx in, -+ bool *mem_p) -+{ -+ const char *fmt; -+ int i; -+ enum rtx_code code; -+ -+ if (in == 0) -+ return 0; -+ -+ if (reg == in) -+ return 1; -+ -+ if (GET_CODE (in) == LABEL_REF) -+ return reg == XEXP (in, 0); -+ -+ code = GET_CODE (in); -+ -+ switch (code) -+ { -+ /* Compare registers by number. */ -+ case REG: -+ return REG_P (reg) && REGNO (in) == REGNO (reg); -+ -+ /* These codes have no constituent expressions -+ and are unique. */ -+ case SCRATCH: -+ case CC0: -+ case PC: -+ return 0; -+ -+ case CONST_INT: -+ case CONST_VECTOR: -+ case CONST_DOUBLE: -+ case CONST_FIXED: -+ /* These are kept unique for a given value. */ -+ return 0; -+ -+ default: -+ break; -+ } -+ -+ if (GET_CODE (reg) == code && rtx_equal_p (reg, in)) -+ return 1; -+ -+ fmt = GET_RTX_FORMAT (code); -+ -+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) -+ { -+ if (fmt[i] == 'E') -+ { -+ int j; -+ for (j = XVECLEN (in, i) - 1; j >= 0; j--) -+ if (reg_mentioned_by_mem_p_1 (reg, XVECEXP (in, i, j), mem_p)) -+ { -+ if (code == MEM) -+ *mem_p = true; -+ -+ return 1; -+ } -+ } -+ else if (fmt[i] == 'e' -+ && reg_mentioned_by_mem_p_1 (reg, XEXP (in, i), mem_p)) -+ { -+ if (code == MEM) -+ *mem_p = true; -+ -+ return 1; -+ } -+ } -+ return 0; -+} -+ -+/* Similar to the function reg_mentioned_p, return true only when -+ register REG appears in a MEM container of RTX IN. */ -+ -+bool -+reg_mentioned_by_mem_p (const_rtx reg, const_rtx in) -+{ -+ bool mem = false; -+ -+ reg_mentioned_by_mem_p_1 (reg, in, &mem); -+ return mem; -+} -+ -+/* Return true if dest regsiter in set_insn is used in use_insn as -+ address calculation. -+ For example, returns true if -+ set_insn: reg_a = reg_b -+ use_insn: reg_c = (reg_a) # reg_a used in addr calculation -+ False if -+ set_insn: reg_a = reg_b -+ use_insn: (reg_c) = reg_a # reg_a is used, by not as addr. */ -+ -+bool -+reg_dep_by_addr_p (const_rtx set_insn, const_rtx use_insn) -+{ -+ rtx pattern = PATTERN (set_insn); -+ rtx set_dest = NULL; -+ -+ switch (GET_CODE (pattern)) -+ { -+ case SET: -+ set_dest = SET_DEST (pattern); -+ break; -+ case PARALLEL: -+ { -+ rtx pattern2 = XVECEXP (PATTERN (set_insn), 0,0); -+ if (GET_CODE (pattern2) == SET) -+ set_dest = SET_DEST (pattern2); -+ break; -+ } -+ default: -+ set_dest = NULL; -+ } -+ -+ /* True if destination of set is reg and used as address. */ -+ return set_dest && REG_P (set_dest) -+ && reg_mentioned_by_mem_p (set_dest, use_insn); -+} -+ - - /* Return 1 if in between BEG and END, exclusive of BEG and END, there is - no CODE_LABEL insn. */ ---- gcc/genautomata.c (.../trunk) (revision 144460) -+++ gcc/genautomata.c (.../branches/ix86/atom) (revision 144601) -@@ -22,21 +22,25 @@ along with GCC; see the file COPYING3. - - /* References: - -- 1. Detecting pipeline structural hazards quickly. T. Proebsting, -+ 1. The finite state automaton based pipeline hazard recognizer and -+ instruction scheduler in GCC. V. Makarov. Proceedings of GCC -+ summit, 2003. -+ -+ 2. Detecting pipeline structural hazards quickly. T. Proebsting, - C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on - Principles of Programming Languages, pages 280--286, 1994. - - This article is a good start point to understand usage of finite - state automata for pipeline hazard recognizers. But I'd -- recommend the 2nd article for more deep understanding. -+ recommend the 1st and 3rd article for more deep understanding. - -- 2. Efficient Instruction Scheduling Using Finite State Automata: -+ 3. Efficient Instruction Scheduling Using Finite State Automata: - V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best - article about usage of finite state automata for pipeline hazard - recognizers. - -- The current implementation is different from the 2nd article in the -- following: -+ The current implementation is described in the 1st article and it -+ is different from the 3rd article in the following: - - 1. New operator `|' (alternative) is permitted in functional unit - reservation which can be treated deterministically and -@@ -463,7 +467,10 @@ struct insn_reserv_decl - insn. */ - int insn_num; - /* The following field value is list of bypasses in which given insn -- is output insn. */ -+ is output insn. Bypasses with the same input insn stay one after -+ another in the list in the same order as their occurrences in the -+ description but the bypass without a guard stays always the last -+ in a row of bypasses with the same input insn. */ - struct bypass_decl *bypass_list; - - /* The following fields are defined by automaton generator. */ -@@ -2367,18 +2374,67 @@ add_presence_absence (unit_set_el_t dest - } - - --/* The function searches for bypass with given IN_INSN_RESERV in given -- BYPASS_LIST. */ --static struct bypass_decl * --find_bypass (struct bypass_decl *bypass_list, -- struct insn_reserv_decl *in_insn_reserv) --{ -- struct bypass_decl *bypass; -- -- for (bypass = bypass_list; bypass != NULL; bypass = bypass->next) -- if (bypass->in_insn_reserv == in_insn_reserv) -- break; -- return bypass; -+/* The function inserts BYPASS in the list of bypasses of the -+ corresponding output insn. The order of bypasses in the list is -+ decribed in a comment for member `bypass_list' (see above). If -+ there is already the same bypass in the list the function reports -+ this and does nothing. */ -+static void -+insert_bypass (struct bypass_decl *bypass) -+{ -+ struct bypass_decl *curr, *last; -+ struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv; -+ struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv; -+ -+ for (curr = out_insn_reserv->bypass_list, last = NULL; -+ curr != NULL; -+ last = curr, curr = curr->next) -+ if (curr->in_insn_reserv == in_insn_reserv) -+ { -+ if ((bypass->bypass_guard_name != NULL -+ && curr->bypass_guard_name != NULL -+ && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name)) -+ || bypass->bypass_guard_name == curr->bypass_guard_name) -+ { -+ if (bypass->bypass_guard_name == NULL) -+ { -+ if (!w_flag) -+ error ("the same bypass `%s - %s' is already defined", -+ bypass->out_insn_name, bypass->in_insn_name); -+ else -+ warning (0, "the same bypass `%s - %s' is already defined", -+ bypass->out_insn_name, bypass->in_insn_name); -+ } -+ else if (!w_flag) -+ error ("the same bypass `%s - %s' (guard %s) is already defined", -+ bypass->out_insn_name, bypass->in_insn_name, -+ bypass->bypass_guard_name); -+ else -+ warning -+ (0, "the same bypass `%s - %s' (guard %s) is already defined", -+ bypass->out_insn_name, bypass->in_insn_name, -+ bypass->bypass_guard_name); -+ return; -+ } -+ if (curr->bypass_guard_name == NULL) -+ break; -+ if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv) -+ { -+ last = curr; -+ break; -+ } -+ -+ } -+ if (last == NULL) -+ { -+ bypass->next = out_insn_reserv->bypass_list; -+ out_insn_reserv->bypass_list = bypass; -+ } -+ else -+ { -+ bypass->next = last->next; -+ last->next = bypass; -+ } - } - - /* The function processes pipeline description declarations, checks -@@ -2391,7 +2447,6 @@ process_decls (void) - decl_t decl_in_table; - decl_t out_insn_reserv; - decl_t in_insn_reserv; -- struct bypass_decl *bypass; - int automaton_presence; - int i; - -@@ -2514,36 +2569,7 @@ process_decls (void) - = DECL_INSN_RESERV (out_insn_reserv); - DECL_BYPASS (decl)->in_insn_reserv - = DECL_INSN_RESERV (in_insn_reserv); -- bypass -- = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list, -- DECL_BYPASS (decl)->in_insn_reserv); -- if (bypass != NULL) -- { -- if (DECL_BYPASS (decl)->latency == bypass->latency) -- { -- if (!w_flag) -- error -- ("the same bypass `%s - %s' is already defined", -- DECL_BYPASS (decl)->out_insn_name, -- DECL_BYPASS (decl)->in_insn_name); -- else -- warning -- (0, "the same bypass `%s - %s' is already defined", -- DECL_BYPASS (decl)->out_insn_name, -- DECL_BYPASS (decl)->in_insn_name); -- } -- else -- error ("bypass `%s - %s' is already defined", -- DECL_BYPASS (decl)->out_insn_name, -- DECL_BYPASS (decl)->in_insn_name); -- } -- else -- { -- DECL_BYPASS (decl)->next -- = DECL_INSN_RESERV (out_insn_reserv)->bypass_list; -- DECL_INSN_RESERV (out_insn_reserv)->bypass_list -- = DECL_BYPASS (decl); -- } -+ insert_bypass (DECL_BYPASS (decl)); - } - } - } -@@ -8159,19 +8185,32 @@ output_internal_insn_latency_func (void) - (advance_cycle_insn_decl)->insn_num)); - fprintf (output_file, " case %d:\n", - bypass->in_insn_reserv->insn_num); -- if (bypass->bypass_guard_name == NULL) -- fprintf (output_file, " return %d;\n", -- bypass->latency); -- else -+ for (;;) - { -- fprintf (output_file, -- " if (%s (%s, %s))\n", -- bypass->bypass_guard_name, INSN_PARAMETER_NAME, -- INSN2_PARAMETER_NAME); -- fprintf (output_file, -- " return %d;\n break;\n", -- bypass->latency); -+ if (bypass->bypass_guard_name == NULL) -+ { -+ gcc_assert (bypass->next == NULL -+ || (bypass->in_insn_reserv -+ != bypass->next->in_insn_reserv)); -+ fprintf (output_file, " return %d;\n", -+ bypass->latency); -+ } -+ else -+ { -+ fprintf (output_file, -+ " if (%s (%s, %s))\n", -+ bypass->bypass_guard_name, INSN_PARAMETER_NAME, -+ INSN2_PARAMETER_NAME); -+ fprintf (output_file, " return %d;\n", -+ bypass->latency); -+ } -+ if (bypass->next == NULL -+ || bypass->in_insn_reserv != bypass->next->in_insn_reserv) -+ break; -+ bypass = bypass->next; - } -+ if (bypass->bypass_guard_name != NULL) -+ fprintf (output_file, " break;\n"); - } - fputs (" }\n break;\n", output_file); - } ---- gcc/rtl.def (.../trunk) (revision 144460) -+++ gcc/rtl.def (.../branches/ix86/atom) (revision 144601) -@@ -1088,7 +1088,11 @@ DEF_RTL_EXPR(FINAL_ABSENCE_SET, "final_a - guard for the bypass. The function will get the two insns as - parameters. If the function returns zero the bypass will be - ignored for this case. Additional guard is necessary to recognize -- complicated bypasses, e.g. when consumer is load address. */ -+ complicated bypasses, e.g. when consumer is load address. If there -+ are more one bypass with the same output and input insns, the -+ chosen bypass is the first bypass with a guard in description whose -+ guard function returns nonzero. If there is no such bypass, then -+ bypass without the guard function is chosen. */ - DEF_RTL_EXPR(DEFINE_BYPASS, "define_bypass", "issS", RTX_EXTRA) - - /* (define_automaton string) describes names of automata generated and ---- gcc/rtl.h (.../trunk) (revision 144460) -+++ gcc/rtl.h (.../branches/ix86/atom) (revision 144601) -@@ -1731,6 +1731,8 @@ extern rtx get_related_value (const_rtx) - extern bool offset_within_block_p (const_rtx, HOST_WIDE_INT); - extern void split_const (rtx, rtx *, rtx *); - extern int reg_mentioned_p (const_rtx, const_rtx); -+extern bool reg_mentioned_by_mem_p (const_rtx, const_rtx); -+extern bool reg_dep_by_addr_p (const_rtx, const_rtx); - extern int count_occurrences (const_rtx, const_rtx, int); - extern int reg_referenced_p (const_rtx, const_rtx); - extern int reg_used_between_p (const_rtx, const_rtx, const_rtx); ---- gcc/config.gcc (.../trunk) (revision 144460) -+++ gcc/config.gcc (.../branches/ix86/atom) (revision 144601) -@@ -1087,7 +1087,7 @@ i[34567]86-*-linux* | i[34567]86-*-kfree - tmake_file="${tmake_file} i386/t-linux64" - need_64bit_hwint=yes - case X"${with_cpu}" in -- Xgeneric|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) -+ Xgeneric|Xatom|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) - ;; - X) - if test x$with_cpu_64 = x; then -@@ -1096,7 +1096,7 @@ i[34567]86-*-linux* | i[34567]86-*-kfree - ;; - *) - echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2 -- echo "generic core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2 -+ echo "generic atom core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2 - exit 1 - ;; - esac -@@ -1201,7 +1201,7 @@ i[34567]86-*-solaris2*) - # libgcc/configure.ac instead. - need_64bit_hwint=yes - case X"${with_cpu}" in -- Xgeneric|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) -+ Xgeneric|Xatom|Xcore2|Xnocona|Xx86-64|Xamdfam10|Xbarcelona|Xk8|Xopteron|Xathlon64|Xathlon-fx) - ;; - X) - if test x$with_cpu_64 = x; then -@@ -1210,7 +1210,7 @@ i[34567]86-*-solaris2*) - ;; - *) - echo "Unsupported CPU used in --with-cpu=$with_cpu, supported values:" 1>&2 -- echo "generic core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2 -+ echo "generic atom core2 nocona x86-64 amdfam10 barcelona k8 opteron athlon64 athlon-fx" 1>&2 - exit 1 - ;; - esac -@@ -2803,7 +2803,7 @@ case "${target}" in - esac - # OK - ;; -- "" | amdfam10 | barcelona | k8 | opteron | athlon64 | athlon-fx | nocona | core2 | generic) -+ "" | amdfam10 | barcelona | k8 | opteron | athlon64 | athlon-fx | nocona | core2 | atom | generic) - # OK - ;; - *) ---- gcc/config/i386/i386.h (.../trunk) (revision 144460) -+++ gcc/config/i386/i386.h (.../branches/ix86/atom) (revision 144601) -@@ -231,6 +231,7 @@ extern const struct processor_costs ix86 - #define TARGET_GENERIC64 (ix86_tune == PROCESSOR_GENERIC64) - #define TARGET_GENERIC (TARGET_GENERIC32 || TARGET_GENERIC64) - #define TARGET_AMDFAM10 (ix86_tune == PROCESSOR_AMDFAM10) -+#define TARGET_ATOM (ix86_tune == PROCESSOR_ATOM) - - /* Feature tests against the various tunings. */ - enum ix86_tune_indices { -@@ -295,6 +296,7 @@ enum ix86_tune_indices { - X86_TUNE_USE_VECTOR_FP_CONVERTS, - X86_TUNE_USE_VECTOR_CONVERTS, - X86_TUNE_FUSE_CMP_AND_BRANCH, -+ X86_TUNE_OPT_AGU, - - X86_TUNE_LAST - }; -@@ -382,6 +384,7 @@ extern unsigned char ix86_tune_features[ - ix86_tune_features[X86_TUNE_USE_VECTOR_CONVERTS] - #define TARGET_FUSE_CMP_AND_BRANCH \ - ix86_tune_features[X86_TUNE_FUSE_CMP_AND_BRANCH] -+#define TARGET_OPT_AGU ix86_tune_features[X86_TUNE_OPT_AGU] - - /* Feature tests against the various architecture variations. */ - enum ix86_arch_indices { -@@ -564,6 +567,7 @@ enum target_cpu_default - TARGET_CPU_DEFAULT_prescott, - TARGET_CPU_DEFAULT_nocona, - TARGET_CPU_DEFAULT_core2, -+ TARGET_CPU_DEFAULT_atom, - - TARGET_CPU_DEFAULT_geode, - TARGET_CPU_DEFAULT_k6, -@@ -2256,6 +2260,7 @@ enum processor_type - PROCESSOR_GENERIC32, - PROCESSOR_GENERIC64, - PROCESSOR_AMDFAM10, -+ PROCESSOR_ATOM, - PROCESSOR_max - }; - ---- gcc/config/i386/i386.md (.../trunk) (revision 144460) -+++ gcc/config/i386/i386.md (.../branches/ix86/atom) (revision 144601) -@@ -298,7 +298,7 @@ (define_constants - - - ;; Processor type. --(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2, -+(define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,atom, - generic64,amdfam10" - (const (symbol_ref "ix86_schedule"))) - -@@ -594,6 +594,12 @@ (define_attr "fp_int_src" "false,true" - (define_attr "i387_cw" "trunc,floor,ceil,mask_pm,uninitialized,any" - (const_string "any")) - -+;; Define attribute to classify add/sub insns that consumes carry flag (CF) -+(define_attr "use_carry" "0,1" (const_string "0")) -+ -+;; Define attribute to indicate unaligned ssemov insns -+(define_attr "movu" "0,1" (const_string "0")) -+ - ;; Describe a user's asm statement. - (define_asm_attributes - [(set_attr "length" "128") -@@ -709,6 +715,7 @@ (define_mode_iterator P [(SI "Pmode == S - (include "k6.md") - (include "athlon.md") - (include "geode.md") -+(include "atom.md") - - - ;; Operand and operator predicates and constraints -@@ -5776,6 +5783,7 @@ (define_insn "adddi3_carry_rex64" - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - "adc{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "DI")]) - -@@ -5850,6 +5858,7 @@ (define_insn "addqi3_carry" - "ix86_binary_operator_ok (PLUS, QImode, operands)" - "adc{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "QI")]) - -@@ -5862,6 +5871,7 @@ (define_insn "addhi3_carry" - "ix86_binary_operator_ok (PLUS, HImode, operands)" - "adc{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "HI")]) - -@@ -5874,6 +5884,7 @@ (define_insn "addsi3_carry" - "ix86_binary_operator_ok (PLUS, SImode, operands)" - "adc{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - -@@ -5887,6 +5898,7 @@ (define_insn "*addsi3_carry_zext" - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" - "adc{l}\t{%2, %k0|%k0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - -@@ -6116,9 +6128,9 @@ (define_insn_and_split "*lea_general_3_z - (set_attr "mode" "SI")]) - - (define_insn "*adddi_1_rex64" -- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r") -- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r") -- (match_operand:DI 2 "x86_64_general_operand" "rme,re,le"))) -+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r") -+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r,r") -+ (match_operand:DI 2 "x86_64_general_operand" "rme,re,0,le"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)" - { -@@ -6139,6 +6151,10 @@ (define_insn "*adddi_1_rex64" - } - - default: -+ /* Use add as much as possible to replace lea for AGU optimization. */ -+ if (which_alternative == 2 && TARGET_OPT_AGU) -+ return "add{q}\t{%1, %0|%0, %1}"; -+ - gcc_assert (rtx_equal_p (operands[0], operands[1])); - - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. -@@ -6157,8 +6173,11 @@ (define_insn "*adddi_1_rex64" - } - } - [(set (attr "type") -- (cond [(eq_attr "alternative" "2") -+ (cond [(and (eq_attr "alternative" "2") -+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) - (const_string "lea") -+ (eq_attr "alternative" "3") -+ (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. - (match_operand:DI 2 "pic_symbolic_operand" "") -@@ -6175,8 +6194,8 @@ (define_split - (plus:DI (match_operand:DI 1 "register_operand" "") - (match_operand:DI 2 "x86_64_nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] -- "TARGET_64BIT && reload_completed -- && true_regnum (operands[0]) != true_regnum (operands[1])" -+ "TARGET_64BIT && reload_completed -+ && ix86_lea_for_add_ok (PLUS, insn, operands)" - [(set (match_dup 0) - (plus:DI (match_dup 1) - (match_dup 2)))] -@@ -6380,9 +6399,9 @@ (define_insn "*adddi_5_rex64" - - - (define_insn "*addsi_1" -- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") -- (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") -- (match_operand:SI 2 "general_operand" "g,ri,li"))) -+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r,r") -+ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r,r") -+ (match_operand:SI 2 "general_operand" "g,ri,0,li"))) - (clobber (reg:CC FLAGS_REG))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" - { -@@ -6403,6 +6422,10 @@ (define_insn "*addsi_1" - } - - default: -+ /* Use add as much as possible to replace lea for AGU optimization. */ -+ if (which_alternative == 2 && TARGET_OPT_AGU) -+ return "add{l}\t{%1, %0|%0, %1}"; -+ - gcc_assert (rtx_equal_p (operands[0], operands[1])); - - /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'. -@@ -6419,7 +6442,10 @@ (define_insn "*addsi_1" - } - } - [(set (attr "type") -- (cond [(eq_attr "alternative" "2") -+ (cond [(and (eq_attr "alternative" "2") -+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) -+ (const_string "lea") -+ (eq_attr "alternative" "3") - (const_string "lea") - ; Current assemblers are broken and do not allow @GOTOFF in - ; ought but a memory context. -@@ -6437,8 +6463,7 @@ (define_split - (plus (match_operand 1 "register_operand" "") - (match_operand 2 "nonmemory_operand" ""))) - (clobber (reg:CC FLAGS_REG))] -- "reload_completed -- && true_regnum (operands[0]) != true_regnum (operands[1])" -+ "reload_completed && ix86_lea_for_add_ok (PLUS, insn, operands)" - [(const_int 0)] - { - rtx pat; -@@ -7539,6 +7564,7 @@ (define_insn "subdi3_carry_rex64" - "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)" - "sbb{q}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "DI")]) - -@@ -7587,6 +7613,7 @@ (define_insn "subqi3_carry" - "ix86_binary_operator_ok (MINUS, QImode, operands)" - "sbb{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "QI")]) - -@@ -7599,6 +7626,7 @@ (define_insn "subhi3_carry" - "ix86_binary_operator_ok (MINUS, HImode, operands)" - "sbb{w}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "HI")]) - -@@ -7611,6 +7639,7 @@ (define_insn "subsi3_carry" - "ix86_binary_operator_ok (MINUS, SImode, operands)" - "sbb{l}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "mode" "SI")]) - -@@ -15224,6 +15253,7 @@ (define_insn "return_internal" - "reload_completed" - "ret" - [(set_attr "length" "1") -+ (set_attr "atom_unit" "jeu") - (set_attr "length_immediate" "0") - (set_attr "modrm" "0")]) - -@@ -15236,6 +15266,7 @@ (define_insn "return_internal_long" - "reload_completed" - "rep\;ret" - [(set_attr "length" "1") -+ (set_attr "atom_unit" "jeu") - (set_attr "length_immediate" "0") - (set_attr "prefix_rep" "1") - (set_attr "modrm" "0")]) -@@ -15246,6 +15277,7 @@ (define_insn "return_pop_internal" - "reload_completed" - "ret\t%0" - [(set_attr "length" "3") -+ (set_attr "atom_unit" "jeu") - (set_attr "length_immediate" "2") - (set_attr "modrm" "0")]) - -@@ -16367,6 +16399,7 @@ (define_insn "*rcpsf2_sse" - "TARGET_SSE_MATH" - "%vrcpss\t{%1, %d0|%d0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "rcp") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "SF")]) - -@@ -16718,6 +16751,7 @@ (define_insn "*rsqrtsf2_sse" - "TARGET_SSE_MATH" - "%vrsqrtss\t{%1, %d0|%d0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "rcp") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "SF")]) - -@@ -16738,6 +16772,7 @@ (define_insn "*sqrt2_sse" - "SSE_FLOAT_MODE_P (mode) && TARGET_SSE_MATH" - "%vsqrts\t{%1, %d0|%d0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "sqrt") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "") - (set_attr "athlon_decode" "*") -@@ -19791,6 +19826,7 @@ (define_insn "x86_movdicc_0_m1_rex64" - ; Since we don't have the proper number of operands for an alu insn, - ; fill in all the blanks. - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") -@@ -19806,6 +19842,7 @@ (define_insn "*x86_movdicc_0_m1_se" - "" - "sbb{q}\t%0, %0" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") -@@ -19849,6 +19886,7 @@ (define_insn "x86_movsicc_0_m1" - ; Since we don't have the proper number of operands for an alu insn, - ; fill in all the blanks. - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") -@@ -19864,6 +19902,7 @@ (define_insn "*x86_movsicc_0_m1_se" - "" - "sbb{l}\t%0, %0" - [(set_attr "type" "alu") -+ (set_attr "use_carry" "1") - (set_attr "pent_pair" "pu") - (set_attr "memory" "none") - (set_attr "imm_disp" "false") -@@ -20196,7 +20235,8 @@ (define_insn "pro_epilogue_adjust_stack_ - } - } - [(set (attr "type") -- (cond [(eq_attr "alternative" "0") -+ (cond [(and (eq_attr "alternative" "0") -+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) - (const_string "alu") - (match_operand:SI 2 "const0_operand" "") - (const_string "imov") -@@ -20239,7 +20279,8 @@ (define_insn "pro_epilogue_adjust_stack_ - } - } - [(set (attr "type") -- (cond [(eq_attr "alternative" "0") -+ (cond [(and (eq_attr "alternative" "0") -+ (eq (symbol_ref "TARGET_OPT_AGU") (const_int 0))) - (const_string "alu") - (match_operand:DI 2 "const0_operand" "") - (const_string "imov") -@@ -21731,6 +21772,7 @@ (define_insn "*prefetch_sse" - return patterns[locality]; - } - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "prefetch") - (set_attr "memory" "none")]) - - (define_insn "*prefetch_sse_rex" -@@ -21749,6 +21791,7 @@ (define_insn "*prefetch_sse_rex" - return patterns[locality]; - } - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "prefetch") - (set_attr "memory" "none")]) - - (define_insn "*prefetch_3dnow" ---- gcc/config/i386/atom.md (.../trunk) (revision 0) -+++ gcc/config/i386/atom.md (.../branches/ix86/atom) (revision 144601) -@@ -0,0 +1,796 @@ -+;; Atom Scheduling -+;; Copyright (C) 2009 Free Software Foundation, Inc. -+;; -+;; This file is part of GCC. -+;; -+;; 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 option) -+;; any later version. -+;; -+;; GCC is distributed in the hope that it will be useful, -+;; but WITHOUT ANY WARRANTY; without even the implied warranty of -+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+;; GNU General Public 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. */ -+;; -+;; Atom is an in-order core with two integer pipelines. -+ -+ -+(define_attr "atom_unit" "sishuf,simul,jeu,complex,other" -+ (const_string "other")) -+ -+(define_attr "atom_sse_attr" "rcp,movdup,lfence,fence,prefetch,sqrt,mxcsr,other" -+ (const_string "other")) -+ -+(define_automaton "atom") -+ -+;; Atom has two ports: port 0 and port 1 connecting to all execution units -+(define_cpu_unit "atom-port-0,atom-port-1" "atom") -+ -+;; EU: Execution Unit -+;; Atom EUs are connected by port 0 or port 1. -+ -+(define_cpu_unit "atom-eu-0, atom-eu-1, -+ atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4" -+ "atom") -+ -+;; Some EUs have duplicated copied and can be accessed via either -+;; port 0 or port 1 -+;; (define_reservation "atom-port-either" "(atom-port-0 | atom-port-1)") -+ -+;;; Some instructions is dual-pipe execution, need both ports -+;;; Complex multi-op macro-instructoins need both ports and all EUs -+(define_reservation "atom-port-dual" "(atom-port-0 + atom-port-1)") -+(define_reservation "atom-all-eu" "(atom-eu-0 + atom-eu-1 + -+ atom-imul-1 + atom-imul-2 + atom-imul-3 + -+ atom-imul-4)") -+ -+;;; Most of simple instructions have 1 cycle latency. Some of them -+;;; issue in port 0, some in port 0 and some in either port. -+(define_reservation "atom-simple-0" "(atom-port-0 + atom-eu-0)") -+(define_reservation "atom-simple-1" "(atom-port-1 + atom-eu-1)") -+(define_reservation "atom-simple-either" "(atom-simple-0 | atom-simple-1)") -+ -+;;; Some insn issues in port 0 with 3 cycle latency and 1 cycle tput -+(define_reservation "atom-eu-0-3-1" "(atom-port-0 + atom-eu-0, nothing*2)") -+ -+;;; fmul insn can have 4 or 5 cycles latency -+(define_reservation "atom-fmul-5c" "(atom-port-0 + atom-eu-0), nothing*4") -+(define_reservation "atom-fmul-4c" "(atom-port-0 + atom-eu-0), nothing*3") -+ -+;;; fadd can has 5 cycles latency depends on instruction forms -+(define_reservation "atom-fadd-5c" "(atom-port-1 + atom-eu-1), nothing*5") -+ -+;;; imul insn has 5 cycles latency -+(define_reservation "atom-imul-32" -+ "atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4, -+ atom-port-0") -+;;; imul instruction excludes other non-FP instructions. -+(exclusion_set "atom-eu-0, atom-eu-1" -+ "atom-imul-1, atom-imul-2, atom-imul-3, atom-imul-4") -+ -+;;; dual-execution instructions can have 1,2,4,5 cycles latency depends on -+;;; instruction forms -+(define_reservation "atom-dual-1c" "(atom-port-dual + atom-eu-0 + atom-eu-1)") -+(define_reservation "atom-dual-2c" -+ "(atom-port-dual + atom-eu-0 + atom-eu-1, nothing)") -+(define_reservation "atom-dual-5c" -+ "(atom-port-dual + atom-eu-0 + atom-eu-1, nothing*4)") -+ -+;;; Complex macro-instruction has variants of latency, and uses both ports. -+(define_reservation "atom-complex" "(atom-port-dual + atom-all-eu)") -+ -+(define_insn_reservation "atom_other" 9 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "other") -+ (eq_attr "atom_unit" "!jeu"))) -+ "atom-complex, atom-all-eu*8") -+ -+;; return has type "other" with atom_unit "jeu" -+(define_insn_reservation "atom_other_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "other") -+ (eq_attr "atom_unit" "jeu"))) -+ "atom-dual-1c") -+ -+(define_insn_reservation "atom_multi" 9 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "multi")) -+ "atom-complex, atom-all-eu*8") -+ -+;; Normal alu insns without carry -+(define_insn_reservation "atom_alu" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu") -+ (and (eq_attr "memory" "none") -+ (eq_attr "use_carry" "0")))) -+ "atom-simple-either") -+ -+;; Normal alu insns without carry -+(define_insn_reservation "atom_alu_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu") -+ (and (eq_attr "memory" "!none") -+ (eq_attr "use_carry" "0")))) -+ "atom-simple-either") -+ -+;; Alu insn consuming CF, such as add/sbb -+(define_insn_reservation "atom_alu_carry" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu") -+ (and (eq_attr "memory" "none") -+ (eq_attr "use_carry" "1")))) -+ "atom-simple-either") -+ -+;; Alu insn consuming CF, such as add/sbb -+(define_insn_reservation "atom_alu_carry_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu") -+ (and (eq_attr "memory" "!none") -+ (eq_attr "use_carry" "1")))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_alu1" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu1") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_alu1_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "alu1") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_negnot" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "negnot") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_negnot_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "negnot") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_imov" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imov") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_imov_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imov") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+;; 16<-16, 32<-32 -+(define_insn_reservation "atom_imovx" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (eq_attr "memory" "none") -+ (ior (and (match_operand:HI 0 "register_operand") -+ (match_operand:HI 1 "general_operand")) -+ (and (match_operand:SI 0 "register_operand") -+ (match_operand:SI 1 "general_operand")))))) -+ "atom-simple-either") -+ -+;; 16<-16, 32<-32, mem -+(define_insn_reservation "atom_imovx_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (eq_attr "memory" "!none") -+ (ior (and (match_operand:HI 0 "register_operand") -+ (match_operand:HI 1 "general_operand")) -+ (and (match_operand:SI 0 "register_operand") -+ (match_operand:SI 1 "general_operand")))))) -+ "atom-simple-either") -+ -+;; 32<-16, 32<-8, 64<-16, 64<-8, 64<-32, 8<-8 -+(define_insn_reservation "atom_imovx_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (eq_attr "memory" "none") -+ (ior (match_operand:QI 0 "register_operand") -+ (ior (and (match_operand:SI 0 "register_operand") -+ (not (match_operand:SI 1 "general_operand"))) -+ (match_operand:DI 0 "register_operand")))))) -+ "atom-simple-0") -+ -+;; 32<-16, 32<-8, 64<-16, 64<-8, 64<-32, 8<-8, mem -+(define_insn_reservation "atom_imovx_2_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (eq_attr "memory" "!none") -+ (ior (match_operand:QI 0 "register_operand") -+ (ior (and (match_operand:SI 0 "register_operand") -+ (not (match_operand:SI 1 "general_operand"))) -+ (match_operand:DI 0 "register_operand")))))) -+ "atom-simple-0") -+ -+;; 16<-8 -+(define_insn_reservation "atom_imovx_3" 3 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imovx") -+ (and (match_operand:HI 0 "register_operand") -+ (match_operand:QI 1 "general_operand")))) -+ "atom-complex, atom-all-eu*2") -+ -+(define_insn_reservation "atom_lea" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "lea") -+ (eq_attr "mode" "!HI"))) -+ "atom-simple-either") -+ -+;; lea 16bit address is complex insn -+(define_insn_reservation "atom_lea_2" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "lea") -+ (eq_attr "mode" "HI"))) -+ "atom-complex, atom-all-eu") -+ -+(define_insn_reservation "atom_incdec" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "incdec") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_incdec_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "incdec") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+;; simple shift instruction use SHIFT eu, none memory -+(define_insn_reservation "atom_ishift" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift") -+ (and (eq_attr "memory" "none") (eq_attr "prefix_0f" "0")))) -+ "atom-simple-0") -+ -+;; simple shift instruction use SHIFT eu, memory -+(define_insn_reservation "atom_ishift_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift") -+ (and (eq_attr "memory" "!none") (eq_attr "prefix_0f" "0")))) -+ "atom-simple-0") -+ -+;; DF shift (prefixed with 0f) is complex insn with latency of 7 cycles -+(define_insn_reservation "atom_ishift_3" 7 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift") -+ (eq_attr "prefix_0f" "1"))) -+ "atom-complex, atom-all-eu*6") -+ -+(define_insn_reservation "atom_ishift1" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift1") -+ (eq_attr "memory" "none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_ishift1_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ishift1") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_rotate" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "rotate") -+ (eq_attr "memory" "none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_rotate_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "rotate") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_rotate1" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "rotate1") -+ (eq_attr "memory" "none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_rotate1_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "rotate1") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_imul" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imul") -+ (and (eq_attr "memory" "none") (eq_attr "mode" "SI")))) -+ "atom-imul-32") -+ -+(define_insn_reservation "atom_imul_mem" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imul") -+ (and (eq_attr "memory" "!none") (eq_attr "mode" "SI")))) -+ "atom-imul-32") -+ -+;; latency set to 10 as common 64x64 imul -+(define_insn_reservation "atom_imul_3" 10 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "imul") -+ (eq_attr "mode" "!SI"))) -+ "atom-complex, atom-all-eu*9") -+ -+(define_insn_reservation "atom_idiv" 65 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "idiv")) -+ "atom-complex, atom-all-eu*32, nothing*32") -+ -+(define_insn_reservation "atom_icmp" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "icmp") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_icmp_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "icmp") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_test" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "test") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_test_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "test") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_ibr" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ibr") -+ (eq_attr "memory" "!load"))) -+ "atom-simple-1") -+ -+;; complex if jump target is from address -+(define_insn_reservation "atom_ibr_2" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ibr") -+ (eq_attr "memory" "load"))) -+ "atom-complex, atom-all-eu") -+ -+(define_insn_reservation "atom_setcc" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "setcc") -+ (eq_attr "memory" "!store"))) -+ "atom-simple-either") -+ -+;; 2 cycles complex if target is in memory -+(define_insn_reservation "atom_setcc_2" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "setcc") -+ (eq_attr "memory" "store"))) -+ "atom-complex, atom-all-eu") -+ -+(define_insn_reservation "atom_icmov" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "icmov") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_icmov_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "icmov") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+;; UCODE if segreg, ignored -+(define_insn_reservation "atom_push" 2 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "push")) -+ "atom-dual-2c") -+ -+;; pop r64 is 1 cycle. UCODE if segreg, ignored -+(define_insn_reservation "atom_pop" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "pop") -+ (eq_attr "mode" "DI"))) -+ "atom-dual-1c") -+ -+;; pop non-r64 is 2 cycles. UCODE if segreg, ignored -+(define_insn_reservation "atom_pop_2" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "pop") -+ (eq_attr "mode" "!DI"))) -+ "atom-dual-2c") -+ -+;; UCODE if segreg, ignored -+(define_insn_reservation "atom_call" 1 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "call")) -+ "atom-dual-1c") -+ -+(define_insn_reservation "atom_callv" 1 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "callv")) -+ "atom-dual-1c") -+ -+(define_insn_reservation "atom_leave" 3 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "leave")) -+ "atom-complex, atom-all-eu*2") -+ -+(define_insn_reservation "atom_str" 3 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "str")) -+ "atom-complex, atom-all-eu*2") -+ -+(define_insn_reservation "atom_sselog" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sselog") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_sselog_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sselog") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_sselog1" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sselog1") -+ (eq_attr "memory" "none"))) -+ "atom-simple-0") -+ -+(define_insn_reservation "atom_sselog1_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sselog1") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-0") -+ -+;; not pmad, not psad -+(define_insn_reservation "atom_sseiadd" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseiadd") -+ (and (not (match_operand:V2DI 0 "register_operand")) -+ (and (eq_attr "atom_unit" "!simul") -+ (eq_attr "atom_unit" "!complex"))))) -+ "atom-simple-either") -+ -+;; pmad, psad and 64 -+(define_insn_reservation "atom_sseiadd_2" 4 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseiadd") -+ (and (not (match_operand:V2DI 0 "register_operand")) -+ (and (eq_attr "atom_unit" "simul" ) -+ (eq_attr "mode" "DI"))))) -+ "atom-fmul-4c") -+ -+;; pmad, psad and 128 -+(define_insn_reservation "atom_sseiadd_3" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseiadd") -+ (and (not (match_operand:V2DI 0 "register_operand")) -+ (and (eq_attr "atom_unit" "simul" ) -+ (eq_attr "mode" "TI"))))) -+ "atom-fmul-5c") -+ -+;; if paddq(64 bit op), phadd/phsub -+(define_insn_reservation "atom_sseiadd_4" 6 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseiadd") -+ (ior (match_operand:V2DI 0 "register_operand") -+ (eq_attr "atom_unit" "complex")))) -+ "atom-complex, atom-all-eu*5") -+ -+;; if immediate op. -+(define_insn_reservation "atom_sseishft" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseishft") -+ (and (eq_attr "atom_unit" "!sishuf") -+ (match_operand 2 "immediate_operand")))) -+ "atom-simple-either") -+ -+;; if palignr or psrldq -+(define_insn_reservation "atom_sseishft_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseishft") -+ (and (eq_attr "atom_unit" "sishuf") -+ (match_operand 2 "immediate_operand")))) -+ "atom-simple-0") -+ -+;; if reg/mem op -+(define_insn_reservation "atom_sseishft_3" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseishft") -+ (not (match_operand 2 "immediate_operand")))) -+ "atom-complex, atom-all-eu") -+ -+(define_insn_reservation "atom_sseimul" 1 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "sseimul")) -+ "atom-simple-0") -+ -+;; rcpss or rsqrtss -+(define_insn_reservation "atom_sse" 4 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (and (eq_attr "atom_sse_attr" "rcp") (eq_attr "mode" "SF")))) -+ "atom-fmul-4c") -+ -+;; movshdup, movsldup. Suggest to type sseishft -+(define_insn_reservation "atom_sse_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (eq_attr "atom_sse_attr" "movdup"))) -+ "atom-simple-0") -+ -+;; lfence -+(define_insn_reservation "atom_sse_3" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (eq_attr "atom_sse_attr" "lfence"))) -+ "atom-simple-either") -+ -+;; sfence,clflush,mfence, prefetch -+(define_insn_reservation "atom_sse_4" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (ior (eq_attr "atom_sse_attr" "fence") -+ (eq_attr "atom_sse_attr" "prefetch")))) -+ "atom-simple-0") -+ -+;; rcpps, rsqrtss, sqrt, ldmxcsr -+(define_insn_reservation "atom_sse_5" 7 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sse") -+ (ior (ior (eq_attr "atom_sse_attr" "sqrt") -+ (eq_attr "atom_sse_attr" "mxcsr")) -+ (and (eq_attr "atom_sse_attr" "rcp") -+ (eq_attr "mode" "V4SF"))))) -+ "atom-complex, atom-all-eu*6") -+ -+;; xmm->xmm -+(define_insn_reservation "atom_ssemov" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (and (match_operand 0 "register_operand" "xy") (match_operand 1 "register_operand" "xy")))) -+ "atom-simple-either") -+ -+;; reg->xmm -+(define_insn_reservation "atom_ssemov_2" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (and (match_operand 0 "register_operand" "xy") (match_operand 1 "register_operand" "r")))) -+ "atom-simple-0") -+ -+;; xmm->reg -+(define_insn_reservation "atom_ssemov_3" 3 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (and (match_operand 0 "register_operand" "r") (match_operand 1 "register_operand" "xy")))) -+ "atom-eu-0-3-1") -+ -+;; mov mem -+(define_insn_reservation "atom_ssemov_4" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (and (eq_attr "movu" "0") (eq_attr "memory" "!none")))) -+ "atom-simple-0") -+ -+;; movu mem -+(define_insn_reservation "atom_ssemov_5" 2 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemov") -+ (ior (eq_attr "movu" "1") (eq_attr "memory" "!none")))) -+ "atom-complex, atom-all-eu") -+ -+;; no memory simple -+(define_insn_reservation "atom_sseadd" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseadd") -+ (and (eq_attr "memory" "none") -+ (and (eq_attr "mode" "!V2DF") -+ (eq_attr "atom_unit" "!complex"))))) -+ "atom-fadd-5c") -+ -+;; memory simple -+(define_insn_reservation "atom_sseadd_mem" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseadd") -+ (and (eq_attr "memory" "!none") -+ (and (eq_attr "mode" "!V2DF") -+ (eq_attr "atom_unit" "!complex"))))) -+ "atom-dual-5c") -+ -+;; maxps, minps, *pd, hadd, hsub -+(define_insn_reservation "atom_sseadd_3" 8 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseadd") -+ (ior (eq_attr "mode" "V2DF") (eq_attr "atom_unit" "complex")))) -+ "atom-complex, atom-all-eu*7") -+ -+;; Except dppd/dpps -+(define_insn_reservation "atom_ssemul" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemul") -+ (eq_attr "mode" "!SF"))) -+ "atom-fmul-5c") -+ -+;; Except dppd/dpps, 4 cycle if mulss -+(define_insn_reservation "atom_ssemul_2" 4 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssemul") -+ (eq_attr "mode" "SF"))) -+ "atom-fmul-4c") -+ -+(define_insn_reservation "atom_ssecmp" 1 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "ssecmp")) -+ "atom-simple-either") -+ -+(define_insn_reservation "atom_ssecomi" 10 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "ssecomi")) -+ "atom-complex, atom-all-eu*9") -+ -+;; no memory and cvtpi2ps, cvtps2pi, cvttps2pi -+(define_insn_reservation "atom_ssecvt" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssecvt") -+ (ior (and (match_operand:V2SI 0 "register_operand") -+ (match_operand:V4SF 1 "register_operand")) -+ (and (match_operand:V4SF 0 "register_operand") -+ (match_operand:V2SI 1 "register_operand"))))) -+ "atom-fadd-5c") -+ -+;; memory and cvtpi2ps, cvtps2pi, cvttps2pi -+(define_insn_reservation "atom_ssecvt_2" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssecvt") -+ (ior (and (match_operand:V2SI 0 "register_operand") -+ (match_operand:V4SF 1 "memory_operand")) -+ (and (match_operand:V4SF 0 "register_operand") -+ (match_operand:V2SI 1 "memory_operand"))))) -+ "atom-dual-5c") -+ -+;; otherwise. 7 cycles average for cvtss2sd -+(define_insn_reservation "atom_ssecvt_3" 7 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "ssecvt") -+ (not (ior (and (match_operand:V2SI 0 "register_operand") -+ (match_operand:V4SF 1 "nonimmediate_operand")) -+ (and (match_operand:V4SF 0 "register_operand") -+ (match_operand:V2SI 1 "nonimmediate_operand")))))) -+ "atom-complex, atom-all-eu*6") -+ -+;; memory and cvtsi2sd -+(define_insn_reservation "atom_sseicvt" 5 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseicvt") -+ (and (match_operand:V2DF 0 "register_operand") -+ (match_operand:SI 1 "memory_operand")))) -+ "atom-dual-5c") -+ -+;; otherwise. 8 cycles average for cvtsd2si -+(define_insn_reservation "atom_sseicvt_2" 8 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "sseicvt") -+ (not (and (match_operand:V2DF 0 "register_operand") -+ (match_operand:SI 1 "memory_operand"))))) -+ "atom-complex, atom-all-eu*7") -+ -+(define_insn_reservation "atom_ssediv" 62 -+ (and (eq_attr "cpu" "atom") -+ (eq_attr "type" "ssediv")) -+ "atom-complex, atom-all-eu*12, nothing*49") -+ -+;; simple for fmov -+(define_insn_reservation "atom_fmov" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "fmov") -+ (eq_attr "memory" "none"))) -+ "atom-simple-either") -+ -+;; simple for fmov -+(define_insn_reservation "atom_fmov_mem" 1 -+ (and (eq_attr "cpu" "atom") -+ (and (eq_attr "type" "fmov") -+ (eq_attr "memory" "!none"))) -+ "atom-simple-either") -+ -+;; Define bypass here -+ -+;; There will be no stall from lea to non-mem EX insns -+(define_bypass 0 "atom_lea" -+ "atom_alu_carry, -+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx, -+ atom_incdec, atom_setcc, atom_icmov, atom_pop") -+ -+(define_bypass 0 "atom_lea" -+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem" -+ "!ix86_agi_dependent") -+ -+;; There will be 3 cycles stall from EX insns to AGAN insns LEA -+(define_bypass 4 "atom_alu_carry, -+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx, -+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate, -+ atom_rotate1, atom_setcc, atom_icmov, atom_pop, -+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem" -+ "atom_lea") -+ -+;; There will be 3 cycles stall from EX insns to insns need addr calculation -+(define_bypass 4 "atom_alu_carry, -+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx, -+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate, -+ atom_rotate1, atom_setcc, atom_icmov, atom_pop, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem" -+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_negnot_mem, atom_imov_mem, atom_incdec_mem, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_imul_mem, atom_icmp_mem, -+ atom_test_mem, atom_icmov_mem, atom_sselog_mem, -+ atom_sselog1_mem, atom_fmov_mem, atom_sseadd_mem, -+ atom_ishift_mem, atom_ishift1_mem, -+ atom_rotate_mem, atom_rotate1_mem" -+ "ix86_agi_dependent") -+ -+;; Stall from imul to lea is 8 cycles. -+(define_bypass 9 "atom_imul, atom_imul_mem" "atom_lea") -+ -+;; Stall from imul to memory address is 8 cycles. -+(define_bypass 9 "atom_imul, atom_imul_mem" -+ "atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_negnot_mem, atom_imov_mem, atom_incdec_mem, -+ atom_ishift_mem, atom_ishift1_mem, atom_rotate_mem, -+ atom_rotate1_mem, atom_imul_mem, atom_icmp_mem, -+ atom_test_mem, atom_icmov_mem, atom_sselog_mem, -+ atom_sselog1_mem, atom_fmov_mem, atom_sseadd_mem" -+ "ix86_agi_dependent") -+ -+;; There will be 0 cycle stall from cmp/test to jcc -+ -+;; There will be 1 cycle stall from flag producer to cmov and adc/sbb -+(define_bypass 2 "atom_icmp, atom_test, atom_alu, atom_alu_carry, -+ atom_alu1, atom_negnot, atom_incdec, atom_ishift, -+ atom_ishift1, atom_rotate, atom_rotate1" -+ "atom_icmov, atom_alu_carry") -+ -+;; lea to shift count stall is 2 cycles -+(define_bypass 3 "atom_lea" -+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1, -+ atom_ishift_mem, atom_ishift1_mem, -+ atom_rotate_mem, atom_rotate1_mem" -+ "ix86_dep_by_shift_count") -+ -+;; lea to shift source stall is 1 cycle -+(define_bypass 2 "atom_lea" -+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1" -+ "!ix86_dep_by_shift_count") -+ -+;; non-lea to shift count stall is 1 cycle -+(define_bypass 2 "atom_alu_carry, -+ atom_alu,atom_alu1,atom_negnot,atom_imov,atom_imovx, -+ atom_incdec,atom_ishift,atom_ishift1,atom_rotate, -+ atom_rotate1, atom_setcc, atom_icmov, atom_pop, -+ atom_alu_mem, atom_alu_carry_mem, atom_alu1_mem, -+ atom_imovx_mem, atom_imovx_2_mem, -+ atom_imov_mem, atom_icmov_mem, atom_fmov_mem" -+ "atom_ishift, atom_ishift1, atom_rotate, atom_rotate1, -+ atom_ishift_mem, atom_ishift1_mem, -+ atom_rotate_mem, atom_rotate1_mem" -+ "ix86_dep_by_shift_count") ---- gcc/config/i386/sse.md (.../trunk) (revision 144460) -+++ gcc/config/i386/sse.md (.../branches/ix86/atom) (revision 144601) -@@ -338,6 +338,7 @@ (define_insn "avx_movup\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "prefix" "vex") - (set_attr "mode" "")]) - -@@ -363,6 +364,7 @@ (define_insn "_movup\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "mode" "")]) - - (define_insn "avx_movdqu" -@@ -373,6 +375,7 @@ (define_insn "avx_movdqu" - "TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "vmovdqu\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "prefix" "vex") - (set_attr "mode" "")]) - -@@ -383,6 +386,7 @@ (define_insn "sse2_movdqu" - "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))" - "movdqu\t{%1, %0|%0, %1}" - [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - -@@ -424,7 +428,7 @@ (define_insn "sse2_movntv2di" - UNSPEC_MOVNT))] - "TARGET_SSE2" - "movntdq\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - -@@ -434,7 +438,7 @@ (define_insn "sse2_movntsi" - UNSPEC_MOVNT))] - "TARGET_SSE2" - "movnti\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "mode" "V2DF")]) - - (define_insn "avx_lddqu" -@@ -445,6 +449,7 @@ (define_insn "avx_lddqu" - "TARGET_AVX" - "vlddqu\t{%1, %0|%0, %1}" - [(set_attr "type" "ssecvt") -+ (set_attr "movu" "1") - (set_attr "prefix" "vex") - (set_attr "mode" "")]) - -@@ -454,7 +459,8 @@ (define_insn "sse3_lddqu" - UNSPEC_LDDQU))] - "TARGET_SSE3" - "lddqu\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") -+ (set_attr "movu" "1") - (set_attr "prefix_rep" "1") - (set_attr "mode" "TI")]) - -@@ -761,6 +767,7 @@ (define_insn "sse_rcpv4sf2" - "TARGET_SSE" - "%vrcpps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "rcp") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "V4SF")]) - -@@ -787,6 +794,7 @@ (define_insn "sse_vmrcpv4sf2" - "TARGET_SSE" - "rcpss\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "rcp") - (set_attr "mode" "SF")]) - - (define_expand "sqrtv8sf2" -@@ -832,6 +840,7 @@ (define_insn "sse_sqrtv4sf2" - "TARGET_SSE" - "%vsqrtps\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "sqrt") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "V4SF")]) - -@@ -876,6 +885,7 @@ (define_insn "_vmsqrt2" - "SSE_VEC_FLOAT_MODE_P (mode)" - "sqrts\t{%1, %0|%0, %1}" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "sqrt") - (set_attr "mode" "")]) - - (define_expand "rsqrtv8sf2" -@@ -1039,7 +1049,7 @@ (define_insn "_vm3" - (const_int 1)))] - "SSE_VEC_FLOAT_MODE_P (mode)" - "s\t{%2, %0|%0, %2}" -- [(set_attr "type" "sse") -+ [(set_attr "type" "sseadd") - (set_attr "mode" "")]) - - ;; These versions of the min/max patterns implement exactly the operations -@@ -1175,6 +1185,7 @@ (define_insn "sse3_addsubv2df3" - "TARGET_SSE3" - "addsubpd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") -+ (set_attr "atom_unit" "complex") - (set_attr "mode" "V2DF")]) - - (define_insn "avx_hv4df3" -@@ -1298,6 +1309,7 @@ (define_insn "sse3_hv4sf - "TARGET_SSE3" - "hps\t{%2, %0|%0, %2}" - [(set_attr "type" "sseadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_rep" "1") - (set_attr "mode" "V4SF")]) - -@@ -5066,6 +5078,7 @@ (define_insn "*sse2_pmaddwd" - "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)" - "pmaddwd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "simul") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - -@@ -7025,6 +7038,7 @@ (define_insn "*vec_extractv2di_1_rex64" - movq\t{%H1, %0|%0, %H1} - mov{q}\t{%H1, %0|%0, %H1}" - [(set_attr "type" "ssemov,sseishft,ssemov,imov") -+ (set_attr "atom_unit" "*,sishuf,*,*") - (set_attr "memory" "*,none,*,*") - (set_attr "mode" "V2SF,TI,TI,DI")]) - -@@ -7057,6 +7071,7 @@ (define_insn "*vec_extractv2di_1_sse2" - psrldq\t{$8, %0|%0, 8} - movq\t{%H1, %0|%0, %H1}" - [(set_attr "type" "ssemov,sseishft,ssemov") -+ (set_attr "atom_unit" "*,sishuf,*") - (set_attr "memory" "*,none,*") - (set_attr "mode" "V2SF,TI,TI")]) - -@@ -7614,6 +7629,7 @@ (define_insn "sse2_psadbw" - "TARGET_SSE2" - "psadbw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "simul") - (set_attr "prefix_data16" "1") - (set_attr "mode" "TI")]) - -@@ -7635,7 +7651,7 @@ (define_insn "_movmskpmode)" - "%vmovmskp\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "")]) - -@@ -7645,7 +7661,7 @@ (define_insn "sse2_pmovmskb" - UNSPEC_MOVMSK))] - "TARGET_SSE2" - "%vpmovmskb\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_data16" "1") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "SI")]) -@@ -7668,7 +7684,7 @@ (define_insn "*sse2_maskmovdqu" - "TARGET_SSE2 && !TARGET_64BIT" - ;; @@@ check ordering of operands in intel/nonintel syntax - "%vmaskmovdqu\t{%2, %1|%1, %2}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_data16" "1") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "TI")]) -@@ -7682,7 +7698,7 @@ (define_insn "*sse2_maskmovdqu_rex64" - "TARGET_SSE2 && TARGET_64BIT" - ;; @@@ check ordering of operands in intel/nonintel syntax - "%vmaskmovdqu\t{%2, %1|%1, %2}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_data16" "1") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "TI")]) -@@ -7693,6 +7709,7 @@ (define_insn "sse_ldmxcsr" - "TARGET_SSE" - "%vldmxcsr\t%0" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "mxcsr") - (set_attr "prefix" "maybe_vex") - (set_attr "memory" "load")]) - -@@ -7702,6 +7719,7 @@ (define_insn "sse_stmxcsr" - "TARGET_SSE" - "%vstmxcsr\t%0" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "mxcsr") - (set_attr "prefix" "maybe_vex") - (set_attr "memory" "store")]) - -@@ -7720,6 +7738,7 @@ (define_insn "*sse_sfence" - "TARGET_SSE || TARGET_3DNOW_A" - "sfence" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "fence") - (set_attr "memory" "unknown")]) - - (define_insn "sse2_clflush" -@@ -7728,6 +7747,7 @@ (define_insn "sse2_clflush" - "TARGET_SSE2" - "clflush\t%a0" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "fence") - (set_attr "memory" "unknown")]) - - (define_expand "sse2_mfence" -@@ -7745,6 +7765,7 @@ (define_insn "*sse2_mfence" - "TARGET_64BIT || TARGET_SSE2" - "mfence" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "fence") - (set_attr "memory" "unknown")]) - - (define_expand "sse2_lfence" -@@ -7762,6 +7783,7 @@ (define_insn "*sse2_lfence" - "TARGET_SSE2" - "lfence" - [(set_attr "type" "sse") -+ (set_attr "atom_sse_attr" "lfence") - (set_attr "memory" "unknown")]) - - (define_insn "sse3_mwait" -@@ -7885,6 +7907,7 @@ (define_insn "ssse3_phaddwv8hi3" - "TARGET_SSSE3" - "phaddw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -7913,6 +7936,7 @@ (define_insn "ssse3_phaddwv4hi3" - "TARGET_SSSE3" - "phaddw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -7967,6 +7991,7 @@ (define_insn "ssse3_phadddv4si3" - "TARGET_SSSE3" - "phaddd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -7987,6 +8012,7 @@ (define_insn "ssse3_phadddv2si3" - "TARGET_SSSE3" - "phaddd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8073,6 +8099,7 @@ (define_insn "ssse3_phaddswv8hi3" - "TARGET_SSSE3" - "phaddsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8101,6 +8128,7 @@ (define_insn "ssse3_phaddswv4hi3" - "TARGET_SSSE3" - "phaddsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8187,6 +8215,7 @@ (define_insn "ssse3_phsubwv8hi3" - "TARGET_SSSE3" - "phsubw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8215,6 +8244,7 @@ (define_insn "ssse3_phsubwv4hi3" - "TARGET_SSSE3" - "phsubw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8269,6 +8299,7 @@ (define_insn "ssse3_phsubdv4si3" - "TARGET_SSSE3" - "phsubd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8289,6 +8320,7 @@ (define_insn "ssse3_phsubdv2si3" - "TARGET_SSSE3" - "phsubd\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8375,6 +8407,7 @@ (define_insn "ssse3_phsubswv8hi3" - "TARGET_SSSE3" - "phsubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8403,6 +8436,7 @@ (define_insn "ssse3_phsubswv4hi3" - "TARGET_SSSE3" - "phsubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "complex") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8509,6 +8543,7 @@ (define_insn "ssse3_pmaddubsw128" - "TARGET_SSSE3" - "pmaddubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "simul") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8547,6 +8582,7 @@ (define_insn "ssse3_pmaddubsw" - "TARGET_SSSE3" - "pmaddubsw\t{%2, %0|%0, %2}" - [(set_attr "type" "sseiadd") -+ (set_attr "atom_unit" "simul") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8754,6 +8790,7 @@ (define_insn "ssse3_palignrti" - return "palignr\t{%3, %2, %0|%0, %2, %3}"; - } - [(set_attr "type" "sseishft") -+ (set_attr "atom_unit" "sishuf") - (set_attr "prefix_data16" "1") - (set_attr "prefix_extra" "1") - (set_attr "mode" "TI")]) -@@ -8770,6 +8807,7 @@ (define_insn "ssse3_palignrdi" - return "palignr\t{%3, %2, %0|%0, %2, %3}"; - } - [(set_attr "type" "sseishft") -+ (set_attr "atom_unit" "sishuf") - (set_attr "prefix_extra" "1") - (set_attr "mode" "DI")]) - -@@ -8956,7 +8994,7 @@ (define_insn "sse4_1_movntdqa" - UNSPEC_MOVNTDQA))] - "TARGET_SSE4_1" - "%vmovntdqa\t{%1, %0|%0, %1}" -- [(set_attr "type" "ssecvt") -+ [(set_attr "type" "ssemov") - (set_attr "prefix_extra" "1") - (set_attr "prefix" "maybe_vex") - (set_attr "mode" "TI")]) ---- gcc/config/i386/i386-c.c (.../trunk) (revision 144460) -+++ gcc/config/i386/i386-c.c (.../branches/ix86/atom) (revision 144601) -@@ -119,6 +119,10 @@ ix86_target_macros_internal (int isa_fla - def_or_undef (parse_in, "__core2"); - def_or_undef (parse_in, "__core2__"); - break; -+ case PROCESSOR_ATOM: -+ def_or_undef (parse_in, "__atom"); -+ def_or_undef (parse_in, "__atom__"); -+ break; - /* use PROCESSOR_max to not set/unset the arch macro. */ - case PROCESSOR_max: - break; -@@ -187,6 +191,9 @@ ix86_target_macros_internal (int isa_fla - case PROCESSOR_CORE2: - def_or_undef (parse_in, "__tune_core2__"); - break; -+ case PROCESSOR_ATOM: -+ def_or_undef (parse_in, "__tune_atom__"); -+ break; - case PROCESSOR_GENERIC32: - case PROCESSOR_GENERIC64: - break; ---- gcc/config/i386/i386-protos.h (.../trunk) (revision 144460) -+++ gcc/config/i386/i386-protos.h (.../branches/ix86/atom) (revision 144601) -@@ -85,6 +85,9 @@ extern void ix86_fixup_binary_operands_n - extern void ix86_expand_binary_operator (enum rtx_code, - enum machine_mode, rtx[]); - extern int ix86_binary_operator_ok (enum rtx_code, enum machine_mode, rtx[]); -+extern bool ix86_lea_for_add_ok (enum rtx_code, rtx, rtx[]); -+extern bool ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn); -+extern bool ix86_agi_dependent (rtx set_insn, rtx use_insn); - extern void ix86_expand_unary_operator (enum rtx_code, enum machine_mode, - rtx[]); - extern rtx ix86_build_const_vector (enum machine_mode, bool, rtx); ---- gcc/config/i386/i386.c (.../trunk) (revision 144460) -+++ gcc/config/i386/i386.c (.../branches/ix86/atom) (revision 144601) -@@ -1036,6 +1036,79 @@ struct processor_costs core2_cost = { - 1, /* cond_not_taken_branch_cost. */ - }; - -+static const -+struct processor_costs atom_cost = { -+ COSTS_N_INSNS (1), /* cost of an add instruction */ -+ COSTS_N_INSNS (1) + 1, /* cost of a lea instruction */ -+ COSTS_N_INSNS (1), /* variable shift costs */ -+ COSTS_N_INSNS (1), /* constant shift costs */ -+ {COSTS_N_INSNS (3), /* cost of starting multiply for QI */ -+ COSTS_N_INSNS (4), /* HI */ -+ COSTS_N_INSNS (3), /* SI */ -+ COSTS_N_INSNS (4), /* DI */ -+ COSTS_N_INSNS (2)}, /* other */ -+ 0, /* cost of multiply per each bit set */ -+ {COSTS_N_INSNS (18), /* cost of a divide/mod for QI */ -+ COSTS_N_INSNS (26), /* HI */ -+ COSTS_N_INSNS (42), /* SI */ -+ COSTS_N_INSNS (74), /* DI */ -+ COSTS_N_INSNS (74)}, /* other */ -+ COSTS_N_INSNS (1), /* cost of movsx */ -+ COSTS_N_INSNS (1), /* cost of movzx */ -+ 8, /* "large" insn */ -+ 17, /* MOVE_RATIO */ -+ 2, /* cost for loading QImode using movzbl */ -+ {4, 4, 4}, /* cost of loading integer registers -+ in QImode, HImode and SImode. -+ Relative to reg-reg move (2). */ -+ {4, 4, 4}, /* cost of storing integer registers */ -+ 4, /* cost of reg,reg fld/fst */ -+ {12, 12, 12}, /* cost of loading fp registers -+ in SFmode, DFmode and XFmode */ -+ {6, 6, 8}, /* cost of storing fp registers -+ in SFmode, DFmode and XFmode */ -+ 2, /* cost of moving MMX register */ -+ {8, 8}, /* cost of loading MMX registers -+ in SImode and DImode */ -+ {8, 8}, /* cost of storing MMX registers -+ in SImode and DImode */ -+ 2, /* cost of moving SSE register */ -+ {8, 8, 8}, /* cost of loading SSE registers -+ in SImode, DImode and TImode */ -+ {8, 8, 8}, /* cost of storing SSE registers -+ in SImode, DImode and TImode */ -+ 5, /* MMX or SSE register to integer */ -+ 32, /* size of l1 cache. */ -+ 256, /* size of l2 cache. */ -+ 64, /* size of prefetch block */ -+ 6, /* number of parallel prefetches */ -+ 3, /* Branch cost */ -+ COSTS_N_INSNS (8), /* cost of FADD and FSUB insns. */ -+ COSTS_N_INSNS (8), /* cost of FMUL instruction. */ -+ COSTS_N_INSNS (20), /* cost of FDIV instruction. */ -+ COSTS_N_INSNS (8), /* cost of FABS instruction. */ -+ COSTS_N_INSNS (8), /* cost of FCHS instruction. */ -+ COSTS_N_INSNS (40), /* cost of FSQRT instruction. */ -+ {{libcall, {{11, loop}, {-1, rep_prefix_4_byte}}}, -+ {libcall, {{32, loop}, {64, rep_prefix_4_byte}, -+ {8192, rep_prefix_8_byte}, {-1, libcall}}}}, -+ {{libcall, {{8, loop}, {15, unrolled_loop}, -+ {2048, rep_prefix_4_byte}, {-1, libcall}}}, -+ {libcall, {{24, loop}, {32, unrolled_loop}, -+ {8192, rep_prefix_8_byte}, {-1, libcall}}}}, -+ 1, /* scalar_stmt_cost. */ -+ 1, /* scalar load_cost. */ -+ 1, /* scalar_store_cost. */ -+ 1, /* vec_stmt_cost. */ -+ 1, /* vec_to_scalar_cost. */ -+ 1, /* scalar_to_vec_cost. */ -+ 1, /* vec_align_load_cost. */ -+ 2, /* vec_unalign_load_cost. */ -+ 1, /* vec_store_cost. */ -+ 3, /* cond_taken_branch_cost. */ -+ 1, /* cond_not_taken_branch_cost. */ -+}; -+ - /* Generic64 should produce code tuned for Nocona and K8. */ - static const - struct processor_costs generic64_cost = { -@@ -1194,6 +1267,7 @@ const struct processor_costs *ix86_cost - #define m_PENT4 (1<preds) -+ if (e->src == bb) -+ { -+ simple_loop = true; -+ break; -+ } -+ -+ if (simple_loop) -+ { -+ rtx prev = BB_END (bb); -+ while (prev -+ && prev != insn -+ && distance < LEA_SEARCH_THRESHOLD) -+ { -+ if (INSN_P (prev)) -+ { -+ distance++; -+ if ((reg_op1 && reg_set_p (reg_op1, prev)) -+ || (reg_op2 && reg_set_p (reg_op2, prev))) -+ return distance; -+ } -+ prev = PREV_INSN (prev); -+ } -+ } -+ } -+ -+ return -1; -+} -+ -+/* Return the distance between this insn and the next insn that uses -+ result of this insn as memory address. -+ Return -1 if not found such a use within LEA_SEARCH_THRESHOLD. */ -+static int -+distance_agu_use (rtx op0, rtx insn) -+{ -+ basic_block bb = BLOCK_FOR_INSN (insn); -+ int distance = 0; -+ -+ if (insn != BB_END(bb)) -+ { -+ rtx next = NEXT_INSN (insn); -+ -+ while (next && distance < LEA_SEARCH_THRESHOLD) -+ { -+ if (INSN_P (next)) -+ { -+ distance++; -+ if (reg_mentioned_by_mem_p (op0, next)) -+ return distance; -+ if (reg_set_p (op0, next)) -+ return -1; -+ } -+ if (next == BB_END (bb)) -+ break; -+ next = NEXT_INSN (next); -+ } -+ } -+ -+ if (distance < LEA_SEARCH_THRESHOLD) -+ { -+ edge e; -+ edge_iterator ei; -+ bool simple_loop = false; -+ -+ FOR_EACH_EDGE (e, ei, bb->succs) -+ if (e->dest == bb) -+ { -+ simple_loop = true; -+ break; -+ } -+ -+ if (simple_loop) -+ { -+ rtx next = BB_HEAD (bb); -+ while (next && distance < LEA_SEARCH_THRESHOLD) -+ { -+ if (next == insn) -+ break; -+ if (INSN_P (next)) -+ { -+ distance++; -+ if (reg_mentioned_by_mem_p (op0, next)) -+ return distance; -+ if (reg_set_p (op0, next)) -+ return -1; -+ } -+ next = NEXT_INSN (next); -+ } -+ } -+ } -+ -+ return -1; -+} -+ -+/* Define this macro to tune LEA priority vs ADD, it take effect when -+ there is a dilemma of choicing LEA or ADD -+ Negative value: ADD is more preferred than LEA -+ Zero: Netrual -+ Positive value: LEA is more preferred than ADD*/ -+#define IX86_LEA_PRIORITY 2 -+ -+/* Return true if it is ok to optimize an ADD operation to LEA -+ operation to avoid flag register consumation. For the processors -+ like ATOM, if the destination register of LEA holds an actual -+ address which will be used soon, LEA is better and otherwise ADD -+ is better. */ -+ -+bool -+ix86_lea_for_add_ok (enum rtx_code code ATTRIBUTE_UNUSED, -+ rtx insn, -+ rtx operands[]) -+{ -+ gcc_assert (REG_P (operands[0])); -+ gcc_assert (operands[1] && operands[2]); -+ -+ if (!TARGET_OPT_AGU || optimize_function_for_size_p (cfun)) -+ { -+ if (true_regnum (operands[0]) != true_regnum (operands[1])) -+ return true; -+ else -+ return false; -+ } -+ -+ /* If a = b + c, (a!=b && a!=c), must use lea form. */ -+ if (true_regnum (operands[0]) != true_regnum (operands[1]) -+ && true_regnum (operands[0]) != true_regnum (operands[2])) -+ return true; -+ else -+ { -+ int dist_define, dist_use; -+ dist_define = distance_non_agu_define (operands[1], -+ operands[2], insn); -+ if (dist_define <= 0) -+ return true; -+ -+ /* If this insn has both backward non-agu dependence and forward -+ agu dependence, the one with short distance take effect. */ -+ dist_use = distance_agu_use (operands[0], insn); -+ if (dist_use <= 0 -+ || (dist_define + IX86_LEA_PRIORITY) < dist_use) -+ return false; -+ -+ return true; -+ } -+} -+ -+/* Return true if destination reg of SET_INSN is shift count of -+ USE_INSN. */ -+ -+bool -+ix86_dep_by_shift_count (const_rtx set_insn, const_rtx use_insn) -+{ -+ rtx set_pattern = PATTERN (set_insn); -+ rtx set_dest; -+ rtx shift_rtx; -+ rtx use_pattern; -+ -+ /* Retrieve destination of set_insn */ -+ switch (GET_CODE (set_pattern)) -+ { -+ case SET: -+ set_dest = SET_DEST (set_pattern); -+ break; -+ case PARALLEL: -+ set_pattern = XVECEXP (set_pattern, 0, 0); -+ if (GET_CODE (set_pattern ) == SET) -+ { -+ set_dest = SET_DEST (set_pattern); -+ break; -+ } -+ default: -+ set_dest = NULL; -+ break; -+ } -+ if (!set_dest || !REG_P (set_dest)) -+ return false; -+ -+ /* Retrieve shift count of use_insn */ -+ use_pattern = PATTERN (use_insn); -+ switch (GET_CODE (use_pattern)) -+ { -+ case SET: -+ shift_rtx = XEXP (use_pattern, 1); -+ break; -+ case PARALLEL: -+ set_pattern = XVECEXP (use_pattern, 0, 0); -+ if (GET_CODE (set_pattern) == SET) -+ { -+ shift_rtx = XEXP (set_pattern, 1); -+ break; -+ } -+ default: -+ shift_rtx = NULL; -+ break; -+ } -+ -+ if (shift_rtx -+ && (GET_CODE (shift_rtx) == ASHIFT -+ || GET_CODE (shift_rtx) == LSHIFTRT -+ || GET_CODE (shift_rtx) == ASHIFTRT -+ || GET_CODE (shift_rtx) == ROTATE -+ || GET_CODE (shift_rtx) == ROTATERT)) -+ { -+ rtx shift_count = XEXP (shift_rtx, 1); -+ gcc_assert (shift_count); -+ -+ /* Return true if shift count is dest of set_insn */ -+ if (REG_P (shift_count) -+ && true_regnum (set_dest) == true_regnum (shift_count)) -+ return true; -+ } -+ -+ return false; -+} -+ - /* Return TRUE or FALSE depending on whether the unary operator meets the - appropriate constraints. */ - -@@ -18985,6 +19333,7 @@ ix86_issue_rate (void) - switch (ix86_tune) - { - case PROCESSOR_PENTIUM: -+ case PROCESSOR_ATOM: - case PROCESSOR_K6: - return 2; - -@@ -19051,41 +19400,21 @@ ix86_flags_dependent (rtx insn, rtx dep_ - return 1; - } - --/* A subroutine of ix86_adjust_cost -- return true iff INSN has a memory -- address with operands set by DEP_INSN. */ -+/* Return true iff USE_INSN has a memory address with operands set by -+ SET_INSN. */ - --static int --ix86_agi_dependent (rtx insn, rtx dep_insn, enum attr_type insn_type) -+bool -+ix86_agi_dependent (rtx set_insn, rtx use_insn) - { -- rtx addr; -- -- if (insn_type == TYPE_LEA -- && TARGET_PENTIUM) -- { -- addr = PATTERN (insn); -- -- if (GET_CODE (addr) == PARALLEL) -- addr = XVECEXP (addr, 0, 0); -- -- gcc_assert (GET_CODE (addr) == SET); -- -- addr = SET_SRC (addr); -- } -- else -- { -- int i; -- extract_insn_cached (insn); -- for (i = recog_data.n_operands - 1; i >= 0; --i) -- if (MEM_P (recog_data.operand[i])) -- { -- addr = XEXP (recog_data.operand[i], 0); -- goto found; -- } -- return 0; -- found:; -- } -- -- return modified_in_p (addr, dep_insn); -+ int i; -+ extract_insn_cached (use_insn); -+ for (i = recog_data.n_operands - 1; i >= 0; --i) -+ if (MEM_P (recog_data.operand[i])) -+ { -+ rtx addr = XEXP (recog_data.operand[i], 0); -+ return modified_in_p (addr, set_insn) != 0; -+ } -+ return false; - } - - static int -@@ -19113,8 +19442,19 @@ ix86_adjust_cost (rtx insn, rtx link, rt - { - case PROCESSOR_PENTIUM: - /* Address Generation Interlock adds a cycle of latency. */ -- if (ix86_agi_dependent (insn, dep_insn, insn_type)) -- cost += 1; -+ if (insn_type == TYPE_LEA) -+ { -+ rtx addr = PATTERN (insn); -+ -+ if (GET_CODE (addr) == PARALLEL) -+ addr = XVECEXP (addr, 0, 0); -+ -+ gcc_assert (GET_CODE (addr) == SET); -+ -+ addr = SET_SRC (addr); -+ if (modified_in_p (addr, dep_insn)) -+ cost += 1; -+ } - - /* ??? Compares pair with jump/setcc. */ - if (ix86_flags_dependent (insn, dep_insn, insn_type)) -@@ -19123,7 +19463,7 @@ ix86_adjust_cost (rtx insn, rtx link, rt - /* Floating point stores require value to be ready one cycle earlier. */ - if (insn_type == TYPE_FMOV - && get_attr_memory (insn) == MEMORY_STORE -- && !ix86_agi_dependent (insn, dep_insn, insn_type)) -+ && !ix86_agi_dependent (dep_insn, insn)) - cost += 1; - break; - -@@ -19146,7 +19486,7 @@ ix86_adjust_cost (rtx insn, rtx link, rt - in parallel with previous instruction in case - previous instruction is not needed to compute the address. */ - if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH) -- && !ix86_agi_dependent (insn, dep_insn, insn_type)) -+ && !ix86_agi_dependent (dep_insn, insn)) - { - /* Claim moves to take one cycle, as core can issue one load - at time and the next load can start cycle later. */ -@@ -19175,7 +19515,7 @@ ix86_adjust_cost (rtx insn, rtx link, rt - in parallel with previous instruction in case - previous instruction is not needed to compute the address. */ - if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH) -- && !ix86_agi_dependent (insn, dep_insn, insn_type)) -+ && !ix86_agi_dependent (dep_insn, insn)) - { - /* Claim moves to take one cycle, as core can issue one load - at time and the next load can start cycle later. */ -@@ -19192,6 +19532,7 @@ ix86_adjust_cost (rtx insn, rtx link, rt - case PROCESSOR_ATHLON: - case PROCESSOR_K8: - case PROCESSOR_AMDFAM10: -+ case PROCESSOR_ATOM: - case PROCESSOR_GENERIC32: - case PROCESSOR_GENERIC64: - memory = get_attr_memory (insn); -@@ -19200,7 +19541,7 @@ ix86_adjust_cost (rtx insn, rtx link, rt - in parallel with previous instruction in case - previous instruction is not needed to compute the address. */ - if ((memory == MEMORY_LOAD || memory == MEMORY_BOTH) -- && !ix86_agi_dependent (insn, dep_insn, insn_type)) -+ && !ix86_agi_dependent (dep_insn, insn)) - { - enum attr_unit unit = get_attr_unit (insn); - int loadcost = 3; diff --git a/gcc44-hack.patch b/gcc44-hack.patch index da00568..c770339 100644 --- a/gcc44-hack.patch +++ b/gcc44-hack.patch @@ -1,8 +1,8 @@ --- libada/Makefile.in.jj 2009-01-14 12:07:35.000000000 +0100 +++ libada/Makefile.in 2009-01-15 14:25:33.000000000 +0100 -@@ -66,17 +66,39 @@ target_noncanonical:=@target_noncanonica - version := $(shell cat $(srcdir)/../gcc/BASE-VER) +@@ -67,17 +67,39 @@ version := $(shell cat $(srcdir)/../gcc/ libsubdir := $(libdir)/gcc/$(target_noncanonical)/$(version)$(MULTISUBDIR) + ADA_RTS_DIR=$(GCC_DIR)/ada/rts$(subst /,_,$(MULTISUBDIR)) +DEFAULTMULTIFLAGS := +ifeq ($(MULTISUBDIR),) @@ -43,7 +43,7 @@ "TARGET_LIBGCC2_CFLAGS=$(TARGET_LIBGCC2_CFLAGS)" \ "THREAD_KIND=$(THREAD_KIND)" \ "TRACE=$(TRACE)" \ -@@ -87,7 +109,7 @@ LIBADA_FLAGS_TO_PASS = \ +@@ -88,7 +110,7 @@ LIBADA_FLAGS_TO_PASS = \ "exeext=.exeext.should.not.be.used " \ 'CC=the.host.compiler.should.not.be.needed' \ "GCC_FOR_TARGET=$(CC)" \ diff --git a/gcc44-libstdc++-docs.patch b/gcc44-libstdc++-docs.patch new file mode 100644 index 0000000..45caafe --- /dev/null +++ b/gcc44-libstdc++-docs.patch @@ -0,0 +1,47 @@ +--- libstdc++-v3/doc/html/index.html 2009-01-14 12:06:37.000000000 +0100 ++++ libstdc++-v3/doc/html/index.html 2009-05-06 09:17:30.000000000 +0200 +@@ -12,7 +12,8 @@ +
+

The GNU C++ Library Documentation

+ +-

Copyright 2008 FSF

++

Release 4.4.0

++

Copyright 2008, 2009 FSF

+ +

+ Permission is granted to copy, distribute and/or modify this +--- libstdc++-v3/doc/html/api.html 2009-04-20 21:21:15.000000000 +0200 ++++ libstdc++-v3/doc/html/api.html 2009-05-06 09:17:24.000000000 +0200 +@@ -17,27 +17,12 @@ useful for examining the signatures of p + the library classes, finding out what is in a particular include + file, looking at inheritance diagrams, etc. +

+-The source-level documentation for the most recent releases can be +-viewed online: +-

  • +- for the 3.4 release ++The source-level documentation can be viewed here: ++

    ++

    + This generated HTML collection, as above, is also available for download in the libstdc++ snapshots directory at + <URL:ftp://gcc.gnu.org/pub/gcc/libstdc++/doxygen/>. diff --git a/gcc44-memmove-opt.patch b/gcc44-memmove-opt.patch deleted file mode 100644 index e35ade2..0000000 --- a/gcc44-memmove-opt.patch +++ /dev/null @@ -1,128 +0,0 @@ -2009-03-18 Jakub Jelinek - - * builtins.c (fold_builtin_memory_op): Optimize memmove - into memcpy if we can prove source and destination don't overlap. - - * gcc.dg/memmove-2.c: New test. - * gcc.dg/memmove-3.c: New test. - ---- gcc/builtins.c.jj 2009-03-04 20:06:31.000000000 +0100 -+++ gcc/builtins.c 2009-03-18 18:19:28.000000000 +0100 -@@ -8882,17 +8882,74 @@ fold_builtin_memory_op (tree dest, tree - really mandatory? - - If either SRC is readonly or length is 1, we can use memcpy. */ -- if (dest_align && src_align -- && (readonly_data_expr (src) -- || (host_integerp (len, 1) -- && (MIN (src_align, dest_align) / BITS_PER_UNIT >= -- tree_low_cst (len, 1))))) -+ if (!dest_align || !src_align) -+ return NULL_TREE; -+ if (readonly_data_expr (src) -+ || (host_integerp (len, 1) -+ && (MIN (src_align, dest_align) / BITS_PER_UNIT >= -+ tree_low_cst (len, 1)))) - { - tree fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; - if (!fn) - return NULL_TREE; - return build_call_expr (fn, 3, dest, src, len); - } -+ -+ /* If *src and *dest can't overlap, optimize into memcpy as well. */ -+ srcvar = build_fold_indirect_ref (src); -+ destvar = build_fold_indirect_ref (dest); -+ if (srcvar && !TREE_THIS_VOLATILE (srcvar) -+ && destvar && !TREE_THIS_VOLATILE (destvar)) -+ { -+ tree src_base, dest_base, fn; -+ HOST_WIDE_INT src_offset = 0, dest_offset = 0; -+ HOST_WIDE_INT size = -1; -+ HOST_WIDE_INT maxsize = -1; -+ -+ src_base = srcvar; -+ if (handled_component_p (src_base)) -+ src_base = get_ref_base_and_extent (src_base, &src_offset, -+ &size, &maxsize); -+ dest_base = destvar; -+ if (handled_component_p (dest_base)) -+ dest_base = get_ref_base_and_extent (dest_base, &dest_offset, -+ &size, &maxsize); -+ if (host_integerp (len, 1)) -+ { -+ maxsize = tree_low_cst (len, 1); -+ if (maxsize -+ > INTTYPE_MAXIMUM (HOST_WIDE_INT) / BITS_PER_UNIT) -+ maxsize = -1; -+ else -+ maxsize *= BITS_PER_UNIT; -+ } -+ else -+ maxsize = -1; -+ if (SSA_VAR_P (src_base) -+ && SSA_VAR_P (dest_base)) -+ { -+ if (operand_equal_p (src_base, dest_base, 0) -+ && ranges_overlap_p (src_offset, maxsize, -+ dest_offset, maxsize)) -+ return NULL_TREE; -+ } -+ else if (TREE_CODE (src_base) == INDIRECT_REF -+ && TREE_CODE (dest_base) == INDIRECT_REF) -+ { -+ if (! operand_equal_p (TREE_OPERAND (src_base, 0), -+ TREE_OPERAND (dest_base, 0), 0) -+ || ranges_overlap_p (src_offset, maxsize, -+ dest_offset, maxsize)) -+ return NULL_TREE; -+ } -+ else -+ return NULL_TREE; -+ -+ fn = implicit_built_in_decls[BUILT_IN_MEMCPY]; -+ if (!fn) -+ return NULL_TREE; -+ return build_call_expr (fn, 3, dest, src, len); -+ } - return NULL_TREE; - } - ---- gcc/testsuite/gcc.dg/memmove-2.c.jj 2009-03-18 18:30:17.000000000 +0100 -+++ gcc/testsuite/gcc.dg/memmove-2.c 2009-03-18 18:30:49.000000000 +0100 -@@ -0,0 +1,16 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -fdump-tree-optimized" } */ -+/* { dg-final { scan-tree-dump-times "memmove" 0 "optimized" } } */ -+/* { dg-final { cleanup-tree-dump "optimized" } } */ -+ -+char a[40]; -+extern void bar (char *); -+ -+void -+foo (void) -+{ -+ char b[10]; -+ __builtin_memmove (&a[0], &a[20], 20); -+ __builtin_memmove (&b[1], &a[25], 9); -+ bar (b); -+} ---- gcc/testsuite/gcc.dg/memmove-3.c.jj 2009-03-18 18:30:19.000000000 +0100 -+++ gcc/testsuite/gcc.dg/memmove-3.c 2009-03-18 18:31:01.000000000 +0100 -@@ -0,0 +1,16 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -fdump-tree-optimized" } */ -+/* { dg-final { scan-tree-dump-times "memmove" 3 "optimized" } } */ -+/* { dg-final { cleanup-tree-dump "optimized" } } */ -+ -+char a[40]; -+struct A { char a[30]; }; -+ -+void -+foo (struct A *p, char *q, char *r) -+{ -+ char b[10]; -+ __builtin_memmove (&a[1], &a[19], 20); -+ __builtin_memmove (&p->a[1], &p->a[9], 10); -+ __builtin_memmove (q, r, 9); -+} diff --git a/gcc44-power7-2.patch b/gcc44-power7-2.patch index 519f8b9..a296217 100644 --- a/gcc44-power7-2.patch +++ b/gcc44-power7-2.patch @@ -1,1369 +1,267 @@ -2009-03-13 Michael Meissner +2009-04-14 Michael Meissner - PR target/39457 - * config/rs6000/rs6000.opt (-mdisallow-float-in-lr-ctr): Add - temporary debug switch. + * config/rs6000/rs6000.c (rs6000_secondary_reload_inner): Handle + more possible combinations of addresses. - * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Revert - behavior of disallowing + * config/rs6000/vector.md (vec_reload_and_plus_): Allow + register+small constant in addition to register+register, and + restrict the insn to only match during reload and afterwards. + (vec_reload_and_reg_): Allow for and of register + indirect to not generate insn not found message. -2009-03-13 Michael Meissner - - * config/rs6000/vector.md (vec_extract_evenv2df): Delete, insn - causes problems in building spec 2006. - (vec_extract_oddv2df): Ditto. - (vec_pack_trunc_v2df): New expanders for VSX vectorized - conversions. - (vec_pack_sfix_trunc_v2df): Ditto. - (vec_pack_ufix_trunc_v2df): Ditto. - (vec_unpacks_hi_v4sf): Ditto. - (vec_unpacks_lo_v4sf): Ditto. - (vec_unpacks_float_hi_v4si): Ditto. - (vec_unpacks_float_lo_v4si): Ditto. - (vec_unpacku_float_hi_v4si): Ditto. - (vec_unpacku_float_lo_v4si): Ditto. - - * config/rs6000/rs6000-protos.h (rs6000_vector_secondary_reload): - Declaration for new target hook. - - * config/rs6000/rs6000.c (TARGET_SECONDARY_RELOAD): Add new target - hook for eventually fixing up the memory references for Altivec - and VSX reloads to be reg+reg instead of reg+offset. Right now, - this is a stub function that prints debug information if - -mdebug=addr and then calls default_secondary_reload. - (rs6000_secondary_reload): Ditto. - (rs6000_vector_secondary_reload): Ditto. - (rs6000_builtin_conversion): Add support for V2DI/V2DF - conversions. - (rs6000_legitimate_offset_address_p): Test for the vector unit - doing the memory references. - (rs6000_legimize_reload_address): Ditto. - (rs6000_legitimize_address): Print extra \n if -mdebug=addr. - (rs6000_legitimize_reload_address): Ditto. - (rs6000_legitimate_address): Ditto. - (rs6000_mode_dependent_address): Ditto. - (bdesc_2arg): Add VSX builtins. - (bdesc_abs): Ditto. - (bdesc_1arg): Ditto. - (altivec_init_builtins): Ditto. - (rs6000_secondary_memory_needed_rtx): Add debug support if - -mdebug=addr. - (rs6000_preferred_reload_class): Ditto. - (rs6000_secondary_memory_needed): Ditto. - (rs6000_secondary_reload_class): Ditto. - (rs6000_cannot_change_mode_class): Ditto. - - * config/rs6000/vsx.md (UNSPEC_VSX_*): Add unspecs for VSX - conversions. - (vsx_nabs): Add generator function. - (vsx_float2): Ditto. - (vsx_floatuns2): Ditto. - (vsx_xxmrghw): Ditto. - (vsx_xxmrglw): Ditto. - (vsx_xvcvdpsp): New VSX vector conversion insn. - (vsx_xvcvdpsxws): Ditto. - (vsx_xvcvdpuxws): Ditto. - (vsx_xvcvspdp): Ditto. - (vsx_xvcvsxwdp): Ditto. - (vsx_xvcvuxwdp): Ditto. - (vsx_reload_*): New insns for reload support. - - * config/rs6000/rs6000.h: Fix a comment. - - * config/rs6000/altivec.md (altivec_reload_*): New insns for - reload support. - - * config/rs6000/rs6000.md (ptrsize): New mode attribute for the - pointer size. - -2009-03-10 Michael Meissner - - * config/rs6000/vsx.md (vsx_concat_v2df): Add explicit 'f' - register class for scalar data, correct uses of the xxpermdi - instruction. - (vsx_set_v2df): Ditto. - (vsx_extract_v2df): Ditto. - (vsx_xxpermdi): Ditto. - (vsx_splatv2df): Ditto. - (vsx_xxmrghw): Use wf instead of v constraints. - (vsx_xxmrglw): Ditto. -testsuite/ -2009-03-13 Michael Meissner - - PR target/39457 - * gcc.target/powerpc/pr39457.c: New test for PR39457. - -2009-03-13 Michael Meissner - - * gcc.target/powerpc/vsx-builtin-1.c: New test for builtins. - * gcc.target/powerpc/vsx-builtin-2.c: Ditto. - ---- gcc/config/rs6000/vector.md (revision 144758) -+++ gcc/config/rs6000/vector.md (revision 144843) -@@ -496,23 +496,122 @@ (define_expand "vec_interleave_lowv2df" - "VECTOR_UNIT_VSX_P (V2DFmode)" - "") +--- gcc/config/rs6000/vector.md (revision 146069) ++++ gcc/config/rs6000/vector.md (revision 146118) +@@ -129,14 +129,15 @@ (define_expand "reload__" + [(set (match_operand:P 0 "gpc_reg_operand" "=b") + (and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r") +- (match_operand:P 2 "gpc_reg_operand" "r")) ++ (match_operand:P 2 "reg_or_cint_operand" "rI")) + (const_int -16)))] +- "TARGET_ALTIVEC || TARGET_VSX" ++ "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)" + "#" + "&& reload_completed" + [(set (match_dup 0) +@@ -146,6 +147,21 @@ (define_insn_and_split "*vec_reload_and_ + (and:P (match_dup 0) + (const_int -16))) + (clobber:CC (scratch:CC))])]) + -+(define_expand "vec_pack_sfix_trunc_v2df" -+ [(match_operand:V4SI 0 "vsx_register_operand" "") -+ (match_operand:V2DF 1 "vsx_register_operand" "") -+ (match_operand:V2DF 2 "vsx_register_operand" "")] -+ "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" -+{ -+ rtx r1 = gen_reg_rtx (V4SImode); -+ rtx r2 = gen_reg_rtx (V4SImode); -+ -+ emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1])); -+ emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2])); -+ emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2)); -+ DONE; -+}) -+ -+(define_expand "vec_pack_ufix_trunc_v2df" -+ [(match_operand:V4SI 0 "vsx_register_operand" "") -+ (match_operand:V2DF 1 "vsx_register_operand" "") -+ (match_operand:V2DF 2 "vsx_register_operand" "")] -+ "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" -+{ -+ rtx r1 = gen_reg_rtx (V4SImode); -+ rtx r2 = gen_reg_rtx (V4SImode); -+ -+ emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1])); -+ emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2])); -+ emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2)); -+ DONE; -+}) -+ -+;; Convert single word types to double word -+(define_expand "vec_unpacks_hi_v4sf" -+ [(match_operand:V2DF 0 "vsx_register_operand" "") -+ (match_operand:V4SF 1 "vsx_register_operand" "")] -+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)" -+{ -+ rtx reg = gen_reg_rtx (V4SFmode); -+ -+ emit_insn (gen_vec_interleave_highv4sf (reg, operands[1], operands[1])); -+ emit_insn (gen_vsx_xvcvspdp (operands[0], reg)); -+ DONE; -+}) -+ -+(define_expand "vec_unpacks_lo_v4sf" -+ [(match_operand:V2DF 0 "vsx_register_operand" "") -+ (match_operand:V4SF 1 "vsx_register_operand" "")] -+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)" -+{ -+ rtx reg = gen_reg_rtx (V4SFmode); -+ -+ emit_insn (gen_vec_interleave_lowv4sf (reg, operands[1], operands[1])); -+ emit_insn (gen_vsx_xvcvspdp (operands[0], reg)); -+ DONE; -+}) -+ -+(define_expand "vec_unpacks_float_hi_v4si" -+ [(match_operand:V2DF 0 "vsx_register_operand" "") -+ (match_operand:V4SI 1 "vsx_register_operand" "")] -+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" -+{ -+ rtx reg = gen_reg_rtx (V4SImode); -+ -+ emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1])); -+ emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg)); -+ DONE; -+}) -+ -+(define_expand "vec_unpacks_float_lo_v4si" -+ [(match_operand:V2DF 0 "vsx_register_operand" "") -+ (match_operand:V4SI 1 "vsx_register_operand" "")] -+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" -+{ -+ rtx reg = gen_reg_rtx (V4SImode); -+ -+ emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1])); -+ emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg)); -+ DONE; -+}) -+ -+(define_expand "vec_unpacku_float_hi_v4si" -+ [(match_operand:V2DF 0 "vsx_register_operand" "") -+ (match_operand:V4SI 1 "vsx_register_operand" "")] -+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" -+{ -+ rtx reg = gen_reg_rtx (V4SImode); -+ -+ emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1])); -+ emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg)); -+ DONE; -+}) -+ -+(define_expand "vec_unpacku_float_lo_v4si" -+ [(match_operand:V2DF 0 "vsx_register_operand" "") -+ (match_operand:V4SI 1 "vsx_register_operand" "")] -+ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" -+{ -+ rtx reg = gen_reg_rtx (V4SImode); -+ -+ emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1])); -+ emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg)); -+ DONE; -+}) ---- gcc/config/rs6000/rs6000-protos.h (revision 144758) -+++ gcc/config/rs6000/rs6000-protos.h (revision 144843) -@@ -72,6 +72,7 @@ extern bool rs6000_secondary_memory_need - extern bool rs6000_cannot_change_mode_class (enum machine_mode, - enum machine_mode, - enum reg_class); -+extern void rs6000_vector_secondary_reload (rtx, rtx, rtx, bool); - extern int paired_emit_vector_cond_expr (rtx, rtx, rtx, - rtx, rtx, rtx); - extern void paired_expand_vector_move (rtx operands[]); ---- gcc/config/rs6000/rs6000.opt (revision 144845) -+++ gcc/config/rs6000/rs6000.opt (revision 144857) -@@ -139,6 +139,9 @@ mvsx-scalar-memory - Target Report Var(TARGET_VSX_SCALAR_MEMORY) - If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default) - -+mdisallow-float-in-lr-ctr -+Target Undocumented Var(TARGET_DISALLOW_FLOAT_IN_LR_CTR) Init(-1) -+ - mupdate - Target Report Var(TARGET_UPDATE) Init(1) - Generate load/store with update instructions ---- gcc/config/rs6000/rs6000.c (revision 144758) -+++ gcc/config/rs6000/rs6000.c (revision 144843) -@@ -1004,6 +1004,10 @@ static rtx rs6000_emit_vector_compare (e - enum machine_mode); - static tree rs6000_stack_protect_fail (void); - -+static enum reg_class rs6000_secondary_reload (bool, rtx, enum reg_class, -+ enum machine_mode, -+ struct secondary_reload_info *); -+ - const int INSN_NOT_AVAILABLE = -1; - static enum machine_mode rs6000_eh_return_filter_mode (void); - -@@ -1333,6 +1337,9 @@ static const char alt_reg_names[][8] = - #undef TARGET_INSTANTIATE_DECLS - #define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls - -+#undef TARGET_SECONDARY_RELOAD -+#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload -+ - struct gcc_target targetm = TARGET_INITIALIZER; ++;; The normal ANDSI3/ANDDI3 won't match if reload decides to move an AND -16 ++;; address to a register because there is no clobber of a (scratch), so we add ++;; it here. ++(define_insn_and_split "*vec_reload_and_reg_" ++ [(set (match_operand:P 0 "gpc_reg_operand" "=b") ++ (and:P (match_operand:P 1 "gpc_reg_operand" "r") ++ (const_int -16)))] ++ "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)" ++ "#" ++ "&& reload_completed" ++ [(parallel [(set (match_dup 0) ++ (and:P (match_dup 1) ++ (const_int -16))) ++ (clobber:CC (scratch:CC))])]) - /* Return number of consecutive hard regs needed starting at reg REGNO -@@ -1448,10 +1448,16 @@ rs6000_hard_regno_mode_ok (int regno, en - if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode)) - return 1; + ;; Generic floating point vector arithmetic support + (define_expand "add3" +--- gcc/config/rs6000/rs6000.c (revision 146069) ++++ gcc/config/rs6000/rs6000.c (revision 146118) +@@ -12574,6 +12574,11 @@ rs6000_secondary_reload_inner (rtx reg, + enum reg_class rclass; + rtx addr; + rtx and_op2 = NULL_RTX; ++ rtx addr_op1; ++ rtx addr_op2; ++ rtx scratch_or_premodify = scratch; ++ rtx and_rtx; ++ rtx cc_clobber; -- /* Don't allow anything but word sized integers (aka pointers) in CTR/LR. You -- really don't want to spill your floating point values to those -- registers. Also do it for the old MQ register in the power. */ -- if (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO) -+ /* Don't allow anything but word sized integers (aka pointers) in CTR/LR. -+ You really don't want to spill your floating point values to those -+ registers. Also do it for the old MQ register in the power. -+ -+ While this is desirable in theory, disabling float to go in LR/CTR does -+ cause some regressions, so until they are taken care of, revert to the old -+ behavior by default for most power systems, but enable it for power7. */ -+ if ((TARGET_DISALLOW_FLOAT_IN_LR_CTR > 0 -+ || (TARGET_DISALLOW_FLOAT_IN_LR_CTR < 0 && TARGET_VSX)) -+ && (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO)) - return (GET_MODE_CLASS (mode) == MODE_INT - && GET_MODE_SIZE (mode) <= UNITS_PER_WORD); - -@@ -2447,6 +2454,14 @@ rs6000_builtin_conversion (enum tree_cod - case FIX_TRUNC_EXPR: - switch (TYPE_MODE (type)) - { -+ case V2DImode: -+ if (!VECTOR_UNIT_VSX_P (V2DFmode)) -+ return NULL_TREE; -+ -+ return TYPE_UNSIGNED (type) -+ ? rs6000_builtin_decls[VSX_BUILTIN_XVCVDPUXDS] -+ : rs6000_builtin_decls[VSX_BUILTIN_XVCVDPSXDS]; -+ - case V4SImode: - if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode)) - return NULL_TREE; -@@ -2462,6 +2477,14 @@ rs6000_builtin_conversion (enum tree_cod - case FLOAT_EXPR: - switch (TYPE_MODE (type)) - { -+ case V2DImode: -+ if (!VECTOR_UNIT_VSX_P (V2DFmode)) -+ return NULL_TREE; -+ -+ return TYPE_UNSIGNED (type) -+ ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDSP] -+ : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDSP]; -+ - case V4SImode: - if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode)) - return NULL_TREE; -@@ -2469,6 +2492,7 @@ rs6000_builtin_conversion (enum tree_cod - return TYPE_UNSIGNED (type) - ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF] - : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF]; -+ - default: - return NULL_TREE; - } -@@ -4101,7 +4125,7 @@ rs6000_legitimate_offset_address_p (enum - case V2DImode: - /* AltiVec/VSX vector modes. Only reg+reg addressing is valid and - constant offset zero should not occur due to canonicalization. */ -- if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)) -+ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)) - return false; - break; - -@@ -4441,6 +4465,7 @@ rs6000_legitimize_address (rtx x, rtx ol - } - else - fprintf (stderr, "NULL returned\n"); -+ fprintf (stderr, "\n"); - } - - return ret; -@@ -4776,8 +4801,7 @@ rs6000_legitimize_reload_address (rtx x, - && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode) - && GET_CODE (XEXP (x, 1)) == CONST_INT - && (INTVAL (XEXP (x, 1)) & 3) != 0 -- && !ALTIVEC_VECTOR_MODE (mode) -- && !VSX_VECTOR_MODE (mode) -+ && VECTOR_MEM_NONE_P (mode) - && GET_MODE_SIZE (mode) >= UNITS_PER_WORD - && TARGET_POWERPC64) - { -@@ -4798,8 +4822,7 @@ rs6000_legitimize_reload_address (rtx x, - && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode - || mode == DDmode || mode == TDmode - || mode == DImode)) -- && !ALTIVEC_VECTOR_MODE (mode) -- && !VSX_VECTOR_MODE (mode)) -+ && VECTOR_MEM_NONE_P (mode)) - { - HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); - HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; -@@ -4843,6 +4866,7 @@ rs6000_legitimize_reload_address (rtx x, - /* Don't do this for TFmode or TDmode, since the result isn't - offsettable. The same goes for DImode without 64-bit gprs and - DFmode and DDmode without fprs. */ -+ && VECTOR_MEM_NONE_P (mode) - && mode != TFmode - && mode != TDmode - && (mode != DImode || TARGET_POWERPC64) -@@ -4918,6 +4942,8 @@ rs6000_legitimize_reload_address (rtx x, - fprintf (stderr, "New address:\n"); - debug_rtx (ret); - } -+ -+ fprintf (stderr, "\n"); - } - - return ret; -@@ -5035,6 +5061,7 @@ rs6000_legitimate_address (enum machine_ - GET_MODE_NAME (mode), - reg_ok_strict); - debug_rtx (orig_x); -+ fprintf (stderr, "\n"); - } - - return ret; -@@ -5082,9 +5109,10 @@ rs6000_mode_dependent_address (rtx addr) if (TARGET_DEBUG_ADDR) { - fprintf (stderr, -- "\nrs6000_mode_dependent_address: ret = %d\n", -- (int)ret); -+ "\nrs6000_mode_dependent_address: ret = %s\n", -+ ret ? "true" : "false"); - debug_rtx (addr); -+ fprintf (stderr, "\n"); - } +@@ -12595,7 +12600,8 @@ rs6000_secondary_reload_inner (rtx reg, - return ret; -@@ -7917,6 +7945,20 @@ static struct builtin_description bdesc_ - { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS }, - { MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR }, - -+ { MASK_VSX, CODE_FOR_addv2df3, "__builtin_vsx_xvadddp", VSX_BUILTIN_XVADDDP }, -+ { MASK_VSX, CODE_FOR_subv2df3, "__builtin_vsx_xvsubdp", VSX_BUILTIN_XVSUBDP }, -+ { MASK_VSX, CODE_FOR_mulv2df3, "__builtin_vsx_xvmuldp", VSX_BUILTIN_XVMULDP }, -+ { MASK_VSX, CODE_FOR_divv2df3, "__builtin_vsx_xvdivdp", VSX_BUILTIN_XVDIVDP }, -+ { MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP }, -+ { MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP }, -+ -+ { MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP }, -+ { MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP }, -+ { MASK_VSX, CODE_FOR_mulv4sf3, "__builtin_vsx_xvmulsp", VSX_BUILTIN_XVMULSP }, -+ { MASK_VSX, CODE_FOR_divv4sf3, "__builtin_vsx_xvdivsp", VSX_BUILTIN_XVDIVSP }, -+ { MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP }, -+ { MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP }, -+ - { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD }, - { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP }, - { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM }, -@@ -8288,7 +8330,11 @@ static const struct builtin_description - { MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI }, - { MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI }, - { MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI }, -- { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI } -+ { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI }, -+ { MASK_VSX, CODE_FOR_absv2df2, "__builtin_vsx_xvabsdp", VSX_BUILTIN_XVABSDP }, -+ { MASK_VSX, CODE_FOR_vsx_nabsv2df2, "__builtin_vsx_xvnabsdp", VSX_BUILTIN_XVNABSDP }, -+ { MASK_VSX, CODE_FOR_absv4sf2, "__builtin_vsx_xvabssp", VSX_BUILTIN_XVABSSP }, -+ { MASK_VSX, CODE_FOR_vsx_nabsv4sf2, "__builtin_vsx_xvnabssp", VSX_BUILTIN_XVNABSSP }, - }; - - /* Simple unary operations: VECb = foo (unsigned literal) or VECb = -@@ -8314,6 +8360,11 @@ static struct builtin_description bdesc_ - { MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX }, - { MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH }, - -+ { MASK_VSX, CODE_FOR_negv2df2, "__builtin_vsx_xvnegdp", VSX_BUILTIN_XVNEGDP }, -+ { MASK_VSX, CODE_FOR_sqrtv2df2, "__builtin_vsx_xvsqrtdp", VSX_BUILTIN_XVSQRTDP }, -+ { MASK_VSX, CODE_FOR_negv4sf2, "__builtin_vsx_xvnegsp", VSX_BUILTIN_XVNEGSP }, -+ { MASK_VSX, CODE_FOR_sqrtv4sf2, "__builtin_vsx_xvsqrtsp", VSX_BUILTIN_XVSQRTSP }, -+ - { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS }, - { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS }, - { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL }, -@@ -8339,6 +8390,15 @@ static struct builtin_description bdesc_ - { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI }, - { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI }, - -+ { MASK_VSX, CODE_FOR_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP }, -+ { MASK_VSX, CODE_FOR_unsigned_floatv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP }, -+ { MASK_VSX, CODE_FOR_fix_truncv2dfv2di2, "__builtin_vsx_xvdpsxds", VSX_BUILTIN_XVCVDPSXDS }, -+ { MASK_VSX, CODE_FOR_fixuns_truncv2dfv2di2, "__builtin_vsx_xvdpuxds", VSX_BUILTIN_XVCVDPUXDS }, -+ { MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXDSP }, -+ { MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP }, -+ { MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vsx_xvspsxws", VSX_BUILTIN_XVCVSPSXWS }, -+ { MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vsx_xvspuxws", VSX_BUILTIN_XVCVSPUXWS }, -+ - /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and - end with SPE_BUILTIN_EVSUBFUSIAAW. */ - { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS }, -@@ -10484,6 +10544,8 @@ altivec_init_builtins (void) - = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE); - tree v4sf_ftype_v4sf - = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE); -+ tree v2df_ftype_v2df -+ = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE); - tree void_ftype_pcvoid_int_int - = build_function_type_list (void_type_node, - pcvoid_type_node, integer_type_node, -@@ -10641,6 +10703,9 @@ altivec_init_builtins (void) - case V4SFmode: - type = v4sf_ftype_v4sf; - break; -+ case V2DFmode: -+ type = v2df_ftype_v2df; -+ break; - default: - gcc_unreachable (); + switch (rclass) + { +- /* Move reg+reg addresses into a scratch register for GPRs. */ ++ /* GPRs can handle reg + small constant, all other addresses need to use ++ the scratch register. */ + case GENERAL_REGS: + case BASE_REGS: + if (GET_CODE (addr) == AND) +@@ -12603,70 +12609,152 @@ rs6000_secondary_reload_inner (rtx reg, + and_op2 = XEXP (addr, 1); + addr = XEXP (addr, 0); } -@@ -10960,6 +11025,18 @@ rs6000_common_init_builtins (void) - tree int_ftype_v8hi_v8hi - = build_function_type_list (integer_type_node, - V8HI_type_node, V8HI_type_node, NULL_TREE); -+ tree v2di_ftype_v2df -+ = build_function_type_list (V2DI_type_node, -+ V2DF_type_node, NULL_TREE); -+ tree v2df_ftype_v2df -+ = build_function_type_list (V2DF_type_node, -+ V2DF_type_node, NULL_TREE); -+ tree v2df_ftype_v2di -+ = build_function_type_list (V2DF_type_node, -+ V2DI_type_node, NULL_TREE); -+ tree v2df_ftype_v2df_v2df -+ = build_function_type_list (V2DF_type_node, -+ V2DF_type_node, V2DF_type_node, NULL_TREE); - tree v2df_ftype_v2df_v2df_v2df - = build_function_type_list (V2DF_type_node, - V2DF_type_node, V2DF_type_node, -@@ -11136,6 +11213,9 @@ rs6000_common_init_builtins (void) - case VOIDmode: - type = opaque_ftype_opaque_opaque; - break; -+ case V2DFmode: -+ type = v2df_ftype_v2df_v2df; -+ break; - case V4SFmode: - type = v4sf_ftype_v4sf_v4sf; - break; -@@ -11285,6 +11365,8 @@ rs6000_common_init_builtins (void) - type = v16qi_ftype_int; - else if (mode0 == VOIDmode && mode1 == VOIDmode) - type = opaque_ftype_opaque; -+ else if (mode0 == V2DFmode && mode1 == V2DFmode) -+ type = v2df_ftype_v2df; - else if (mode0 == V4SFmode && mode1 == V4SFmode) - type = v4sf_ftype_v4sf; - else if (mode0 == V8HImode && mode1 == V16QImode) -@@ -11310,6 +11392,10 @@ rs6000_common_init_builtins (void) - type = v4si_ftype_v4sf; - else if (mode0 == V4SFmode && mode1 == V4SImode) - type = v4sf_ftype_v4si; -+ else if (mode0 == V2DImode && mode1 == V2DFmode) -+ type = v2di_ftype_v2df; -+ else if (mode0 == V2DFmode && mode1 == V2DImode) -+ type = v2df_ftype_v2di; - else - gcc_unreachable (); - -@@ -12092,8 +12178,10 @@ rtx - rs6000_secondary_memory_needed_rtx (enum machine_mode mode) - { - static bool eliminated = false; -+ rtx ret; + - if (mode != SDmode) -- return assign_stack_local (mode, GET_MODE_SIZE (mode), 0); -+ ret = assign_stack_local (mode, GET_MODE_SIZE (mode), 0); - else - { - rtx mem = cfun->machine->sdmode_stack_slot; -@@ -12105,8 +12193,21 @@ rs6000_secondary_memory_needed_rtx (enum - cfun->machine->sdmode_stack_slot = mem; - eliminated = true; - } -- return mem; -+ ret = mem; -+ } -+ -+ if (TARGET_DEBUG_ADDR) -+ { -+ fprintf (stderr, "rs6000_secondary_memory_needed_rtx, mode %s, rtx:\n", -+ GET_MODE_NAME (mode)); -+ if (!ret) -+ fprintf (stderr, "\tNULL_RTX\n"); -+ else -+ debug_rtx (ret); -+ fprintf (stderr, "\n"); - } -+ -+ return ret; - } - - static tree -@@ -12140,6 +12241,54 @@ rs6000_check_sdmode (tree *tp, int *walk - return NULL_TREE; - } - -+/* Inform reload about cases where moving X with a mode MODE to a register in -+ RCLASS requires an extra scratch or immediate register. Return the class -+ needed for the immediate register. */ -+ -+static enum reg_class -+rs6000_secondary_reload (bool in_p, -+ rtx x, -+ enum reg_class rclass, -+ enum machine_mode mode, -+ secondary_reload_info *sri) -+{ -+ if (TARGET_DEBUG_ADDR) -+ { -+ fprintf (stderr, -+ "rs6000_secondary_reload, in_p = %s, rclass = %s, mode = %s\n", -+ in_p ? "true" : "false", reg_class_names[rclass], -+ GET_MODE_NAME (mode)); -+ debug_rtx (x); -+ fprintf (stderr, "\n"); -+ } -+ -+ return default_secondary_reload (in_p, x, rclass, mode, sri); -+} -+ -+/* Fixup reload addresses for Altivec or VSX loads/stores to change SP+offset -+ to SP+reg addressing. */ -+ -+void -+rs6000_vector_secondary_reload (rtx op0, rtx op1, rtx op2, bool to_mem_p) -+{ -+ rtx memref = to_mem_p ? op0 : op1; -+ gcc_assert (MEM_P (memref)); -+ -+ if (TARGET_DEBUG_ADDR) -+ { -+ fprintf (stderr, "rs6000_vector_secondary_reload, to_mem_p = %s\n", -+ to_mem_p ? "true" : "false"); -+ fprintf (stderr, "op0:\n"); -+ debug_rtx (op0); -+ fprintf (stderr, "op1:\n"); -+ debug_rtx (op1); -+ fprintf (stderr, "op2:\n"); -+ debug_rtx (op2); -+ fprintf (stderr, "\n"); -+ } -+ -+ gcc_unreachable (); -+} - - /* Allocate a 64-bit stack slot to be used for copying SDmode - values through if this function has any SDmode references. */ -@@ -12212,32 +12361,44 @@ enum reg_class - rs6000_preferred_reload_class (rtx x, enum reg_class rclass) - { - enum machine_mode mode = GET_MODE (x); -+ enum reg_class ret; - - if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode) - && VSX_REG_CLASS_P (rclass)) -- return rclass; -+ ret = rclass; - -- if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) && rclass == ALTIVEC_REGS -- && easy_vector_constant (x, mode)) -- return rclass; -+ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) -+ && rclass == ALTIVEC_REGS && easy_vector_constant (x, mode)) -+ ret = rclass; - -- if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS)) -- return NO_REGS; -+ else if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS)) -+ ret = NO_REGS; - -- if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS) -- return GENERAL_REGS; -+ else if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS) -+ ret = GENERAL_REGS; - - /* For VSX, prefer the traditional registers. */ -- if (rclass == VSX_REGS) -+ else if (rclass == VSX_REGS) - { - if (mode == DFmode) -- return FLOAT_REGS; -+ ret = FLOAT_REGS; - - if (ALTIVEC_VECTOR_MODE (mode)) -- return ALTIVEC_REGS; -+ ret = ALTIVEC_REGS; -+ } -+ else -+ ret = rclass; -+ -+ if (TARGET_DEBUG_ADDR) -+ { -+ fprintf (stderr, -+ "rs6000_preferred_reload_class, return %s, rclass = %s, x:\n", -+ reg_class_names[ret], reg_class_names[rclass]); -+ debug_rtx (x); -+ fprintf (stderr, "\n"); - } - -- return rclass; -+ return ret; - } - - /* If we are copying between FP or AltiVec registers and anything else, we need -@@ -12251,31 +12412,46 @@ rs6000_secondary_memory_needed (enum reg - enum reg_class class2, - enum machine_mode mode) - { -+ bool ret; -+ bool vsx1; -+ bool vsx2; -+ - if (class1 == class2) -- return false; -+ ret = false; - -- if (TARGET_VSX && VSX_MOVE_MODE (mode) && VSX_REG_CLASS_P (class1) -- && VSX_REG_CLASS_P (class2)) -- return false; -+ else if (TARGET_VSX && VECTOR_MEM_VSX_P (mode) -+ && ((vsx1 = VSX_REG_CLASS_P (class1)) -+ || (vsx2 = VSX_REG_CLASS_P (class2)))) -+ ret = (vsx1 != vsx2); -+ -+ else if (class1 == FLOAT_REGS -+ && (!TARGET_MFPGPR || !TARGET_POWERPC64 -+ || ((mode != DFmode) -+ && (mode != DDmode) -+ && (mode != DImode)))) -+ ret = true; -+ -+ else if (class2 == FLOAT_REGS -+ && (!TARGET_MFPGPR || !TARGET_POWERPC64 -+ || ((mode != DFmode) -+ && (mode != DDmode) -+ && (mode != DImode)))) -+ ret = true; - -- if (class1 == FLOAT_REGS -- && (!TARGET_MFPGPR || !TARGET_POWERPC64 -- || ((mode != DFmode) -- && (mode != DDmode) -- && (mode != DImode)))) -- return true; -+ else if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS) -+ ret = true; - -- if (class2 == FLOAT_REGS -- && (!TARGET_MFPGPR || !TARGET_POWERPC64 -- || ((mode != DFmode) -- && (mode != DDmode) -- && (mode != DImode)))) -- return true; -+ else -+ ret = false; - -- if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS) -- return true; -+ if (TARGET_DEBUG_ADDR) -+ fprintf (stderr, -+ "rs6000_secondary_memory_needed, return: %s, class1 = %s, " -+ "class2 = %s, mode = %s\n", -+ ret ? "true" : "false", reg_class_names[class1], -+ reg_class_names[class2], GET_MODE_NAME (mode)); - -- return false; -+ return ret; - } - - /* Return the register class of a scratch register needed to copy IN into -@@ -12287,6 +12463,7 @@ rs6000_secondary_reload_class (enum reg_ - enum machine_mode mode, - rtx in) - { -+ enum reg_class ret = NO_REGS; - int regno; - - if (TARGET_ELF || (DEFAULT_ABI == ABI_DARWIN -@@ -12307,58 +12484,75 @@ rs6000_secondary_reload_class (enum reg_ - || GET_CODE (in) == HIGH - || GET_CODE (in) == LABEL_REF - || GET_CODE (in) == CONST)) -- return BASE_REGS; -+ ret = BASE_REGS; - } - -- if (GET_CODE (in) == REG) -+ if (ret == NO_REGS) - { -- regno = REGNO (in); -- if (regno >= FIRST_PSEUDO_REGISTER) -+ if (GET_CODE (in) == REG) ++ if (GET_CODE (addr) == PRE_MODIFY) + { -+ regno = REGNO (in); -+ if (regno >= FIRST_PSEUDO_REGISTER) -+ { -+ regno = true_regnum (in); -+ if (regno >= FIRST_PSEUDO_REGISTER) -+ regno = -1; -+ } ++ scratch_or_premodify = XEXP (addr, 0); ++ gcc_assert (REG_P (scratch_or_premodify)); ++ gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS); ++ addr = XEXP (addr, 1); + } -+ else if (GET_CODE (in) == SUBREG) ++ + if (GET_CODE (addr) == PLUS + && (!rs6000_legitimate_offset_address_p (TImode, addr, true) + || and_op2 != NULL_RTX)) { - regno = true_regnum (in); - if (regno >= FIRST_PSEUDO_REGISTER) - regno = -1; +- if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST +- || GET_CODE (addr) == CONST_INT) +- rs6000_emit_move (scratch, addr, GET_MODE (addr)); +- else +- emit_insn (gen_rtx_SET (VOIDmode, scratch, addr)); +- addr = scratch; ++ addr_op1 = XEXP (addr, 0); ++ addr_op2 = XEXP (addr, 1); ++ gcc_assert (legitimate_indirect_address_p (addr_op1, true)); ++ ++ if (!REG_P (addr_op2) ++ && (GET_CODE (addr_op2) != CONST_INT ++ || !satisfies_constraint_I (addr_op2))) ++ { ++ rs6000_emit_move (scratch, addr_op2, Pmode); ++ addr_op2 = scratch; ++ } ++ ++ emit_insn (gen_rtx_SET (VOIDmode, ++ scratch_or_premodify, ++ gen_rtx_PLUS (Pmode, ++ addr_op1, ++ addr_op2))); ++ ++ addr = scratch_or_premodify; ++ scratch_or_premodify = scratch; } -- } -- else if (GET_CODE (in) == SUBREG) -- { -- regno = true_regnum (in); -- if (regno >= FIRST_PSEUDO_REGISTER) -+ else - regno = -1; -- } -- else -- regno = -1; +- else if (GET_CODE (addr) == PRE_MODIFY +- && REG_P (XEXP (addr, 0)) +- && GET_CODE (XEXP (addr, 1)) == PLUS) ++ else if (!legitimate_indirect_address_p (addr, true) ++ && !rs6000_legitimate_offset_address_p (TImode, addr, true)) + { +- emit_insn (gen_rtx_SET (VOIDmode, XEXP (addr, 0), XEXP (addr, 1))); +- addr = XEXP (addr, 0); ++ rs6000_emit_move (scratch_or_premodify, addr, Pmode); ++ addr = scratch_or_premodify; ++ scratch_or_premodify = scratch; + } + break; -- /* We can place anything into GENERAL_REGS and can put GENERAL_REGS -- into anything. */ -- if (rclass == GENERAL_REGS || rclass == BASE_REGS -- || (regno >= 0 && INT_REGNO_P (regno))) -- return NO_REGS; -- -- /* Constants, memory, and FP registers can go into FP registers. */ -- if ((regno == -1 || FP_REGNO_P (regno)) -- && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS)) -- return (mode != SDmode) ? NO_REGS : GENERAL_REGS; -- -- /* Memory, and FP/altivec registers can go into fp/altivec registers under -- VSX. */ -- if (TARGET_VSX -- && (regno == -1 || VSX_REGNO_P (regno)) -- && VSX_REG_CLASS_P (rclass)) -- return NO_REGS; -+ /* We can place anything into GENERAL_REGS and can put GENERAL_REGS -+ into anything. */ -+ if (rclass == GENERAL_REGS || rclass == BASE_REGS -+ || (regno >= 0 && INT_REGNO_P (regno))) -+ ret = NO_REGS; ++ /* Float/Altivec registers can only handle reg+reg addressing. Move ++ other addresses into a scratch register. */ ++ case FLOAT_REGS: ++ case VSX_REGS: ++ case ALTIVEC_REGS: + -+ /* Constants, memory, and FP registers can go into FP registers. */ -+ else if ((regno == -1 || FP_REGNO_P (regno)) -+ && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS)) -+ ret = (mode != SDmode) ? NO_REGS : GENERAL_REGS; -+ -+ /* Memory, and FP/altivec registers can go into fp/altivec registers under -+ VSX. */ -+ else if (TARGET_VSX -+ && (regno == -1 || VSX_REGNO_P (regno)) -+ && VSX_REG_CLASS_P (rclass)) -+ ret = NO_REGS; -+ -+ /* Memory, and AltiVec registers can go into AltiVec registers. */ -+ else if ((regno == -1 || ALTIVEC_REGNO_P (regno)) -+ && rclass == ALTIVEC_REGS) -+ ret = NO_REGS; -+ -+ /* We can copy among the CR registers. */ -+ else if ((rclass == CR_REGS || rclass == CR0_REGS) -+ && regno >= 0 && CR_REGNO_P (regno)) -+ ret = NO_REGS; -+ -+ /* Otherwise, we need GENERAL_REGS. */ -+ else -+ ret = GENERAL_REGS; -+ } + /* With float regs, we need to handle the AND ourselves, since we can't + use the Altivec instruction with an implicit AND -16. Allow scalar + loads to float registers to use reg+offset even if VSX. */ +- case FLOAT_REGS: +- case VSX_REGS: +- if (GET_CODE (addr) == AND) ++ if (GET_CODE (addr) == AND ++ && (rclass != ALTIVEC_REGS || GET_MODE_SIZE (mode) != 16)) + { + and_op2 = XEXP (addr, 1); + addr = XEXP (addr, 0); + } +- /* fall through */ -- /* Memory, and AltiVec registers can go into AltiVec registers. */ -- if ((regno == -1 || ALTIVEC_REGNO_P (regno)) -- && rclass == ALTIVEC_REGS) -- return NO_REGS; -- -- /* We can copy among the CR registers. */ -- if ((rclass == CR_REGS || rclass == CR0_REGS) -- && regno >= 0 && CR_REGNO_P (regno)) -- return NO_REGS; -+ if (TARGET_DEBUG_ADDR) +- /* Move reg+offset addresses into a scratch register. */ +- case ALTIVEC_REGS: +- if (!legitimate_indirect_address_p (addr, true) +- && !legitimate_indexed_address_p (addr, true) +- && (GET_CODE (addr) != PRE_MODIFY +- || !legitimate_indexed_address_p (XEXP (addr, 1), true)) +- && (rclass != FLOAT_REGS +- || GET_MODE_SIZE (mode) != 8 ++ /* If we aren't using a VSX load, save the PRE_MODIFY register and use it ++ as the address later. */ ++ if (GET_CODE (addr) == PRE_MODIFY ++ && (!VECTOR_MEM_VSX_P (mode) + || and_op2 != NULL_RTX +- || !rs6000_legitimate_offset_address_p (mode, addr, true))) ++ || !legitimate_indexed_address_p (XEXP (addr, 1), true))) + { +- if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST +- || GET_CODE (addr) == CONST_INT) +- rs6000_emit_move (scratch, addr, GET_MODE (addr)); +- else +- emit_insn (gen_rtx_SET (VOIDmode, scratch, addr)); +- addr = scratch; ++ scratch_or_premodify = XEXP (addr, 0); ++ gcc_assert (legitimate_indirect_address_p (scratch_or_premodify, ++ true)); ++ gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS); ++ addr = XEXP (addr, 1); ++ } ++ ++ if (legitimate_indirect_address_p (addr, true) /* reg */ ++ || legitimate_indexed_address_p (addr, true) /* reg+reg */ ++ || GET_CODE (addr) == PRE_MODIFY /* VSX pre-modify */ ++ || GET_CODE (addr) == AND /* Altivec memory */ ++ || (rclass == FLOAT_REGS /* legacy float mem */ ++ && GET_MODE_SIZE (mode) == 8 ++ && and_op2 == NULL_RTX ++ && scratch_or_premodify == scratch ++ && rs6000_legitimate_offset_address_p (mode, addr, true))) ++ ; ++ ++ else if (GET_CODE (addr) == PLUS) ++ { ++ addr_op1 = XEXP (addr, 0); ++ addr_op2 = XEXP (addr, 1); ++ gcc_assert (REG_P (addr_op1)); ++ ++ rs6000_emit_move (scratch, addr_op2, Pmode); ++ emit_insn (gen_rtx_SET (VOIDmode, ++ scratch_or_premodify, ++ gen_rtx_PLUS (Pmode, ++ addr_op1, ++ scratch))); ++ addr = scratch_or_premodify; ++ scratch_or_premodify = scratch; + } ++ ++ else if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST ++ || GET_CODE (addr) == CONST_INT) ++ { ++ rs6000_emit_move (scratch_or_premodify, addr, Pmode); ++ addr = scratch_or_premodify; ++ scratch_or_premodify = scratch; ++ } ++ ++ else ++ gcc_unreachable (); ++ + break; + + default: + gcc_unreachable (); + } + +- /* If the original address involved an AND -16 that is part of the Altivec +- addresses, recreate the and now. */ ++ /* If the original address involved a pre-modify that we couldn't use the VSX ++ memory instruction with update, and we haven't taken care of already, ++ store the address in the pre-modify register and use that as the ++ address. */ ++ if (scratch_or_premodify != scratch && scratch_or_premodify != addr) + { -+ fprintf (stderr, -+ "rs6000_secondary_reload_class, return %s, rclass = %s, " -+ "mode = %s, input rtx:\n", -+ reg_class_names[ret], reg_class_names[rclass], -+ GET_MODE_NAME (mode)); -+ debug_rtx (in); -+ fprintf (stderr, "\n"); ++ emit_insn (gen_rtx_SET (VOIDmode, scratch_or_premodify, addr)); ++ addr = scratch_or_premodify; + } - -- /* Otherwise, we need GENERAL_REGS. */ -- return GENERAL_REGS; -+ return ret; - } - - /* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */ -@@ -12368,19 +12562,29 @@ rs6000_cannot_change_mode_class (enum ma - enum machine_mode to, - enum reg_class rclass) - { -- return (GET_MODE_SIZE (from) != GET_MODE_SIZE (to) -- ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8 -- || TARGET_IEEEQUAD) -- && reg_classes_intersect_p (FLOAT_REGS, rclass)) -- : (((TARGET_E500_DOUBLE -- && ((((to) == DFmode) + ((from) == DFmode)) == 1 -- || (((to) == TFmode) + ((from) == TFmode)) == 1 -- || (((to) == DDmode) + ((from) == DDmode)) == 1 -- || (((to) == TDmode) + ((from) == TDmode)) == 1 -- || (((to) == DImode) + ((from) == DImode)) == 1)) -- || (TARGET_SPE -- && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1)) -- && reg_classes_intersect_p (GENERAL_REGS, rclass))); -+ bool ret = (GET_MODE_SIZE (from) != GET_MODE_SIZE (to) -+ ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8 -+ || TARGET_IEEEQUAD) -+ && reg_classes_intersect_p (FLOAT_REGS, rclass)) -+ : (((TARGET_E500_DOUBLE -+ && ((((to) == DFmode) + ((from) == DFmode)) == 1 -+ || (((to) == TFmode) + ((from) == TFmode)) == 1 -+ || (((to) == DDmode) + ((from) == DDmode)) == 1 -+ || (((to) == TDmode) + ((from) == TDmode)) == 1 -+ || (((to) == DImode) + ((from) == DImode)) == 1)) -+ || (TARGET_SPE -+ && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1)) -+ && reg_classes_intersect_p (GENERAL_REGS, rclass))); + -+ if (TARGET_DEBUG_ADDR) -+ fprintf (stderr, -+ "rs6000_cannot_change_mode_class, return %s, from = %s, " -+ "to = %s, rclass = %s\n", -+ ret ? "true" : "false", -+ GET_MODE_NAME (from), GET_MODE_NAME (to), -+ reg_class_names[rclass]); ++ /* If the original address involved an AND -16 and we couldn't use an ALTIVEC ++ memory instruction, recreate the AND now, including the clobber which is ++ generated by the general ANDSI3/ANDDI3 patterns for the ++ andi. instruction. */ + if (and_op2 != NULL_RTX) + { +- rtx and_rtx = gen_rtx_SET (VOIDmode, +- scratch, +- gen_rtx_AND (Pmode, addr, and_op2)); +- rtx cc_clobber = gen_rtx_CLOBBER (CCmode, gen_rtx_SCRATCH (CCmode)); ++ if (! legitimate_indirect_address_p (addr, true)) ++ { ++ emit_insn (gen_rtx_SET (VOIDmode, scratch, addr)); ++ addr = scratch; ++ } + -+ return ret; - } - - /* Given a comparison operation, return the bit number in CCR to test. We ---- gcc/config/rs6000/vsx.md (revision 144758) -+++ gcc/config/rs6000/vsx.md (revision 144843) -@@ -68,7 +68,13 @@ (define_mode_attr VSbit [(SI "32") - (DI "64")]) - - (define_constants -- [(UNSPEC_VSX_CONCAT_V2DF 500)]) -+ [(UNSPEC_VSX_CONCAT_V2DF 500) -+ (UNSPEC_VSX_XVCVDPSP 501) -+ (UNSPEC_VSX_XVCVDPSXWS 502) -+ (UNSPEC_VSX_XVCVDPUXWS 503) -+ (UNSPEC_VSX_XVCVSPDP 504) -+ (UNSPEC_VSX_XVCVSXWDP 505) -+ (UNSPEC_VSX_XVCVUXWDP 506)]) - - ;; VSX moves - (define_insn "*vsx_mov" -@@ -245,7 +251,7 @@ (define_insn "*vsx_abs2" - "xvabs %x0,%x1" - [(set_attr "type" "vecfloat")]) - --(define_insn "*vsx_nabs2" -+(define_insn "vsx_nabs2" - [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") - (neg:VSX_F - (abs:VSX_F -@@ -417,14 +423,14 @@ (define_insn "*vsx_ftrunc2" - "xvrpiz %x0,%x1" - [(set_attr "type" "vecperm")]) - --(define_insn "*vsx_float2" -+(define_insn "vsx_float2" - [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") - (float:VSX_F (match_operand: 1 "vsx_register_operand" "")))] - "VECTOR_UNIT_VSX_P (mode)" - "xvcvsx %x0,%x1" - [(set_attr "type" "vecfloat")]) - --(define_insn "*vsx_floatuns2" -+(define_insn "vsx_floatuns2" - [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") - (unsigned_float:VSX_F (match_operand: 1 "vsx_register_operand" "")))] - "VECTOR_UNIT_VSX_P (mode)" -@@ -446,6 +452,62 @@ (define_insn "*vsx_fixuns_trunc3" - (define_insn "vsx_concat_v2df" - [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") - (unspec:V2DF -- [(match_operand:DF 1 "vsx_register_operand" "f,wa") -- (match_operand:DF 2 "vsx_register_operand" "f,wa")] -+ [(match_operand:DF 1 "vsx_register_operand" "ws,wa") -+ (match_operand:DF 2 "vsx_register_operand" "ws,wa")] - UNSPEC_VSX_CONCAT_V2DF))] - "VECTOR_UNIT_VSX_P (V2DFmode)" - "xxpermdi %x0,%x1,%x2,0" -@@ -762,32 +824,37 @@ (define_insn "vsx_concat_v2df" - - ;; Set a double into one element - (define_insn "vsx_set_v2df" -- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd") -+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") - (vec_merge:V2DF -- (match_operand:V2DF 1 "vsx_register_operand" "wd") -- (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws")) -- (match_operand:QI 3 "u5bit_cint_operand" "i")))] -+ (match_operand:V2DF 1 "vsx_register_operand" "wd,wa") -+ (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws,f")) -+ (match_operand:QI 3 "u5bit_cint_operand" "i,i")))] - "VECTOR_UNIT_VSX_P (V2DFmode)" - { -- operands[3] = GEN_INT (INTVAL (operands[3]) & 1); -- return \"xxpermdi %x0,%x1,%x2,%3\"; -+ if (INTVAL (operands[3]) == 0) -+ return \"xxpermdi %x0,%x1,%x2,1\"; -+ else if (INTVAL (operands[3]) == 1) -+ return \"xxpermdi %x0,%x2,%x1,0\"; -+ else -+ gcc_unreachable (); - } - [(set_attr "type" "vecperm")]) - - ;; Extract a DF element from V2DF - (define_insn "vsx_extract_v2df" -- [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -- (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd") -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,f,?wa") -+ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd,wd,wa") - (parallel -- [(match_operand:QI 2 "u5bit_cint_operand" "i")])))] -+ [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))] - "VECTOR_UNIT_VSX_P (V2DFmode)" - { -- operands[3] = GEN_INT (INTVAL (operands[2]) & 1); -+ gcc_assert (UINTVAL (operands[2]) <= 1); -+ operands[3] = GEN_INT (INTVAL (operands[2]) << 1); - return \"xxpermdi %x0,%x1,%x1,%3\"; - } - [(set_attr "type" "vecperm")]) - --;; General V2DF permute -+;; General V2DF permute, extract_{high,low,even,odd} - (define_insn "vsx_xxpermdi" - [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd") - (vec_concat:V2DF -@@ -799,6 +866,7 @@ (define_insn "vsx_xxpermdi" - [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))] - "VECTOR_UNIT_VSX_P (V2DFmode)" - { -+ gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1)); - operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1) - | (INTVAL (operands[4]) & 1)); - return \"xxpermdi %x0,%x1,%x3,%5\"; -@@ -807,14 +875,15 @@ (define_insn "vsx_xxpermdi" - - ;; V2DF splat - (define_insn "vsx_splatv2df" -- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd") -+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,wd") - (vec_duplicate:V2DF -- (match_operand:DF 1 "input_operand" "ws,Z")))] -+ (match_operand:DF 1 "input_operand" "ws,f,Z")))] - "VECTOR_UNIT_VSX_P (V2DFmode)" - "@ - xxpermdi %x0,%x1,%x1,0 -+ xxpermdi %x0,%x1,%x1,0 - lxvdsx %x0,%y1" -- [(set_attr "type" "vecperm,vecload")]) -+ [(set_attr "type" "vecperm,vecperm,vecload")]) - - ;; V4SF splat - (define_insn "*vsx_xxspltw" -@@ -828,14 +897,14 @@ (define_insn "*vsx_xxspltw" - [(set_attr "type" "vecperm")]) - - ;; V4SF interleave --(define_insn "*vsx_xxmrghw" -- [(set (match_operand:V4SF 0 "register_operand" "=v") -- (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v") -+(define_insn "vsx_xxmrghw" -+ [(set (match_operand:V4SF 0 "register_operand" "=wf") -+ (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "wf") - (parallel [(const_int 0) - (const_int 2) - (const_int 1) - (const_int 3)])) -- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v") -+ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "wf") - (parallel [(const_int 2) - (const_int 0) - (const_int 3) -@@ -845,15 +914,15 @@ (define_insn "*vsx_xxmrghw" - "xxmrghw %x0,%x1,%x2" - [(set_attr "type" "vecperm")]) - --(define_insn "*vsx_xxmrglw" -- [(set (match_operand:V4SF 0 "register_operand" "=v") -+(define_insn "vsx_xxmrglw" -+ [(set (match_operand:V4SF 0 "register_operand" "=wf") - (vec_merge:V4SF -- (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v") -+ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "wf") - (parallel [(const_int 2) - (const_int 0) - (const_int 3) - (const_int 1)])) -- (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v") -+ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "wf") - (parallel [(const_int 0) - (const_int 2) - (const_int 1) -@@ -862,3 +931,26 @@ (define_insn "*vsx_xxmrglw" - "VECTOR_UNIT_VSX_P (V4SFmode)" - "xxmrglw %x0,%x1,%x2" - [(set_attr "type" "vecperm")]) -+ -+ -+;; Reload patterns for VSX loads/stores. We need a scratch register to convert -+;; the stack temporary address from reg+offset to reg+reg addressing. -+(define_expand "vsx_reload___to_mem" -+ [(parallel [(match_operand:VSX_L 0 "memory_operand" "") -+ (match_operand:VSX_L 1 "register_operand" "=wa") -+ (match_operand:P 2 "register_operand" "=&b")])] -+ "VECTOR_MEM_VSX_P (mode)" -+{ -+ rs6000_vector_secondary_reload (operands[0], operands[1], operands[2], true); -+ DONE; -+}) -+ -+(define_expand "vsx_reload___to_reg" -+ [(parallel [(match_operand:VSX_L 0 "register_operand" "=wa") -+ (match_operand:VSX_L 1 "memory_operand" "") -+ (match_operand:P 2 "register_operand" "=&b")])] -+ "VECTOR_MEM_VSX_P (mode)" -+{ -+ rs6000_vector_secondary_reload (operands[0], operands[1], operands[2], false); -+ DONE; -+}) ---- gcc/config/rs6000/rs6000.h (revision 144758) -+++ gcc/config/rs6000/rs6000.h (revision 144843) -@@ -3388,7 +3388,7 @@ enum rs6000_builtins - VSX_BUILTIN_XXSPLTW, - VSX_BUILTIN_XXSWAPD, - -- /* Combine VSX/Altivec builtins. */ -+ /* Combined VSX/Altivec builtins. */ - VECTOR_BUILTIN_FLOAT_V4SI_V4SF, - VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF, - VECTOR_BUILTIN_FIX_V4SF_V4SI, ---- gcc/config/rs6000/altivec.md (revision 144758) -+++ gcc/config/rs6000/altivec.md (revision 144843) -@@ -2685,3 +2685,27 @@ (define_expand "vec_unpacku_float_lo_v8h - emit_insn (gen_altivec_vcfux (operands[0], tmp, const0_rtx)); - DONE; - }") -+ -+ -+;; Reload patterns for Altivec loads/stores. We need a scratch register to -+;; convert the stack temporary address from reg+offset to reg+reg addressing. -+ -+(define_expand "altivec_reload___to_mem" -+ [(parallel [(match_operand:V 0 "memory_operand" "") -+ (match_operand:V 1 "register_operand" "=v") -+ (match_operand:P 2 "register_operand" "=&b")])] -+ "VECTOR_MEM_ALTIVEC_P (mode)" -+{ -+ rs6000_vector_secondary_reload (operands[0], operands[1], operands[2], true); -+ DONE; -+}) -+ -+(define_expand "altivec_reload___to_reg" -+ [(parallel [(match_operand:V 0 "register_operand" "=v") -+ (match_operand:V 1 "memory_operand" "") -+ (match_operand:P 2 "register_operand" "=&b")])] -+ "VECTOR_MEM_ALTIVEC_P (mode)" -+{ -+ rs6000_vector_secondary_reload (operands[0], operands[1], operands[2], false); -+ DONE; -+}) ---- gcc/config/rs6000/rs6000.md (revision 144758) -+++ gcc/config/rs6000/rs6000.md (revision 144843) -@@ -222,6 +222,10 @@ (define_mode_attr dbits [(QI "56") (HI " - ;; ISEL/ISEL64 target selection - (define_mode_attr sel [(SI "") (DI "64")]) - -+;; Suffix for reload patterns -+(define_mode_attr ptrsize [(SI "32bit") -+ (DI "64bit")]) -+ - - ;; Start with fixed-point load and store insns. Here we put only the more - ;; complex forms. Basic data transfer is done later. ---- gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c (revision 144843) -@@ -0,0 +1,29 @@ -+/* { dg-do compile { target { powerpc*-*-* } } } */ -+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ -+/* { dg-require-effective-target powerpc_vsx_ok } */ -+/* { dg-options "-O2 -mcpu=power7" } */ -+/* { dg-final { scan-assembler "xvaddsp" } } */ -+/* { dg-final { scan-assembler "xvsubsp" } } */ -+/* { dg-final { scan-assembler "xvmulsp" } } */ -+/* { dg-final { scan-assembler "xvdivsp" } } */ -+/* { dg-final { scan-assembler "xvmaxsp" } } */ -+/* { dg-final { scan-assembler "xvminsp" } } */ -+/* { dg-final { scan-assembler "xvsqrtsp" } } */ -+/* { dg-final { scan-assembler "xvabssp" } } */ -+/* { dg-final { scan-assembler "xvnabssp" } } */ -+ -+void use_builtins (__vector float *p, __vector float *q, __vector float *r) -+{ -+ __vector float tmp1 = *q; -+ __vector float tmp2 = *r; -+ -+ *p++ = __builtin_vsx_xvaddsp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvsubsp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvmulsp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvdivsp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvmaxsp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvminsp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvabssp (tmp1); -+ *p++ = __builtin_vsx_xvnabssp (tmp1); -+ *p = __builtin_vsx_xvsqrtsp (tmp1); -+} ---- gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c (revision 144843) -@@ -0,0 +1,29 @@ -+/* { dg-do compile { target { powerpc*-*-* } } } */ -+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ -+/* { dg-require-effective-target powerpc_vsx_ok } */ -+/* { dg-options "-O2 -mcpu=power7" } */ -+/* { dg-final { scan-assembler "xvadddp" } } */ -+/* { dg-final { scan-assembler "xvsubdp" } } */ -+/* { dg-final { scan-assembler "xvmuldp" } } */ -+/* { dg-final { scan-assembler "xvdivdp" } } */ -+/* { dg-final { scan-assembler "xvmaxdp" } } */ -+/* { dg-final { scan-assembler "xvmindp" } } */ -+/* { dg-final { scan-assembler "xvsqrtdp" } } */ -+/* { dg-final { scan-assembler "xvabsdp" } } */ -+/* { dg-final { scan-assembler "xvnabsdp" } } */ -+ -+void use_builtins (__vector double *p, __vector double *q, __vector double *r) -+{ -+ __vector double tmp1 = *q; -+ __vector double tmp2 = *r; -+ -+ *p++ = __builtin_vsx_xvadddp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvsubdp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvmuldp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvdivdp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvmaxdp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvmindp (tmp1, tmp2); -+ *p++ = __builtin_vsx_xvabsdp (tmp1); -+ *p++ = __builtin_vsx_xvnabsdp (tmp1); -+ *p = __builtin_vsx_xvsqrtdp (tmp1); -+} ---- gcc/testsuite/gcc.target/powerpc/pr39457.c (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/pr39457.c (revision 144857) -@@ -0,0 +1,56 @@ -+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ -+/* { dg-options "-m64 -O2 -mminimal-toc" } */ -+ -+/* PR 39457 -- fix breakage because the compiler ran out of registers and -+ wanted to stash a floating point value to the LR/CTR register. */ -+ -+/* -O2 -m64 -mminimal-toc */ -+typedef struct { void *s; } S; -+typedef void (*T1) (void); -+typedef void (*T2) (void *, void *, int, void *); -+char *fn1 (const char *, ...); -+void *fn2 (void); -+int fn3 (char *, int); -+int fn4 (const void *); -+int fn5 (const void *); -+long fn6 (void) __attribute__ ((__const__)); -+int fn7 (void *, void *, void *); -+void *fn8 (void *, long); -+void *fn9 (void *, long, const char *, ...); -+void *fn10 (void *); -+long fn11 (void) __attribute__ ((__const__)); -+long fn12 (void *, const char *, T1, T2, void *); -+void *fn13 (void *); -+long fn14 (void) __attribute__ ((__const__)); -+extern void *v1; -+extern char *v2; -+extern int v3; -+ -+void -+foo (void *x, char *z) -+{ -+ void *i1, *i2; -+ int y; -+ if (v1) -+ return; -+ v1 = fn9 (fn10 (fn2 ()), fn6 (), "x", 0., "y", 0., 0); -+ y = 520 - (520 - fn4 (x)) / 2; -+ fn9 (fn8 (v1, fn6 ()), fn6 (), "wig", fn8 (v1, fn14 ()), "x", 18.0, -+ "y", 16.0, "wid", 80.0, "hi", 500.0, 0); -+ fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 80.0, "y2", -+ 500.0, "f", fn3 ("fff", 0x0D0DFA00), 0); -+ fn13 (((S *) fn8 (v1, fn6 ()))->s); -+ fn12 (fn8 (v1, fn11 ()), "ev", (T1) fn7, 0, fn8 (v1, fn6 ())); -+ fn9 (fn8 (v1, fn6 ()), fn6 (), "wig", -+ fn8 (v1, fn14 ()), "x", 111.0, "y", 14.0, "wid", 774.0, "hi", -+ 500.0, 0); -+ v1 = fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 774.0, "y2", -+ 500.0, "f", fn3 ("gc", 0x0D0DFA00), 0); -+ fn1 (z, 0); -+ i1 = fn9 (fn8 (v1, fn6 ()), fn6 (), "pixbuf", x, "x", -+ 800 - fn5 (x) / 2, "y", y - fn4 (x), 0); -+ fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, "/ok/"); -+ fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, 0); -+ i2 = fn9 (fn8 (v1, fn6 ()), fn6 (), "txt", "OK", "fnt", v2, "x", -+ 800, "y", y - fn4 (x) + 15, "ar", 0, "f", v3, 0); -+} ++ cc_clobber = gen_rtx_CLOBBER (CCmode, gen_rtx_SCRATCH (CCmode)); + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, and_rtx, cc_clobber))); + addr = scratch; diff --git a/gcc44-power7-3.patch b/gcc44-power7-3.patch new file mode 100644 index 0000000..3dd8afe --- /dev/null +++ b/gcc44-power7-3.patch @@ -0,0 +1,3523 @@ +2009-04-26 Michael Meissner + + * config/rs6000/vector.md (vector_vsel): Generate the insns + directly instead of calling VSX/Altivec expanders. + + * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Map VSX + builtins that are identical to Altivec, to the Altivec vesion. + (altivec_overloaded_builtins): Add V2DF/V2DI sel, perm support. + (altivec_resolve_overloaded_builtin): Add V2DF/V2DI support. + + * config/rs6000/rs6000.c (rs6000_expand_vector_init): Rename VSX + splat functions. + (expand_vector_set): Merge V2DF/V2DI code. + (expand_vector_extract): Ditto. + (bdesc_3arg): Add more VSX builtins. + (bdesc_2arg): Ditto. + (bdesc_1arg): Ditto. + (rs6000_expand_ternop_builtin): Require xxpermdi 3rd argument to + be 2 bit-constant, and V2DF/V2DI set to be a 1 bit-constant. + (altivec_expand_builtin): Add support for VSX overloaded builtins. + (altivec_init_builtins): Ditto. + (rs6000_common_init_builtins): Ditto. + (rs6000_init_builtins): Add V2DI types and vector long support. + (rs6000_handle_altivec_attribute): Ditto. + (rs6000_mange_type): Ditto. + + * config/rs6000/vsx.md (UNSPEC_*): Add new UNSPEC constants. + (vsx_vsel): Add support for all vector types, including + Altivec types. + (vsx_ftrunc2): Emit the correct instruction. + (vsx_xri): New builtin rounding mode insns. + (vsx_xric): Ditto. + (vsx_concat_): Key off of VSX memory instructions being + generated instead of the vector arithmetic unit to enable V2DI + mode. + (vsx_extract_): Ditto. + (vsx_set_): Rewrite as an unspec. + (vsx_xxpermdi2_): Rename old vsx_xxpermdi_ here. Key + off of VSX memory instructions instead of arithmetic unit. + (vsx_xxpermdi_): New insn for __builtin_vsx_xxpermdi. + (vsx_splat_): Rename from vsx_splat. + (vsx_xxspltw_): Change from V4SF only to V4SF/V4SI modes. + Fix up constraints. Key off of memory instructions instead of + arithmetic instructions to allow use with V4SI. + (vsx_xxmrghw_): Ditto. + (vsx_xxmrglw_): Ditto. + (vsx_xxsldwi_): Implement vector shift double by word + immediate. + + * config/rs6000/rs6000.h (VSX_BUILTIN_*): Update for current + builtins being generated. + (RS6000_BTI_unsigned_V2DI): Add vector long support. + (RS6000_BTI_bool_long): Ditto. + (RS6000_BTI_bool_V2DI): Ditto. + (unsigned_V2DI_type_node): Ditto. + (bool_long_type_node): Ditto. + (bool_V2DI_type_node): Ditto. + + * config/rs6000/altivec.md (altivec_vsel): Add '*' since we + don't need the generator function now. Use VSX instruction if + -mvsx. + (altivec_vmrghw): Use VSX instruction if -mvsx. + (altivec_vmrghsf): Ditto. + (altivec_vmrglw): Ditto. + (altivec_vmrglsf): Ditto. + + * doc/extend.texi (PowerPC AltiVec/VSX Built-in Functions): + Document that under VSX, vector double/long are available. + +testsuite/ + * gcc.target/powerpc/vsx-builtin-3.c: New test for VSX builtins. + +2009-04-23 Michael Meissner + + * config/rs6000/vector.md (VEC_E): New iterator to add V2DImode. + (vec_init): Use VEC_E instead of VEC_C iterator, to add + V2DImode support. + (vec_set): Ditto. + (vec_extract): Ditto. + + * config/rs6000/predicates.md (easy_vector_constant): Add support + for setting TImode to 0. + + * config/rs6000/rs6000.opt (-mvsx-vector-memory): Delete old debug + switch that is no longer used. + (-mvsx-vector-float): Ditto. + (-mvsx-vector-double): Ditto. + (-mvsx-v4sf-altivec-regs): Ditto. + (-mreload-functions): Ditto. + (-mallow-timode): New debug switch. + + * config/rs6000/rs6000.c (rs6000_ira_cover_classes): New target + hook for IRA cover classes, to know that under VSX the float and + altivec registers are part of the same register class, but before + they weren't. + (TARGET_IRA_COVER_CLASSES): Set ira cover classes target hookd. + (rs6000_hard_regno_nregs): Key off of whether VSX/Altivec memory + instructions are supported, and not whether the vector unit has + arithmetic support to enable V2DI/TI mode. + (rs6000_hard_regno_mode_ok): Ditto. + (rs6000_init_hard_regno_mode_ok): Add V2DImode, TImode support. + Drop several of the debug switches. + (rs6000_emit_move): Force TImode constants to memory if we have + either Altivec or VSX. + (rs6000_builtin_conversion): Use correct insns for V2DI<->V2DF + conversions. + (rs6000_expand_vector_init): Add V2DI support. + (rs6000_expand_vector_set): Ditto. + (avoiding_indexed_address_p): Simplify tests to say if the mode + uses VSX/Altivec memory instructions we can't eliminate reg+reg + addressing. + (rs6000_legitimize_address): Move VSX/Altivec REG+REG support + before the large integer support. + (rs6000_legitimate_address): Add support for TImode in VSX/Altivec + registers. + (rs6000_emit_move): Ditto. + (def_builtin): Change internal error message to provide more + information. + (bdesc_2arg): Add conversion builtins. + (builtin_hash_function): New function for hashing all of the types + for builtin functions. + (builtin_hash_eq): Ditto. + (builtin_function_type): Ditto. + (builtin_mode_to_type): New static for builtin argument hashing. + (builtin_hash_table): Ditto. + (rs6000_common_init_builtins): Rewrite so that types for builtin + functions are only created when we need them, and use a hash table + to store all of the different argument combinations that are + created. Add support for VSX conversion builtins. + (rs6000_preferred_reload_class): Add TImode support. + (reg_classes_cannot_change_mode_class): Be stricter about VSX and + Altivec vector types. + (rs6000_emit_vector_cond_expr): Use VSX_MOVE_MODE, not + VSX_VECTOR_MOVE_MODE. + (rs6000_handle_altivec_attribute): Allow __vector long on VSX. + + * config/rs6000/vsx.md (VSX_D): New iterator for vectors with + 64-bit elements. + (VSX_M): New iterator for 128 bit types for moves, except for + TImode. + (VSm, VSs, VSr): Add TImode. + (VSr4, VSr5): New mode attributes for float<->double conversion. + (VSX_SPDP): New iterator for float<->double conversion. + (VS_spdp_*): New mode attributes for float<->double conversion. + (UNSPEC_VSX_*): Rename unspec constants to remove XV from the + names. Change all users. + (vsx_mov): Drop TImode support here. + (vsx_movti): New TImode support, allow GPRs, but favor VSX + registers. + (vsx_): New support for float<->double conversions. + (vsx_xvcvdpsp): Delete, move into vsx_. + (vsx_xvcvspdp): Ditto. + (vsx_xvcvuxdsp): New conversion insn. + (vsx_xvcvspsxds): Ditto. + (vsx_xvcvspuxds): Ditto. + (vsx_concat_): Generalize V2DF permute/splat operations to + include V2DI. + (vsx_set_): Ditto. + (vsx_extract_): Ditto. + (vsx_xxpermdi_): Ditto. + (vsx_splat): Ditto. + + * config/rs6000/rs6000.h (VSX_VECTOR_MOVE_MODE): Delete. + (VSX_MOVE_MODE): Add TImode. + (IRA_COVER_CLASSES): Delete. + (IRA_COVER_CLASSES_PRE_VSX): New cover classes for machines + without VSX where float and altivec are different registers. + (IRA_COVER_CLASS_VSX): New cover classes for machines with VSX + where float and altivec are part of the same register class. + + * config/rs6000/altivec.md (VM2): New iterator for 128-bit types, + except TImode. + (altivec_mov): Drop movti mode here. + (altivec_movti): Add movti insn, and allow GPRs, but favor altivec + registers. + +2009-04-16 Michael Meissner + + * config/rs6000/rs6000-protos.h (rs6000_has_indirect_jump_p): New + declaration. + (rs6000_set_indirect_jump): Ditto. + + * config/rs6000/rs6000.c (struct machine_function): Add + indirect_jump_p field. + (rs6000_override_options): Wrap warning messages in N_(). If + -mvsx was implicitly set, don't give a warning for -msoft-float, + just silently turn off vsx. + (rs6000_secondary_reload_inner): Don't use strict register + checking, since pseudos may still be present. + (register_move_cost): If -mdebug=cost, print out cost information. + (rs6000_memory_move_cost): Ditto. + (rs6000_has_indirect_jump_p): New function, return true if + current function has an indirect jump. + (rs6000_set_indirect_jump): New function, note that an indirect + jump has been generated. + + * config/rs6000/rs6000.md (indirect_jump): Note that we've + generated an indirect jump. + (tablejump): Ditto. + (doloop_end): Do not generate decrement ctr and branch + instructions if an indirect jump has been generated. + +--- gcc/doc/extend.texi (revision 146119) ++++ gcc/doc/extend.texi (revision 146798) +@@ -7094,7 +7094,7 @@ instructions, but allow the compiler to + * MIPS Loongson Built-in Functions:: + * Other MIPS Built-in Functions:: + * picoChip Built-in Functions:: +-* PowerPC AltiVec Built-in Functions:: ++* PowerPC AltiVec/VSX Built-in Functions:: + * SPARC VIS Built-in Functions:: + * SPU Built-in Functions:: + @end menu +@@ -9571,7 +9571,7 @@ GCC defines the preprocessor macro @code + when this function is available. + @end table + +-@node PowerPC AltiVec Built-in Functions ++@node PowerPC AltiVec/VSX Built-in Functions + @subsection PowerPC AltiVec Built-in Functions + + GCC provides an interface for the PowerPC family of processors to access +@@ -9597,6 +9597,19 @@ vector bool int + vector float + @end smallexample + ++If @option{-mvsx} is used the following additional vector types are ++implemented. ++ ++@smallexample ++vector unsigned long ++vector signed long ++vector double ++@end smallexample ++ ++The long types are only implemented for 64-bit code generation, and ++the long type is only used in the floating point/integer conversion ++instructions. ++ + GCC's implementation of the high-level language interface available from + C and C++ code differs from Motorola's documentation in several ways. + +--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c (revision 0) ++++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c (revision 146798) +@@ -0,0 +1,212 @@ ++/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ ++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ ++/* { dg-require-effective-target powerpc_vsx_ok } */ ++/* { dg-options "-O2 -mcpu=power7" } */ ++/* { dg-final { scan-assembler "xxsel" } } */ ++/* { dg-final { scan-assembler "vperm" } } */ ++/* { dg-final { scan-assembler "xvrdpi" } } */ ++/* { dg-final { scan-assembler "xvrdpic" } } */ ++/* { dg-final { scan-assembler "xvrdpim" } } */ ++/* { dg-final { scan-assembler "xvrdpip" } } */ ++/* { dg-final { scan-assembler "xvrdpiz" } } */ ++/* { dg-final { scan-assembler "xvrspi" } } */ ++/* { dg-final { scan-assembler "xvrspic" } } */ ++/* { dg-final { scan-assembler "xvrspim" } } */ ++/* { dg-final { scan-assembler "xvrspip" } } */ ++/* { dg-final { scan-assembler "xvrspiz" } } */ ++/* { dg-final { scan-assembler "xsrdpi" } } */ ++/* { dg-final { scan-assembler "xsrdpic" } } */ ++/* { dg-final { scan-assembler "xsrdpim" } } */ ++/* { dg-final { scan-assembler "xsrdpip" } } */ ++/* { dg-final { scan-assembler "xsrdpiz" } } */ ++/* { dg-final { scan-assembler "xsmaxdp" } } */ ++/* { dg-final { scan-assembler "xsmindp" } } */ ++/* { dg-final { scan-assembler "xxland" } } */ ++/* { dg-final { scan-assembler "xxlandc" } } */ ++/* { dg-final { scan-assembler "xxlnor" } } */ ++/* { dg-final { scan-assembler "xxlor" } } */ ++/* { dg-final { scan-assembler "xxlxor" } } */ ++/* { dg-final { scan-assembler "xvcmpeqdp" } } */ ++/* { dg-final { scan-assembler "xvcmpgtdp" } } */ ++/* { dg-final { scan-assembler "xvcmpgedp" } } */ ++/* { dg-final { scan-assembler "xvcmpeqsp" } } */ ++/* { dg-final { scan-assembler "xvcmpgtsp" } } */ ++/* { dg-final { scan-assembler "xvcmpgesp" } } */ ++/* { dg-final { scan-assembler "xxsldwi" } } */ ++/* { dg-final { scan-assembler-not "call" } } */ ++ ++extern __vector int si[][4]; ++extern __vector short ss[][4]; ++extern __vector signed char sc[][4]; ++extern __vector float f[][4]; ++extern __vector unsigned int ui[][4]; ++extern __vector unsigned short us[][4]; ++extern __vector unsigned char uc[][4]; ++extern __vector __bool int bi[][4]; ++extern __vector __bool short bs[][4]; ++extern __vector __bool char bc[][4]; ++extern __vector __pixel p[][4]; ++#ifdef __VSX__ ++extern __vector double d[][4]; ++extern __vector long sl[][4]; ++extern __vector unsigned long ul[][4]; ++extern __vector __bool long bl[][4]; ++#endif ++ ++int do_sel(void) ++{ ++ int i = 0; ++ ++ si[i][0] = __builtin_vsx_xxsel_4si (si[i][1], si[i][2], si[i][3]); i++; ++ ss[i][0] = __builtin_vsx_xxsel_8hi (ss[i][1], ss[i][2], ss[i][3]); i++; ++ sc[i][0] = __builtin_vsx_xxsel_16qi (sc[i][1], sc[i][2], sc[i][3]); i++; ++ f[i][0] = __builtin_vsx_xxsel_4sf (f[i][1], f[i][2], f[i][3]); i++; ++ d[i][0] = __builtin_vsx_xxsel_2df (d[i][1], d[i][2], d[i][3]); i++; ++ ++ si[i][0] = __builtin_vsx_xxsel (si[i][1], si[i][2], bi[i][3]); i++; ++ ss[i][0] = __builtin_vsx_xxsel (ss[i][1], ss[i][2], bs[i][3]); i++; ++ sc[i][0] = __builtin_vsx_xxsel (sc[i][1], sc[i][2], bc[i][3]); i++; ++ f[i][0] = __builtin_vsx_xxsel (f[i][1], f[i][2], bi[i][3]); i++; ++ d[i][0] = __builtin_vsx_xxsel (d[i][1], d[i][2], bl[i][3]); i++; ++ ++ si[i][0] = __builtin_vsx_xxsel (si[i][1], si[i][2], ui[i][3]); i++; ++ ss[i][0] = __builtin_vsx_xxsel (ss[i][1], ss[i][2], us[i][3]); i++; ++ sc[i][0] = __builtin_vsx_xxsel (sc[i][1], sc[i][2], uc[i][3]); i++; ++ f[i][0] = __builtin_vsx_xxsel (f[i][1], f[i][2], ui[i][3]); i++; ++ d[i][0] = __builtin_vsx_xxsel (d[i][1], d[i][2], ul[i][3]); i++; ++ ++ return i; ++} ++ ++int do_perm(void) ++{ ++ int i = 0; ++ ++ si[i][0] = __builtin_vsx_vperm_4si (si[i][1], si[i][2], sc[i][3]); i++; ++ ss[i][0] = __builtin_vsx_vperm_8hi (ss[i][1], ss[i][2], sc[i][3]); i++; ++ sc[i][0] = __builtin_vsx_vperm_16qi (sc[i][1], sc[i][2], sc[i][3]); i++; ++ f[i][0] = __builtin_vsx_vperm_4sf (f[i][1], f[i][2], sc[i][3]); i++; ++ d[i][0] = __builtin_vsx_vperm_2df (d[i][1], d[i][2], sc[i][3]); i++; ++ ++ si[i][0] = __builtin_vsx_vperm (si[i][1], si[i][2], uc[i][3]); i++; ++ ss[i][0] = __builtin_vsx_vperm (ss[i][1], ss[i][2], uc[i][3]); i++; ++ sc[i][0] = __builtin_vsx_vperm (sc[i][1], sc[i][2], uc[i][3]); i++; ++ f[i][0] = __builtin_vsx_vperm (f[i][1], f[i][2], uc[i][3]); i++; ++ d[i][0] = __builtin_vsx_vperm (d[i][1], d[i][2], uc[i][3]); i++; ++ ++ return i; ++} ++ ++int do_xxperm (void) ++{ ++ int i = 0; ++ ++ d[i][0] = __builtin_vsx_xxpermdi_2df (d[i][1], d[i][2], 0); i++; ++ d[i][0] = __builtin_vsx_xxpermdi (d[i][1], d[i][2], 1); i++; ++ return i; ++} ++ ++double x, y; ++void do_concat (void) ++{ ++ d[0][0] = __builtin_vsx_concat_2df (x, y); ++} ++ ++void do_set (void) ++{ ++ d[0][0] = __builtin_vsx_set_2df (d[0][1], x, 0); ++ d[1][0] = __builtin_vsx_set_2df (d[1][1], y, 1); ++} ++ ++extern double z[][4]; ++ ++int do_math (void) ++{ ++ int i = 0; ++ ++ d[i][0] = __builtin_vsx_xvrdpi (d[i][1]); i++; ++ d[i][0] = __builtin_vsx_xvrdpic (d[i][1]); i++; ++ d[i][0] = __builtin_vsx_xvrdpim (d[i][1]); i++; ++ d[i][0] = __builtin_vsx_xvrdpip (d[i][1]); i++; ++ d[i][0] = __builtin_vsx_xvrdpiz (d[i][1]); i++; ++ ++ f[i][0] = __builtin_vsx_xvrspi (f[i][1]); i++; ++ f[i][0] = __builtin_vsx_xvrspic (f[i][1]); i++; ++ f[i][0] = __builtin_vsx_xvrspim (f[i][1]); i++; ++ f[i][0] = __builtin_vsx_xvrspip (f[i][1]); i++; ++ f[i][0] = __builtin_vsx_xvrspiz (f[i][1]); i++; ++ ++ z[i][0] = __builtin_vsx_xsrdpi (z[i][1]); i++; ++ z[i][0] = __builtin_vsx_xsrdpic (z[i][1]); i++; ++ z[i][0] = __builtin_vsx_xsrdpim (z[i][1]); i++; ++ z[i][0] = __builtin_vsx_xsrdpip (z[i][1]); i++; ++ z[i][0] = __builtin_vsx_xsrdpiz (z[i][1]); i++; ++ z[i][0] = __builtin_vsx_xsmaxdp (z[i][1], z[i][0]); i++; ++ z[i][0] = __builtin_vsx_xsmindp (z[i][1], z[i][0]); i++; ++ return i; ++} ++ ++int do_cmp (void) ++{ ++ int i = 0; ++ ++ d[i][0] = __builtin_vsx_xvcmpeqdp (d[i][1], d[i][2]); i++; ++ d[i][0] = __builtin_vsx_xvcmpgtdp (d[i][1], d[i][2]); i++; ++ d[i][0] = __builtin_vsx_xvcmpgedp (d[i][1], d[i][2]); i++; ++ ++ f[i][0] = __builtin_vsx_xvcmpeqsp (f[i][1], f[i][2]); i++; ++ f[i][0] = __builtin_vsx_xvcmpgtsp (f[i][1], f[i][2]); i++; ++ f[i][0] = __builtin_vsx_xvcmpgesp (f[i][1], f[i][2]); i++; ++ return i; ++} ++ ++int do_logical (void) ++{ ++ int i = 0; ++ ++ si[i][0] = __builtin_vsx_xxland (si[i][1], si[i][2]); i++; ++ si[i][0] = __builtin_vsx_xxlandc (si[i][1], si[i][2]); i++; ++ si[i][0] = __builtin_vsx_xxlnor (si[i][1], si[i][2]); i++; ++ si[i][0] = __builtin_vsx_xxlor (si[i][1], si[i][2]); i++; ++ si[i][0] = __builtin_vsx_xxlxor (si[i][1], si[i][2]); i++; ++ ++ ss[i][0] = __builtin_vsx_xxland (ss[i][1], ss[i][2]); i++; ++ ss[i][0] = __builtin_vsx_xxlandc (ss[i][1], ss[i][2]); i++; ++ ss[i][0] = __builtin_vsx_xxlnor (ss[i][1], ss[i][2]); i++; ++ ss[i][0] = __builtin_vsx_xxlor (ss[i][1], ss[i][2]); i++; ++ ss[i][0] = __builtin_vsx_xxlxor (ss[i][1], ss[i][2]); i++; ++ ++ sc[i][0] = __builtin_vsx_xxland (sc[i][1], sc[i][2]); i++; ++ sc[i][0] = __builtin_vsx_xxlandc (sc[i][1], sc[i][2]); i++; ++ sc[i][0] = __builtin_vsx_xxlnor (sc[i][1], sc[i][2]); i++; ++ sc[i][0] = __builtin_vsx_xxlor (sc[i][1], sc[i][2]); i++; ++ sc[i][0] = __builtin_vsx_xxlxor (sc[i][1], sc[i][2]); i++; ++ ++ d[i][0] = __builtin_vsx_xxland (d[i][1], d[i][2]); i++; ++ d[i][0] = __builtin_vsx_xxlandc (d[i][1], d[i][2]); i++; ++ d[i][0] = __builtin_vsx_xxlnor (d[i][1], d[i][2]); i++; ++ d[i][0] = __builtin_vsx_xxlor (d[i][1], d[i][2]); i++; ++ d[i][0] = __builtin_vsx_xxlxor (d[i][1], d[i][2]); i++; ++ ++ f[i][0] = __builtin_vsx_xxland (f[i][1], f[i][2]); i++; ++ f[i][0] = __builtin_vsx_xxlandc (f[i][1], f[i][2]); i++; ++ f[i][0] = __builtin_vsx_xxlnor (f[i][1], f[i][2]); i++; ++ f[i][0] = __builtin_vsx_xxlor (f[i][1], f[i][2]); i++; ++ f[i][0] = __builtin_vsx_xxlxor (f[i][1], f[i][2]); i++; ++ return i; ++} ++ ++int do_xxsldwi (void) ++{ ++ int i = 0; ++ ++ si[i][0] = __builtin_vsx_xxsldwi (si[i][1], si[i][2], 0); i++; ++ ss[i][0] = __builtin_vsx_xxsldwi (ss[i][1], ss[i][2], 1); i++; ++ sc[i][0] = __builtin_vsx_xxsldwi (sc[i][1], sc[i][2], 2); i++; ++ ui[i][0] = __builtin_vsx_xxsldwi (ui[i][1], ui[i][2], 3); i++; ++ us[i][0] = __builtin_vsx_xxsldwi (us[i][1], us[i][2], 0); i++; ++ uc[i][0] = __builtin_vsx_xxsldwi (uc[i][1], uc[i][2], 1); i++; ++ f[i][0] = __builtin_vsx_xxsldwi (f[i][1], f[i][2], 2); i++; ++ d[i][0] = __builtin_vsx_xxsldwi (d[i][1], d[i][2], 3); i++; ++ return i; ++} +--- gcc/config/rs6000/vector.md (revision 146119) ++++ gcc/config/rs6000/vector.md (revision 146798) +@@ -39,6 +39,9 @@ (define_mode_iterator VEC_M [V16QI V8HI + ;; Vector comparison modes + (define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF]) + ++;; Vector init/extract modes ++(define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF]) ++ + ;; Vector reload iterator + (define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF DF TI]) + +@@ -347,34 +350,13 @@ (define_expand "vector_geu" + ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask + ;; which is in the reverse order that we want + (define_expand "vector_vsel" +- [(match_operand:VEC_F 0 "vlogical_operand" "") +- (match_operand:VEC_F 1 "vlogical_operand" "") +- (match_operand:VEC_F 2 "vlogical_operand" "") +- (match_operand:VEC_F 3 "vlogical_operand" "")] ++ [(set (match_operand:VEC_L 0 "vlogical_operand" "") ++ (if_then_else:VEC_L (ne (match_operand:VEC_L 3 "vlogical_operand" "") ++ (const_int 0)) ++ (match_operand:VEC_L 2 "vlogical_operand" "") ++ (match_operand:VEC_L 1 "vlogical_operand" "")))] + "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" +- " +-{ +- if (VECTOR_UNIT_VSX_P (mode)) +- emit_insn (gen_vsx_vsel (operands[0], operands[3], +- operands[2], operands[1])); +- else +- emit_insn (gen_altivec_vsel (operands[0], operands[3], +- operands[2], operands[1])); +- DONE; +-}") +- +-(define_expand "vector_vsel" +- [(match_operand:VEC_I 0 "vlogical_operand" "") +- (match_operand:VEC_I 1 "vlogical_operand" "") +- (match_operand:VEC_I 2 "vlogical_operand" "") +- (match_operand:VEC_I 3 "vlogical_operand" "")] +- "VECTOR_UNIT_ALTIVEC_P (mode)" +- " +-{ +- emit_insn (gen_altivec_vsel (operands[0], operands[3], +- operands[2], operands[1])); +- DONE; +-}") ++ "") + + + ;; Vector logical instructions +@@ -475,19 +457,23 @@ (define_expand "fixuns_trunc" +- [(match_operand:VEC_C 0 "vlogical_operand" "") +- (match_operand:VEC_C 1 "vec_init_operand" "")] +- "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" ++ [(match_operand:VEC_E 0 "vlogical_operand" "") ++ (match_operand:VEC_E 1 "vec_init_operand" "")] ++ "(mode == V2DImode ++ ? VECTOR_MEM_VSX_P (V2DImode) ++ : VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))" + { + rs6000_expand_vector_init (operands[0], operands[1]); + DONE; + }) + + (define_expand "vec_set" +- [(match_operand:VEC_C 0 "vlogical_operand" "") ++ [(match_operand:VEC_E 0 "vlogical_operand" "") + (match_operand: 1 "register_operand" "") + (match_operand 2 "const_int_operand" "")] +- "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" ++ "(mode == V2DImode ++ ? VECTOR_MEM_VSX_P (V2DImode) ++ : VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))" + { + rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2])); + DONE; +@@ -495,9 +481,11 @@ (define_expand "vec_set" + + (define_expand "vec_extract" + [(match_operand: 0 "register_operand" "") +- (match_operand:VEC_C 1 "vlogical_operand" "") ++ (match_operand:VEC_E 1 "vlogical_operand" "") + (match_operand 2 "const_int_operand" "")] +- "VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)" ++ "(mode == V2DImode ++ ? VECTOR_MEM_VSX_P (V2DImode) ++ : VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))" + { + rs6000_expand_vector_extract (operands[0], operands[1], + INTVAL (operands[2])); +--- gcc/config/rs6000/predicates.md (revision 146119) ++++ gcc/config/rs6000/predicates.md (revision 146798) +@@ -327,6 +327,9 @@ (define_predicate "easy_vector_constant" + if (TARGET_PAIRED_FLOAT) + return false; + ++ if ((VSX_VECTOR_MODE (mode) || mode == TImode) && zero_constant (op, mode)) ++ return true; ++ + if (ALTIVEC_VECTOR_MODE (mode)) + { + if (zero_constant (op, mode)) +--- gcc/config/rs6000/rs6000-protos.h (revision 146119) ++++ gcc/config/rs6000/rs6000-protos.h (revision 146798) +@@ -176,6 +176,8 @@ extern int rs6000_register_move_cost (en + enum reg_class, enum reg_class); + extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int); + extern bool rs6000_tls_referenced_p (rtx); ++extern bool rs6000_has_indirect_jump_p (void); ++extern void rs6000_set_indirect_jump (void); + extern void rs6000_conditional_register_usage (void); + + /* Declare functions in rs6000-c.c */ +--- gcc/config/rs6000/rs6000-c.c (revision 146119) ++++ gcc/config/rs6000/rs6000-c.c (revision 146798) +@@ -336,7 +336,20 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi + if (TARGET_NO_LWSYNC) + builtin_define ("__NO_LWSYNC__"); + if (TARGET_VSX) +- builtin_define ("__VSX__"); ++ { ++ builtin_define ("__VSX__"); ++ ++ /* For the VSX builtin functions identical to Altivec functions, just map ++ the altivec builtin into the vsx version (the altivec functions ++ generate VSX code if -mvsx). */ ++ builtin_define ("__builtin_vsx_xxland=__builtin_vec_and"); ++ builtin_define ("__builtin_vsx_xxlandc=__builtin_vec_andc"); ++ builtin_define ("__builtin_vsx_xxlnor=__builtin_vec_nor"); ++ builtin_define ("__builtin_vsx_xxlor=__builtin_vec_or"); ++ builtin_define ("__builtin_vsx_xxlxor=__builtin_vec_xor"); ++ builtin_define ("__builtin_vsx_xxsel=__builtin_vec_sel"); ++ builtin_define ("__builtin_vsx_vperm=__builtin_vec_perm"); ++ } + + /* May be overridden by target configuration. */ + RS6000_CPU_CPP_ENDIAN_BUILTINS(); +@@ -400,7 +413,7 @@ struct altivec_builtin_types + }; + + const struct altivec_builtin_types altivec_overloaded_builtins[] = { +- /* Unary AltiVec builtins. */ ++ /* Unary AltiVec/VSX builtins. */ + { ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V16QI, + RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 }, + { ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V8HI, +@@ -496,7 +509,7 @@ const struct altivec_builtin_types altiv + { ALTIVEC_BUILTIN_VEC_VUPKLSB, ALTIVEC_BUILTIN_VUPKLSB, + RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V16QI, 0, 0 }, + +- /* Binary AltiVec builtins. */ ++ /* Binary AltiVec/VSX builtins. */ + { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM, + RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 }, + { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM, +@@ -2206,7 +2219,7 @@ const struct altivec_builtin_types altiv + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 }, + +- /* Ternary AltiVec builtins. */ ++ /* Ternary AltiVec/VSX builtins. */ + { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST, + RS6000_BTI_void, ~RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI }, + { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST, +@@ -2407,6 +2420,10 @@ const struct altivec_builtin_types altiv + RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI }, + { ALTIVEC_BUILTIN_VEC_NMSUB, ALTIVEC_BUILTIN_VNMSUBFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF }, ++ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DF, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_unsigned_V16QI }, ++ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DI, ++ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_unsigned_V16QI }, + { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SF, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V16QI }, + { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SI, +@@ -2433,11 +2450,29 @@ const struct altivec_builtin_types altiv + RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI }, + { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_16QI, + RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_unsigned_V2DI }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DI }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI, ++ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI, ++ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_unsigned_V2DI }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI, ++ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI }, + { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI }, + { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI }, + { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI, ++ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI, ++ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SI }, ++ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI, + RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI }, + { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI, + RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI }, +@@ -2805,6 +2840,37 @@ const struct altivec_builtin_types altiv + RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI }, + { ALTIVEC_BUILTIN_VEC_STVRXL, ALTIVEC_BUILTIN_STVRXL, + RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI, ++ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI, ++ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, ++ RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_8HI, ++ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_8HI, ++ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, ++ RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SI, ++ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SI, ++ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, ++ RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DI, ++ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DI, ++ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, ++ RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SF, ++ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DF, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DF, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DI, ++ RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_NOT_OPAQUE }, ++ { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DI, ++ RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, ++ RS6000_BTI_NOT_OPAQUE }, + + /* Predicates. */ + { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUB_P, +@@ -3108,6 +3174,10 @@ altivec_resolve_overloaded_builtin (tree + goto bad; + switch (TYPE_MODE (type)) + { ++ case DImode: ++ type = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node); ++ size = 2; ++ break; + case SImode: + type = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node); + size = 4; +@@ -3121,6 +3191,7 @@ altivec_resolve_overloaded_builtin (tree + size = 16; + break; + case SFmode: type = V4SF_type_node; size = 4; break; ++ case DFmode: type = V2DF_type_node; size = 2; break; + default: + goto bad; + } +--- gcc/config/rs6000/rs6000.opt (revision 146119) ++++ gcc/config/rs6000/rs6000.opt (revision 146798) +@@ -119,18 +119,6 @@ mvsx + Target Report Mask(VSX) + Use vector/scalar (VSX) instructions + +-mvsx-vector-memory +-Target Undocumented Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1) +-; If -mvsx, use VSX vector load/store instructions instead of Altivec instructions +- +-mvsx-vector-float +-Target Undocumented Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1) +-; If -mvsx, use VSX arithmetic instructions for float vectors (on by default) +- +-mvsx-vector-double +-Target Undocumented Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1) +-; If -mvsx, use VSX arithmetic instructions for double vectors (on by default) +- + mvsx-scalar-double + Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1) + ; If -mvsx, use VSX arithmetic instructions for scalar double (on by default) +@@ -139,18 +127,14 @@ mvsx-scalar-memory + Target Undocumented Report Var(TARGET_VSX_SCALAR_MEMORY) + ; If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default) + +-mvsx-v4sf-altivec-regs +-Target Undocumented Report Var(TARGET_V4SF_ALTIVEC_REGS) Init(-1) +-; If -mvsx, prefer V4SF types to use Altivec regs and not the floating registers +- +-mreload-functions +-Target Undocumented Report Var(TARGET_RELOAD_FUNCTIONS) Init(-1) +-; If -mvsx or -maltivec, enable reload functions +- + mpower7-adjust-cost + Target Undocumented Var(TARGET_POWER7_ADJUST_COST) + ; Add extra cost for setting CR registers before a branch like is done for Power5 + ++mallow-timode ++Target Undocumented Var(TARGET_ALLOW_TIMODE) ++; Allow VSX/Altivec to target loading TImode variables. ++ + mdisallow-float-in-lr-ctr + Target Undocumented Var(TARGET_DISALLOW_FLOAT_IN_LR_CTR) Init(-1) + ; Disallow floating point in LR or CTR, causes some reload bugs +--- gcc/config/rs6000/rs6000.c (revision 146119) ++++ gcc/config/rs6000/rs6000.c (revision 146798) +@@ -130,6 +130,8 @@ typedef struct machine_function GTY(()) + 64-bits wide and is allocated early enough so that the offset + does not overflow the 16-bit load/store offset field. */ + rtx sdmode_stack_slot; ++ /* Whether an indirect jump or table jump was generated. */ ++ bool indirect_jump_p; + } machine_function; + + /* Target cpu type */ +@@ -917,6 +919,11 @@ static rtx rs6000_expand_binop_builtin ( + static rtx rs6000_expand_ternop_builtin (enum insn_code, tree, rtx); + static rtx rs6000_expand_builtin (tree, rtx, rtx, enum machine_mode, int); + static void altivec_init_builtins (void); ++static unsigned builtin_hash_function (const void *); ++static int builtin_hash_eq (const void *, const void *); ++static tree builtin_function_type (enum machine_mode, enum machine_mode, ++ enum machine_mode, enum machine_mode, ++ const char *name); + static void rs6000_common_init_builtins (void); + static void rs6000_init_libfuncs (void); + +@@ -1018,6 +1025,8 @@ static enum reg_class rs6000_secondary_r + enum machine_mode, + struct secondary_reload_info *); + ++static const enum reg_class *rs6000_ira_cover_classes (void); ++ + const int INSN_NOT_AVAILABLE = -1; + static enum machine_mode rs6000_eh_return_filter_mode (void); + +@@ -1033,6 +1042,16 @@ struct toc_hash_struct GTY(()) + }; + + static GTY ((param_is (struct toc_hash_struct))) htab_t toc_hash_table; ++ ++/* Hash table to keep track of the argument types for builtin functions. */ ++ ++struct builtin_hash_struct GTY(()) ++{ ++ tree type; ++ enum machine_mode mode[4]; /* return value + 3 arguments */ ++}; ++ ++static GTY ((param_is (struct builtin_hash_struct))) htab_t builtin_hash_table; + + /* Default register names. */ + char rs6000_reg_names[][8] = +@@ -1350,6 +1369,9 @@ static const char alt_reg_names[][8] = + #undef TARGET_SECONDARY_RELOAD + #define TARGET_SECONDARY_RELOAD rs6000_secondary_reload + ++#undef TARGET_IRA_COVER_CLASSES ++#define TARGET_IRA_COVER_CLASSES rs6000_ira_cover_classes ++ + struct gcc_target targetm = TARGET_INITIALIZER; + + /* Return number of consecutive hard regs needed starting at reg REGNO +@@ -1370,7 +1392,7 @@ rs6000_hard_regno_nregs_internal (int re + unsigned HOST_WIDE_INT reg_size; + + if (FP_REGNO_P (regno)) +- reg_size = (VECTOR_UNIT_VSX_P (mode) ++ reg_size = (VECTOR_MEM_VSX_P (mode) + ? UNITS_PER_VSX_WORD + : UNITS_PER_FP_WORD); + +@@ -1452,7 +1474,7 @@ rs6000_hard_regno_mode_ok (int regno, en + + /* AltiVec only in AldyVec registers. */ + if (ALTIVEC_REGNO_P (regno)) +- return VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode); ++ return VECTOR_MEM_ALTIVEC_OR_VSX_P (mode); + + /* ...but GPRs can hold SIMD data on the SPE in one register. */ + if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode)) +@@ -1613,10 +1635,8 @@ rs6000_init_hard_regno_mode_ok (void) + rs6000_vector_reload[m][1] = CODE_FOR_nothing; + } + +- /* TODO, add TI/V2DI mode for moving data if Altivec or VSX. */ +- + /* V2DF mode, VSX only. */ +- if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_DOUBLE) ++ if (float_p && TARGET_VSX) + { + rs6000_vector_unit[V2DFmode] = VECTOR_VSX; + rs6000_vector_mem[V2DFmode] = VECTOR_VSX; +@@ -1624,17 +1644,11 @@ rs6000_init_hard_regno_mode_ok (void) + } + + /* V4SF mode, either VSX or Altivec. */ +- if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_FLOAT) ++ if (float_p && TARGET_VSX) + { + rs6000_vector_unit[V4SFmode] = VECTOR_VSX; +- if (TARGET_VSX_VECTOR_MEMORY || !TARGET_ALTIVEC) +- { +- rs6000_vector_align[V4SFmode] = 32; +- rs6000_vector_mem[V4SFmode] = VECTOR_VSX; +- } else { +- rs6000_vector_align[V4SFmode] = 128; +- rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC; +- } ++ rs6000_vector_align[V4SFmode] = 32; ++ rs6000_vector_mem[V4SFmode] = VECTOR_VSX; + } + else if (float_p && TARGET_ALTIVEC) + { +@@ -1655,7 +1669,7 @@ rs6000_init_hard_regno_mode_ok (void) + rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS; + rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS; + +- if (TARGET_VSX && TARGET_VSX_VECTOR_MEMORY) ++ if (TARGET_VSX) + { + rs6000_vector_mem[V4SImode] = VECTOR_VSX; + rs6000_vector_mem[V8HImode] = VECTOR_VSX; +@@ -1675,6 +1689,23 @@ rs6000_init_hard_regno_mode_ok (void) + } + } + ++ /* V2DImode, prefer vsx over altivec, since the main use will be for ++ vectorized floating point conversions. */ ++ if (float_p && TARGET_VSX) ++ { ++ rs6000_vector_mem[V2DImode] = VECTOR_VSX; ++ rs6000_vector_unit[V2DImode] = VECTOR_NONE; ++ rs6000_vector_reg_class[V2DImode] = vsx_rc; ++ rs6000_vector_align[V2DImode] = 64; ++ } ++ else if (TARGET_ALTIVEC) ++ { ++ rs6000_vector_mem[V2DImode] = VECTOR_ALTIVEC; ++ rs6000_vector_unit[V2DImode] = VECTOR_NONE; ++ rs6000_vector_reg_class[V2DImode] = ALTIVEC_REGS; ++ rs6000_vector_align[V2DImode] = 128; ++ } ++ + /* DFmode, see if we want to use the VSX unit. */ + if (float_p && TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE) + { +@@ -1684,16 +1715,30 @@ rs6000_init_hard_regno_mode_ok (void) + = (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE); + } + +- /* TODO, add SPE and paired floating point vector support. */ ++ /* TImode. Until this is debugged, only add it under switch control. */ ++ if (TARGET_ALLOW_TIMODE) ++ { ++ if (float_p && TARGET_VSX) ++ { ++ rs6000_vector_mem[TImode] = VECTOR_VSX; ++ rs6000_vector_unit[TImode] = VECTOR_NONE; ++ rs6000_vector_reg_class[TImode] = vsx_rc; ++ rs6000_vector_align[TImode] = 64; ++ } ++ else if (TARGET_ALTIVEC) ++ { ++ rs6000_vector_mem[TImode] = VECTOR_ALTIVEC; ++ rs6000_vector_unit[TImode] = VECTOR_NONE; ++ rs6000_vector_reg_class[TImode] = ALTIVEC_REGS; ++ rs6000_vector_align[TImode] = 128; ++ } ++ } ++ ++ /* TODO add SPE and paired floating point vector support. */ + + /* Set the VSX register classes. */ +- +- /* For V4SF, prefer the Altivec registers, because there are a few operations +- that want to use Altivec operations instead of VSX. */ + rs6000_vector_reg_class[V4SFmode] +- = ((VECTOR_UNIT_VSX_P (V4SFmode) +- && VECTOR_MEM_VSX_P (V4SFmode) +- && !TARGET_V4SF_ALTIVEC_REGS) ++ = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode)) + ? vsx_rc + : (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) + ? ALTIVEC_REGS +@@ -1712,7 +1757,7 @@ rs6000_init_hard_regno_mode_ok (void) + rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS; + + /* Set up the reload helper functions. */ +- if (TARGET_RELOAD_FUNCTIONS && (TARGET_VSX || TARGET_ALTIVEC)) ++ if (TARGET_VSX || TARGET_ALTIVEC) + { + if (TARGET_64BIT) + { +@@ -1728,6 +1773,11 @@ rs6000_init_hard_regno_mode_ok (void) + rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_di_load; + rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_di_store; + rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_di_load; ++ if (TARGET_ALLOW_TIMODE) ++ { ++ rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_di_store; ++ rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_di_load; ++ } + } + else + { +@@ -1743,6 +1793,11 @@ rs6000_init_hard_regno_mode_ok (void) + rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_si_load; + rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_si_store; + rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_si_load; ++ if (TARGET_ALLOW_TIMODE) ++ { ++ rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_si_store; ++ rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_si_load; ++ } + } + } + +@@ -2132,23 +2187,29 @@ rs6000_override_options (const char *def + const char *msg = NULL; + if (!TARGET_HARD_FLOAT || !TARGET_FPRS + || !TARGET_SINGLE_FLOAT || !TARGET_DOUBLE_FLOAT) +- msg = "-mvsx requires hardware floating point"; ++ { ++ if (target_flags_explicit & MASK_VSX) ++ msg = N_("-mvsx requires hardware floating point"); ++ else ++ target_flags &= ~ MASK_VSX; ++ } + else if (TARGET_PAIRED_FLOAT) +- msg = "-mvsx and -mpaired are incompatible"; ++ msg = N_("-mvsx and -mpaired are incompatible"); + /* The hardware will allow VSX and little endian, but until we make sure + things like vector select, etc. work don't allow VSX on little endian + systems at this point. */ + else if (!BYTES_BIG_ENDIAN) +- msg = "-mvsx used with little endian code"; ++ msg = N_("-mvsx used with little endian code"); + else if (TARGET_AVOID_XFORM > 0) +- msg = "-mvsx needs indexed addressing"; ++ msg = N_("-mvsx needs indexed addressing"); + + if (msg) + { + warning (0, msg); +- target_flags &= MASK_VSX; ++ target_flags &= ~ MASK_VSX; + } +- else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC) == 0) ++ else if (TARGET_VSX && !TARGET_ALTIVEC ++ && (target_flags_explicit & MASK_ALTIVEC) == 0) + target_flags |= MASK_ALTIVEC; + } + +@@ -2581,8 +2642,8 @@ rs6000_builtin_conversion (enum tree_cod + return NULL_TREE; + + return TYPE_UNSIGNED (type) +- ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDSP] +- : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDSP]; ++ ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDDP] ++ : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDDP]; + + case V4SImode: + if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode)) +@@ -3780,15 +3841,28 @@ rs6000_expand_vector_init (rtx target, r + } + } + +- if (mode == V2DFmode) ++ if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode)) + { +- gcc_assert (TARGET_VSX); ++ rtx (*splat) (rtx, rtx); ++ rtx (*concat) (rtx, rtx, rtx); ++ ++ if (mode == V2DFmode) ++ { ++ splat = gen_vsx_splat_v2df; ++ concat = gen_vsx_concat_v2df; ++ } ++ else ++ { ++ splat = gen_vsx_splat_v2di; ++ concat = gen_vsx_concat_v2di; ++ } ++ + if (all_same) +- emit_insn (gen_vsx_splatv2df (target, XVECEXP (vals, 0, 0))); ++ emit_insn (splat (target, XVECEXP (vals, 0, 0))); + else +- emit_insn (gen_vsx_concat_v2df (target, +- copy_to_reg (XVECEXP (vals, 0, 0)), +- copy_to_reg (XVECEXP (vals, 0, 1)))); ++ emit_insn (concat (target, ++ copy_to_reg (XVECEXP (vals, 0, 0)), ++ copy_to_reg (XVECEXP (vals, 0, 1)))); + return; + } + +@@ -3851,10 +3925,12 @@ rs6000_expand_vector_set (rtx target, rt + int width = GET_MODE_SIZE (inner_mode); + int i; + +- if (mode == V2DFmode) ++ if (mode == V2DFmode || mode == V2DImode) + { ++ rtx (*set_func) (rtx, rtx, rtx, rtx) ++ = ((mode == V2DFmode) ? gen_vsx_set_v2df : gen_vsx_set_v2di); + gcc_assert (TARGET_VSX); +- emit_insn (gen_vsx_set_v2df (target, val, target, GEN_INT (elt))); ++ emit_insn (set_func (target, val, target, GEN_INT (elt))); + return; + } + +@@ -3895,10 +3971,12 @@ rs6000_expand_vector_extract (rtx target + enum machine_mode inner_mode = GET_MODE_INNER (mode); + rtx mem, x; + +- if (mode == V2DFmode) ++ if (mode == V2DFmode || mode == V2DImode) + { ++ rtx (*extract_func) (rtx, rtx, rtx) ++ = ((mode == V2DFmode) ? gen_vsx_extract_v2df : gen_vsx_extract_v2di); + gcc_assert (TARGET_VSX); +- emit_insn (gen_vsx_extract_v2df (target, vec, GEN_INT (elt))); ++ emit_insn (extract_func (target, vec, GEN_INT (elt))); + return; + } + +@@ -4318,9 +4396,7 @@ avoiding_indexed_address_p (enum machine + { + /* Avoid indexed addressing for modes that have non-indexed + load/store instruction forms. */ +- return (TARGET_AVOID_XFORM +- && (!TARGET_ALTIVEC || !ALTIVEC_VECTOR_MODE (mode)) +- && (!TARGET_VSX || !VSX_VECTOR_MODE (mode))); ++ return (TARGET_AVOID_XFORM && VECTOR_MEM_NONE_P (mode)); + } + + inline bool +@@ -4443,6 +4519,16 @@ rs6000_legitimize_address (rtx x, rtx ol + ret = rs6000_legitimize_tls_address (x, model); + } + ++ else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)) ++ { ++ /* Make sure both operands are registers. */ ++ if (GET_CODE (x) == PLUS) ++ ret = gen_rtx_PLUS (Pmode, ++ force_reg (Pmode, XEXP (x, 0)), ++ force_reg (Pmode, XEXP (x, 1))); ++ else ++ ret = force_reg (Pmode, x); ++ } + else if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 0)) == REG + && GET_CODE (XEXP (x, 1)) == CONST_INT +@@ -4452,8 +4538,6 @@ rs6000_legitimize_address (rtx x, rtx ol + && (mode == DImode || mode == TImode) + && (INTVAL (XEXP (x, 1)) & 3) != 0) + || (TARGET_SPE && SPE_VECTOR_MODE (mode)) +- || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode)) +- || (TARGET_VSX && VSX_VECTOR_MODE (mode)) + || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode + || mode == DImode || mode == DDmode + || mode == TDmode)))) +@@ -4485,15 +4569,6 @@ rs6000_legitimize_address (rtx x, rtx ol + ret = gen_rtx_PLUS (Pmode, XEXP (x, 0), + force_reg (Pmode, force_operand (XEXP (x, 1), 0))); + } +- else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)) +- { +- /* Make sure both operands are registers. */ +- if (GET_CODE (x) == PLUS) +- ret = gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)), +- force_reg (Pmode, XEXP (x, 1))); +- else +- ret = force_reg (Pmode, x); +- } + else if ((TARGET_SPE && SPE_VECTOR_MODE (mode)) + || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode + || mode == DDmode || mode == TDmode +@@ -5131,7 +5206,7 @@ rs6000_legitimate_address (enum machine_ + ret = 1; + else if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict)) + ret = 1; +- else if (mode != TImode ++ else if ((mode != TImode || !VECTOR_MEM_NONE_P (TImode)) + && mode != TFmode + && mode != TDmode + && ((TARGET_HARD_FLOAT && TARGET_FPRS) +@@ -5971,7 +6046,13 @@ rs6000_emit_move (rtx dest, rtx source, + + case TImode: + if (VECTOR_MEM_ALTIVEC_OR_VSX_P (TImode)) +- break; ++ { ++ if (CONSTANT_P (operands[1]) ++ && !easy_vector_constant (operands[1], mode)) ++ operands[1] = force_const_mem (mode, operands[1]); ++ ++ break; ++ } + + rs6000_eliminate_indexed_memrefs (operands); + +@@ -7888,7 +7969,8 @@ def_builtin (int mask, const char *name, + if ((mask & target_flags) || TARGET_PAIRED_FLOAT) + { + if (rs6000_builtin_decls[code]) +- abort (); ++ fatal_error ("internal error: builtin function to %s already processed.", ++ name); + + rs6000_builtin_decls[code] = + add_builtin_function (name, type, code, BUILT_IN_MD, +@@ -7953,6 +8035,34 @@ static const struct builtin_description + { MASK_VSX, CODE_FOR_vsx_fnmaddv4sf4, "__builtin_vsx_xvnmaddsp", VSX_BUILTIN_XVNMADDSP }, + { MASK_VSX, CODE_FOR_vsx_fnmsubv4sf4, "__builtin_vsx_xvnmsubsp", VSX_BUILTIN_XVNMSUBSP }, + ++ { MASK_VSX, CODE_FOR_vector_vselv2di, "__builtin_vsx_xxsel_2di", VSX_BUILTIN_XXSEL_2DI }, ++ { MASK_VSX, CODE_FOR_vector_vselv2df, "__builtin_vsx_xxsel_2df", VSX_BUILTIN_XXSEL_2DF }, ++ { MASK_VSX, CODE_FOR_vector_vselv4sf, "__builtin_vsx_xxsel_4sf", VSX_BUILTIN_XXSEL_4SF }, ++ { MASK_VSX, CODE_FOR_vector_vselv4si, "__builtin_vsx_xxsel_4si", VSX_BUILTIN_XXSEL_4SI }, ++ { MASK_VSX, CODE_FOR_vector_vselv8hi, "__builtin_vsx_xxsel_8hi", VSX_BUILTIN_XXSEL_8HI }, ++ { MASK_VSX, CODE_FOR_vector_vselv16qi, "__builtin_vsx_xxsel_16qi", VSX_BUILTIN_XXSEL_16QI }, ++ ++ { MASK_VSX, CODE_FOR_altivec_vperm_v2di, "__builtin_vsx_vperm_2di", VSX_BUILTIN_VPERM_2DI }, ++ { MASK_VSX, CODE_FOR_altivec_vperm_v2df, "__builtin_vsx_vperm_2df", VSX_BUILTIN_VPERM_2DF }, ++ { MASK_VSX, CODE_FOR_altivec_vperm_v4sf, "__builtin_vsx_vperm_4sf", VSX_BUILTIN_VPERM_4SF }, ++ { MASK_VSX, CODE_FOR_altivec_vperm_v4si, "__builtin_vsx_vperm_4si", VSX_BUILTIN_VPERM_4SI }, ++ { MASK_VSX, CODE_FOR_altivec_vperm_v8hi, "__builtin_vsx_vperm_8hi", VSX_BUILTIN_VPERM_8HI }, ++ { MASK_VSX, CODE_FOR_altivec_vperm_v16qi, "__builtin_vsx_vperm_16qi", VSX_BUILTIN_VPERM_16QI }, ++ ++ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2df, "__builtin_vsx_xxpermdi_2df", VSX_BUILTIN_XXPERMDI_2DF }, ++ { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2di, "__builtin_vsx_xxpermdi_2di", VSX_BUILTIN_XXPERMDI_2DI }, ++ { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxpermdi", VSX_BUILTIN_VEC_XXPERMDI }, ++ { MASK_VSX, CODE_FOR_vsx_set_v2df, "__builtin_vsx_set_2df", VSX_BUILTIN_SET_2DF }, ++ { MASK_VSX, CODE_FOR_vsx_set_v2di, "__builtin_vsx_set_2di", VSX_BUILTIN_SET_2DI }, ++ ++ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2di, "__builtin_vsx_xxsldwi_2di", VSX_BUILTIN_XXSLDWI_2DI }, ++ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2df, "__builtin_vsx_xxsldwi_2df", VSX_BUILTIN_XXSLDWI_2DF }, ++ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4sf, "__builtin_vsx_xxsldwi_4sf", VSX_BUILTIN_XXSLDWI_4SF }, ++ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4si, "__builtin_vsx_xxsldwi_4si", VSX_BUILTIN_XXSLDWI_4SI }, ++ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v8hi, "__builtin_vsx_xxsldwi_8hi", VSX_BUILTIN_XXSLDWI_8HI }, ++ { MASK_VSX, CODE_FOR_vsx_xxsldwi_v16qi, "__builtin_vsx_xxsldwi_16qi", VSX_BUILTIN_XXSLDWI_16QI }, ++ { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxsldwi", VSX_BUILTIN_VEC_XXSLDWI }, ++ + { 0, CODE_FOR_paired_msub, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB }, + { 0, CODE_FOR_paired_madd, "__builtin_paired_madd", PAIRED_BUILTIN_MADD }, + { 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 }, +@@ -8102,6 +8212,9 @@ static struct builtin_description bdesc_ + { MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP }, + { MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP }, + { MASK_VSX, CODE_FOR_vsx_tdivv2df3, "__builtin_vsx_xvtdivdp", VSX_BUILTIN_XVTDIVDP }, ++ { MASK_VSX, CODE_FOR_vector_eqv2df, "__builtin_vsx_xvcmpeqdp", VSX_BUILTIN_XVCMPEQDP }, ++ { MASK_VSX, CODE_FOR_vector_gtv2df, "__builtin_vsx_xvcmpgtdp", VSX_BUILTIN_XVCMPGTDP }, ++ { MASK_VSX, CODE_FOR_vector_gev2df, "__builtin_vsx_xvcmpgedp", VSX_BUILTIN_XVCMPGEDP }, + + { MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP }, + { MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP }, +@@ -8110,6 +8223,21 @@ static struct builtin_description bdesc_ + { MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP }, + { MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP }, + { MASK_VSX, CODE_FOR_vsx_tdivv4sf3, "__builtin_vsx_xvtdivsp", VSX_BUILTIN_XVTDIVSP }, ++ { MASK_VSX, CODE_FOR_vector_eqv4sf, "__builtin_vsx_xvcmpeqsp", VSX_BUILTIN_XVCMPEQSP }, ++ { MASK_VSX, CODE_FOR_vector_gtv4sf, "__builtin_vsx_xvcmpgtsp", VSX_BUILTIN_XVCMPGTSP }, ++ { MASK_VSX, CODE_FOR_vector_gev4sf, "__builtin_vsx_xvcmpgesp", VSX_BUILTIN_XVCMPGESP }, ++ ++ { MASK_VSX, CODE_FOR_smindf3, "__builtin_vsx_xsmindp", VSX_BUILTIN_XSMINDP }, ++ { MASK_VSX, CODE_FOR_smaxdf3, "__builtin_vsx_xsmaxdp", VSX_BUILTIN_XSMAXDP }, ++ ++ { MASK_VSX, CODE_FOR_vsx_concat_v2df, "__builtin_vsx_concat_2df", VSX_BUILTIN_CONCAT_2DF }, ++ { MASK_VSX, CODE_FOR_vsx_concat_v2di, "__builtin_vsx_concat_2di", VSX_BUILTIN_CONCAT_2DI }, ++ { MASK_VSX, CODE_FOR_vsx_splat_v2df, "__builtin_vsx_splat_2df", VSX_BUILTIN_SPLAT_2DF }, ++ { MASK_VSX, CODE_FOR_vsx_splat_v2di, "__builtin_vsx_splat_2di", VSX_BUILTIN_SPLAT_2DI }, ++ { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4sf, "__builtin_vsx_xxmrghw", VSX_BUILTIN_XXMRGHW_4SF }, ++ { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4si, "__builtin_vsx_xxmrghw_4si", VSX_BUILTIN_XXMRGHW_4SI }, ++ { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4sf, "__builtin_vsx_xxmrglw", VSX_BUILTIN_XXMRGLW_4SF }, ++ { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4si, "__builtin_vsx_xxmrglw_4si", VSX_BUILTIN_XXMRGLW_4SI }, + + { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD }, + { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP }, +@@ -8527,6 +8655,47 @@ static struct builtin_description bdesc_ + { MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2, "__builtin_vsx_xvtsqrtsp", VSX_BUILTIN_XVTSQRTSP }, + { MASK_VSX, CODE_FOR_vsx_frev4sf2, "__builtin_vsx_xvresp", VSX_BUILTIN_XVRESP }, + ++ { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvdpsp", VSX_BUILTIN_XSCVDPSP }, ++ { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvspdp", VSX_BUILTIN_XSCVSPDP }, ++ { MASK_VSX, CODE_FOR_vsx_xvcvdpsp, "__builtin_vsx_xvcvdpsp", VSX_BUILTIN_XVCVDPSP }, ++ { MASK_VSX, CODE_FOR_vsx_xvcvspdp, "__builtin_vsx_xvcvspdp", VSX_BUILTIN_XVCVSPDP }, ++ ++ { MASK_VSX, CODE_FOR_vsx_fix_truncv2dfv2di2, "__builtin_vsx_xvcvdpsxds", VSX_BUILTIN_XVCVDPSXDS }, ++ { MASK_VSX, CODE_FOR_vsx_fixuns_truncv2dfv2di2, "__builtin_vsx_xvcvdpuxds", VSX_BUILTIN_XVCVDPUXDS }, ++ { MASK_VSX, CODE_FOR_vsx_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP }, ++ { MASK_VSX, CODE_FOR_vsx_floatunsv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP }, ++ ++ { MASK_VSX, CODE_FOR_vsx_fix_truncv4sfv4si2, "__builtin_vsx_xvcvspsxws", VSX_BUILTIN_XVCVSPSXWS }, ++ { MASK_VSX, CODE_FOR_vsx_fixuns_truncv4sfv4si2, "__builtin_vsx_xvcvspuxws", VSX_BUILTIN_XVCVSPUXWS }, ++ { MASK_VSX, CODE_FOR_vsx_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXWSP }, ++ { MASK_VSX, CODE_FOR_vsx_floatunsv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP }, ++ ++ { MASK_VSX, CODE_FOR_vsx_xvcvdpsxws, "__builtin_vsx_xvcvdpsxws", VSX_BUILTIN_XVCVDPSXWS }, ++ { MASK_VSX, CODE_FOR_vsx_xvcvdpuxws, "__builtin_vsx_xvcvdpuxws", VSX_BUILTIN_XVCVDPUXWS }, ++ { MASK_VSX, CODE_FOR_vsx_xvcvsxwdp, "__builtin_vsx_xvcvsxwdp", VSX_BUILTIN_XVCVSXWDP }, ++ { MASK_VSX, CODE_FOR_vsx_xvcvuxwdp, "__builtin_vsx_xvcvuxwdp", VSX_BUILTIN_XVCVUXWDP }, ++ { MASK_VSX, CODE_FOR_vsx_xvrdpi, "__builtin_vsx_xvrdpi", VSX_BUILTIN_XVRDPI }, ++ { MASK_VSX, CODE_FOR_vsx_xvrdpic, "__builtin_vsx_xvrdpic", VSX_BUILTIN_XVRDPIC }, ++ { MASK_VSX, CODE_FOR_vsx_floorv2df2, "__builtin_vsx_xvrdpim", VSX_BUILTIN_XVRDPIM }, ++ { MASK_VSX, CODE_FOR_vsx_ceilv2df2, "__builtin_vsx_xvrdpip", VSX_BUILTIN_XVRDPIP }, ++ { MASK_VSX, CODE_FOR_vsx_btruncv2df2, "__builtin_vsx_xvrdpiz", VSX_BUILTIN_XVRDPIZ }, ++ ++ { MASK_VSX, CODE_FOR_vsx_xvcvspsxds, "__builtin_vsx_xvcvspsxds", VSX_BUILTIN_XVCVSPSXDS }, ++ { MASK_VSX, CODE_FOR_vsx_xvcvspuxds, "__builtin_vsx_xvcvspuxds", VSX_BUILTIN_XVCVSPUXDS }, ++ { MASK_VSX, CODE_FOR_vsx_xvcvsxdsp, "__builtin_vsx_xvcvsxdsp", VSX_BUILTIN_XVCVSXDSP }, ++ { MASK_VSX, CODE_FOR_vsx_xvcvuxdsp, "__builtin_vsx_xvcvuxdsp", VSX_BUILTIN_XVCVUXDSP }, ++ { MASK_VSX, CODE_FOR_vsx_xvrspi, "__builtin_vsx_xvrspi", VSX_BUILTIN_XVRSPI }, ++ { MASK_VSX, CODE_FOR_vsx_xvrspic, "__builtin_vsx_xvrspic", VSX_BUILTIN_XVRSPIC }, ++ { MASK_VSX, CODE_FOR_vsx_floorv4sf2, "__builtin_vsx_xvrspim", VSX_BUILTIN_XVRSPIM }, ++ { MASK_VSX, CODE_FOR_vsx_ceilv4sf2, "__builtin_vsx_xvrspip", VSX_BUILTIN_XVRSPIP }, ++ { MASK_VSX, CODE_FOR_vsx_btruncv4sf2, "__builtin_vsx_xvrspiz", VSX_BUILTIN_XVRSPIZ }, ++ ++ { MASK_VSX, CODE_FOR_vsx_xsrdpi, "__builtin_vsx_xsrdpi", VSX_BUILTIN_XSRDPI }, ++ { MASK_VSX, CODE_FOR_vsx_xsrdpic, "__builtin_vsx_xsrdpic", VSX_BUILTIN_XSRDPIC }, ++ { MASK_VSX, CODE_FOR_vsx_floordf2, "__builtin_vsx_xsrdpim", VSX_BUILTIN_XSRDPIM }, ++ { MASK_VSX, CODE_FOR_vsx_ceildf2, "__builtin_vsx_xsrdpip", VSX_BUILTIN_XSRDPIP }, ++ { MASK_VSX, CODE_FOR_vsx_btruncdf2, "__builtin_vsx_xsrdpiz", VSX_BUILTIN_XSRDPIZ }, ++ + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL }, +@@ -8552,15 +8721,6 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI }, + { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI }, + +- { MASK_VSX, CODE_FOR_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP }, +- { MASK_VSX, CODE_FOR_unsigned_floatv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP }, +- { MASK_VSX, CODE_FOR_fix_truncv2dfv2di2, "__builtin_vsx_xvdpsxds", VSX_BUILTIN_XVCVDPSXDS }, +- { MASK_VSX, CODE_FOR_fixuns_truncv2dfv2di2, "__builtin_vsx_xvdpuxds", VSX_BUILTIN_XVCVDPUXDS }, +- { MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXDSP }, +- { MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP }, +- { MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vsx_xvspsxws", VSX_BUILTIN_XVCVSPSXWS }, +- { MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vsx_xvspuxws", VSX_BUILTIN_XVCVSPUXWS }, +- + /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and + end with SPE_BUILTIN_EVSUBFUSIAAW. */ + { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS }, +@@ -9065,11 +9225,12 @@ rs6000_expand_ternop_builtin (enum insn_ + || arg2 == error_mark_node) + return const0_rtx; + +- if (icode == CODE_FOR_altivec_vsldoi_v4sf +- || icode == CODE_FOR_altivec_vsldoi_v4si +- || icode == CODE_FOR_altivec_vsldoi_v8hi +- || icode == CODE_FOR_altivec_vsldoi_v16qi) ++ switch (icode) + { ++ case CODE_FOR_altivec_vsldoi_v4sf: ++ case CODE_FOR_altivec_vsldoi_v4si: ++ case CODE_FOR_altivec_vsldoi_v8hi: ++ case CODE_FOR_altivec_vsldoi_v16qi: + /* Only allow 4-bit unsigned literals. */ + STRIP_NOPS (arg2); + if (TREE_CODE (arg2) != INTEGER_CST +@@ -9078,6 +9239,40 @@ rs6000_expand_ternop_builtin (enum insn_ + error ("argument 3 must be a 4-bit unsigned literal"); + return const0_rtx; + } ++ break; ++ ++ case CODE_FOR_vsx_xxpermdi_v2df: ++ case CODE_FOR_vsx_xxpermdi_v2di: ++ case CODE_FOR_vsx_xxsldwi_v16qi: ++ case CODE_FOR_vsx_xxsldwi_v8hi: ++ case CODE_FOR_vsx_xxsldwi_v4si: ++ case CODE_FOR_vsx_xxsldwi_v4sf: ++ case CODE_FOR_vsx_xxsldwi_v2di: ++ case CODE_FOR_vsx_xxsldwi_v2df: ++ /* Only allow 2-bit unsigned literals. */ ++ STRIP_NOPS (arg2); ++ if (TREE_CODE (arg2) != INTEGER_CST ++ || TREE_INT_CST_LOW (arg2) & ~0x3) ++ { ++ error ("argument 3 must be a 2-bit unsigned literal"); ++ return const0_rtx; ++ } ++ break; ++ ++ case CODE_FOR_vsx_set_v2df: ++ case CODE_FOR_vsx_set_v2di: ++ /* Only allow 1-bit unsigned literals. */ ++ STRIP_NOPS (arg2); ++ if (TREE_CODE (arg2) != INTEGER_CST ++ || TREE_INT_CST_LOW (arg2) & ~0x1) ++ { ++ error ("argument 3 must be a 1-bit unsigned literal"); ++ return const0_rtx; ++ } ++ break; ++ ++ default: ++ break; + } + + if (target == 0 +@@ -9385,8 +9580,10 @@ altivec_expand_builtin (tree exp, rtx ta + enum machine_mode tmode, mode0; + unsigned int fcode = DECL_FUNCTION_CODE (fndecl); + +- if (fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST +- && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST) ++ if ((fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST ++ && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST) ++ || (fcode >= VSX_BUILTIN_OVERLOADED_FIRST ++ && fcode <= VSX_BUILTIN_OVERLOADED_LAST)) + { + *expandedp = true; + error ("unresolved overload for Altivec builtin %qF", fndecl); +@@ -10175,6 +10372,7 @@ rs6000_init_builtins (void) + unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16); + unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8); + unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4); ++ unsigned_V2DI_type_node = build_vector_type (unsigned_intDI_type_node, 2); + + opaque_V2SF_type_node = build_opaque_vector_type (float_type_node, 2); + opaque_V2SI_type_node = build_opaque_vector_type (intSI_type_node, 2); +@@ -10188,6 +10386,7 @@ rs6000_init_builtins (void) + bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node); + bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node); + bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node); ++ bool_long_type_node = build_distinct_type_copy (unsigned_intDI_type_node); + pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node); + + long_integer_type_internal_node = long_integer_type_node; +@@ -10220,6 +10419,7 @@ rs6000_init_builtins (void) + bool_V16QI_type_node = build_vector_type (bool_char_type_node, 16); + bool_V8HI_type_node = build_vector_type (bool_short_type_node, 8); + bool_V4SI_type_node = build_vector_type (bool_int_type_node, 4); ++ bool_V2DI_type_node = build_vector_type (bool_long_type_node, 2); + pixel_V8HI_type_node = build_vector_type (pixel_type_node, 8); + + (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, +@@ -10260,9 +10460,17 @@ rs6000_init_builtins (void) + pixel_V8HI_type_node)); + + if (TARGET_VSX) +- (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, +- get_identifier ("__vector double"), +- V2DF_type_node)); ++ { ++ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, ++ get_identifier ("__vector double"), ++ V2DF_type_node)); ++ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, ++ get_identifier ("__vector long"), ++ V2DI_type_node)); ++ (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, ++ get_identifier ("__vector __bool long"), ++ bool_V2DI_type_node)); ++ } + + if (TARGET_PAIRED_FLOAT) + paired_init_builtins (); +@@ -10837,8 +11045,10 @@ altivec_init_builtins (void) + { + enum machine_mode mode1; + tree type; +- bool is_overloaded = dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST +- && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST; ++ bool is_overloaded = ((dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST ++ && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST) ++ || (dp->code >= VSX_BUILTIN_OVERLOADED_FIRST ++ && dp->code <= VSX_BUILTIN_OVERLOADED_LAST)); + + if (is_overloaded) + mode1 = VOIDmode; +@@ -11001,592 +11211,302 @@ altivec_init_builtins (void) + ALTIVEC_BUILTIN_VEC_EXT_V4SF); + } + +-static void +-rs6000_common_init_builtins (void) ++/* Hash function for builtin functions with up to 3 arguments and a return ++ type. */ ++static unsigned ++builtin_hash_function (const void *hash_entry) + { +- const struct builtin_description *d; +- size_t i; ++ unsigned ret = 0; ++ int i; ++ const struct builtin_hash_struct *bh = ++ (const struct builtin_hash_struct *) hash_entry; + +- tree v2sf_ftype_v2sf_v2sf_v2sf +- = build_function_type_list (V2SF_type_node, +- V2SF_type_node, V2SF_type_node, +- V2SF_type_node, NULL_TREE); +- +- tree v4sf_ftype_v4sf_v4sf_v16qi +- = build_function_type_list (V4SF_type_node, +- V4SF_type_node, V4SF_type_node, +- V16QI_type_node, NULL_TREE); +- tree v4si_ftype_v4si_v4si_v16qi +- = build_function_type_list (V4SI_type_node, +- V4SI_type_node, V4SI_type_node, +- V16QI_type_node, NULL_TREE); +- tree v8hi_ftype_v8hi_v8hi_v16qi +- = build_function_type_list (V8HI_type_node, +- V8HI_type_node, V8HI_type_node, +- V16QI_type_node, NULL_TREE); +- tree v16qi_ftype_v16qi_v16qi_v16qi +- = build_function_type_list (V16QI_type_node, +- V16QI_type_node, V16QI_type_node, +- V16QI_type_node, NULL_TREE); +- tree v4si_ftype_int +- = build_function_type_list (V4SI_type_node, integer_type_node, NULL_TREE); +- tree v8hi_ftype_int +- = build_function_type_list (V8HI_type_node, integer_type_node, NULL_TREE); +- tree v16qi_ftype_int +- = build_function_type_list (V16QI_type_node, integer_type_node, NULL_TREE); +- tree v8hi_ftype_v16qi +- = build_function_type_list (V8HI_type_node, V16QI_type_node, NULL_TREE); +- tree v4sf_ftype_v4sf +- = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE); ++ for (i = 0; i < 4; i++) ++ ret = (ret * (unsigned)MAX_MACHINE_MODE) + ((unsigned)bh->mode[i]); + +- tree v2si_ftype_v2si_v2si +- = build_function_type_list (opaque_V2SI_type_node, +- opaque_V2SI_type_node, +- opaque_V2SI_type_node, NULL_TREE); +- +- tree v2sf_ftype_v2sf_v2sf_spe +- = build_function_type_list (opaque_V2SF_type_node, +- opaque_V2SF_type_node, +- opaque_V2SF_type_node, NULL_TREE); +- +- tree v2sf_ftype_v2sf_v2sf +- = build_function_type_list (V2SF_type_node, +- V2SF_type_node, +- V2SF_type_node, NULL_TREE); +- +- +- tree v2si_ftype_int_int +- = build_function_type_list (opaque_V2SI_type_node, +- integer_type_node, integer_type_node, +- NULL_TREE); ++ return ret; ++} + +- tree opaque_ftype_opaque +- = build_function_type_list (opaque_V4SI_type_node, +- opaque_V4SI_type_node, NULL_TREE); ++/* Compare builtin hash entries H1 and H2 for equivalence. */ ++static int ++builtin_hash_eq (const void *h1, const void *h2) ++{ ++ const struct builtin_hash_struct *p1 = (const struct builtin_hash_struct *) h1; ++ const struct builtin_hash_struct *p2 = (const struct builtin_hash_struct *) h2; + +- tree v2si_ftype_v2si +- = build_function_type_list (opaque_V2SI_type_node, +- opaque_V2SI_type_node, NULL_TREE); +- +- tree v2sf_ftype_v2sf_spe +- = build_function_type_list (opaque_V2SF_type_node, +- opaque_V2SF_type_node, NULL_TREE); +- +- tree v2sf_ftype_v2sf +- = build_function_type_list (V2SF_type_node, +- V2SF_type_node, NULL_TREE); +- +- tree v2sf_ftype_v2si +- = build_function_type_list (opaque_V2SF_type_node, +- opaque_V2SI_type_node, NULL_TREE); +- +- tree v2si_ftype_v2sf +- = build_function_type_list (opaque_V2SI_type_node, +- opaque_V2SF_type_node, NULL_TREE); +- +- tree v2si_ftype_v2si_char +- = build_function_type_list (opaque_V2SI_type_node, +- opaque_V2SI_type_node, +- char_type_node, NULL_TREE); +- +- tree v2si_ftype_int_char +- = build_function_type_list (opaque_V2SI_type_node, +- integer_type_node, char_type_node, NULL_TREE); +- +- tree v2si_ftype_char +- = build_function_type_list (opaque_V2SI_type_node, +- char_type_node, NULL_TREE); ++ return ((p1->mode[0] == p2->mode[0]) ++ && (p1->mode[1] == p2->mode[1]) ++ && (p1->mode[2] == p2->mode[2]) ++ && (p1->mode[3] == p2->mode[3])); ++} + +- tree int_ftype_int_int +- = build_function_type_list (integer_type_node, +- integer_type_node, integer_type_node, +- NULL_TREE); ++/* Map selected modes to types for builtins. */ ++static tree builtin_mode_to_type[MAX_MACHINE_MODE]; + +- tree opaque_ftype_opaque_opaque +- = build_function_type_list (opaque_V4SI_type_node, +- opaque_V4SI_type_node, opaque_V4SI_type_node, NULL_TREE); +- tree v4si_ftype_v4si_v4si +- = build_function_type_list (V4SI_type_node, +- V4SI_type_node, V4SI_type_node, NULL_TREE); +- tree v4sf_ftype_v4si_int +- = build_function_type_list (V4SF_type_node, +- V4SI_type_node, integer_type_node, NULL_TREE); +- tree v4si_ftype_v4sf_int +- = build_function_type_list (V4SI_type_node, +- V4SF_type_node, integer_type_node, NULL_TREE); +- tree v4si_ftype_v4si_int +- = build_function_type_list (V4SI_type_node, +- V4SI_type_node, integer_type_node, NULL_TREE); +- tree v8hi_ftype_v8hi_int +- = build_function_type_list (V8HI_type_node, +- V8HI_type_node, integer_type_node, NULL_TREE); +- tree v16qi_ftype_v16qi_int +- = build_function_type_list (V16QI_type_node, +- V16QI_type_node, integer_type_node, NULL_TREE); +- tree v16qi_ftype_v16qi_v16qi_int +- = build_function_type_list (V16QI_type_node, +- V16QI_type_node, V16QI_type_node, +- integer_type_node, NULL_TREE); +- tree v8hi_ftype_v8hi_v8hi_int +- = build_function_type_list (V8HI_type_node, +- V8HI_type_node, V8HI_type_node, +- integer_type_node, NULL_TREE); +- tree v4si_ftype_v4si_v4si_int +- = build_function_type_list (V4SI_type_node, +- V4SI_type_node, V4SI_type_node, +- integer_type_node, NULL_TREE); +- tree v4sf_ftype_v4sf_v4sf_int +- = build_function_type_list (V4SF_type_node, +- V4SF_type_node, V4SF_type_node, +- integer_type_node, NULL_TREE); +- tree v4sf_ftype_v4sf_v4sf +- = build_function_type_list (V4SF_type_node, +- V4SF_type_node, V4SF_type_node, NULL_TREE); +- tree opaque_ftype_opaque_opaque_opaque +- = build_function_type_list (opaque_V4SI_type_node, +- opaque_V4SI_type_node, opaque_V4SI_type_node, +- opaque_V4SI_type_node, NULL_TREE); +- tree v4sf_ftype_v4sf_v4sf_v4si +- = build_function_type_list (V4SF_type_node, +- V4SF_type_node, V4SF_type_node, +- V4SI_type_node, NULL_TREE); +- tree v4sf_ftype_v4sf_v4sf_v4sf +- = build_function_type_list (V4SF_type_node, +- V4SF_type_node, V4SF_type_node, +- V4SF_type_node, NULL_TREE); +- tree v4si_ftype_v4si_v4si_v4si +- = build_function_type_list (V4SI_type_node, +- V4SI_type_node, V4SI_type_node, +- V4SI_type_node, NULL_TREE); +- tree v8hi_ftype_v8hi_v8hi +- = build_function_type_list (V8HI_type_node, +- V8HI_type_node, V8HI_type_node, NULL_TREE); +- tree v8hi_ftype_v8hi_v8hi_v8hi +- = build_function_type_list (V8HI_type_node, +- V8HI_type_node, V8HI_type_node, +- V8HI_type_node, NULL_TREE); +- tree v4si_ftype_v8hi_v8hi_v4si +- = build_function_type_list (V4SI_type_node, +- V8HI_type_node, V8HI_type_node, +- V4SI_type_node, NULL_TREE); +- tree v4si_ftype_v16qi_v16qi_v4si +- = build_function_type_list (V4SI_type_node, +- V16QI_type_node, V16QI_type_node, +- V4SI_type_node, NULL_TREE); +- tree v16qi_ftype_v16qi_v16qi +- = build_function_type_list (V16QI_type_node, +- V16QI_type_node, V16QI_type_node, NULL_TREE); +- tree v4si_ftype_v4sf_v4sf +- = build_function_type_list (V4SI_type_node, +- V4SF_type_node, V4SF_type_node, NULL_TREE); +- tree v8hi_ftype_v16qi_v16qi +- = build_function_type_list (V8HI_type_node, +- V16QI_type_node, V16QI_type_node, NULL_TREE); +- tree v4si_ftype_v8hi_v8hi +- = build_function_type_list (V4SI_type_node, +- V8HI_type_node, V8HI_type_node, NULL_TREE); +- tree v8hi_ftype_v4si_v4si +- = build_function_type_list (V8HI_type_node, +- V4SI_type_node, V4SI_type_node, NULL_TREE); +- tree v16qi_ftype_v8hi_v8hi +- = build_function_type_list (V16QI_type_node, +- V8HI_type_node, V8HI_type_node, NULL_TREE); +- tree v4si_ftype_v16qi_v4si +- = build_function_type_list (V4SI_type_node, +- V16QI_type_node, V4SI_type_node, NULL_TREE); +- tree v4si_ftype_v16qi_v16qi +- = build_function_type_list (V4SI_type_node, +- V16QI_type_node, V16QI_type_node, NULL_TREE); +- tree v4si_ftype_v8hi_v4si +- = build_function_type_list (V4SI_type_node, +- V8HI_type_node, V4SI_type_node, NULL_TREE); +- tree v4si_ftype_v8hi +- = build_function_type_list (V4SI_type_node, V8HI_type_node, NULL_TREE); +- tree int_ftype_v4si_v4si +- = build_function_type_list (integer_type_node, +- V4SI_type_node, V4SI_type_node, NULL_TREE); +- tree int_ftype_v4sf_v4sf +- = build_function_type_list (integer_type_node, +- V4SF_type_node, V4SF_type_node, NULL_TREE); +- tree int_ftype_v16qi_v16qi +- = build_function_type_list (integer_type_node, +- V16QI_type_node, V16QI_type_node, NULL_TREE); +- tree int_ftype_v8hi_v8hi +- = build_function_type_list (integer_type_node, +- V8HI_type_node, V8HI_type_node, NULL_TREE); +- tree v2di_ftype_v2df +- = build_function_type_list (V2DI_type_node, +- V2DF_type_node, NULL_TREE); +- tree v2df_ftype_v2df +- = build_function_type_list (V2DF_type_node, +- V2DF_type_node, NULL_TREE); +- tree v2df_ftype_v2di +- = build_function_type_list (V2DF_type_node, +- V2DI_type_node, NULL_TREE); +- tree v2df_ftype_v2df_v2df +- = build_function_type_list (V2DF_type_node, +- V2DF_type_node, V2DF_type_node, NULL_TREE); +- tree v2df_ftype_v2df_v2df_v2df +- = build_function_type_list (V2DF_type_node, +- V2DF_type_node, V2DF_type_node, +- V2DF_type_node, NULL_TREE); +- tree v2di_ftype_v2di_v2di_v2di +- = build_function_type_list (V2DI_type_node, +- V2DI_type_node, V2DI_type_node, +- V2DI_type_node, NULL_TREE); +- tree v2df_ftype_v2df_v2df_v16qi +- = build_function_type_list (V2DF_type_node, +- V2DF_type_node, V2DF_type_node, +- V16QI_type_node, NULL_TREE); +- tree v2di_ftype_v2di_v2di_v16qi +- = build_function_type_list (V2DI_type_node, +- V2DI_type_node, V2DI_type_node, +- V16QI_type_node, NULL_TREE); +- tree v4sf_ftype_v4si +- = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE); +- tree v4si_ftype_v4sf +- = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE); ++/* Map types for builtin functions with an explicit return type and up to 3 ++ arguments. Functions with fewer than 3 arguments use VOIDmode as the type ++ of the argument. */ ++static tree ++builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0, ++ enum machine_mode mode_arg1, enum machine_mode mode_arg2, ++ const char *name) ++{ ++ struct builtin_hash_struct h; ++ struct builtin_hash_struct *h2; ++ void **found; ++ int num_args = 3; ++ int i; + +- /* Add the simple ternary operators. */ ++ /* Create builtin_hash_table. */ ++ if (builtin_hash_table == NULL) ++ builtin_hash_table = htab_create_ggc (1500, builtin_hash_function, ++ builtin_hash_eq, NULL); ++ ++ h.type = NULL_TREE; ++ h.mode[0] = mode_ret; ++ h.mode[1] = mode_arg0; ++ h.mode[2] = mode_arg1; ++ h.mode[3] = mode_arg2; ++ ++ /* Figure out how many args are present. */ ++ while (num_args > 0 && h.mode[num_args] == VOIDmode) ++ num_args--; ++ ++ if (num_args == 0) ++ fatal_error ("internal error: builtin function %s had no type", name); ++ ++ if (!builtin_mode_to_type[h.mode[0]]) ++ fatal_error ("internal error: builtin function %s had an unexpected " ++ "return type %s", name, GET_MODE_NAME (h.mode[0])); ++ ++ for (i = 0; i < num_args; i++) ++ if (!builtin_mode_to_type[h.mode[i+1]]) ++ fatal_error ("internal error: builtin function %s, argument %d " ++ "had unexpected argument type %s", name, i, ++ GET_MODE_NAME (h.mode[i+1])); ++ ++ found = htab_find_slot (builtin_hash_table, &h, 1); ++ if (*found == NULL) ++ { ++ h2 = GGC_NEW (struct builtin_hash_struct); ++ *h2 = h; ++ *found = (void *)h2; ++ ++ switch (num_args) ++ { ++ case 1: ++ h2->type = build_function_type_list (builtin_mode_to_type[mode_ret], ++ builtin_mode_to_type[mode_arg0], ++ NULL_TREE); ++ break; ++ ++ case 2: ++ h2->type = build_function_type_list (builtin_mode_to_type[mode_ret], ++ builtin_mode_to_type[mode_arg0], ++ builtin_mode_to_type[mode_arg1], ++ NULL_TREE); ++ break; ++ ++ case 3: ++ h2->type = build_function_type_list (builtin_mode_to_type[mode_ret], ++ builtin_mode_to_type[mode_arg0], ++ builtin_mode_to_type[mode_arg1], ++ builtin_mode_to_type[mode_arg2], ++ NULL_TREE); ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ } ++ ++ return ((struct builtin_hash_struct *)(*found))->type; ++} ++ ++static void ++rs6000_common_init_builtins (void) ++{ ++ const struct builtin_description *d; ++ size_t i; ++ ++ tree opaque_ftype_opaque = NULL_TREE; ++ tree opaque_ftype_opaque_opaque = NULL_TREE; ++ tree opaque_ftype_opaque_opaque_opaque = NULL_TREE; ++ tree v2si_ftype_qi = NULL_TREE; ++ tree v2si_ftype_v2si_qi = NULL_TREE; ++ tree v2si_ftype_int_qi = NULL_TREE; ++ ++ /* Initialize the tables for the unary, binary, and ternary ops. */ ++ builtin_mode_to_type[QImode] = integer_type_node; ++ builtin_mode_to_type[HImode] = integer_type_node; ++ builtin_mode_to_type[SImode] = intSI_type_node; ++ builtin_mode_to_type[DImode] = intDI_type_node; ++ builtin_mode_to_type[SFmode] = float_type_node; ++ builtin_mode_to_type[DFmode] = double_type_node; ++ builtin_mode_to_type[V2SImode] = V2SI_type_node; ++ builtin_mode_to_type[V2SFmode] = V2SF_type_node; ++ builtin_mode_to_type[V2DImode] = V2DI_type_node; ++ builtin_mode_to_type[V2DFmode] = V2DF_type_node; ++ builtin_mode_to_type[V4HImode] = V4HI_type_node; ++ builtin_mode_to_type[V4SImode] = V4SI_type_node; ++ builtin_mode_to_type[V4SFmode] = V4SF_type_node; ++ builtin_mode_to_type[V8HImode] = V8HI_type_node; ++ builtin_mode_to_type[V16QImode] = V16QI_type_node; ++ ++ if (!TARGET_PAIRED_FLOAT) ++ { ++ builtin_mode_to_type[V2SImode] = opaque_V2SI_type_node; ++ builtin_mode_to_type[V2SFmode] = opaque_V2SF_type_node; ++ } ++ ++ /* Add the ternary operators. */ + d = bdesc_3arg; + for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++) + { +- enum machine_mode mode0, mode1, mode2, mode3; + tree type; +- bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST +- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST; ++ int mask = d->mask; + +- if (is_overloaded) +- { +- mode0 = VOIDmode; +- mode1 = VOIDmode; +- mode2 = VOIDmode; +- mode3 = VOIDmode; ++ if ((mask != 0 && (mask & target_flags) == 0) ++ || (mask == 0 && !TARGET_PAIRED_FLOAT)) ++ continue; ++ ++ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST ++ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST) ++ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST ++ && d->code <= VSX_BUILTIN_OVERLOADED_LAST)) ++ { ++ if (! (type = opaque_ftype_opaque_opaque_opaque)) ++ type = opaque_ftype_opaque_opaque_opaque ++ = build_function_type_list (opaque_V4SI_type_node, ++ opaque_V4SI_type_node, ++ opaque_V4SI_type_node, ++ opaque_V4SI_type_node, ++ NULL_TREE); + } + else + { +- if (d->name == 0 || d->icode == CODE_FOR_nothing) ++ enum insn_code icode = d->icode; ++ if (d->name == 0 || icode == CODE_FOR_nothing) + continue; + +- mode0 = insn_data[d->icode].operand[0].mode; +- mode1 = insn_data[d->icode].operand[1].mode; +- mode2 = insn_data[d->icode].operand[2].mode; +- mode3 = insn_data[d->icode].operand[3].mode; ++ type = builtin_function_type (insn_data[icode].operand[0].mode, ++ insn_data[icode].operand[1].mode, ++ insn_data[icode].operand[2].mode, ++ insn_data[icode].operand[3].mode, ++ d->name); + } + +- /* When all four are of the same mode. */ +- if (mode0 == mode1 && mode1 == mode2 && mode2 == mode3) +- { +- switch (mode0) +- { +- case VOIDmode: +- type = opaque_ftype_opaque_opaque_opaque; +- break; +- case V2DImode: +- type = v2di_ftype_v2di_v2di_v2di; +- break; +- case V2DFmode: +- type = v2df_ftype_v2df_v2df_v2df; +- break; +- case V4SImode: +- type = v4si_ftype_v4si_v4si_v4si; +- break; +- case V4SFmode: +- type = v4sf_ftype_v4sf_v4sf_v4sf; +- break; +- case V8HImode: +- type = v8hi_ftype_v8hi_v8hi_v8hi; +- break; +- case V16QImode: +- type = v16qi_ftype_v16qi_v16qi_v16qi; +- break; +- case V2SFmode: +- type = v2sf_ftype_v2sf_v2sf_v2sf; +- break; +- default: +- gcc_unreachable (); +- } +- } +- else if (mode0 == mode1 && mode1 == mode2 && mode3 == V16QImode) +- { +- switch (mode0) +- { +- case V2DImode: +- type = v2di_ftype_v2di_v2di_v16qi; +- break; +- case V2DFmode: +- type = v2df_ftype_v2df_v2df_v16qi; +- break; +- case V4SImode: +- type = v4si_ftype_v4si_v4si_v16qi; +- break; +- case V4SFmode: +- type = v4sf_ftype_v4sf_v4sf_v16qi; +- break; +- case V8HImode: +- type = v8hi_ftype_v8hi_v8hi_v16qi; +- break; +- case V16QImode: +- type = v16qi_ftype_v16qi_v16qi_v16qi; +- break; +- default: +- gcc_unreachable (); +- } +- } +- else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode +- && mode3 == V4SImode) +- type = v4si_ftype_v16qi_v16qi_v4si; +- else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode +- && mode3 == V4SImode) +- type = v4si_ftype_v8hi_v8hi_v4si; +- else if (mode0 == V4SFmode && mode1 == V4SFmode && mode2 == V4SFmode +- && mode3 == V4SImode) +- type = v4sf_ftype_v4sf_v4sf_v4si; +- +- /* vchar, vchar, vchar, 4-bit literal. */ +- else if (mode0 == V16QImode && mode1 == mode0 && mode2 == mode0 +- && mode3 == QImode) +- type = v16qi_ftype_v16qi_v16qi_int; +- +- /* vshort, vshort, vshort, 4-bit literal. */ +- else if (mode0 == V8HImode && mode1 == mode0 && mode2 == mode0 +- && mode3 == QImode) +- type = v8hi_ftype_v8hi_v8hi_int; +- +- /* vint, vint, vint, 4-bit literal. */ +- else if (mode0 == V4SImode && mode1 == mode0 && mode2 == mode0 +- && mode3 == QImode) +- type = v4si_ftype_v4si_v4si_int; +- +- /* vfloat, vfloat, vfloat, 4-bit literal. */ +- else if (mode0 == V4SFmode && mode1 == mode0 && mode2 == mode0 +- && mode3 == QImode) +- type = v4sf_ftype_v4sf_v4sf_int; +- +- else +- gcc_unreachable (); +- + def_builtin (d->mask, d->name, type, d->code); + } + +- /* Add the simple binary operators. */ ++ /* Add the binary operators. */ + d = (struct builtin_description *) bdesc_2arg; + for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++) + { + enum machine_mode mode0, mode1, mode2; + tree type; +- bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST +- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST; ++ int mask = d->mask; + +- if (is_overloaded) +- { +- mode0 = VOIDmode; +- mode1 = VOIDmode; +- mode2 = VOIDmode; ++ if ((mask != 0 && (mask & target_flags) == 0) ++ || (mask == 0 && !TARGET_PAIRED_FLOAT)) ++ continue; ++ ++ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST ++ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST) ++ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST ++ && d->code <= VSX_BUILTIN_OVERLOADED_LAST)) ++ { ++ if (! (type = opaque_ftype_opaque_opaque)) ++ type = opaque_ftype_opaque_opaque ++ = build_function_type_list (opaque_V4SI_type_node, ++ opaque_V4SI_type_node, ++ opaque_V4SI_type_node, ++ NULL_TREE); + } + else + { +- if (d->name == 0 || d->icode == CODE_FOR_nothing) ++ enum insn_code icode = d->icode; ++ if (d->name == 0 || icode == CODE_FOR_nothing) + continue; + +- mode0 = insn_data[d->icode].operand[0].mode; +- mode1 = insn_data[d->icode].operand[1].mode; +- mode2 = insn_data[d->icode].operand[2].mode; +- } ++ mode0 = insn_data[icode].operand[0].mode; ++ mode1 = insn_data[icode].operand[1].mode; ++ mode2 = insn_data[icode].operand[2].mode; + +- /* When all three operands are of the same mode. */ +- if (mode0 == mode1 && mode1 == mode2) +- { +- switch (mode0) ++ if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode) + { +- case VOIDmode: +- type = opaque_ftype_opaque_opaque; +- break; +- case V2DFmode: +- type = v2df_ftype_v2df_v2df; +- break; +- case V4SFmode: +- type = v4sf_ftype_v4sf_v4sf; +- break; +- case V4SImode: +- type = v4si_ftype_v4si_v4si; +- break; +- case V16QImode: +- type = v16qi_ftype_v16qi_v16qi; +- break; +- case V8HImode: +- type = v8hi_ftype_v8hi_v8hi; +- break; +- case V2SImode: +- type = v2si_ftype_v2si_v2si; +- break; +- case V2SFmode: +- if (TARGET_PAIRED_FLOAT) +- type = v2sf_ftype_v2sf_v2sf; +- else +- type = v2sf_ftype_v2sf_v2sf_spe; +- break; +- case SImode: +- type = int_ftype_int_int; +- break; +- default: +- gcc_unreachable (); ++ if (! (type = v2si_ftype_v2si_qi)) ++ type = v2si_ftype_v2si_qi ++ = build_function_type_list (opaque_V2SI_type_node, ++ opaque_V2SI_type_node, ++ char_type_node, ++ NULL_TREE); + } +- } +- +- /* A few other combos we really don't want to do manually. */ +- +- /* vint, vfloat, vfloat. */ +- else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode) +- type = v4si_ftype_v4sf_v4sf; +- +- /* vshort, vchar, vchar. */ +- else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode) +- type = v8hi_ftype_v16qi_v16qi; +- +- /* vint, vshort, vshort. */ +- else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode) +- type = v4si_ftype_v8hi_v8hi; +- +- /* vshort, vint, vint. */ +- else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode) +- type = v8hi_ftype_v4si_v4si; +- +- /* vchar, vshort, vshort. */ +- else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode) +- type = v16qi_ftype_v8hi_v8hi; +- +- /* vint, vchar, vint. */ +- else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode) +- type = v4si_ftype_v16qi_v4si; +- +- /* vint, vchar, vchar. */ +- else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode) +- type = v4si_ftype_v16qi_v16qi; +- +- /* vint, vshort, vint. */ +- else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode) +- type = v4si_ftype_v8hi_v4si; + +- /* vint, vint, 5-bit literal. */ +- else if (mode0 == V4SImode && mode1 == V4SImode && mode2 == QImode) +- type = v4si_ftype_v4si_int; +- +- /* vshort, vshort, 5-bit literal. */ +- else if (mode0 == V8HImode && mode1 == V8HImode && mode2 == QImode) +- type = v8hi_ftype_v8hi_int; +- +- /* vchar, vchar, 5-bit literal. */ +- else if (mode0 == V16QImode && mode1 == V16QImode && mode2 == QImode) +- type = v16qi_ftype_v16qi_int; +- +- /* vfloat, vint, 5-bit literal. */ +- else if (mode0 == V4SFmode && mode1 == V4SImode && mode2 == QImode) +- type = v4sf_ftype_v4si_int; +- +- /* vint, vfloat, 5-bit literal. */ +- else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == QImode) +- type = v4si_ftype_v4sf_int; +- +- else if (mode0 == V2SImode && mode1 == SImode && mode2 == SImode) +- type = v2si_ftype_int_int; +- +- else if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode) +- type = v2si_ftype_v2si_char; +- +- else if (mode0 == V2SImode && mode1 == SImode && mode2 == QImode) +- type = v2si_ftype_int_char; +- +- else +- { +- /* int, x, x. */ +- gcc_assert (mode0 == SImode); +- switch (mode1) ++ else if (mode0 == V2SImode && GET_MODE_CLASS (mode1) == MODE_INT ++ && mode2 == QImode) + { +- case V4SImode: +- type = int_ftype_v4si_v4si; +- break; +- case V4SFmode: +- type = int_ftype_v4sf_v4sf; +- break; +- case V16QImode: +- type = int_ftype_v16qi_v16qi; +- break; +- case V8HImode: +- type = int_ftype_v8hi_v8hi; +- break; +- default: +- gcc_unreachable (); ++ if (! (type = v2si_ftype_int_qi)) ++ type = v2si_ftype_int_qi ++ = build_function_type_list (opaque_V2SI_type_node, ++ integer_type_node, ++ char_type_node, ++ NULL_TREE); + } ++ ++ else ++ type = builtin_function_type (mode0, mode1, mode2, VOIDmode, ++ d->name); + } + + def_builtin (d->mask, d->name, type, d->code); + } + +- /* Add the simple unary operators. */ ++ /* Add the unary operators. */ + d = (struct builtin_description *) bdesc_1arg; + for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++) + { + enum machine_mode mode0, mode1; + tree type; +- bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST +- && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST; ++ int mask = d->mask; + +- if (is_overloaded) +- { +- mode0 = VOIDmode; +- mode1 = VOIDmode; +- } ++ if ((mask != 0 && (mask & target_flags) == 0) ++ || (mask == 0 && !TARGET_PAIRED_FLOAT)) ++ continue; ++ ++ if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST ++ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST) ++ || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST ++ && d->code <= VSX_BUILTIN_OVERLOADED_LAST)) ++ { ++ if (! (type = opaque_ftype_opaque)) ++ type = opaque_ftype_opaque ++ = build_function_type_list (opaque_V4SI_type_node, ++ opaque_V4SI_type_node, ++ NULL_TREE); ++ } + else + { +- if (d->name == 0 || d->icode == CODE_FOR_nothing) ++ enum insn_code icode = d->icode; ++ if (d->name == 0 || icode == CODE_FOR_nothing) + continue; + +- mode0 = insn_data[d->icode].operand[0].mode; +- mode1 = insn_data[d->icode].operand[1].mode; +- } ++ mode0 = insn_data[icode].operand[0].mode; ++ mode1 = insn_data[icode].operand[1].mode; + +- if (mode0 == V4SImode && mode1 == QImode) +- type = v4si_ftype_int; +- else if (mode0 == V8HImode && mode1 == QImode) +- type = v8hi_ftype_int; +- else if (mode0 == V16QImode && mode1 == QImode) +- type = v16qi_ftype_int; +- else if (mode0 == VOIDmode && mode1 == VOIDmode) +- type = opaque_ftype_opaque; +- else if (mode0 == V2DFmode && mode1 == V2DFmode) +- type = v2df_ftype_v2df; +- else if (mode0 == V4SFmode && mode1 == V4SFmode) +- type = v4sf_ftype_v4sf; +- else if (mode0 == V8HImode && mode1 == V16QImode) +- type = v8hi_ftype_v16qi; +- else if (mode0 == V4SImode && mode1 == V8HImode) +- type = v4si_ftype_v8hi; +- else if (mode0 == V2SImode && mode1 == V2SImode) +- type = v2si_ftype_v2si; +- else if (mode0 == V2SFmode && mode1 == V2SFmode) +- { +- if (TARGET_PAIRED_FLOAT) +- type = v2sf_ftype_v2sf; +- else +- type = v2sf_ftype_v2sf_spe; +- } +- else if (mode0 == V2SFmode && mode1 == V2SImode) +- type = v2sf_ftype_v2si; +- else if (mode0 == V2SImode && mode1 == V2SFmode) +- type = v2si_ftype_v2sf; +- else if (mode0 == V2SImode && mode1 == QImode) +- type = v2si_ftype_char; +- else if (mode0 == V4SImode && mode1 == V4SFmode) +- type = v4si_ftype_v4sf; +- else if (mode0 == V4SFmode && mode1 == V4SImode) +- type = v4sf_ftype_v4si; +- else if (mode0 == V2DImode && mode1 == V2DFmode) +- type = v2di_ftype_v2df; +- else if (mode0 == V2DFmode && mode1 == V2DImode) +- type = v2df_ftype_v2di; +- else +- gcc_unreachable (); ++ if (mode0 == V2SImode && mode1 == QImode) ++ { ++ if (! (type = v2si_ftype_qi)) ++ type = v2si_ftype_qi ++ = build_function_type_list (opaque_V2SI_type_node, ++ char_type_node, ++ NULL_TREE); ++ } ++ ++ else ++ type = builtin_function_type (mode0, mode1, VOIDmode, VOIDmode, ++ d->name); ++ } + + def_builtin (d->mask, d->name, type, d->code); + } +@@ -12637,12 +12557,12 @@ rs6000_secondary_reload_inner (rtx reg, + } + + if (GET_CODE (addr) == PLUS +- && (!rs6000_legitimate_offset_address_p (TImode, addr, true) ++ && (!rs6000_legitimate_offset_address_p (TImode, addr, false) + || and_op2 != NULL_RTX)) + { + addr_op1 = XEXP (addr, 0); + addr_op2 = XEXP (addr, 1); +- gcc_assert (legitimate_indirect_address_p (addr_op1, true)); ++ gcc_assert (legitimate_indirect_address_p (addr_op1, false)); + + if (!REG_P (addr_op2) + && (GET_CODE (addr_op2) != CONST_INT +@@ -12661,8 +12581,8 @@ rs6000_secondary_reload_inner (rtx reg, + addr = scratch_or_premodify; + scratch_or_premodify = scratch; + } +- else if (!legitimate_indirect_address_p (addr, true) +- && !rs6000_legitimate_offset_address_p (TImode, addr, true)) ++ else if (!legitimate_indirect_address_p (addr, false) ++ && !rs6000_legitimate_offset_address_p (TImode, addr, false)) + { + rs6000_emit_move (scratch_or_premodify, addr, Pmode); + addr = scratch_or_premodify; +@@ -12691,24 +12611,24 @@ rs6000_secondary_reload_inner (rtx reg, + if (GET_CODE (addr) == PRE_MODIFY + && (!VECTOR_MEM_VSX_P (mode) + || and_op2 != NULL_RTX +- || !legitimate_indexed_address_p (XEXP (addr, 1), true))) ++ || !legitimate_indexed_address_p (XEXP (addr, 1), false))) + { + scratch_or_premodify = XEXP (addr, 0); + gcc_assert (legitimate_indirect_address_p (scratch_or_premodify, +- true)); ++ false)); + gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS); + addr = XEXP (addr, 1); + } + +- if (legitimate_indirect_address_p (addr, true) /* reg */ +- || legitimate_indexed_address_p (addr, true) /* reg+reg */ ++ if (legitimate_indirect_address_p (addr, false) /* reg */ ++ || legitimate_indexed_address_p (addr, false) /* reg+reg */ + || GET_CODE (addr) == PRE_MODIFY /* VSX pre-modify */ + || GET_CODE (addr) == AND /* Altivec memory */ + || (rclass == FLOAT_REGS /* legacy float mem */ + && GET_MODE_SIZE (mode) == 8 + && and_op2 == NULL_RTX + && scratch_or_premodify == scratch +- && rs6000_legitimate_offset_address_p (mode, addr, true))) ++ && rs6000_legitimate_offset_address_p (mode, addr, false))) + ; + + else if (GET_CODE (addr) == PLUS) +@@ -12728,7 +12648,7 @@ rs6000_secondary_reload_inner (rtx reg, + } + + else if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST +- || GET_CODE (addr) == CONST_INT) ++ || GET_CODE (addr) == CONST_INT || REG_P (addr)) + { + rs6000_emit_move (scratch_or_premodify, addr, Pmode); + addr = scratch_or_premodify; +@@ -12760,7 +12680,7 @@ rs6000_secondary_reload_inner (rtx reg, + andi. instruction. */ + if (and_op2 != NULL_RTX) + { +- if (! legitimate_indirect_address_p (addr, true)) ++ if (! legitimate_indirect_address_p (addr, false)) + { + emit_insn (gen_rtx_SET (VOIDmode, scratch, addr)); + addr = scratch; +@@ -12795,6 +12715,26 @@ rs6000_secondary_reload_inner (rtx reg, + return; + } + ++/* Target hook to return the cover classes for Integrated Register Allocator. ++ Cover classes is a set of non-intersected register classes covering all hard ++ registers used for register allocation purpose. Any move between two ++ registers of a cover class should be cheaper than load or store of the ++ registers. The value is array of register classes with LIM_REG_CLASSES used ++ as the end marker. ++ ++ We need two IRA_COVER_CLASSES, one for pre-VSX, and the other for VSX to ++ account for the Altivec and Floating registers being subsets of the VSX ++ register set under VSX, but distinct register sets on pre-VSX machines. */ ++ ++static const enum reg_class * ++rs6000_ira_cover_classes (void) ++{ ++ static const enum reg_class cover_pre_vsx[] = IRA_COVER_CLASSES_PRE_VSX; ++ static const enum reg_class cover_vsx[] = IRA_COVER_CLASSES_VSX; ++ ++ return (TARGET_VSX) ? cover_vsx : cover_pre_vsx; ++} ++ + /* Allocate a 64-bit stack slot to be used for copying SDmode + values through if this function has any SDmode references. */ + +@@ -12868,13 +12808,15 @@ rs6000_preferred_reload_class (rtx x, en + enum machine_mode mode = GET_MODE (x); + enum reg_class ret; + +- if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode) +- && VSX_REG_CLASS_P (rclass)) ++ if (TARGET_VSX ++ && (VSX_VECTOR_MODE (mode) || mode == TImode) ++ && x == CONST0_RTX (mode) && VSX_REG_CLASS_P (rclass)) + ret = rclass; + +- else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) +- && rclass == ALTIVEC_REGS && easy_vector_constant (x, mode)) +- ret = rclass; ++ else if (TARGET_ALTIVEC && (ALTIVEC_VECTOR_MODE (mode) || mode == TImode) ++ && (rclass == ALTIVEC_REGS || rclass == VSX_REGS) ++ && easy_vector_constant (x, mode)) ++ ret = ALTIVEC_REGS; + + else if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS)) + ret = NO_REGS; +@@ -13093,8 +13035,10 @@ rs6000_cannot_change_mode_class (enum ma + || (((to) == TDmode) + ((from) == TDmode)) == 1 + || (((to) == DImode) + ((from) == DImode)) == 1)) + || (TARGET_VSX +- && (VSX_VECTOR_MODE (from) + VSX_VECTOR_MODE (to)) == 1) ++ && (VSX_MOVE_MODE (from) + VSX_MOVE_MODE (to)) == 1 ++ && VSX_REG_CLASS_P (rclass)) + || (TARGET_ALTIVEC ++ && rclass == ALTIVEC_REGS + && (ALTIVEC_VECTOR_MODE (from) + + ALTIVEC_VECTOR_MODE (to)) == 1) + || (TARGET_SPE +@@ -14972,7 +14916,7 @@ rs6000_emit_vector_cond_expr (rtx dest, + if (!mask) + return 0; + +- if ((TARGET_VSX && VSX_VECTOR_MOVE_MODE (dest_mode)) ++ if ((TARGET_VSX && VSX_MOVE_MODE (dest_mode)) + || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dest_mode))) + { + rtx cond2 = gen_rtx_fmt_ee (NE, VOIDmode, mask, const0_rtx); +@@ -22161,7 +22105,8 @@ rs6000_handle_altivec_attribute (tree *n + mode = TYPE_MODE (type); + + /* Check for invalid AltiVec type qualifiers. */ +- if (type == long_unsigned_type_node || type == long_integer_type_node) ++ if ((type == long_unsigned_type_node || type == long_integer_type_node) ++ && !TARGET_VSX) + { + if (TARGET_64BIT) + error ("use of % in AltiVec types is invalid for 64-bit code"); +@@ -22199,6 +22144,7 @@ rs6000_handle_altivec_attribute (tree *n + break; + case SFmode: result = V4SF_type_node; break; + case DFmode: result = V2DF_type_node; break; ++ case DImode: result = V2DI_type_node; break; + /* If the user says 'vector int bool', we may be handed the 'bool' + attribute _before_ the 'vector' attribute, and so select the + proper type in the 'b' case below. */ +@@ -22210,6 +22156,7 @@ rs6000_handle_altivec_attribute (tree *n + case 'b': + switch (mode) + { ++ case DImode: case V2DImode: result = bool_V2DI_type_node; break; + case SImode: case V4SImode: result = bool_V4SI_type_node; break; + case HImode: case V8HImode: result = bool_V8HI_type_node; break; + case QImode: case V16QImode: result = bool_V16QI_type_node; +@@ -22254,6 +22201,7 @@ rs6000_mangle_type (const_tree type) + if (type == bool_short_type_node) return "U6__bools"; + if (type == pixel_type_node) return "u7__pixel"; + if (type == bool_int_type_node) return "U6__booli"; ++ if (type == bool_long_type_node) return "U6__booll"; + + /* Mangle IBM extended float long double as `g' (__float128) on + powerpc*-linux where long-double-64 previously was the default. */ +@@ -23781,6 +23729,8 @@ int + rs6000_register_move_cost (enum machine_mode mode, + enum reg_class from, enum reg_class to) + { ++ int ret; ++ + /* Moves from/to GENERAL_REGS. */ + if (reg_classes_intersect_p (to, GENERAL_REGS) + || reg_classes_intersect_p (from, GENERAL_REGS)) +@@ -23789,39 +23739,47 @@ rs6000_register_move_cost (enum machine_ + from = to; + + if (from == FLOAT_REGS || from == ALTIVEC_REGS || from == VSX_REGS) +- return (rs6000_memory_move_cost (mode, from, 0) +- + rs6000_memory_move_cost (mode, GENERAL_REGS, 0)); ++ ret = (rs6000_memory_move_cost (mode, from, 0) ++ + rs6000_memory_move_cost (mode, GENERAL_REGS, 0)); + + /* It's more expensive to move CR_REGS than CR0_REGS because of the + shift. */ + else if (from == CR_REGS) +- return 4; ++ ret = 4; + + /* Power6 has slower LR/CTR moves so make them more expensive than + memory in order to bias spills to memory .*/ + else if (rs6000_cpu == PROCESSOR_POWER6 + && reg_classes_intersect_p (from, LINK_OR_CTR_REGS)) +- return 6 * hard_regno_nregs[0][mode]; ++ ret = 6 * hard_regno_nregs[0][mode]; + + else + /* A move will cost one instruction per GPR moved. */ +- return 2 * hard_regno_nregs[0][mode]; ++ ret = 2 * hard_regno_nregs[0][mode]; + } + + /* If we have VSX, we can easily move between FPR or Altivec registers. */ +- else if (TARGET_VSX +- && ((from == VSX_REGS || from == FLOAT_REGS || from == ALTIVEC_REGS) +- || (to == VSX_REGS || to == FLOAT_REGS || to == ALTIVEC_REGS))) +- return 2; ++ else if (VECTOR_UNIT_VSX_P (mode) ++ && reg_classes_intersect_p (to, VSX_REGS) ++ && reg_classes_intersect_p (from, VSX_REGS)) ++ ret = 2 * hard_regno_nregs[32][mode]; + + /* Moving between two similar registers is just one instruction. */ + else if (reg_classes_intersect_p (to, from)) +- return (mode == TFmode || mode == TDmode) ? 4 : 2; ++ ret = (mode == TFmode || mode == TDmode) ? 4 : 2; + + /* Everything else has to go through GENERAL_REGS. */ + else +- return (rs6000_register_move_cost (mode, GENERAL_REGS, to) +- + rs6000_register_move_cost (mode, from, GENERAL_REGS)); ++ ret = (rs6000_register_move_cost (mode, GENERAL_REGS, to) ++ + rs6000_register_move_cost (mode, from, GENERAL_REGS)); ++ ++ if (TARGET_DEBUG_COST) ++ fprintf (stderr, ++ "rs6000_register_move_cost:, ret=%d, mode=%s, from=%s, to=%s\n", ++ ret, GET_MODE_NAME (mode), reg_class_names[from], ++ reg_class_names[to]); ++ ++ return ret; + } + + /* A C expressions returning the cost of moving data of MODE from a register to +@@ -23831,14 +23789,23 @@ int + rs6000_memory_move_cost (enum machine_mode mode, enum reg_class rclass, + int in ATTRIBUTE_UNUSED) + { ++ int ret; ++ + if (reg_classes_intersect_p (rclass, GENERAL_REGS)) +- return 4 * hard_regno_nregs[0][mode]; ++ ret = 4 * hard_regno_nregs[0][mode]; + else if (reg_classes_intersect_p (rclass, FLOAT_REGS)) +- return 4 * hard_regno_nregs[32][mode]; ++ ret = 4 * hard_regno_nregs[32][mode]; + else if (reg_classes_intersect_p (rclass, ALTIVEC_REGS)) +- return 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode]; ++ ret = 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode]; + else +- return 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS); ++ ret = 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS); ++ ++ if (TARGET_DEBUG_COST) ++ fprintf (stderr, ++ "rs6000_memory_move_cost: ret=%d, mode=%s, rclass=%s, in=%d\n", ++ ret, GET_MODE_NAME (mode), reg_class_names[rclass], in); ++ ++ return ret; + } + + /* Returns a code for a target-specific builtin that implements +@@ -24546,4 +24513,24 @@ rs6000_final_prescan_insn (rtx insn, rtx + } + } + ++/* Return true if the function has an indirect jump or a table jump. The compiler ++ prefers the ctr register for such jumps, which interferes with using the decrement ++ ctr register and branch. */ ++ ++bool ++rs6000_has_indirect_jump_p (void) ++{ ++ gcc_assert (cfun && cfun->machine); ++ return cfun->machine->indirect_jump_p; ++} ++ ++/* Remember when we've generated an indirect jump. */ ++ ++void ++rs6000_set_indirect_jump (void) ++{ ++ gcc_assert (cfun && cfun->machine); ++ cfun->machine->indirect_jump_p = true; ++} ++ + #include "gt-rs6000.h" +--- gcc/config/rs6000/vsx.md (revision 146119) ++++ gcc/config/rs6000/vsx.md (revision 146798) +@@ -22,12 +22,22 @@ + ;; Iterator for both scalar and vector floating point types supported by VSX + (define_mode_iterator VSX_B [DF V4SF V2DF]) + ++;; Iterator for the 2 64-bit vector types ++(define_mode_iterator VSX_D [V2DF V2DI]) ++ ++;; Iterator for the 2 32-bit vector types ++(define_mode_iterator VSX_W [V4SF V4SI]) ++ + ;; Iterator for vector floating point types supported by VSX + (define_mode_iterator VSX_F [V4SF V2DF]) + + ;; Iterator for logical types supported by VSX + (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI]) + ++;; Iterator for memory move. Handle TImode specially to allow ++;; it to use gprs as well as vsx registers. ++(define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF]) ++ + ;; Iterator for types for load/store with update + (define_mode_iterator VSX_U [V16QI V8HI V4SI V2DI V4SF V2DF TI DF]) + +@@ -49,9 +59,10 @@ (define_mode_attr VSs [(V16QI "sp") + (V2DF "dp") + (V2DI "dp") + (DF "dp") ++ (SF "sp") + (TI "sp")]) + +-;; Map into the register class used ++;; Map the register class used + (define_mode_attr VSr [(V16QI "v") + (V8HI "v") + (V4SI "v") +@@ -59,9 +70,10 @@ (define_mode_attr VSr [(V16QI "v") + (V2DI "wd") + (V2DF "wd") + (DF "ws") ++ (SF "f") + (TI "wd")]) + +-;; Map into the register class used for float<->int conversions ++;; Map the register class used for float<->int conversions + (define_mode_attr VSr2 [(V2DF "wd") + (V4SF "wf") + (DF "!f#r")]) +@@ -70,6 +82,18 @@ (define_mode_attr VSr3 [(V2DF "wa") + (V4SF "wa") + (DF "!f#r")]) + ++;; Map the register class for sp<->dp float conversions, destination ++(define_mode_attr VSr4 [(SF "ws") ++ (DF "f") ++ (V2DF "wd") ++ (V4SF "v")]) ++ ++;; Map the register class for sp<->dp float conversions, destination ++(define_mode_attr VSr5 [(SF "ws") ++ (DF "f") ++ (V2DF "v") ++ (V4SF "wd")]) ++ + ;; Same size integer type for floating point data + (define_mode_attr VSi [(V4SF "v4si") + (V2DF "v2di") +@@ -137,6 +161,32 @@ (define_mode_attr VSfptype_sqrt [(V2DF " + (V4SF "fp_sqrt_s") + (DF "fp_sqrt_d")]) + ++;; Iterator and modes for sp<->dp conversions ++(define_mode_iterator VSX_SPDP [SF DF V4SF V2DF]) ++ ++(define_mode_attr VS_spdp_res [(SF "DF") ++ (DF "SF") ++ (V4SF "V2DF") ++ (V2DF "V4SF")]) ++ ++(define_mode_attr VS_spdp_insn [(SF "xscvspdp") ++ (DF "xscvdpsp") ++ (V4SF "xvcvspdp") ++ (V2DF "xvcvdpsp")]) ++ ++(define_mode_attr VS_spdp_type [(SF "fp") ++ (DF "fp") ++ (V4SF "vecfloat") ++ (V2DF "vecfloat")]) ++ ++;; Map the scalar mode for a vector type ++(define_mode_attr VS_scalar [(V2DF "DF") ++ (V2DI "DI") ++ (V4SF "SF") ++ (V4SI "SI") ++ (V8HI "HI") ++ (V16QI "QI")]) ++ + ;; Appropriate type for load + update + (define_mode_attr VStype_load_update [(V16QI "vecload") + (V8HI "vecload") +@@ -159,25 +209,33 @@ (define_mode_attr VStype_store_update [( + + ;; Constants for creating unspecs + (define_constants +- [(UNSPEC_VSX_CONCAT_V2DF 500) +- (UNSPEC_VSX_XVCVDPSP 501) +- (UNSPEC_VSX_XVCVDPSXWS 502) +- (UNSPEC_VSX_XVCVDPUXWS 503) +- (UNSPEC_VSX_XVCVSPDP 504) +- (UNSPEC_VSX_XVCVSXWDP 505) +- (UNSPEC_VSX_XVCVUXWDP 506) +- (UNSPEC_VSX_XVMADD 507) +- (UNSPEC_VSX_XVMSUB 508) +- (UNSPEC_VSX_XVNMADD 509) +- (UNSPEC_VSX_XVNMSUB 510) +- (UNSPEC_VSX_XVRSQRTE 511) +- (UNSPEC_VSX_XVTDIV 512) +- (UNSPEC_VSX_XVTSQRT 513)]) ++ [(UNSPEC_VSX_CONCAT 500) ++ (UNSPEC_VSX_CVDPSXWS 501) ++ (UNSPEC_VSX_CVDPUXWS 502) ++ (UNSPEC_VSX_CVSPDP 503) ++ (UNSPEC_VSX_CVSXWDP 504) ++ (UNSPEC_VSX_CVUXWDP 505) ++ (UNSPEC_VSX_CVSXDSP 506) ++ (UNSPEC_VSX_CVUXDSP 507) ++ (UNSPEC_VSX_CVSPSXDS 508) ++ (UNSPEC_VSX_CVSPUXDS 509) ++ (UNSPEC_VSX_MADD 510) ++ (UNSPEC_VSX_MSUB 511) ++ (UNSPEC_VSX_NMADD 512) ++ (UNSPEC_VSX_NMSUB 513) ++ (UNSPEC_VSX_RSQRTE 514) ++ (UNSPEC_VSX_TDIV 515) ++ (UNSPEC_VSX_TSQRT 516) ++ (UNSPEC_VSX_XXPERMDI 517) ++ (UNSPEC_VSX_SET 518) ++ (UNSPEC_VSX_ROUND_I 519) ++ (UNSPEC_VSX_ROUND_IC 520) ++ (UNSPEC_VSX_SLDWI 521)]) + + ;; VSX moves + (define_insn "*vsx_mov" +- [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,,,?Z,?wa,?wa,*o,*r,*r,,?wa,v,wZ,v") +- (match_operand:VSX_L 1 "input_operand" ",Z,,wa,Z,wa,r,o,r,j,j,W,v,wZ"))] ++ [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,,,?Z,?wa,?wa,*o,*r,*r,,?wa,v,wZ,v") ++ (match_operand:VSX_M 1 "input_operand" ",Z,,wa,Z,wa,r,o,r,j,j,W,v,wZ"))] + "VECTOR_MEM_VSX_P (mode) + && (register_operand (operands[0], mode) + || register_operand (operands[1], mode))" +@@ -220,6 +278,49 @@ (define_insn "*vsx_mov" + } + [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")]) + ++;; Unlike other VSX moves, allow the GPRs, since a normal use of TImode is for ++;; unions. However for plain data movement, slightly favor the vector loads ++(define_insn "*vsx_movti" ++ [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,wa,wa,?o,?r,?r,wa,v,v,wZ") ++ (match_operand:TI 1 "input_operand" "wa,Z,wa,r,o,r,j,W,wZ,v"))] ++ "VECTOR_MEM_VSX_P (TImode) ++ && (register_operand (operands[0], TImode) ++ || register_operand (operands[1], TImode))" ++{ ++ switch (which_alternative) ++ { ++ case 0: ++ return "stxvd2%U0x %x1,%y0"; ++ ++ case 1: ++ return "lxvd2%U0x %x0,%y1"; ++ ++ case 2: ++ return "xxlor %x0,%x1,%x1"; ++ ++ case 3: ++ case 4: ++ case 5: ++ return "#"; ++ ++ case 6: ++ return "xxlxor %x0,%x0,%x0"; ++ ++ case 7: ++ return output_vec_const_move (operands); ++ ++ case 8: ++ return "stvx %1,%y0"; ++ ++ case 9: ++ return "lvx %0,%y1"; ++ ++ default: ++ gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "vecstore,vecload,vecsimple,*,*,*,vecsimple,*,vecstore,vecload")]) ++ + ;; Load/store with update + ;; Define insns that do load or store with update. Because VSX only has + ;; reg+reg addressing, pre-decrement or pre-inrement is unlikely to be +@@ -297,7 +398,7 @@ (define_insn "vsx_tdiv3" + [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") + (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa") + (match_operand:VSX_B 2 "vsx_register_operand" ",wa")] +- UNSPEC_VSX_XVTDIV))] ++ UNSPEC_VSX_TDIV))] + "VECTOR_UNIT_VSX_P (mode)" + "xtdiv %x0,%x1,%x2" + [(set_attr "type" "") +@@ -367,7 +468,7 @@ (define_insn "*vsx_sqrt2" + (define_insn "vsx_rsqrte2" + [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") + (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] +- UNSPEC_VSX_XVRSQRTE))] ++ UNSPEC_VSX_RSQRTE))] + "VECTOR_UNIT_VSX_P (mode)" + "xrsqrte %x0,%x1" + [(set_attr "type" "") +@@ -376,7 +477,7 @@ (define_insn "vsx_rsqrte2" + (define_insn "vsx_tsqrt2" + [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") + (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] +- UNSPEC_VSX_XVTSQRT))] ++ UNSPEC_VSX_TSQRT))] + "VECTOR_UNIT_VSX_P (mode)" + "xtsqrt %x0,%x1" + [(set_attr "type" "") +@@ -426,7 +527,7 @@ (define_insn "vsx_fmadd4_2" + (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") + (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0") + (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")] +- UNSPEC_VSX_XVMADD))] ++ UNSPEC_VSX_MADD))] + "VECTOR_UNIT_VSX_P (mode)" + "@ + xmadda %x0,%x1,%x2 +@@ -474,7 +575,7 @@ (define_insn "vsx_fmsub4_2" + (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") + (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0") + (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")] +- UNSPEC_VSX_XVMSUB))] ++ UNSPEC_VSX_MSUB))] + "VECTOR_UNIT_VSX_P (mode)" + "@ + xmsuba %x0,%x1,%x2 +@@ -552,7 +653,7 @@ (define_insn "vsx_fnmadd4_3" + (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",,wa,wa") + (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0") + (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")] +- UNSPEC_VSX_XVNMADD))] ++ UNSPEC_VSX_NMADD))] + "VECTOR_UNIT_VSX_P (mode)" + "@ + xnmadda %x0,%x1,%x2 +@@ -629,7 +730,7 @@ (define_insn "vsx_fnmsub4_3" + (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") + (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0") + (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")] +- UNSPEC_VSX_XVNMSUB))] ++ UNSPEC_VSX_NMSUB))] + "VECTOR_UNIT_VSX_P (mode)" + "@ + xnmsuba %x0,%x1,%x2 +@@ -667,13 +768,13 @@ (define_insn "*vsx_ge" + [(set_attr "type" "") + (set_attr "fp_type" "")]) + +-(define_insn "vsx_vsel" +- [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,?wa") +- (if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" ",wa") ++(define_insn "*vsx_vsel" ++ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=,?wa") ++ (if_then_else:VSX_L (ne (match_operand:VSX_L 1 "vsx_register_operand" ",wa") + (const_int 0)) +- (match_operand:VSX_F 2 "vsx_register_operand" ",wa") +- (match_operand:VSX_F 3 "vsx_register_operand" ",wa")))] +- "VECTOR_UNIT_VSX_P (mode)" ++ (match_operand:VSX_L 2 "vsx_register_operand" ",wa") ++ (match_operand:VSX_L 3 "vsx_register_operand" ",wa")))] ++ "VECTOR_MEM_VSX_P (mode)" + "xxsel %x0,%x3,%x2,%x1" + [(set_attr "type" "vecperm")]) + +@@ -698,7 +799,7 @@ (define_insn "vsx_ftrunc2" + [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") + (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" +- "xrpiz %x0,%x1" ++ "xriz %x0,%x1" + [(set_attr "type" "") + (set_attr "fp_type" "")]) + +@@ -735,6 +836,24 @@ (define_insn "vsx_fixuns_trunc")]) + + ;; Math rounding functions ++(define_insn "vsx_xri" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] ++ UNSPEC_VSX_ROUND_I))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xri %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_insn "vsx_xric" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] ++ UNSPEC_VSX_ROUND_IC))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xric %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ + (define_insn "vsx_btrunc2" + [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") + (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] +@@ -765,22 +884,26 @@ (define_insn "vsx_ceil2" + + ;; VSX convert to/from double vector + ++;; Convert between single and double precision ++;; Don't use xscvspdp and xscvdpsp for scalar conversions, since the normal ++;; scalar single precision instructions internally use the double format. ++;; Prefer the altivec registers, since we likely will need to do a vperm ++(define_insn "vsx_" ++ [(set (match_operand: 0 "vsx_register_operand" "=,?wa") ++ (unspec: [(match_operand:VSX_SPDP 1 "vsx_register_operand" ",wa")] ++ UNSPEC_VSX_CVSPDP))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ " %x0,%x1" ++ [(set_attr "type" "")]) ++ + ;; Convert from 64-bit to 32-bit types + ;; Note, favor the Altivec registers since the usual use of these instructions + ;; is in vector converts and we need to use the Altivec vperm instruction. + +-(define_insn "vsx_xvcvdpsp" +- [(set (match_operand:V4SF 0 "vsx_register_operand" "=v,?wa") +- (unspec:V4SF [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")] +- UNSPEC_VSX_XVCVDPSP))] +- "VECTOR_UNIT_VSX_P (V2DFmode)" +- "xvcvdpsp %x0,%x1" +- [(set_attr "type" "vecfloat")]) +- + (define_insn "vsx_xvcvdpsxws" + [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa") + (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")] +- UNSPEC_VSX_XVCVDPSXWS))] ++ UNSPEC_VSX_CVDPSXWS))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xvcvdpsxws %x0,%x1" + [(set_attr "type" "vecfloat")]) +@@ -788,24 +911,32 @@ (define_insn "vsx_xvcvdpsxws" + (define_insn "vsx_xvcvdpuxws" + [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa") + (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")] +- UNSPEC_VSX_XVCVDPUXWS))] ++ UNSPEC_VSX_CVDPUXWS))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xvcvdpuxws %x0,%x1" + [(set_attr "type" "vecfloat")]) + +-;; Convert from 32-bit to 64-bit types +-(define_insn "vsx_xvcvspdp" +- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") +- (unspec:V2DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")] +- UNSPEC_VSX_XVCVSPDP))] ++(define_insn "vsx_xvcvsxdsp" ++ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa") ++ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")] ++ UNSPEC_VSX_CVSXDSP))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvsxdsp %x0,%x1" ++ [(set_attr "type" "vecfloat")]) ++ ++(define_insn "vsx_xvcvuxdsp" ++ [(set (match_operand:V4SI 0 "vsx_register_operand" "=wd,?wa") ++ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wf,wa")] ++ UNSPEC_VSX_CVUXDSP))] + "VECTOR_UNIT_VSX_P (V2DFmode)" +- "xvcvspdp %x0,%x1" ++ "xvcvuxwdp %x0,%x1" + [(set_attr "type" "vecfloat")]) + ++;; Convert from 32-bit to 64-bit types + (define_insn "vsx_xvcvsxwdp" + [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") + (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")] +- UNSPEC_VSX_XVCVSXWDP))] ++ UNSPEC_VSX_CVSXWDP))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xvcvsxwdp %x0,%x1" + [(set_attr "type" "vecfloat")]) +@@ -813,11 +944,26 @@ (define_insn "vsx_xvcvsxwdp" + (define_insn "vsx_xvcvuxwdp" + [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") + (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")] +- UNSPEC_VSX_XVCVUXWDP))] ++ UNSPEC_VSX_CVUXWDP))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xvcvuxwdp %x0,%x1" + [(set_attr "type" "vecfloat")]) + ++(define_insn "vsx_xvcvspsxds" ++ [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa") ++ (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")] ++ UNSPEC_VSX_CVSPSXDS))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvspsxds %x0,%x1" ++ [(set_attr "type" "vecfloat")]) ++ ++(define_insn "vsx_xvcvspuxds" ++ [(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa") ++ (unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")] ++ UNSPEC_VSX_CVSPUXDS))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvspuxds %x0,%x1" ++ [(set_attr "type" "vecfloat")]) + + ;; Logical and permute operations + (define_insn "*vsx_and3" +@@ -877,24 +1023,25 @@ (define_insn "*vsx_andc3" + + ;; Permute operations + +-(define_insn "vsx_concat_v2df" +- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") +- (unspec:V2DF +- [(match_operand:DF 1 "vsx_register_operand" "ws,wa") +- (match_operand:DF 2 "vsx_register_operand" "ws,wa")] +- UNSPEC_VSX_CONCAT_V2DF))] +- "VECTOR_UNIT_VSX_P (V2DFmode)" ++;; Build a V2DF/V2DI vector from two scalars ++(define_insn "vsx_concat_" ++ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa") ++ (unspec:VSX_D ++ [(match_operand: 1 "vsx_register_operand" "ws,wa") ++ (match_operand: 2 "vsx_register_operand" "ws,wa")] ++ UNSPEC_VSX_CONCAT))] ++ "VECTOR_MEM_VSX_P (mode)" + "xxpermdi %x0,%x1,%x2,0" + [(set_attr "type" "vecperm")]) + +-;; Set a double into one element +-(define_insn "vsx_set_v2df" +- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") +- (vec_merge:V2DF +- (match_operand:V2DF 1 "vsx_register_operand" "wd,wa") +- (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws,f")) +- (match_operand:QI 3 "u5bit_cint_operand" "i,i")))] +- "VECTOR_UNIT_VSX_P (V2DFmode)" ++;; Set the element of a V2DI/VD2F mode ++(define_insn "vsx_set_" ++ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa") ++ (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa") ++ (match_operand: 2 "vsx_register_operand" "ws,wa") ++ (match_operand:QI 3 "u5bit_cint_operand" "i,i")] ++ UNSPEC_VSX_SET))] ++ "VECTOR_MEM_VSX_P (mode)" + { + if (INTVAL (operands[3]) == 0) + return \"xxpermdi %x0,%x1,%x2,1\"; +@@ -906,12 +1053,12 @@ (define_insn "vsx_set_v2df" + [(set_attr "type" "vecperm")]) + + ;; Extract a DF element from V2DF +-(define_insn "vsx_extract_v2df" +- [(set (match_operand:DF 0 "vsx_register_operand" "=ws,f,?wa") +- (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd,wd,wa") ++(define_insn "vsx_extract_" ++ [(set (match_operand: 0 "vsx_register_operand" "=ws,f,?wa") ++ (vec_select: (match_operand:VSX_D 1 "vsx_register_operand" "wd,wd,wa") + (parallel + [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))] +- "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "VECTOR_MEM_VSX_P (mode)" + { + gcc_assert (UINTVAL (operands[2]) <= 1); + operands[3] = GEN_INT (INTVAL (operands[2]) << 1); +@@ -919,17 +1066,30 @@ (define_insn "vsx_extract_v2df" + } + [(set_attr "type" "vecperm")]) + +-;; General V2DF permute, extract_{high,low,even,odd} +-(define_insn "vsx_xxpermdi" +- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd") +- (vec_concat:V2DF +- (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd") +- (parallel +- [(match_operand:QI 2 "u5bit_cint_operand" "i")])) +- (vec_select:DF (match_operand:V2DF 3 "vsx_register_operand" "wd") +- (parallel +- [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))] +- "VECTOR_UNIT_VSX_P (V2DFmode)" ++;; General V2DF/V2DI permute ++(define_insn "vsx_xxpermdi_" ++ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa") ++ (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wd,wa") ++ (match_operand:VSX_D 2 "vsx_register_operand" "wd,wa") ++ (match_operand:QI 3 "u5bit_cint_operand" "i,i")] ++ UNSPEC_VSX_XXPERMDI))] ++ "VECTOR_MEM_VSX_P (mode)" ++ "xxpermdi %x0,%x1,%x2,%3" ++ [(set_attr "type" "vecperm")]) ++ ++;; Varient of xxpermdi that is emitted by the vec_interleave functions ++(define_insn "*vsx_xxpermdi2_" ++ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd") ++ (vec_concat:VSX_D ++ (vec_select: ++ (match_operand:VSX_D 1 "vsx_register_operand" "wd") ++ (parallel ++ [(match_operand:QI 2 "u5bit_cint_operand" "i")])) ++ (vec_select: ++ (match_operand:VSX_D 3 "vsx_register_operand" "wd") ++ (parallel ++ [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))] ++ "VECTOR_MEM_VSX_P (mode)" + { + gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1)); + operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1) +@@ -939,11 +1099,11 @@ (define_insn "vsx_xxpermdi" + [(set_attr "type" "vecperm")]) + + ;; V2DF splat +-(define_insn "vsx_splatv2df" +- [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa") +- (vec_duplicate:V2DF +- (match_operand:DF 1 "input_operand" "ws,f,Z,wa,wa,Z")))] +- "VECTOR_UNIT_VSX_P (V2DFmode)" ++(define_insn "vsx_splat_" ++ [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa") ++ (vec_duplicate:VSX_D ++ (match_operand: 1 "input_operand" "ws,f,Z,wa,wa,Z")))] ++ "VECTOR_UNIT_VSX_P (mode)" + "@ + xxpermdi %x0,%x1,%x1,0 + xxpermdi %x0,%x1,%x1,0 +@@ -953,52 +1113,66 @@ (define_insn "vsx_splatv2df" + lxvdsx %x0,%y1" + [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")]) + +-;; V4SF splat +-(define_insn "*vsx_xxspltw" +- [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,?wa") +- (vec_duplicate:V4SF +- (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf,wa") +- (parallel +- [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))] +- "VECTOR_UNIT_VSX_P (V4SFmode)" ++;; V4SF/V4SI splat ++(define_insn "vsx_xxspltw_" ++ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa") ++ (vec_duplicate:VSX_W ++ (vec_select: ++ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa") ++ (parallel ++ [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))] ++ "VECTOR_MEM_VSX_P (mode)" + "xxspltw %x0,%x1,%2" + [(set_attr "type" "vecperm")]) + +-;; V4SF interleave +-(define_insn "vsx_xxmrghw" +- [(set (match_operand:V4SF 0 "register_operand" "=wf,?wa") +- (vec_merge:V4SF +- (vec_select:V4SF (match_operand:V4SF 1 "vsx_register_operand" "wf,wa") +- (parallel [(const_int 0) +- (const_int 2) +- (const_int 1) +- (const_int 3)])) +- (vec_select:V4SF (match_operand:V4SF 2 "vsx_register_operand" "wf,wa") +- (parallel [(const_int 2) +- (const_int 0) +- (const_int 3) +- (const_int 1)])) ++;; V4SF/V4SI interleave ++(define_insn "vsx_xxmrghw_" ++ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa") ++ (vec_merge:VSX_W ++ (vec_select:VSX_W ++ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa") ++ (parallel [(const_int 0) ++ (const_int 2) ++ (const_int 1) ++ (const_int 3)])) ++ (vec_select:VSX_W ++ (match_operand:VSX_W 2 "vsx_register_operand" "wf,wa") ++ (parallel [(const_int 2) ++ (const_int 0) ++ (const_int 3) ++ (const_int 1)])) + (const_int 5)))] +- "VECTOR_UNIT_VSX_P (V4SFmode)" ++ "VECTOR_MEM_VSX_P (mode)" + "xxmrghw %x0,%x1,%x2" + [(set_attr "type" "vecperm")]) + +-(define_insn "vsx_xxmrglw" +- [(set (match_operand:V4SF 0 "register_operand" "=wf,?wa") +- (vec_merge:V4SF +- (vec_select:V4SF +- (match_operand:V4SF 1 "register_operand" "wf,wa") ++(define_insn "vsx_xxmrglw_" ++ [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa") ++ (vec_merge:VSX_W ++ (vec_select:VSX_W ++ (match_operand:VSX_W 1 "vsx_register_operand" "wf,wa") + (parallel [(const_int 2) + (const_int 0) + (const_int 3) + (const_int 1)])) +- (vec_select:V4SF +- (match_operand:V4SF 2 "register_operand" "wf,?wa") ++ (vec_select:VSX_W ++ (match_operand:VSX_W 2 "vsx_register_operand" "wf,?wa") + (parallel [(const_int 0) + (const_int 2) + (const_int 1) + (const_int 3)])) + (const_int 5)))] +- "VECTOR_UNIT_VSX_P (V4SFmode)" ++ "VECTOR_MEM_VSX_P (mode)" + "xxmrglw %x0,%x1,%x2" + [(set_attr "type" "vecperm")]) ++ ++;; Shift left double by word immediate ++(define_insn "vsx_xxsldwi_" ++ [(set (match_operand:VSX_L 0 "vsx_register_operand" "=wa") ++ (unspec:VSX_L [(match_operand:VSX_L 1 "vsx_register_operand" "wa") ++ (match_operand:VSX_L 2 "vsx_register_operand" "wa") ++ (match_operand:QI 3 "u5bit_cint_operand" "i")] ++ UNSPEC_VSX_SLDWI))] ++ "VECTOR_MEM_VSX_P (mode)" ++ "xxsldwi %x0,%x1,%x2,%3" ++ [(set_attr "type" "vecperm")]) +--- gcc/config/rs6000/rs6000.h (revision 146119) ++++ gcc/config/rs6000/rs6000.h (revision 146798) +@@ -1033,14 +1033,6 @@ extern int rs6000_vector_align[]; + ((MODE) == V4SFmode \ + || (MODE) == V2DFmode) \ + +-#define VSX_VECTOR_MOVE_MODE(MODE) \ +- ((MODE) == V16QImode \ +- || (MODE) == V8HImode \ +- || (MODE) == V4SImode \ +- || (MODE) == V2DImode \ +- || (MODE) == V4SFmode \ +- || (MODE) == V2DFmode) \ +- + #define VSX_SCALAR_MODE(MODE) \ + ((MODE) == DFmode) + +@@ -1049,12 +1041,9 @@ extern int rs6000_vector_align[]; + || VSX_SCALAR_MODE (MODE)) + + #define VSX_MOVE_MODE(MODE) \ +- (VSX_VECTOR_MOVE_MODE (MODE) \ +- || VSX_SCALAR_MODE(MODE) \ +- || (MODE) == V16QImode \ +- || (MODE) == V8HImode \ +- || (MODE) == V4SImode \ +- || (MODE) == V2DImode \ ++ (VSX_VECTOR_MODE (MODE) \ ++ || VSX_SCALAR_MODE (MODE) \ ++ || ALTIVEC_VECTOR_MODE (MODE) \ + || (MODE) == TImode) + + #define ALTIVEC_VECTOR_MODE(MODE) \ +@@ -1304,12 +1293,24 @@ enum reg_class + purpose. Any move between two registers of a cover class should be + cheaper than load or store of the registers. The macro value is + array of register classes with LIM_REG_CLASSES used as the end +- marker. */ ++ marker. ++ ++ We need two IRA_COVER_CLASSES, one for pre-VSX, and the other for VSX to ++ account for the Altivec and Floating registers being subsets of the VSX ++ register set. */ ++ ++#define IRA_COVER_CLASSES_PRE_VSX \ ++{ \ ++ GENERAL_REGS, SPECIAL_REGS, FLOAT_REGS, ALTIVEC_REGS, /* VSX_REGS, */ \ ++ /* VRSAVE_REGS,*/ VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, \ ++ /* MQ_REGS, LINK_REGS, CTR_REGS, */ \ ++ CR_REGS, XER_REGS, LIM_REG_CLASSES \ ++} + +-#define IRA_COVER_CLASSES \ ++#define IRA_COVER_CLASSES_VSX \ + { \ +- GENERAL_REGS, SPECIAL_REGS, FLOAT_REGS, ALTIVEC_REGS, \ +- /*VRSAVE_REGS,*/ VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, \ ++ GENERAL_REGS, SPECIAL_REGS, /* FLOAT_REGS, ALTIVEC_REGS, */ VSX_REGS, \ ++ /* VRSAVE_REGS,*/ VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, \ + /* MQ_REGS, LINK_REGS, CTR_REGS, */ \ + CR_REGS, XER_REGS, LIM_REG_CLASSES \ + } +@@ -3371,21 +3372,36 @@ enum rs6000_builtins + VSX_BUILTIN_XVTDIVSP, + VSX_BUILTIN_XVTSQRTDP, + VSX_BUILTIN_XVTSQRTSP, +- VSX_BUILTIN_XXLAND, +- VSX_BUILTIN_XXLANDC, +- VSX_BUILTIN_XXLNOR, +- VSX_BUILTIN_XXLOR, +- VSX_BUILTIN_XXLXOR, +- VSX_BUILTIN_XXMRGHD, +- VSX_BUILTIN_XXMRGHW, +- VSX_BUILTIN_XXMRGLD, +- VSX_BUILTIN_XXMRGLW, +- VSX_BUILTIN_XXPERMDI, +- VSX_BUILTIN_XXSEL, +- VSX_BUILTIN_XXSLDWI, +- VSX_BUILTIN_XXSPLTD, +- VSX_BUILTIN_XXSPLTW, +- VSX_BUILTIN_XXSWAPD, ++ VSX_BUILTIN_XXSEL_2DI, ++ VSX_BUILTIN_XXSEL_2DF, ++ VSX_BUILTIN_XXSEL_4SI, ++ VSX_BUILTIN_XXSEL_4SF, ++ VSX_BUILTIN_XXSEL_8HI, ++ VSX_BUILTIN_XXSEL_16QI, ++ VSX_BUILTIN_VPERM_2DI, ++ VSX_BUILTIN_VPERM_2DF, ++ VSX_BUILTIN_VPERM_4SI, ++ VSX_BUILTIN_VPERM_4SF, ++ VSX_BUILTIN_VPERM_8HI, ++ VSX_BUILTIN_VPERM_16QI, ++ VSX_BUILTIN_XXPERMDI_2DF, ++ VSX_BUILTIN_XXPERMDI_2DI, ++ VSX_BUILTIN_CONCAT_2DF, ++ VSX_BUILTIN_CONCAT_2DI, ++ VSX_BUILTIN_SET_2DF, ++ VSX_BUILTIN_SET_2DI, ++ VSX_BUILTIN_SPLAT_2DF, ++ VSX_BUILTIN_SPLAT_2DI, ++ VSX_BUILTIN_XXMRGHW_4SF, ++ VSX_BUILTIN_XXMRGHW_4SI, ++ VSX_BUILTIN_XXMRGLW_4SF, ++ VSX_BUILTIN_XXMRGLW_4SI, ++ VSX_BUILTIN_XXSLDWI_16QI, ++ VSX_BUILTIN_XXSLDWI_8HI, ++ VSX_BUILTIN_XXSLDWI_4SI, ++ VSX_BUILTIN_XXSLDWI_4SF, ++ VSX_BUILTIN_XXSLDWI_2DI, ++ VSX_BUILTIN_XXSLDWI_2DF, + + /* VSX overloaded builtins, add the overloaded functions not present in + Altivec. */ +@@ -3395,7 +3411,13 @@ enum rs6000_builtins + VSX_BUILTIN_VEC_NMADD, + VSX_BUITLIN_VEC_NMSUB, + VSX_BUILTIN_VEC_DIV, +- VSX_BUILTIN_OVERLOADED_LAST = VSX_BUILTIN_VEC_DIV, ++ VSX_BUILTIN_VEC_XXMRGHW, ++ VSX_BUILTIN_VEC_XXMRGLW, ++ VSX_BUILTIN_VEC_XXPERMDI, ++ VSX_BUILTIN_VEC_XXSLDWI, ++ VSX_BUILTIN_VEC_XXSPLTD, ++ VSX_BUILTIN_VEC_XXSPLTW, ++ VSX_BUILTIN_OVERLOADED_LAST = VSX_BUILTIN_VEC_XXSPLTW, + + /* Combined VSX/Altivec builtins. */ + VECTOR_BUILTIN_FLOAT_V4SI_V4SF, +@@ -3425,13 +3447,16 @@ enum rs6000_builtin_type_index + RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V8HI, + RS6000_BTI_unsigned_V4SI, ++ RS6000_BTI_unsigned_V2DI, + RS6000_BTI_bool_char, /* __bool char */ + RS6000_BTI_bool_short, /* __bool short */ + RS6000_BTI_bool_int, /* __bool int */ ++ RS6000_BTI_bool_long, /* __bool long */ + RS6000_BTI_pixel, /* __pixel */ + RS6000_BTI_bool_V16QI, /* __vector __bool char */ + RS6000_BTI_bool_V8HI, /* __vector __bool short */ + RS6000_BTI_bool_V4SI, /* __vector __bool int */ ++ RS6000_BTI_bool_V2DI, /* __vector __bool long */ + RS6000_BTI_pixel_V8HI, /* __vector __pixel */ + RS6000_BTI_long, /* long_integer_type_node */ + RS6000_BTI_unsigned_long, /* long_unsigned_type_node */ +@@ -3466,13 +3491,16 @@ enum rs6000_builtin_type_index + #define unsigned_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V16QI]) + #define unsigned_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V8HI]) + #define unsigned_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V4SI]) ++#define unsigned_V2DI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V2DI]) + #define bool_char_type_node (rs6000_builtin_types[RS6000_BTI_bool_char]) + #define bool_short_type_node (rs6000_builtin_types[RS6000_BTI_bool_short]) + #define bool_int_type_node (rs6000_builtin_types[RS6000_BTI_bool_int]) ++#define bool_long_type_node (rs6000_builtin_types[RS6000_BTI_bool_long]) + #define pixel_type_node (rs6000_builtin_types[RS6000_BTI_pixel]) + #define bool_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V16QI]) + #define bool_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V8HI]) + #define bool_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V4SI]) ++#define bool_V2DI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V2DI]) + #define pixel_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_pixel_V8HI]) + + #define long_integer_type_internal_node (rs6000_builtin_types[RS6000_BTI_long]) +--- gcc/config/rs6000/altivec.md (revision 146119) ++++ gcc/config/rs6000/altivec.md (revision 146798) +@@ -166,12 +166,15 @@ (define_mode_iterator V [V4SI V8HI V16QI + ;; otherwise handled by altivec (v2df, v2di, ti) + (define_mode_iterator VM [V4SI V8HI V16QI V4SF V2DF V2DI TI]) + ++;; Like VM, except don't do TImode ++(define_mode_iterator VM2 [V4SI V8HI V16QI V4SF V2DF V2DI]) ++ + (define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")]) + + ;; Vector move instructions. + (define_insn "*altivec_mov" +- [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,*o,*r,*r,v,v") +- (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,j,W"))] ++ [(set (match_operand:VM2 0 "nonimmediate_operand" "=Z,v,v,*o,*r,*r,v,v") ++ (match_operand:VM2 1 "input_operand" "v,Z,v,r,o,r,j,W"))] + "VECTOR_MEM_ALTIVEC_P (mode) + && (register_operand (operands[0], mode) + || register_operand (operands[1], mode))" +@@ -191,6 +194,31 @@ (define_insn "*altivec_mov" + } + [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")]) + ++;; Unlike other altivec moves, allow the GPRs, since a normal use of TImode ++;; is for unions. However for plain data movement, slightly favor the vector ++;; loads ++(define_insn "*altivec_movti" ++ [(set (match_operand:TI 0 "nonimmediate_operand" "=Z,v,v,?o,?r,?r,v,v") ++ (match_operand:TI 1 "input_operand" "v,Z,v,r,o,r,j,W"))] ++ "VECTOR_MEM_ALTIVEC_P (TImode) ++ && (register_operand (operands[0], TImode) ++ || register_operand (operands[1], TImode))" ++{ ++ switch (which_alternative) ++ { ++ case 0: return "stvx %1,%y0"; ++ case 1: return "lvx %0,%y1"; ++ case 2: return "vor %0,%1,%1"; ++ case 3: return "#"; ++ case 4: return "#"; ++ case 5: return "#"; ++ case 6: return "vxor %0,%0,%0"; ++ case 7: return output_vec_const_move (operands); ++ default: gcc_unreachable (); ++ } ++} ++ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")]) ++ + (define_split + [(set (match_operand:VM 0 "altivec_register_operand" "") + (match_operand:VM 1 "easy_vector_constant_add_self" ""))] +@@ -434,13 +462,13 @@ (define_insn "*altivec_gev4sf" + "vcmpgefp %0,%1,%2" + [(set_attr "type" "veccmp")]) + +-(define_insn "altivec_vsel" ++(define_insn "*altivec_vsel" + [(set (match_operand:VM 0 "altivec_register_operand" "=v") + (if_then_else:VM (ne (match_operand:VM 1 "altivec_register_operand" "v") + (const_int 0)) + (match_operand:VM 2 "altivec_register_operand" "v") + (match_operand:VM 3 "altivec_register_operand" "v")))] +- "VECTOR_UNIT_ALTIVEC_P (mode)" ++ "VECTOR_MEM_ALTIVEC_P (mode)" + "vsel %0,%3,%2,%1" + [(set_attr "type" "vecperm")]) + +@@ -780,7 +808,7 @@ (define_insn "altivec_vmrghw" + (const_int 3) + (const_int 1)])) + (const_int 5)))] +- "TARGET_ALTIVEC" ++ "VECTOR_MEM_ALTIVEC_P (V4SImode)" + "vmrghw %0,%1,%2" + [(set_attr "type" "vecperm")]) + +@@ -797,7 +825,7 @@ (define_insn "*altivec_vmrghsf" + (const_int 3) + (const_int 1)])) + (const_int 5)))] +- "VECTOR_UNIT_ALTIVEC_P (V4SFmode)" ++ "VECTOR_MEM_ALTIVEC_P (V4SFmode)" + "vmrghw %0,%1,%2" + [(set_attr "type" "vecperm")]) + +@@ -881,7 +909,7 @@ (define_insn "altivec_vmrglw" + (const_int 1) + (const_int 3)])) + (const_int 5)))] +- "TARGET_ALTIVEC" ++ "VECTOR_MEM_ALTIVEC_P (V4SImode)" + "vmrglw %0,%1,%2" + [(set_attr "type" "vecperm")]) + +@@ -899,7 +927,7 @@ (define_insn "*altivec_vmrglsf" + (const_int 1) + (const_int 3)])) + (const_int 5)))] +- "VECTOR_UNIT_ALTIVEC_P (V4SFmode)" ++ "VECTOR_MEM_ALTIVEC_P (V4SFmode)" + "vmrglw %0,%1,%2" + [(set_attr "type" "vecperm")]) + +--- gcc/config/rs6000/rs6000.md (revision 146119) ++++ gcc/config/rs6000/rs6000.md (revision 146798) +@@ -14667,7 +14667,11 @@ (define_insn "return" + [(set_attr "type" "jmpreg")]) + + (define_expand "indirect_jump" +- [(set (pc) (match_operand 0 "register_operand" ""))]) ++ [(set (pc) (match_operand 0 "register_operand" ""))] ++ "" ++{ ++ rs6000_set_indirect_jump (); ++}) + + (define_insn "*indirect_jump" + [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))] +@@ -14682,14 +14686,14 @@ (define_expand "tablejump" + [(use (match_operand 0 "" "")) + (use (label_ref (match_operand 1 "" "")))] + "" +- " + { ++ rs6000_set_indirect_jump (); + if (TARGET_32BIT) + emit_jump_insn (gen_tablejumpsi (operands[0], operands[1])); + else + emit_jump_insn (gen_tablejumpdi (operands[0], operands[1])); + DONE; +-}") ++}) + + (define_expand "tablejumpsi" + [(set (match_dup 3) +@@ -14749,6 +14753,11 @@ (define_expand "doloop_end" + /* Only use this on innermost loops. */ + if (INTVAL (operands[3]) > 1) + FAIL; ++ /* Do not try to use decrement and count on code that has an indirect ++ jump or a table jump, because the ctr register is preferred over the ++ lr register. */ ++ if (rs6000_has_indirect_jump_p ()) ++ FAIL; + if (TARGET_64BIT) + { + if (GET_MODE (operands[0]) != DImode) diff --git a/gcc44-power7.patch b/gcc44-power7.patch index 42f8088..04c3d9c 100644 --- a/gcc44-power7.patch +++ b/gcc44-power7.patch @@ -1,3 +1,247 @@ +2009-04-08 Michael Meissner + + * doc/invoke.texi (-mvsx-vector-memory): Make debug switches + undoucmented. + (-mvsx-vector-float): Ditto. + (-mvsx-vector-double): Ditto. + (-mvsx-scalar-double): Ditto. + (-mvsx-scalar-memory): Ditto. + + * config/rs6000/vector.md (VEC_R): New iterator for reload + patterns. + (mov): Don't call rs6000_emit_move. + (reload___*): New insns for + secondary_reload support. + (vec_reload_and_plus_): New insns in case reload needs + to move a VSX/Altivec (and (plus reg reg) -16) type address to a + base register. + + * config/rs6000/rs6000-protos.h (rs6000_secondary_reload_inner): + Rename from rs6000_vector_secondary_reload. + + * config/rs6000/rs6000.opt (-mvsx-vector-memory): Make debug + switches undoucmented. + (-mvsx-vector-float): Ditto. + (-mvsx-vector-double): Ditto. + (-mvsx-scalar-double): Ditto. + (-mvsx-scalar-memory): Ditto. + (-mvsx-v4sf-altivec-regs): New undocumented debug switch to + control whether V4SF types prefer the Altivec registers or all of + the VSX registers. + (-mreload-functions): New undocumented debug switch to + enable/disable the secondary reload support. + + * config/rs6000/rs6000.c (rs6000_regno_regclass): New global to + map register number to regclass. + (rs6000_vector_reload): New array to hold the secondary reload + insn codes for the vector types. + (rs6000_init_hard_regno_mode_ok): Fill in rs6000_regno_regclass + and rs6000_vector_reload. + (rs6000_mode_dependent_address): Using AND in addresses is mode + dependent. + (rs6000_emit_move): Add debug information if -mdebug=addr. + (rs6000_reload_register_type): Classify register classes for + secondary reload. + (rs6000_secondary_reload): For the vector types, add reload + support to support reg+reg addressing for gprs, and reg+offset + addressing for vector registers. + (rs6000_secondary_reload_inner): Rename from + rs6000_vector_secondary_reload. Fixup gpr addressing to just reg + or reg+offset, and vector addressing to just reg or reg+reg. + (rs6000_preferred_reload_class): Make sure all cases set the + return value. If VSX/Altivec address with AND -16, prefer using + an Altivec register. + (rs6000_secondary_memory_needed): Handle things like SFmode that + can go in floating registers, but not altivec registers under + -mvsx. + + * config/rs6000/vsx.md (VSX_U): New iterator for load/store with + update. + (VSi, VSI): Reorder fields. + (VSd): Add support for load/store with update rewrite. + (VSv): Ditto. + (VStype_load_update): New mode attribute for load/store with + update. + (VStype_store_update): Ditto. + (vsx_mov): Use * instead of store/load attributes for + multi-instruction gpr loads/stores. + (vsx_reload**): Delete unused reload patterns. + + * config/rs6000/rs6000.h (REGNO_REG_CLASS): Change from a bunch of + if statements to using a lookup table. + (rs6000_regno_regclass): Lookup table for REGNO_REG_CLASS. + + * config/rs6000/altivec.md (altivec_reload*): Delete unused reload + patterns. + + * config/rs6000/rs6000.md (tptrsize, mptrsize): New mode + attributes for -m32/-m64 support. + +2009-03-27 Jakub Jelinek + + PR target/39558 + * macro.c (cpp_get_token): If macro_to_expand returns NULL + and used some tokens, add CPP_PADDING before next token. + + * gcc.target/powerpc/altivec-29.c: New test. + +2009-03-27 Michael Meissner + + * config/rs6000/constraints.md ("wZ" constraint): New constraint + for using Altivec loads/stores under VSX for vector realignment. + + * config/rs6000/predicates.md + (altivec_indexed_or_indirect_operand): New predicate to recognize + Altivec load/stores with an explicit AND -16. + + * config/rs6000/power7.md: Whitespace change. + + * config/rs6000/rs6000.opt (-mpower7-adjust-cost): New debug + switch. + + * config/rs6000/rs6000-c.c (altivec_categorize_keyword): If -mvsx + and -mno-altivec, recognize the 'vector' keyword, but do not + recognize 'bool' or 'pixel'. Recognize vector double under VSX. + (init_vector_keywords): Ditto. + (rs6000_macro_to_expand): Ditto. + (altivec_overloaded_builtins): Add VSX overloaded builtins. + (altivec_resolve_overloaded_builtin): Ditto. + + * config/rs6000/rs6000.c (rs6000_debug_cost): New global for + -mdebug=cost. + (rs6000_debug_address_cost): New function for printing costs if + -mdebug=cost. + (rs6000_debug_rtx_costs): Ditto. + (rs6000_debug_adjust_cost): Ditto. + (rs6000_override_options): Add -mdebug=cost support. + (rs6000_legitimize_reload_address): Allow Altivec loads and stores + with an explicit AND -16, in VSX for vector realignment. + (rs6000_legitimize_reload_address): Ditto. + (rs6000_legitimate_address): Ditto. + (print_operand): Ditto. + (bdesc_3arg): Add VSX builtins. + (bdesc_2arg): Ditto. + (bdesc_1arg): Ditto. + (bdesc_abs): Ditto. + (vsx_expand_builtin): Stub function for expanding VSX builtins. + (rs6000_expand_builtin): Call vsx_expand_builtin. + + * config/rs6000/vsx.md (most DF insns): Merge DF insns in with + V2DF and V4SF insns, rather than duplicating much of the code. + (all insns): Go through all insns, and alternatives to address the + full VSX register set, as a non-preferred option. + (vsx_mod): Add support for using Altivec load/store with + explicit AND -16. Use xxlor to copy registers, not copy sign. + (multiply/add insns): Add an expander and unspec so the insn can + be used directly even if -mno-fused-madd. + (vsx_tdiv3): New insn for use as a builtin function. + (vsx_tsqrt2): Ditto. + (vsx_rsqrte2): Ditto. + + * config/rs6000/rs6000.h (rs6000_debug_cost): New for + -mdebug=cost. + (TARGET_DEBUG_COST): Ditto. + (VSX_BUILTIN_*): Merge the two forms of multiply/add instructions + into a single insn. Start to add overloaded VSX builtins. + + * config/rs6000/altivec.md (build_vector_mask_for_load): Delete + VSX code. + + * config/rs6000/rs6000.md (btruncsf2): Delete extra space. + (movdf_hardfloat32): Use xxlor instead of xscpsgndp to copy data. + (movdf_hardfloat64_mfpgpr): Ditto. + (movdf_hardfloat64): Ditto. + +2009-03-13 Michael Meissner + + PR target/39457 + * config/rs6000/rs6000.opt (-mdisallow-float-in-lr-ctr): Add + temporary debug switch. + + * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Revert + behavior of disallowing + +2009-03-13 Michael Meissner + + * config/rs6000/vector.md (vec_extract_evenv2df): Delete, insn + causes problems in building spec 2006. + (vec_extract_oddv2df): Ditto. + (vec_pack_trunc_v2df): New expanders for VSX vectorized + conversions. + (vec_pack_sfix_trunc_v2df): Ditto. + (vec_pack_ufix_trunc_v2df): Ditto. + (vec_unpacks_hi_v4sf): Ditto. + (vec_unpacks_lo_v4sf): Ditto. + (vec_unpacks_float_hi_v4si): Ditto. + (vec_unpacks_float_lo_v4si): Ditto. + (vec_unpacku_float_hi_v4si): Ditto. + (vec_unpacku_float_lo_v4si): Ditto. + + * config/rs6000/rs6000-protos.h (rs6000_vector_secondary_reload): + Declaration for new target hook. + + * config/rs6000/rs6000.c (TARGET_SECONDARY_RELOAD): Add new target + hook for eventually fixing up the memory references for Altivec + and VSX reloads to be reg+reg instead of reg+offset. Right now, + this is a stub function that prints debug information if + -mdebug=addr and then calls default_secondary_reload. + (rs6000_secondary_reload): Ditto. + (rs6000_vector_secondary_reload): Ditto. + (rs6000_builtin_conversion): Add support for V2DI/V2DF + conversions. + (rs6000_legitimate_offset_address_p): Test for the vector unit + doing the memory references. + (rs6000_legimize_reload_address): Ditto. + (rs6000_legitimize_address): Print extra \n if -mdebug=addr. + (rs6000_legitimize_reload_address): Ditto. + (rs6000_legitimate_address): Ditto. + (rs6000_mode_dependent_address): Ditto. + (bdesc_2arg): Add VSX builtins. + (bdesc_abs): Ditto. + (bdesc_1arg): Ditto. + (altivec_init_builtins): Ditto. + (rs6000_secondary_memory_needed_rtx): Add debug support if + -mdebug=addr. + (rs6000_preferred_reload_class): Ditto. + (rs6000_secondary_memory_needed): Ditto. + (rs6000_secondary_reload_class): Ditto. + (rs6000_cannot_change_mode_class): Ditto. + + * config/rs6000/vsx.md (UNSPEC_VSX_*): Add unspecs for VSX + conversions. + (vsx_nabs): Add generator function. + (vsx_float2): Ditto. + (vsx_floatuns2): Ditto. + (vsx_xxmrghw): Ditto. + (vsx_xxmrglw): Ditto. + (vsx_xvcvdpsp): New VSX vector conversion insn. + (vsx_xvcvdpsxws): Ditto. + (vsx_xvcvdpuxws): Ditto. + (vsx_xvcvspdp): Ditto. + (vsx_xvcvsxwdp): Ditto. + (vsx_xvcvuxwdp): Ditto. + (vsx_reload_*): New insns for reload support. + + * config/rs6000/rs6000.h: Fix a comment. + + * config/rs6000/altivec.md (altivec_reload_*): New insns for + reload support. + + * config/rs6000/rs6000.md (ptrsize): New mode attribute for the + pointer size. + +2009-03-10 Michael Meissner + + * config/rs6000/vsx.md (vsx_concat_v2df): Add explicit 'f' + register class for scalar data, correct uses of the xxpermdi + instruction. + (vsx_set_v2df): Ditto. + (vsx_extract_v2df): Ditto. + (vsx_xxpermdi): Ditto. + (vsx_splatv2df): Ditto. + (vsx_xxmrghw): Use wf instead of v constraints. + (vsx_xxmrglw): Ditto. + 2009-03-09 Michael Meissner * config/rs6000/vsx.md (vsx_store_update64): Use correct @@ -868,7 +1112,27 @@ (popcntwsi2): Add popcntw support. (popcntddi2): Add popcntd support. -testsuite/ +2009-03-27 Jakub Jelinek + + PR target/39558 + * gcc.target/powerpc/altivec-29.c: New test. + +2009-03-27 Michael Meissner + + * gcc.target/powerpc/vsx-builtin-1.c: Add more VSX builtins. + Prevent the optimizer from combining the various multiplies. + * gcc.target/powerpc/vsx-builtin-2.c: Ditto. + +2009-03-13 Michael Meissner + + PR target/39457 + * gcc.target/powerpc/pr39457.c: New test for PR39457. + +2009-03-13 Michael Meissner + + * gcc.target/powerpc/vsx-builtin-1.c: New test for builtins. + * gcc.target/powerpc/vsx-builtin-2.c: Ditto. + 2009-03-01 Michael Meissner * gcc.target/powerpc/vsx-vector-1.c: Fix typos. @@ -899,9 +1163,9 @@ testsuite/ * gcc.target/powerpc/popcount-2.c: New file for power7 support. * gcc.target/powerpc/popcount-3.c: Ditto. ---- gcc/doc/invoke.texi (.../trunk) (revision 144557) -+++ gcc/doc/invoke.texi (.../branches/ibm/power7-meissner) (revision 144730) -@@ -712,7 +712,8 @@ See RS/6000 and PowerPC Options. +--- gcc/doc/invoke.texi (.../trunk) (revision 145777) ++++ gcc/doc/invoke.texi (.../branches/ibm/power7-meissner) (revision 146027) +@@ -715,7 +715,8 @@ See RS/6000 and PowerPC Options. -maltivec -mno-altivec @gol -mpowerpc-gpopt -mno-powerpc-gpopt @gol -mpowerpc-gfxopt -mno-powerpc-gfxopt @gol @@ -911,18 +1175,16 @@ testsuite/ -mcmpb -mno-cmpb -mmfpgpr -mno-mfpgpr -mhard-dfp -mno-hard-dfp @gol -mnew-mnemonics -mold-mnemonics @gol -mfull-toc -mminimal-toc -mno-fp-in-toc -mno-sum-in-toc @gol -@@ -726,7 +727,9 @@ See RS/6000 and PowerPC Options. +@@ -729,7 +730,7 @@ See RS/6000 and PowerPC Options. -mstrict-align -mno-strict-align -mrelocatable @gol -mno-relocatable -mrelocatable-lib -mno-relocatable-lib @gol -mtoc -mno-toc -mlittle -mlittle-endian -mbig -mbig-endian @gol --mdynamic-no-pic -maltivec -mswdiv @gol -+-mdynamic-no-pic -maltivec -mswdiv -mvsx -mvsx-vector-memory @gol -+-mvsx-vector-float -mvsx-vector-double @gol -+-mvsx-scalar-double -mvsx-scalar-memory @gol ++-mdynamic-no-pic -maltivec -mswdiv @gol -mprioritize-restricted-insns=@var{priority} @gol -msched-costly-dep=@var{dependence_type} @gol -minsert-sched-nops=@var{scheme} @gol -@@ -13512,6 +13515,8 @@ These @samp{-m} options are defined for +@@ -13614,6 +13615,8 @@ These @samp{-m} options are defined for @itemx -mno-mfcrf @itemx -mpopcntb @itemx -mno-popcntb @@ -931,7 +1193,7 @@ testsuite/ @itemx -mfprnd @itemx -mno-fprnd @itemx -mcmpb -@@ -13536,6 +13541,8 @@ These @samp{-m} options are defined for +@@ -13638,6 +13641,8 @@ These @samp{-m} options are defined for @opindex mno-mfcrf @opindex mpopcntb @opindex mno-popcntb @@ -940,7 +1202,7 @@ testsuite/ @opindex mfprnd @opindex mno-fprnd @opindex mcmpb -@@ -13585,6 +13592,9 @@ The @option{-mpopcntb} option allows GCC +@@ -13687,6 +13692,9 @@ The @option{-mpopcntb} option allows GCC double precision FP reciprocal estimate instruction implemented on the POWER5 processor and other processors that support the PowerPC V2.02 architecture. @@ -950,7 +1212,7 @@ testsuite/ The @option{-mfprnd} option allows GCC to generate the FP round to integer instructions implemented on the POWER5+ processor and other processors that support the PowerPC V2.03 architecture. -@@ -13663,9 +13673,9 @@ The @option{-mcpu} options automatically +@@ -13765,9 +13773,9 @@ The @option{-mcpu} options automatically following options: @gccoptlist{-maltivec -mfprnd -mhard-float -mmfcrf -mmultiple @gol @@ -962,7 +1224,7 @@ testsuite/ The particular options set for any particular CPU will vary between compiler versions, depending on what setting seems to produce optimal -@@ -13766,6 +13776,44 @@ instructions. +@@ -13868,6 +13876,14 @@ instructions. This option has been deprecated. Use @option{-mspe} and @option{-mno-spe} instead. @@ -973,43 +1235,13 @@ testsuite/ +Generate code that uses (does not use) vector/scalar (VSX) +instructions, and also enable the use of built-in functions that allow +more direct access to the VSX instruction set. -+ -+@item -mvsx-vector-memory -+@itemx -mno-vsx-vector-memory -+If @option{-mvsx}, use VSX memory reference instructions for vectors -+instead of the Altivec instructions This option is a temporary switch -+to tune the compiler, and may not be supported in future versions. -+ -+@item -mvsx-vector-float -+@itemx -mno-vsx-vector-float -+If @option{-mvsx}, use VSX arithmetic instructions for float vectors. -+This option is a temporary switch to tune the compiler, and may not be -+supported in future versions. -+ -+@item -mvsx-vector-double -+@itemx -mno-vsx-vector-double -+If @option{-mvsx}, use VSX arithmetic instructions for double -+vectors. This option is a temporary switch to tune the -+compiler, and may not be supported in future versions. -+ -+@item -mvsx-scalar-double -+@itemx -mno-vsx-scalar-double -+If @option{-mvsx}, use VSX arithmetic instructions for scalar double. -+This option is a temporary switch to tune the compiler, and may not be -+supported in future versions. -+ -+@item -mvsx-scalar-memory -+@itemx -mno-vsx-scalar-memory -+If @option{-mvsx}, use VSX memory reference instructions for scalar -+double. This option is a temporary switch to tune the compiler, and -+may not be supported in future versions. + @item -mfloat-gprs=@var{yes/single/double/no} @itemx -mfloat-gprs @opindex mfloat-gprs ---- gcc/doc/md.texi (.../trunk) (revision 144557) -+++ gcc/doc/md.texi (.../branches/ibm/power7-meissner) (revision 144730) -@@ -1905,7 +1905,19 @@ Address base register +--- gcc/doc/md.texi (.../trunk) (revision 145777) ++++ gcc/doc/md.texi (.../branches/ibm/power7-meissner) (revision 146027) +@@ -1913,7 +1913,19 @@ Address base register Floating point register @item v @@ -1030,7 +1262,7 @@ testsuite/ @item h @samp{MQ}, @samp{CTR}, or @samp{LINK} register -@@ -1991,6 +2003,9 @@ AND masks that can be performed by two r +@@ -1999,6 +2011,9 @@ AND masks that can be performed by two r @item W Vector constant that does not require memory @@ -1040,8 +1272,8 @@ testsuite/ @end table @item Intel 386---@file{config/i386/constraints.md} ---- gcc/reload.c (.../trunk) (revision 144557) -+++ gcc/reload.c (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/reload.c (.../trunk) (revision 145777) ++++ gcc/reload.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -6255,8 +6255,14 @@ subst_reloads (rtx insn) *r->where = reloadreg; } @@ -1059,8 +1291,144 @@ testsuite/ } } +--- gcc/configure (.../trunk) (revision 145777) ++++ gcc/configure (.../branches/ibm/power7-meissner) (revision 146027) +@@ -23075,7 +23075,7 @@ if test "${gcc_cv_as_powerpc_mfpgpr+set} + else + gcc_cv_as_powerpc_mfpgpr=no + if test $in_tree_gas = yes; then +- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` ++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` + then gcc_cv_as_powerpc_mfpgpr=yes + fi + elif test x$gcc_cv_as != x; then +@@ -23171,7 +23171,7 @@ if test "${gcc_cv_as_powerpc_cmpb+set}" + else + gcc_cv_as_powerpc_cmpb=no + if test $in_tree_gas = yes; then +- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` ++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` + then gcc_cv_as_powerpc_cmpb=yes + fi + elif test x$gcc_cv_as != x; then +@@ -23217,7 +23217,7 @@ if test "${gcc_cv_as_powerpc_dfp+set}" = + else + gcc_cv_as_powerpc_dfp=no + if test $in_tree_gas = yes; then +- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` ++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` + then gcc_cv_as_powerpc_dfp=yes + fi + elif test x$gcc_cv_as != x; then +@@ -23263,7 +23263,7 @@ if test "${gcc_cv_as_powerpc_vsx+set}" = + else + gcc_cv_as_powerpc_vsx=no + if test $in_tree_gas = yes; then +- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` ++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` + then gcc_cv_as_powerpc_vsx=yes + fi + elif test x$gcc_cv_as != x; then +@@ -23293,6 +23293,52 @@ _ACEOF + + fi + ++ case $target in ++ *-*-aix*) conftest_s=' .machine "pwr7" ++ .csect .text[PR] ++ popcntd 3,3';; ++ *) conftest_s=' .machine power7 ++ .text ++ popcntd 3,3';; ++ esac ++ ++ echo "$as_me:$LINENO: checking assembler for popcntd support" >&5 ++echo $ECHO_N "checking assembler for popcntd support... $ECHO_C" >&6 ++if test "${gcc_cv_as_powerpc_popcntd+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ gcc_cv_as_powerpc_popcntd=no ++ if test $in_tree_gas = yes; then ++ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` ++ then gcc_cv_as_powerpc_popcntd=yes ++fi ++ elif test x$gcc_cv_as != x; then ++ echo "$conftest_s" > conftest.s ++ if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } ++ then ++ gcc_cv_as_powerpc_popcntd=yes ++ else ++ echo "configure: failed program was" >&5 ++ cat conftest.s >&5 ++ fi ++ rm -f conftest.o conftest.s ++ fi ++fi ++echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntd" >&5 ++echo "${ECHO_T}$gcc_cv_as_powerpc_popcntd" >&6 ++if test $gcc_cv_as_powerpc_popcntd = yes; then ++ ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_AS_POPCNTD 1 ++_ACEOF ++ ++fi ++ + echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5 + echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6 + if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then +--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c (.../trunk) (revision 0) ++++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c (.../branches/ibm/power7-meissner) (revision 146027) +@@ -0,0 +1,42 @@ ++/* { dg-do compile { target { powerpc*-*-* } } } */ ++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ ++/* { dg-require-effective-target powerpc_vsx_ok } */ ++/* { dg-options "-O2 -mcpu=power7" } */ ++/* { dg-final { scan-assembler "xvaddsp" } } */ ++/* { dg-final { scan-assembler "xvsubsp" } } */ ++/* { dg-final { scan-assembler "xvmulsp" } } */ ++/* { dg-final { scan-assembler "xvmadd" } } */ ++/* { dg-final { scan-assembler "xvmsub" } } */ ++/* { dg-final { scan-assembler "xvnmadd" } } */ ++/* { dg-final { scan-assembler "xvnmsub" } } */ ++/* { dg-final { scan-assembler "xvdivsp" } } */ ++/* { dg-final { scan-assembler "xvmaxsp" } } */ ++/* { dg-final { scan-assembler "xvminsp" } } */ ++/* { dg-final { scan-assembler "xvsqrtsp" } } */ ++/* { dg-final { scan-assembler "xvabssp" } } */ ++/* { dg-final { scan-assembler "xvnabssp" } } */ ++/* { dg-final { scan-assembler "xvresp" } } */ ++/* { dg-final { scan-assembler "xvrsqrtesp" } } */ ++/* { dg-final { scan-assembler "xvtsqrtsp" } } */ ++/* { dg-final { scan-assembler "xvtdivsp" } } */ ++ ++void use_builtins (__vector float *p, __vector float *q, __vector float *r, __vector float *s) ++{ ++ p[0] = __builtin_vsx_xvaddsp (q[0], r[0]); ++ p[1] = __builtin_vsx_xvsubsp (q[1], r[1]); ++ p[2] = __builtin_vsx_xvmulsp (q[2], r[2]); ++ p[3] = __builtin_vsx_xvdivsp (q[3], r[3]); ++ p[4] = __builtin_vsx_xvmaxsp (q[4], r[4]); ++ p[5] = __builtin_vsx_xvminsp (q[5], r[5]); ++ p[6] = __builtin_vsx_xvabssp (q[6]); ++ p[7] = __builtin_vsx_xvnabssp (q[7]); ++ p[8] = __builtin_vsx_xvsqrtsp (q[8]); ++ p[9] = __builtin_vsx_xvmaddsp (q[9], r[9], s[9]); ++ p[10] = __builtin_vsx_xvmsubsp (q[10], r[10], s[10]); ++ p[11] = __builtin_vsx_xvnmaddsp (q[11], r[11], s[11]); ++ p[12] = __builtin_vsx_xvnmsubsp (q[12], r[12], s[12]); ++ p[13] = __builtin_vsx_xvresp (q[13]); ++ p[14] = __builtin_vsx_xvrsqrtesp (q[14]); ++ p[15] = __builtin_vsx_xvtsqrtsp (q[15]); ++ p[16] = __builtin_vsx_xvtdivsp (q[16], r[16]); ++} --- gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../trunk) (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../branches/ibm/power7-meissner) (revision 144730) ++++ gcc/testsuite/gcc.target/powerpc/popcount-3.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -0,0 +1,9 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ @@ -1072,7 +1440,7 @@ testsuite/ + return __builtin_popcountl(x); +} --- gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../trunk) (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../branches/ibm/power7-meissner) (revision 144730) ++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -0,0 +1,74 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ @@ -1149,7 +1517,7 @@ testsuite/ + a[i] = b[i] / c[i]; +} --- gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../trunk) (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../branches/ibm/power7-meissner) (revision 144730) ++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -0,0 +1,74 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ @@ -1225,8 +1593,67 @@ testsuite/ + for (i = 0; i < SIZE; i++) + a[i] = b[i] / c[i]; +} +--- gcc/testsuite/gcc.target/powerpc/pr39457.c (.../trunk) (revision 0) ++++ gcc/testsuite/gcc.target/powerpc/pr39457.c (.../branches/ibm/power7-meissner) (revision 146027) +@@ -0,0 +1,56 @@ ++/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ ++/* { dg-options "-m64 -O2 -mminimal-toc" } */ ++ ++/* PR 39457 -- fix breakage because the compiler ran out of registers and ++ wanted to stash a floating point value to the LR/CTR register. */ ++ ++/* -O2 -m64 -mminimal-toc */ ++typedef struct { void *s; } S; ++typedef void (*T1) (void); ++typedef void (*T2) (void *, void *, int, void *); ++char *fn1 (const char *, ...); ++void *fn2 (void); ++int fn3 (char *, int); ++int fn4 (const void *); ++int fn5 (const void *); ++long fn6 (void) __attribute__ ((__const__)); ++int fn7 (void *, void *, void *); ++void *fn8 (void *, long); ++void *fn9 (void *, long, const char *, ...); ++void *fn10 (void *); ++long fn11 (void) __attribute__ ((__const__)); ++long fn12 (void *, const char *, T1, T2, void *); ++void *fn13 (void *); ++long fn14 (void) __attribute__ ((__const__)); ++extern void *v1; ++extern char *v2; ++extern int v3; ++ ++void ++foo (void *x, char *z) ++{ ++ void *i1, *i2; ++ int y; ++ if (v1) ++ return; ++ v1 = fn9 (fn10 (fn2 ()), fn6 (), "x", 0., "y", 0., 0); ++ y = 520 - (520 - fn4 (x)) / 2; ++ fn9 (fn8 (v1, fn6 ()), fn6 (), "wig", fn8 (v1, fn14 ()), "x", 18.0, ++ "y", 16.0, "wid", 80.0, "hi", 500.0, 0); ++ fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 80.0, "y2", ++ 500.0, "f", fn3 ("fff", 0x0D0DFA00), 0); ++ fn13 (((S *) fn8 (v1, fn6 ()))->s); ++ fn12 (fn8 (v1, fn11 ()), "ev", (T1) fn7, 0, fn8 (v1, fn6 ())); ++ fn9 (fn8 (v1, fn6 ()), fn6 (), "wig", ++ fn8 (v1, fn14 ()), "x", 111.0, "y", 14.0, "wid", 774.0, "hi", ++ 500.0, 0); ++ v1 = fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 774.0, "y2", ++ 500.0, "f", fn3 ("gc", 0x0D0DFA00), 0); ++ fn1 (z, 0); ++ i1 = fn9 (fn8 (v1, fn6 ()), fn6 (), "pixbuf", x, "x", ++ 800 - fn5 (x) / 2, "y", y - fn4 (x), 0); ++ fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, "/ok/"); ++ fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, 0); ++ i2 = fn9 (fn8 (v1, fn6 ()), fn6 (), "txt", "OK", "fnt", v2, "x", ++ 800, "y", y - fn4 (x) + 15, "ar", 0, "f", v3, 0); ++} --- gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../trunk) (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../branches/ibm/power7-meissner) (revision 144730) ++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -0,0 +1,48 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ @@ -1276,8 +1703,53 @@ testsuite/ +{ + a = b / c; +} +--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c (.../trunk) (revision 0) ++++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c (.../branches/ibm/power7-meissner) (revision 146027) +@@ -0,0 +1,42 @@ ++/* { dg-do compile { target { powerpc*-*-* } } } */ ++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ ++/* { dg-require-effective-target powerpc_vsx_ok } */ ++/* { dg-options "-O2 -mcpu=power7" } */ ++/* { dg-final { scan-assembler "xvadddp" } } */ ++/* { dg-final { scan-assembler "xvsubdp" } } */ ++/* { dg-final { scan-assembler "xvmuldp" } } */ ++/* { dg-final { scan-assembler "xvmadd" } } */ ++/* { dg-final { scan-assembler "xvmsub" } } */ ++/* { dg-final { scan-assembler "xvnmadd" } } */ ++/* { dg-final { scan-assembler "xvnmsub" } } */ ++/* { dg-final { scan-assembler "xvdivdp" } } */ ++/* { dg-final { scan-assembler "xvmaxdp" } } */ ++/* { dg-final { scan-assembler "xvmindp" } } */ ++/* { dg-final { scan-assembler "xvsqrtdp" } } */ ++/* { dg-final { scan-assembler "xvrsqrtedp" } } */ ++/* { dg-final { scan-assembler "xvtsqrtdp" } } */ ++/* { dg-final { scan-assembler "xvabsdp" } } */ ++/* { dg-final { scan-assembler "xvnabsdp" } } */ ++/* { dg-final { scan-assembler "xvredp" } } */ ++/* { dg-final { scan-assembler "xvtdivdp" } } */ ++ ++void use_builtins (__vector double *p, __vector double *q, __vector double *r, __vector double *s) ++{ ++ p[0] = __builtin_vsx_xvadddp (q[0], r[0]); ++ p[1] = __builtin_vsx_xvsubdp (q[1], r[1]); ++ p[2] = __builtin_vsx_xvmuldp (q[2], r[2]); ++ p[3] = __builtin_vsx_xvdivdp (q[3], r[3]); ++ p[4] = __builtin_vsx_xvmaxdp (q[4], r[4]); ++ p[5] = __builtin_vsx_xvmindp (q[5], r[5]); ++ p[6] = __builtin_vsx_xvabsdp (q[6]); ++ p[7] = __builtin_vsx_xvnabsdp (q[7]); ++ p[8] = __builtin_vsx_xvsqrtdp (q[8]); ++ p[9] = __builtin_vsx_xvmadddp (q[9], r[9], s[9]); ++ p[10] = __builtin_vsx_xvmsubdp (q[10], r[10], s[10]); ++ p[11] = __builtin_vsx_xvnmadddp (q[11], r[11], s[11]); ++ p[12] = __builtin_vsx_xvnmsubdp (q[12], r[12], s[12]); ++ p[13] = __builtin_vsx_xvredp (q[13]); ++ p[14] = __builtin_vsx_xvrsqrtedp (q[14]); ++ p[15] = __builtin_vsx_xvtsqrtdp (q[15]); ++ p[16] = __builtin_vsx_xvtdivdp (q[16], r[16]); ++} --- gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../trunk) (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../branches/ibm/power7-meissner) (revision 144730) ++++ gcc/testsuite/gcc.target/powerpc/popcount-2.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -0,0 +1,9 @@ +/* { dg-do compile { target { ilp32 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ @@ -1289,7 +1761,7 @@ testsuite/ + return __builtin_popcount(x); +} --- gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../trunk) (revision 0) -+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../branches/ibm/power7-meissner) (revision 144730) ++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -0,0 +1,48 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ @@ -1339,8 +1811,8 @@ testsuite/ +{ + a = b / c; +} ---- gcc/testsuite/gcc.dg/vmx/vmx.exp (.../trunk) (revision 144557) -+++ gcc/testsuite/gcc.dg/vmx/vmx.exp (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/testsuite/gcc.dg/vmx/vmx.exp (.../trunk) (revision 145777) ++++ gcc/testsuite/gcc.dg/vmx/vmx.exp (.../branches/ibm/power7-meissner) (revision 146027) @@ -31,7 +31,7 @@ if {![istarget powerpc*-*-*] # nothing but extensions. global DEFAULT_VMXCFLAGS @@ -1350,8 +1822,8 @@ testsuite/ } # If the target system supports AltiVec instructions, the default action ---- gcc/testsuite/lib/target-supports.exp (.../trunk) (revision 144557) -+++ gcc/testsuite/lib/target-supports.exp (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/testsuite/lib/target-supports.exp (.../trunk) (revision 145777) ++++ gcc/testsuite/lib/target-supports.exp (.../branches/ibm/power7-meissner) (revision 146027) @@ -873,6 +873,32 @@ proc check_sse2_hw_available { } { }] } @@ -1436,9 +1908,9 @@ testsuite/ # Return 1 if this is a PowerPC target supporting -mcpu=cell. proc check_effective_target_powerpc_ppu_ok { } { ---- gcc/config.in (.../trunk) (revision 144557) -+++ gcc/config.in (.../branches/ibm/power7-meissner) (revision 144730) -@@ -334,12 +334,18 @@ +--- gcc/config.in (.../trunk) (revision 145777) ++++ gcc/config.in (.../branches/ibm/power7-meissner) (revision 146027) +@@ -327,12 +327,18 @@ #endif @@ -1458,18 +1930,9 @@ testsuite/ /* Define if your assembler supports .register. */ #ifndef USED_FOR_TARGET #undef HAVE_AS_REGISTER_PSEUDO_OP ---- gcc/configure.ac (.../trunk) (revision 144557) -+++ gcc/configure.ac (.../branches/ibm/power7-meissner) (revision 144730) -@@ -2,7 +2,7 @@ - # Process this file with autoconf to generate a configuration script. - - # Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, --# 2007, 2008 Free Software Foundation, Inc. -+# 2007, 2008, 2009 Free Software Foundation, Inc. - - #This file is part of GCC. - -@@ -3080,7 +3080,7 @@ foo: nop +--- gcc/configure.ac (.../trunk) (revision 145777) ++++ gcc/configure.ac (.../branches/ibm/power7-meissner) (revision 146027) +@@ -3054,7 +3054,7 @@ foo: nop esac gcc_GAS_CHECK_FEATURE([move fp gpr support], @@ -1478,7 +1941,7 @@ testsuite/ [$conftest_s],, [AC_DEFINE(HAVE_AS_MFPGPR, 1, [Define if your assembler supports mffgpr and mftgpr.])]) -@@ -3114,7 +3114,7 @@ LCF0: +@@ -3088,7 +3088,7 @@ LCF0: esac gcc_GAS_CHECK_FEATURE([compare bytes support], @@ -1487,7 +1950,7 @@ testsuite/ [$conftest_s],, [AC_DEFINE(HAVE_AS_CMPB, 1, [Define if your assembler supports cmpb.])]) -@@ -3129,7 +3129,7 @@ LCF0: +@@ -3103,7 +3103,7 @@ LCF0: esac gcc_GAS_CHECK_FEATURE([decimal float support], @@ -1496,7 +1959,7 @@ testsuite/ [$conftest_s],, [AC_DEFINE(HAVE_AS_DFP, 1, [Define if your assembler supports DFP instructions.])]) -@@ -3144,11 +3144,26 @@ LCF0: +@@ -3118,11 +3118,26 @@ LCF0: esac gcc_GAS_CHECK_FEATURE([vector-scalar support], @@ -1524,99 +1987,8 @@ testsuite/ gcc_GAS_CHECK_FEATURE([.gnu_attribute support], gcc_cv_as_powerpc_gnu_attribute, [2,18,0],, [.gnu_attribute 4,1],, ---- gcc/configure (.../trunk) (revision 144557) -+++ gcc/configure (.../branches/ibm/power7-meissner) (revision 144730) -@@ -23225,7 +23225,7 @@ if test "${gcc_cv_as_powerpc_mfpgpr+set} - else - gcc_cv_as_powerpc_mfpgpr=no - if test $in_tree_gas = yes; then -- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` -+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` - then gcc_cv_as_powerpc_mfpgpr=yes - fi - elif test x$gcc_cv_as != x; then -@@ -23321,7 +23321,7 @@ if test "${gcc_cv_as_powerpc_cmpb+set}" - else - gcc_cv_as_powerpc_cmpb=no - if test $in_tree_gas = yes; then -- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` -+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` - then gcc_cv_as_powerpc_cmpb=yes - fi - elif test x$gcc_cv_as != x; then -@@ -23367,7 +23367,7 @@ if test "${gcc_cv_as_powerpc_dfp+set}" = - else - gcc_cv_as_powerpc_dfp=no - if test $in_tree_gas = yes; then -- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` -+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` - then gcc_cv_as_powerpc_dfp=yes - fi - elif test x$gcc_cv_as != x; then -@@ -23413,7 +23413,7 @@ if test "${gcc_cv_as_powerpc_vsx+set}" = - else - gcc_cv_as_powerpc_vsx=no - if test $in_tree_gas = yes; then -- if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0` -+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` - then gcc_cv_as_powerpc_vsx=yes - fi - elif test x$gcc_cv_as != x; then -@@ -23443,6 +23443,52 @@ _ACEOF - - fi - -+ case $target in -+ *-*-aix*) conftest_s=' .machine "pwr7" -+ .csect .text[PR] -+ popcntd 3,3';; -+ *) conftest_s=' .machine power7 -+ .text -+ popcntd 3,3';; -+ esac -+ -+ echo "$as_me:$LINENO: checking assembler for popcntd support" >&5 -+echo $ECHO_N "checking assembler for popcntd support... $ECHO_C" >&6 -+if test "${gcc_cv_as_powerpc_popcntd+set}" = set; then -+ echo $ECHO_N "(cached) $ECHO_C" >&6 -+else -+ gcc_cv_as_powerpc_popcntd=no -+ if test $in_tree_gas = yes; then -+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2` -+ then gcc_cv_as_powerpc_popcntd=yes -+fi -+ elif test x$gcc_cv_as != x; then -+ echo "$conftest_s" > conftest.s -+ if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5' -+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 -+ (eval $ac_try) 2>&5 -+ ac_status=$? -+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 -+ (exit $ac_status); }; } -+ then -+ gcc_cv_as_powerpc_popcntd=yes -+ else -+ echo "configure: failed program was" >&5 -+ cat conftest.s >&5 -+ fi -+ rm -f conftest.o conftest.s -+ fi -+fi -+echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntd" >&5 -+echo "${ECHO_T}$gcc_cv_as_powerpc_popcntd" >&6 -+if test $gcc_cv_as_powerpc_popcntd = yes; then -+ -+cat >>confdefs.h <<\_ACEOF -+#define HAVE_AS_POPCNTD 1 -+_ACEOF -+ -+fi -+ - echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5 - echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6 - if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then ---- gcc/config/rs6000/aix53.h (.../trunk) (revision 144557) -+++ gcc/config/rs6000/aix53.h (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/aix53.h (.../trunk) (revision 145777) ++++ gcc/config/rs6000/aix53.h (.../branches/ibm/power7-meissner) (revision 146027) @@ -57,20 +57,24 @@ do { \ #undef ASM_SPEC #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)" @@ -1645,8 +2017,8 @@ testsuite/ %{mcpu=rs64a: -mppc} \ %{mcpu=603: -m603} \ --- gcc/config/rs6000/vector.md (.../trunk) (revision 0) -+++ gcc/config/rs6000/vector.md (.../branches/ibm/power7-meissner) (revision 144730) -@@ -0,0 +1,518 @@ ++++ gcc/config/rs6000/vector.md (.../branches/ibm/power7-meissner) (revision 146027) +@@ -0,0 +1,664 @@ +;; Expander definitions for vector support between altivec & vsx. No +;; instructions are in this file, this file provides the generic vector +;; expander, and the actual vector instructions will be in altivec.md and @@ -1688,6 +2060,9 @@ testsuite/ +;; Vector comparison modes +(define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF]) + ++;; Vector reload iterator ++(define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF DF TI]) ++ +;; Base type from vector mode +(define_mode_attr VEC_base [(V16QI "QI") + (V8HI "HI") @@ -1710,15 +2085,16 @@ testsuite/ + (match_operand:VEC_M 1 "any_operand" ""))] + "VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)" +{ -+ /* modes without special handling just generate the normal SET operation. */ -+ if (mode != TImode && mode != V2DImode && mode != V2DFmode) ++ if (can_create_pseudo_p ()) + { -+ rs6000_emit_move (operands[0], operands[1], mode); -+ DONE; ++ if (CONSTANT_P (operands[1]) ++ && !easy_vector_constant (operands[1], mode)) ++ operands[1] = force_const_mem (mode, operands[1]); ++ ++ else if (!vlogical_operand (operands[0], mode) ++ && !vlogical_operand (operands[1], mode)) ++ operands[1] = force_reg (mode, operands[1]); + } -+ else if (!vlogical_operand (operands[0], mode) -+ && !vlogical_operand (operands[1], mode)) -+ operands[1] = force_reg (mode, operands[1]); +}) + +;; Generic vector floating point load/store instructions. These will match @@ -1749,6 +2125,49 @@ testsuite/ +}) + + ++;; Reload patterns for vector operations. We may need an addtional base ++;; register to convert the reg+offset addressing to reg+reg for vector ++;; registers and reg+reg or (reg+reg)&(-16) addressing to just an index ++;; register for gpr registers. ++(define_expand "reload___store" ++ [(parallel [(match_operand:VEC_R 0 "memory_operand" "m") ++ (match_operand:VEC_R 1 "gpc_reg_operand" "r") ++ (match_operand:P 2 "register_operand" "=&b")])] ++ "" ++{ ++ rs6000_secondary_reload_inner (operands[1], operands[0], operands[2], true); ++ DONE; ++}) ++ ++(define_expand "reload___load" ++ [(parallel [(match_operand:VEC_R 0 "gpc_reg_operand" "=&r") ++ (match_operand:VEC_R 1 "memory_operand" "m") ++ (match_operand:P 2 "register_operand" "=&b")])] ++ "" ++{ ++ rs6000_secondary_reload_inner (operands[0], operands[1], operands[2], false); ++ DONE; ++}) ++ ++;; Reload sometimes tries to move the address to a GPR, and can generate ++;; invalid RTL for addresses involving AND -16. ++ ++(define_insn_and_split "*vec_reload_and_plus_" ++ [(set (match_operand:P 0 "gpc_reg_operand" "=b") ++ (and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r") ++ (match_operand:P 2 "gpc_reg_operand" "r")) ++ (const_int -16)))] ++ "TARGET_ALTIVEC || TARGET_VSX" ++ "#" ++ "&& reload_completed" ++ [(set (match_dup 0) ++ (plus:P (match_dup 1) ++ (match_dup 2))) ++ (parallel [(set (match_dup 0) ++ (and:P (match_dup 0) ++ (const_int -16))) ++ (clobber:CC (scratch:CC))])]) ++ +;; Generic floating point vector arithmetic support +(define_expand "add3" + [(set (match_operand:VEC_F 0 "vfloat_operand" "") @@ -2145,28 +2564,127 @@ testsuite/ + "VECTOR_UNIT_VSX_P (V2DFmode)" + "") + -+;; For 2 element vectors, even/odd is the same as high/low -+(define_expand "vec_extract_evenv2df" -+ [(set (match_operand:V2DF 0 "vfloat_operand" "") -+ (vec_concat:V2DF -+ (vec_select:DF (match_operand:V2DF 1 "vfloat_operand" "") -+ (parallel [(const_int 0)])) -+ (vec_select:DF (match_operand:V2DF 2 "vfloat_operand" "") -+ (parallel [(const_int 0)]))))] -+ "VECTOR_UNIT_VSX_P (V2DFmode)" -+ "") ++ ++;; Convert double word types to single word types ++(define_expand "vec_pack_trunc_v2df" ++ [(match_operand:V4SF 0 "vsx_register_operand" "") ++ (match_operand:V2DF 1 "vsx_register_operand" "") ++ (match_operand:V2DF 2 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" ++{ ++ rtx r1 = gen_reg_rtx (V4SFmode); ++ rtx r2 = gen_reg_rtx (V4SFmode); + -+(define_expand "vec_extract_oddv2df" -+ [(set (match_operand:V2DF 0 "vfloat_operand" "") -+ (vec_concat:V2DF -+ (vec_select:DF (match_operand:V2DF 1 "vfloat_operand" "") -+ (parallel [(const_int 1)])) -+ (vec_select:DF (match_operand:V2DF 2 "vfloat_operand" "") -+ (parallel [(const_int 1)]))))] -+ "VECTOR_UNIT_VSX_P (V2DFmode)" -+ "") ---- gcc/config/rs6000/spe.md (.../trunk) (revision 144557) -+++ gcc/config/rs6000/spe.md (.../branches/ibm/power7-meissner) (revision 144730) ++ emit_insn (gen_vsx_xvcvdpsp (r1, operands[1])); ++ emit_insn (gen_vsx_xvcvdpsp (r2, operands[2])); ++ emit_insn (gen_vec_extract_evenv4sf (operands[0], r1, r2)); ++ DONE; ++}) ++ ++(define_expand "vec_pack_sfix_trunc_v2df" ++ [(match_operand:V4SI 0 "vsx_register_operand" "") ++ (match_operand:V2DF 1 "vsx_register_operand" "") ++ (match_operand:V2DF 2 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" ++{ ++ rtx r1 = gen_reg_rtx (V4SImode); ++ rtx r2 = gen_reg_rtx (V4SImode); ++ ++ emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1])); ++ emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2])); ++ emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2)); ++ DONE; ++}) ++ ++(define_expand "vec_pack_ufix_trunc_v2df" ++ [(match_operand:V4SI 0 "vsx_register_operand" "") ++ (match_operand:V2DF 1 "vsx_register_operand" "") ++ (match_operand:V2DF 2 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC" ++{ ++ rtx r1 = gen_reg_rtx (V4SImode); ++ rtx r2 = gen_reg_rtx (V4SImode); ++ ++ emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1])); ++ emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2])); ++ emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2)); ++ DONE; ++}) ++ ++;; Convert single word types to double word ++(define_expand "vec_unpacks_hi_v4sf" ++ [(match_operand:V2DF 0 "vsx_register_operand" "") ++ (match_operand:V4SF 1 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)" ++{ ++ rtx reg = gen_reg_rtx (V4SFmode); ++ ++ emit_insn (gen_vec_interleave_highv4sf (reg, operands[1], operands[1])); ++ emit_insn (gen_vsx_xvcvspdp (operands[0], reg)); ++ DONE; ++}) ++ ++(define_expand "vec_unpacks_lo_v4sf" ++ [(match_operand:V2DF 0 "vsx_register_operand" "") ++ (match_operand:V4SF 1 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)" ++{ ++ rtx reg = gen_reg_rtx (V4SFmode); ++ ++ emit_insn (gen_vec_interleave_lowv4sf (reg, operands[1], operands[1])); ++ emit_insn (gen_vsx_xvcvspdp (operands[0], reg)); ++ DONE; ++}) ++ ++(define_expand "vec_unpacks_float_hi_v4si" ++ [(match_operand:V2DF 0 "vsx_register_operand" "") ++ (match_operand:V4SI 1 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" ++{ ++ rtx reg = gen_reg_rtx (V4SImode); ++ ++ emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1])); ++ emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg)); ++ DONE; ++}) ++ ++(define_expand "vec_unpacks_float_lo_v4si" ++ [(match_operand:V2DF 0 "vsx_register_operand" "") ++ (match_operand:V4SI 1 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" ++{ ++ rtx reg = gen_reg_rtx (V4SImode); ++ ++ emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1])); ++ emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg)); ++ DONE; ++}) ++ ++(define_expand "vec_unpacku_float_hi_v4si" ++ [(match_operand:V2DF 0 "vsx_register_operand" "") ++ (match_operand:V4SI 1 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" ++{ ++ rtx reg = gen_reg_rtx (V4SImode); ++ ++ emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1])); ++ emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg)); ++ DONE; ++}) ++ ++(define_expand "vec_unpacku_float_lo_v4si" ++ [(match_operand:V2DF 0 "vsx_register_operand" "") ++ (match_operand:V4SI 1 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)" ++{ ++ rtx reg = gen_reg_rtx (V4SImode); ++ ++ emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1])); ++ emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg)); ++ DONE; ++}) +--- gcc/config/rs6000/spe.md (.../trunk) (revision 145777) ++++ gcc/config/rs6000/spe.md (.../branches/ibm/power7-meissner) (revision 146027) @@ -99,7 +99,7 @@ (define_insn "*divsf3_gpr" ;; Floating point conversion instructions. @@ -2176,8 +2694,8 @@ testsuite/ [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "r")))] "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE" ---- gcc/config/rs6000/constraints.md (.../trunk) (revision 144557) -+++ gcc/config/rs6000/constraints.md (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/constraints.md (.../trunk) (revision 145777) ++++ gcc/config/rs6000/constraints.md (.../branches/ibm/power7-meissner) (revision 146027) @@ -17,6 +17,8 @@ ;; along with GCC; see the file COPYING3. If not see ;; . @@ -2187,7 +2705,7 @@ testsuite/ ;; Register constraints (define_register_constraint "f" "TARGET_HARD_FLOAT && TARGET_FPRS -@@ -50,6 +52,23 @@ (define_register_constraint "y" "CR_REGS +@@ -50,6 +52,28 @@ (define_register_constraint "y" "CR_REGS (define_register_constraint "z" "XER_REGS" "@internal") @@ -2207,11 +2725,16 @@ testsuite/ +;; any VSX register +(define_register_constraint "wa" "rs6000_vsx_reg_class" + "@internal") ++ ++;; Altivec style load/store that ignores the bottom bits of the address ++(define_memory_constraint "wZ" ++ "Indexed or indirect memory operand, ignoring the bottom 4 bits" ++ (match_operand 0 "altivec_indexed_or_indirect_operand")) + ;; Integer constraints (define_constraint "I" -@@ -159,3 +178,7 @@ (define_constraint "t" +@@ -159,3 +183,7 @@ (define_constraint "t" (define_constraint "W" "vector constant that does not require memory" (match_operand 0 "easy_vector_constant")) @@ -2219,8 +2742,8 @@ testsuite/ +(define_constraint "j" + "Zero vector constant" + (match_test "(op == const0_rtx || op == CONST0_RTX (GET_MODE (op)))")) ---- gcc/config/rs6000/predicates.md (.../trunk) (revision 144557) -+++ gcc/config/rs6000/predicates.md (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/predicates.md (.../trunk) (revision 145777) ++++ gcc/config/rs6000/predicates.md (.../branches/ibm/power7-meissner) (revision 146027) @@ -38,6 +38,37 @@ (define_predicate "altivec_register_oper || ALTIVEC_REGNO_P (REGNO (op)) || REGNO (op) > LAST_VIRTUAL_REGISTER"))) @@ -2270,7 +2793,7 @@ testsuite/ /* Force constants to memory before reload to utilize compress_float_constant. Avoid this when flag_unsafe_math_optimizations is enabled -@@ -396,13 +431,16 @@ (define_predicate "indexed_or_indirect_o +@@ -396,16 +431,36 @@ (define_predicate "indexed_or_indirect_o (match_code "mem") { op = XEXP (op, 0); @@ -2289,7 +2812,27 @@ testsuite/ return indexed_or_indirect_address (op, mode); }) -@@ -1336,3 +1374,19 @@ (define_predicate "stmw_operation" ++;; Return 1 if the operand is an indexed or indirect memory operand with an ++;; AND -16 in it, used to recognize when we need to switch to Altivec loads ++;; to realign loops instead of VSX (altivec silently ignores the bottom bits, ++;; while VSX uses the full address and traps) ++(define_predicate "altivec_indexed_or_indirect_operand" ++ (match_code "mem") ++{ ++ op = XEXP (op, 0); ++ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) ++ && GET_CODE (op) == AND ++ && GET_CODE (XEXP (op, 1)) == CONST_INT ++ && INTVAL (XEXP (op, 1)) == -16) ++ return indexed_or_indirect_address (XEXP (op, 0), mode); ++ ++ return 0; ++}) ++ + ;; Return 1 if the operand is an indexed or indirect address. + (define_special_predicate "indexed_or_indirect_address" + (and (match_test "REG_P (op) +@@ -1336,3 +1391,19 @@ (define_predicate "stmw_operation" return 1; }) @@ -2309,8 +2852,8 @@ testsuite/ + + return 1; +}) ---- gcc/config/rs6000/ppc-asm.h (.../trunk) (revision 144557) -+++ gcc/config/rs6000/ppc-asm.h (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/ppc-asm.h (.../trunk) (revision 145777) ++++ gcc/config/rs6000/ppc-asm.h (.../branches/ibm/power7-meissner) (revision 146027) @@ -63,7 +63,7 @@ #define f16 16 #define f17 17 @@ -2464,8 +3007,8 @@ testsuite/ /* * Macros to glue together two tokens. */ ---- gcc/config/rs6000/linux64.opt (.../trunk) (revision 144557) -+++ gcc/config/rs6000/linux64.opt (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/linux64.opt (.../trunk) (revision 145777) ++++ gcc/config/rs6000/linux64.opt (.../branches/ibm/power7-meissner) (revision 146027) @@ -20,5 +20,5 @@ ; . @@ -2473,8 +3016,8 @@ testsuite/ -Target Report Mask(PROFILE_KERNEL) +Target Report Var(TARGET_PROFILE_KERNEL) Call mcount for profiling before a function prologue ---- gcc/config/rs6000/sysv4.opt (.../trunk) (revision 144557) -+++ gcc/config/rs6000/sysv4.opt (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/sysv4.opt (.../trunk) (revision 145777) ++++ gcc/config/rs6000/sysv4.opt (.../branches/ibm/power7-meissner) (revision 146027) @@ -32,7 +32,7 @@ Target RejectNegative Joined Specify bit size of immediate TLS offsets @@ -2498,9 +3041,9 @@ testsuite/ Use alternate register names ;; FIXME: Does nothing. ---- gcc/config/rs6000/rs6000-protos.h (.../trunk) (revision 144557) -+++ gcc/config/rs6000/rs6000-protos.h (.../branches/ibm/power7-meissner) (revision 144730) -@@ -64,9 +64,14 @@ extern int insvdi_rshift_rlwimi_p (rtx, +--- gcc/config/rs6000/rs6000-protos.h (.../trunk) (revision 145777) ++++ gcc/config/rs6000/rs6000-protos.h (.../branches/ibm/power7-meissner) (revision 146027) +@@ -64,9 +64,15 @@ extern int insvdi_rshift_rlwimi_p (rtx, extern int registers_ok_for_quad_peep (rtx, rtx); extern int mems_ok_for_quad_peep (rtx, rtx); extern bool gpr_or_gpr_p (rtx, rtx); @@ -2513,10 +3056,11 @@ testsuite/ +extern bool rs6000_cannot_change_mode_class (enum machine_mode, + enum machine_mode, + enum reg_class); ++extern void rs6000_secondary_reload_inner (rtx, rtx, rtx, bool); extern int paired_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx); extern void paired_expand_vector_move (rtx operands[]); -@@ -170,7 +175,6 @@ extern int rs6000_register_move_cost (en +@@ -170,7 +176,6 @@ extern int rs6000_register_move_cost (en enum reg_class, enum reg_class); extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int); extern bool rs6000_tls_referenced_p (rtx); @@ -2524,15 +3068,15 @@ testsuite/ extern void rs6000_conditional_register_usage (void); /* Declare functions in rs6000-c.c */ -@@ -189,4 +193,6 @@ const char * rs6000_xcoff_strip_dollar ( +@@ -189,4 +194,6 @@ const char * rs6000_xcoff_strip_dollar ( void rs6000_final_prescan_insn (rtx, rtx *operand, int num_operands); extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER]; +extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES]; +extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER]; #endif /* rs6000-protos.h */ ---- gcc/config/rs6000/t-rs6000 (.../trunk) (revision 144557) -+++ gcc/config/rs6000/t-rs6000 (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/t-rs6000 (.../trunk) (revision 145777) ++++ gcc/config/rs6000/t-rs6000 (.../branches/ibm/power7-meissner) (revision 146027) @@ -16,3 +16,33 @@ rs6000-c.o: $(srcdir)/config/rs6000/rs60 # The rs6000 backend doesn't cause warnings in these files. @@ -2568,8 +3112,8 @@ testsuite/ + $(srcdir)/config/rs6000/dfp.md \ + $(srcdir)/config/rs6000/paired.md --- gcc/config/rs6000/power7.md (.../trunk) (revision 0) -+++ gcc/config/rs6000/power7.md (.../branches/ibm/power7-meissner) (revision 144730) -@@ -0,0 +1,320 @@ ++++ gcc/config/rs6000/power7.md (.../branches/ibm/power7-meissner) (revision 146027) +@@ -0,0 +1,318 @@ +;; Scheduling description for IBM POWER7 processor. +;; Copyright (C) 2009 Free Software Foundation, Inc. +;; @@ -2888,11 +3432,82 @@ testsuite/ + (and (eq_attr "type" "vecperm") + (eq_attr "cpu" "power7")) + "du2_power7,VSU_power7") +--- gcc/config/rs6000/rs6000-c.c (.../trunk) (revision 145777) ++++ gcc/config/rs6000/rs6000-c.c (.../branches/ibm/power7-meissner) (revision 146027) +@@ -106,14 +106,17 @@ altivec_categorize_keyword (const cpp_to + if (ident == C_CPP_HASHNODE (vector_keyword)) + return C_CPP_HASHNODE (__vector_keyword); + +- if (ident == C_CPP_HASHNODE (pixel_keyword)) +- return C_CPP_HASHNODE (__pixel_keyword); ++ if (TARGET_ALTIVEC) ++ { ++ if (ident == C_CPP_HASHNODE (pixel_keyword)) ++ return C_CPP_HASHNODE (__pixel_keyword); + +- if (ident == C_CPP_HASHNODE (bool_keyword)) +- return C_CPP_HASHNODE (__bool_keyword); ++ if (ident == C_CPP_HASHNODE (bool_keyword)) ++ return C_CPP_HASHNODE (__bool_keyword); + +- if (ident == C_CPP_HASHNODE (_Bool_keyword)) +- return C_CPP_HASHNODE (__bool_keyword); ++ if (ident == C_CPP_HASHNODE (_Bool_keyword)) ++ return C_CPP_HASHNODE (__bool_keyword); ++ } + + return ident; + } +@@ -131,23 +134,26 @@ init_vector_keywords (void) + __vector_keyword = get_identifier ("__vector"); + C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL; + +- __pixel_keyword = get_identifier ("__pixel"); +- C_CPP_HASHNODE (__pixel_keyword)->flags |= NODE_CONDITIONAL; +- +- __bool_keyword = get_identifier ("__bool"); +- C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL; +- + vector_keyword = get_identifier ("vector"); + C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL; + +- pixel_keyword = get_identifier ("pixel"); +- C_CPP_HASHNODE (pixel_keyword)->flags |= NODE_CONDITIONAL; ++ if (TARGET_ALTIVEC) ++ { ++ __pixel_keyword = get_identifier ("__pixel"); ++ C_CPP_HASHNODE (__pixel_keyword)->flags |= NODE_CONDITIONAL; + ++ __bool_keyword = get_identifier ("__bool"); ++ C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL; + +- bool_keyword = get_identifier ("bool"); +- C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL; ++ pixel_keyword = get_identifier ("pixel"); ++ C_CPP_HASHNODE (pixel_keyword)->flags |= NODE_CONDITIONAL; + +- _Bool_keyword = get_identifier ("_Bool"); +- C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL; ++ bool_keyword = get_identifier ("bool"); ++ C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL; + ---- gcc/config/rs6000/rs6000-c.c (.../trunk) (revision 144557) -+++ gcc/config/rs6000/rs6000-c.c (.../branches/ibm/power7-meissner) (revision 144730) -@@ -265,6 +265,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi ++ _Bool_keyword = get_identifier ("_Bool"); ++ C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL; ++ } + } + + /* Called to decide whether a conditional macro should be expanded. +@@ -214,7 +220,8 @@ rs6000_macro_to_expand (cpp_reader *pfil + if (rid_code == RID_UNSIGNED || rid_code == RID_LONG + || rid_code == RID_SHORT || rid_code == RID_SIGNED + || rid_code == RID_INT || rid_code == RID_CHAR +- || rid_code == RID_FLOAT) ++ || rid_code == RID_FLOAT ++ || (rid_code == RID_DOUBLE && TARGET_VSX)) + { + expand_this = C_CPP_HASHNODE (__vector_keyword); + /* If the next keyword is bool or pixel, it +@@ -284,13 +291,14 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi builtin_define ("_ARCH_PWR6X"); if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC) builtin_define ("_ARCH_COM"); @@ -2901,7 +3516,37 @@ testsuite/ if (TARGET_ALTIVEC) { builtin_define ("__ALTIVEC__"); -@@ -306,6 +308,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi + builtin_define ("__VEC__=10206"); + + /* Define the AltiVec syntactic elements. */ +- builtin_define ("__vector=__attribute__((altivec(vector__)))"); + builtin_define ("__pixel=__attribute__((altivec(pixel__))) unsigned short"); + builtin_define ("__bool=__attribute__((altivec(bool__))) unsigned"); + +@@ -298,11 +306,20 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi + { + /* Define this when supporting context-sensitive keywords. */ + builtin_define ("__APPLE_ALTIVEC__"); +- +- builtin_define ("vector=vector"); ++ + builtin_define ("pixel=pixel"); + builtin_define ("bool=bool"); + builtin_define ("_Bool=_Bool"); ++ } ++ } ++ if (TARGET_ALTIVEC || TARGET_VSX) ++ { ++ /* Define the AltiVec/VSX syntactic elements. */ ++ builtin_define ("__vector=__attribute__((altivec(vector__)))"); ++ ++ if (!flag_iso) ++ { ++ builtin_define ("vector=vector"); + init_vector_keywords (); + + /* Enable context-sensitive macros. */ +@@ -326,6 +343,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi /* Used by libstdc++. */ if (TARGET_NO_LWSYNC) builtin_define ("__NO_LWSYNC__"); @@ -2910,9 +3555,119 @@ testsuite/ /* May be overridden by target configuration. */ RS6000_CPU_CPP_ENDIAN_BUILTINS(); ---- gcc/config/rs6000/rs6000.opt (.../trunk) (revision 144557) -+++ gcc/config/rs6000/rs6000.opt (.../branches/ibm/power7-meissner) (revision 144730) -@@ -111,24 +111,44 @@ mhard-float +@@ -504,6 +523,8 @@ const struct altivec_builtin_types altiv + RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_ADD, VSX_BUILTIN_XVADDDP, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_VADDFP, ALTIVEC_BUILTIN_VADDFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM, +@@ -647,6 +668,12 @@ const struct altivec_builtin_types altiv + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 }, ++ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, ++ RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 }, +@@ -695,6 +722,12 @@ const struct altivec_builtin_types altiv + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 }, ++ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, ++ RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 }, +@@ -1198,6 +1231,8 @@ const struct altivec_builtin_types altiv + RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_MAX, VSX_BUILTIN_XVMAXDP, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_VMAXFP, ALTIVEC_BUILTIN_VMAXFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_VMAXSW, ALTIVEC_BUILTIN_VMAXSW, +@@ -1374,6 +1409,8 @@ const struct altivec_builtin_types altiv + RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_MIN, VSX_BUILTIN_XVMINDP, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_VMINFP, ALTIVEC_BUILTIN_VMINFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_VMINSW, ALTIVEC_BUILTIN_VMINSW, +@@ -1459,6 +1496,8 @@ const struct altivec_builtin_types altiv + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 }, +@@ -1483,6 +1522,12 @@ const struct altivec_builtin_types altiv + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 }, ++ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, ++ RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 }, +@@ -1940,6 +1985,8 @@ const struct altivec_builtin_types altiv + RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_SUB, VSX_BUILTIN_XVSUBDP, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_VSUBFP, ALTIVEC_BUILTIN_VSUBFP, + RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM, +@@ -2099,6 +2146,12 @@ const struct altivec_builtin_types altiv + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 }, + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, ++ RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 }, ++ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, ++ RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 }, ++ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 }, +@@ -2989,8 +3042,10 @@ altivec_resolve_overloaded_builtin (tree + const struct altivec_builtin_types *desc; + int n; + +- if (fcode < ALTIVEC_BUILTIN_OVERLOADED_FIRST +- || fcode > ALTIVEC_BUILTIN_OVERLOADED_LAST) ++ if ((fcode < ALTIVEC_BUILTIN_OVERLOADED_FIRST ++ || fcode > ALTIVEC_BUILTIN_OVERLOADED_LAST) ++ && (fcode < VSX_BUILTIN_OVERLOADED_FIRST ++ || fcode > VSX_BUILTIN_OVERLOADED_LAST)) + return NULL_TREE; + + /* For now treat vec_splats and vec_promote as the same. */ +--- gcc/config/rs6000/rs6000.opt (.../trunk) (revision 145777) ++++ gcc/config/rs6000/rs6000.opt (.../branches/ibm/power7-meissner) (revision 146027) +@@ -111,24 +111,60 @@ mhard-float Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT) Use hardware floating point @@ -2928,24 +3683,40 @@ testsuite/ +Use vector/scalar (VSX) instructions + +mvsx-vector-memory -+Target Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1) -+If -mvsx, use VSX vector load/store instructions instead of Altivec instructions ++Target Undocumented Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1) ++; If -mvsx, use VSX vector load/store instructions instead of Altivec instructions + +mvsx-vector-float -+Target Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1) -+If -mvsx, use VSX arithmetic instructions for float vectors (on by default) ++Target Undocumented Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1) ++; If -mvsx, use VSX arithmetic instructions for float vectors (on by default) + +mvsx-vector-double -+Target Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1) -+If -mvsx, use VSX arithmetic instructions for double vectors (on by default) ++Target Undocumented Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1) ++; If -mvsx, use VSX arithmetic instructions for double vectors (on by default) + +mvsx-scalar-double -+Target Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1) -+If -mvsx, use VSX arithmetic instructions for scalar double (on by default) ++Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1) ++; If -mvsx, use VSX arithmetic instructions for scalar double (on by default) + +mvsx-scalar-memory -+Target Report Var(TARGET_VSX_SCALAR_MEMORY) -+If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default) ++Target Undocumented Report Var(TARGET_VSX_SCALAR_MEMORY) ++; If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default) ++ ++mvsx-v4sf-altivec-regs ++Target Undocumented Report Var(TARGET_V4SF_ALTIVEC_REGS) Init(-1) ++; If -mvsx, prefer V4SF types to use Altivec regs and not the floating registers ++ ++mreload-functions ++Target Undocumented Report Var(TARGET_RELOAD_FUNCTIONS) Init(-1) ++; If -mvsx or -maltivec, enable reload functions ++ ++mpower7-adjust-cost ++Target Undocumented Var(TARGET_POWER7_ADJUST_COST) ++; Add extra cost for setting CR registers before a branch like is done for Power5 ++ ++mdisallow-float-in-lr-ctr ++Target Undocumented Var(TARGET_DISALLOW_FLOAT_IN_LR_CTR) Init(-1) ++; Disallow floating point in LR or CTR, causes some reload bugs mupdate -Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE) @@ -2966,7 +3737,7 @@ testsuite/ Generate fused multiply/add instructions msched-prolog -@@ -194,7 +214,7 @@ Target RejectNegative Joined +@@ -194,7 +230,7 @@ Target RejectNegative Joined -mvrsave=yes/no Deprecated option. Use -mvrsave/-mno-vrsave instead misel @@ -2975,8 +3746,8 @@ testsuite/ Generate isel instructions misel= ---- gcc/config/rs6000/linux64.h (.../trunk) (revision 144557) -+++ gcc/config/rs6000/linux64.h (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/linux64.h (.../trunk) (revision 145777) ++++ gcc/config/rs6000/linux64.h (.../branches/ibm/power7-meissner) (revision 146027) @@ -114,7 +114,7 @@ extern int dot_symbols; error (INVALID_32BIT, "32"); \ if (TARGET_PROFILE_KERNEL) \ @@ -2986,8 +3757,8 @@ testsuite/ error (INVALID_32BIT, "profile-kernel"); \ } \ } \ ---- gcc/config/rs6000/rs6000.c (.../trunk) (revision 144557) -+++ gcc/config/rs6000/rs6000.c (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/rs6000.c (.../trunk) (revision 145777) ++++ gcc/config/rs6000/rs6000.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -178,9 +178,6 @@ int rs6000_spe; /* Nonzero if we want SPE ABI extensions. */ int rs6000_spe_abi; @@ -2998,26 +3769,35 @@ testsuite/ /* Nonzero if floating point operations are done in the GPRs. */ int rs6000_float_gprs = 0; -@@ -227,10 +224,18 @@ int dot_symbols; +@@ -227,12 +224,26 @@ int dot_symbols; const char *rs6000_debug_name; int rs6000_debug_stack; /* debug stack applications */ int rs6000_debug_arg; /* debug argument handling */ +int rs6000_debug_reg; /* debug register classes */ +int rs6000_debug_addr; /* debug memory addressing */ ++int rs6000_debug_cost; /* debug rtx_costs */ /* Value is TRUE if register/mode pair is acceptable. */ bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER]; +-/* Built in types. */ +/* Maximum number of registers needed for a given register class and mode. */ +unsigned char rs6000_class_max_nregs[NUM_MACHINE_MODES][LIM_REG_CLASSES]; + +/* How many registers are needed for a given register and mode. */ +unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER]; + - /* Built in types. */ ++/* Map register number to register class. */ ++enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER]; ++/* Reload functions based on the type and the vector unit. */ ++static enum insn_code rs6000_vector_reload[NUM_MACHINE_MODES][2]; ++ ++/* Built in types. */ tree rs6000_builtin_types[RS6000_BTI_MAX]; -@@ -270,7 +275,6 @@ struct { + tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT]; + +@@ -270,7 +281,6 @@ struct { bool altivec_abi; /* True if -mabi=altivec/no-altivec used. */ bool spe; /* True if -mspe= was used. */ bool float_gprs; /* True if -mfloat-gprs= was used. */ @@ -3025,7 +3805,7 @@ testsuite/ bool long_double; /* True if -mlong-double- was used. */ bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */ bool vrsave; /* True if -mvrsave was used. */ -@@ -286,6 +290,18 @@ struct builtin_description +@@ -286,6 +296,18 @@ struct builtin_description const char *const name; const enum rs6000_builtins code; }; @@ -3044,7 +3824,7 @@ testsuite/ /* Target cpu costs. */ -@@ -749,6 +765,25 @@ struct processor_costs power6_cost = { +@@ -749,6 +771,25 @@ struct processor_costs power6_cost = { 16, /* prefetch streams */ }; @@ -3070,7 +3850,26 @@ testsuite/ static bool rs6000_function_ok_for_sibcall (tree, tree); static const char *rs6000_invalid_within_doloop (const_rtx); -@@ -963,12 +998,10 @@ static tree rs6000_gimplify_va_arg (tree +@@ -827,7 +868,10 @@ static void rs6000_xcoff_file_end (void) + #endif + static int rs6000_variable_issue (FILE *, int, rtx, int); + static bool rs6000_rtx_costs (rtx, int, int, int *, bool); ++static bool rs6000_debug_rtx_costs (rtx, int, int, int *, bool); ++static int rs6000_debug_address_cost (rtx, bool); + static int rs6000_adjust_cost (rtx, rtx, rtx, int); ++static int rs6000_debug_adjust_cost (rtx, rtx, rtx, int); + static void rs6000_sched_init (FILE *, int, int); + static bool is_microcoded_insn (rtx); + static bool is_nonpipeline_insn (rtx); +@@ -906,6 +950,7 @@ static rtx altivec_expand_stv_builtin (e + static rtx altivec_expand_vec_init_builtin (tree, tree, rtx); + static rtx altivec_expand_vec_set_builtin (tree); + static rtx altivec_expand_vec_ext_builtin (tree, rtx); ++static rtx vsx_expand_builtin (tree, rtx, bool *); + static int get_element_number (tree, tree); + static bool rs6000_handle_option (size_t, const char *, int); + static void rs6000_parse_tls_size_option (void); +@@ -963,14 +1008,16 @@ static tree rs6000_gimplify_va_arg (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); @@ -3084,8 +3883,14 @@ testsuite/ -static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx); static tree rs6000_stack_protect_fail (void); ++static enum reg_class rs6000_secondary_reload (bool, rtx, enum reg_class, ++ enum machine_mode, ++ struct secondary_reload_info *); ++ const int INSN_NOT_AVAILABLE = -1; -@@ -1045,6 +1078,9 @@ static const char alt_reg_names[][8] = + static enum machine_mode rs6000_eh_return_filter_mode (void); + +@@ -1045,6 +1092,9 @@ static const char alt_reg_names[][8] = #endif #ifndef TARGET_PROFILE_KERNEL #define TARGET_PROFILE_KERNEL 0 @@ -3095,8 +3900,13 @@ testsuite/ #endif /* The VRSAVE bitmask puts bit %v0 as the most significant bit. */ -@@ -1299,28 +1335,96 @@ static const char alt_reg_names[][8] = +@@ -1297,30 +1347,101 @@ static const char alt_reg_names[][8] = + #undef TARGET_INSTANTIATE_DECLS + #define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls ++#undef TARGET_SECONDARY_RELOAD ++#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload ++ struct gcc_target targetm = TARGET_INITIALIZER; +/* Return number of consecutive hard regs needed starting at reg REGNO @@ -3202,7 +4012,7 @@ testsuite/ /* The CR register can only hold CC modes. */ if (CR_REGNO_P (regno)) -@@ -1331,28 +1435,312 @@ rs6000_hard_regno_mode_ok (int regno, en +@@ -1331,28 +1452,389 @@ rs6000_hard_regno_mode_ok (int regno, en /* AltiVec only in AldyVec registers. */ if (ALTIVEC_REGNO_P (regno)) @@ -3215,10 +4025,16 @@ testsuite/ - /* We cannot put TImode anywhere except general register and it must be - able to fit within the register set. */ -+ /* Don't allow anything but word sized integers (aka pointers) in CTR/LR. You -+ really don't want to spill your floating point values to those -+ registers. Also do it for the old MQ register in the power. */ -+ if (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO) ++ /* Don't allow anything but word sized integers (aka pointers) in CTR/LR. ++ You really don't want to spill your floating point values to those ++ registers. Also do it for the old MQ register in the power. ++ ++ While this is desirable in theory, disabling float to go in LR/CTR does ++ cause some regressions, so until they are taken care of, revert to the old ++ behavior by default for most power systems, but enable it for power7. */ ++ if ((TARGET_DISALLOW_FLOAT_IN_LR_CTR > 0 ++ || (TARGET_DISALLOW_FLOAT_IN_LR_CTR < 0 && TARGET_VSX)) ++ && (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO)) + return (GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_SIZE (mode) <= UNITS_PER_WORD); + @@ -3327,12 +4143,43 @@ testsuite/ + enum reg_class vsx_rc = (TARGET_ALTIVEC ? VSX_REGS : FLOAT_REGS); + bool float_p = (TARGET_HARD_FLOAT && TARGET_FPRS); + ++ /* Precalculate REGNO_REG_CLASS. */ ++ rs6000_regno_regclass[0] = GENERAL_REGS; ++ for (r = 1; r < 32; ++r) ++ rs6000_regno_regclass[r] = BASE_REGS; ++ ++ for (r = 32; r < 64; ++r) ++ rs6000_regno_regclass[r] = FLOAT_REGS; ++ ++ for (r = 64; r < FIRST_PSEUDO_REGISTER; ++r) ++ rs6000_regno_regclass[r] = NO_REGS; ++ ++ for (r = FIRST_ALTIVEC_REGNO; r <= LAST_ALTIVEC_REGNO; ++r) ++ rs6000_regno_regclass[r] = ALTIVEC_REGS; ++ ++ rs6000_regno_regclass[CR0_REGNO] = CR0_REGS; ++ for (r = CR1_REGNO; r <= CR7_REGNO; ++r) ++ rs6000_regno_regclass[r] = CR_REGS; ++ ++ rs6000_regno_regclass[MQ_REGNO] = MQ_REGS; ++ rs6000_regno_regclass[LR_REGNO] = LINK_REGS; ++ rs6000_regno_regclass[CTR_REGNO] = CTR_REGS; ++ rs6000_regno_regclass[XER_REGNO] = XER_REGS; ++ rs6000_regno_regclass[VRSAVE_REGNO] = VRSAVE_REGS; ++ rs6000_regno_regclass[VSCR_REGNO] = VRSAVE_REGS; ++ rs6000_regno_regclass[SPE_ACC_REGNO] = SPE_ACC_REGS; ++ rs6000_regno_regclass[SPEFSCR_REGNO] = SPEFSCR_REGS; ++ rs6000_regno_regclass[ARG_POINTER_REGNUM] = BASE_REGS; ++ rs6000_regno_regclass[FRAME_POINTER_REGNUM] = BASE_REGS; ++ + /* Precalculate vector information, this must be set up before the + rs6000_hard_regno_nregs_internal below. */ + for (m = 0; m < NUM_MACHINE_MODES; ++m) + { + rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE; + rs6000_vector_reg_class[m] = NO_REGS; ++ rs6000_vector_reload[m][0] = CODE_FOR_nothing; ++ rs6000_vector_reload[m][1] = CODE_FOR_nothing; + } + + /* TODO, add TI/V2DI mode for moving data if Altivec or VSX. */ @@ -3409,8 +4256,13 @@ testsuite/ + /* TODO, add SPE and paired floating point vector support. */ + + /* Set the VSX register classes. */ ++ ++ /* For V4SF, prefer the Altivec registers, because there are a few operations ++ that want to use Altivec operations instead of VSX. */ + rs6000_vector_reg_class[V4SFmode] -+ = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode)) ++ = ((VECTOR_UNIT_VSX_P (V4SFmode) ++ && VECTOR_MEM_VSX_P (V4SFmode) ++ && !TARGET_V4SF_ALTIVEC_REGS) + ? vsx_rc + : (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode) + ? ALTIVEC_REGS @@ -3428,6 +4280,41 @@ testsuite/ + + rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS; + ++ /* Set up the reload helper functions. */ ++ if (TARGET_RELOAD_FUNCTIONS && (TARGET_VSX || TARGET_ALTIVEC)) ++ { ++ if (TARGET_64BIT) ++ { ++ rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_di_store; ++ rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_di_load; ++ rs6000_vector_reload[V8HImode][0] = CODE_FOR_reload_v8hi_di_store; ++ rs6000_vector_reload[V8HImode][1] = CODE_FOR_reload_v8hi_di_load; ++ rs6000_vector_reload[V4SImode][0] = CODE_FOR_reload_v4si_di_store; ++ rs6000_vector_reload[V4SImode][1] = CODE_FOR_reload_v4si_di_load; ++ rs6000_vector_reload[V2DImode][0] = CODE_FOR_reload_v2di_di_store; ++ rs6000_vector_reload[V2DImode][1] = CODE_FOR_reload_v2di_di_load; ++ rs6000_vector_reload[V4SFmode][0] = CODE_FOR_reload_v4sf_di_store; ++ rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_di_load; ++ rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_di_store; ++ rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_di_load; ++ } ++ else ++ { ++ rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_si_store; ++ rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_si_load; ++ rs6000_vector_reload[V8HImode][0] = CODE_FOR_reload_v8hi_si_store; ++ rs6000_vector_reload[V8HImode][1] = CODE_FOR_reload_v8hi_si_load; ++ rs6000_vector_reload[V4SImode][0] = CODE_FOR_reload_v4si_si_store; ++ rs6000_vector_reload[V4SImode][1] = CODE_FOR_reload_v4si_si_load; ++ rs6000_vector_reload[V2DImode][0] = CODE_FOR_reload_v2di_si_store; ++ rs6000_vector_reload[V2DImode][1] = CODE_FOR_reload_v2di_si_load; ++ rs6000_vector_reload[V4SFmode][0] = CODE_FOR_reload_v4sf_si_store; ++ rs6000_vector_reload[V4SFmode][1] = CODE_FOR_reload_v4sf_si_load; ++ rs6000_vector_reload[V2DFmode][0] = CODE_FOR_reload_v2df_si_store; ++ rs6000_vector_reload[V2DFmode][1] = CODE_FOR_reload_v2df_si_load; ++ } ++ } ++ + /* Precalculate HARD_REGNO_NREGS. */ + for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r) + for (m = 0; m < NUM_MACHINE_MODES; ++m) @@ -3520,7 +4407,7 @@ testsuite/ } #if TARGET_MACHO -@@ -1482,12 +1870,15 @@ rs6000_override_options (const char *def +@@ -1482,12 +1964,15 @@ rs6000_override_options (const char *def {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, @@ -3539,7 +4426,7 @@ testsuite/ {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT}, {"970", PROCESSOR_POWER4, POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64}, -@@ -1520,9 +1911,10 @@ rs6000_override_options (const char *def +@@ -1520,9 +2005,10 @@ rs6000_override_options (const char *def POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_MFPGPR}, @@ -3552,7 +4439,7 @@ testsuite/ {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK}, {"powerpc64", PROCESSOR_POWERPC64, POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}, -@@ -1549,7 +1941,8 @@ rs6000_override_options (const char *def +@@ -1549,7 +2035,8 @@ rs6000_override_options (const char *def POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW @@ -3562,7 +4449,7 @@ testsuite/ }; set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT; -@@ -1594,10 +1987,6 @@ rs6000_override_options (const char *def +@@ -1594,10 +2081,6 @@ rs6000_override_options (const char *def } } @@ -3573,7 +4460,7 @@ testsuite/ if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3 || rs6000_cpu == PROCESSOR_PPCE500MC) { -@@ -1642,15 +2031,47 @@ rs6000_override_options (const char *def +@@ -1642,17 +2125,61 @@ rs6000_override_options (const char *def } } @@ -3610,7 +4497,7 @@ testsuite/ if (! strcmp (rs6000_debug_name, "all")) - rs6000_debug_stack = rs6000_debug_arg = 1; + rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg -+ = rs6000_debug_addr = 1; ++ = rs6000_debug_addr = rs6000_debug_cost = 1; else if (! strcmp (rs6000_debug_name, "stack")) rs6000_debug_stack = 1; else if (! strcmp (rs6000_debug_name, "arg")) @@ -3619,10 +4506,24 @@ testsuite/ + rs6000_debug_reg = 1; + else if (! strcmp (rs6000_debug_name, "addr")) + rs6000_debug_addr = 1; ++ else if (! strcmp (rs6000_debug_name, "cost")) ++ rs6000_debug_cost = 1; else error ("unknown -mdebug-%s switch", rs6000_debug_name); ++ ++ /* If -mdebug=cost or -mdebug=all, replace the cost target hooks with ++ debug versions that call the real version and then prints debugging ++ information. */ ++ if (TARGET_DEBUG_COST) ++ { ++ targetm.rtx_costs = rs6000_debug_rtx_costs; ++ targetm.address_cost = rs6000_debug_address_cost; ++ targetm.sched.adjust_cost = rs6000_debug_adjust_cost; ++ } } -@@ -1741,8 +2162,8 @@ rs6000_override_options (const char *def + + if (rs6000_traceback_name) +@@ -1741,8 +2268,8 @@ rs6000_override_options (const char *def rs6000_spe = 0; if (!rs6000_explicit_options.float_gprs) rs6000_float_gprs = 0; @@ -3633,7 +4534,7 @@ testsuite/ } /* Detect invalid option combinations with E500. */ -@@ -1751,12 +2172,14 @@ rs6000_override_options (const char *def +@@ -1751,12 +2278,14 @@ rs6000_override_options (const char *def rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4 && rs6000_cpu != PROCESSOR_POWER5 && rs6000_cpu != PROCESSOR_POWER6 @@ -3649,7 +4550,7 @@ testsuite/ rs6000_sched_restricted_insns_priority = (rs6000_sched_groups ? 1 : 0); -@@ -1951,6 +2374,10 @@ rs6000_override_options (const char *def +@@ -1951,6 +2480,10 @@ rs6000_override_options (const char *def rs6000_cost = &power6_cost; break; @@ -3660,7 +4561,7 @@ testsuite/ default: gcc_unreachable (); } -@@ -2001,7 +2428,7 @@ rs6000_override_options (const char *def +@@ -2001,7 +2534,7 @@ rs6000_override_options (const char *def static tree rs6000_builtin_mask_for_load (void) { @@ -3669,7 +4570,7 @@ testsuite/ return altivec_builtin_mask_for_load; else return 0; -@@ -2015,18 +2442,19 @@ rs6000_builtin_mask_for_load (void) +@@ -2015,18 +2548,27 @@ rs6000_builtin_mask_for_load (void) static tree rs6000_builtin_conversion (enum tree_code code, tree type) { @@ -3681,6 +4582,14 @@ testsuite/ case FIX_TRUNC_EXPR: switch (TYPE_MODE (type)) { ++ case V2DImode: ++ if (!VECTOR_UNIT_VSX_P (V2DFmode)) ++ return NULL_TREE; ++ ++ return TYPE_UNSIGNED (type) ++ ? rs6000_builtin_decls[VSX_BUILTIN_XVCVDPUXDS] ++ : rs6000_builtin_decls[VSX_BUILTIN_XVCVDPSXDS]; ++ case V4SImode: + if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode)) + return NULL_TREE; @@ -3694,9 +4603,18 @@ testsuite/ default: return NULL_TREE; } -@@ -2035,9 +2463,12 @@ rs6000_builtin_conversion (enum tree_cod +@@ -2034,10 +2576,22 @@ rs6000_builtin_conversion (enum tree_cod + case FLOAT_EXPR: switch (TYPE_MODE (type)) { ++ case V2DImode: ++ if (!VECTOR_UNIT_VSX_P (V2DFmode)) ++ return NULL_TREE; ++ ++ return TYPE_UNSIGNED (type) ++ ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDSP] ++ : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDSP]; ++ case V4SImode: + if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode)) + return NULL_TREE; @@ -3706,10 +4624,11 @@ testsuite/ - : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFSX]; + ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF] + : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF]; ++ default: return NULL_TREE; } -@@ -2150,6 +2581,14 @@ rs6000_builtin_vec_perm (tree type, tree +@@ -2150,6 +2704,14 @@ rs6000_builtin_vec_perm (tree type, tree d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SF]; break; @@ -3724,7 +4643,7 @@ testsuite/ default: return NULL_TREE; } -@@ -2229,6 +2668,7 @@ static bool +@@ -2229,6 +2791,7 @@ static bool rs6000_handle_option (size_t code, const char *arg, int value) { enum fpu_type_t fpu_type = FPU_NONE; @@ -3732,7 +4651,7 @@ testsuite/ switch (code) { -@@ -2331,14 +2771,14 @@ rs6000_handle_option (size_t code, const +@@ -2331,14 +2894,14 @@ rs6000_handle_option (size_t code, const rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE)); break; @@ -3754,7 +4673,7 @@ testsuite/ break; case OPT_mspe: -@@ -2967,6 +3407,9 @@ output_vec_const_move (rtx *operands) +@@ -2967,6 +3530,9 @@ output_vec_const_move (rtx *operands) vec = operands[1]; mode = GET_MODE (dest); @@ -3764,7 +4683,7 @@ testsuite/ if (TARGET_ALTIVEC) { rtx splat_vec; -@@ -3190,20 +3633,21 @@ rs6000_expand_vector_init (rtx target, r +@@ -3190,20 +3756,21 @@ rs6000_expand_vector_init (rtx target, r if (n_var == 0) { rtx const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)); @@ -3789,7 +4708,7 @@ testsuite/ ; /* Splat vector element. */ else { -@@ -3213,6 +3657,18 @@ rs6000_expand_vector_init (rtx target, r +@@ -3213,6 +3780,18 @@ rs6000_expand_vector_init (rtx target, r } } @@ -3808,7 +4727,7 @@ testsuite/ /* Store value to stack temp. Load vector element. Splat. */ if (all_same) { -@@ -3272,6 +3728,13 @@ rs6000_expand_vector_set (rtx target, rt +@@ -3272,6 +3851,13 @@ rs6000_expand_vector_set (rtx target, rt int width = GET_MODE_SIZE (inner_mode); int i; @@ -3822,7 +4741,7 @@ testsuite/ /* Load single variable value. */ mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0); emit_move_insn (adjust_address_nv (mem, inner_mode, 0), val); -@@ -3309,6 +3772,13 @@ rs6000_expand_vector_extract (rtx target +@@ -3309,6 +3895,13 @@ rs6000_expand_vector_extract (rtx target enum machine_mode inner_mode = GET_MODE_INNER (mode); rtx mem, x; @@ -3836,7 +4755,7 @@ testsuite/ /* Allocate mode-sized buffer. */ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0); -@@ -3627,9 +4097,13 @@ rs6000_legitimate_offset_address_p (enum +@@ -3627,9 +4220,13 @@ rs6000_legitimate_offset_address_p (enum case V8HImode: case V4SFmode: case V4SImode: @@ -3846,13 +4765,13 @@ testsuite/ + /* AltiVec/VSX vector modes. Only reg+reg addressing is valid and constant offset zero should not occur due to canonicalization. */ - return false; -+ if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)) ++ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)) + return false; + break; case V4HImode: case V2SImode: -@@ -3646,6 +4120,11 @@ rs6000_legitimate_offset_address_p (enum +@@ -3646,6 +4243,11 @@ rs6000_legitimate_offset_address_p (enum if (TARGET_E500_DOUBLE) return SPE_CONST_OFFSET_OK (offset); @@ -3864,7 +4783,7 @@ testsuite/ case DDmode: case DImode: /* On e500v2, we may have: -@@ -3716,7 +4195,9 @@ avoiding_indexed_address_p (enum machine +@@ -3716,7 +4318,9 @@ avoiding_indexed_address_p (enum machine { /* Avoid indexed addressing for modes that have non-indexed load/store instruction forms. */ @@ -3875,25 +4794,33 @@ testsuite/ } inline bool -@@ -3808,25 +4289,30 @@ rtx +@@ -3808,15 +4412,10 @@ rtx rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode) { + rtx ret = NULL_RTX; + rtx orig_x = x; -+ - if (GET_CODE (x) == SYMBOL_REF) - { - enum tls_model model = SYMBOL_REF_TLS_MODEL (x); - if (model != 0) + unsigned int extra = 0; + +- if (GET_CODE (x) == SYMBOL_REF) +- { +- enum tls_model model = SYMBOL_REF_TLS_MODEL (x); +- if (model != 0) - return rs6000_legitimize_tls_address (x, model); -+ ret = rs6000_legitimize_tls_address (x, model); +- } +- + switch (mode) + { + case DFmode: +@@ -3838,19 +4437,26 @@ rs6000_legitimize_address (rtx x, rtx ol + break; } - if (GET_CODE (x) == PLUS - && GET_CODE (XEXP (x, 0)) == REG - && GET_CODE (XEXP (x, 1)) == CONST_INT -- && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000 +- && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) +- >= 0x10000 - extra) - && !((TARGET_POWERPC64 - && (mode == DImode || mode == TImode) - && (INTVAL (XEXP (x, 1)) & 3) != 0) @@ -3902,11 +4829,17 @@ testsuite/ - || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode - || mode == DImode || mode == DDmode - || mode == TDmode)))) ++ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x)) ++ { ++ enum tls_model model = SYMBOL_REF_TLS_MODEL (x); ++ ret = rs6000_legitimize_tls_address (x, model); ++ } ++ + else if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 0)) == REG + && GET_CODE (XEXP (x, 1)) == CONST_INT + && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) -+ >= 0x10000) ++ >= 0x10000 - extra) + && !((TARGET_POWERPC64 + && (mode == DImode || mode == TImode) + && (INTVAL (XEXP (x, 1)) & 3) != 0) @@ -3919,16 +4852,16 @@ testsuite/ { HOST_WIDE_INT high_int, low_int; rtx sum; -@@ -3834,7 +4320,7 @@ rs6000_legitimize_address (rtx x, rtx ol +@@ -3860,7 +4466,7 @@ rs6000_legitimize_address (rtx x, rtx ol high_int = INTVAL (XEXP (x, 1)) - low_int; sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0), GEN_INT (high_int)), 0); -- return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int)); -+ ret = gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int)); +- return plus_constant (sum, low_int); ++ ret = plus_constant (sum, low_int); } else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == REG -@@ -3850,32 +4336,29 @@ rs6000_legitimize_address (rtx x, rtx ol +@@ -3876,32 +4482,29 @@ rs6000_legitimize_address (rtx x, rtx ol && mode != TFmode && mode != TDmode) { @@ -3973,7 +4906,7 @@ testsuite/ rtx op1 = XEXP (x, 0); rtx op2 = XEXP (x, 1); rtx y; -@@ -3894,12 +4377,12 @@ rs6000_legitimize_address (rtx x, rtx ol +@@ -3920,12 +4523,12 @@ rs6000_legitimize_address (rtx x, rtx ol y = gen_rtx_PLUS (Pmode, op1, op2); if ((GET_MODE_SIZE (mode) > 8 || mode == DDmode) && REG_P (op2)) @@ -3990,7 +4923,7 @@ testsuite/ } else if (TARGET_ELF && TARGET_32BIT -@@ -3915,7 +4398,7 @@ rs6000_legitimize_address (rtx x, rtx ol +@@ -3941,7 +4544,7 @@ rs6000_legitimize_address (rtx x, rtx ol { rtx reg = gen_reg_rtx (Pmode); emit_insn (gen_elf_high (reg, x)); @@ -3999,7 +4932,7 @@ testsuite/ } else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC && ! flag_pic -@@ -3933,17 +4416,34 @@ rs6000_legitimize_address (rtx x, rtx ol +@@ -3959,17 +4562,35 @@ rs6000_legitimize_address (rtx x, rtx ol { rtx reg = gen_reg_rtx (Pmode); emit_insn (gen_macho_high (reg, x)); @@ -4031,13 +4964,14 @@ testsuite/ + } + else + fprintf (stderr, "NULL returned\n"); ++ fprintf (stderr, "\n"); + } + + return ret; } /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL. -@@ -4232,6 +4732,9 @@ rs6000_legitimize_reload_address (rtx x, +@@ -4258,6 +4879,9 @@ rs6000_legitimize_reload_address (rtx x, int opnum, int type, int ind_levels ATTRIBUTE_UNUSED, int *win) { @@ -4047,7 +4981,7 @@ testsuite/ /* We must recognize output that we have already generated ourselves. */ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS -@@ -4243,17 +4746,17 @@ rs6000_legitimize_reload_address (rtx x, +@@ -4269,17 +4893,17 @@ rs6000_legitimize_reload_address (rtx x, BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, opnum, (enum reload_type)type); *win = 1; @@ -4073,7 +5007,7 @@ testsuite/ { /* Result of previous invocation of this function on Darwin floating point constant. */ -@@ -4261,40 +4764,42 @@ rs6000_legitimize_reload_address (rtx x, +@@ -4287,40 +4911,40 @@ rs6000_legitimize_reload_address (rtx x, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, (enum reload_type)type); *win = 1; @@ -4099,8 +5033,7 @@ testsuite/ + && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode) + && GET_CODE (XEXP (x, 1)) == CONST_INT + && (INTVAL (XEXP (x, 1)) & 3) != 0 -+ && !ALTIVEC_VECTOR_MODE (mode) -+ && !VSX_VECTOR_MODE (mode) ++ && VECTOR_MEM_NONE_P (mode) + && GET_MODE_SIZE (mode) >= UNITS_PER_WORD + && TARGET_POWERPC64) { @@ -4132,12 +5065,11 @@ testsuite/ + && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode + || mode == DDmode || mode == TDmode + || mode == DImode)) -+ && !ALTIVEC_VECTOR_MODE (mode) -+ && !VSX_VECTOR_MODE (mode)) ++ && VECTOR_MEM_NONE_P (mode)) { HOST_WIDE_INT val = INTVAL (XEXP (x, 1)); HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000; -@@ -4305,42 +4810,44 @@ rs6000_legitimize_reload_address (rtx x, +@@ -4331,42 +4955,45 @@ rs6000_legitimize_reload_address (rtx x, if (high + low != val) { *win = 0; @@ -4202,6 +5134,7 @@ testsuite/ + /* Don't do this for TFmode or TDmode, since the result isn't + offsettable. The same goes for DImode without 64-bit gprs and + DFmode and DDmode without fprs. */ ++ && VECTOR_MEM_NONE_P (mode) + && mode != TFmode + && mode != TDmode + && (mode != DImode || TARGET_POWERPC64) @@ -4210,7 +5143,7 @@ testsuite/ { #if TARGET_MACHO if (flag_pic) -@@ -4359,37 +4866,61 @@ rs6000_legitimize_reload_address (rtx x, +@@ -4385,37 +5012,63 @@ rs6000_legitimize_reload_address (rtx x, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, (enum reload_type)type); *win = 1; @@ -4229,7 +5162,7 @@ testsuite/ - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT - && GET_CODE (XEXP (x, 1)) == CONST_INT - && INTVAL (XEXP (x, 1)) == -16) -+ else if (VECTOR_MEM_ALTIVEC_P (mode) ++ else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) + && GET_CODE (x) == AND + && GET_CODE (XEXP (x, 0)) == PLUS + && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG @@ -4262,9 +5195,7 @@ testsuite/ + { + *win = 0; + ret = x; - } -- *win = 0; -- return x; ++ } + + if (TARGET_DEBUG_ADDR) + { @@ -4283,13 +5214,17 @@ testsuite/ + fprintf (stderr, "New address:\n"); + debug_rtx (ret); + } -+ } ++ ++ fprintf (stderr, "\n"); + } +- *win = 0; +- return x; + + return ret; } /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression -@@ -4412,77 +4943,101 @@ rs6000_legitimize_reload_address (rtx x, +@@ -4438,77 +5091,101 @@ rs6000_legitimize_reload_address (rtx x, int rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict) { @@ -4297,9 +5232,10 @@ testsuite/ + rtx orig_x = x; + /* If this is an unaligned stvx/ldvx type address, discard the outer AND. */ - if (TARGET_ALTIVEC +- if (TARGET_ALTIVEC - && ALTIVEC_VECTOR_MODE (mode) -+ && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode)) ++ if ((TARGET_ALTIVEC || TARGET_VSX) ++ && VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) && GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == -16) @@ -4328,8 +5264,7 @@ testsuite/ + else if (legitimate_indirect_address_p (x, reg_ok_strict)) + ret = 1; + else if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC) -+ && !VECTOR_MEM_ALTIVEC_P (mode) -+ /* && !VECTOR_MEM_VSX_P (mode) */ ++ && !VECTOR_MEM_ALTIVEC_OR_VSX_P (mode) + && (TARGET_SPE && !SPE_VECTOR_MODE (mode)) + && mode != TFmode + && mode != TDmode @@ -4447,13 +5382,14 @@ testsuite/ + GET_MODE_NAME (mode), + reg_ok_strict); + debug_rtx (orig_x); ++ fprintf (stderr, "\n"); + } + + return ret; } /* Go to LABEL if ADDR (a legitimate address expression) -@@ -4499,28 +5054,40 @@ rs6000_legitimate_address (enum machine_ +@@ -4525,28 +5202,46 @@ rs6000_legitimate_address (enum machine_ bool rs6000_mode_dependent_address (rtx addr) { @@ -4479,6 +5415,11 @@ testsuite/ case PRE_MODIFY: - return TARGET_UPDATE; + ret = (TARGET_UPDATE != 0); ++ break; ++ ++ /* AND is only allowed in Altivec loads. */ ++ case AND: ++ ret = true; + break; default: @@ -4489,16 +5430,17 @@ testsuite/ + if (TARGET_DEBUG_ADDR) + { + fprintf (stderr, -+ "\nrs6000_mode_dependent_address: ret = %d\n", -+ (int)ret); ++ "\nrs6000_mode_dependent_address: ret = %s\n", ++ ret ? "true" : "false"); + debug_rtx (addr); ++ fprintf (stderr, "\n"); + } + + return ret; } /* Implement FIND_BASE_TERM. */ -@@ -4571,43 +5138,6 @@ rs6000_offsettable_memref_p (rtx op) +@@ -4597,43 +5292,6 @@ rs6000_offsettable_memref_p (rtx op) return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1); } @@ -4542,7 +5484,7 @@ testsuite/ /* Change register usage conditional on target flags. */ void rs6000_conditional_register_usage (void) -@@ -4672,14 +5202,14 @@ rs6000_conditional_register_usage (void) +@@ -4698,14 +5356,14 @@ rs6000_conditional_register_usage (void) = call_really_used_regs[14] = 1; } @@ -4559,7 +5501,28 @@ testsuite/ global_regs[VSCR_REGNO] = 1; if (TARGET_ALTIVEC_ABI) -@@ -5101,6 +5631,8 @@ rs6000_emit_move (rtx dest, rtx source, +@@ -4923,6 +5581,20 @@ rs6000_emit_move (rtx dest, rtx source, + operands[0] = dest; + operands[1] = source; + ++ if (TARGET_DEBUG_ADDR) ++ { ++ fprintf (stderr, ++ "\nrs6000_emit_move: mode = %s, reload_in_progress = %d, " ++ "reload_completed = %d, can_create_pseudos = %d.\ndest:\n", ++ GET_MODE_NAME (mode), ++ reload_in_progress, ++ reload_completed, ++ can_create_pseudo_p ()); ++ debug_rtx (dest); ++ fprintf (stderr, "source:\n"); ++ debug_rtx (source); ++ } ++ + /* Sanity checks. Check that we get CONST_DOUBLE only when we should. */ + if (GET_CODE (operands[1]) == CONST_DOUBLE + && ! FLOAT_MODE_P (mode) +@@ -5127,6 +5799,8 @@ rs6000_emit_move (rtx dest, rtx source, case V2SFmode: case V2SImode: case V1DImode: @@ -4568,7 +5531,7 @@ testsuite/ if (CONSTANT_P (operands[1]) && !easy_vector_constant (operands[1], mode)) operands[1] = force_const_mem (mode, operands[1]); -@@ -5270,6 +5802,9 @@ rs6000_emit_move (rtx dest, rtx source, +@@ -5296,6 +5970,9 @@ rs6000_emit_move (rtx dest, rtx source, break; case TImode: @@ -4578,7 +5541,7 @@ testsuite/ rs6000_eliminate_indexed_memrefs (operands); if (TARGET_POWER) -@@ -5285,7 +5820,7 @@ rs6000_emit_move (rtx dest, rtx source, +@@ -5311,7 +5988,7 @@ rs6000_emit_move (rtx dest, rtx source, break; default: @@ -4587,7 +5550,7 @@ testsuite/ } /* Above, we may have called force_const_mem which may have returned -@@ -5305,10 +5840,10 @@ rs6000_emit_move (rtx dest, rtx source, +@@ -5331,10 +6008,10 @@ rs6000_emit_move (rtx dest, rtx source, && TARGET_HARD_FLOAT && TARGET_FPRS) /* Nonzero if we can use an AltiVec register to pass this arg. */ @@ -4602,7 +5565,7 @@ testsuite/ && (NAMED)) /* Return a nonzero value to say to return the function value in -@@ -5549,7 +6084,7 @@ function_arg_boundary (enum machine_mode +@@ -5575,7 +6252,7 @@ function_arg_boundary (enum machine_mode && int_size_in_bytes (type) >= 8 && int_size_in_bytes (type) < 16)) return 64; @@ -4611,7 +5574,7 @@ testsuite/ || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) >= 16)) return 128; -@@ -5694,7 +6229,7 @@ function_arg_advance (CUMULATIVE_ARGS *c +@@ -5720,7 +6397,7 @@ function_arg_advance (CUMULATIVE_ARGS *c cum->nargs_prototype--; if (TARGET_ALTIVEC_ABI @@ -4620,7 +5583,7 @@ testsuite/ || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) == 16))) { -@@ -6288,7 +6823,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum +@@ -6314,7 +6991,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum else return gen_rtx_REG (mode, cum->vregno); else if (TARGET_ALTIVEC_ABI @@ -4629,7 +5592,7 @@ testsuite/ || (type && TREE_CODE (type) == VECTOR_TYPE && int_size_in_bytes (type) == 16))) { -@@ -7212,10 +7747,13 @@ static const struct builtin_description +@@ -7238,10 +7915,13 @@ static const struct builtin_description { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI }, { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI }, { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI }, @@ -4647,7 +5610,24 @@ testsuite/ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI }, { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI }, { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI }, -@@ -7289,18 +7827,18 @@ static struct builtin_description bdesc_ +@@ -7263,6 +7943,16 @@ static const struct builtin_description + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL }, + ++ { MASK_VSX, CODE_FOR_vsx_fmaddv2df4, "__builtin_vsx_xvmadddp", VSX_BUILTIN_XVMADDDP }, ++ { MASK_VSX, CODE_FOR_vsx_fmsubv2df4, "__builtin_vsx_xvmsubdp", VSX_BUILTIN_XVMSUBDP }, ++ { MASK_VSX, CODE_FOR_vsx_fnmaddv2df4, "__builtin_vsx_xvnmadddp", VSX_BUILTIN_XVNMADDDP }, ++ { MASK_VSX, CODE_FOR_vsx_fnmsubv2df4, "__builtin_vsx_xvnmsubdp", VSX_BUILTIN_XVNMSUBDP }, ++ ++ { MASK_VSX, CODE_FOR_vsx_fmaddv4sf4, "__builtin_vsx_xvmaddsp", VSX_BUILTIN_XVMADDSP }, ++ { MASK_VSX, CODE_FOR_vsx_fmsubv4sf4, "__builtin_vsx_xvmsubsp", VSX_BUILTIN_XVMSUBSP }, ++ { MASK_VSX, CODE_FOR_vsx_fnmaddv4sf4, "__builtin_vsx_xvnmaddsp", VSX_BUILTIN_XVNMADDSP }, ++ { MASK_VSX, CODE_FOR_vsx_fnmsubv4sf4, "__builtin_vsx_xvnmsubsp", VSX_BUILTIN_XVNMSUBSP }, ++ + { 0, CODE_FOR_paired_msub, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB }, + { 0, CODE_FOR_paired_madd, "__builtin_paired_madd", PAIRED_BUILTIN_MADD }, + { 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 }, +@@ -7315,18 +8005,18 @@ static struct builtin_description bdesc_ { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX }, { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX }, { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP }, @@ -4678,7 +5658,7 @@ testsuite/ { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS }, { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS }, { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB }, -@@ -7331,7 +7869,7 @@ static struct builtin_description bdesc_ +@@ -7357,7 +8047,7 @@ static struct builtin_description bdesc_ { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB }, { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH }, { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH }, @@ -4687,7 +5667,133 @@ testsuite/ { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR }, { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM }, { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM }, -@@ -7796,6 +8334,11 @@ static struct builtin_description bdesc_ +@@ -7405,8 +8095,24 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS }, + { MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR }, + +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP }, ++ { MASK_VSX, CODE_FOR_addv2df3, "__builtin_vsx_xvadddp", VSX_BUILTIN_XVADDDP }, ++ { MASK_VSX, CODE_FOR_subv2df3, "__builtin_vsx_xvsubdp", VSX_BUILTIN_XVSUBDP }, ++ { MASK_VSX, CODE_FOR_mulv2df3, "__builtin_vsx_xvmuldp", VSX_BUILTIN_XVMULDP }, ++ { MASK_VSX, CODE_FOR_divv2df3, "__builtin_vsx_xvdivdp", VSX_BUILTIN_XVDIVDP }, ++ { MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP }, ++ { MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP }, ++ { MASK_VSX, CODE_FOR_vsx_tdivv2df3, "__builtin_vsx_xvtdivdp", VSX_BUILTIN_XVTDIVDP }, ++ ++ { MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP }, ++ { MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP }, ++ { MASK_VSX, CODE_FOR_mulv4sf3, "__builtin_vsx_xvmulsp", VSX_BUILTIN_XVMULSP }, ++ { MASK_VSX, CODE_FOR_divv4sf3, "__builtin_vsx_xvdivsp", VSX_BUILTIN_XVDIVSP }, ++ { MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP }, ++ { MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP }, ++ { MASK_VSX, CODE_FOR_vsx_tdivv4sf3, "__builtin_vsx_xvtdivsp", VSX_BUILTIN_XVTDIVSP }, ++ ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhm", ALTIVEC_BUILTIN_VEC_VADDUHM }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubm", ALTIVEC_BUILTIN_VEC_VADDUBM }, +@@ -7418,8 +8124,8 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhs", ALTIVEC_BUILTIN_VEC_VADDUHS }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsbs", ALTIVEC_BUILTIN_VEC_VADDSBS }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubs", ALTIVEC_BUILTIN_VEC_VADDUBS }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_avg", ALTIVEC_BUILTIN_VEC_AVG }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsw", ALTIVEC_BUILTIN_VEC_VAVGSW }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguw", ALTIVEC_BUILTIN_VEC_VAVGUW }, +@@ -7444,8 +8150,8 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtub", ALTIVEC_BUILTIN_VEC_VCMPGTUB }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmple", ALTIVEC_BUILTIN_VEC_CMPLE }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmplt", ALTIVEC_BUILTIN_VEC_CMPLT }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsw", ALTIVEC_BUILTIN_VEC_VMAXSW }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuw", ALTIVEC_BUILTIN_VEC_VMAXUW }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsh", ALTIVEC_BUILTIN_VEC_VMAXSH }, +@@ -7460,8 +8166,8 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglw", ALTIVEC_BUILTIN_VEC_VMRGLW }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglh", ALTIVEC_BUILTIN_VEC_VMRGLH }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglb", ALTIVEC_BUILTIN_VEC_VMRGLB }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsw", ALTIVEC_BUILTIN_VEC_VMINSW }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuw", ALTIVEC_BUILTIN_VEC_VMINUW }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsh", ALTIVEC_BUILTIN_VEC_VMINSH }, +@@ -7478,8 +8184,8 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulouh", ALTIVEC_BUILTIN_VEC_VMULOUH }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosb", ALTIVEC_BUILTIN_VEC_VMULOSB }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuloub", ALTIVEC_BUILTIN_VEC_VMULOUB }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_pack", ALTIVEC_BUILTIN_VEC_PACK }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwum", ALTIVEC_BUILTIN_VEC_VPKUWUM }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhum", ALTIVEC_BUILTIN_VEC_VPKUHUM }, +@@ -7512,8 +8218,8 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrab", ALTIVEC_BUILTIN_VEC_VSRAB }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_srl", ALTIVEC_BUILTIN_VEC_SRL }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sro", ALTIVEC_BUILTIN_VEC_SRO }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuwm", ALTIVEC_BUILTIN_VEC_VSUBUWM }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhm", ALTIVEC_BUILTIN_VEC_VSUBUHM }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububm", ALTIVEC_BUILTIN_VEC_VSUBUBM }, +@@ -7531,7 +8237,10 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4ubs", ALTIVEC_BUILTIN_VEC_VSUM4UBS }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum2s", ALTIVEC_BUILTIN_VEC_SUM2S }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS }, +- { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR }, ++ { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR }, ++ ++ { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_mul", VSX_BUILTIN_VEC_MUL }, ++ { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_div", VSX_BUILTIN_VEC_DIV }, + + { 0, CODE_FOR_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 }, + { 0, CODE_FOR_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 }, +@@ -7776,7 +8485,11 @@ static const struct builtin_description + { MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI }, + { MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI }, + { MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI }, +- { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI } ++ { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI }, ++ { MASK_VSX, CODE_FOR_absv2df2, "__builtin_vsx_xvabsdp", VSX_BUILTIN_XVABSDP }, ++ { MASK_VSX, CODE_FOR_vsx_nabsv2df2, "__builtin_vsx_xvnabsdp", VSX_BUILTIN_XVNABSDP }, ++ { MASK_VSX, CODE_FOR_absv4sf2, "__builtin_vsx_xvabssp", VSX_BUILTIN_XVABSSP }, ++ { MASK_VSX, CODE_FOR_vsx_nabsv4sf2, "__builtin_vsx_xvnabssp", VSX_BUILTIN_XVNABSSP }, + }; + + /* Simple unary operations: VECb = foo (unsigned literal) or VECb = +@@ -7802,6 +8515,18 @@ static struct builtin_description bdesc_ + { MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX }, + { MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH }, + ++ { MASK_VSX, CODE_FOR_negv2df2, "__builtin_vsx_xvnegdp", VSX_BUILTIN_XVNEGDP }, ++ { MASK_VSX, CODE_FOR_sqrtv2df2, "__builtin_vsx_xvsqrtdp", VSX_BUILTIN_XVSQRTDP }, ++ { MASK_VSX, CODE_FOR_vsx_rsqrtev2df2, "__builtin_vsx_xvrsqrtedp", VSX_BUILTIN_XVRSQRTEDP }, ++ { MASK_VSX, CODE_FOR_vsx_tsqrtv2df2, "__builtin_vsx_xvtsqrtdp", VSX_BUILTIN_XVTSQRTDP }, ++ { MASK_VSX, CODE_FOR_vsx_frev2df2, "__builtin_vsx_xvredp", VSX_BUILTIN_XVREDP }, ++ ++ { MASK_VSX, CODE_FOR_negv4sf2, "__builtin_vsx_xvnegsp", VSX_BUILTIN_XVNEGSP }, ++ { MASK_VSX, CODE_FOR_sqrtv4sf2, "__builtin_vsx_xvsqrtsp", VSX_BUILTIN_XVSQRTSP }, ++ { MASK_VSX, CODE_FOR_vsx_rsqrtev4sf2, "__builtin_vsx_xvrsqrtesp", VSX_BUILTIN_XVRSQRTESP }, ++ { MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2, "__builtin_vsx_xvtsqrtsp", VSX_BUILTIN_XVTSQRTSP }, ++ { MASK_VSX, CODE_FOR_vsx_frev4sf2, "__builtin_vsx_xvresp", VSX_BUILTIN_XVRESP }, ++ + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS }, + { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL }, +@@ -7822,6 +8547,20 @@ static struct builtin_description bdesc_ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsh", ALTIVEC_BUILTIN_VEC_VUPKLSH }, { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsb", ALTIVEC_BUILTIN_VEC_VUPKLSB }, @@ -4695,11 +5801,20 @@ testsuite/ + { MASK_ALTIVEC|MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vec_uns_float_sisf", VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF }, + { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI }, + { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI }, ++ ++ { MASK_VSX, CODE_FOR_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP }, ++ { MASK_VSX, CODE_FOR_unsigned_floatv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP }, ++ { MASK_VSX, CODE_FOR_fix_truncv2dfv2di2, "__builtin_vsx_xvdpsxds", VSX_BUILTIN_XVCVDPSXDS }, ++ { MASK_VSX, CODE_FOR_fixuns_truncv2dfv2di2, "__builtin_vsx_xvdpuxds", VSX_BUILTIN_XVCVDPUXDS }, ++ { MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXDSP }, ++ { MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP }, ++ { MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vsx_xvspsxws", VSX_BUILTIN_XVCVSPSXWS }, ++ { MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vsx_xvspuxws", VSX_BUILTIN_XVCVSPUXWS }, + /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and end with SPE_BUILTIN_EVSUBFUSIAAW. */ { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS }, -@@ -8352,16 +8895,16 @@ altivec_expand_ld_builtin (tree exp, rtx +@@ -8378,16 +9117,16 @@ altivec_expand_ld_builtin (tree exp, rtx switch (fcode) { case ALTIVEC_BUILTIN_LD_INTERNAL_16qi: @@ -4720,7 +5835,7 @@ testsuite/ break; default: *expandedp = false; -@@ -8405,16 +8948,16 @@ altivec_expand_st_builtin (tree exp, rtx +@@ -8431,16 +9170,16 @@ altivec_expand_st_builtin (tree exp, rtx switch (fcode) { case ALTIVEC_BUILTIN_ST_INTERNAL_16qi: @@ -4741,7 +5856,57 @@ testsuite/ break; default: *expandedp = false; -@@ -9372,6 +9915,8 @@ rs6000_init_builtins (void) +@@ -8835,6 +9574,26 @@ altivec_expand_builtin (tree exp, rtx ta + /* Expand the builtin in EXP and store the result in TARGET. Store + true in *EXPANDEDP if we found a builtin to expand. */ + static rtx ++vsx_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, bool *expandedp) ++{ ++ tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); ++ unsigned int fcode = DECL_FUNCTION_CODE (fndecl); ++ ++ if (fcode >= VSX_BUILTIN_OVERLOADED_FIRST ++ && fcode <= VSX_BUILTIN_OVERLOADED_LAST) ++ { ++ *expandedp = true; ++ error ("unresolved overload for vsx builtin %qF", fndecl); ++ return const0_rtx; ++ } ++ ++ *expandedp = false; ++ return NULL_RTX; ++} ++ ++/* Expand the builtin in EXP and store the result in TARGET. Store ++ true in *EXPANDEDP if we found a builtin to expand. */ ++static rtx + paired_expand_builtin (tree exp, rtx target, bool * expandedp) + { + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); +@@ -9346,6 +10105,13 @@ rs6000_expand_builtin (tree exp, rtx tar + if (success) + return ret; + } ++ if (TARGET_VSX) ++ { ++ ret = vsx_expand_builtin (exp, target, &success); ++ ++ if (success) ++ return ret; ++ } + if (TARGET_SPE) + { + ret = spe_expand_builtin (exp, target, &success); +@@ -9361,7 +10127,7 @@ rs6000_expand_builtin (tree exp, rtx tar + return ret; + } + +- gcc_assert (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT); ++ gcc_assert (TARGET_ALTIVEC || TARGET_VSX || TARGET_SPE || TARGET_PAIRED_FLOAT); + + /* Handle simple unary operations. */ + d = (struct builtin_description *) bdesc_1arg; +@@ -9398,6 +10164,8 @@ rs6000_init_builtins (void) { V2SI_type_node = build_vector_type (intSI_type_node, 2); V2SF_type_node = build_vector_type (float_type_node, 2); @@ -4750,7 +5915,7 @@ testsuite/ V4HI_type_node = build_vector_type (intHI_type_node, 4); V4SI_type_node = build_vector_type (intSI_type_node, 4); V4SF_type_node = build_vector_type (float_type_node, 4); -@@ -9404,7 +9949,10 @@ rs6000_init_builtins (void) +@@ -9430,7 +10198,10 @@ rs6000_init_builtins (void) uintHI_type_internal_node = unsigned_intHI_type_node; intSI_type_internal_node = intSI_type_node; uintSI_type_internal_node = unsigned_intSI_type_node; @@ -4761,7 +5926,7 @@ testsuite/ void_type_internal_node = void_type_node; (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL, -@@ -9462,13 +10010,18 @@ rs6000_init_builtins (void) +@@ -9488,13 +10259,18 @@ rs6000_init_builtins (void) get_identifier ("__vector __pixel"), pixel_V8HI_type_node)); @@ -4781,10 +5946,41 @@ testsuite/ rs6000_common_init_builtins (); if (TARGET_PPC_GFXOPT) { -@@ -10407,6 +10960,26 @@ rs6000_common_init_builtins (void) +@@ -9957,6 +10733,8 @@ altivec_init_builtins (void) + = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE); + tree v4sf_ftype_v4sf + = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE); ++ tree v2df_ftype_v2df ++ = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE); + tree void_ftype_pcvoid_int_int + = build_function_type_list (void_type_node, + pcvoid_type_node, integer_type_node, +@@ -10114,6 +10892,9 @@ altivec_init_builtins (void) + case V4SFmode: + type = v4sf_ftype_v4sf; + break; ++ case V2DFmode: ++ type = v2df_ftype_v2df; ++ break; + default: + gcc_unreachable (); + } +@@ -10433,6 +11214,38 @@ rs6000_common_init_builtins (void) tree int_ftype_v8hi_v8hi = build_function_type_list (integer_type_node, V8HI_type_node, V8HI_type_node, NULL_TREE); ++ tree v2di_ftype_v2df ++ = build_function_type_list (V2DI_type_node, ++ V2DF_type_node, NULL_TREE); ++ tree v2df_ftype_v2df ++ = build_function_type_list (V2DF_type_node, ++ V2DF_type_node, NULL_TREE); ++ tree v2df_ftype_v2di ++ = build_function_type_list (V2DF_type_node, ++ V2DI_type_node, NULL_TREE); ++ tree v2df_ftype_v2df_v2df ++ = build_function_type_list (V2DF_type_node, ++ V2DF_type_node, V2DF_type_node, NULL_TREE); + tree v2df_ftype_v2df_v2df_v2df + = build_function_type_list (V2DF_type_node, + V2DF_type_node, V2DF_type_node, @@ -4808,7 +6004,7 @@ testsuite/ /* Add the simple ternary operators. */ d = bdesc_3arg; -@@ -10443,6 +11016,12 @@ rs6000_common_init_builtins (void) +@@ -10469,6 +11282,12 @@ rs6000_common_init_builtins (void) case VOIDmode: type = opaque_ftype_opaque_opaque_opaque; break; @@ -4821,7 +6017,7 @@ testsuite/ case V4SImode: type = v4si_ftype_v4si_v4si_v4si; break; -@@ -10466,6 +11045,12 @@ rs6000_common_init_builtins (void) +@@ -10492,6 +11311,12 @@ rs6000_common_init_builtins (void) { switch (mode0) { @@ -4834,7 +6030,26 @@ testsuite/ case V4SImode: type = v4si_ftype_v4si_v4si_v16qi; break; -@@ -10721,6 +11306,10 @@ rs6000_common_init_builtins (void) +@@ -10577,6 +11402,9 @@ rs6000_common_init_builtins (void) + case VOIDmode: + type = opaque_ftype_opaque_opaque; + break; ++ case V2DFmode: ++ type = v2df_ftype_v2df_v2df; ++ break; + case V4SFmode: + type = v4sf_ftype_v4sf_v4sf; + break; +@@ -10726,6 +11554,8 @@ rs6000_common_init_builtins (void) + type = v16qi_ftype_int; + else if (mode0 == VOIDmode && mode1 == VOIDmode) + type = opaque_ftype_opaque; ++ else if (mode0 == V2DFmode && mode1 == V2DFmode) ++ type = v2df_ftype_v2df; + else if (mode0 == V4SFmode && mode1 == V4SFmode) + type = v4sf_ftype_v4sf; + else if (mode0 == V8HImode && mode1 == V16QImode) +@@ -10747,6 +11577,14 @@ rs6000_common_init_builtins (void) type = v2si_ftype_v2sf; else if (mode0 == V2SImode && mode1 == QImode) type = v2si_ftype_char; @@ -4842,10 +6057,332 @@ testsuite/ + type = v4si_ftype_v4sf; + else if (mode0 == V4SFmode && mode1 == V4SImode) + type = v4sf_ftype_v4si; ++ else if (mode0 == V2DImode && mode1 == V2DFmode) ++ type = v2di_ftype_v2df; ++ else if (mode0 == V2DFmode && mode1 == V2DImode) ++ type = v2df_ftype_v2di; else gcc_unreachable (); -@@ -11601,13 +12190,101 @@ rs6000_instantiate_decls (void) +@@ -11529,8 +12367,10 @@ rtx + rs6000_secondary_memory_needed_rtx (enum machine_mode mode) + { + static bool eliminated = false; ++ rtx ret; ++ + if (mode != SDmode) +- return assign_stack_local (mode, GET_MODE_SIZE (mode), 0); ++ ret = assign_stack_local (mode, GET_MODE_SIZE (mode), 0); + else + { + rtx mem = cfun->machine->sdmode_stack_slot; +@@ -11542,8 +12382,21 @@ rs6000_secondary_memory_needed_rtx (enum + cfun->machine->sdmode_stack_slot = mem; + eliminated = true; + } +- return mem; ++ ret = mem; ++ } ++ ++ if (TARGET_DEBUG_ADDR) ++ { ++ fprintf (stderr, "rs6000_secondary_memory_needed_rtx, mode %s, rtx:\n", ++ GET_MODE_NAME (mode)); ++ if (!ret) ++ fprintf (stderr, "\tNULL_RTX\n"); ++ else ++ debug_rtx (ret); ++ fprintf (stderr, "\n"); + } ++ ++ return ret; + } + + static tree +@@ -11577,6 +12430,282 @@ rs6000_check_sdmode (tree *tp, int *walk + return NULL_TREE; + } + ++enum reload_reg_type { ++ GPR_REGISTER_TYPE, ++ VECTOR_REGISTER_TYPE, ++ OTHER_REGISTER_TYPE ++}; ++ ++static enum reload_reg_type ++rs6000_reload_register_type (enum reg_class rclass) ++{ ++ switch (rclass) ++ { ++ case GENERAL_REGS: ++ case BASE_REGS: ++ return GPR_REGISTER_TYPE; ++ ++ case FLOAT_REGS: ++ case ALTIVEC_REGS: ++ case VSX_REGS: ++ return VECTOR_REGISTER_TYPE; ++ ++ default: ++ return OTHER_REGISTER_TYPE; ++ } ++} ++ ++/* Inform reload about cases where moving X with a mode MODE to a register in ++ RCLASS requires an extra scratch or immediate register. Return the class ++ needed for the immediate register. ++ ++ For VSX and Altivec, we may need a register to convert sp+offset into ++ reg+sp. */ ++ ++static enum reg_class ++rs6000_secondary_reload (bool in_p, ++ rtx x, ++ enum reg_class rclass, ++ enum machine_mode mode, ++ secondary_reload_info *sri) ++{ ++ enum reg_class ret; ++ enum insn_code icode; ++ ++ /* Convert vector loads and stores into gprs to use an additional base ++ register. */ ++ icode = rs6000_vector_reload[mode][in_p != false]; ++ if (icode != CODE_FOR_nothing) ++ { ++ ret = NO_REGS; ++ sri->icode = CODE_FOR_nothing; ++ sri->extra_cost = 0; ++ ++ if (GET_CODE (x) == MEM) ++ { ++ rtx addr = XEXP (x, 0); ++ ++ /* Loads to and stores from gprs can do reg+offset, and wouldn't need ++ an extra register in that case, but it would need an extra ++ register if the addressing is reg+reg or (reg+reg)&(-16). */ ++ if (rclass == GENERAL_REGS || rclass == BASE_REGS) ++ { ++ if (! rs6000_legitimate_offset_address_p (TImode, addr, true)) ++ { ++ sri->icode = icode; ++ /* account for splitting the loads, and converting the ++ address from reg+reg to reg. */ ++ sri->extra_cost = (((TARGET_64BIT) ? 3 : 5) ++ + ((GET_CODE (addr) == AND) ? 1 : 0)); ++ } ++ } ++ /* Loads to and stores from vector registers can only do reg+reg ++ addressing. Altivec registers can also do (reg+reg)&(-16). */ ++ else if (rclass == VSX_REGS || rclass == ALTIVEC_REGS ++ || rclass == FLOAT_REGS) ++ { ++ if (rclass != ALTIVEC_REGS ++ && GET_CODE (addr) == AND ++ && GET_CODE (XEXP (addr, 1)) == CONST_INT ++ && INTVAL (XEXP (addr, 1)) == -16 ++ && (legitimate_indirect_address_p (XEXP (addr, 0), true) ++ || legitimate_indexed_address_p (XEXP (addr, 0), true))) ++ { ++ sri->icode = icode; ++ sri->extra_cost = ((GET_CODE (XEXP (addr, 0)) == PLUS) ++ ? 2 : 1); ++ } ++ else if (!legitimate_indexed_address_p (addr, true) ++ && !legitimate_indirect_address_p (addr, true)) ++ { ++ sri->icode = icode; ++ sri->extra_cost = 1; ++ } ++ else ++ icode = CODE_FOR_nothing; ++ } ++ /* Any other loads, including to pseudo registers which haven't been ++ assigned to a register yet, default to require a scratch ++ register. */ ++ else ++ { ++ sri->icode = icode; ++ sri->extra_cost = 2; ++ } ++ } ++ else ++ { ++ int regno = true_regnum (x); ++ ++ icode = CODE_FOR_nothing; ++ if (regno < 0 || regno >= FIRST_PSEUDO_REGISTER) ++ ret = default_secondary_reload (in_p, x, rclass, mode, sri); ++ else ++ { ++ enum reg_class xclass = REGNO_REG_CLASS (regno); ++ enum reload_reg_type rtype1 = rs6000_reload_register_type (rclass); ++ enum reload_reg_type rtype2 = rs6000_reload_register_type (xclass); ++ ++ /* If memory is needed, use default_secondary_reload to create the ++ stack slot. */ ++ if (rtype1 != rtype2 || rtype1 == OTHER_REGISTER_TYPE) ++ ret = default_secondary_reload (in_p, x, rclass, mode, sri); ++ else ++ ret = NO_REGS; ++ } ++ } ++ } ++ else ++ ret = default_secondary_reload (in_p, x, rclass, mode, sri); ++ ++ if (TARGET_DEBUG_ADDR) ++ { ++ fprintf (stderr, ++ "rs6000_secondary_reload, return %s, in_p = %s, rclass = %s, " ++ "mode = %s", ++ reg_class_names[ret], ++ in_p ? "true" : "false", ++ reg_class_names[rclass], ++ GET_MODE_NAME (mode)); ++ ++ if (icode != CODE_FOR_nothing) ++ fprintf (stderr, ", reload func = %s, extra cost = %d\n", ++ insn_data[icode].name, sri->extra_cost); ++ else ++ fprintf (stderr, "\n"); ++ ++ debug_rtx (x); ++ fprintf (stderr, "\n"); ++ } ++ ++ return ret; ++} ++ ++/* Fixup reload addresses for Altivec or VSX loads/stores to change SP+offset ++ to SP+reg addressing. */ ++ ++void ++rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p) ++{ ++ int regno = true_regnum (reg); ++ enum machine_mode mode = GET_MODE (reg); ++ enum reg_class rclass; ++ rtx addr; ++ rtx and_op2 = NULL_RTX; ++ ++ if (TARGET_DEBUG_ADDR) ++ { ++ fprintf (stderr, "rs6000_secondary_reload_inner, type = %s\n", ++ store_p ? "store" : "load"); ++ fprintf (stderr, "reg:\n"); ++ debug_rtx (reg); ++ fprintf (stderr, "mem:\n"); ++ debug_rtx (mem); ++ fprintf (stderr, "scratch:\n"); ++ debug_rtx (scratch); ++ fprintf (stderr, "\n"); ++ } ++ ++ gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER); ++ gcc_assert (GET_CODE (mem) == MEM); ++ rclass = REGNO_REG_CLASS (regno); ++ addr = XEXP (mem, 0); ++ ++ switch (rclass) ++ { ++ /* Move reg+reg addresses into a scratch register for GPRs. */ ++ case GENERAL_REGS: ++ case BASE_REGS: ++ if (GET_CODE (addr) == AND) ++ { ++ and_op2 = XEXP (addr, 1); ++ addr = XEXP (addr, 0); ++ } ++ if (GET_CODE (addr) == PLUS ++ && (!rs6000_legitimate_offset_address_p (TImode, addr, true) ++ || and_op2 != NULL_RTX)) ++ { ++ if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST ++ || GET_CODE (addr) == CONST_INT) ++ rs6000_emit_move (scratch, addr, GET_MODE (addr)); ++ else ++ emit_insn (gen_rtx_SET (VOIDmode, scratch, addr)); ++ addr = scratch; ++ } ++ else if (GET_CODE (addr) == PRE_MODIFY ++ && REG_P (XEXP (addr, 0)) ++ && GET_CODE (XEXP (addr, 1)) == PLUS) ++ { ++ emit_insn (gen_rtx_SET (VOIDmode, XEXP (addr, 0), XEXP (addr, 1))); ++ addr = XEXP (addr, 0); ++ } ++ break; ++ ++ /* With float regs, we need to handle the AND ourselves, since we can't ++ use the Altivec instruction with an implicit AND -16. Allow scalar ++ loads to float registers to use reg+offset even if VSX. */ ++ case FLOAT_REGS: ++ case VSX_REGS: ++ if (GET_CODE (addr) == AND) ++ { ++ and_op2 = XEXP (addr, 1); ++ addr = XEXP (addr, 0); ++ } ++ /* fall through */ ++ ++ /* Move reg+offset addresses into a scratch register. */ ++ case ALTIVEC_REGS: ++ if (!legitimate_indirect_address_p (addr, true) ++ && !legitimate_indexed_address_p (addr, true) ++ && (GET_CODE (addr) != PRE_MODIFY ++ || !legitimate_indexed_address_p (XEXP (addr, 1), true)) ++ && (rclass != FLOAT_REGS ++ || GET_MODE_SIZE (mode) != 8 ++ || and_op2 != NULL_RTX ++ || !rs6000_legitimate_offset_address_p (mode, addr, true))) ++ { ++ if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST ++ || GET_CODE (addr) == CONST_INT) ++ rs6000_emit_move (scratch, addr, GET_MODE (addr)); ++ else ++ emit_insn (gen_rtx_SET (VOIDmode, scratch, addr)); ++ addr = scratch; ++ } ++ break; ++ ++ default: ++ gcc_unreachable (); ++ } ++ ++ /* If the original address involved an AND -16 that is part of the Altivec ++ addresses, recreate the and now. */ ++ if (and_op2 != NULL_RTX) ++ { ++ rtx and_rtx = gen_rtx_SET (VOIDmode, ++ scratch, ++ gen_rtx_AND (Pmode, addr, and_op2)); ++ rtx cc_clobber = gen_rtx_CLOBBER (CCmode, gen_rtx_SCRATCH (CCmode)); ++ emit_insn (gen_rtx_PARALLEL (VOIDmode, ++ gen_rtvec (2, and_rtx, cc_clobber))); ++ addr = scratch; ++ } ++ ++ /* Adjust the address if it changed. */ ++ if (addr != XEXP (mem, 0)) ++ { ++ mem = change_address (mem, mode, addr); ++ if (TARGET_DEBUG_ADDR) ++ fprintf (stderr, "rs6000_secondary_reload_inner, mem adjusted.\n"); ++ } ++ ++ /* Now create the move. */ ++ if (store_p) ++ emit_insn (gen_rtx_SET (VOIDmode, mem, reg)); ++ else ++ emit_insn (gen_rtx_SET (VOIDmode, reg, mem)); ++ ++ return; ++} + + /* Allocate a 64-bit stack slot to be used for copying SDmode + values through if this function has any SDmode references. */ +@@ -11627,15 +12756,146 @@ rs6000_instantiate_decls (void) instantiate_decl_rtl (cfun->machine->sdmode_stack_slot); } @@ -4871,32 +6408,52 @@ testsuite/ +rs6000_preferred_reload_class (rtx x, enum reg_class rclass) +{ + enum machine_mode mode = GET_MODE (x); ++ enum reg_class ret; + + if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode) + && VSX_REG_CLASS_P (rclass)) -+ return rclass; ++ ret = rclass; + -+ if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) && rclass == ALTIVEC_REGS -+ && easy_vector_constant (x, mode)) -+ return rclass; ++ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) ++ && rclass == ALTIVEC_REGS && easy_vector_constant (x, mode)) ++ ret = rclass; + -+ if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS)) -+ return NO_REGS; ++ else if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS)) ++ ret = NO_REGS; + -+ if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS) -+ return GENERAL_REGS; ++ else if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS) ++ ret = GENERAL_REGS; + -+ /* For VSX, prefer the traditional registers. */ -+ if (rclass == VSX_REGS) ++ /* For VSX, prefer the traditional registers unless the address involves AND ++ -16, where we prefer to use the Altivec register so we don't have to break ++ down the AND. */ ++ else if (rclass == VSX_REGS) + { + if (mode == DFmode) -+ return FLOAT_REGS; ++ ret = FLOAT_REGS; + -+ if (ALTIVEC_VECTOR_MODE (mode)) -+ return ALTIVEC_REGS; ++ else if (altivec_indexed_or_indirect_operand (x, mode)) ++ ret = ALTIVEC_REGS; ++ ++ else if (ALTIVEC_VECTOR_MODE (mode)) ++ ret = ALTIVEC_REGS; ++ ++ else ++ ret = rclass; ++ } ++ else ++ ret = rclass; ++ ++ if (TARGET_DEBUG_ADDR) ++ { ++ fprintf (stderr, ++ "rs6000_preferred_reload_class, return %s, rclass = %s, x:\n", ++ reg_class_names[ret], reg_class_names[rclass]); ++ debug_rtx (x); ++ fprintf (stderr, "\n"); + } + -+ return rclass; ++ return ret; +} + +/* If we are copying between FP or AltiVec registers and anything else, we need @@ -4910,31 +6467,53 @@ testsuite/ + enum reg_class class2, + enum machine_mode mode) +{ ++ bool ret; ++ + if (class1 == class2) -+ return false; ++ ret = false; + -+ if (TARGET_VSX && VSX_MOVE_MODE (mode) && VSX_REG_CLASS_P (class1) -+ && VSX_REG_CLASS_P (class2)) -+ return false; ++ /* Under VSX, there are 3 register classes that values could be in (VSX_REGS, ++ ALTIVEC_REGS, and FLOAT_REGS). We don't need to use memory to copy ++ between these classes. But we need memory for other things that can go in ++ FLOAT_REGS like SFmode. */ ++ else if (TARGET_VSX ++ && (VECTOR_MEM_VSX_P (mode) || VECTOR_UNIT_VSX_P (mode)) ++ && (class1 == VSX_REGS || class1 == ALTIVEC_REGS ++ || class1 == FLOAT_REGS)) ++ ret = (class2 != VSX_REGS && class2 != ALTIVEC_REGS ++ && class2 != FLOAT_REGS); + -+ if (class1 == FLOAT_REGS -+ && (!TARGET_MFPGPR || !TARGET_POWERPC64 -+ || ((mode != DFmode) -+ && (mode != DDmode) -+ && (mode != DImode)))) -+ return true; ++ else if (class1 == VSX_REGS || class2 == VSX_REGS) ++ ret = true; + -+ if (class2 == FLOAT_REGS -+ && (!TARGET_MFPGPR || !TARGET_POWERPC64 -+ || ((mode != DFmode) -+ && (mode != DDmode) -+ && (mode != DImode)))) -+ return true; ++ else if (class1 == FLOAT_REGS ++ && (!TARGET_MFPGPR || !TARGET_POWERPC64 ++ || ((mode != DFmode) ++ && (mode != DDmode) ++ && (mode != DImode)))) ++ ret = true; + -+ if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS) -+ return true; ++ else if (class2 == FLOAT_REGS ++ && (!TARGET_MFPGPR || !TARGET_POWERPC64 ++ || ((mode != DFmode) ++ && (mode != DDmode) ++ && (mode != DImode)))) ++ ret = true; + -+ return false; ++ else if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS) ++ ret = true; ++ ++ else ++ ret = false; ++ ++ if (TARGET_DEBUG_ADDR) ++ fprintf (stderr, ++ "rs6000_secondary_memory_needed, return: %s, class1 = %s, " ++ "class2 = %s, mode = %s\n", ++ ret ? "true" : "false", reg_class_names[class1], ++ reg_class_names[class2], GET_MODE_NAME (mode)); ++ ++ return ret; +} + /* Return the register class of a scratch register needed to copy IN into @@ -4947,51 +6526,157 @@ testsuite/ + enum machine_mode mode, rtx in) { ++ enum reg_class ret = NO_REGS; int regno; -@@ -11663,6 +12340,13 @@ rs6000_secondary_reload_class (enum reg_ - && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS)) - return (mode != SDmode) ? NO_REGS : GENERAL_REGS; -+ /* Memory, and FP/altivec registers can go into fp/altivec registers under -+ VSX. */ -+ if (TARGET_VSX -+ && (regno == -1 || VSX_REGNO_P (regno)) -+ && VSX_REG_CLASS_P (rclass)) -+ return NO_REGS; + if (TARGET_ELF || (DEFAULT_ABI == ABI_DARWIN +@@ -11656,51 +12916,112 @@ rs6000_secondary_reload_class (enum reg_ + || GET_CODE (in) == HIGH + || GET_CODE (in) == LABEL_REF + || GET_CODE (in) == CONST)) +- return BASE_REGS; ++ ret = BASE_REGS; + } + +- if (GET_CODE (in) == REG) ++ if (ret == NO_REGS) + { +- regno = REGNO (in); +- if (regno >= FIRST_PSEUDO_REGISTER) ++ if (GET_CODE (in) == REG) ++ { ++ regno = REGNO (in); ++ if (regno >= FIRST_PSEUDO_REGISTER) ++ { ++ regno = true_regnum (in); ++ if (regno >= FIRST_PSEUDO_REGISTER) ++ regno = -1; ++ } ++ } ++ else if (GET_CODE (in) == SUBREG) + { + regno = true_regnum (in); + if (regno >= FIRST_PSEUDO_REGISTER) + regno = -1; + } +- } +- else if (GET_CODE (in) == SUBREG) +- { +- regno = true_regnum (in); +- if (regno >= FIRST_PSEUDO_REGISTER) ++ else + regno = -1; + - /* Memory, and AltiVec registers can go into AltiVec registers. */ - if ((regno == -1 || ALTIVEC_REGNO_P (regno)) - && rclass == ALTIVEC_REGS) -@@ -11676,6 +12360,28 @@ rs6000_secondary_reload_class (enum reg_ - /* Otherwise, we need GENERAL_REGS. */ - return GENERAL_REGS; - } ++ /* We can place anything into GENERAL_REGS and can put GENERAL_REGS ++ into anything. */ ++ if (rclass == GENERAL_REGS || rclass == BASE_REGS ++ || (regno >= 0 && INT_REGNO_P (regno))) ++ ret = NO_REGS; ++ ++ /* Constants, memory, and FP registers can go into FP registers. */ ++ else if ((regno == -1 || FP_REGNO_P (regno)) ++ && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS)) ++ ret = (mode != SDmode) ? NO_REGS : GENERAL_REGS; ++ ++ /* Memory, and FP/altivec registers can go into fp/altivec registers under ++ VSX. */ ++ else if (TARGET_VSX ++ && (regno == -1 || VSX_REGNO_P (regno)) ++ && VSX_REG_CLASS_P (rclass)) ++ ret = NO_REGS; ++ ++ /* Memory, and AltiVec registers can go into AltiVec registers. */ ++ else if ((regno == -1 || ALTIVEC_REGNO_P (regno)) ++ && rclass == ALTIVEC_REGS) ++ ret = NO_REGS; ++ ++ /* We can copy among the CR registers. */ ++ else if ((rclass == CR_REGS || rclass == CR0_REGS) ++ && regno >= 0 && CR_REGNO_P (regno)) ++ ret = NO_REGS; ++ ++ /* Otherwise, we need GENERAL_REGS. */ ++ else ++ ret = GENERAL_REGS; ++ } ++ ++ if (TARGET_DEBUG_ADDR) ++ { ++ fprintf (stderr, ++ "rs6000_secondary_reload_class, return %s, rclass = %s, " ++ "mode = %s, input rtx:\n", ++ reg_class_names[ret], reg_class_names[rclass], ++ GET_MODE_NAME (mode)); ++ debug_rtx (in); ++ fprintf (stderr, "\n"); + } +- else +- regno = -1; + +- /* We can place anything into GENERAL_REGS and can put GENERAL_REGS +- into anything. */ +- if (rclass == GENERAL_REGS || rclass == BASE_REGS +- || (regno >= 0 && INT_REGNO_P (regno))) +- return NO_REGS; +- +- /* Constants, memory, and FP registers can go into FP registers. */ +- if ((regno == -1 || FP_REGNO_P (regno)) +- && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS)) +- return (mode != SDmode) ? NO_REGS : GENERAL_REGS; +- +- /* Memory, and AltiVec registers can go into AltiVec registers. */ +- if ((regno == -1 || ALTIVEC_REGNO_P (regno)) +- && rclass == ALTIVEC_REGS) +- return NO_REGS; +- +- /* We can copy among the CR registers. */ +- if ((rclass == CR_REGS || rclass == CR0_REGS) +- && regno >= 0 && CR_REGNO_P (regno)) +- return NO_REGS; ++ return ret; ++} + +/* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */ -+ + +- /* Otherwise, we need GENERAL_REGS. */ +- return GENERAL_REGS; +bool +rs6000_cannot_change_mode_class (enum machine_mode from, + enum machine_mode to, + enum reg_class rclass) +{ -+ return (GET_MODE_SIZE (from) != GET_MODE_SIZE (to) -+ ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8 -+ || TARGET_IEEEQUAD) -+ && reg_classes_intersect_p (FLOAT_REGS, rclass)) -+ : (((TARGET_E500_DOUBLE -+ && ((((to) == DFmode) + ((from) == DFmode)) == 1 -+ || (((to) == TFmode) + ((from) == TFmode)) == 1 -+ || (((to) == DDmode) + ((from) == DDmode)) == 1 -+ || (((to) == TDmode) + ((from) == TDmode)) == 1 -+ || (((to) == DImode) + ((from) == DImode)) == 1)) -+ || (TARGET_SPE -+ && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1)) -+ && reg_classes_intersect_p (GENERAL_REGS, rclass))); -+} ++ bool ret = (GET_MODE_SIZE (from) != GET_MODE_SIZE (to) ++ ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8 ++ || TARGET_IEEEQUAD) ++ && reg_classes_intersect_p (FLOAT_REGS, rclass)) ++ : (((TARGET_E500_DOUBLE ++ && ((((to) == DFmode) + ((from) == DFmode)) == 1 ++ || (((to) == TFmode) + ((from) == TFmode)) == 1 ++ || (((to) == DDmode) + ((from) == DDmode)) == 1 ++ || (((to) == TDmode) + ((from) == TDmode)) == 1 ++ || (((to) == DImode) + ((from) == DImode)) == 1)) ++ || (TARGET_VSX ++ && (VSX_VECTOR_MODE (from) + VSX_VECTOR_MODE (to)) == 1) ++ || (TARGET_ALTIVEC ++ && (ALTIVEC_VECTOR_MODE (from) ++ + ALTIVEC_VECTOR_MODE (to)) == 1) ++ || (TARGET_SPE ++ && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1)) ++ && reg_classes_intersect_p (GENERAL_REGS, rclass))); ++ ++ if (TARGET_DEBUG_ADDR) ++ fprintf (stderr, ++ "rs6000_cannot_change_mode_class, return %s, from = %s, " ++ "to = %s, rclass = %s\n", ++ ret ? "true" : "false", ++ GET_MODE_NAME (from), GET_MODE_NAME (to), ++ reg_class_names[rclass]); ++ ++ return ret; + } /* Given a comparison operation, return the bit number in CCR to test. We - know this is a valid comparison. -@@ -12406,6 +13112,26 @@ print_operand (FILE *file, rtx x, int co +@@ -12432,6 +13753,26 @@ print_operand (FILE *file, rtx x, int co fprintf (file, "%d", i + 1); return; @@ -5018,12 +6703,12 @@ testsuite/ case 'X': if (GET_CODE (x) == MEM && (legitimate_indexed_address_p (XEXP (x, 0), 0) -@@ -12518,13 +13244,16 @@ print_operand (FILE *file, rtx x, int co +@@ -12544,13 +13885,16 @@ print_operand (FILE *file, rtx x, int co /* Fall through. Must be [reg+reg]. */ } - if (TARGET_ALTIVEC -+ if (VECTOR_MEM_ALTIVEC_P (GET_MODE (x)) ++ if (VECTOR_MEM_ALTIVEC_OR_VSX_P (GET_MODE (x)) && GET_CODE (tmp) == AND && GET_CODE (XEXP (tmp, 1)) == CONST_INT && INTVAL (XEXP (tmp, 1)) == -16) @@ -5037,7 +6722,7 @@ testsuite/ else { if (!GET_CODE (tmp) == PLUS -@@ -13296,55 +14025,62 @@ output_e500_flip_gt_bit (rtx dst, rtx sr +@@ -13322,55 +14666,62 @@ output_e500_flip_gt_bit (rtx dst, rtx sr return string; } @@ -5139,7 +6824,7 @@ testsuite/ } /* Emit vector compare for operands OP0 and OP1 using code RCODE. -@@ -13355,129 +14091,111 @@ rs6000_emit_vector_compare (enum rtx_cod +@@ -13381,129 +14732,111 @@ rs6000_emit_vector_compare (enum rtx_cod rtx op0, rtx op1, enum machine_mode dmode) { @@ -5358,7 +7043,7 @@ testsuite/ if (swap_operands) { rtx tmp; -@@ -13485,69 +14203,23 @@ rs6000_emit_vector_compare (enum rtx_cod +@@ -13511,69 +14844,23 @@ rs6000_emit_vector_compare (enum rtx_cod op0 = op1; op1 = tmp; } @@ -5376,10 +7061,10 @@ testsuite/ - } - return mask; -} -- + -/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if - valid insn doesn exist for given mode. */ - +- -static int -get_vsel_insn (enum machine_mode mode) -{ @@ -5425,9 +7110,9 @@ testsuite/ - rtx t, temp; - enum machine_mode dest_mode = GET_MODE (dest); - int vsel_insn_index = get_vsel_insn (GET_MODE (dest)); - -- temp = gen_reg_rtx (dest_mode); - +- temp = gen_reg_rtx (dest_mode); + - /* For each vector element, select op1 when mask is 1 otherwise - select op2. */ - t = gen_rtx_SET (VOIDmode, temp, @@ -5442,7 +7127,7 @@ testsuite/ } /* Emit vector conditional expression. -@@ -13562,15 +14234,29 @@ rs6000_emit_vector_cond_expr (rtx dest, +@@ -13588,15 +14875,29 @@ rs6000_emit_vector_cond_expr (rtx dest, enum rtx_code rcode = GET_CODE (cond); rtx mask; @@ -5475,7 +7160,7 @@ testsuite/ } /* Emit a conditional move: move TRUE_COND to DEST if OP of the -@@ -13766,8 +14452,8 @@ rs6000_emit_int_cmove (rtx dest, rtx op, +@@ -13792,8 +15093,8 @@ rs6000_emit_int_cmove (rtx dest, rtx op, { rtx condition_rtx, cr; @@ -5486,7 +7171,7 @@ testsuite/ return 0; /* We still have to do the compare, because isel doesn't do a -@@ -13776,12 +14462,24 @@ rs6000_emit_int_cmove (rtx dest, rtx op, +@@ -13802,12 +15103,24 @@ rs6000_emit_int_cmove (rtx dest, rtx op, condition_rtx = rs6000_generate_compare (GET_CODE (op)); cr = XEXP (condition_rtx, 0); @@ -5516,7 +7201,7 @@ testsuite/ return 1; } -@@ -13808,6 +14506,15 @@ rs6000_emit_minmax (rtx dest, enum rtx_c +@@ -13834,6 +15147,15 @@ rs6000_emit_minmax (rtx dest, enum rtx_c enum rtx_code c; rtx target; @@ -5532,7 +7217,7 @@ testsuite/ if (code == SMAX || code == SMIN) c = GE; else -@@ -15785,6 +16492,7 @@ emit_frame_save (rtx frame_reg, rtx fram +@@ -15811,6 +17133,7 @@ emit_frame_save (rtx frame_reg, rtx fram /* Some cases that need register indexed addressing. */ if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode)) @@ -5540,7 +7225,51 @@ testsuite/ || (TARGET_E500_DOUBLE && mode == DFmode) || (TARGET_SPE_ABI && SPE_VECTOR_MODE (mode) -@@ -19320,6 +20028,7 @@ rs6000_issue_rate (void) +@@ -18923,6 +20246,7 @@ rs6000_adjust_cost (rtx insn, rtx link, + || rs6000_cpu_attr == CPU_PPC7450 + || rs6000_cpu_attr == CPU_POWER4 + || rs6000_cpu_attr == CPU_POWER5 ++ || (rs6000_cpu_attr == CPU_POWER7 && TARGET_POWER7_ADJUST_COST) + || rs6000_cpu_attr == CPU_CELL) + && recog_memoized (dep_insn) + && (INSN_CODE (dep_insn) >= 0)) +@@ -19162,6 +20486,35 @@ rs6000_adjust_cost (rtx insn, rtx link, + return cost; + } + ++/* Debug version of rs6000_adjust_cost. */ ++ ++static int ++rs6000_debug_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost) ++{ ++ int ret = rs6000_adjust_cost (insn, link, dep_insn, cost); ++ ++ if (ret != cost) ++ { ++ const char *dep; ++ ++ switch (REG_NOTE_KIND (link)) ++ { ++ default: dep = "unknown depencency"; break; ++ case REG_DEP_TRUE: dep = "data dependency"; break; ++ case REG_DEP_OUTPUT: dep = "output dependency"; break; ++ case REG_DEP_ANTI: dep = "anti depencency"; break; ++ } ++ ++ fprintf (stderr, ++ "\nrs6000_adjust_cost, final cost = %d, orig cost = %d, " ++ "%s, insn:\n", ret, cost, dep); ++ ++ debug_rtx (insn); ++ } ++ ++ return ret; ++} ++ + /* The function returns a true if INSN is microcoded. + Return false otherwise. */ + +@@ -19443,6 +20796,7 @@ rs6000_issue_rate (void) case CPU_POWER4: case CPU_POWER5: case CPU_POWER6: @@ -5548,7 +7277,7 @@ testsuite/ return 5; default: return 1; -@@ -19921,6 +20630,41 @@ insn_must_be_first_in_group (rtx insn) +@@ -20044,6 +21398,41 @@ insn_must_be_first_in_group (rtx insn) break; } break; @@ -5590,7 +7319,7 @@ testsuite/ default: break; } -@@ -19982,6 +20726,23 @@ insn_must_be_last_in_group (rtx insn) +@@ -20105,6 +21494,23 @@ insn_must_be_last_in_group (rtx insn) break; } break; @@ -5614,7 +7343,7 @@ testsuite/ default: break; } -@@ -20554,8 +21315,8 @@ rs6000_handle_altivec_attribute (tree *n +@@ -20677,8 +22083,8 @@ rs6000_handle_altivec_attribute (tree *n else if (type == long_long_unsigned_type_node || type == long_long_integer_type_node) error ("use of % in AltiVec types is invalid"); @@ -5625,7 +7354,7 @@ testsuite/ else if (type == long_double_type_node) error ("use of % in AltiVec types is invalid"); else if (type == boolean_type_node) -@@ -20581,6 +21342,7 @@ rs6000_handle_altivec_attribute (tree *n +@@ -20704,6 +22110,7 @@ rs6000_handle_altivec_attribute (tree *n result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node); break; case SFmode: result = V4SF_type_node; break; @@ -5633,7 +7362,51 @@ testsuite/ /* If the user says 'vector int bool', we may be handed the 'bool' attribute _before_ the 'vector' attribute, and so select the proper type in the 'b' case below. */ -@@ -22116,7 +22878,7 @@ rs6000_register_move_cost (enum machine_ +@@ -22242,6 +23649,43 @@ rs6000_rtx_costs (rtx x, int code, int o + return false; + } + ++/* Debug form of r6000_rtx_costs that is selected if -mdebug=cost. */ ++ ++static bool ++rs6000_debug_rtx_costs (rtx x, int code, int outer_code, int *total, ++ bool speed) ++{ ++ bool ret = rs6000_rtx_costs (x, code, outer_code, total, speed); ++ ++ fprintf (stderr, ++ "\nrs6000_rtx_costs, return = %s, code = %s, outer_code = %s, " ++ "total = %d, speed = %s, x:\n", ++ ret ? "complete" : "scan inner", ++ GET_RTX_NAME (code), ++ GET_RTX_NAME (outer_code), ++ *total, ++ speed ? "true" : "false"); ++ ++ debug_rtx (x); ++ ++ return ret; ++} ++ ++/* Debug form of ADDRESS_COST that is selected if -mdebug=cost. */ ++ ++static int ++rs6000_debug_address_cost (rtx x, bool speed) ++{ ++ int ret = TARGET_ADDRESS_COST (x, speed); ++ ++ fprintf (stderr, "\nrs6000_address_cost, return = %d, speed = %s, x:\n", ++ ret, speed ? "true" : "false"); ++ debug_rtx (x); ++ ++ return ret; ++} ++ ++ + /* A C expression returning the cost of moving data from a register of class + CLASS1 to one of CLASS2. */ + +@@ -22256,7 +23700,7 @@ rs6000_register_move_cost (enum machine_ if (! reg_classes_intersect_p (to, GENERAL_REGS)) from = to; @@ -5642,7 +7415,7 @@ testsuite/ return (rs6000_memory_move_cost (mode, from, 0) + rs6000_memory_move_cost (mode, GENERAL_REGS, 0)); -@@ -22136,6 +22898,12 @@ rs6000_register_move_cost (enum machine_ +@@ -22276,6 +23720,12 @@ rs6000_register_move_cost (enum machine_ return 2 * hard_regno_nregs[0][mode]; } @@ -5655,7 +7428,7 @@ testsuite/ /* Moving between two similar registers is just one instruction. */ else if (reg_classes_intersect_p (to, from)) return (mode == TFmode || mode == TDmode) ? 4 : 2; -@@ -22376,8 +23144,8 @@ rs6000_emit_swrsqrtsf (rtx dst, rtx src) +@@ -22516,8 +23966,8 @@ rs6000_emit_swrsqrtsf (rtx dst, rtx src) emit_label (XEXP (label, 0)); } @@ -5666,7 +7439,7 @@ testsuite/ void rs6000_emit_popcount (rtx dst, rtx src) -@@ -22385,6 +23153,16 @@ rs6000_emit_popcount (rtx dst, rtx src) +@@ -22525,6 +23975,16 @@ rs6000_emit_popcount (rtx dst, rtx src) enum machine_mode mode = GET_MODE (dst); rtx tmp1, tmp2; @@ -5683,7 +7456,7 @@ testsuite/ tmp1 = gen_reg_rtx (mode); if (mode == SImode) -@@ -22797,7 +23575,7 @@ rs6000_vector_mode_supported_p (enum mac +@@ -22937,7 +24397,7 @@ rs6000_vector_mode_supported_p (enum mac if (TARGET_SPE && SPE_VECTOR_MODE (mode)) return true; @@ -5693,8 +7466,8 @@ testsuite/ else --- gcc/config/rs6000/vsx.md (.../trunk) (revision 0) -+++ gcc/config/rs6000/vsx.md (.../branches/ibm/power7-meissner) (revision 144730) -@@ -0,0 +1,864 @@ ++++ gcc/config/rs6000/vsx.md (.../branches/ibm/power7-meissner) (revision 146027) +@@ -0,0 +1,1004 @@ +;; VSX patterns. +;; Copyright (C) 2009 +;; Free Software Foundation, Inc. @@ -5716,12 +7489,18 @@ testsuite/ +;; along with GCC; see the file COPYING3. If not see +;; . + ++;; Iterator for both scalar and vector floating point types supported by VSX ++(define_mode_iterator VSX_B [DF V4SF V2DF]) ++ +;; Iterator for vector floating point types supported by VSX +(define_mode_iterator VSX_F [V4SF V2DF]) + +;; Iterator for logical types supported by VSX +(define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI]) + ++;; Iterator for types for load/store with update ++(define_mode_iterator VSX_U [V16QI V8HI V4SI V2DI V4SF V2DF TI DF]) ++ +;; Map into the appropriate load/store name based on the type +(define_mode_attr VSm [(V16QI "vw4") + (V8HI "vw4") @@ -5729,6 +7508,7 @@ testsuite/ + (V4SF "vw4") + (V2DF "vd2") + (V2DI "vd2") ++ (DF "d") + (TI "vw4")]) + +;; Map into the appropriate suffix based on the type @@ -5738,6 +7518,7 @@ testsuite/ + (V4SF "sp") + (V2DF "dp") + (V2DI "dp") ++ (DF "dp") + (TI "sp")]) + +;; Map into the register class used @@ -5747,30 +7528,126 @@ testsuite/ + (V4SF "wf") + (V2DI "wd") + (V2DF "wd") ++ (DF "ws") + (TI "wd")]) + ++;; Map into the register class used for float<->int conversions ++(define_mode_attr VSr2 [(V2DF "wd") ++ (V4SF "wf") ++ (DF "!f#r")]) ++ ++(define_mode_attr VSr3 [(V2DF "wa") ++ (V4SF "wa") ++ (DF "!f#r")]) ++ +;; Same size integer type for floating point data +(define_mode_attr VSi [(V4SF "v4si") -+ (V2DF "v2di")]) ++ (V2DF "v2di") ++ (DF "di")]) + +(define_mode_attr VSI [(V4SF "V4SI") -+ (V2DF "V2DI")]) ++ (V2DF "V2DI") ++ (DF "DI")]) + +;; Word size for same size conversion +(define_mode_attr VSc [(V4SF "w") -+ (V2DF "d")]) ++ (V2DF "d") ++ (DF "d")]) + +;; Bitsize for DF load with update +(define_mode_attr VSbit [(SI "32") + (DI "64")]) + ++;; Map into either s or v, depending on whether this is a scalar or vector ++;; operation ++(define_mode_attr VSv [(V16QI "v") ++ (V8HI "v") ++ (V4SI "v") ++ (V4SF "v") ++ (V2DI "v") ++ (V2DF "v") ++ (TI "v") ++ (DF "s")]) ++ ++;; Appropriate type for add ops (and other simple FP ops) ++(define_mode_attr VStype_simple [(V2DF "vecfloat") ++ (V4SF "vecfloat") ++ (DF "fp")]) ++ ++(define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d") ++ (V4SF "fp_addsub_s") ++ (DF "fp_addsub_d")]) ++ ++;; Appropriate type for multiply ops ++(define_mode_attr VStype_mul [(V2DF "vecfloat") ++ (V4SF "vecfloat") ++ (DF "dmul")]) ++ ++(define_mode_attr VSfptype_mul [(V2DF "fp_mul_d") ++ (V4SF "fp_mul_s") ++ (DF "fp_mul_d")]) ++ ++;; Appropriate type for divide ops. For now, just lump the vector divide with ++;; the scalar divides ++(define_mode_attr VStype_div [(V2DF "ddiv") ++ (V4SF "sdiv") ++ (DF "ddiv")]) ++ ++(define_mode_attr VSfptype_div [(V2DF "fp_div_d") ++ (V4SF "fp_div_s") ++ (DF "fp_div_d")]) ++ ++;; Appropriate type for sqrt ops. For now, just lump the vector sqrt with ++;; the scalar sqrt ++(define_mode_attr VStype_sqrt [(V2DF "dsqrt") ++ (V4SF "sdiv") ++ (DF "ddiv")]) ++ ++(define_mode_attr VSfptype_sqrt [(V2DF "fp_sqrt_d") ++ (V4SF "fp_sqrt_s") ++ (DF "fp_sqrt_d")]) ++ ++;; Appropriate type for load + update ++(define_mode_attr VStype_load_update [(V16QI "vecload") ++ (V8HI "vecload") ++ (V4SI "vecload") ++ (V4SF "vecload") ++ (V2DI "vecload") ++ (V2DF "vecload") ++ (TI "vecload") ++ (DF "fpload")]) ++ ++;; Appropriate type for store + update ++(define_mode_attr VStype_store_update [(V16QI "vecstore") ++ (V8HI "vecstore") ++ (V4SI "vecstore") ++ (V4SF "vecstore") ++ (V2DI "vecstore") ++ (V2DF "vecstore") ++ (TI "vecstore") ++ (DF "fpstore")]) ++ ++;; Constants for creating unspecs +(define_constants -+ [(UNSPEC_VSX_CONCAT_V2DF 500)]) ++ [(UNSPEC_VSX_CONCAT_V2DF 500) ++ (UNSPEC_VSX_XVCVDPSP 501) ++ (UNSPEC_VSX_XVCVDPSXWS 502) ++ (UNSPEC_VSX_XVCVDPUXWS 503) ++ (UNSPEC_VSX_XVCVSPDP 504) ++ (UNSPEC_VSX_XVCVSXWDP 505) ++ (UNSPEC_VSX_XVCVUXWDP 506) ++ (UNSPEC_VSX_XVMADD 507) ++ (UNSPEC_VSX_XVMSUB 508) ++ (UNSPEC_VSX_XVNMADD 509) ++ (UNSPEC_VSX_XVNMSUB 510) ++ (UNSPEC_VSX_XVRSQRTE 511) ++ (UNSPEC_VSX_XVTDIV 512) ++ (UNSPEC_VSX_XVTSQRT 513)]) + +;; VSX moves +(define_insn "*vsx_mov" -+ [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,,,?Z,?wa,?wa,*o,*r,*r,,?wa,v") -+ (match_operand:VSX_L 1 "input_operand" ",Z,,wa,Z,wa,r,o,r,j,j,W"))] ++ [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,,,?Z,?wa,?wa,*o,*r,*r,,?wa,v,wZ,v") ++ (match_operand:VSX_L 1 "input_operand" ",Z,,wa,Z,wa,r,o,r,j,j,W,v,wZ"))] + "VECTOR_MEM_VSX_P (mode) + && (register_operand (operands[0], mode) + || register_operand (operands[1], mode))" @@ -5787,7 +7664,7 @@ testsuite/ + + case 2: + case 5: -+ return "xvmov %x0,%x1"; ++ return "xxlor %x0,%x1,%x1"; + + case 6: + case 7: @@ -5801,11 +7678,17 @@ testsuite/ + case 11: + return output_vec_const_move (operands); + ++ case 12: ++ return "stvx %1,%y0"; ++ ++ case 13: ++ return "lvx %0,%y1"; ++ + default: + gcc_unreachable (); + } +} -+ [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,store,load,*,vecsimple,vecsimple,*")]) ++ [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")]) + +;; Load/store with update +;; Define insns that do load or store with update. Because VSX only has @@ -5817,575 +7700,592 @@ testsuite/ +;; tie and these are the pair most likely to be tieable (and the ones +;; that will benefit the most). + -+(define_insn "*vsx_load_update64" -+ [(set (match_operand:VSX_L 3 "vsx_register_operand" "=,?wa") -+ (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0") -+ (match_operand:DI 2 "gpc_reg_operand" "r,r")))) -+ (set (match_operand:DI 0 "gpc_reg_operand" "=b,b") -+ (plus:DI (match_dup 1) -+ (match_dup 2)))] -+ "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (mode)" -+ "lxux %x3,%0,%2" -+ [(set_attr "type" "vecload")]) -+ -+(define_insn "*vsx_load_update32" -+ [(set (match_operand:VSX_L 3 "vsx_register_operand" "=,?wa") -+ (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0") -+ (match_operand:SI 2 "gpc_reg_operand" "r,r")))) -+ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b") -+ (plus:SI (match_dup 1) -+ (match_dup 2)))] -+ "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (mode)" -+ "lxux %x3,%0,%2" -+ [(set_attr "type" "vecload")]) -+ -+(define_insn "*vsx_store_update64" -+ [(set (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0") -+ (match_operand:DI 2 "gpc_reg_operand" "r,r"))) -+ (match_operand:VSX_L 3 "gpc_reg_operand" ",?wa")) -+ (set (match_operand:DI 0 "gpc_reg_operand" "=b,b") -+ (plus:DI (match_dup 1) -+ (match_dup 2)))] -+ "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (mode)" -+ "stxux %x3,%0,%2" -+ [(set_attr "type" "vecstore")]) -+ -+(define_insn "*vsx_store_update32" -+ [(set (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0") -+ (match_operand:SI 2 "gpc_reg_operand" "r,r"))) -+ (match_operand:VSX_L 3 "gpc_reg_operand" ",?wa")) -+ (set (match_operand:SI 0 "gpc_reg_operand" "=b,b") -+ (plus:SI (match_dup 1) -+ (match_dup 2)))] -+ "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (mode)" -+ "stxux %x3,%0,%2" -+ [(set_attr "type" "vecstore")]) -+ -+(define_insn "*vsx_loaddf_update" -+ [(set (match_operand:DF 3 "vsx_register_operand" "=ws,?wa") -+ (mem:DF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0") -+ (match_operand:P 2 "gpc_reg_operand" "r,r")))) ++(define_insn "*vsx_load_update_" ++ [(set (match_operand:VSX_U 3 "vsx_register_operand" "=,?wa") ++ (mem:VSX_U (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0") ++ (match_operand:P 2 "gpc_reg_operand" "r,r")))) + (set (match_operand:P 0 "gpc_reg_operand" "=b,b") + (plus:P (match_dup 1) + (match_dup 2)))] -+ "TARGET_BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)" -+ "lxsdux %x3,%0,%2" -+ [(set_attr "type" "vecload")]) ++ " && TARGET_UPDATE && VECTOR_MEM_VSX_P (mode)" ++ "lxux %x3,%0,%2" ++ [(set_attr "type" "")]) + -+(define_insn "*vsx_storedf_update" -+ [(set (mem:DF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0") -+ (match_operand:P 2 "gpc_reg_operand" "r,r"))) -+ (match_operand:DF 3 "gpc_reg_operand" "ws,?wa")) ++(define_insn "*vsx_store_update_" ++ [(set (mem:VSX_U (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0") ++ (match_operand:P 2 "gpc_reg_operand" "r,r"))) ++ (match_operand:VSX_U 3 "gpc_reg_operand" ",?wa")) + (set (match_operand:P 0 "gpc_reg_operand" "=b,b") + (plus:P (match_dup 1) + (match_dup 2)))] -+ "TARGET_BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)" -+ "stxsdux %x3,%0,%2" -+ [(set_attr "type" "vecstore")]) ++ " && TARGET_UPDATE && VECTOR_MEM_VSX_P (mode)" ++ "stxux %x3,%0,%2" ++ [(set_attr "type" "")]) + +;; We may need to have a varient on the pattern for use in the prologue +;; that doesn't depend on TARGET_UPDATE. + + -+;; VSX vector floating point arithmetic instructions ++;; VSX scalar and vector floating point arithmetic instructions +(define_insn "*vsx_add3" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvadd %x0,%x1,%x2" -+ [(set_attr "type" "vecfloat")]) ++ "xadd %x0,%x1,%x2" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "*vsx_sub3" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvsub %x0,%x1,%x2" -+ [(set_attr "type" "vecfloat")]) ++ "xsub %x0,%x1,%x2" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "*vsx_mul3" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvmul %x0,%x1,%x2" -+ [(set_attr "type" "vecfloat")]) ++ "xmul %x0,%x1,%x2" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "*vsx_div3" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvdiv %x0,%x1,%x2" -+ [(set_attr "type" "vecfdiv")]) ++ "xdiv %x0,%x1,%x2" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_fre2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "")] ++(define_insn "vsx_tdiv3" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",wa")] ++ UNSPEC_VSX_XVTDIV))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xtdiv %x0,%x1,%x2" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_insn "vsx_fre2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] + UNSPEC_FRES))] -+ "flag_finite_math_only && VECTOR_UNIT_VSX_P (mode)" -+ "xvre %x0,%x1" -+ [(set_attr "type" "fp")]) ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xre %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "*vsx_neg2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvneg %x0,%x1" -+ [(set_attr "type" "vecfloat")]) ++ "xneg %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "*vsx_abs2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvabs %x0,%x1" -+ [(set_attr "type" "vecfloat")]) ++ "xabs %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_nabs2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (neg:VSX_F -+ (abs:VSX_F -+ (match_operand:VSX_F 1 "vsx_register_operand" ""))))] ++(define_insn "vsx_nabs2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (neg:VSX_B ++ (abs:VSX_B ++ (match_operand:VSX_B 1 "vsx_register_operand" ",wa"))))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvnabs %x0,%x1" -+ [(set_attr "type" "vecfloat")]) ++ "xnabs %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_smax3" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++(define_insn "vsx_smax3" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvmax %x0,%x1,%x2" -+ [(set_attr "type" "veccmp")]) ++ "xmax %x0,%x1,%x2" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "*vsx_smin3" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvmin %x0,%x1,%x2" -+ [(set_attr "type" "veccmp")]) ++ "xmin %x0,%x1,%x2" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "*vsx_sqrt2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvsqrt %x0,%x1" -+ [(set_attr "type" "vecfdiv")]) ++ "xsqrt %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_insn "vsx_rsqrte2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] ++ UNSPEC_VSX_XVRSQRTE))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xrsqrte %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_insn "vsx_tsqrt2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] ++ UNSPEC_VSX_XVTSQRT))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xtsqrt %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +;; Fused vector multiply/add instructions -+(define_insn "*vsx_fmadd4" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,") -+ (plus:VSX_F -+ (mult:VSX_F -+ (match_operand:VSX_F 1 "vsx_register_operand" "%,") -+ (match_operand:VSX_F 2 "vsx_register_operand" ",0")) -+ (match_operand:VSX_F 3 "gpc_reg_operand" "0,")))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD" -+ "@ -+ xvmadda %x0,%x1,%x2 -+ xvmaddm %x0,%x1,%x3" -+ [(set_attr "type" "vecfloat")]) + -+(define_insn "*vsx_fmsub4" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,") -+ (minus:VSX_F -+ (mult:VSX_F -+ (match_operand:VSX_F 1 "vsx_register_operand" "%,") -+ (match_operand:VSX_F 2 "vsx_register_operand" ",0")) -+ (match_operand:VSX_F 3 "vsx_register_operand" "0,")))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD" -+ "@ -+ xvmsuba %x0,%x1,%x2 -+ xvmsubm %x0,%x1,%x3" -+ [(set_attr "type" "vecfloat")]) ++;; Note we have a pattern for the multiply/add operations that uses unspec and ++;; does not check -mfused-madd to allow users to use these ops when they know ++;; they want the fused multiply/add. + -+(define_insn "*vsx_fnmadd4_1" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,") -+ (neg:VSX_F -+ (plus:VSX_F -+ (mult:VSX_F -+ (match_operand:VSX_F 1 "vsx_register_operand" "%,") -+ (match_operand:VSX_F 2 "vsx_register_operand" ",0")) -+ (match_operand:VSX_F 3 "vsx_register_operand" "0,"))))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD ++(define_expand "vsx_fmadd4" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "") ++ (plus:VSX_B ++ (mult:VSX_B ++ (match_operand:VSX_B 1 "vsx_register_operand" "") ++ (match_operand:VSX_B 2 "vsx_register_operand" "")) ++ (match_operand:VSX_B 3 "vsx_register_operand" "")))] ++ "VECTOR_UNIT_VSX_P (mode)" ++{ ++ if (!TARGET_FUSED_MADD) ++ { ++ emit_insn (gen_vsx_fmadd4_2 (operands[0], operands[1], operands[2], ++ operands[3])); ++ DONE; ++ } ++}) ++ ++(define_insn "*vsx_fmadd4_1" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (plus:VSX_B ++ (mult:VSX_B ++ (match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0")) ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")))] ++ "VECTOR_UNIT_VSX_P (mode) && TARGET_FUSED_MADD" ++ "@ ++ xmadda %x0,%x1,%x2 ++ xmaddm %x0,%x1,%x3 ++ xmadda %x0,%x1,%x2 ++ xmaddm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_insn "vsx_fmadd4_2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0") ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")] ++ UNSPEC_VSX_XVMADD))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "@ ++ xmadda %x0,%x1,%x2 ++ xmaddm %x0,%x1,%x3 ++ xmadda %x0,%x1,%x2 ++ xmaddm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_expand "vsx_fmsub4" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "") ++ (minus:VSX_B ++ (mult:VSX_B ++ (match_operand:VSX_B 1 "vsx_register_operand" "") ++ (match_operand:VSX_B 2 "vsx_register_operand" "")) ++ (match_operand:VSX_B 3 "vsx_register_operand" "")))] ++ "VECTOR_UNIT_VSX_P (mode)" ++{ ++ if (!TARGET_FUSED_MADD) ++ { ++ emit_insn (gen_vsx_fmsub4_2 (operands[0], operands[1], operands[2], ++ operands[3])); ++ DONE; ++ } ++}) ++ ++(define_insn "*vsx_fmsub4_1" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (minus:VSX_B ++ (mult:VSX_B ++ (match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0")) ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")))] ++ "VECTOR_UNIT_VSX_P (mode) && TARGET_FUSED_MADD" ++ "@ ++ xmsuba %x0,%x1,%x2 ++ xmsubm %x0,%x1,%x3 ++ xmsuba %x0,%x1,%x2 ++ xmsubm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_insn "vsx_fmsub4_2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0") ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")] ++ UNSPEC_VSX_XVMSUB))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "@ ++ xmsuba %x0,%x1,%x2 ++ xmsubm %x0,%x1,%x3 ++ xmsuba %x0,%x1,%x2 ++ xmsubm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_expand "vsx_fnmadd4" ++ [(match_operand:VSX_B 0 "vsx_register_operand" "") ++ (match_operand:VSX_B 1 "vsx_register_operand" "") ++ (match_operand:VSX_B 2 "vsx_register_operand" "") ++ (match_operand:VSX_B 3 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (mode)" ++{ ++ if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode)) ++ { ++ emit_insn (gen_vsx_fnmadd4_1 (operands[0], operands[1], ++ operands[2], operands[3])); ++ DONE; ++ } ++ else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode)) ++ { ++ emit_insn (gen_vsx_fnmadd4_2 (operands[0], operands[1], ++ operands[2], operands[3])); ++ DONE; ++ } ++ else ++ { ++ emit_insn (gen_vsx_fnmadd4_3 (operands[0], operands[1], ++ operands[2], operands[3])); ++ DONE; ++ } ++}) ++ ++(define_insn "vsx_fnmadd4_1" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (neg:VSX_B ++ (plus:VSX_B ++ (mult:VSX_B ++ (match_operand:VSX_B 1 "vsx_register_operand" ",,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0")) ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa"))))] ++ "VECTOR_UNIT_VSX_P (mode) && TARGET_FUSED_MADD + && HONOR_SIGNED_ZEROS (DFmode)" + "@ -+ xvnmadda %x0,%x1,%x2 -+ xvnmaddm %x0,%x1,%x3" -+ [(set_attr "type" "vecfloat")]) ++ xnmadda %x0,%x1,%x2 ++ xnmaddm %x0,%x1,%x3 ++ xnmadda %x0,%x1,%x2 ++ xnmaddm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_fnmadd4_2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,") -+ (minus:VSX_F -+ (mult:VSX_F -+ (neg:VSX_F -+ (match_operand:VSX_F 1 "gpc_reg_operand" "%,")) -+ (match_operand:VSX_F 2 "gpc_reg_operand" ",0")) -+ (match_operand:VSX_F 3 "vsx_register_operand" "0,")))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD ++(define_insn "vsx_fnmadd4_2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (minus:VSX_B ++ (mult:VSX_B ++ (neg:VSX_B ++ (match_operand:VSX_B 1 "gpc_reg_operand" ",,wa,wa")) ++ (match_operand:VSX_B 2 "gpc_reg_operand" ",0,wa,0")) ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")))] ++ "VECTOR_UNIT_VSX_P (mode) && TARGET_FUSED_MADD + && !HONOR_SIGNED_ZEROS (DFmode)" + "@ -+ xvnmadda %x0,%x1,%x2 -+ xvnmaddm %x0,%x1,%x3" -+ [(set_attr "type" "vecfloat")]) ++ xnmadda %x0,%x1,%x2 ++ xnmaddm %x0,%x1,%x3 ++ xnmadda %x0,%x1,%x2 ++ xnmaddm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_fnmsub4_1" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,") -+ (neg:VSX_F -+ (minus:VSX_F -+ (mult:VSX_F -+ (match_operand:VSX_F 1 "vsx_register_operand" "%,") -+ (match_operand:VSX_F 2 "vsx_register_operand" ",0")) -+ (match_operand:VSX_F 3 "vsx_register_operand" "0,"))))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD ++(define_insn "vsx_fnmadd4_3" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0") ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")] ++ UNSPEC_VSX_XVNMADD))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "@ ++ xnmadda %x0,%x1,%x2 ++ xnmaddm %x0,%x1,%x3 ++ xnmadda %x0,%x1,%x2 ++ xnmaddm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++(define_expand "vsx_fnmsub4" ++ [(match_operand:VSX_B 0 "vsx_register_operand" "") ++ (match_operand:VSX_B 1 "vsx_register_operand" "") ++ (match_operand:VSX_B 2 "vsx_register_operand" "") ++ (match_operand:VSX_B 3 "vsx_register_operand" "")] ++ "VECTOR_UNIT_VSX_P (mode)" ++{ ++ if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode)) ++ { ++ emit_insn (gen_vsx_fnmsub4_1 (operands[0], operands[1], ++ operands[2], operands[3])); ++ DONE; ++ } ++ else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode)) ++ { ++ emit_insn (gen_vsx_fnmsub4_2 (operands[0], operands[1], ++ operands[2], operands[3])); ++ DONE; ++ } ++ else ++ { ++ emit_insn (gen_vsx_fnmsub4_3 (operands[0], operands[1], ++ operands[2], operands[3])); ++ DONE; ++ } ++}) ++ ++(define_insn "vsx_fnmsub4_1" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (neg:VSX_B ++ (minus:VSX_B ++ (mult:VSX_B ++ (match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0")) ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa"))))] ++ "VECTOR_UNIT_VSX_P (mode) && TARGET_FUSED_MADD + && HONOR_SIGNED_ZEROS (DFmode)" + "@ -+ xvnmsuba %x0,%x1,%x2 -+ xvnmsubm %x0,%x1,%x3" -+ [(set_attr "type" "vecfloat")]) ++ xnmsuba %x0,%x1,%x2 ++ xnmsubm %x0,%x1,%x3 ++ xnmsuba %x0,%x1,%x2 ++ xnmsubm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_fnmsub4_2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,") -+ (minus:VSX_F -+ (match_operand:VSX_F 3 "vsx_register_operand" "0,") -+ (mult:VSX_F -+ (match_operand:VSX_F 1 "vsx_register_operand" "%,") -+ (match_operand:VSX_F 2 "vsx_register_operand" ",0"))))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD ++(define_insn "vsx_fnmsub4_2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (minus:VSX_B ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa") ++ (mult:VSX_B ++ (match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0"))))] ++ "VECTOR_UNIT_VSX_P (mode) && TARGET_FUSED_MADD + && !HONOR_SIGNED_ZEROS (DFmode)" + "@ -+ xvnmsuba %x0,%x1,%x2 -+ xvnmsubm %x0,%x1,%x3" -+ [(set_attr "type" "vecfloat")]) ++ xnmsuba %x0,%x1,%x2 ++ xnmsubm %x0,%x1,%x3 ++ xnmsuba %x0,%x1,%x2 ++ xnmsubm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+;; Vector conditional expressions -+(define_insn "*vsx_eq" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++(define_insn "vsx_fnmsub4_3" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,,?wa,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%,,wa,wa") ++ (match_operand:VSX_B 2 "vsx_register_operand" ",0,wa,0") ++ (match_operand:VSX_B 3 "vsx_register_operand" "0,,0,wa")] ++ UNSPEC_VSX_XVNMSUB))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "@ ++ xnmsuba %x0,%x1,%x2 ++ xnmsubm %x0,%x1,%x3 ++ xnmsuba %x0,%x1,%x2 ++ xnmsubm %x0,%x1,%x3" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) ++ ++;; Vector conditional expressions (no scalar version for these instructions) ++(define_insn "vsx_eq" ++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,?wa") ++ (eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_F 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" + "xvcmpeq %x0,%x1,%x2" -+ [(set_attr "type" "veccmp")]) ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_gt" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++(define_insn "vsx_gt" ++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,?wa") ++ (gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_F 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" + "xvcmpgt %x0,%x1,%x2" -+ [(set_attr "type" "veccmp")]) ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "*vsx_ge" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "") -+ (match_operand:VSX_F 2 "vsx_register_operand" "")))] ++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,?wa") ++ (ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" ",wa") ++ (match_operand:VSX_F 2 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" + "xvcmpge %x0,%x1,%x2" -+ [(set_attr "type" "veccmp")]) ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +(define_insn "vsx_vsel" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" "") ++ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,?wa") ++ (if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" ",wa") + (const_int 0)) -+ (match_operand:VSX_F 2 "vsx_register_operand" "") -+ (match_operand:VSX_F 3 "vsx_register_operand" "")))] ++ (match_operand:VSX_F 2 "vsx_register_operand" ",wa") ++ (match_operand:VSX_F 3 "vsx_register_operand" ",wa")))] + "VECTOR_UNIT_VSX_P (mode)" + "xxsel %x0,%x3,%x2,%x1" + [(set_attr "type" "vecperm")]) + +;; Copy sign -+(define_insn "*vsx_copysign3" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (if_then_else:VSX_F -+ (ge:VSX_F (match_operand:VSX_F 2 "vsx_register_operand" "") ++(define_insn "vsx_copysign3" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (if_then_else:VSX_B ++ (ge:VSX_B (match_operand:VSX_B 2 "vsx_register_operand" ",wa") + (const_int 0)) -+ (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "")) -+ (neg:VSX_F (abs:VSX_F (match_dup 1)))))] ++ (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa")) ++ (neg:VSX_B (abs:VSX_B (match_dup 1)))))] + "VECTOR_UNIT_VSX_P (mode)" -+ "xvcpsgn %x0,%x2,%x1" -+ [(set_attr "type" "vecsimple")]) -+ -+(define_insn "*vsx_ftrunc2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "")))] -+ "VECTOR_UNIT_VSX_P (mode)" -+ "xvrpiz %x0,%x1" -+ [(set_attr "type" "vecperm")]) -+ -+(define_insn "*vsx_float2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (float:VSX_F (match_operand: 1 "vsx_register_operand" "")))] -+ "VECTOR_UNIT_VSX_P (mode)" -+ "xvcvsx %x0,%x1" -+ [(set_attr "type" "vecfloat")]) -+ -+(define_insn "*vsx_floatuns2" -+ [(set (match_operand:VSX_F 0 "vsx_register_operand" "=") -+ (unsigned_float:VSX_F (match_operand: 1 "vsx_register_operand" "")))] -+ "VECTOR_UNIT_VSX_P (mode)" -+ "xvcvux %x0,%x1" -+ [(set_attr "type" "vecfloat")]) -+ -+(define_insn "*vsx_fix_trunc2" -+ [(set (match_operand: 0 "vsx_register_operand" "=") -+ (fix: (match_operand:VSX_F 1 "vsx_register_operand" "")))] -+ "VECTOR_UNIT_VSX_P (mode)" -+ "xvcvsxs %x0,%x1" -+ [(set_attr "type" "vecfloat")]) -+ -+(define_insn "*vsx_fixuns_trunc2" -+ [(set (match_operand: 0 "vsx_register_operand" "=") -+ (unsigned_fix: (match_operand:VSX_F 1 "vsx_register_operand" "")))] -+ "VECTOR_UNIT_VSX_P (mode)" -+ "xvcvuxs %x0,%x1" -+ [(set_attr "type" "vecfloat")]) -+ -+ -+;; VSX scalar double precision floating point operations -+(define_insn"*vsx_adddf3" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (plus:DF (match_operand:DF 1 "vsx_register_operand" "ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsadddp %x0,%x1,%x2" -+ [(set_attr "type" "fp") -+ (set_attr "fp_type" "fp_addsub_d")]) -+ -+(define_insn"*vsx_subdf3" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (minus:DF (match_operand:DF 1 "vsx_register_operand" "ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xssubdp %x0,%x1,%x2" -+ [(set_attr "type" "fp") -+ (set_attr "fp_type" "fp_addsub_d")]) -+ -+(define_insn"*vsx_muldf3" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (mult:DF (match_operand:DF 1 "vsx_register_operand" "ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsmuldp %x0,%x1,%x2" -+ [(set_attr "type" "dmul") -+ (set_attr "fp_type" "fp_mul_d")]) -+ -+(define_insn"*vsx_divdf3" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (div:DF (match_operand:DF 1 "vsx_register_operand" "ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsdivdp %x0,%x1,%x2" -+ [(set_attr "type" "ddiv")]) -+ -+(define_insn "*vsx_fredf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")] -+ UNSPEC_FRES))] -+ "flag_finite_math_only && VECTOR_UNIT_VSX_P (DFmode)" -+ "xsredp %x0,%x1" -+ [(set_attr "type" "fp")]) -+ -+(define_insn "*vsx_sqrtdf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (sqrt:DF (match_operand:DF 1 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xssqrtdp %x0,%x1" -+ [(set_attr "type" "dsqrt")]) -+ -+(define_insn"*vsx_negdf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (neg:DF (match_operand:DF 1 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsnegdp %x0,%x1" -+ [(set_attr "type" "fp")]) -+ -+(define_insn"vsx_absdf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsabsdp %x0,%x1" -+ [(set_attr "type" "fp")]) -+ -+(define_insn"*vsx_nabsdf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (neg:DF (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsnabsdp %x0,%x1" -+ [(set_attr "type" "fp")]) -+ -+(define_insn "*vsx_smaxdf3" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (smax:DF (match_operand:DF 1 "vsx_register_operand" "ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsmaxdp %x0,%x1,%x2" -+ [(set_attr "type" "fp")]) -+ -+ -+(define_insn "*vsx_smindf3" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (smin:DF (match_operand:DF 1 "vsx_register_operand" "ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsmindp %x0,%x1,%x2" -+ [(set_attr "type" "fp")]) -+ -+;; Fused vector multiply/add instructions -+(define_insn "*vsx_fmadddf4" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws") -+ (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws,0")) -+ (match_operand:DF 3 "gpc_reg_operand" "0,ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD" -+ "@ -+ xsmaddadp %x0,%x1,%x2 -+ xsmaddmdp %x0,%x1,%x3" -+ [(set_attr "type" "dmul") -+ (set_attr "fp_type" "fp_maddsub_d")]) -+ -+(define_insn "*vsx_fmsubdf4" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws") -+ (minus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws,0")) -+ (match_operand:DF 3 "vsx_register_operand" "0,ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD" -+ "@ -+ xsmsubadp %x0,%x1,%x2 -+ xsmsubmdp %x0,%x1,%x3" -+ [(set_attr "type" "dmul") -+ (set_attr "fp_type" "fp_maddsub_d")]) -+ -+(define_insn "*vsx_fnmadddf4_1" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws") -+ (neg:DF -+ (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws,0")) -+ (match_operand:DF 3 "vsx_register_operand" "0,ws"))))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD -+ && HONOR_SIGNED_ZEROS (DFmode)" -+ "@ -+ xsnmaddadp %x0,%x1,%x2 -+ xsnmaddmdp %x0,%x1,%x3" -+ [(set_attr "type" "dmul") -+ (set_attr "fp_type" "fp_maddsub_d")]) -+ -+(define_insn "*vsx_fnmadddf4_2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws") -+ (minus:DF (mult:DF (neg:DF -+ (match_operand:DF 1 "gpc_reg_operand" "%ws,ws")) -+ (match_operand:DF 2 "gpc_reg_operand" "ws,0")) -+ (match_operand:DF 3 "vsx_register_operand" "0,ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD -+ && !HONOR_SIGNED_ZEROS (DFmode)" -+ "@ -+ xsnmaddadp %x0,%x1,%x2 -+ xsnmaddmdp %x0,%x1,%x3" -+ [(set_attr "type" "dmul") -+ (set_attr "fp_type" "fp_maddsub_d")]) -+ -+(define_insn "*vsx_fnmsubdf4_1" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws") -+ (neg:DF -+ (minus:DF -+ (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws,0")) -+ (match_operand:DF 3 "vsx_register_operand" "0,ws"))))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD -+ && HONOR_SIGNED_ZEROS (DFmode)" -+ "@ -+ xsnmsubadp %x0,%x1,%x2 -+ xsnmsubmdp %x0,%x1,%x3" -+ [(set_attr "type" "dmul") -+ (set_attr "fp_type" "fp_maddsub_d")]) -+ -+(define_insn "*vsx_fnmsubdf4_2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws") -+ (minus:DF -+ (match_operand:DF 3 "vsx_register_operand" "0,ws") -+ (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws") -+ (match_operand:DF 2 "vsx_register_operand" "ws,0"))))] -+ "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD -+ && !HONOR_SIGNED_ZEROS (DFmode)" -+ "@ -+ xsnmsubadp %x0,%x1,%x2 -+ xsnmsubmdp %x0,%x1,%x3" -+ [(set_attr "type" "dmul") -+ (set_attr "fp_type" "fp_maddsub_d")]) ++ "xcpsgn %x0,%x2,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + +;; For the conversions, limit the register class for the integer value to be -+;; the fprs. For the unsigned tests, there isn't a generic double -> unsigned -+;; conversion in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against -+;; VSX. ++;; the fprs because we don't want to add the altivec registers to movdi/movsi. ++;; For the unsigned tests, there isn't a generic double -> unsigned conversion ++;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX. ++(define_insn "vsx_ftrunc2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" ",wa")))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xrpiz %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_floatdidf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xscvsxddp %x0,%x1" -+ [(set_attr "type" "fp")]) ++(define_insn "vsx_float2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (float:VSX_B (match_operand: 1 "vsx_register_operand" ",")))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xcvsx %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_floatunsdidf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (unsigned_float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))] -+ "TARGET_HARD_FLOAT && TARGET_VSX" -+ "xscvuxddp %x0,%x1" -+ [(set_attr "type" "fp")]) ++(define_insn "vsx_floatuns2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unsigned_float:VSX_B (match_operand: 1 "vsx_register_operand" ",")))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xcvux %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_fix_truncdfdi2" -+ [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r") -+ (fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xscvdpsxds %x0,%x1" -+ [(set_attr "type" "fp")]) ++(define_insn "vsx_fix_trunc2" ++ [(set (match_operand: 0 "vsx_register_operand" "=,?") ++ (fix: (match_operand:VSX_B 1 "vsx_register_operand" ",wa")))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xcvsxs %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_fixuns_truncdfdi2" -+ [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r") -+ (unsigned_fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))] -+ "TARGET_HARD_FLOAT && TARGET_VSX" -+ "xscvdpuxds %x0,%x1" -+ [(set_attr "type" "fp")]) ++(define_insn "vsx_fixuns_trunc2" ++ [(set (match_operand: 0 "vsx_register_operand" "=,?") ++ (unsigned_fix: (match_operand:VSX_B 1 "vsx_register_operand" ",wa")))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xcvuxs %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_btruncdf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")] -+ UNSPEC_FRIZ))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsrdpiz %x0,%x1" -+ [(set_attr "type" "fp")]) ++;; Math rounding functions ++(define_insn "vsx_btrunc2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] ++ UNSPEC_FRIZ))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xriz %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_floordf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")] -+ UNSPEC_FRIM))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsrdpim %x0,%x1" -+ [(set_attr "type" "fp")]) ++(define_insn "vsx_floor2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] ++ UNSPEC_FRIM))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xrim %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "*vsx_ceildf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")] -+ UNSPEC_FRIP))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsrdpip %x0,%x1" -+ [(set_attr "type" "fp")]) ++(define_insn "vsx_ceil2" ++ [(set (match_operand:VSX_B 0 "vsx_register_operand" "=,?wa") ++ (unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" ",wa")] ++ UNSPEC_FRIP))] ++ "VECTOR_UNIT_VSX_P (mode)" ++ "xrip %x0,%x1" ++ [(set_attr "type" "") ++ (set_attr "fp_type" "")]) + -+(define_insn "vsx_copysigndf3" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (if_then_else:DF (ge:DF (match_operand:DF 2 "vsx_register_operand" "ws") -+ (const_int 0)) -+ (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws")) -+ (neg:DF (abs:DF (match_dup 1)))))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xscpsgndp %x0,%x2,%x1" -+ [(set_attr "type" "fp")]) ++ ++;; VSX convert to/from double vector + -+(define_insn "*vsx_ftruncdf2" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (fix:DF (match_operand:DF 1 "register_operand" "ws")))] -+ "VECTOR_UNIT_VSX_P (DFmode)" -+ "xsrdppiz %x0,%x1" ++;; Convert from 64-bit to 32-bit types ++;; Note, favor the Altivec registers since the usual use of these instructions ++;; is in vector converts and we need to use the Altivec vperm instruction. ++ ++(define_insn "vsx_xvcvdpsp" ++ [(set (match_operand:V4SF 0 "vsx_register_operand" "=v,?wa") ++ (unspec:V4SF [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")] ++ UNSPEC_VSX_XVCVDPSP))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvdpsp %x0,%x1" ++ [(set_attr "type" "vecfloat")]) ++ ++(define_insn "vsx_xvcvdpsxws" ++ [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa") ++ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")] ++ UNSPEC_VSX_XVCVDPSXWS))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvdpsxws %x0,%x1" ++ [(set_attr "type" "vecfloat")]) ++ ++(define_insn "vsx_xvcvdpuxws" ++ [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa") ++ (unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")] ++ UNSPEC_VSX_XVCVDPUXWS))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvdpuxws %x0,%x1" ++ [(set_attr "type" "vecfloat")]) ++ ++;; Convert from 32-bit to 64-bit types ++(define_insn "vsx_xvcvspdp" ++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") ++ (unspec:V2DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")] ++ UNSPEC_VSX_XVCVSPDP))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvspdp %x0,%x1" ++ [(set_attr "type" "vecfloat")]) ++ ++(define_insn "vsx_xvcvsxwdp" ++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") ++ (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")] ++ UNSPEC_VSX_XVCVSXWDP))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvsxwdp %x0,%x1" ++ [(set_attr "type" "vecfloat")]) ++ ++(define_insn "vsx_xvcvuxwdp" ++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") ++ (unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")] ++ UNSPEC_VSX_XVCVUXWDP))] ++ "VECTOR_UNIT_VSX_P (V2DFmode)" ++ "xvcvuxwdp %x0,%x1" + [(set_attr "type" "vecfloat")]) + + @@ -6450,8 +8350,8 @@ testsuite/ +(define_insn "vsx_concat_v2df" + [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") + (unspec:V2DF -+ [(match_operand:DF 1 "vsx_register_operand" "f,wa") -+ (match_operand:DF 2 "vsx_register_operand" "f,wa")] ++ [(match_operand:DF 1 "vsx_register_operand" "ws,wa") ++ (match_operand:DF 2 "vsx_register_operand" "ws,wa")] + UNSPEC_VSX_CONCAT_V2DF))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xxpermdi %x0,%x1,%x2,0" @@ -6459,32 +8359,37 @@ testsuite/ + +;; Set a double into one element +(define_insn "vsx_set_v2df" -+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd") ++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa") + (vec_merge:V2DF -+ (match_operand:V2DF 1 "vsx_register_operand" "wd") -+ (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws")) -+ (match_operand:QI 3 "u5bit_cint_operand" "i")))] ++ (match_operand:V2DF 1 "vsx_register_operand" "wd,wa") ++ (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws,f")) ++ (match_operand:QI 3 "u5bit_cint_operand" "i,i")))] + "VECTOR_UNIT_VSX_P (V2DFmode)" +{ -+ operands[3] = GEN_INT (INTVAL (operands[3]) & 1); -+ return \"xxpermdi %x0,%x1,%x2,%3\"; ++ if (INTVAL (operands[3]) == 0) ++ return \"xxpermdi %x0,%x1,%x2,1\"; ++ else if (INTVAL (operands[3]) == 1) ++ return \"xxpermdi %x0,%x2,%x1,0\"; ++ else ++ gcc_unreachable (); +} + [(set_attr "type" "vecperm")]) + +;; Extract a DF element from V2DF +(define_insn "vsx_extract_v2df" -+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws") -+ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd") ++ [(set (match_operand:DF 0 "vsx_register_operand" "=ws,f,?wa") ++ (vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd,wd,wa") + (parallel -+ [(match_operand:QI 2 "u5bit_cint_operand" "i")])))] ++ [(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))] + "VECTOR_UNIT_VSX_P (V2DFmode)" +{ -+ operands[3] = GEN_INT (INTVAL (operands[2]) & 1); ++ gcc_assert (UINTVAL (operands[2]) <= 1); ++ operands[3] = GEN_INT (INTVAL (operands[2]) << 1); + return \"xxpermdi %x0,%x1,%x1,%3\"; +} + [(set_attr "type" "vecperm")]) + -+;; General V2DF permute ++;; General V2DF permute, extract_{high,low,even,odd} +(define_insn "vsx_xxpermdi" + [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd") + (vec_concat:V2DF @@ -6496,6 +8401,7 @@ testsuite/ + [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))] + "VECTOR_UNIT_VSX_P (V2DFmode)" +{ ++ gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1)); + operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1) + | (INTVAL (operands[4]) & 1)); + return \"xxpermdi %x0,%x1,%x3,%5\"; @@ -6504,71 +8410,70 @@ testsuite/ + +;; V2DF splat +(define_insn "vsx_splatv2df" -+ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd") ++ [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa") + (vec_duplicate:V2DF -+ (match_operand:DF 1 "input_operand" "ws,Z")))] ++ (match_operand:DF 1 "input_operand" "ws,f,Z,wa,wa,Z")))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "@ + xxpermdi %x0,%x1,%x1,0 ++ xxpermdi %x0,%x1,%x1,0 ++ lxvdsx %x0,%y1 ++ xxpermdi %x0,%x1,%x1,0 ++ xxpermdi %x0,%x1,%x1,0 + lxvdsx %x0,%y1" -+ [(set_attr "type" "vecperm,vecload")]) ++ [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")]) + +;; V4SF splat +(define_insn "*vsx_xxspltw" -+ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf") ++ [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,?wa") + (vec_duplicate:V4SF -+ (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf") ++ (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf,wa") + (parallel -+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))] ++ [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))] + "VECTOR_UNIT_VSX_P (V4SFmode)" + "xxspltw %x0,%x1,%2" + [(set_attr "type" "vecperm")]) + +;; V4SF interleave -+(define_insn "*vsx_xxmrghw" -+ [(set (match_operand:V4SF 0 "register_operand" "=v") -+ (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v") -+ (parallel [(const_int 0) -+ (const_int 2) -+ (const_int 1) -+ (const_int 3)])) -+ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v") -+ (parallel [(const_int 2) -+ (const_int 0) -+ (const_int 3) -+ (const_int 1)])) -+ (const_int 5)))] -+ "VECTOR_UNIT_VSX_P (V4SFmode)" -+ "xxmrghw %x0,%x1,%x2" -+ [(set_attr "type" "vecperm")]) -+ -+(define_insn "*vsx_xxmrglw" -+ [(set (match_operand:V4SF 0 "register_operand" "=v") ++(define_insn "vsx_xxmrghw" ++ [(set (match_operand:V4SF 0 "register_operand" "=wf,?wa") + (vec_merge:V4SF -+ (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v") -+ (parallel [(const_int 2) -+ (const_int 0) -+ (const_int 3) -+ (const_int 1)])) -+ (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v") ++ (vec_select:V4SF (match_operand:V4SF 1 "vsx_register_operand" "wf,wa") + (parallel [(const_int 0) + (const_int 2) + (const_int 1) + (const_int 3)])) ++ (vec_select:V4SF (match_operand:V4SF 2 "vsx_register_operand" "wf,wa") ++ (parallel [(const_int 2) ++ (const_int 0) ++ (const_int 3) ++ (const_int 1)])) ++ (const_int 5)))] ++ "VECTOR_UNIT_VSX_P (V4SFmode)" ++ "xxmrghw %x0,%x1,%x2" ++ [(set_attr "type" "vecperm")]) ++ ++(define_insn "vsx_xxmrglw" ++ [(set (match_operand:V4SF 0 "register_operand" "=wf,?wa") ++ (vec_merge:V4SF ++ (vec_select:V4SF ++ (match_operand:V4SF 1 "register_operand" "wf,wa") ++ (parallel [(const_int 2) ++ (const_int 0) ++ (const_int 3) ++ (const_int 1)])) ++ (vec_select:V4SF ++ (match_operand:V4SF 2 "register_operand" "wf,?wa") ++ (parallel [(const_int 0) ++ (const_int 2) ++ (const_int 1) ++ (const_int 3)])) + (const_int 5)))] + "VECTOR_UNIT_VSX_P (V4SFmode)" + "xxmrglw %x0,%x1,%x2" + [(set_attr "type" "vecperm")]) ---- gcc/config/rs6000/rs6000.h (.../trunk) (revision 144557) -+++ gcc/config/rs6000/rs6000.h (.../branches/ibm/power7-meissner) (revision 144730) -@@ -1,6 +1,6 @@ - /* Definitions of target machine for GNU compiler, for IBM RS/6000. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -- 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 -+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. - Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu) - +--- gcc/config/rs6000/rs6000.h (.../trunk) (revision 145777) ++++ gcc/config/rs6000/rs6000.h (.../branches/ibm/power7-meissner) (revision 146027) @@ -72,14 +72,16 @@ #define ASM_CPU_POWER6_SPEC "-mpower4 -maltivec" #endif @@ -6616,22 +8521,25 @@ testsuite/ #endif #ifndef CC1_CPU_SPEC -@@ -240,6 +248,14 @@ extern const char *host_detect_local_cpu - #define TARGET_DFP 0 +@@ -233,11 +241,12 @@ extern const char *host_detect_local_cpu + #define TARGET_MFPGPR 0 #endif +-/* Define TARGET_DFP if the target assembler does not support decimal +- floating point instructions. */ +-#ifndef HAVE_AS_DFP +-#undef TARGET_DFP +-#define TARGET_DFP 0 +/* Define TARGET_POPCNTD if the target assembler does not support the + popcount word and double word instructions. */ + +#ifndef HAVE_AS_POPCNTD +#undef TARGET_POPCNTD +#define TARGET_POPCNTD 0 -+#endif -+ - #ifndef TARGET_SECURE_PLT - #define TARGET_SECURE_PLT 0 #endif -@@ -295,6 +311,7 @@ enum processor_type + + #ifndef TARGET_SECURE_PLT +@@ -295,6 +304,7 @@ enum processor_type PROCESSOR_POWER4, PROCESSOR_POWER5, PROCESSOR_POWER6, @@ -6639,21 +8547,23 @@ testsuite/ PROCESSOR_CELL }; -@@ -388,9 +405,13 @@ extern struct rs6000_cpu_select rs6000_s +@@ -388,9 +398,15 @@ extern struct rs6000_cpu_select rs6000_s extern const char *rs6000_debug_name; /* Name for -mdebug-xxxx option */ extern int rs6000_debug_stack; /* debug stack applications */ extern int rs6000_debug_arg; /* debug argument handling */ +extern int rs6000_debug_reg; /* debug register handling */ +extern int rs6000_debug_addr; /* debug memory addressing */ ++extern int rs6000_debug_cost; /* debug rtx_costs */ #define TARGET_DEBUG_STACK rs6000_debug_stack #define TARGET_DEBUG_ARG rs6000_debug_arg +#define TARGET_DEBUG_REG rs6000_debug_reg +#define TARGET_DEBUG_ADDR rs6000_debug_addr ++#define TARGET_DEBUG_COST rs6000_debug_cost extern const char *rs6000_traceback_name; /* Type of traceback table. */ -@@ -401,13 +422,65 @@ extern int rs6000_ieeequad; +@@ -401,13 +417,65 @@ extern int rs6000_ieeequad; extern int rs6000_altivec_abi; extern int rs6000_spe_abi; extern int rs6000_spe; @@ -6720,7 +8630,7 @@ testsuite/ /* Alignment options for fields in structures for sub-targets following AIX-like ABI. ALIGN_POWER word-aligns FP doubles (default AIX ABI). -@@ -432,7 +505,7 @@ extern int rs6000_xilinx_fpu; +@@ -432,7 +500,7 @@ extern int rs6000_xilinx_fpu; #define TARGET_SPE_ABI 0 #define TARGET_SPE 0 #define TARGET_E500 0 @@ -6729,7 +8639,7 @@ testsuite/ #define TARGET_FPRS 1 #define TARGET_E500_SINGLE 0 #define TARGET_E500_DOUBLE 0 -@@ -530,6 +603,7 @@ extern int rs6000_xilinx_fpu; +@@ -530,6 +598,7 @@ extern int rs6000_xilinx_fpu; #endif #define UNITS_PER_FP_WORD 8 #define UNITS_PER_ALTIVEC_WORD 16 @@ -6737,7 +8647,7 @@ testsuite/ #define UNITS_PER_SPE_WORD 8 #define UNITS_PER_PAIRED_WORD 8 -@@ -600,8 +674,9 @@ extern int rs6000_xilinx_fpu; +@@ -600,8 +669,9 @@ extern int rs6000_xilinx_fpu; #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64) /* Boundary (in *bits*) on which stack pointer should be aligned. */ @@ -6749,7 +8659,7 @@ testsuite/ /* Allocation boundary (in *bits*) for the code of a function. */ #define FUNCTION_BOUNDARY 32 -@@ -613,10 +688,11 @@ extern int rs6000_xilinx_fpu; +@@ -613,10 +683,11 @@ extern int rs6000_xilinx_fpu; local store. TYPE is the data type, and ALIGN is the alignment that the object would ordinarily have. */ #define LOCAL_ALIGNMENT(TYPE, ALIGN) \ @@ -6764,7 +8674,7 @@ testsuite/ && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \ && TREE_CODE (TYPE) == VECTOR_TYPE \ && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN) -@@ -674,15 +750,17 @@ extern int rs6000_xilinx_fpu; +@@ -674,15 +745,17 @@ extern int rs6000_xilinx_fpu; /* Define this macro to be the value 1 if unaligned accesses have a cost many times greater than aligned accesses, for example if they are emulated in a trap handler. */ @@ -6785,7 +8695,7 @@ testsuite/ /* Standard register usage. */ -@@ -909,16 +987,60 @@ extern int rs6000_xilinx_fpu; +@@ -909,16 +982,60 @@ extern int rs6000_xilinx_fpu; /* True if register is an AltiVec register. */ #define ALTIVEC_REGNO_P(N) ((N) >= FIRST_ALTIVEC_REGNO && (N) <= LAST_ALTIVEC_REGNO) @@ -6847,7 +8757,7 @@ testsuite/ #define ALTIVEC_VECTOR_MODE(MODE) \ ((MODE) == V16QImode \ || (MODE) == V8HImode \ -@@ -934,10 +1056,12 @@ extern int rs6000_xilinx_fpu; +@@ -934,10 +1051,12 @@ extern int rs6000_xilinx_fpu; #define PAIRED_VECTOR_MODE(MODE) \ ((MODE) == V2SFmode) @@ -6864,7 +8774,7 @@ testsuite/ /* Value is TRUE if hard register REGNO can hold a value of machine-mode MODE. */ -@@ -965,6 +1089,10 @@ extern int rs6000_xilinx_fpu; +@@ -965,6 +1084,10 @@ extern int rs6000_xilinx_fpu; ? ALTIVEC_VECTOR_MODE (MODE2) \ : ALTIVEC_VECTOR_MODE (MODE2) \ ? ALTIVEC_VECTOR_MODE (MODE1) \ @@ -6875,7 +8785,7 @@ testsuite/ : 1) /* Post-reload, we can't use any new AltiVec registers, as we already -@@ -1056,9 +1184,10 @@ extern int rs6000_xilinx_fpu; +@@ -1056,9 +1179,10 @@ extern int rs6000_xilinx_fpu; For any two classes, it is very desirable that there be another class that represents their union. */ @@ -6889,7 +8799,7 @@ testsuite/ However, r0 is special in that it cannot be used as a base register. So make a class for registers valid as base registers. -@@ -1073,6 +1202,7 @@ enum reg_class +@@ -1073,6 +1197,7 @@ enum reg_class GENERAL_REGS, FLOAT_REGS, ALTIVEC_REGS, @@ -6897,7 +8807,7 @@ testsuite/ VRSAVE_REGS, VSCR_REGS, SPE_ACC_REGS, -@@ -1103,6 +1233,7 @@ enum reg_class +@@ -1103,6 +1228,7 @@ enum reg_class "GENERAL_REGS", \ "FLOAT_REGS", \ "ALTIVEC_REGS", \ @@ -6905,7 +8815,7 @@ testsuite/ "VRSAVE_REGS", \ "VSCR_REGS", \ "SPE_ACC_REGS", \ -@@ -1132,6 +1263,7 @@ enum reg_class +@@ -1132,6 +1258,7 @@ enum reg_class { 0xffffffff, 0x00000000, 0x00000008, 0x00020000 }, /* GENERAL_REGS */ \ { 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FLOAT_REGS */ \ { 0x00000000, 0x00000000, 0xffffe000, 0x00001fff }, /* ALTIVEC_REGS */ \ @@ -6913,25 +8823,43 @@ testsuite/ { 0x00000000, 0x00000000, 0x00000000, 0x00002000 }, /* VRSAVE_REGS */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */ \ { 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */ \ -@@ -1179,8 +1311,8 @@ enum reg_class - : (REGNO) == CR0_REGNO ? CR0_REGS \ - : CR_REGNO_P (REGNO) ? CR_REGS \ - : (REGNO) == MQ_REGNO ? MQ_REGS \ +@@ -1171,29 +1298,29 @@ enum reg_class + reg number REGNO. This could be a conditional expression + or could index an array. */ + +-#define REGNO_REG_CLASS(REGNO) \ +- ((REGNO) == 0 ? GENERAL_REGS \ +- : (REGNO) < 32 ? BASE_REGS \ +- : FP_REGNO_P (REGNO) ? FLOAT_REGS \ +- : ALTIVEC_REGNO_P (REGNO) ? ALTIVEC_REGS \ +- : (REGNO) == CR0_REGNO ? CR0_REGS \ +- : CR_REGNO_P (REGNO) ? CR_REGS \ +- : (REGNO) == MQ_REGNO ? MQ_REGS \ - : (REGNO) == LR_REGNO ? LINK_REGS \ - : (REGNO) == CTR_REGNO ? CTR_REGS \ -+ : (REGNO) == LR_REGNO ? LINK_REGS \ -+ : (REGNO) == CTR_REGNO ? CTR_REGS \ - : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS \ - : (REGNO) == XER_REGNO ? XER_REGS \ - : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS \ -@@ -1190,10 +1322,18 @@ enum reg_class - : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS \ - : NO_REGS) - +- : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS \ +- : (REGNO) == XER_REGNO ? XER_REGS \ +- : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS \ +- : (REGNO) == VSCR_REGNO ? VRSAVE_REGS \ +- : (REGNO) == SPE_ACC_REGNO ? SPE_ACC_REGS \ +- : (REGNO) == SPEFSCR_REGNO ? SPEFSCR_REGS \ +- : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS \ +- : NO_REGS) ++extern enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER]; ++ ++#if ENABLE_CHECKING ++#define REGNO_REG_CLASS(REGNO) \ ++ (gcc_assert (IN_RANGE ((REGNO), 0, FIRST_PSEUDO_REGISTER-1)), \ ++ rs6000_regno_regclass[(REGNO)]) ++ ++#else ++#define REGNO_REG_CLASS(REGNO) rs6000_regno_regclass[(REGNO)] ++#endif ++ +/* VSX register classes. */ +extern enum reg_class rs6000_vector_reg_class[]; +extern enum reg_class rs6000_vsx_reg_class; -+ + /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS GENERAL_REGS #define BASE_REG_CLASS BASE_REGS @@ -6943,7 +8871,7 @@ testsuite/ /* Given an rtx X being reloaded into a reg required to be in class CLASS, return the class of reg to actually use. In general this is just CLASS; but on some machines -@@ -1213,13 +1353,7 @@ enum reg_class +@@ -1213,13 +1340,7 @@ enum reg_class */ #define PREFERRED_RELOAD_CLASS(X,CLASS) \ @@ -6958,7 +8886,7 @@ testsuite/ /* Return the register class of a scratch register needed to copy IN into or out of a register in CLASS in MODE. If it can be done directly, -@@ -1234,18 +1368,7 @@ enum reg_class +@@ -1234,18 +1355,7 @@ enum reg_class are available.*/ #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \ @@ -6978,7 +8906,7 @@ testsuite/ /* For cpus that cannot load/store SDmode values from the 64-bit FP registers without using a full 64-bit load/store, we need -@@ -1257,32 +1380,15 @@ enum reg_class +@@ -1257,32 +1367,15 @@ enum reg_class /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. @@ -7016,7 +8944,7 @@ testsuite/ /* Stack layout; function entry, exit and calling. */ -@@ -1343,8 +1449,8 @@ extern enum rs6000_abi rs6000_current_ab +@@ -1343,8 +1436,8 @@ extern enum rs6000_abi rs6000_current_ab #define STARTING_FRAME_OFFSET \ (FRAME_GROWS_DOWNWARD \ ? 0 \ @@ -7027,7 +8955,7 @@ testsuite/ + RS6000_SAVE_AREA)) /* Offset from the stack pointer register to an item dynamically -@@ -1354,8 +1460,8 @@ extern enum rs6000_abi rs6000_current_ab +@@ -1354,8 +1447,8 @@ extern enum rs6000_abi rs6000_current_ab length of the outgoing arguments. The default is correct for most machines. See `function.c' for details. */ #define STACK_DYNAMIC_OFFSET(FUNDECL) \ @@ -7038,7 +8966,7 @@ testsuite/ + (STACK_POINTER_OFFSET)) /* If we generate an insn to push BYTES bytes, -@@ -1605,7 +1711,7 @@ typedef struct rs6000_args +@@ -1605,7 +1698,7 @@ typedef struct rs6000_args #define EPILOGUE_USES(REGNO) \ ((reload_completed && (REGNO) == LR_REGNO) \ || (TARGET_ALTIVEC && (REGNO) == VRSAVE_REGNO) \ @@ -7047,7 +8975,7 @@ testsuite/ && TARGET_AIX \ && (REGNO) == 2)) -@@ -2316,7 +2422,24 @@ extern char rs6000_reg_names[][8]; /* re +@@ -2316,7 +2409,24 @@ extern char rs6000_reg_names[][8]; /* re /* no additional names for: mq, lr, ctr, ap */ \ {"cr0", 68}, {"cr1", 69}, {"cr2", 70}, {"cr3", 71}, \ {"cr4", 72}, {"cr5", 73}, {"cr6", 74}, {"cr7", 75}, \ @@ -7073,7 +9001,7 @@ testsuite/ /* Text to write out after a CALL that may be replaced by glue code by the loader. This depends on the AIX version. */ -@@ -2480,10 +2603,14 @@ enum rs6000_builtins +@@ -2480,10 +2590,14 @@ enum rs6000_builtins ALTIVEC_BUILTIN_VSEL_4SF, ALTIVEC_BUILTIN_VSEL_8HI, ALTIVEC_BUILTIN_VSEL_16QI, @@ -7088,7 +9016,15 @@ testsuite/ ALTIVEC_BUILTIN_VPKUHUM, ALTIVEC_BUILTIN_VPKUWUM, ALTIVEC_BUILTIN_VPKPX, -@@ -3110,6 +3237,163 @@ enum rs6000_builtins +@@ -2839,6 +2953,7 @@ enum rs6000_builtins + ALTIVEC_BUILTIN_VEC_PROMOTE, + ALTIVEC_BUILTIN_VEC_INSERT, + ALTIVEC_BUILTIN_VEC_SPLATS, ++ + ALTIVEC_BUILTIN_OVERLOADED_LAST = ALTIVEC_BUILTIN_VEC_SPLATS, + + /* SPE builtins. */ +@@ -3110,6 +3225,163 @@ enum rs6000_builtins RS6000_BUILTIN_RECIPF, RS6000_BUILTIN_RSQRTF, @@ -7177,34 +9113,24 @@ testsuite/ + VSX_BUILTIN_XVCVUXWSP, + VSX_BUILTIN_XVDIVDP, + VSX_BUILTIN_XVDIVSP, -+ VSX_BUILTIN_XVMADDADP, -+ VSX_BUILTIN_XVMADDASP, -+ VSX_BUILTIN_XVMADDMDP, -+ VSX_BUILTIN_XVMADDMSP, ++ VSX_BUILTIN_XVMADDDP, ++ VSX_BUILTIN_XVMADDSP, + VSX_BUILTIN_XVMAXDP, + VSX_BUILTIN_XVMAXSP, + VSX_BUILTIN_XVMINDP, + VSX_BUILTIN_XVMINSP, -+ VSX_BUILTIN_XVMOVDP, -+ VSX_BUILTIN_XVMOVSP, -+ VSX_BUILTIN_XVMSUBADP, -+ VSX_BUILTIN_XVMSUBASP, -+ VSX_BUILTIN_XVMSUBMDP, -+ VSX_BUILTIN_XVMSUBMSP, ++ VSX_BUILTIN_XVMSUBDP, ++ VSX_BUILTIN_XVMSUBSP, + VSX_BUILTIN_XVMULDP, + VSX_BUILTIN_XVMULSP, + VSX_BUILTIN_XVNABSDP, + VSX_BUILTIN_XVNABSSP, + VSX_BUILTIN_XVNEGDP, + VSX_BUILTIN_XVNEGSP, -+ VSX_BUILTIN_XVNMADDADP, -+ VSX_BUILTIN_XVNMADDASP, -+ VSX_BUILTIN_XVNMADDMDP, -+ VSX_BUILTIN_XVNMADDMSP, -+ VSX_BUILTIN_XVNMSUBADP, -+ VSX_BUILTIN_XVNMSUBASP, -+ VSX_BUILTIN_XVNMSUBMDP, -+ VSX_BUILTIN_XVNMSUBMSP, ++ VSX_BUILTIN_XVNMADDDP, ++ VSX_BUILTIN_XVNMADDSP, ++ VSX_BUILTIN_XVNMSUBDP, ++ VSX_BUILTIN_XVNMSUBSP, + VSX_BUILTIN_XVRDPI, + VSX_BUILTIN_XVRDPIC, + VSX_BUILTIN_XVRDPIM, @@ -7243,7 +9169,17 @@ testsuite/ + VSX_BUILTIN_XXSPLTW, + VSX_BUILTIN_XXSWAPD, + -+ /* Combine VSX/Altivec builtins. */ ++ /* VSX overloaded builtins, add the overloaded functions not present in ++ Altivec. */ ++ VSX_BUILTIN_VEC_MUL, ++ VSX_BUILTIN_OVERLOADED_FIRST = VSX_BUILTIN_VEC_MUL, ++ VSX_BUILTIN_VEC_MSUB, ++ VSX_BUILTIN_VEC_NMADD, ++ VSX_BUITLIN_VEC_NMSUB, ++ VSX_BUILTIN_VEC_DIV, ++ VSX_BUILTIN_OVERLOADED_LAST = VSX_BUILTIN_VEC_DIV, ++ ++ /* Combined VSX/Altivec builtins. */ + VECTOR_BUILTIN_FLOAT_V4SI_V4SF, + VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF, + VECTOR_BUILTIN_FIX_V4SF_V4SI, @@ -7252,7 +9188,7 @@ testsuite/ RS6000_BUILTIN_COUNT }; -@@ -3123,6 +3407,8 @@ enum rs6000_builtin_type_index +@@ -3123,6 +3395,8 @@ enum rs6000_builtin_type_index RS6000_BTI_V16QI, RS6000_BTI_V2SI, RS6000_BTI_V2SF, @@ -7261,7 +9197,7 @@ testsuite/ RS6000_BTI_V4HI, RS6000_BTI_V4SI, RS6000_BTI_V4SF, -@@ -3146,7 +3432,10 @@ enum rs6000_builtin_type_index +@@ -3146,7 +3420,10 @@ enum rs6000_builtin_type_index RS6000_BTI_UINTHI, /* unsigned_intHI_type_node */ RS6000_BTI_INTSI, /* intSI_type_node */ RS6000_BTI_UINTSI, /* unsigned_intSI_type_node */ @@ -7272,7 +9208,7 @@ testsuite/ RS6000_BTI_void, /* void_type_node */ RS6000_BTI_MAX }; -@@ -3157,6 +3446,8 @@ enum rs6000_builtin_type_index +@@ -3157,6 +3434,8 @@ enum rs6000_builtin_type_index #define opaque_p_V2SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_p_V2SI]) #define opaque_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_V4SI]) #define V16QI_type_node (rs6000_builtin_types[RS6000_BTI_V16QI]) @@ -7281,7 +9217,7 @@ testsuite/ #define V2SI_type_node (rs6000_builtin_types[RS6000_BTI_V2SI]) #define V2SF_type_node (rs6000_builtin_types[RS6000_BTI_V2SF]) #define V4HI_type_node (rs6000_builtin_types[RS6000_BTI_V4HI]) -@@ -3183,7 +3474,10 @@ enum rs6000_builtin_type_index +@@ -3183,7 +3462,10 @@ enum rs6000_builtin_type_index #define uintHI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTHI]) #define intSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTSI]) #define uintSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTSI]) @@ -7292,8 +9228,8 @@ testsuite/ #define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void]) extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX]; ---- gcc/config/rs6000/altivec.md (.../trunk) (revision 144557) -+++ gcc/config/rs6000/altivec.md (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/altivec.md (.../trunk) (revision 145777) ++++ gcc/config/rs6000/altivec.md (.../branches/ibm/power7-meissner) (revision 146027) @@ -21,18 +21,7 @@ (define_constants @@ -7398,8 +9334,9 @@ testsuite/ } } - [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")]) -- --(define_split ++ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")]) + + (define_split - [(set (match_operand:V4SI 0 "nonimmediate_operand" "") - (match_operand:V4SI 1 "input_operand" ""))] - "TARGET_ALTIVEC && reload_completed @@ -7416,9 +9353,8 @@ testsuite/ - && gpr_or_gpr_p (operands[0], operands[1])" - [(pc)] -{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) -+ [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")]) - - (define_split +- +-(define_split - [(set (match_operand:V16QI 0 "nonimmediate_operand" "") - (match_operand:V16QI 1 "input_operand" ""))] - "TARGET_ALTIVEC && reload_completed @@ -8088,22 +10024,7 @@ testsuite/ (define_insn "altivec_vsldoi_" [(set (match_operand:V 0 "register_operand" "=v") (unspec:V [(match_operand:V 1 "register_operand" "v") -@@ -1878,6 +1570,14 @@ (define_expand "build_vector_mask_for_lo - gcc_assert (GET_CODE (operands[1]) == MEM); - - addr = XEXP (operands[1], 0); -+ if (VECTOR_MEM_VSX_P (GET_MODE (operands[1]))) -+ { -+ /* VSX doesn't and off the bottom address bits, and memory -+ operations are aligned to the natural data type. */ -+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); -+ DONE; -+ } -+ - temp = gen_reg_rtx (GET_MODE (addr)); - emit_insn (gen_rtx_SET (VOIDmode, temp, - gen_rtx_NEG (GET_MODE (addr), addr))); -@@ -1959,95 +1659,6 @@ (define_insn "*altivec_stvesfx" +@@ -1959,95 +1651,6 @@ (define_insn "*altivec_stvesfx" "stvewx %1,%y0" [(set_attr "type" "vecstore")]) @@ -8199,7 +10120,7 @@ testsuite/ ;; Generate ;; vspltis? SCRATCH0,0 ;; vsubu?m SCRATCH2,SCRATCH1,%1 -@@ -2069,7 +1680,7 @@ (define_expand "abs2" +@@ -2069,7 +1672,7 @@ (define_expand "abs2" ;; vspltisw SCRATCH1,-1 ;; vslw SCRATCH2,SCRATCH1,SCRATCH1 ;; vandc %0,%1,SCRATCH2 @@ -8208,7 +10129,7 @@ testsuite/ [(set (match_dup 2) (vec_duplicate:V4SI (const_int -1))) (set (match_dup 3) -@@ -2132,7 +1743,7 @@ (define_expand "vec_shl_" +@@ -2132,7 +1735,7 @@ (define_expand "vec_shl_" DONE; }") @@ -8217,7 +10138,7 @@ testsuite/ ;; amounts that can be expressed as byte shifts (divisible by 8). ;; General shift amounts can be supported using vsro + vsr. We're ;; not expecting to see these yet (the vectorizer currently -@@ -2665,7 +2276,7 @@ (define_expand "vec_pack_trunc_v4si" +@@ -2665,7 +2268,7 @@ (define_expand "vec_pack_trunc_v4si" DONE; }") @@ -8226,7 +10147,7 @@ testsuite/ [(use (match_operand:V4SF 0 "register_operand" "")) (use (match_operand:V4SF 1 "register_operand" ""))] "TARGET_ALTIVEC" -@@ -2994,29 +2605,6 @@ (define_expand "vec_extract_oddv16qi" +@@ -2994,29 +2597,6 @@ (define_expand "vec_extract_oddv16qi" emit_insn (gen_vpkuhum_nomode (operands[0], operands[1], operands[2])); DONE; }") @@ -8256,8 +10177,8 @@ testsuite/ (define_expand "vec_interleave_high" [(set (match_operand:VI 0 "register_operand" "") ---- gcc/config/rs6000/aix61.h (.../trunk) (revision 144557) -+++ gcc/config/rs6000/aix61.h (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/aix61.h (.../trunk) (revision 145777) ++++ gcc/config/rs6000/aix61.h (.../branches/ibm/power7-meissner) (revision 146027) @@ -57,20 +57,24 @@ do { \ #undef ASM_SPEC #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)" @@ -8285,9 +10206,9 @@ testsuite/ %{mcpu=powerpc: -mppc} \ %{mcpu=rs64a: -mppc} \ %{mcpu=603: -m603} \ ---- gcc/config/rs6000/rs6000.md (.../trunk) (revision 144557) -+++ gcc/config/rs6000/rs6000.md (.../branches/ibm/power7-meissner) (revision 144730) -@@ -138,7 +138,7 @@ (define_attr "length" "" +--- gcc/config/rs6000/rs6000.md (.../trunk) (revision 145777) ++++ gcc/config/rs6000/rs6000.md (.../branches/ibm/power7-meissner) (revision 146027) +@@ -138,7 +138,7 @@ ;; Processor type -- this attribute must exactly match the processor_type ;; enumeration in rs6000.h. @@ -8296,7 +10217,7 @@ testsuite/ (const (symbol_ref "rs6000_cpu_attr"))) -@@ -167,6 +167,7 @@ (define_attr "cell_micro" "not,condition +@@ -167,6 +167,7 @@ (include "power4.md") (include "power5.md") (include "power6.md") @@ -8304,17 +10225,27 @@ testsuite/ (include "cell.md") (include "xfpu.md") -@@ -218,6 +219,9 @@ (define_mode_attr wd [(QI "b") (HI "h") +@@ -218,6 +219,19 @@ ; DImode bits (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")]) +;; ISEL/ISEL64 target selection +(define_mode_attr sel [(SI "") (DI "64")]) ++ ++;; Suffix for reload patterns ++(define_mode_attr ptrsize [(SI "32bit") ++ (DI "64bit")]) ++ ++(define_mode_attr tptrsize [(SI "TARGET_32BIT") ++ (DI "TARGET_64BIT")]) ++ ++(define_mode_attr mptrsize [(SI "si") ++ (DI "di")]) + ;; Start with fixed-point load and store insns. Here we put only the more ;; complex forms. Basic data transfer is done later. -@@ -520,7 +524,7 @@ (define_insn "" +@@ -520,7 +534,7 @@ "@ {andil.|andi.} %2,%1,0xff #" @@ -8323,7 +10254,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -546,7 +550,7 @@ (define_insn "" +@@ -546,7 +560,7 @@ "@ {andil.|andi.} %0,%1,0xff #" @@ -8332,7 +10263,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -687,7 +691,7 @@ (define_insn "" +@@ -687,7 +701,7 @@ "@ {andil.|andi.} %2,%1,0xff #" @@ -8341,7 +10272,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -713,7 +717,7 @@ (define_insn "" +@@ -713,7 +727,7 @@ "@ {andil.|andi.} %0,%1,0xff #" @@ -8350,7 +10281,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -856,7 +860,7 @@ (define_insn "" +@@ -856,7 +870,7 @@ "@ {andil.|andi.} %2,%1,0xffff #" @@ -8359,7 +10290,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -882,7 +886,7 @@ (define_insn "" +@@ -882,7 +896,7 @@ "@ {andil.|andi.} %0,%1,0xffff #" @@ -8368,7 +10299,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -1670,7 +1674,7 @@ (define_insn "" +@@ -1670,7 +1684,7 @@ "@ nor. %2,%1,%1 #" @@ -8377,7 +10308,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -1696,7 +1700,7 @@ (define_insn "" +@@ -1696,7 +1710,7 @@ "@ nor. %0,%1,%1 #" @@ -8386,7 +10317,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -2221,10 +2225,22 @@ (define_insn "popcntb2" +@@ -2221,10 +2235,22 @@ "TARGET_POPCNTB" "popcntb %0,%1") @@ -8410,7 +10341,7 @@ testsuite/ { rs6000_emit_popcount (operands[0], operands[1]); DONE; -@@ -2852,7 +2868,7 @@ (define_insn "andsi3_mc" +@@ -2852,7 +2878,7 @@ {rlinm|rlwinm} %0,%1,0,%m2,%M2 {andil.|andi.} %0,%1,%b2 {andiu.|andis.} %0,%1,%u2" @@ -8419,7 +10350,7 @@ testsuite/ (define_insn "andsi3_nomc" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") -@@ -2895,7 +2911,8 @@ (define_insn "*andsi3_internal2_mc" +@@ -2895,7 +2921,8 @@ # # #" @@ -8429,7 +10360,7 @@ testsuite/ (set_attr "length" "4,4,4,4,8,8,8,8")]) (define_insn "*andsi3_internal3_mc" -@@ -2915,7 +2932,8 @@ (define_insn "*andsi3_internal3_mc" +@@ -2915,7 +2942,8 @@ # # #" @@ -8439,7 +10370,7 @@ testsuite/ (set_attr "length" "8,4,4,4,8,8,8,8")]) (define_split -@@ -2974,7 +2992,8 @@ (define_insn "*andsi3_internal4" +@@ -2974,7 +3002,8 @@ # # #" @@ -8449,17 +10380,17 @@ testsuite/ (set_attr "length" "4,4,4,4,8,8,8,8")]) (define_insn "*andsi3_internal5_mc" -@@ -2996,7 +3015,8 @@ (define_insn "*andsi3_internal5_mc" +@@ -2996,7 +3025,8 @@ # # #" - [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare") + [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\ -+ compare,compare,compare") ++ compare,compare,compare") (set_attr "length" "8,4,4,4,8,8,8,8")]) (define_split -@@ -3127,7 +3147,7 @@ (define_insn "*boolsi3_internal2" +@@ -3127,7 +3157,7 @@ "@ %q4. %3,%1,%2 #" @@ -8468,7 +10399,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -3156,7 +3176,7 @@ (define_insn "*boolsi3_internal3" +@@ -3156,7 +3186,7 @@ "@ %q4. %0,%1,%2 #" @@ -8477,7 +10408,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -3281,7 +3301,7 @@ (define_insn "*boolccsi3_internal2" +@@ -3281,7 +3311,7 @@ "@ %q4. %3,%1,%2 #" @@ -8486,7 +10417,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -3310,7 +3330,7 @@ (define_insn "*boolccsi3_internal3" +@@ -3310,7 +3340,7 @@ "@ %q4. %0,%1,%2 #" @@ -8495,7 +10426,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -5303,7 +5323,7 @@ (define_insn "fres" +@@ -5303,7 +5333,7 @@ "fres %0,%1" [(set_attr "type" "fp")]) @@ -8504,7 +10435,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5314,7 +5334,7 @@ (define_insn "" +@@ -5314,7 +5344,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) @@ -8513,7 +10444,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5323,7 +5343,7 @@ (define_insn "" +@@ -5323,7 +5353,7 @@ "{fma|fmadd} %0,%1,%2,%3" [(set_attr "type" "dmul")]) @@ -8522,7 +10453,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5334,7 +5354,7 @@ (define_insn "" +@@ -5334,7 +5364,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) @@ -8531,7 +10462,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5343,7 +5363,7 @@ (define_insn "" +@@ -5343,7 +5373,7 @@ "{fms|fmsub} %0,%1,%2,%3" [(set_attr "type" "dmul")]) @@ -8540,7 +10471,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5354,7 +5374,7 @@ (define_insn "" +@@ -5354,7 +5384,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) @@ -8549,7 +10480,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")) (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5365,7 +5385,7 @@ (define_insn "" +@@ -5365,7 +5395,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) @@ -8558,7 +10489,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5374,7 +5394,7 @@ (define_insn "" +@@ -5374,7 +5404,7 @@ "{fnma|fnmadd} %0,%1,%2,%3" [(set_attr "type" "dmul")]) @@ -8567,7 +10498,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f")) (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5384,7 +5404,7 @@ (define_insn "" +@@ -5384,7 +5414,7 @@ "{fnma|fnmadd} %0,%1,%2,%3" [(set_attr "type" "dmul")]) @@ -8576,7 +10507,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5395,7 +5415,7 @@ (define_insn "" +@@ -5395,7 +5425,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) @@ -8585,7 +10516,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f") (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") -@@ -5406,7 +5426,7 @@ (define_insn "" +@@ -5406,7 +5436,7 @@ [(set_attr "type" "fp") (set_attr "fp_type" "fp_maddsub_s")]) @@ -8594,7 +10525,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") (match_operand:SF 2 "gpc_reg_operand" "f")) -@@ -5415,7 +5435,7 @@ (define_insn "" +@@ -5415,7 +5445,7 @@ "{fnms|fnmsub} %0,%1,%2,%3" [(set_attr "type" "dmul")]) @@ -8603,7 +10534,7 @@ testsuite/ [(set (match_operand:SF 0 "gpc_reg_operand" "=f") (minus:SF (match_operand:SF 3 "gpc_reg_operand" "f") (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f") -@@ -5496,9 +5516,18 @@ (define_expand "copysigndf3" +@@ -5496,9 +5526,18 @@ (match_dup 5)) (match_dup 3) (match_dup 4)))] @@ -8624,7 +10555,7 @@ testsuite/ operands[3] = gen_reg_rtx (DFmode); operands[4] = gen_reg_rtx (DFmode); operands[5] = CONST0_RTX (DFmode); -@@ -5542,12 +5571,12 @@ (define_split +@@ -5542,12 +5581,12 @@ DONE; }") @@ -8643,7 +10574,7 @@ testsuite/ " { if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3])) -@@ -5564,28 +5593,28 @@ (define_expand "movsicc" +@@ -5564,28 +5603,28 @@ ;; leave out the mode in operand 4 and use one pattern, but reload can ;; change the mode underneath our feet and then gets confused trying ;; to reload the value. @@ -8684,7 +10615,7 @@ testsuite/ "* { return output_isel (operands); }" [(set_attr "length" "4")]) -@@ -5633,7 +5662,8 @@ (define_expand "negdf2" +@@ -5633,7 +5672,8 @@ (define_insn "*negdf2_fpr" [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))] @@ -8694,7 +10625,7 @@ testsuite/ "fneg %0,%1" [(set_attr "type" "fp")]) -@@ -5646,14 +5676,16 @@ (define_expand "absdf2" +@@ -5646,14 +5686,16 @@ (define_insn "*absdf2_fpr" [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))] @@ -8713,7 +10644,7 @@ testsuite/ "fnabs %0,%1" [(set_attr "type" "fp")]) -@@ -5668,7 +5700,8 @@ (define_insn "*adddf3_fpr" +@@ -5668,7 +5710,8 @@ [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f") (match_operand:DF 2 "gpc_reg_operand" "f")))] @@ -8723,7 +10654,7 @@ testsuite/ "{fa|fadd} %0,%1,%2" [(set_attr "type" "fp") (set_attr "fp_type" "fp_addsub_d")]) -@@ -5684,7 +5717,8 @@ (define_insn "*subdf3_fpr" +@@ -5684,7 +5727,8 @@ [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (minus:DF (match_operand:DF 1 "gpc_reg_operand" "f") (match_operand:DF 2 "gpc_reg_operand" "f")))] @@ -8733,7 +10664,7 @@ testsuite/ "{fs|fsub} %0,%1,%2" [(set_attr "type" "fp") (set_attr "fp_type" "fp_addsub_d")]) -@@ -5700,7 +5734,8 @@ (define_insn "*muldf3_fpr" +@@ -5700,7 +5744,8 @@ [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f") (match_operand:DF 2 "gpc_reg_operand" "f")))] @@ -8743,7 +10674,7 @@ testsuite/ "{fm|fmul} %0,%1,%2" [(set_attr "type" "dmul") (set_attr "fp_type" "fp_mul_d")]) -@@ -5718,7 +5753,8 @@ (define_insn "*divdf3_fpr" +@@ -5718,7 +5763,8 @@ [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (div:DF (match_operand:DF 1 "gpc_reg_operand" "f") (match_operand:DF 2 "gpc_reg_operand" "f")))] @@ -8753,7 +10684,7 @@ testsuite/ "{fd|fdiv} %0,%1,%2" [(set_attr "type" "ddiv")]) -@@ -5734,73 +5770,81 @@ (define_expand "recipdf3" +@@ -5734,73 +5780,81 @@ DONE; }) @@ -8849,7 +10780,7 @@ testsuite/ "{fnms|fnmsub} %0,%1,%2,%3" [(set_attr "type" "dmul") (set_attr "fp_type" "fp_maddsub_d")]) -@@ -5809,7 +5853,8 @@ (define_insn "sqrtdf2" +@@ -5809,7 +5863,8 @@ [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "f")))] "(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT && TARGET_FPRS @@ -8859,7 +10790,7 @@ testsuite/ "fsqrt %0,%1" [(set_attr "type" "dsqrt")]) -@@ -5898,6 +5943,18 @@ (define_expand "fix_truncsfsi2" +@@ -5898,6 +5953,18 @@ "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT" "") @@ -8878,7 +10809,7 @@ testsuite/ ; For each of these conversions, there is a define_expand, a define_insn ; with a '#' template, and a define_split (with C code). The idea is ; to allow constant folding with the template of the define_insn, -@@ -6139,10 +6196,17 @@ (define_insn "fctiwz" +@@ -6139,24 +6206,38 @@ "{fcirz|fctiwz} %0,%1" [(set_attr "type" "fp")]) @@ -8897,7 +10828,11 @@ testsuite/ "friz %0,%1" [(set_attr "type" "fp")]) -@@ -6153,10 +6217,17 @@ (define_insn "btruncsf2" + (define_insn "btruncsf2" + [(set (match_operand:SF 0 "gpc_reg_operand" "=f") + (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))] +- "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT " ++ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" "friz %0,%1" [(set_attr "type" "fp")]) @@ -8917,7 +10852,7 @@ testsuite/ "frip %0,%1" [(set_attr "type" "fp")]) -@@ -6167,10 +6238,17 @@ (define_insn "ceilsf2" +@@ -6167,10 +6248,17 @@ "frip %0,%1" [(set_attr "type" "fp")]) @@ -8937,7 +10872,7 @@ testsuite/ "frim %0,%1" [(set_attr "type" "fp")]) -@@ -6181,6 +6259,7 @@ (define_insn "floorsf2" +@@ -6181,6 +6269,7 @@ "frim %0,%1" [(set_attr "type" "fp")]) @@ -8945,7 +10880,7 @@ testsuite/ (define_insn "rounddf2" [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))] -@@ -6195,6 +6274,12 @@ (define_insn "roundsf2" +@@ -6195,6 +6284,12 @@ "frin %0,%1" [(set_attr "type" "fp")]) @@ -8958,7 +10893,7 @@ testsuite/ ; An UNSPEC is used so we don't have to support SImode in FP registers. (define_insn "stfiwx" [(set (match_operand:SI 0 "memory_operand" "=Z") -@@ -6210,17 +6295,40 @@ (define_expand "floatsisf2" +@@ -6210,17 +6305,40 @@ "TARGET_HARD_FLOAT && !TARGET_FPRS" "") @@ -9003,7 +10938,7 @@ testsuite/ "fctidz %0,%1" [(set_attr "type" "fp")]) -@@ -7609,7 +7717,7 @@ (define_insn "anddi3_mc" +@@ -7609,7 +7727,7 @@ andi. %0,%1,%b2 andis. %0,%1,%u2 #" @@ -9012,7 +10947,7 @@ testsuite/ (set_attr "length" "4,4,4,4,4,8")]) (define_insn "anddi3_nomc" -@@ -7667,7 +7775,9 @@ (define_insn "*anddi3_internal2_mc" +@@ -7667,7 +7785,9 @@ # # #" @@ -9023,7 +10958,7 @@ testsuite/ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")]) (define_split -@@ -7718,7 +7828,9 @@ (define_insn "*anddi3_internal3_mc" +@@ -7718,7 +7838,9 @@ # # #" @@ -9034,7 +10969,7 @@ testsuite/ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")]) (define_split -@@ -7858,7 +7970,7 @@ (define_insn "*booldi3_internal2" +@@ -7858,7 +7980,7 @@ "@ %q4. %3,%1,%2 #" @@ -9043,7 +10978,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -7887,7 +7999,7 @@ (define_insn "*booldi3_internal3" +@@ -7887,7 +8009,7 @@ "@ %q4. %0,%1,%2 #" @@ -9052,7 +10987,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -7958,7 +8070,7 @@ (define_insn "*boolcdi3_internal2" +@@ -7958,7 +8080,7 @@ "@ %q4. %3,%2,%1 #" @@ -9061,7 +10996,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -7987,7 +8099,7 @@ (define_insn "*boolcdi3_internal3" +@@ -7987,7 +8109,7 @@ "@ %q4. %0,%2,%1 #" @@ -9070,7 +11005,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -8024,7 +8136,7 @@ (define_insn "*boolccdi3_internal2" +@@ -8024,7 +8146,7 @@ "@ %q4. %3,%1,%2 #" @@ -9079,7 +11014,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -8053,7 +8165,7 @@ (define_insn "*boolccdi3_internal3" +@@ -8053,7 +8175,7 @@ "@ %q4. %0,%1,%2 #" @@ -9088,7 +11023,7 @@ testsuite/ (set_attr "length" "4,8")]) (define_split -@@ -8070,6 +8182,51 @@ (define_split +@@ -8070,6 +8192,51 @@ (compare:CC (match_dup 0) (const_int 0)))] "") @@ -9140,7 +11075,7 @@ testsuite/ ;; Now define ways of moving data around. -@@ -8473,8 +8630,8 @@ (define_split +@@ -8473,8 +8640,8 @@ ;; The "??" is a kludge until we can figure out a more reasonable way ;; of handling these non-offsettable values. (define_insn "*movdf_hardfloat32" @@ -9151,14 +11086,14 @@ testsuite/ "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && (gpc_reg_operand (operands[0], DFmode) || gpc_reg_operand (operands[1], DFmode))" -@@ -8553,19 +8710,30 @@ (define_insn "*movdf_hardfloat32" +@@ -8553,19 +8720,30 @@ return \"\"; } case 3: - return \"fmr %0,%1\"; case 4: - return \"lfd%U1%X1 %0,%1\"; -+ return \"xscpsgndp %x0,%x1,%x1\"; ++ return \"xxlor %x0,%x1,%x1\"; case 5: - return \"stfd%U0%X0 %1,%0\"; case 6: @@ -9187,7 +11122,7 @@ testsuite/ (define_insn "*movdf_softfloat32" [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r") -@@ -8613,19 +8781,26 @@ (define_insn "*movdf_softfloat32" +@@ -8613,19 +8791,26 @@ ; ld/std require word-aligned displacements -> 'Y' constraint. ; List Y->r and r->Y before r->r for reload. (define_insn "*movdf_hardfloat64_mfpgpr" @@ -9204,8 +11139,8 @@ testsuite/ std%U0%X0 %1,%0 ld%U1%X1 %0,%1 mr %0,%1 -+ xscpsgndp %x0,%x1,%x1 -+ xscpsgndp %x0,%x1,%x1 ++ xxlor %x0,%x1,%x1 ++ xxlor %x0,%x1,%x1 + lxsd%U1x %x0,%y1 + lxsd%U1x %x0,%y1 + stxsd%U0x %x1,%y0 @@ -9217,7 +11152,7 @@ testsuite/ mt%0 %1 mf%1 %0 {cror 0,0,0|nop} -@@ -8634,33 +8809,40 @@ (define_insn "*movdf_hardfloat64_mfpgpr" +@@ -8634,33 +8819,40 @@ # mftgpr %0,%1 mffgpr %0,%1" @@ -9242,8 +11177,8 @@ testsuite/ std%U0%X0 %1,%0 ld%U1%X1 %0,%1 mr %0,%1 -+ xscpsgndp %x0,%x1,%x1 -+ xscpsgndp %x0,%x1,%x1 ++ xxlor %x0,%x1,%x1 ++ xxlor %x0,%x1,%x1 + lxsd%U1x %x0,%y1 + lxsd%U1x %x0,%y1 + stxsd%U0x %x1,%y0 @@ -9265,7 +11200,7 @@ testsuite/ (define_insn "*movdf_softfloat64" [(set (match_operand:DF 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h") -@@ -9237,15 +9419,16 @@ (define_insn "*movti_string" +@@ -9237,15 +9429,16 @@ (define_insn "*movti_ppc64" [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o<>,r") (match_operand:TI 1 "input_operand" "r,r,m"))] @@ -9285,7 +11220,7 @@ testsuite/ [(set (match_dup 2) (match_dup 4)) (set (match_dup 3) (match_dup 5))] " -@@ -9271,7 +9454,7 @@ (define_split +@@ -9271,7 +9464,7 @@ (define_split [(set (match_operand:TI 0 "nonimmediate_operand" "") (match_operand:TI 1 "input_operand" ""))] @@ -9294,7 +11229,7 @@ testsuite/ && gpr_or_gpr_p (operands[0], operands[1])" [(pc)] { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) -@@ -14891,6 +15074,8 @@ (define_insn "prefetch" +@@ -14891,6 +15084,8 @@ (include "sync.md") @@ -9303,8 +11238,8 @@ testsuite/ (include "altivec.md") (include "spe.md") (include "dfp.md") ---- gcc/config/rs6000/e500.h (.../trunk) (revision 144557) -+++ gcc/config/rs6000/e500.h (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/e500.h (.../trunk) (revision 145777) ++++ gcc/config/rs6000/e500.h (.../branches/ibm/power7-meissner) (revision 146027) @@ -37,6 +37,8 @@ { \ if (TARGET_ALTIVEC) \ @@ -9314,8 +11249,8 @@ testsuite/ if (TARGET_64BIT) \ error ("64-bit E500 not supported"); \ if (TARGET_HARD_FLOAT && TARGET_FPRS) \ ---- gcc/config/rs6000/driver-rs6000.c (.../trunk) (revision 144557) -+++ gcc/config/rs6000/driver-rs6000.c (.../branches/ibm/power7-meissner) (revision 144730) +--- gcc/config/rs6000/driver-rs6000.c (.../trunk) (revision 145777) ++++ gcc/config/rs6000/driver-rs6000.c (.../branches/ibm/power7-meissner) (revision 146027) @@ -343,11 +343,115 @@ detect_processor_aix (void) #endif /* _AIX */ @@ -9496,9 +11431,9 @@ testsuite/ return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL); } ---- gcc/config/rs6000/sysv4.h (.../trunk) (revision 144557) -+++ gcc/config/rs6000/sysv4.h (.../branches/ibm/power7-meissner) (revision 144730) -@@ -119,9 +119,9 @@ do { \ +--- gcc/config/rs6000/sysv4.h (.../trunk) (revision 145777) ++++ gcc/config/rs6000/sysv4.h (.../branches/ibm/power7-meissner) (revision 146027) +@@ -120,9 +120,9 @@ do { \ else if (!strcmp (rs6000_abi_name, "i960-old")) \ { \ rs6000_current_abi = ABI_V4; \ diff --git a/gcc44-pr27898.patch b/gcc44-pr27898.patch deleted file mode 100644 index 172bb81..0000000 --- a/gcc44-pr27898.patch +++ /dev/null @@ -1,16 +0,0 @@ -2006-08-18 Jakub Jelinek - - PR c/27898 - * gcc.dg/pr27898.c: New test. - ---- gcc/testsuite/gcc.dg/pr27898.c.jj 2006-08-18 09:19:33.000000000 +0200 -+++ gcc/testsuite/gcc.dg/pr27898.c 2006-08-18 09:19:27.000000000 +0200 -@@ -0,0 +1,8 @@ -+/* PR c/27898 */ -+/* { dg-do compile } */ -+/* { dg-options "--combine" } */ -+/* { dg-additional-sources "pr27898.c" } */ -+ -+union u { struct { int i; }; }; -+ -+extern int foo (union u *); diff --git a/gcc44-pr32139.patch b/gcc44-pr32139.patch deleted file mode 100644 index f356967..0000000 --- a/gcc44-pr32139.patch +++ /dev/null @@ -1,19 +0,0 @@ -2007-06-01 Jakub Jelinek - - PR tree-optimization/32139 - * gcc.c-torture/compile/20070531-1.c: New test. - ---- gcc/testsuite/gcc.c-torture/compile/20070531-1.c.jj 2007-05-31 13:47:22.000000000 +0200 -+++ gcc/testsuite/gcc.c-torture/compile/20070531-1.c 2007-06-01 10:57:15.000000000 +0200 -@@ -0,0 +1,11 @@ -+/* PR tree-optimization/32139 */ -+int foo (void); -+int bar (void) __attribute__ ((const)); -+ -+int -+test (int x) -+{ -+ int a = (x == 10000 ? foo : bar) (); -+ int b = (x == 10000 ? foo : bar) (); -+ return a + b; -+} diff --git a/gcc44-pr37959.patch b/gcc44-pr37959.patch deleted file mode 100644 index 00363b1..0000000 --- a/gcc44-pr37959.patch +++ /dev/null @@ -1,146 +0,0 @@ -2009-03-18 Dodji Seketeli - Jakub Jelinek - - PR debug/37959 - * dwarf2out.c (dwarf_attr_name): Handle DW_AT_explicit attribute. - (gen_subprogram_die): When a function is explicit, generate the DW_AT_explicit - attribute. - * langhooks.h (struct lang_hooks_for_decls): Add function_decl_explicit_p - langhook. - * langhooks-def.h (LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P): Define. - (LANG_HOOKS_DECLS): Add LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P. - - * cp-objcp-common.h (LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P): Define. - (cp_function_decl_explicit_p): New prototype. - * cp-objcp-common.c (cp_function_decl_explicit_p): New function. - - * g++.dg/debug/dwarf2/explicit-constructor.C: New test. - ---- gcc/cp/cp-objcp-common.c.jj 2009-03-05 22:32:17.000000000 +0100 -+++ gcc/cp/cp-objcp-common.c 2009-03-18 14:31:17.000000000 +0100 -@@ -1,5 +1,5 @@ - /* Some code common to C++ and ObjC++ front ends. -- Copyright (C) 2004, 2007, 2008 Free Software Foundation, Inc. -+ Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc. - Contributed by Ziemowit Laski - - This file is part of GCC. -@@ -203,6 +203,16 @@ cxx_staticp (tree arg) - return NULL_TREE; - } - -+/* Return true if DECL is explicit member function. */ -+ -+bool -+cp_function_decl_explicit_p (tree decl) -+{ -+ return (decl -+ && FUNCTION_FIRST_USER_PARMTYPE (decl) != void_list_node -+ && DECL_NONCONVERTING_P (decl)); -+} -+ - /* Stubs to keep c-opts.c happy. */ - void - push_file_scope (void) ---- gcc/cp/cp-objcp-common.h.jj 2009-03-02 16:21:33.000000000 +0100 -+++ gcc/cp/cp-objcp-common.h 2009-03-18 14:33:51.000000000 +0100 -@@ -1,5 +1,5 @@ - /* Language hooks common to C++ and ObjC++ front ends. -- Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. -+ Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. - Contributed by Ziemowit Laski - - This file is part of GCC. -@@ -26,6 +26,8 @@ along with GCC; see the file COPYING3. - extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t, - tree, bool); - -+extern bool cp_function_decl_explicit_p (tree decl); -+ - /* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks - specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c, - respectively. */ -@@ -131,6 +133,8 @@ extern tree objcp_tsubst_copy_and_build - #define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset - #undef LANG_HOOKS_GIMPLIFY_EXPR - #define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr -+#undef LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P -+#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P cp_function_decl_explicit_p - #undef LANG_HOOKS_OMP_PREDETERMINED_SHARING - #define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing - #undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR ---- gcc/langhooks-def.h.jj 2009-03-18 14:24:43.000000000 +0100 -+++ gcc/langhooks-def.h 2009-03-18 14:32:37.000000000 +0100 -@@ -190,6 +190,7 @@ extern tree lhd_make_node (enum tree_cod - #define LANG_HOOKS_GLOBAL_BINDINGS_P global_bindings_p - #define LANG_HOOKS_PUSHDECL pushdecl - #define LANG_HOOKS_GETDECLS getdecls -+#define LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P hook_bool_tree_false - #define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL lhd_warn_unused_global_decl - #define LANG_HOOKS_WRITE_GLOBALS write_global_declarations - #define LANG_HOOKS_DECL_OK_FOR_SIBCALL lhd_decl_ok_for_sibcall -@@ -209,6 +210,7 @@ extern tree lhd_make_node (enum tree_cod - LANG_HOOKS_GLOBAL_BINDINGS_P, \ - LANG_HOOKS_PUSHDECL, \ - LANG_HOOKS_GETDECLS, \ -+ LANG_HOOKS_FUNCTION_DECL_EXPLICIT_P, \ - LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL, \ - LANG_HOOKS_WRITE_GLOBALS, \ - LANG_HOOKS_DECL_OK_FOR_SIBCALL, \ ---- gcc/langhooks.h.jj 2009-03-18 14:24:43.000000000 +0100 -+++ gcc/langhooks.h 2009-03-18 14:32:06.000000000 +0100 -@@ -159,6 +159,9 @@ struct lang_hooks_for_decls - /* Returns the chain of decls so far in the current scope level. */ - tree (*getdecls) (void); - -+ /* Returns true if DECL is explicit member function. */ -+ bool (*function_decl_explicit_p) (tree); -+ - /* Returns true when we should warn for an unused global DECL. - We will already have checked that it has static binding. */ - bool (*warn_unused_global) (const_tree); ---- gcc/dwarf2out.c.jj 2009-03-18 14:24:43.000000000 +0100 -+++ gcc/dwarf2out.c 2009-03-18 14:33:04.000000000 +0100 -@@ -5599,6 +5599,8 @@ dwarf_attr_name (unsigned int attr) - return "DW_AT_encoding"; - case DW_AT_external: - return "DW_AT_external"; -+ case DW_AT_explicit: -+ return "DW_AT_explicit"; - case DW_AT_frame_base: - return "DW_AT_frame_base"; - case DW_AT_friend: -@@ -13620,6 +13622,11 @@ gen_subprogram_die (tree decl, dw_die_re - { - add_AT_flag (subr_die, DW_AT_declaration, 1); - -+ /* If this is an explicit function declaration then generate -+ a DW_AT_explicit attribute. */ -+ if (lang_hooks.decls.function_decl_explicit_p (decl)) -+ add_AT_flag (subr_die, DW_AT_explicit, 1); -+ - /* The first time we see a member function, it is in the context of - the class to which it belongs. We make sure of this by emitting - the class first. The next time is the definition, which is ---- gcc/testsuite/g++.dg/debug/dwarf2/explicit-constructor.C.jj 2009-03-18 14:24:55.000000000 +0100 -+++ gcc/testsuite/g++.dg/debug/dwarf2/explicit-constructor.C 2009-03-18 14:24:55.000000000 +0100 -@@ -0,0 +1,19 @@ -+// Contributed by Dodji Seketeli -+// Origin: PR c++ -+// { dg-do compile } -+// { dg-options "-O -g -dA" } -+// { dg-final { scan-assembler-times "DW_AT_explicit" 2 } } -+ -+struct Foo -+{ -+ Foo () {} -+ explicit Foo (int) {} -+ Foo (char) {} -+ ~Foo () {}; -+}; -+ -+void -+bar () -+{ -+ Foo foo; -+} diff --git a/gcc44-pr39226.patch b/gcc44-pr39226.patch deleted file mode 100644 index 9b99e6e..0000000 --- a/gcc44-pr39226.patch +++ /dev/null @@ -1,108 +0,0 @@ -2009-03-03 Jakub Jelinek - - PR target/39226 - * config/rs6000/rs6000.md (andsi3_internal5_nomc, - anddi3_internal2_nomc, anddi3_internal3_nomc): Removed. - (booldi3_internal3): Use boolean_or_operator instead of - boolean_operator. - - * gcc.dg/pr39226.c: New test. - ---- gcc/config/rs6000/rs6000.md.jj 2009-03-02 18:09:02.000000000 +0100 -+++ gcc/config/rs6000/rs6000.md 2009-03-03 10:02:37.771461086 +0100 -@@ -2999,20 +2999,6 @@ - [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare") - (set_attr "length" "8,4,4,4,8,8,8,8")]) - --(define_insn "*andsi3_internal5_nomc" -- [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y,??y,??y,?y") -- (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r") -- (match_operand:SI 2 "and_operand" "r,r,K,L,T")) -- (const_int 0))) -- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r") -- (and:SI (match_dup 1) -- (match_dup 2))) -- (clobber (match_scratch:CC 4 "=X,X,x,x,X"))] -- "TARGET_64BIT && !rs6000_gen_cell_microcode" -- "#" -- [(set_attr "type" "compare") -- (set_attr "length" "8,8,8,8,8")]) -- - (define_split - [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") - (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "") -@@ -7684,18 +7670,6 @@ - [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare") - (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")]) - --(define_insn "*anddi3_internal2_nomc" -- [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y,?y,??y,??y,?y") -- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r") -- (match_operand:DI 2 "and64_2_operand" "t,r,S,K,J,t")) -- (const_int 0))) -- (clobber (match_scratch:DI 3 "=r,r,r,r,r,r")) -- (clobber (match_scratch:CC 4 "=X,X,X,x,x,X"))] -- "TARGET_64BIT && !rs6000_gen_cell_microcode" -- "#" -- [(set_attr "type" "delayed_compare,compare,compare,compare,compare,compare") -- (set_attr "length" "8,8,8,8,8,12")]) -- - (define_split - [(set (match_operand:CC 0 "cc_reg_operand" "") - (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "") -@@ -7747,18 +7721,6 @@ - [(set_attr "type" "compare,compare,delayed_compare,compare,compare,compare,compare,compare,compare,compare,compare,compare") - (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")]) - --(define_insn "*anddi3_internal3_nomc" -- [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y,?y,??y,??y,?y") -- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r") -- (match_operand:DI 2 "and64_2_operand" "t,r,S,K,J,t")) -- (const_int 0))) -- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r") -- (and:DI (match_dup 1) (match_dup 2))) -- (clobber (match_scratch:CC 4 "=X,X,X,x,x,X"))] -- "TARGET_64BIT && !rs6000_gen_cell_microcode" -- "#" -- [(set_attr "type" "delayed_compare,compare,compare,compare,compare,compare") -- (set_attr "length" "8,8,8,8,8,12")]) - (define_split - [(set (match_operand:CC 3 "cc_reg_not_micro_cr0_operand" "") - (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "") -@@ -7915,7 +7877,7 @@ - - (define_insn "*booldi3_internal3" - [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y") -- (compare:CC (match_operator:DI 4 "boolean_operator" -+ (compare:CC (match_operator:DI 4 "boolean_or_operator" - [(match_operand:DI 1 "gpc_reg_operand" "%r,r") - (match_operand:DI 2 "gpc_reg_operand" "r,r")]) - (const_int 0))) ---- gcc/testsuite/gcc.dg/pr39226.c.jj 2009-03-02 23:27:03.398459808 +0100 -+++ gcc/testsuite/gcc.dg/pr39226.c 2009-03-02 23:26:19.696462209 +0100 -@@ -0,0 +1,25 @@ -+/* PR target/39226 */ -+/* { dg-do compile } */ -+/* { dg-options "-O2" } */ -+/* { dg-options "-O2 -mtune=cell -mminimal-toc" { target { powerpc*-*-* && lp64 } } } */ -+ -+struct A -+{ -+ char *a; -+ unsigned int b : 1; -+ unsigned int c : 31; -+}; -+ -+struct B -+{ -+ struct A *d; -+}; -+ -+void -+foo (struct B *x, unsigned long y) -+{ -+ if (x->d[y].c) -+ return; -+ if (x->d[y].b) -+ x->d[y].a = 0; -+} diff --git a/gcc44-rh330771.patch b/gcc44-rh330771.patch index f52b919..f7c365d 100644 --- a/gcc44-rh330771.patch +++ b/gcc44-rh330771.patch @@ -3,20 +3,20 @@ * Makefile.am (libgcj_tools_la_LIBADD): Add. * Makefile.in: Regenerated. ---- libjava/Makefile.am.jj 2007-03-17 09:20:30.000000000 +0100 -+++ libjava/Makefile.am 2007-10-16 15:45:14.000000000 +0200 -@@ -277,6 +277,8 @@ EXTRA_libgcj_la_SOURCES = java/lang/Obje - - libgcj_tools_la_SOURCES = classpath/tools/tools.zip - libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS) -findirect-dispatch -fno-indirect-classes -fsource-filename=$(here)/classpath/tools/all-classes.lst +--- libjava/Makefile.am.jj 2009-05-06 08:14:50.000000000 +0200 ++++ libjava/Makefile.am 2009-05-06 10:26:43.000000000 +0200 +@@ -314,6 +314,8 @@ libgcj_tools_la_SOURCES = classpath/tool + libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS) -findirect-dispatch \ + -fno-bootstrap-classes -fno-indirect-classes \ + -fsource-filename=$(here)/classpath/tools/all-classes.lst +## See jv_convert_LDADD. +libgcj_tools_la_LIBADD = -L$(here)/.libs libgcj.la libgcj_tools_la_LDFLAGS = -rpath $(toolexeclibdir) \ -version-info `grep -v '^\#' $(srcdir)/libtool-version` \ $(LIBGCJ_LD_SYMBOLIC_FUNCTIONS) ---- libjava/Makefile.in.jj 2007-07-04 21:11:11.000000000 +0200 -+++ libjava/Makefile.in 2007-10-16 15:56:07.000000000 +0200 -@@ -153,7 +153,6 @@ am__objects_1 = gnu/gcj/xlib/lib_gnu_awt +--- libjava/Makefile.in.jj 2009-05-06 08:14:49.000000000 +0200 ++++ libjava/Makefile.in 2009-05-06 10:27:18.000000000 +0200 +@@ -160,7 +160,6 @@ am__objects_1 = gnu/gcj/xlib/lib_gnu_awt am_lib_gnu_awt_xlib_la_OBJECTS = $(am__objects_1) lib_gnu_awt_xlib_la_OBJECTS = $(am_lib_gnu_awt_xlib_la_OBJECTS) @XLIB_AWT_TRUE@am_lib_gnu_awt_xlib_la_rpath = -rpath $(toolexeclibdir) @@ -24,10 +24,10 @@ am_libgcj_tools_la_OBJECTS = classpath/tools/libgcj_tools_la-tools.lo libgcj_tools_la_OBJECTS = $(am_libgcj_tools_la_OBJECTS) @INTERPRETER_TRUE@am__DEPENDENCIES_1 = gnu/classpath/jdwp.lo \ -@@ -941,6 +940,7 @@ libgcj_la_LINK = $(LIBLINK) - EXTRA_libgcj_la_SOURCES = java/lang/Object.java - libgcj_tools_la_SOURCES = classpath/tools/tools.zip - libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS) -findirect-dispatch -fno-indirect-classes -fsource-filename=$(here)/classpath/tools/all-classes.lst +@@ -1041,6 +1040,7 @@ libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS + -fno-bootstrap-classes -fno-indirect-classes \ + -fsource-filename=$(here)/classpath/tools/all-classes.lst + +libgcj_tools_la_LIBADD = -L$(here)/.libs libgcj.la libgcj_tools_la_LDFLAGS = -rpath $(toolexeclibdir) \ -version-info `grep -v '^\#' $(srcdir)/libtool-version` \ diff --git a/gcc44-rh503816-1.patch b/gcc44-rh503816-1.patch new file mode 100644 index 0000000..7516f85 --- /dev/null +++ b/gcc44-rh503816-1.patch @@ -0,0 +1,827 @@ +2009-06-21 Jakub Jelinek + + * var-tracking.c (struct shared_hash_def, shared_hash): New types. + (dataflow_set): Change vars type from htab_t to shared_hash. + (shared_hash_pool, empty_shared_hash): New variables. + (vars_clear): Removed. + (shared_hash_shared, shared_hash_htab, shared_hash_copy, + shared_hash_find_slot_unshare, shared_hash_find_slot, + shared_hash_find_slot_noinsert, shared_hash_find): New + static inlines. + (shared_hash_unshare, shared_hash_destroy): New functions. + (unshare_variable): Unshare set->vars if shared, use + shared_hash_htab. + (vars_copy): Use htab_traverse_noresize instead of htab_traverse. + (get_init_value, find_src_set_src, dump_dataflow_set, + clobber_variable_part, emit_notes_for_differences): Use + shared_hash_htab. + (dataflow_set_init): Remove second argument, set vars to + empty_shared_hash instead of creating a new htab. + (dataflow_set_clear): Call shared_hash_destroy and set vars + to empty_shared_hash instead of calling vars_clear. + (dataflow_set_copy): Don't call vars_copy, instead just share + the src htab with dst. + (variable_union): Use shared_hash_*, use initially NO_INSERT + lookup if set->vars is shared. Don't keep slot cleared before + calling unshare_variable. Unshare set->vars if needed. + Even ->refcount == 1 vars must be unshared if set->vars is shared + and var needs to be modified. + (variable_canonicalize): New function. + (dataflow_set_union): If dst->vars is empty, just share src->vars + with dst->vars and traverse with variable_canonicalize to canonicalize + and unshare what is needed. + (dataflow_set_different): If old_set and new_set use the same shared + htab, they aren't different. If number of htab elements is different, + htabs are different. Use shared_hash_*. + (dataflow_set_destroy): Call shared_hash_destroy instead of + htab_delete. + (compute_bb_dataflow, emit_notes_in_bb, vt_emit_notes): Don't pass + second argument to dataflow_set_init. + (vt_initialize): Likewise. Initialize shared_hash_pool and + empty_shared_hash, move bb in/out initialization afterwards. + Use variable_htab_free instead of NULL as changed_variables del hook. + (variable_was_changed): Change type of second argument to pointer to + dataflow_set. When inserting var into changed_variables, bump + refcount. Unshare set->vars if set is shared htab and slot needs to + be cleared. + (set_variable_part): Use shared_hash_*, use initially NO_INSERT + lookup if set->vars is shared. Unshare set->vars if needed. + Even ->refcount == 1 vars must be unshared if set->vars is shared + and var needs to be modified. Adjust variable_was_changed caller. + (delete_variable_part): Use shared_hash_*. Even ->refcount == 1 + vars must be unshared if set->vars is shared and var needs to be + modified. Adjust variable_was_changed caller. + (emit_note_insn_var_location): Don't pool_free var. + (emit_notes_for_differences_1): Initialize empty_var->refcount to 0 + instead of 1. + (vt_finalize): Call htab_delete on empty_shared_hash->htab and + free_alloc_pool on shared_hash_pool. + + * hashtab.c (htab_traverse): Don't call htab_expand for + nearly empty hashtabs with sizes 7, 13 or 31. + +--- gcc/var-tracking.c (revision 148758) ++++ gcc/var-tracking.c (revision 148760) +@@ -182,6 +182,17 @@ typedef struct attrs_def + HOST_WIDE_INT offset; + } *attrs; + ++/* Structure holding a refcounted hash table. If refcount > 1, ++ it must be first unshared before modified. */ ++typedef struct shared_hash_def ++{ ++ /* Reference count. */ ++ int refcount; ++ ++ /* Actual hash table. */ ++ htab_t htab; ++} *shared_hash; ++ + /* Structure holding the IN or OUT set for a basic block. */ + typedef struct dataflow_set_def + { +@@ -192,7 +203,7 @@ typedef struct dataflow_set_def + attrs regs[FIRST_PSEUDO_REGISTER]; + + /* Variable locations. */ +- htab_t vars; ++ shared_hash vars; + } dataflow_set; + + /* The structure (one for each basic block) containing the information +@@ -280,12 +291,18 @@ static alloc_pool var_pool; + /* Alloc pool for struct location_chain_def. */ + static alloc_pool loc_chain_pool; + ++/* Alloc pool for struct shared_hash_def. */ ++static alloc_pool shared_hash_pool; ++ + /* Changed variables, notes will be emitted for them. */ + static htab_t changed_variables; + + /* Shall notes be emitted? */ + static bool emit_notes; + ++/* Empty shared hashtable. */ ++static shared_hash empty_shared_hash; ++ + /* Local function prototypes. */ + static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *, + HOST_WIDE_INT *); +@@ -305,7 +322,6 @@ static void attrs_list_insert (attrs *, + static void attrs_list_copy (attrs *, attrs); + static void attrs_list_union (attrs *, attrs); + +-static void vars_clear (htab_t); + static variable unshare_variable (dataflow_set *set, variable var, + enum var_init_status); + static int vars_copy_1 (void **, void *); +@@ -321,11 +337,12 @@ static void var_mem_delete_and_set (data + enum var_init_status, rtx); + static void var_mem_delete (dataflow_set *, rtx, bool); + +-static void dataflow_set_init (dataflow_set *, int); ++static void dataflow_set_init (dataflow_set *); + static void dataflow_set_clear (dataflow_set *); + static void dataflow_set_copy (dataflow_set *, dataflow_set *); + static int variable_union_info_cmp_pos (const void *, const void *); + static int variable_union (void **, void *); ++static int variable_canonicalize (void **, void *); + static void dataflow_set_union (dataflow_set *, dataflow_set *); + static bool variable_part_different_p (variable_part *, variable_part *); + static bool variable_different_p (variable, variable, bool); +@@ -352,7 +369,7 @@ static void dump_vars (htab_t); + static void dump_dataflow_set (dataflow_set *); + static void dump_dataflow_sets (void); + +-static void variable_was_changed (variable, htab_t); ++static void variable_was_changed (variable, dataflow_set *); + static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT, + enum var_init_status, rtx); + static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT, +@@ -742,12 +759,107 @@ attrs_list_union (attrs *dstp, attrs src + } + } + +-/* Delete all variables from hash table VARS. */ ++/* Shared hashtable support. */ ++ ++/* Return true if VARS is shared. */ ++ ++static inline bool ++shared_hash_shared (shared_hash vars) ++{ ++ return vars->refcount > 1; ++} ++ ++/* Return the hash table for VARS. */ ++ ++static inline htab_t ++shared_hash_htab (shared_hash vars) ++{ ++ return vars->htab; ++} ++ ++/* Copy variables into a new hash table. */ ++ ++static shared_hash ++shared_hash_unshare (shared_hash vars) ++{ ++ shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool); ++ gcc_assert (vars->refcount > 1); ++ new_vars->refcount = 1; ++ new_vars->htab ++ = htab_create (htab_elements (vars->htab) + 3, variable_htab_hash, ++ variable_htab_eq, variable_htab_free); ++ vars_copy (new_vars->htab, vars->htab); ++ vars->refcount--; ++ return new_vars; ++} ++ ++/* Increment reference counter on VARS and return it. */ ++ ++static inline shared_hash ++shared_hash_copy (shared_hash vars) ++{ ++ vars->refcount++; ++ return vars; ++} ++ ++/* Decrement reference counter and destroy hash table if not shared ++ anymore. */ + + static void +-vars_clear (htab_t vars) ++shared_hash_destroy (shared_hash vars) + { +- htab_empty (vars); ++ gcc_assert (vars->refcount > 0); ++ if (--vars->refcount == 0) ++ { ++ htab_delete (vars->htab); ++ pool_free (shared_hash_pool, vars); ++ } ++} ++ ++/* Unshare *PVARS if shared and return slot for DECL. If INS is ++ INSERT, insert it if not already present. */ ++ ++static inline void ** ++shared_hash_find_slot_unshare (shared_hash *pvars, tree decl, ++ enum insert_option ins) ++{ ++ if (shared_hash_shared (*pvars)) ++ *pvars = shared_hash_unshare (*pvars); ++ return htab_find_slot_with_hash (shared_hash_htab (*pvars), decl, ++ VARIABLE_HASH_VAL (decl), ins); ++} ++ ++/* Return slot for DECL, if it is already present in the hash table. ++ If it is not present, insert it only VARS is not shared, otherwise ++ return NULL. */ ++ ++static inline void ** ++shared_hash_find_slot (shared_hash vars, tree decl) ++{ ++ return htab_find_slot_with_hash (shared_hash_htab (vars), decl, ++ VARIABLE_HASH_VAL (decl), ++ shared_hash_shared (vars) ++ ? NO_INSERT : INSERT); ++} ++ ++/* Return slot for DECL only if it is already present in the hash table. */ ++ ++static inline void ** ++shared_hash_find_slot_noinsert (shared_hash vars, tree decl) ++{ ++ return htab_find_slot_with_hash (shared_hash_htab (vars), decl, ++ VARIABLE_HASH_VAL (decl), NO_INSERT); ++} ++ ++/* Return variable for DECL or NULL if not already present in the hash ++ table. */ ++ ++static inline variable ++shared_hash_find (shared_hash vars, tree decl) ++{ ++ return (variable) ++ htab_find_with_hash (shared_hash_htab (vars), decl, ++ VARIABLE_HASH_VAL (decl)); + } + + /* Return a copy of a variable VAR and insert it to dataflow set SET. */ +@@ -801,9 +913,7 @@ unshare_variable (dataflow_set *set, var + new_var->var_part[i].cur_loc = NULL; + } + +- slot = htab_find_slot_with_hash (set->vars, new_var->decl, +- VARIABLE_HASH_VAL (new_var->decl), +- INSERT); ++ slot = shared_hash_find_slot_unshare (&set->vars, new_var->decl, INSERT); + *slot = new_var; + return new_var; + } +@@ -834,8 +944,7 @@ vars_copy_1 (void **slot, void *data) + static void + vars_copy (htab_t dst, htab_t src) + { +- vars_clear (dst); +- htab_traverse (src, vars_copy_1, dst); ++ htab_traverse_noresize (src, vars_copy_1, dst); + } + + /* Map a decl to its main debug decl. */ +@@ -874,7 +983,6 @@ var_reg_set (dataflow_set *set, rtx loc, + static int + get_init_value (dataflow_set *set, rtx loc, tree decl) + { +- void **slot; + variable var; + int i; + int ret_val = VAR_INIT_STATUS_UNKNOWN; +@@ -882,11 +990,9 @@ get_init_value (dataflow_set *set, rtx l + if (! flag_var_tracking_uninit) + return VAR_INIT_STATUS_INITIALIZED; + +- slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl), +- NO_INSERT); +- if (slot) ++ var = shared_hash_find (set->vars, decl); ++ if (var) + { +- var = * (variable *) slot; + for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++) + { + location_chain nextp; +@@ -1050,11 +1156,10 @@ var_mem_delete (dataflow_set *set, rtx l + VARS_SIZE is the initial size of hash table VARS. */ + + static void +-dataflow_set_init (dataflow_set *set, int vars_size) ++dataflow_set_init (dataflow_set *set) + { + init_attrs_list_set (set->regs); +- set->vars = htab_create (vars_size, variable_htab_hash, variable_htab_eq, +- variable_htab_free); ++ set->vars = shared_hash_copy (empty_shared_hash); + set->stack_adjust = 0; + } + +@@ -1068,7 +1173,8 @@ dataflow_set_clear (dataflow_set *set) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + attrs_list_clear (&set->regs[i]); + +- vars_clear (set->vars); ++ shared_hash_destroy (set->vars); ++ set->vars = shared_hash_copy (empty_shared_hash); + } + + /* Copy the contents of dataflow set SRC to DST. */ +@@ -1081,7 +1187,8 @@ dataflow_set_copy (dataflow_set *dst, da + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + attrs_list_copy (&dst->regs[i], src->regs[i]); + +- vars_copy (dst->vars, src->vars); ++ shared_hash_destroy (dst->vars); ++ dst->vars = shared_hash_copy (src->vars); + dst->stack_adjust = src->stack_adjust; + } + +@@ -1129,15 +1236,14 @@ variable_union_info_cmp_pos (const void + static int + variable_union (void **slot, void *data) + { +- variable src, dst, *dstp; ++ variable src, dst; ++ void **dstp; + dataflow_set *set = (dataflow_set *) data; + int i, j, k; + + src = *(variable *) slot; +- dstp = (variable *) htab_find_slot_with_hash (set->vars, src->decl, +- VARIABLE_HASH_VAL (src->decl), +- INSERT); +- if (!*dstp) ++ dstp = shared_hash_find_slot (set->vars, src->decl); ++ if (!dstp || !*dstp) + { + src->refcount++; + +@@ -1162,16 +1268,23 @@ variable_union (void **slot, void *data) + if (! flag_var_tracking_uninit) + status = VAR_INIT_STATUS_INITIALIZED; + ++ if (dstp) ++ *dstp = (void *) src; + unshare_variable (set, src, status); + } + else +- *dstp = src; ++ { ++ if (!dstp) ++ dstp = shared_hash_find_slot_unshare (&set->vars, src->decl, ++ INSERT); ++ *dstp = (void *) src; ++ } + + /* Continue traversing the hash table. */ + return 1; + } + else +- dst = *dstp; ++ dst = (variable) *dstp; + + gcc_assert (src->n_var_parts); + +@@ -1196,7 +1309,8 @@ variable_union (void **slot, void *data) + thus there are at most MAX_VAR_PARTS different offsets. */ + gcc_assert (k <= MAX_VAR_PARTS); + +- if (dst->refcount > 1 && dst->n_var_parts != k) ++ if ((dst->refcount > 1 || shared_hash_shared (set->vars)) ++ && dst->n_var_parts != k) + { + enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; + +@@ -1226,7 +1340,7 @@ variable_union (void **slot, void *data) + /* If DST is shared compare the location chains. + If they are different we will modify the chain in DST with + high probability so make a copy of DST. */ +- if (dst->refcount > 1) ++ if (dst->refcount > 1 || shared_hash_shared (set->vars)) + { + for (node = src->var_part[i].loc_chain, + node2 = dst->var_part[j].loc_chain; node && node2; +@@ -1379,6 +1493,46 @@ variable_union (void **slot, void *data) + return 1; + } + ++/* Like variable_union, but only used when doing dataflow_set_union ++ into an empty hashtab. To allow sharing, dst is initially shared ++ with src (so all variables are "copied" from src to dst hashtab), ++ so only unshare_variable for variables that need canonicalization ++ are needed. */ ++ ++static int ++variable_canonicalize (void **slot, void *data) ++{ ++ variable src; ++ dataflow_set *set = (dataflow_set *) data; ++ int k; ++ ++ src = *(variable *) slot; ++ ++ /* If CUR_LOC of some variable part is not the first element of ++ the location chain we are going to change it so we have to make ++ a copy of the variable. */ ++ for (k = 0; k < src->n_var_parts; k++) ++ { ++ gcc_assert (!src->var_part[k].loc_chain == !src->var_part[k].cur_loc); ++ if (src->var_part[k].loc_chain) ++ { ++ gcc_assert (src->var_part[k].cur_loc); ++ if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc) ++ break; ++ } ++ } ++ if (k < src->n_var_parts) ++ { ++ enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; ++ ++ if (! flag_var_tracking_uninit) ++ status = VAR_INIT_STATUS_INITIALIZED; ++ ++ unshare_variable (set, src, status); ++ } ++ return 1; ++} ++ + /* Compute union of dataflow sets SRC and DST and store it to DST. */ + + static void +@@ -1389,7 +1543,14 @@ dataflow_set_union (dataflow_set *dst, d + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + attrs_list_union (&dst->regs[i], src->regs[i]); + +- htab_traverse (src->vars, variable_union, dst); ++ if (dst->vars == empty_shared_hash) ++ { ++ shared_hash_destroy (dst->vars); ++ dst->vars = shared_hash_copy (src->vars); ++ htab_traverse (shared_hash_htab (src->vars), variable_canonicalize, dst); ++ } ++ else ++ htab_traverse (shared_hash_htab (src->vars), variable_union, dst); + } + + /* Flag whether two dataflow sets being compared contain different data. */ +@@ -1522,15 +1683,24 @@ dataflow_set_different_2 (void **slot, v + static bool + dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set) + { ++ if (old_set->vars == new_set->vars) ++ return false; ++ ++ if (htab_elements (shared_hash_htab (old_set->vars)) ++ != htab_elements (shared_hash_htab (new_set->vars))) ++ return true; ++ + dataflow_set_different_value = false; + +- htab_traverse (old_set->vars, dataflow_set_different_1, new_set->vars); ++ htab_traverse (shared_hash_htab (old_set->vars), dataflow_set_different_1, ++ shared_hash_htab (new_set->vars)); + if (!dataflow_set_different_value) + { + /* We have compared the variables which are in both hash tables + so now only check whether there are some variables in NEW_SET->VARS + which are not in OLD_SET->VARS. */ +- htab_traverse (new_set->vars, dataflow_set_different_2, old_set->vars); ++ htab_traverse (shared_hash_htab (new_set->vars), dataflow_set_different_2, ++ shared_hash_htab (old_set->vars)); + } + return dataflow_set_different_value; + } +@@ -1545,7 +1715,7 @@ dataflow_set_destroy (dataflow_set *set) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + attrs_list_clear (&set->regs[i]); + +- htab_delete (set->vars); ++ shared_hash_destroy (set->vars); + set->vars = NULL; + } + +@@ -1985,7 +2155,6 @@ find_src_set_src (dataflow_set *set, rtx + { + tree decl = NULL_TREE; /* The variable being copied around. */ + rtx set_src = NULL_RTX; /* The value for "decl" stored in "src". */ +- void **slot; + variable var; + location_chain nextp; + int i; +@@ -1998,12 +2167,9 @@ find_src_set_src (dataflow_set *set, rtx + + if (src && decl) + { +- slot = htab_find_slot_with_hash (set->vars, decl, +- VARIABLE_HASH_VAL (decl), NO_INSERT); +- +- if (slot) ++ var = shared_hash_find (set->vars, decl); ++ if (var) + { +- var = *(variable *) slot; + found = false; + for (i = 0; i < var->n_var_parts && !found; i++) + for (nextp = var->var_part[i].loc_chain; nextp && !found; +@@ -2031,7 +2197,7 @@ compute_bb_dataflow (basic_block bb) + dataflow_set *in = &VTI (bb)->in; + dataflow_set *out = &VTI (bb)->out; + +- dataflow_set_init (&old_out, htab_elements (VTI (bb)->out.vars) + 3); ++ dataflow_set_init (&old_out); + dataflow_set_copy (&old_out, out); + dataflow_set_copy (out, in); + +@@ -2323,7 +2489,7 @@ dump_dataflow_set (dataflow_set *set) + dump_attrs_list (set->regs[i]); + } + } +- dump_vars (set->vars); ++ dump_vars (shared_hash_htab (set->vars)); + fprintf (dump_file, "\n"); + } + +@@ -2345,10 +2511,10 @@ dump_dataflow_sets (void) + } + + /* Add variable VAR to the hash table of changed variables and +- if it has no locations delete it from hash table HTAB. */ ++ if it has no locations delete it from SET's hash table. */ + + static void +-variable_was_changed (variable var, htab_t htab) ++variable_was_changed (variable var, dataflow_set *set) + { + hashval_t hash = VARIABLE_HASH_VAL (var->decl); + +@@ -2359,36 +2525,39 @@ variable_was_changed (variable var, htab + slot = (variable *) htab_find_slot_with_hash (changed_variables, + var->decl, hash, INSERT); + +- if (htab && var->n_var_parts == 0) ++ if (set && var->n_var_parts == 0) + { + variable empty_var; +- void **old; + + empty_var = (variable) pool_alloc (var_pool); + empty_var->decl = var->decl; + empty_var->refcount = 1; + empty_var->n_var_parts = 0; + *slot = empty_var; +- +- old = htab_find_slot_with_hash (htab, var->decl, hash, +- NO_INSERT); +- if (old) +- htab_clear_slot (htab, old); ++ goto drop_var; + } + else + { ++ var->refcount++; + *slot = var; + } + } + else + { +- gcc_assert (htab); ++ gcc_assert (set); + if (var->n_var_parts == 0) + { +- void **slot = htab_find_slot_with_hash (htab, var->decl, hash, +- NO_INSERT); ++ void **slot; ++ ++ drop_var: ++ slot = shared_hash_find_slot_noinsert (set->vars, var->decl); + if (slot) +- htab_clear_slot (htab, slot); ++ { ++ if (shared_hash_shared (set->vars)) ++ slot = shared_hash_find_slot_unshare (&set->vars, var->decl, ++ NO_INSERT); ++ htab_clear_slot (shared_hash_htab (set->vars), slot); ++ } + } + } + } +@@ -2438,12 +2607,12 @@ set_variable_part (dataflow_set *set, rt + location_chain node, next; + location_chain *nextp; + variable var; +- void **slot; +- +- slot = htab_find_slot_with_hash (set->vars, decl, +- VARIABLE_HASH_VAL (decl), INSERT); +- if (!*slot) ++ void **slot = shared_hash_find_slot (set->vars, decl); ++ ++ if (!slot || !*slot) + { ++ if (!slot) ++ slot = shared_hash_find_slot_unshare (&set->vars, decl, INSERT); + /* Create new variable information. */ + var = (variable) pool_alloc (var_pool); + var->decl = decl; +@@ -2479,13 +2648,12 @@ set_variable_part (dataflow_set *set, rt + if (set_src != NULL) + node->set_src = set_src; + +- *slot = var; + return; + } + else + { + /* We have to make a copy of a shared variable. */ +- if (var->refcount > 1) ++ if (var->refcount > 1 || shared_hash_shared (set->vars)) + var = unshare_variable (set, var, initialized); + } + } +@@ -2494,7 +2662,7 @@ set_variable_part (dataflow_set *set, rt + /* We have not found the location part, new one will be created. */ + + /* We have to make a copy of the shared variable. */ +- if (var->refcount > 1) ++ if (var->refcount > 1 || shared_hash_shared (set->vars)) + var = unshare_variable (set, var, initialized); + + /* We track only variables whose size is <= MAX_VAR_PARTS bytes +@@ -2548,7 +2716,7 @@ set_variable_part (dataflow_set *set, rt + if (var->var_part[pos].cur_loc == NULL) + { + var->var_part[pos].cur_loc = loc; +- variable_was_changed (var, set->vars); ++ variable_was_changed (var, set); + } + } + +@@ -2561,16 +2729,14 @@ static void + clobber_variable_part (dataflow_set *set, rtx loc, tree decl, + HOST_WIDE_INT offset, rtx set_src) + { +- void **slot; ++ variable var; + + if (! decl || ! DECL_P (decl)) + return; + +- slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl), +- NO_INSERT); +- if (slot) ++ var = shared_hash_find (set->vars, decl); ++ if (var) + { +- variable var = (variable) *slot; + int pos = find_variable_location_part (var, offset, NULL); + + if (pos >= 0) +@@ -2627,13 +2793,9 @@ static void + delete_variable_part (dataflow_set *set, rtx loc, tree decl, + HOST_WIDE_INT offset) + { +- void **slot; +- +- slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl), +- NO_INSERT); +- if (slot) ++ variable var = shared_hash_find (set->vars, decl);; ++ if (var) + { +- variable var = (variable) *slot; + int pos = find_variable_location_part (var, offset, NULL); + + if (pos >= 0) +@@ -2642,7 +2804,7 @@ delete_variable_part (dataflow_set *set, + location_chain *nextp; + bool changed; + +- if (var->refcount > 1) ++ if (var->refcount > 1 || shared_hash_shared (set->vars)) + { + /* If the variable contains the location part we have to + make a copy of the variable. */ +@@ -2705,7 +2867,7 @@ delete_variable_part (dataflow_set *set, + } + } + if (changed) +- variable_was_changed (var, set->vars); ++ variable_was_changed (var, set); + } + } + } +@@ -2864,14 +3026,6 @@ emit_note_insn_var_location (void **varp + + htab_clear_slot (changed_variables, varp); + +- /* When there are no location parts the variable has been already +- removed from hash table and a new empty variable was created. +- Free the empty variable. */ +- if (var->n_var_parts == 0) +- { +- pool_free (var_pool, var); +- } +- + /* Continue traversing the hash table. */ + return 1; + } +@@ -2910,7 +3064,7 @@ emit_notes_for_differences_1 (void **slo + + empty_var = (variable) pool_alloc (var_pool); + empty_var->decl = old_var->decl; +- empty_var->refcount = 1; ++ empty_var->refcount = 0; + empty_var->n_var_parts = 0; + variable_was_changed (empty_var, NULL); + } +@@ -2952,8 +3106,12 @@ static void + emit_notes_for_differences (rtx insn, dataflow_set *old_set, + dataflow_set *new_set) + { +- htab_traverse (old_set->vars, emit_notes_for_differences_1, new_set->vars); +- htab_traverse (new_set->vars, emit_notes_for_differences_2, old_set->vars); ++ htab_traverse (shared_hash_htab (old_set->vars), ++ emit_notes_for_differences_1, ++ shared_hash_htab (new_set->vars)); ++ htab_traverse (shared_hash_htab (new_set->vars), ++ emit_notes_for_differences_2, ++ shared_hash_htab (old_set->vars)); + emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN); + } + +@@ -2965,7 +3123,7 @@ emit_notes_in_bb (basic_block bb) + int i; + dataflow_set set; + +- dataflow_set_init (&set, htab_elements (VTI (bb)->in.vars) + 3); ++ dataflow_set_init (&set); + dataflow_set_copy (&set, &VTI (bb)->in); + + for (i = 0; i < VTI (bb)->n_mos; i++) +@@ -3098,7 +3256,7 @@ vt_emit_notes (void) + delete_variable_part). */ + emit_notes = true; + +- dataflow_set_init (&empty, 7); ++ dataflow_set_init (&empty); + last_out = ∅ + + FOR_EACH_BB (bb) +@@ -3343,14 +3501,6 @@ vt_initialize (void) + } + } + +- /* Init the IN and OUT sets. */ +- FOR_ALL_BB (bb) +- { +- VTI (bb)->visited = false; +- dataflow_set_init (&VTI (bb)->in, 7); +- dataflow_set_init (&VTI (bb)->out, 7); +- } +- + attrs_pool = create_alloc_pool ("attrs_def pool", + sizeof (struct attrs_def), 1024); + var_pool = create_alloc_pool ("variable_def pool", +@@ -3358,8 +3508,24 @@ vt_initialize (void) + loc_chain_pool = create_alloc_pool ("location_chain_def pool", + sizeof (struct location_chain_def), + 1024); ++ shared_hash_pool = create_alloc_pool ("shared_hash_def pool", ++ sizeof (struct shared_hash_def), 256); ++ empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool); ++ empty_shared_hash->refcount = 1; ++ empty_shared_hash->htab ++ = htab_create (1, variable_htab_hash, variable_htab_eq, ++ variable_htab_free); + changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq, +- NULL); ++ variable_htab_free); ++ ++ /* Init the IN and OUT sets. */ ++ FOR_ALL_BB (bb) ++ { ++ VTI (bb)->visited = false; ++ dataflow_set_init (&VTI (bb)->in); ++ dataflow_set_init (&VTI (bb)->out); ++ } ++ + vt_add_function_parameters (); + } + +@@ -3381,10 +3547,12 @@ vt_finalize (void) + dataflow_set_destroy (&VTI (bb)->out); + } + free_aux_for_blocks (); ++ htab_delete (empty_shared_hash->htab); ++ htab_delete (changed_variables); + free_alloc_pool (attrs_pool); + free_alloc_pool (var_pool); + free_alloc_pool (loc_chain_pool); +- htab_delete (changed_variables); ++ free_alloc_pool (shared_hash_pool); + } + + /* The entry point to variable tracking pass. */ +--- libiberty/hashtab.c (revision 148758) ++++ libiberty/hashtab.c (revision 148760) +@@ -759,7 +759,8 @@ htab_traverse_noresize (htab_t htab, hta + void + htab_traverse (htab_t htab, htab_trav callback, PTR info) + { +- if (htab_elements (htab) * 8 < htab_size (htab)) ++ size_t size = htab_size (htab); ++ if (htab_elements (htab) * 8 < size && size > 32) + htab_expand (htab); + + htab_traverse_noresize (htab, callback, info); diff --git a/gcc44-rh503816-2.patch b/gcc44-rh503816-2.patch new file mode 100644 index 0000000..5ee452a --- /dev/null +++ b/gcc44-rh503816-2.patch @@ -0,0 +1,491 @@ +2009-06-23 Jakub Jelinek + + * var-tracking.c (unshare_variable): Force initialized to + be VAR_INIT_STATUS_INITIALIZED unless flag_var_tracking_uninit. + (set_variable_part): Likewise. + (struct variable_union_info): Remove pos_src field. + (vui_vec, vui_allocated): New variables. + (variable_union): Pass VAR_INIT_STATUS_UNKNOWN to unshare_variable + unconditionally. Avoid XCVECNEW/free for every sorting, for dst_l + == 1 use a simpler sorting algorithm. Compute pos field right + away, don't fill in pos_src. For dst_l == 2 avoid qsort. + Avoid quadratic comparison if !flag_var_tracking_uninit. + (variable_canonicalize): Pass VAR_INIT_STATUS_UNKNOWN to + unshare_variable unconditionally. + (dataflow_set_different_2): Removed. + (dataflow_set_different): Don't traverse second hash table. + (compute_bb_dataflow): Pass VAR_INIT_STATUS_UNINITIALIZED + unconditionally to var_reg_set or var_mem_set. + (emit_notes_in_bb): Likewise. + (delete_variable_part): Pass VAR_INIT_STATUS_UNKNOWN to + unshare_variable. + (emit_note_insn_var_location): Don't set initialized to + VAR_INIT_STATUS_INITIALIZED early. + (vt_finalize): Free vui_vec if needed, clear vui_vec and + vui_allocated. + +--- gcc/var-tracking.c (revision 148851) ++++ gcc/var-tracking.c (revision 148852) +@@ -347,7 +347,6 @@ static void dataflow_set_union (dataflow + static bool variable_part_different_p (variable_part *, variable_part *); + static bool variable_different_p (variable, variable, bool); + static int dataflow_set_different_1 (void **, void *); +-static int dataflow_set_different_2 (void **, void *); + static bool dataflow_set_different (dataflow_set *, dataflow_set *); + static void dataflow_set_destroy (dataflow_set *); + +@@ -878,6 +877,9 @@ unshare_variable (dataflow_set *set, var + var->refcount--; + new_var->n_var_parts = var->n_var_parts; + ++ if (! flag_var_tracking_uninit) ++ initialized = VAR_INIT_STATUS_INITIALIZED; ++ + for (i = 0; i < var->n_var_parts; i++) + { + location_chain node; +@@ -1202,11 +1204,14 @@ struct variable_union_info + /* The sum of positions in the input chains. */ + int pos; + +- /* The position in the chains of SRC and DST dataflow sets. */ +- int pos_src; ++ /* The position in the chain of DST dataflow set. */ + int pos_dst; + }; + ++/* Buffer for location list sorting and its allocated size. */ ++static struct variable_union_info *vui_vec; ++static int vui_allocated; ++ + /* Compare function for qsort, order the structures by POS element. */ + + static int +@@ -1263,14 +1268,9 @@ variable_union (void **slot, void *data) + } + if (k < src->n_var_parts) + { +- enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; +- +- if (! flag_var_tracking_uninit) +- status = VAR_INIT_STATUS_INITIALIZED; +- + if (dstp) + *dstp = (void *) src; +- unshare_variable (set, src, status); ++ unshare_variable (set, src, VAR_INIT_STATUS_UNKNOWN); + } + else + { +@@ -1311,13 +1311,7 @@ variable_union (void **slot, void *data) + + if ((dst->refcount > 1 || shared_hash_shared (set->vars)) + && dst->n_var_parts != k) +- { +- enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; +- +- if (! flag_var_tracking_uninit) +- status = VAR_INIT_STATUS_INITIALIZED; +- dst = unshare_variable (set, dst, status); +- } ++ dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN); + + i = src->n_var_parts - 1; + j = dst->n_var_parts - 1; +@@ -1366,70 +1360,152 @@ variable_union (void **slot, void *data) + dst_l = 0; + for (node = dst->var_part[j].loc_chain; node; node = node->next) + dst_l++; +- vui = XCNEWVEC (struct variable_union_info, src_l + dst_l); + +- /* Fill in the locations from DST. */ +- for (node = dst->var_part[j].loc_chain, jj = 0; node; +- node = node->next, jj++) ++ if (dst_l == 1) + { +- vui[jj].lc = node; +- vui[jj].pos_dst = jj; ++ /* The most common case, much simpler, no qsort is needed. */ ++ location_chain dstnode = dst->var_part[j].loc_chain; ++ dst->var_part[k].loc_chain = dstnode; ++ dst->var_part[k].offset = dst->var_part[j].offset; ++ node2 = dstnode; ++ for (node = src->var_part[i].loc_chain; node; node = node->next) ++ if (!((REG_P (dstnode->loc) ++ && REG_P (node->loc) ++ && REGNO (dstnode->loc) == REGNO (node->loc)) ++ || rtx_equal_p (dstnode->loc, node->loc))) ++ { ++ location_chain new_node; + +- /* Value larger than a sum of 2 valid positions. */ +- vui[jj].pos_src = src_l + dst_l; ++ /* Copy the location from SRC. */ ++ new_node = (location_chain) pool_alloc (loc_chain_pool); ++ new_node->loc = node->loc; ++ new_node->init = node->init; ++ if (!node->set_src || MEM_P (node->set_src)) ++ new_node->set_src = NULL; ++ else ++ new_node->set_src = node->set_src; ++ node2->next = new_node; ++ node2 = new_node; ++ } ++ node2->next = NULL; + } +- +- /* Fill in the locations from SRC. */ +- n = dst_l; +- for (node = src->var_part[i].loc_chain, ii = 0; node; +- node = node->next, ii++) ++ else + { +- /* Find location from NODE. */ +- for (jj = 0; jj < dst_l; jj++) ++ if (src_l + dst_l > vui_allocated) + { +- if ((REG_P (vui[jj].lc->loc) +- && REG_P (node->loc) +- && REGNO (vui[jj].lc->loc) == REGNO (node->loc)) +- || rtx_equal_p (vui[jj].lc->loc, node->loc)) +- { +- vui[jj].pos_src = ii; +- break; +- } ++ vui_allocated = MAX (vui_allocated * 2, src_l + dst_l); ++ vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec, ++ vui_allocated); + } +- if (jj >= dst_l) /* The location has not been found. */ ++ vui = vui_vec; ++ ++ /* Fill in the locations from DST. */ ++ for (node = dst->var_part[j].loc_chain, jj = 0; node; ++ node = node->next, jj++) + { +- location_chain new_node; ++ vui[jj].lc = node; ++ vui[jj].pos_dst = jj; + +- /* Copy the location from SRC. */ +- new_node = (location_chain) pool_alloc (loc_chain_pool); +- new_node->loc = node->loc; +- new_node->init = node->init; +- if (!node->set_src || MEM_P (node->set_src)) +- new_node->set_src = NULL; +- else +- new_node->set_src = node->set_src; +- vui[n].lc = new_node; +- vui[n].pos_src = ii; +- vui[n].pos_dst = src_l + dst_l; +- n++; ++ /* Pos plus value larger than a sum of 2 valid positions. */ ++ vui[jj].pos = jj + src_l + dst_l; + } +- } + +- for (ii = 0; ii < src_l + dst_l; ii++) +- vui[ii].pos = vui[ii].pos_src + vui[ii].pos_dst; ++ /* Fill in the locations from SRC. */ ++ n = dst_l; ++ for (node = src->var_part[i].loc_chain, ii = 0; node; ++ node = node->next, ii++) ++ { ++ /* Find location from NODE. */ ++ for (jj = 0; jj < dst_l; jj++) ++ { ++ if ((REG_P (vui[jj].lc->loc) ++ && REG_P (node->loc) ++ && REGNO (vui[jj].lc->loc) == REGNO (node->loc)) ++ || rtx_equal_p (vui[jj].lc->loc, node->loc)) ++ { ++ vui[jj].pos = jj + ii; ++ break; ++ } ++ } ++ if (jj >= dst_l) /* The location has not been found. */ ++ { ++ location_chain new_node; + +- qsort (vui, n, sizeof (struct variable_union_info), +- variable_union_info_cmp_pos); ++ /* Copy the location from SRC. */ ++ new_node = (location_chain) pool_alloc (loc_chain_pool); ++ new_node->loc = node->loc; ++ new_node->init = node->init; ++ if (!node->set_src || MEM_P (node->set_src)) ++ new_node->set_src = NULL; ++ else ++ new_node->set_src = node->set_src; ++ vui[n].lc = new_node; ++ vui[n].pos_dst = src_l + dst_l; ++ vui[n].pos = ii + src_l + dst_l; ++ n++; ++ } ++ } + +- /* Reconnect the nodes in sorted order. */ +- for (ii = 1; ii < n; ii++) +- vui[ii - 1].lc->next = vui[ii].lc; +- vui[n - 1].lc->next = NULL; ++ if (dst_l == 2) ++ { ++ /* Special case still very common case. For dst_l == 2 ++ all entries dst_l ... n-1 are sorted, with for i >= dst_l ++ vui[i].pos == i + src_l + dst_l. */ ++ if (vui[0].pos > vui[1].pos) ++ { ++ /* Order should be 1, 0, 2... */ ++ dst->var_part[k].loc_chain = vui[1].lc; ++ vui[1].lc->next = vui[0].lc; ++ if (n >= 3) ++ { ++ vui[0].lc->next = vui[2].lc; ++ vui[n - 1].lc->next = NULL; ++ } ++ else ++ vui[0].lc->next = NULL; ++ ii = 3; ++ } ++ else ++ { ++ dst->var_part[k].loc_chain = vui[0].lc; ++ if (n >= 3 && vui[2].pos < vui[1].pos) ++ { ++ /* Order should be 0, 2, 1, 3... */ ++ vui[0].lc->next = vui[2].lc; ++ vui[2].lc->next = vui[1].lc; ++ if (n >= 4) ++ { ++ vui[1].lc->next = vui[3].lc; ++ vui[n - 1].lc->next = NULL; ++ } ++ else ++ vui[1].lc->next = NULL; ++ ii = 4; ++ } ++ else ++ { ++ /* Order should be 0, 1, 2... */ ++ ii = 1; ++ vui[n - 1].lc->next = NULL; ++ } ++ } ++ for (; ii < n; ii++) ++ vui[ii - 1].lc->next = vui[ii].lc; ++ } ++ else ++ { ++ qsort (vui, n, sizeof (struct variable_union_info), ++ variable_union_info_cmp_pos); + +- dst->var_part[k].loc_chain = vui[0].lc; +- dst->var_part[k].offset = dst->var_part[j].offset; ++ /* Reconnect the nodes in sorted order. */ ++ for (ii = 1; ii < n; ii++) ++ vui[ii - 1].lc->next = vui[ii].lc; ++ vui[n - 1].lc->next = NULL; ++ dst->var_part[k].loc_chain = vui[0].lc; ++ } + +- free (vui); ++ dst->var_part[k].offset = dst->var_part[j].offset; ++ } + i--; + j--; + } +@@ -1477,17 +1553,18 @@ variable_union (void **slot, void *data) + dst->var_part[k].cur_loc = NULL; + } + +- for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++) +- { +- location_chain node, node2; +- for (node = src->var_part[i].loc_chain; node; node = node->next) +- for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next) +- if (rtx_equal_p (node->loc, node2->loc)) +- { +- if (node->init > node2->init) +- node2->init = node->init; +- } +- } ++ if (flag_var_tracking_uninit) ++ for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++) ++ { ++ location_chain node, node2; ++ for (node = src->var_part[i].loc_chain; node; node = node->next) ++ for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next) ++ if (rtx_equal_p (node->loc, node2->loc)) ++ { ++ if (node->init > node2->init) ++ node2->init = node->init; ++ } ++ } + + /* Continue traversing the hash table. */ + return 1; +@@ -1522,14 +1599,7 @@ variable_canonicalize (void **slot, void + } + } + if (k < src->n_var_parts) +- { +- enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; +- +- if (! flag_var_tracking_uninit) +- status = VAR_INIT_STATUS_INITIALIZED; +- +- unshare_variable (set, src, status); +- } ++ unshare_variable (set, src, VAR_INIT_STATUS_UNKNOWN); + return 1; + } + +@@ -1650,34 +1720,6 @@ dataflow_set_different_1 (void **slot, v + return 1; + } + +-/* Compare variable *SLOT with the same variable in hash table DATA +- and set DATAFLOW_SET_DIFFERENT_VALUE if they are different. */ +- +-static int +-dataflow_set_different_2 (void **slot, void *data) +-{ +- htab_t htab = (htab_t) data; +- variable var1, var2; +- +- var1 = *(variable *) slot; +- var2 = (variable) htab_find_with_hash (htab, var1->decl, +- VARIABLE_HASH_VAL (var1->decl)); +- if (!var2) +- { +- dataflow_set_different_value = true; +- +- /* Stop traversing the hash table. */ +- return 0; +- } +- +- /* If both variables are defined they have been already checked for +- equivalence. */ +- gcc_assert (!variable_different_p (var1, var2, false)); +- +- /* Continue traversing the hash table. */ +- return 1; +-} +- + /* Return true if dataflow sets OLD_SET and NEW_SET differ. */ + + static bool +@@ -1694,14 +1736,9 @@ dataflow_set_different (dataflow_set *ol + + htab_traverse (shared_hash_htab (old_set->vars), dataflow_set_different_1, + shared_hash_htab (new_set->vars)); +- if (!dataflow_set_different_value) +- { +- /* We have compared the variables which are in both hash tables +- so now only check whether there are some variables in NEW_SET->VARS +- which are not in OLD_SET->VARS. */ +- htab_traverse (shared_hash_htab (new_set->vars), dataflow_set_different_2, +- shared_hash_htab (old_set->vars)); +- } ++ /* No need to traverse the second hashtab, if both have the same number ++ of elements and the second one had all entries found in the first one, ++ then it can't have any extra entries. */ + return dataflow_set_different_value; + } + +@@ -2215,15 +2252,11 @@ compute_bb_dataflow (basic_block bb) + case MO_USE: + { + rtx loc = VTI (bb)->mos[i].u.loc; +- enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED; +- +- if (! flag_var_tracking_uninit) +- status = VAR_INIT_STATUS_INITIALIZED; + + if (GET_CODE (loc) == REG) +- var_reg_set (out, loc, status, NULL); ++ var_reg_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL); + else if (GET_CODE (loc) == MEM) +- var_mem_set (out, loc, status, NULL); ++ var_mem_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL); + } + break; + +@@ -2262,10 +2295,12 @@ compute_bb_dataflow (basic_block bb) + if (! flag_var_tracking_uninit) + src_status = VAR_INIT_STATUS_INITIALIZED; + else +- src_status = find_src_status (in, set_src); ++ { ++ src_status = find_src_status (in, set_src); + +- if (src_status == VAR_INIT_STATUS_UNKNOWN) +- src_status = find_src_status (out, set_src); ++ if (src_status == VAR_INIT_STATUS_UNKNOWN) ++ src_status = find_src_status (out, set_src); ++ } + + set_src = find_src_set_src (in, set_src); + +@@ -2609,6 +2644,9 @@ set_variable_part (dataflow_set *set, rt + variable var; + void **slot = shared_hash_find_slot (set->vars, decl); + ++ if (! flag_var_tracking_uninit) ++ initialized = VAR_INIT_STATUS_INITIALIZED; ++ + if (!slot || !*slot) + { + if (!slot) +@@ -2815,10 +2853,8 @@ delete_variable_part (dataflow_set *set, + && REGNO (node->loc) == REGNO (loc)) + || rtx_equal_p (node->loc, loc)) + { +- enum var_init_status status = VAR_INIT_STATUS_UNKNOWN; +- if (! flag_var_tracking_uninit) +- status = VAR_INIT_STATUS_INITIALIZED; +- var = unshare_variable (set, var, status); ++ var = unshare_variable (set, var, ++ VAR_INIT_STATUS_UNKNOWN); + break; + } + } +@@ -2893,9 +2929,6 @@ emit_note_insn_var_location (void **varp + + gcc_assert (var->decl); + +- if (! flag_var_tracking_uninit) +- initialized = VAR_INIT_STATUS_INITIALIZED; +- + complete = true; + last_limit = 0; + n_var_parts = 0; +@@ -3148,14 +3181,11 @@ emit_notes_in_bb (basic_block bb) + case MO_USE: + { + rtx loc = VTI (bb)->mos[i].u.loc; +- +- enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED; +- if (! flag_var_tracking_uninit) +- status = VAR_INIT_STATUS_INITIALIZED; ++ + if (GET_CODE (loc) == REG) +- var_reg_set (&set, loc, status, NULL); ++ var_reg_set (&set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL); + else +- var_mem_set (&set, loc, status, NULL); ++ var_mem_set (&set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL); + + emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN); + } +@@ -3553,6 +3583,10 @@ vt_finalize (void) + free_alloc_pool (var_pool); + free_alloc_pool (loc_chain_pool); + free_alloc_pool (shared_hash_pool); ++ if (vui_vec) ++ free (vui_vec); ++ vui_vec = NULL; ++ vui_allocated = 0; + } + + /* The entry point to variable tracking pass. */ diff --git a/gcc44-unique-object.patch b/gcc44-unique-object.patch new file mode 100644 index 0000000..1396e69 --- /dev/null +++ b/gcc44-unique-object.patch @@ -0,0 +1,142 @@ +2009-07-22 Jason Merrill + + * config/elfos.h (ASM_DECLARE_OBJECT_NAME): Use gnu_unique_object + type if available. + * configure.ac: Test for it. + * configure, config.in: Regenerate. + +--- gcc/config/elfos.h.jj 2009-04-14 15:51:24.000000000 +0200 ++++ gcc/config/elfos.h 2009-07-23 09:25:46.000000000 +0200 +@@ -289,24 +289,37 @@ see the files COPYING3 and COPYING.RUNTI + + /* Write the extra assembler code needed to declare an object properly. */ + +-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ +- do \ +- { \ +- HOST_WIDE_INT size; \ +- \ +- ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \ +- \ +- size_directive_output = 0; \ +- if (!flag_inhibit_size_directive \ +- && (DECL) && DECL_SIZE (DECL)) \ +- { \ +- size_directive_output = 1; \ +- size = int_size_in_bytes (TREE_TYPE (DECL)); \ +- ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \ +- } \ +- \ +- ASM_OUTPUT_LABEL (FILE, NAME); \ +- } \ ++#ifdef HAVE_GAS_GNU_UNIQUE_OBJECT ++#define USE_GNU_UNIQUE_OBJECT 1 ++#else ++#define USE_GNU_UNIQUE_OBJECT 0 ++#endif ++ ++#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ ++ do \ ++ { \ ++ HOST_WIDE_INT size; \ ++ \ ++ /* For template static data member instantiations or \ ++ inline fn local statics, use gnu_unique_object so that \ ++ they will be combined even under RTLD_LOCAL. */ \ ++ if (USE_GNU_UNIQUE_OBJECT \ ++ && !DECL_ARTIFICIAL (DECL) && DECL_ONE_ONLY (DECL)) \ ++ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "gnu_unique_object"); \ ++ else \ ++ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \ ++ \ ++ size_directive_output = 0; \ ++ if (!flag_inhibit_size_directive \ ++ && (DECL) && DECL_SIZE (DECL)) \ ++ { \ ++ size_directive_output = 1; \ ++ size = int_size_in_bytes (TREE_TYPE (DECL)); \ ++ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size); \ ++ } \ ++ \ ++ ASM_OUTPUT_LABEL (FILE, NAME); \ ++ } \ + while (0) + + /* Output the size directive for a decl in rest_of_decl_compilation +--- gcc/configure.ac.jj 2009-03-28 09:53:59.000000000 +0100 ++++ gcc/configure.ac 2009-07-23 09:25:46.000000000 +0200 +@@ -3299,6 +3299,12 @@ gcc_GAS_CHECK_FEATURE([.lcomm with align + [AC_DEFINE(HAVE_GAS_LCOMM_WITH_ALIGNMENT, 1, + [Define if your assembler supports .lcomm with an alignment field.])]) + ++gcc_GAS_CHECK_FEATURE([gnu_unique_object], gcc_cv_as_gnu_unique_object, ++ [elf,2,19,52],, ++[.type foo, @gnu_unique_object],, ++[AC_DEFINE(HAVE_GAS_GNU_UNIQUE_OBJECT, 1, ++ [Define if your assembler supports @gnu_unique_object.])]) ++ + AC_CACHE_CHECK([assembler for tolerance to line number 0], + [gcc_cv_as_line_zero], + [gcc_cv_as_line_zero=no +--- gcc/configure.jj 2009-03-28 09:53:37.000000000 +0100 ++++ gcc/configure 2009-07-23 09:26:52.000000000 +0200 +@@ -24288,6 +24288,44 @@ _ACEOF + + fi + ++echo "$as_me:$LINENO: checking assembler for gnu_unique_object" >&5 ++echo $ECHO_N "checking assembler for gnu_unique_object... $ECHO_C" >&6 ++if test "${gcc_cv_as_gnu_unique_object+set}" = set; then ++ echo $ECHO_N "(cached) $ECHO_C" >&6 ++else ++ gcc_cv_as_gnu_unique_object=no ++ if test $in_tree_gas = yes; then ++ if test $in_tree_gas_is_elf = yes \ ++ && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 52` ++ then gcc_cv_as_gnu_unique_object=yes ++fi ++ elif test x$gcc_cv_as != x; then ++ echo '.type foo, @gnu_unique_object' > conftest.s ++ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5' ++ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 ++ (eval $ac_try) 2>&5 ++ ac_status=$? ++ echo "$as_me:$LINENO: \$? = $ac_status" >&5 ++ (exit $ac_status); }; } ++ then ++ gcc_cv_as_gnu_unique_object=yes ++ else ++ echo "configure: failed program was" >&5 ++ cat conftest.s >&5 ++ fi ++ rm -f conftest.o conftest.s ++ fi ++fi ++echo "$as_me:$LINENO: result: $gcc_cv_as_gnu_unique_object" >&5 ++echo "${ECHO_T}$gcc_cv_as_gnu_unique_object" >&6 ++if test $gcc_cv_as_gnu_unique_object = yes; then ++ ++cat >>confdefs.h <<\_ACEOF ++#define HAVE_GAS_GNU_UNIQUE_OBJECT 1 ++_ACEOF ++ ++fi ++ + echo "$as_me:$LINENO: checking assembler for tolerance to line number 0" >&5 + echo $ECHO_N "checking assembler for tolerance to line number 0... $ECHO_C" >&6 + if test "${gcc_cv_as_line_zero+set}" = set; then +--- gcc/config.in.jj 2009-02-16 22:48:20.000000000 +0100 ++++ gcc/config.in 2009-07-23 09:26:56.000000000 +0200 +@@ -845,6 +845,12 @@ + #endif + + ++/* Define if your assembler supports @gnu_unique_object. */ ++#ifndef USED_FOR_TARGET ++#undef HAVE_GAS_GNU_UNIQUE_OBJECT ++#endif ++ ++ + /* Define if your assembler and linker support .hidden. */ + #undef HAVE_GAS_HIDDEN + diff --git a/gcc44-unwind-debug-hook.patch b/gcc44-unwind-debug-hook.patch new file mode 100644 index 0000000..e084be5 --- /dev/null +++ b/gcc44-unwind-debug-hook.patch @@ -0,0 +1,46 @@ +2009-05-27 Tom Tromey + + * unwind-dw2.c (_Unwind_DebugHook): New function. + (uw_install_context): Call _Unwind_DebugHook. + +--- gcc/unwind-dw2.c (revision 147933) ++++ gcc/unwind-dw2.c (revision 147934) +@@ -1473,18 +1473,31 @@ uw_init_context_1 (struct _Unwind_Contex + context->ra = __builtin_extract_return_addr (outer_ra); + } + ++static void _Unwind_DebugHook (void *, void *) __attribute__ ((__noinline__)); ++ ++/* This function is called during unwinding. It is intended as a hook ++ for a debugger to intercept exceptions. CFA is the CFA of the ++ target frame. HANDLER is the PC to which control will be ++ transferred. */ ++static void ++_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)), ++ void *handler __attribute__ ((__unused__))) ++{ ++ asm (""); ++} + + /* Install TARGET into CURRENT so that we can return to it. This is a + macro because __builtin_eh_return must be invoked in the context of + our caller. */ + +-#define uw_install_context(CURRENT, TARGET) \ +- do \ +- { \ +- long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ +- void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ +- __builtin_eh_return (offset, handler); \ +- } \ ++#define uw_install_context(CURRENT, TARGET) \ ++ do \ ++ { \ ++ long offset = uw_install_context_1 ((CURRENT), (TARGET)); \ ++ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \ ++ _Unwind_DebugHook ((TARGET)->cfa, handler); \ ++ __builtin_eh_return (offset, handler); \ ++ } \ + while (0) + + static long diff --git a/mingw32-gcc.spec b/mingw32-gcc.spec index 51ccd31..0e380b2 100644 --- a/mingw32-gcc.spec +++ b/mingw32-gcc.spec @@ -1,14 +1,14 @@ -%define __os_install_post /usr/lib/rpm/brp-compress %{nil} +%global __os_install_post /usr/lib/rpm/brp-compress %{nil} -%define DATE 20090319 -%define SVNREV 144967 +%global DATE 20090818 +%global SVNREV 150873 Name: mingw32-gcc -Version: 4.4.0 -Release: 0.8%{?dist} +Version: 4.4.1 +Release: 1%{?dist} Summary: MinGW Windows cross-compiler (GCC) for C -License: GPLv3+ and GPLv2+ with exceptions +License: GPLv3+, GPLv3+ with exceptions and GPLv2+ with exceptions Group: Development/Languages # We use the same source as Fedora's native gcc. @@ -25,8 +25,6 @@ Patch2: gcc44-c++-builtin-redecl.patch Patch3: gcc44-ia64-libunwind.patch Patch4: gcc44-java-nomulti.patch Patch5: gcc44-ppc32-retaddr.patch -Patch7: gcc44-pr27898.patch -Patch8: gcc44-pr32139.patch Patch9: gcc44-pr33763.patch Patch10: gcc44-rh330771.patch Patch11: gcc44-rh341221.patch @@ -37,13 +35,15 @@ Patch16: gcc44-libgomp-omp_h-multilib.patch Patch20: gcc44-libtool-no-rpath.patch Patch21: gcc44-cloog-dl.patch Patch22: gcc44-raw-string.patch -Patch24: gcc44-atom.patch -Patch25: gcc44-pr39226.patch -Patch26: gcc44-power7.patch -Patch27: gcc44-power7-2.patch +Patch24: gcc44-unwind-debug-hook.patch +Patch25: gcc44-power7.patch +Patch26: gcc44-power7-2.patch +Patch27: gcc44-power7-3.patch Patch28: gcc44-pr38757.patch -Patch29: gcc44-pr37959.patch -Patch30: gcc44-memmove-opt.patch +#Patch29: gcc44-libstdc++-docs.patch +Patch30: gcc44-rh503816-1.patch +Patch31: gcc44-rh503816-2.patch +Patch32: gcc44-unique-object.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) @@ -128,8 +128,6 @@ MinGW Windows cross-compiler for FORTRAN. %patch3 -p0 -b .ia64-libunwind~ %patch4 -p0 -b .java-nomulti~ %patch5 -p0 -b .ppc32-retaddr~ -%patch7 -p0 -b .pr27898~ -%patch8 -p0 -b .pr32139~ %patch9 -p0 -b .pr33763~ %patch10 -p0 -b .rh330771~ %patch11 -p0 -b .rh341221~ @@ -140,13 +138,17 @@ MinGW Windows cross-compiler for FORTRAN. %patch20 -p0 -b .libtool-no-rpath~ %patch21 -p0 -b .cloog-dl~ %patch22 -p0 -b .raw-string~ -%patch24 -p0 -b .atom~ -%patch25 -p0 -b .pr39226~ -%patch26 -p0 -b .power7~ -%patch27 -p0 -b .power7-2~ +%patch24 -p0 -b .unwind-debug-hook~ +%patch25 -p0 -b .power7~ +%patch26 -p0 -b .power7-2~ +%patch27 -p0 -b .power7-3~ %patch28 -p0 -b .pr38757~ -%patch29 -p0 -b .pr37959~ -%patch30 -p0 -b .memmove-opt~ +%patch30 -p0 -b .rh503816-1~ +%patch31 -p0 -b .rh503816-2~ +%patch32 -p0 -b .unique-object~ + +sed -i -e 's/4\.4\.2/%{version}/' gcc/BASE-VER +echo 'Fedora MinGW %{version}-%{release}' > gcc/DEV-PHASE %build @@ -216,7 +218,7 @@ rm -rf $RPM_BUILD_ROOT %files -%defattr(-,root,root) +%defattr(-,root,root,-) %{_bindir}/i686-pc-mingw32-gcc %{_bindir}/i686-pc-mingw32-gcc-%{version} %{_bindir}/i686-pc-mingw32-gccbug @@ -253,7 +255,7 @@ rm -rf $RPM_BUILD_ROOT %files -n mingw32-cpp -%defattr(-,root,root) +%defattr(-,root,root,-) /lib/i686-pc-mingw32-cpp %{_bindir}/i686-pc-mingw32-cpp %{_mandir}/man1/i686-pc-mingw32-cpp.1* @@ -263,7 +265,7 @@ rm -rf $RPM_BUILD_ROOT %files c++ -%defattr(-,root,root) +%defattr(-,root,root,-) %{_bindir}/i686-pc-mingw32-g++ %{_bindir}/i686-pc-mingw32-c++ %{_mandir}/man1/i686-pc-mingw32-g++.1* @@ -275,19 +277,19 @@ rm -rf $RPM_BUILD_ROOT %files objc -%defattr(-,root,root) +%defattr(-,root,root,-) %{_libdir}/gcc/i686-pc-mingw32/%{version}/include/objc/ %{_libdir}/gcc/i686-pc-mingw32/%{version}/libobjc.a %{_libexecdir}/gcc/i686-pc-mingw32/%{version}/cc1obj %files objc++ -%defattr(-,root,root) +%defattr(-,root,root,-) %{_libexecdir}/gcc/i686-pc-mingw32/%{version}/cc1objplus %files gfortran -%defattr(-,root,root) +%defattr(-,root,root,-) %{_bindir}/i686-pc-mingw32-gfortran %{_mandir}/man1/i686-pc-mingw32-gfortran.1* %{_libdir}/gcc/i686-pc-mingw32/%{version}/libgfortran.a @@ -296,6 +298,12 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Sun Aug 23 2009 Kalev Lember - 4.4.1-1 +- Update to gcc 4.4.1 20090818 svn 150873. +- Patches taken from native Fedora gcc-4.4.1-6. +- Replaced %%define with %%global and updated %%defattr. +- Changed license to match native Fedora gcc package. + * Sat Jul 25 2009 Fedora Release Engineering - 4.4.0-0.8 - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild diff --git a/sources b/sources index 155c3d1..7fd7eb9 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -2992035eaf092d72eb98ad16b173f737 gcc-4.4.0-20090319.tar.bz2 +a280c87e7d0a44a99a6bc84bbe3eb86d gcc-4.4.1-20090818.tar.bz2