From b03a15ac61b422ce26fc67c5b0f440669041e534 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 27 Apr 2009 12:43:32 +0000 Subject: [PATCH] 4.4.0-3 --- .cvsignore | 2 +- gcc.spec | 44 +- gcc44-cswtch.patch | 129 -- gcc44-power7-2.patch | 328 ++++ gcc44-power7-3.patch | 3523 ++++++++++++++++++++++++++++++++++++++++ gcc44-pr39543.patch | 293 ---- gcc44-pr39794.patch | 309 ---- gcc44-pr39856.patch | 43 + gcc44-pr39867.patch | 70 - gcc44-pr39903.patch | 79 + gcc44-rh459374-1.patch | 239 --- gcc44-rh459374-2.patch | 175 -- gcc44-rh459374-3.patch | 468 ------ sources | 2 +- 14 files changed, 3999 insertions(+), 1705 deletions(-) delete mode 100644 gcc44-cswtch.patch create mode 100644 gcc44-power7-2.patch create mode 100644 gcc44-power7-3.patch delete mode 100644 gcc44-pr39543.patch delete mode 100644 gcc44-pr39794.patch create mode 100644 gcc44-pr39856.patch delete mode 100644 gcc44-pr39867.patch create mode 100644 gcc44-pr39903.patch delete mode 100644 gcc44-rh459374-1.patch delete mode 100644 gcc44-rh459374-2.patch delete mode 100644 gcc44-rh459374-3.patch diff --git a/.cvsignore b/.cvsignore index 3b92ddd..0762acc 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,2 +1,2 @@ fastjar-0.97.tar.gz -gcc-4.4.0-20090424.tar.bz2 +gcc-4.4.0-20090427.tar.bz2 diff --git a/gcc.spec b/gcc.spec index 0168752..660fab7 100644 --- a/gcc.spec +++ b/gcc.spec @@ -1,9 +1,9 @@ -%define DATE 20090424 -%define SVNREV 146674 +%define DATE 20090427 +%define SVNREV 146836 %define gcc_version 4.4.0 # Note, gcc_release must be integer, if you want to add suffixes to # %{release}, append them after %{gcc_release} on Release: line. -%define gcc_release 2 +%define gcc_release 3 %define _unpackaged_files_terminate_build 0 %define multilib_64_archs sparc64 ppc64 s390x x86_64 %define include_gappletviewer 1 @@ -147,15 +147,12 @@ Patch20: gcc44-libtool-no-rpath.patch Patch21: gcc44-cloog-dl.patch Patch22: gcc44-raw-string.patch Patch24: gcc44-atom.patch -Patch26: gcc44-power7.patch +Patch25: gcc44-power7.patch +Patch26: gcc44-power7-2.patch +Patch27: gcc44-power7-3.patch Patch28: gcc44-pr38757.patch -Patch30: gcc44-pr39543.patch -Patch31: gcc44-pr39794.patch -Patch32: gcc44-rh459374-1.patch -Patch33: gcc44-rh459374-2.patch -Patch34: gcc44-rh459374-3.patch -Patch35: gcc44-cswtch.patch -Patch36: gcc44-pr39867.patch +Patch29: gcc44-pr39856.patch +Patch30: gcc44-pr39903.patch Patch1000: fastjar-0.97-segfault.patch @@ -441,15 +438,12 @@ which are required to compile with the GNAT. %endif %patch22 -p0 -b .raw-string~ %patch24 -p0 -b .atom~ -%patch26 -p0 -b .power7~ +%patch25 -p0 -b .power7~ +%patch26 -p0 -b .power7-2~ +%patch27 -p0 -b .power7-3~ %patch28 -p0 -b .pr38757~ -%patch30 -p0 -b .pr39543~ -%patch31 -p0 -b .pr39794~ -%patch32 -p0 -b .rh459374-1~ -%patch33 -p0 -b .rh459374-2~ -%patch34 -p0 -b .rh459374-3~ -%patch35 -p0 -b .cswtch~ -%patch36 -p0 -b .pr39867~ +%patch29 -p0 -b .pr39856~ +%patch30 -p0 -b .pr39903~ # This testcase doesn't compile. rm libjava/testsuite/libjava.lang/PR35020* @@ -1760,6 +1754,16 @@ fi %doc rpm.doc/changelogs/libmudflap/ChangeLog* %changelog +* Mon Apr 27 2009 Jakub Jelinek 4.4.0-3 +- update from gcc-4_4-branch + - PR bootstrap/39739 + - fix -Wunused-value (#497545, PR c/39889) +- backport further power7-meissner branch changes (#497816) +- fix reg-stack ICE on SPEC2k6 453.povray with -m32 -O3 -msse3 + (PR target/39856) +- fix x86_64 ICE on passing structure with flexible array member + (PR target/39903) + * Fri Apr 24 2009 Jakub Jelinek 4.4.0-2 - update from gcc-4_4-branch - PR c++/38228 @@ -1818,7 +1822,7 @@ fi tree-optimization/39557 - emit debuginfo for block local externs in C (PR debug/39563) - fix -maltivec conditional vector macro (PR target/39558) -- teach fwprop to handle asm (PR rtl-optimization/39543) +- teach fwprop to handle asm (PR inline-asm/39543) * Tue Mar 24 2009 Jakub Jelinek 4.4.0-0.29 - update from trunk diff --git a/gcc44-cswtch.patch b/gcc44-cswtch.patch deleted file mode 100644 index e77118b..0000000 --- a/gcc44-cswtch.patch +++ /dev/null @@ -1,129 +0,0 @@ -2009-04-21 Martin Jambor - - * tree-switch-conversion.c (constructor_contains_same_values_p): - New function. - (build_one_array): Create assigns of constants if possible. - - * gcc.dg/tree-ssa/cswtch-2.c: New test. - ---- gcc/tree-switch-conversion.c.jj 2009-03-28 18:11:43.000000000 +0100 -+++ gcc/tree-switch-conversion.c 2009-04-22 20:09:45.000000000 +0200 -@@ -459,6 +459,28 @@ build_constructors (gimple swtch) - } - } - -+/* If all values in the constructor vector are the same, return the value. -+ Otherwise return NULL_TREE. Not supposed to be called for empty -+ vectors. */ -+ -+static tree -+constructor_contains_same_values_p (VEC (constructor_elt, gc) *vec) -+{ -+ int i, len = VEC_length (constructor_elt, vec); -+ tree prev = NULL_TREE; -+ -+ for (i = 0; i < len; i++) -+ { -+ constructor_elt *elt = VEC_index (constructor_elt, vec, i); -+ -+ if (!prev) -+ prev = elt->value; -+ else if (!operand_equal_p (elt->value, prev, OEP_ONLY_CONST)) -+ return NULL_TREE; -+ } -+ return prev; -+} -+ - /* Create an appropriate array type and declaration and assemble a static array - variable. Also create a load statement that initializes the variable in - question with a value from the static array. SWTCH is the switch statement -@@ -472,35 +494,44 @@ static void - build_one_array (gimple swtch, int num, tree arr_index_type, gimple phi, - tree tidx) - { -- tree array_type, ctor, decl, value_type, name, fetch; -+ tree name, cst; - gimple load; - gimple_stmt_iterator gsi; - - gcc_assert (info.default_values[num]); -- value_type = TREE_TYPE (info.default_values[num]); -- array_type = build_array_type (value_type, arr_index_type); -- -- ctor = build_constructor (array_type, info.constructors[num]); -- TREE_CONSTANT (ctor) = true; -- -- decl = build_decl (VAR_DECL, NULL_TREE, array_type); -- TREE_STATIC (decl) = 1; -- DECL_INITIAL (decl) = ctor; -- -- DECL_NAME (decl) = create_tmp_var_name ("CSWTCH"); -- DECL_ARTIFICIAL (decl) = 1; -- TREE_CONSTANT (decl) = 1; -- add_referenced_var (decl); -- varpool_mark_needed_node (varpool_node (decl)); -- varpool_finalize_decl (decl); -- mark_sym_for_renaming (decl); - - name = make_ssa_name (SSA_NAME_VAR (PHI_RESULT (phi)), NULL); - info.target_inbound_names[num] = name; - -- fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, -- NULL_TREE); -- load = gimple_build_assign (name, fetch); -+ cst = constructor_contains_same_values_p (info.constructors[num]); -+ if (cst) -+ load = gimple_build_assign (name, cst); -+ else -+ { -+ tree array_type, ctor, decl, value_type, fetch; -+ -+ value_type = TREE_TYPE (info.default_values[num]); -+ array_type = build_array_type (value_type, arr_index_type); -+ -+ ctor = build_constructor (array_type, info.constructors[num]); -+ TREE_CONSTANT (ctor) = true; -+ -+ decl = build_decl (VAR_DECL, NULL_TREE, array_type); -+ TREE_STATIC (decl) = 1; -+ DECL_INITIAL (decl) = ctor; -+ -+ DECL_NAME (decl) = create_tmp_var_name ("CSWTCH"); -+ DECL_ARTIFICIAL (decl) = 1; -+ TREE_CONSTANT (decl) = 1; -+ add_referenced_var (decl); -+ varpool_mark_needed_node (varpool_node (decl)); -+ varpool_finalize_decl (decl); -+ mark_sym_for_renaming (decl); -+ -+ fetch = build4 (ARRAY_REF, value_type, decl, tidx, NULL_TREE, -+ NULL_TREE); -+ load = gimple_build_assign (name, fetch); -+ } - SSA_NAME_DEF_STMT (name) = load; - - gsi = gsi_for_stmt (swtch); ---- gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c.jj 2009-04-22 20:01:40.000000000 +0200 -+++ gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c 2009-04-22 20:01:40.000000000 +0200 -@@ -0,0 +1,21 @@ -+/* { dg-do compile } */ -+/* { dg-options "-O2 -fdump-tree-switchconv" } */ -+ -+typedef enum { a = 5, b = 6, c = 7, d = 8, e = 9 } X; -+ -+int h1 (X x) -+{ -+ switch (x) { -+ case a: -+ case b: -+ case c: -+ case d: -+ case e: -+ return 1; -+ default: -+ return 0; -+ } -+} -+ -+/* { dg-final { scan-tree-dump-times "CSWTCH" 0 "switchconv" } } */ -+/* { dg-final { cleanup-tree-dump "switchconv" } } */ diff --git a/gcc44-power7-2.patch b/gcc44-power7-2.patch new file mode 100644 index 0000000..933f6a8 --- /dev/null +++ b/gcc44-power7-2.patch @@ -0,0 +1,328 @@ +2009-04-14 Michael Meissner + + * config/rs6000/rs6000.c (rs6000_secondary_reload_inner): Handle + more possible combinations of addresses. + + * 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. + + PR testsuite/39769 + * gcc.dg/vmx/3a-04.c (test): Don't rely on floating point equality + for testing the results of estimate instructions. + * gcc.dg/vmx/3a-04m.c (test): Ditto. + * gcc.dg/vmx/3a-05.c (test): Ditto. + +--- gcc/testsuite/gcc.dg/vmx/3a-05.c (revision 146069) ++++ gcc/testsuite/gcc.dg/vmx/3a-05.c (revision 146118) +@@ -14,9 +14,13 @@ f(vector float a, vector float b, vector + + static void test() + { +- check(vec_all_eq(f(((vector float){2,3,5,7}), ++ check(vec_all_gt(f(((vector float){2,3,5,7}), + ((vector float){11,13,17,19}), + ((vector float){23,29,31,37})), +- ((vector float){16.9092026, 18.7693329, -2.8233242, -92.9472198})), +- "f"); ++ ((vector float){16.90, 18.76, -2.83, -92.95})) ++ && vec_all_lt(f(((vector float){2,3,5,7}), ++ ((vector float){11,13,17,19}), ++ ((vector float){23,29,31,37})), ++ ((vector float){16.91, 18.77, -2.82, -92.94})), ++ "f"); + } +--- gcc/testsuite/gcc.dg/vmx/3a-04m.c (revision 146069) ++++ gcc/testsuite/gcc.dg/vmx/3a-04m.c (revision 146118) +@@ -10,9 +10,13 @@ f(vector float a, vector float b, vector + + static void test() + { +- check(vec_all_eq(f(((vector float){2,3,5,7}), ++ check(vec_all_gt(f(((vector float){2,3,5,7}), + ((vector float){11,13,17,19}), + ((vector float){23,29,31,37})), +- ((vector float){23.1818085, 29.2307587, 32.2940826, 128.368393})), ++ ((vector float){23.18, 29.23, 32.29, 128.36})) ++ && vec_all_lt(f(((vector float){2,3,5,7}), ++ ((vector float){11,13,17,19}), ++ ((vector float){23,29,31,37})), ++ ((vector float){23.19, 29.24, 32.30, 128.37})), + "f"); + } +--- gcc/testsuite/gcc.dg/vmx/3a-04.c (revision 146069) ++++ gcc/testsuite/gcc.dg/vmx/3a-04.c (revision 146118) +@@ -10,9 +10,13 @@ f(vector float a, vector float b, vector + + static void test() + { +- check(vec_all_eq(f(((vector float){2,3,5,7}), ++ check(vec_all_gt(f(((vector float){2,3,5,7}), + ((vector float){11,13,17,19}), + ((vector float){23,29,31,37})), +- ((vector float){23.1818085, 29.2307587, 32.2940826, 128.368393})), ++ ((vector float){23.18, 29.23, 32.29, 128.36})) ++ && vec_all_lt(f(((vector float){2,3,5,7}), ++ ((vector float){11,13,17,19}), ++ ((vector float){23,29,31,37})), ++ ((vector float){23.19, 29.24, 32.30, 128.37})), + "f"); + } +--- 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))])]) ++ ++;; 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))])]) + + ;; 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; + + if (TARGET_DEBUG_ADDR) + { +@@ -12595,7 +12600,8 @@ rs6000_secondary_reload_inner (rtx reg, + + 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); + } ++ ++ if (GET_CODE (addr) == PRE_MODIFY) ++ { ++ 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); ++ } ++ + 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; ++ 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 (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; + ++ /* 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: ++ + /* 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 */ + +- /* 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) ++ { ++ emit_insn (gen_rtx_SET (VOIDmode, scratch_or_premodify, addr)); ++ addr = scratch_or_premodify; ++ } ++ ++ /* 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; ++ } ++ ++ and_rtx = gen_rtx_SET (VOIDmode, ++ scratch, ++ gen_rtx_AND (Pmode, ++ addr, ++ and_op2)); ++ ++ 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..64b2cb5 --- /dev/null +++ b/gcc44-power7-3.patch @@ -0,0 +1,3523 @@ +--- 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; ++} +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/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)) +@@ -3785,15 +3846,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; + } + +@@ -3856,10 +3930,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; + } + +@@ -3900,10 +3976,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; + } + +@@ -4323,9 +4401,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 +@@ -4427,6 +4503,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 +@@ -4436,8 +4522,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)))) +@@ -4467,15 +4551,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 +@@ -5113,7 +5188,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) +@@ -5953,7 +6028,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); + +@@ -7869,7 +7950,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, +@@ -7934,6 +8016,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 }, +@@ -8083,6 +8193,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 }, +@@ -8091,6 +8204,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 }, +@@ -8508,6 +8636,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 }, +@@ -8533,15 +8702,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 }, +@@ -9046,11 +9206,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 +@@ -9059,6 +9220,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 +@@ -9366,8 +9561,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); +@@ -10156,6 +10353,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); +@@ -10169,6 +10367,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; +@@ -10201,6 +10400,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, +@@ -10241,9 +10441,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 (); +@@ -10818,8 +11026,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; +@@ -10982,592 +11192,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); + } +@@ -12618,12 +12538,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 +@@ -12642,8 +12562,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; +@@ -12672,24 +12592,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) +@@ -12709,7 +12629,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; +@@ -12741,7 +12661,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; +@@ -12776,6 +12696,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. */ + +@@ -12849,13 +12789,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; +@@ -13074,8 +13016,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 +@@ -14953,7 +14897,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); +@@ -22044,7 +21988,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"); +@@ -22082,6 +22027,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. */ +@@ -22093,6 +22039,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; +@@ -22137,6 +22084,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. */ +@@ -23647,6 +23595,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)) +@@ -23655,39 +23605,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 +@@ -23697,14 +23655,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 +@@ -24424,4 +24391,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-pr39543.patch b/gcc44-pr39543.patch deleted file mode 100644 index 3ee4dbd..0000000 --- a/gcc44-pr39543.patch +++ /dev/null @@ -1,293 +0,0 @@ -2009-04-22 Jakub Jelinek - - PR inline-asm/39543 - * fwprop.c (forward_propagate_asm): New function. - (forward_propagate_and_simplify): Propagate also into __asm, if it - doesn't increase the number of referenced registers. - - * gcc.target/i386/pr39543-1.c: New test. - * gcc.target/i386/pr39543-2.c: New test. - * gcc.target/i386/pr39543-3.c: New test. - ---- gcc/fwprop.c.jj 2009-03-30 12:45:45.000000000 +0200 -+++ gcc/fwprop.c 2009-04-10 16:19:36.000000000 +0200 -@@ -1,5 +1,5 @@ - /* RTL-based forward propagation pass for GNU compiler. -- Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -+ Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. - Contributed by Paolo Bonzini and Steven Bosscher. - - This file is part of GCC. -@@ -852,6 +852,80 @@ forward_propagate_subreg (df_ref use, rt - return false; - } - -+/* Try to replace USE with SRC (defined in DEF_INSN) in __asm. */ -+ -+static bool -+forward_propagate_asm (df_ref use, rtx def_insn, rtx def_set, rtx reg) -+{ -+ rtx use_insn = DF_REF_INSN (use), src, use_pat, asm_operands, new_rtx, *loc; -+ int speed_p, i; -+ df_ref *use_vec; -+ -+ gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0); -+ -+ src = SET_SRC (def_set); -+ use_pat = PATTERN (use_insn); -+ -+ /* In __asm don't replace if src might need more registers than -+ reg, as that could increase register pressure on the __asm. */ -+ use_vec = DF_INSN_USES (def_insn); -+ if (use_vec[0] && use_vec[1]) -+ return false; -+ -+ speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)); -+ asm_operands = NULL_RTX; -+ switch (GET_CODE (use_pat)) -+ { -+ case ASM_OPERANDS: -+ asm_operands = use_pat; -+ break; -+ case SET: -+ if (MEM_P (SET_DEST (use_pat))) -+ { -+ loc = &SET_DEST (use_pat); -+ new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p); -+ if (new_rtx) -+ validate_unshare_change (use_insn, loc, new_rtx, true); -+ } -+ asm_operands = SET_SRC (use_pat); -+ break; -+ case PARALLEL: -+ for (i = 0; i < XVECLEN (use_pat, 0); i++) -+ if (GET_CODE (XVECEXP (use_pat, 0, i)) == SET) -+ { -+ if (MEM_P (SET_DEST (XVECEXP (use_pat, 0, i)))) -+ { -+ loc = &SET_DEST (XVECEXP (use_pat, 0, i)); -+ new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, -+ src, speed_p); -+ if (new_rtx) -+ validate_unshare_change (use_insn, loc, new_rtx, true); -+ } -+ asm_operands = SET_SRC (XVECEXP (use_pat, 0, i)); -+ } -+ else if (GET_CODE (XVECEXP (use_pat, 0, i)) == ASM_OPERANDS) -+ asm_operands = XVECEXP (use_pat, 0, i); -+ break; -+ default: -+ gcc_unreachable (); -+ } -+ -+ gcc_assert (asm_operands && GET_CODE (asm_operands) == ASM_OPERANDS); -+ for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (asm_operands); i++) -+ { -+ loc = &ASM_OPERANDS_INPUT (asm_operands, i); -+ new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p); -+ if (new_rtx) -+ validate_unshare_change (use_insn, loc, new_rtx, true); -+ } -+ -+ if (num_changes_pending () == 0 || !apply_change_group ()) -+ return false; -+ -+ num_changes++; -+ return true; -+} -+ - /* Try to replace USE with SRC (defined in DEF_INSN) and simplify the - result. */ - -@@ -863,12 +937,16 @@ forward_propagate_and_simplify (df_ref u - rtx src, reg, new_rtx, *loc; - bool set_reg_equal; - enum machine_mode mode; -+ int asm_use = -1; -+ -+ if (INSN_CODE (use_insn) < 0) -+ asm_use = asm_noperands (PATTERN (use_insn)); - -- if (!use_set) -+ if (!use_set && asm_use < 0) - return false; - - /* Do not propagate into PC, CC0, etc. */ -- if (GET_MODE (SET_DEST (use_set)) == VOIDmode) -+ if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode) - return false; - - /* If def and use are subreg, check if they match. */ -@@ -900,7 +978,7 @@ forward_propagate_and_simplify (df_ref u - if (MEM_P (src) && MEM_READONLY_P (src)) - { - rtx x = avoid_constant_pool_reference (src); -- if (x != src) -+ if (x != src && use_set) - { - rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX); - rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (use_set); -@@ -911,6 +989,9 @@ forward_propagate_and_simplify (df_ref u - return false; - } - -+ if (asm_use >= 0) -+ return forward_propagate_asm (use, def_insn, def_set, reg); -+ - /* Else try simplifying. */ - - if (DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE) ---- gcc/testsuite/gcc.target/i386/pr39543-1.c.jj 2009-04-09 09:47:16.000000000 +0200 -+++ gcc/testsuite/gcc.target/i386/pr39543-1.c 2009-04-09 09:47:16.000000000 +0200 -@@ -0,0 +1,52 @@ -+/* PR inline-asm/39543 */ -+/* { dg-do compile } */ -+/* { dg-options "-O3 -fomit-frame-pointer" } */ -+ -+float __attribute__ ((aligned (16))) s0[128]; -+const float s1 = 0.707; -+float s2[8] __attribute__ ((aligned (16))); -+float s3[8] __attribute__ ((aligned (16))); -+float s4[16] __attribute__ ((aligned (16))); -+float s5[16] __attribute__ ((aligned (16))); -+ -+void -+foo (int k, float *x, float *y, const float *d, const float *z) -+{ -+ float *a, *b, *c, *e; -+ -+ a = x + 2 * k; -+ b = a + 2 * k; -+ c = b + 2 * k; -+ e = y + 2 * k; -+ __asm__ volatile ("" -+ : "=m" (x[0]), "=m" (b[0]), "=m" (a[0]), "=m" (c[0]) -+ : "m" (y[0]), "m" (y[k * 2]), "m" (x[0]), "m" (a[0]) -+ : "memory"); -+ for (;;) -+ { -+ __asm__ volatile ("" -+ : -+ : "m" (y[2]), "m" (d[2]), "m" (e[2]), "m" (z[2]) -+ : "memory"); -+ if (!--k) -+ break; -+ } -+ __asm__ volatile ("" -+ : "=m" (x[2]), "=m" (x[10]), "=m" (x[6]), "=m" (x[14]) -+ : "m" (y[2]), "m" (y[6]), "m" (x[2]), "m" (x[6]), -+ "m" (y[18]), "m" (s1) -+ : "memory"); -+} -+ -+void -+bar (float *a) -+{ -+ foo (4, a, a + 16, s2, s3); -+ foo (8, a, a + 32, s4, s5); -+} -+ -+void -+baz (void) -+{ -+ bar (s0); -+} ---- gcc/testsuite/gcc.target/i386/pr39543-2.c.jj 2009-04-09 09:47:16.000000000 +0200 -+++ gcc/testsuite/gcc.target/i386/pr39543-2.c 2009-04-09 09:47:16.000000000 +0200 -@@ -0,0 +1,51 @@ -+/* PR inline-asm/39543 */ -+/* { dg-do compile } */ -+/* { dg-options "-O3" } */ -+ -+float __attribute__ ((aligned (16))) s0[128]; -+const float s1 = 0.707; -+float s2[8] __attribute__ ((aligned (16))); -+float s3[8] __attribute__ ((aligned (16))); -+float s4[16] __attribute__ ((aligned (16))); -+float s5[16] __attribute__ ((aligned (16))); -+ -+void -+foo (int k, float *x, float *y, const float *d, const float *z) -+{ -+ float *a, *b, *c, *e; -+ -+ a = x + 2 * k; -+ b = a + 2 * k; -+ c = b + 2 * k; -+ e = y + 2 * k; -+ __asm__ volatile ("" -+ : "=m" (x[0]), "=m" (b[0]), "=m" (a[0]), "=m" (c[0]) -+ : "m" (y[0]), "m" (y[k * 2]), "m" (x[0]), "m" (a[0]) -+ : "memory"); -+ for (;;) -+ { -+ __asm__ volatile ("" -+ : -+ : "m" (y[2]), "m" (d[2]), "m" (e[2]), "m" (z[2]) -+ : "memory"); -+ if (!--k) -+ break; -+ } -+ __asm__ volatile ("" -+ : "=m" (x[2]), "=m" (x[10]), "=m" (x[6]), "=m" (x[14]) -+ : "m" (y[2]), "m" (y[6]), "m" (x[2]), "m" (x[6]), "m" (s1) -+ : "memory"); -+} -+ -+void -+bar (float *a) -+{ -+ foo (4, a, a + 16, s2, s3); -+ foo (8, a, a + 32, s4, s5); -+} -+ -+void -+baz (void) -+{ -+ bar (s0); -+} ---- gcc/testsuite/gcc.target/i386/pr39543-3.c.jj 2009-04-09 09:47:16.000000000 +0200 -+++ gcc/testsuite/gcc.target/i386/pr39543-3.c 2009-04-09 09:47:16.000000000 +0200 -@@ -0,0 +1,42 @@ -+/* PR inline-asm/39543 */ -+/* { dg-do compile } */ -+/* { dg-options "-O2" } */ -+ -+int s[128]; -+ -+void -+f1 (void) -+{ -+ int i; -+ asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17" -+ : "=r" (i) -+ : "m" (s[0]), "m" (s[2]), "m" (s[4]), "m" (s[6]), "m" (s[8]), -+ "m" (s[10]), "m" (s[12]), "m" (s[14]), "m" (s[16]), "m" (s[18]), -+ "m" (s[20]), "m" (s[22]), "m" (s[24]), "m" (s[26]), "m" (s[28]), -+ "m" (s[30]), "m" (s[32])); -+ asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17" -+ : "=r" (i) -+ : "m" (s[0]), "m" (s[2]), "m" (s[4]), "m" (s[6]), "m" (s[8]), -+ "m" (s[10]), "m" (s[12]), "m" (s[14]), "m" (s[16]), "m" (s[18]), -+ "m" (s[20]), "m" (s[22]), "m" (s[24]), "m" (s[26]), "m" (s[28]), -+ "m" (s[30]), "m" (s[32])); -+} -+ -+void -+f2 (int *q) -+{ -+ int i; -+ int *p = q + 32; -+ asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17" -+ : "=r" (i) -+ : "m" (p[0]), "m" (p[2]), "m" (p[4]), "m" (p[6]), "m" (p[8]), -+ "m" (p[10]), "m" (p[12]), "m" (p[14]), "m" (p[16]), "m" (p[18]), -+ "m" (p[20]), "m" (p[22]), "m" (p[24]), "m" (p[26]), "m" (p[28]), -+ "m" (p[30]), "m" (p[32])); -+ asm volatile ("# %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16 %17" -+ : "=r" (i) -+ : "m" (p[0]), "m" (p[2]), "m" (p[4]), "m" (p[6]), "m" (p[8]), -+ "m" (p[10]), "m" (p[12]), "m" (p[14]), "m" (p[16]), "m" (p[18]), -+ "m" (p[20]), "m" (p[22]), "m" (p[24]), "m" (p[26]), "m" (p[28]), -+ "m" (p[30]), "m" (p[32])); -+} diff --git a/gcc44-pr39794.patch b/gcc44-pr39794.patch deleted file mode 100644 index dfa7d85..0000000 --- a/gcc44-pr39794.patch +++ /dev/null @@ -1,309 +0,0 @@ -2009-04-24 Jakub Jelinek - - PR rtl-optimization/39794 - * alias.c (canon_true_dependence): Add x_addr argument. - * rtl.h (canon_true_dependence): Adjust prototype. - * cse.c (check_dependence): Adjust canon_true_dependence callers. - * cselib.c (cselib_invalidate_mem): Likewise. - * gcse.c (compute_transp): Likewise. - * dse.c (scan_reads_nospill): Likewise. - (record_store, check_mem_read_rtx): Likewise. For non-const-or-frame - addresses pass base->val_rtx as mem_addr, for const-or-frame addresses - canon_base_addr of the group, plus optional offset. - (struct group_info): Rename canon_base_mem to - canon_base_addr. - (get_group_info): Set canon_base_addr to canon_rtx of base, not - canon_rtx of base_mem. - - * gcc.dg/pr39794.c: New test. - ---- gcc/alias.c.jj 2009-04-22 23:54:25.000000000 +0200 -+++ gcc/alias.c 2009-04-23 18:09:28.000000000 +0200 -@@ -2287,14 +2287,13 @@ true_dependence (const_rtx mem, enum mac - Variant of true_dependence which assumes MEM has already been - canonicalized (hence we no longer do that here). - The mem_addr argument has been added, since true_dependence computed -- this value prior to canonicalizing. */ -+ this value prior to canonicalizing. -+ If x_addr is non-NULL, it is used in preference of XEXP (x, 0). */ - - int - canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, -- const_rtx x, bool (*varies) (const_rtx, bool)) -+ const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool)) - { -- rtx x_addr; -- - if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem)) - return 1; - -@@ -2320,7 +2319,8 @@ canon_true_dependence (const_rtx mem, en - if (nonoverlapping_memrefs_p (x, mem)) - return 0; - -- x_addr = get_addr (XEXP (x, 0)); -+ if (! x_addr) -+ x_addr = get_addr (XEXP (x, 0)); - - if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode)) - return 0; ---- gcc/dse.c.jj 2009-04-22 22:20:23.000000000 +0200 -+++ gcc/dse.c 2009-04-23 18:20:44.000000000 +0200 -@@ -223,7 +223,7 @@ struct store_info - /* This canonized mem. */ - rtx mem; - -- /* The result of get_addr on mem. */ -+ /* Canonized MEM address for use by canon_true_dependence. */ - rtx mem_addr; - - /* If this is non-zero, it is the alias set of a spill location. */ -@@ -476,8 +476,8 @@ struct group_info - do read dependency. */ - rtx base_mem; - -- /* Canonized version of base_mem, most likely the same thing. */ -- rtx canon_base_mem; -+ /* Canonized version of base_mem's address. */ -+ rtx canon_base_addr; - - /* These two sets of two bitmaps are used to keep track of how many - stores are actually referencing that position from this base. We -@@ -705,7 +705,7 @@ get_group_info (rtx base) - gi->rtx_base = base; - gi->id = rtx_group_next_id++; - gi->base_mem = gen_rtx_MEM (QImode, base); -- gi->canon_base_mem = canon_rtx (gi->base_mem); -+ gi->canon_base_addr = canon_rtx (base); - gi->store1_n = BITMAP_ALLOC (NULL); - gi->store1_p = BITMAP_ALLOC (NULL); - gi->store2_n = BITMAP_ALLOC (NULL); -@@ -1286,7 +1286,7 @@ static rtx get_stored_val (store_info_t, - static int - record_store (rtx body, bb_info_t bb_info) - { -- rtx mem, rhs, const_rhs; -+ rtx mem, rhs, const_rhs, mem_addr; - HOST_WIDE_INT offset = 0; - HOST_WIDE_INT width = 0; - alias_set_type spill_alias_set; -@@ -1456,6 +1456,23 @@ record_store (rtx body, bb_info_t bb_inf - ptr = active_local_stores; - last = NULL; - redundant_reason = NULL; -+ mem = canon_rtx (mem); -+ /* For alias_set != 0 canon_true_dependence should be never called. */ -+ if (spill_alias_set) -+ mem_addr = NULL_RTX; -+ else -+ { -+ if (group_id < 0) -+ mem_addr = base->val_rtx; -+ else -+ { -+ group_info_t group -+ = VEC_index (group_info_t, rtx_group_vec, group_id); -+ mem_addr = group->canon_base_addr; -+ } -+ if (offset) -+ mem_addr = plus_constant (mem_addr, offset); -+ } - - while (ptr) - { -@@ -1547,13 +1564,13 @@ record_store (rtx body, bb_info_t bb_inf - if (canon_true_dependence (s_info->mem, - GET_MODE (s_info->mem), - s_info->mem_addr, -- mem, rtx_varies_p)) -+ mem, mem_addr, rtx_varies_p)) - { - s_info->rhs = NULL; - s_info->const_rhs = NULL; - } - } -- -+ - /* An insn can be deleted if every position of every one of - its s_infos is zero. */ - if (any_positions_needed_p (s_info) -@@ -1580,9 +1597,9 @@ record_store (rtx body, bb_info_t bb_inf - /* Finish filling in the store_info. */ - store_info->next = insn_info->store_rec; - insn_info->store_rec = store_info; -- store_info->mem = canon_rtx (mem); -+ store_info->mem = mem; - store_info->alias_set = spill_alias_set; -- store_info->mem_addr = get_addr (XEXP (mem, 0)); -+ store_info->mem_addr = mem_addr; - store_info->cse_base = base; - if (width > HOST_BITS_PER_WIDE_INT) - { -@@ -2006,7 +2023,7 @@ replace_read (store_info_t store_info, i - static int - check_mem_read_rtx (rtx *loc, void *data) - { -- rtx mem = *loc; -+ rtx mem = *loc, mem_addr; - bb_info_t bb_info; - insn_info_t insn_info; - HOST_WIDE_INT offset = 0; -@@ -2058,6 +2075,22 @@ check_mem_read_rtx (rtx *loc, void *data - read_info->end = offset + width; - read_info->next = insn_info->read_rec; - insn_info->read_rec = read_info; -+ /* For alias_set != 0 canon_true_dependence should be never called. */ -+ if (spill_alias_set) -+ mem_addr = NULL_RTX; -+ else -+ { -+ if (group_id < 0) -+ mem_addr = base->val_rtx; -+ else -+ { -+ group_info_t group -+ = VEC_index (group_info_t, rtx_group_vec, group_id); -+ mem_addr = group->canon_base_addr; -+ } -+ if (offset) -+ mem_addr = plus_constant (mem_addr, offset); -+ } - - /* We ignore the clobbers in store_info. The is mildly aggressive, - but there really should not be a clobber followed by a read. */ -@@ -2128,7 +2161,7 @@ check_mem_read_rtx (rtx *loc, void *data - = canon_true_dependence (store_info->mem, - GET_MODE (store_info->mem), - store_info->mem_addr, -- mem, rtx_varies_p); -+ mem, mem_addr, rtx_varies_p); - - else if (group_id == store_info->group_id) - { -@@ -2139,7 +2172,7 @@ check_mem_read_rtx (rtx *loc, void *data - = canon_true_dependence (store_info->mem, - GET_MODE (store_info->mem), - store_info->mem_addr, -- mem, rtx_varies_p); -+ mem, mem_addr, rtx_varies_p); - - /* If this read is just reading back something that we just - stored, rewrite the read. */ -@@ -2224,7 +2257,7 @@ check_mem_read_rtx (rtx *loc, void *data - remove = canon_true_dependence (store_info->mem, - GET_MODE (store_info->mem), - store_info->mem_addr, -- mem, rtx_varies_p); -+ mem, mem_addr, rtx_varies_p); - - if (remove) - { -@@ -3066,8 +3099,9 @@ scan_reads_nospill (insn_info_t insn_inf - if ((read_info->group_id < 0) - && canon_true_dependence (group->base_mem, - QImode, -- group->canon_base_mem, -- read_info->mem, rtx_varies_p)) -+ group->canon_base_addr, -+ read_info->mem, NULL_RTX, -+ rtx_varies_p)) - { - if (kill) - bitmap_ior_into (kill, group->group_kill); ---- gcc/cse.c.jj 2009-04-22 22:20:23.000000000 +0200 -+++ gcc/cse.c 2009-04-23 18:09:35.000000000 +0200 -@@ -1658,7 +1658,7 @@ check_dependence (rtx *x, void *data) - { - struct check_dependence_data *d = (struct check_dependence_data *) data; - if (*x && MEM_P (*x)) -- return canon_true_dependence (d->exp, d->mode, d->addr, *x, -+ return canon_true_dependence (d->exp, d->mode, d->addr, *x, NULL_RTX, - cse_rtx_varies_p); - else - return 0; ---- gcc/rtl.h.jj 2009-04-22 22:20:37.000000000 +0200 -+++ gcc/rtl.h 2009-04-23 18:09:35.000000000 +0200 -@@ -2290,7 +2290,7 @@ extern rtx canon_rtx (rtx); - extern int true_dependence (const_rtx, enum machine_mode, const_rtx, bool (*)(const_rtx, bool)); - extern rtx get_addr (rtx); - extern int canon_true_dependence (const_rtx, enum machine_mode, rtx, const_rtx, -- bool (*)(const_rtx, bool)); -+ rtx, bool (*)(const_rtx, bool)); - extern int read_dependence (const_rtx, const_rtx); - extern int anti_dependence (const_rtx, const_rtx); - extern int output_dependence (const_rtx, const_rtx); ---- gcc/cselib.c.jj 2009-04-22 22:20:23.000000000 +0200 -+++ gcc/cselib.c 2009-04-23 18:09:35.000000000 +0200 -@@ -1,6 +1,6 @@ - /* Common subexpression elimination library for GNU compiler. - Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, -- 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008 -+ 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. - - This file is part of GCC. -@@ -1483,7 +1483,7 @@ cselib_invalidate_mem (rtx mem_rtx) - } - if (num_mems < PARAM_VALUE (PARAM_MAX_CSELIB_MEMORY_LOCATIONS) - && ! canon_true_dependence (mem_rtx, GET_MODE (mem_rtx), mem_addr, -- x, cselib_rtx_varies_p)) -+ x, NULL_RTX, cselib_rtx_varies_p)) - { - has_mem = true; - num_mems++; ---- gcc/gcse.c.jj 2009-04-22 22:20:23.000000000 +0200 -+++ gcc/gcse.c 2009-04-23 18:09:35.000000000 +0200 -@@ -1,7 +1,7 @@ - /* Global common subexpression elimination/Partial redundancy elimination - and global constant/copy propagation for GNU compiler. - Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, -- 2006, 2007, 2008 Free Software Foundation, Inc. -+ 2006, 2007, 2008, 2009 Free Software Foundation, Inc. - - This file is part of GCC. - -@@ -2512,7 +2512,7 @@ compute_transp (const_rtx x, int indx, s - dest_addr = XEXP (list_entry, 0); - - if (canon_true_dependence (dest, GET_MODE (dest), dest_addr, -- x, rtx_addr_varies_p)) -+ x, NULL_RTX, rtx_addr_varies_p)) - { - if (set_p) - SET_BIT (bmap[bb_index], indx); ---- gcc/testsuite/gcc.dg/pr39794.c.jj 2009-04-23 18:09:35.000000000 +0200 -+++ gcc/testsuite/gcc.dg/pr39794.c 2009-04-23 18:21:13.000000000 +0200 -@@ -0,0 +1,33 @@ -+/* PR rtl-optimization/39794 */ -+/* { dg-do run } */ -+/* { dg-options "-O2 -funroll-loops" } */ -+ -+extern void abort (); -+ -+void -+foo (int *a, int n) -+{ -+ int i; -+ for (i = 0; i < n; i++) -+ { -+ a[i] *= 2; -+ a[i + 1] = a[i - 1] + a[i - 2]; -+ } -+} -+ -+int a[16]; -+int ref[16] = { 0, 1, 4, 2, 10, 12, 24, 44, -+ 72, 136, 232, 416, 736, 1296, 2304, 2032 }; -+ -+int -+main () -+{ -+ int i; -+ for (i = 0; i < 16; i++) -+ a[i] = i; -+ foo (a + 2, 16 - 3); -+ for (i = 0; i < 16; i++) -+ if (ref[i] != a[i]) -+ abort (); -+ return 0; -+} diff --git a/gcc44-pr39856.patch b/gcc44-pr39856.patch new file mode 100644 index 0000000..5bc88fe --- /dev/null +++ b/gcc44-pr39856.patch @@ -0,0 +1,43 @@ +2009-04-24 Vladimir Makarov + + PR target/39856 + * reg-stack.c (subst_stack_regs_pat): Remove gcc_assert for note + for clobber. + +--- gcc/reg-stack.c (revision 146648) ++++ gcc/reg-stack.c (working copy) +@@ -1371,21 +1371,23 @@ subst_stack_regs_pat (rtx insn, stack re + + if (pat != PATTERN (insn)) + { +- /* The fix_truncdi_1 pattern wants to be able to allocate +- its own scratch register. It does this by clobbering +- an fp reg so that it is assured of an empty reg-stack +- register. If the register is live, kill it now. +- Remove the DEAD/UNUSED note so we don't try to kill it +- later too. */ ++ /* The fix_truncdi_1 pattern wants to be able to ++ allocate its own scratch register. It does this by ++ clobbering an fp reg so that it is assured of an ++ empty reg-stack register. If the register is live, ++ kill it now. Remove the DEAD/UNUSED note so we ++ don't try to kill it later too. ++ ++ In reality the UNUSED note can be absent in some ++ complicated cases when the register is reused for ++ partially set variable. */ + + if (note) + emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE); + else +- { +- note = find_reg_note (insn, REG_UNUSED, *dest); +- gcc_assert (note); +- } +- remove_note (insn, note); ++ note = find_reg_note (insn, REG_UNUSED, *dest); ++ if (note) ++ remove_note (insn, note); + replace_reg (dest, FIRST_STACK_REG + 1); + } + else diff --git a/gcc44-pr39867.patch b/gcc44-pr39867.patch deleted file mode 100644 index 3f971c6..0000000 --- a/gcc44-pr39867.patch +++ /dev/null @@ -1,70 +0,0 @@ -2009-04-24 Paolo Bonzini - - PR middle-end/39867 - * fold-const.c (fold_cond_expr_with_comparison): When folding - > and >= to MAX, make sure the MAX uses the same type as the - comparison's operands. - - * gcc.dg/pr39867.c: New. - ---- gcc/fold-const.c (revision 146581) -+++ gcc/fold-const.c (working copy) -@@ -5337,31 +5337,34 @@ fold_cond_expr_with_comparison (tree typ - break; - - case GT_EXPR: -- /* If C1 is C2 - 1, this is max(A, C2). */ -+ /* If C1 is C2 - 1, this is max(A, C2), but use ARG00's type for -+ MAX_EXPR, to preserve the signedness of the comparison. */ - if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type), - OEP_ONLY_CONST) - && operand_equal_p (arg01, - const_binop (MINUS_EXPR, arg2, - build_int_cst (type, 1), 0), - OEP_ONLY_CONST)) -- return pedantic_non_lvalue (fold_build2 (MAX_EXPR, -- type, -- fold_convert (type, arg1), -- arg2)); -+ return pedantic_non_lvalue (fold_convert (type, -+ fold_build2 (MAX_EXPR, TREE_TYPE (arg00), -+ arg00, -+ fold_convert (TREE_TYPE (arg00), -+ arg2)))); - break; - - case GE_EXPR: -- /* If C1 is C2 + 1, this is max(A, C2). */ -+ /* If C1 is C2 + 1, this is max(A, C2), with the same care as above. */ - if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type), - OEP_ONLY_CONST) - && operand_equal_p (arg01, - const_binop (PLUS_EXPR, arg2, - build_int_cst (type, 1), 0), - OEP_ONLY_CONST)) -- return pedantic_non_lvalue (fold_build2 (MAX_EXPR, -- type, -- fold_convert (type, arg1), -- arg2)); -+ return pedantic_non_lvalue (fold_convert (type, -+ fold_build2 (MAX_EXPR, TREE_TYPE (arg00), -+ arg00, -+ fold_convert (TREE_TYPE (arg00), -+ arg2)))); - break; - case NE_EXPR: - break; ---- gcc/testsuite/gcc.dg/pr39867.c 2009-04-21 23:33:56.143009234 +0200 -+++ gcc/testsuite/gcc.dg/pr39867.c 2009-04-24 09:20:07.000000000 +0200 -@@ -0,0 +1,11 @@ -+/* { dg-do link } */ -+/* { dg-options "-O2" } */ -+ -+int main (void) -+{ -+ int exp = -1; -+ /* Wrong folding of the LHS to an unsigned MAX leads to 4294967295 > 2. */ -+ if ((exp < 2 ? 2U : (unsigned int) exp) != 2) -+ link_error (); -+ return 0; -+} diff --git a/gcc44-pr39903.patch b/gcc44-pr39903.patch new file mode 100644 index 0000000..eaa64b2 --- /dev/null +++ b/gcc44-pr39903.patch @@ -0,0 +1,79 @@ +2009-04-26 H.J. Lu + + PR target/39903 + * config/i386/i386.c (construct_container): Don't call + gen_reg_or_parallel with BLKmode for X86_64_SSE_CLASS, + X86_64_SSESF_CLASS and X86_64_SSEDF_CLASS. + + PR target/39903 + * gcc.dg/torture/pr39903-1.c: New. + * gcc.dg/torture/pr39903-2.c: Likewise. + +--- gcc/config/i386/i386.c (revision 146817) ++++ gcc/config/i386/i386.c (working copy) +@@ -5466,7 +5466,10 @@ construct_container (enum machine_mode m + case X86_64_SSE_CLASS: + case X86_64_SSESF_CLASS: + case X86_64_SSEDF_CLASS: +- return gen_reg_or_parallel (mode, orig_mode, SSE_REGNO (sse_regno)); ++ if (mode != BLKmode) ++ return gen_reg_or_parallel (mode, orig_mode, ++ SSE_REGNO (sse_regno)); ++ break; + case X86_64_X87_CLASS: + case X86_64_COMPLEX_X87_CLASS: + return gen_rtx_REG (mode, FIRST_STACK_REG); +--- gcc/testsuite/gcc.dg/torture/pr39903-1.c (revision 0) ++++ gcc/testsuite/gcc.dg/torture/pr39903-1.c (revision 0) +@@ -0,0 +1,24 @@ ++/* PR target/39903 */ ++/* { dg-do run } */ ++/* { dg-options "-Wno-psabi" } */ ++ ++struct X { ++ double d; ++ double b[]; ++}; ++ ++struct X __attribute__((noinline)) ++foo (double d) ++{ ++ struct X x; ++ x.d = d; ++ return x; ++} ++extern void abort (void); ++int main() ++{ ++ struct X x = foo(3.0); ++ if (x.d != 3.0) ++ abort (); ++ return 0; ++} +--- gcc/testsuite/gcc.dg/torture/pr39903-2.c (revision 0) ++++ gcc/testsuite/gcc.dg/torture/pr39903-2.c (revision 0) +@@ -0,0 +1,24 @@ ++/* PR target/39903 */ ++/* { dg-do run } */ ++/* { dg-options "-Wno-psabi" } */ ++ ++struct X { ++ float d; ++ float b[]; ++}; ++ ++struct X __attribute__((noinline)) ++foo (float d) ++{ ++ struct X x; ++ x.d = d; ++ return x; ++} ++extern void abort (void); ++int main() ++{ ++ struct X x = foo(3.0); ++ if (x.d != 3.0) ++ abort (); ++ return 0; ++} diff --git a/gcc44-rh459374-1.patch b/gcc44-rh459374-1.patch deleted file mode 100644 index f736bdc..0000000 --- a/gcc44-rh459374-1.patch +++ /dev/null @@ -1,239 +0,0 @@ -2009-04-08 Jakub Jelinek - - * tree.h (DECL_BY_REFERENCE): Note that it is also valid for - !TREE_STATIC VAR_DECLs. - * dwarf2out.c (loc_by_reference, gen_decl_die): Handle - DECL_BY_REFERENCE on !TREE_STATIC VAR_DECLs. - (gen_variable_die): Likewise. Don't look at TREE_PRIVATE if - DECL_BY_REFERENCE is valid. - * dbxout.c (DECL_ACCESSIBILITY_CHAR): Don't look at TREE_PRIVATE - for PARM_DECLs, RESULT_DECLs or !TREE_STATIC VAR_DECLs. - * tree-nested.c (get_nonlocal_debug_decl, get_local_debug_decl): - Copy DECL_BY_REFERENCE. - (struct nesting_copy_body_data): New type. - (nesting_copy_decl): New function. - (finalize_nesting_tree_1): Remap types of debug_var_chain variables, - if they have variable length. - ---- gcc/dwarf2out.c.jj 2009-04-07 08:32:56.000000000 +0200 -+++ gcc/dwarf2out.c 2009-04-08 11:10:16.000000000 +0200 -@@ -11709,7 +11709,9 @@ loc_by_reference (dw_loc_descr_ref loc, - if (loc == NULL) - return NULL; - -- if ((TREE_CODE (decl) != PARM_DECL && TREE_CODE (decl) != RESULT_DECL) -+ if ((TREE_CODE (decl) != PARM_DECL -+ && TREE_CODE (decl) != RESULT_DECL -+ && (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))) - || !DECL_BY_REFERENCE (decl)) - return loc; - -@@ -14047,12 +14049,19 @@ gen_variable_die (tree decl, tree origin - else - { - tree type = TREE_TYPE (decl); -+ bool private_flag_valid = true; - - add_name_and_src_coords_attributes (var_die, decl); - if ((TREE_CODE (decl) == PARM_DECL -- || TREE_CODE (decl) == RESULT_DECL) -+ || TREE_CODE (decl) == RESULT_DECL -+ || (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))) - && DECL_BY_REFERENCE (decl)) -- add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die); -+ { -+ add_type_attribute (var_die, TREE_TYPE (type), 0, 0, context_die); -+ /* DECL_BY_REFERENCE uses the same bit as TREE_PRIVATE, -+ for PARM_DECL, RESULT_DECL or non-static VAR_DECL. */ -+ private_flag_valid = false; -+ } - else - add_type_attribute (var_die, type, TREE_READONLY (decl), - TREE_THIS_VOLATILE (decl), context_die); -@@ -14065,7 +14074,7 @@ gen_variable_die (tree decl, tree origin - - if (TREE_PROTECTED (decl)) - add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected); -- else if (TREE_PRIVATE (decl)) -+ else if (private_flag_valid && TREE_PRIVATE (decl)) - add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private); - } - -@@ -15298,7 +15307,9 @@ gen_decl_die (tree decl, tree origin, dw - - /* Output any DIEs that are needed to specify the type of this data - object. */ -- if (TREE_CODE (decl_or_origin) == RESULT_DECL -+ if ((TREE_CODE (decl_or_origin) == RESULT_DECL -+ || (TREE_CODE (decl_or_origin) == VAR_DECL -+ && !TREE_STATIC (decl_or_origin))) - && DECL_BY_REFERENCE (decl_or_origin)) - gen_type_die (TREE_TYPE (TREE_TYPE (decl_or_origin)), context_die); - else ---- gcc/tree.h.jj 2009-04-06 11:48:32.000000000 +0200 -+++ gcc/tree.h 2009-04-07 17:16:28.000000000 +0200 -@@ -478,7 +478,7 @@ struct tree_common GTY(()) - CALL_EXPR - - DECL_BY_REFERENCE in -- PARM_DECL, RESULT_DECL -+ PARM_DECL, RESULT_DECL, VAR_DECL (only !TREE_STATIC) - - OMP_SECTION_LAST in - OMP_SECTION -@@ -1291,8 +1291,9 @@ extern void omp_clause_range_check_faile - #define CALL_EXPR_RETURN_SLOT_OPT(NODE) \ - (CALL_EXPR_CHECK (NODE)->base.private_flag) - --/* In a RESULT_DECL or PARM_DECL, means that it is passed by invisible -- reference (and the TREE_TYPE is a pointer to the true type). */ -+/* In a RESULT_DECL, PARM_DECL or VAR_DECL without TREE_STATIC, means that it is -+ passed by invisible reference (and the TREE_TYPE is a pointer to the true -+ type). */ - #define DECL_BY_REFERENCE(NODE) (DECL_COMMON_CHECK (NODE)->base.private_flag) - - /* In a CALL_EXPR, means that the call is the jump from a thunk to the ---- gcc/tree-nested.c.jj 2009-04-06 11:47:30.000000000 +0200 -+++ gcc/tree-nested.c 2009-04-08 09:50:55.000000000 +0200 -@@ -827,6 +827,11 @@ get_nonlocal_debug_decl (struct nesting_ - TREE_READONLY (new_decl) = TREE_READONLY (decl); - TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl); - DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1; -+ if ((TREE_CODE (decl) == PARM_DECL -+ || TREE_CODE (decl) == RESULT_DECL -+ || TREE_CODE (decl) == VAR_DECL) -+ && DECL_BY_REFERENCE (decl)) -+ DECL_BY_REFERENCE (new_decl) = 1; - - SET_DECL_VALUE_EXPR (new_decl, x); - DECL_HAS_VALUE_EXPR_P (new_decl) = 1; -@@ -1240,6 +1245,11 @@ get_local_debug_decl (struct nesting_inf - TREE_READONLY (new_decl) = TREE_READONLY (decl); - TREE_ADDRESSABLE (new_decl) = TREE_ADDRESSABLE (decl); - DECL_SEEN_IN_BIND_EXPR_P (new_decl) = 1; -+ if ((TREE_CODE (decl) == PARM_DECL -+ || TREE_CODE (decl) == RESULT_DECL -+ || TREE_CODE (decl) == VAR_DECL) -+ && DECL_BY_REFERENCE (decl)) -+ DECL_BY_REFERENCE (new_decl) = 1; - - SET_DECL_VALUE_EXPR (new_decl, x); - DECL_HAS_VALUE_EXPR_P (new_decl) = 1; -@@ -1944,6 +1954,34 @@ convert_all_function_calls (struct nesti - while (root); - } - -+struct nesting_copy_body_data -+{ -+ copy_body_data cb; -+ struct nesting_info *root; -+}; -+ -+/* A helper subroutine for debug_var_chain type remapping. */ -+ -+static tree -+nesting_copy_decl (tree decl, copy_body_data *id) -+{ -+ struct nesting_copy_body_data *nid = (struct nesting_copy_body_data *) id; -+ void **slot = pointer_map_contains (nid->root->var_map, decl); -+ -+ if (slot) -+ return (tree) *slot; -+ -+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ORIGINAL_TYPE (decl)) -+ { -+ tree new_decl = copy_decl_no_change (decl, id); -+ DECL_ORIGINAL_TYPE (new_decl) -+ = remap_type (DECL_ORIGINAL_TYPE (decl), id); -+ return new_decl; -+ } -+ -+ return copy_decl_no_change (decl, id); -+} -+ - /* Do "everything else" to clean up or complete state collected by the - various walking passes -- lay out the types and decls, generate code - to initialize the frame decl, store critical expressions in the -@@ -2076,10 +2114,66 @@ finalize_nesting_tree_1 (struct nesting_ - declare_vars (root->new_local_var_chain, - gimple_seq_first_stmt (gimple_body (root->context)), - false); -+ - if (root->debug_var_chain) -- declare_vars (root->debug_var_chain, -- gimple_seq_first_stmt (gimple_body (root->context)), -- true); -+ { -+ tree debug_var; -+ -+ for (debug_var = root->debug_var_chain; debug_var; -+ debug_var = TREE_CHAIN (debug_var)) -+ if (variably_modified_type_p (TREE_TYPE (debug_var), NULL)) -+ break; -+ -+ /* If there are any debug decls with variable length types, -+ remap those types using other debug_var_chain variables. */ -+ if (debug_var) -+ { -+ struct nesting_copy_body_data id; -+ -+ memset (&id, 0, sizeof (id)); -+ id.cb.copy_decl = nesting_copy_decl; -+ id.cb.decl_map = pointer_map_create (); -+ id.root = root; -+ -+ for (; debug_var; debug_var = TREE_CHAIN (debug_var)) -+ if (variably_modified_type_p (TREE_TYPE (debug_var), NULL)) -+ { -+ tree type = TREE_TYPE (debug_var); -+ tree newt, t = type; -+ struct nesting_info *i; -+ -+ for (i = root; i; i = i->outer) -+ if (variably_modified_type_p (type, i->context)) -+ break; -+ -+ if (i == NULL) -+ continue; -+ -+ id.cb.src_fn = i->context; -+ id.cb.dst_fn = i->context; -+ id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context); -+ -+ TREE_TYPE (debug_var) = newt = remap_type (type, &id.cb); -+ while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt)) -+ { -+ newt = TREE_TYPE (newt); -+ t = TREE_TYPE (t); -+ } -+ if (TYPE_NAME (newt) -+ && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL -+ && DECL_ORIGINAL_TYPE (TYPE_NAME (newt)) -+ && newt != t -+ && TYPE_NAME (newt) == TYPE_NAME (t)) -+ TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb); -+ } -+ -+ pointer_map_destroy (id.cb.decl_map); -+ } -+ -+ declare_vars (root->debug_var_chain, -+ gimple_seq_first_stmt (gimple_body (root->context)), -+ true); -+ } - - /* Dump the translated tree function. */ - dump_function (TDI_nested, root->context); ---- gcc/dbxout.c.jj 2009-04-06 11:47:29.000000000 +0200 -+++ gcc/dbxout.c 2009-04-07 17:16:27.000000000 +0200 -@@ -1397,7 +1397,9 @@ dbxout_type_index (tree type) - /* Used in several places: evaluates to '0' for a private decl, - '1' for a protected decl, '2' for a public decl. */ - #define DECL_ACCESSIBILITY_CHAR(DECL) \ --(TREE_PRIVATE (DECL) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2') -+((TREE_CODE (DECL) != PARM_DECL && TREE_CODE (DECL) != RESULT_DECL \ -+ && (TREE_CODE (DECL) != VAR_DECL || TREE_STATIC (DECL)) \ -+ && TREE_PRIVATE (DECL)) ? '0' : TREE_PROTECTED (DECL) ? '1' : '2') - - /* Subroutine of `dbxout_type'. Output the type fields of TYPE. - This must be a separate function because anonymous unions require diff --git a/gcc44-rh459374-2.patch b/gcc44-rh459374-2.patch deleted file mode 100644 index d1a8c17..0000000 --- a/gcc44-rh459374-2.patch +++ /dev/null @@ -1,175 +0,0 @@ -2009-04-08 Jakub Jelinek - - * dwarf2out.c (loc_descr_plus_const): New function. - (build_cfa_aligned_loc, tls_mem_loc_descriptor, - mem_loc_descriptor, loc_descriptor_from_tree_1, - descr_info_loc, gen_variable_die): Use it. - ---- gcc/dwarf2out.c.jj 2009-04-08 11:10:16.000000000 +0200 -+++ gcc/dwarf2out.c 2009-04-08 12:52:16.000000000 +0200 -@@ -3890,6 +3890,47 @@ add_loc_descr (dw_loc_descr_ref *list_he - *d = descr; - } - -+/* Add a constant OFFSET to a location expression. */ -+ -+static void -+loc_descr_plus_const (dw_loc_descr_ref *list_head, HOST_WIDE_INT offset) -+{ -+ dw_loc_descr_ref loc; -+ HOST_WIDE_INT *p; -+ -+ gcc_assert (*list_head != NULL); -+ -+ if (!offset) -+ return; -+ -+ /* Find the end of the chain. */ -+ for (loc = *list_head; loc->dw_loc_next != NULL; loc = loc->dw_loc_next) -+ ; -+ -+ p = NULL; -+ if (loc->dw_loc_opc == DW_OP_fbreg -+ || (loc->dw_loc_opc >= DW_OP_breg0 && loc->dw_loc_opc <= DW_OP_breg31)) -+ p = &loc->dw_loc_oprnd1.v.val_int; -+ else if (loc->dw_loc_opc == DW_OP_bregx) -+ p = &loc->dw_loc_oprnd2.v.val_int; -+ -+ /* If the last operation is fbreg, breg{0..31,x}, optimize by adjusting its -+ offset. Don't optimize if an signed integer overflow would happen. */ -+ if (p != NULL -+ && ((offset > 0 && *p <= INTTYPE_MAXIMUM (HOST_WIDE_INT) - offset) -+ || (offset < 0 && *p >= INTTYPE_MINIMUM (HOST_WIDE_INT) - offset))) -+ *p += offset; -+ -+ else if (offset > 0) -+ loc->dw_loc_next = new_loc_descr (DW_OP_plus_uconst, offset, 0); -+ -+ else -+ { -+ loc->dw_loc_next = int_loc_descriptor (offset); -+ add_loc_descr (&loc->dw_loc_next, new_loc_descr (DW_OP_plus, 0, 0)); -+ } -+} -+ - /* Return the size of a location descriptor. */ - - static unsigned long -@@ -4409,9 +4450,7 @@ build_cfa_aligned_loc (HOST_WIDE_INT off - head = new_reg_loc_descr (dwarf_fp, 0); - add_loc_descr (&head, int_loc_descriptor (alignment)); - add_loc_descr (&head, new_loc_descr (DW_OP_and, 0, 0)); -- -- add_loc_descr (&head, int_loc_descriptor (offset)); -- add_loc_descr (&head, new_loc_descr (DW_OP_plus, 0, 0)); -+ loc_descr_plus_const (&head, offset); - } - else - head = new_reg_loc_descr (dwarf_fp, offset); -@@ -9913,7 +9952,7 @@ static dw_loc_descr_ref - tls_mem_loc_descriptor (rtx mem) - { - tree base; -- dw_loc_descr_ref loc_result, loc_result2; -+ dw_loc_descr_ref loc_result; - - if (MEM_EXPR (mem) == NULL_TREE || MEM_OFFSET (mem) == NULL_RTX) - return NULL; -@@ -9929,21 +9968,7 @@ tls_mem_loc_descriptor (rtx mem) - return NULL; - - if (INTVAL (MEM_OFFSET (mem))) -- { -- if (INTVAL (MEM_OFFSET (mem)) >= 0) -- add_loc_descr (&loc_result, -- new_loc_descr (DW_OP_plus_uconst, -- INTVAL (MEM_OFFSET (mem)), 0)); -- else -- { -- loc_result2 = mem_loc_descriptor (MEM_OFFSET (mem), GET_MODE (mem), -- VAR_INIT_STATUS_INITIALIZED); -- if (loc_result2 == 0) -- return NULL; -- add_loc_descr (&loc_result, loc_result2); -- add_loc_descr (&loc_result, new_loc_descr (DW_OP_plus, 0, 0)); -- } -- } -+ loc_descr_plus_const (&loc_result, INTVAL (MEM_OFFSET (mem))); - - return loc_result; - } -@@ -10108,11 +10133,8 @@ mem_loc_descriptor (rtx rtl, enum machin - if (mem_loc_result == 0) - break; - -- if (GET_CODE (XEXP (rtl, 1)) == CONST_INT -- && INTVAL (XEXP (rtl, 1)) >= 0) -- add_loc_descr (&mem_loc_result, -- new_loc_descr (DW_OP_plus_uconst, -- INTVAL (XEXP (rtl, 1)), 0)); -+ if (GET_CODE (XEXP (rtl, 1)) == CONST_INT) -+ loc_descr_plus_const (&mem_loc_result, INTVAL (XEXP (rtl, 1))); - else - { - dw_loc_descr_ref mem_loc_result2 -@@ -10526,13 +10548,7 @@ loc_descriptor_from_tree_1 (tree loc, in - } - - bytepos = bitpos / BITS_PER_UNIT; -- if (bytepos > 0) -- add_loc_descr (&ret, new_loc_descr (DW_OP_plus_uconst, bytepos, 0)); -- else if (bytepos < 0) -- { -- add_loc_descr (&ret, int_loc_descriptor (bytepos)); -- add_loc_descr (&ret, new_loc_descr (DW_OP_plus, 0, 0)); -- } -+ loc_descr_plus_const (&ret, bytepos); - - have_address = 1; - break; -@@ -10616,11 +10632,7 @@ loc_descriptor_from_tree_1 (tree loc, in - if (ret == 0) - return 0; - -- add_loc_descr (&ret, -- new_loc_descr (DW_OP_plus_uconst, -- tree_low_cst (TREE_OPERAND (loc, 1), -- 0), -- 0)); -+ loc_descr_plus_const (&ret, tree_low_cst (TREE_OPERAND (loc, 1), 0)); - break; - } - -@@ -13001,10 +13013,7 @@ descr_info_loc (tree val, tree base_decl - loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); - if (!loc) - break; -- add_loc_descr (&loc, -- new_loc_descr (DW_OP_plus_uconst, -- tree_low_cst (TREE_OPERAND (val, 1), -- 1), 0)); -+ loc_descr_plus_const (&loc, tree_low_cst (TREE_OPERAND (val, 1), 0)); - } - else - { -@@ -13920,9 +13929,7 @@ gen_variable_die (tree decl, tree origin - loc->dw_loc_oprnd1.v.val_addr - = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); - else -- add_loc_descr (&loc, -- new_loc_descr (DW_OP_plus_uconst, -- off, 0)); -+ loc_descr_plus_const (&loc, off); - } - add_AT_loc (var_die, DW_AT_location, loc); - remove_AT (var_die, DW_AT_declaration); -@@ -13985,8 +13992,7 @@ gen_variable_die (tree decl, tree origin - loc->dw_loc_oprnd1.v.val_addr - = plus_constant (loc->dw_loc_oprnd1.v.val_addr, off); - else -- add_loc_descr (&loc, new_loc_descr (DW_OP_plus_uconst, -- off, 0)); -+ loc_descr_plus_const (&loc, off); - } - add_AT_loc (var_die, DW_AT_location, loc); - } diff --git a/gcc44-rh459374-3.patch b/gcc44-rh459374-3.patch deleted file mode 100644 index 3ad7c25..0000000 --- a/gcc44-rh459374-3.patch +++ /dev/null @@ -1,468 +0,0 @@ -2009-04-22 Jakub Jelinek - - * tree-nested.c (get_nonlocal_vla_type): If not optimizing, call - note_nonlocal_vla_type for nonlocal VLAs. - (note_nonlocal_vla_type, note_nonlocal_block_vlas, - contains_remapped_vars, remap_vla_decls): New functions. - (convert_nonlocal_reference_stmt): If not optimizing, call - note_nonlocal_block_vlas on GIMPLE_BIND block vars. - (nesting_copy_decl): Return {VAR,PARM,RESULT}_DECL unmodified - if it wasn't found in var_map. - (finalize_nesting_tree_1): Call remap_vla_decls. If outermost - GIMPLE_BIND doesn't have gimple_bind_block, chain debug_var_chain - to BLOCK_VARS (DECL_INITIAL (root->context)) instead of calling - declare_vars. - * gimplify.c (nonlocal_vlas): New variable. - (gimplify_var_or_parm_decl): Add debug VAR_DECLs for non-local - referenced VLAs. - (gimplify_body): Create and destroy nonlocal_vlas. - - * trans-decl.c: Include pointer-set.h. - (nonlocal_dummy_decl_pset, tree nonlocal_dummy_decls): New variables. - (gfc_nonlocal_dummy_array_decl): New function. - (gfc_get_symbol_decl): Call it for non-local dummy args with saved - descriptor. - (gfc_get_symbol_decl): Set DECL_BY_REFERENCE when needed. - (gfc_generate_function_code): Initialize nonlocal_dummy_decl{s,_pset}, - chain it to outermost block's vars, destroy it afterwards. - - * Make-lang.in (trans-decl.o): Depend on pointer-set.h. - ---- gcc/tree-nested.c.jj 2009-04-21 19:24:25.000000000 +0200 -+++ gcc/tree-nested.c 2009-04-22 10:18:38.000000000 +0200 -@@ -770,6 +770,7 @@ get_frame_field (struct nesting_info *in - return x; - } - -+static void note_nonlocal_vla_type (struct nesting_info *info, tree type); - - /* A subroutine of convert_nonlocal_reference_op. Create a local variable - in the nested function with DECL_VALUE_EXPR set to reference the true -@@ -840,6 +841,11 @@ get_nonlocal_debug_decl (struct nesting_ - TREE_CHAIN (new_decl) = info->debug_var_chain; - info->debug_var_chain = new_decl; - -+ if (!optimize -+ && info->context != target_context -+ && variably_modified_type_p (TREE_TYPE (decl), NULL)) -+ note_nonlocal_vla_type (info, TREE_TYPE (decl)); -+ - return new_decl; - } - -@@ -1111,6 +1117,60 @@ convert_nonlocal_omp_clauses (tree *pcla - return need_chain; - } - -+/* Create nonlocal debug decls for nonlocal VLA array bounds. */ -+ -+static void -+note_nonlocal_vla_type (struct nesting_info *info, tree type) -+{ -+ while (POINTER_TYPE_P (type) && !TYPE_NAME (type)) -+ type = TREE_TYPE (type); -+ -+ if (TYPE_NAME (type) -+ && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL -+ && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) -+ type = DECL_ORIGINAL_TYPE (TYPE_NAME (type)); -+ -+ while (POINTER_TYPE_P (type) -+ || TREE_CODE (type) == VECTOR_TYPE -+ || TREE_CODE (type) == FUNCTION_TYPE -+ || TREE_CODE (type) == METHOD_TYPE) -+ type = TREE_TYPE (type); -+ -+ if (TREE_CODE (type) == ARRAY_TYPE) -+ { -+ tree domain, t; -+ -+ note_nonlocal_vla_type (info, TREE_TYPE (type)); -+ domain = TYPE_DOMAIN (type); -+ if (domain) -+ { -+ t = TYPE_MIN_VALUE (domain); -+ if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) -+ && decl_function_context (t) != info->context) -+ get_nonlocal_debug_decl (info, t); -+ t = TYPE_MAX_VALUE (domain); -+ if (t && (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL) -+ && decl_function_context (t) != info->context) -+ get_nonlocal_debug_decl (info, t); -+ } -+ } -+} -+ -+/* Create nonlocal debug decls for nonlocal VLA array bounds for VLAs -+ in BLOCK. */ -+ -+static void -+note_nonlocal_block_vlas (struct nesting_info *info, tree block) -+{ -+ tree var; -+ -+ for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var)) -+ if (TREE_CODE (var) == VAR_DECL -+ && variably_modified_type_p (TREE_TYPE (var), NULL) -+ && DECL_HAS_VALUE_EXPR_P (var) -+ && decl_function_context (var) != info->context) -+ note_nonlocal_vla_type (info, TREE_TYPE (var)); -+} - - /* Callback for walk_gimple_stmt. Rewrite all references to VAR and - PARM_DECLs that belong to outer functions. This handles statements -@@ -1202,6 +1262,13 @@ convert_nonlocal_reference_stmt (gimple_ - info, gimple_omp_body (stmt)); - break; - -+ case GIMPLE_BIND: -+ if (!optimize && gimple_bind_block (stmt)) -+ note_nonlocal_block_vlas (info, gimple_bind_block (stmt)); -+ -+ *handled_ops_p = false; -+ return NULL_TREE; -+ - default: - /* For every other statement that we are not interested in - handling here, let the walker traverse the operands. */ -@@ -1979,9 +2046,117 @@ nesting_copy_decl (tree decl, copy_body_ - return new_decl; - } - -+ if (TREE_CODE (decl) == VAR_DECL -+ || TREE_CODE (decl) == PARM_DECL -+ || TREE_CODE (decl) == RESULT_DECL) -+ return decl; -+ - return copy_decl_no_change (decl, id); - } - -+/* A helper function for remap_vla_decls. See if *TP contains -+ some remapped variables. */ -+ -+static tree -+contains_remapped_vars (tree *tp, int *walk_subtrees, void *data) -+{ -+ struct nesting_info *root = (struct nesting_info *) data; -+ tree t = *tp; -+ void **slot; -+ -+ if (DECL_P (t)) -+ { -+ *walk_subtrees = 0; -+ slot = pointer_map_contains (root->var_map, t); -+ -+ if (slot) -+ return (tree) *slot; -+ } -+ return NULL; -+} -+ -+/* Remap VLA decls in BLOCK and subblocks if remapped variables are -+ involved. */ -+ -+static void -+remap_vla_decls (tree block, struct nesting_info *root) -+{ -+ tree var, subblock, val, type; -+ struct nesting_copy_body_data id; -+ -+ for (subblock = BLOCK_SUBBLOCKS (block); -+ subblock; -+ subblock = BLOCK_CHAIN (subblock)) -+ remap_vla_decls (subblock, root); -+ -+ for (var = BLOCK_VARS (block); var; var = TREE_CHAIN (var)) -+ { -+ if (TREE_CODE (var) == VAR_DECL -+ && variably_modified_type_p (TREE_TYPE (var), NULL) -+ && DECL_HAS_VALUE_EXPR_P (var)) -+ { -+ type = TREE_TYPE (var); -+ val = DECL_VALUE_EXPR (var); -+ if (walk_tree (&type, contains_remapped_vars, root, NULL) != NULL -+ || walk_tree (&val, contains_remapped_vars, root, NULL) != NULL) -+ break; -+ } -+ } -+ if (var == NULL_TREE) -+ return; -+ -+ memset (&id, 0, sizeof (id)); -+ id.cb.copy_decl = nesting_copy_decl; -+ id.cb.decl_map = pointer_map_create (); -+ id.root = root; -+ -+ for (; var; var = TREE_CHAIN (var)) -+ if (TREE_CODE (var) == VAR_DECL -+ && variably_modified_type_p (TREE_TYPE (var), NULL) -+ && DECL_HAS_VALUE_EXPR_P (var)) -+ { -+ struct nesting_info *i; -+ tree newt, t, context; -+ -+ t = type = TREE_TYPE (var); -+ val = DECL_VALUE_EXPR (var); -+ if (walk_tree (&type, contains_remapped_vars, root, NULL) == NULL -+ && walk_tree (&val, contains_remapped_vars, root, NULL) == NULL) -+ continue; -+ -+ context = decl_function_context (var); -+ for (i = root; i; i = i->outer) -+ if (i->context == context) -+ break; -+ -+ if (i == NULL) -+ continue; -+ -+ id.cb.src_fn = i->context; -+ id.cb.dst_fn = i->context; -+ id.cb.src_cfun = DECL_STRUCT_FUNCTION (root->context); -+ -+ TREE_TYPE (var) = newt = remap_type (type, &id.cb); -+ while (POINTER_TYPE_P (newt) && !TYPE_NAME (newt)) -+ { -+ newt = TREE_TYPE (newt); -+ t = TREE_TYPE (t); -+ } -+ if (TYPE_NAME (newt) -+ && TREE_CODE (TYPE_NAME (newt)) == TYPE_DECL -+ && DECL_ORIGINAL_TYPE (TYPE_NAME (newt)) -+ && newt != t -+ && TYPE_NAME (newt) == TYPE_NAME (t)) -+ TYPE_NAME (newt) = remap_decl (TYPE_NAME (newt), &id.cb); -+ -+ walk_tree (&val, copy_tree_body_r, &id.cb, NULL); -+ if (val != DECL_VALUE_EXPR (var)) -+ SET_DECL_VALUE_EXPR (var, val); -+ } -+ -+ pointer_map_destroy (id.cb.decl_map); -+} -+ - /* Do "everything else" to clean up or complete state collected by the - various walking passes -- lay out the types and decls, generate code - to initialize the frame decl, store critical expressions in the -@@ -2118,6 +2293,9 @@ finalize_nesting_tree_1 (struct nesting_ - if (root->debug_var_chain) - { - tree debug_var; -+ gimple scope; -+ -+ remap_vla_decls (DECL_INITIAL (root->context), root); - - for (debug_var = root->debug_var_chain; debug_var; - debug_var = TREE_CHAIN (debug_var)) -@@ -2170,9 +2348,13 @@ finalize_nesting_tree_1 (struct nesting_ - pointer_map_destroy (id.cb.decl_map); - } - -- declare_vars (root->debug_var_chain, -- gimple_seq_first_stmt (gimple_body (root->context)), -- true); -+ scope = gimple_seq_first_stmt (gimple_body (root->context)); -+ if (gimple_bind_block (scope)) -+ declare_vars (root->debug_var_chain, scope, true); -+ else -+ BLOCK_VARS (DECL_INITIAL (root->context)) -+ = chainon (BLOCK_VARS (DECL_INITIAL (root->context)), -+ root->debug_var_chain); - } - - /* Dump the translated tree function. */ ---- gcc/gimplify.c.jj 2009-04-21 19:23:29.000000000 +0200 -+++ gcc/gimplify.c 2009-04-22 00:20:41.000000000 +0200 -@@ -1851,6 +1851,9 @@ gimplify_conversion (tree *expr_p) - return GS_OK; - } - -+/* Nonlocal VLAs seen in the current function. */ -+static struct pointer_set_t *nonlocal_vlas; -+ - /* Gimplify a VAR_DECL or PARM_DECL. Returns GS_OK if we expanded a - DECL_VALUE_EXPR, and it's worth re-examining things. */ - -@@ -1881,7 +1884,36 @@ gimplify_var_or_parm_decl (tree *expr_p) - /* If the decl is an alias for another expression, substitute it now. */ - if (DECL_HAS_VALUE_EXPR_P (decl)) - { -- *expr_p = unshare_expr (DECL_VALUE_EXPR (decl)); -+ tree value_expr = DECL_VALUE_EXPR (decl); -+ -+ /* For referenced nonlocal VLAs add a decl for debugging purposes -+ to the current function. */ -+ if (TREE_CODE (decl) == VAR_DECL -+ && TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST -+ && nonlocal_vlas != NULL -+ && TREE_CODE (value_expr) == INDIRECT_REF -+ && TREE_CODE (TREE_OPERAND (value_expr, 0)) == VAR_DECL -+ && decl_function_context (decl) != current_function_decl) -+ { -+ struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; -+ while (ctx && ctx->region_type == ORT_WORKSHARE) -+ ctx = ctx->outer_context; -+ if (!ctx && !pointer_set_insert (nonlocal_vlas, decl)) -+ { -+ tree copy = copy_node (decl), block; -+ -+ lang_hooks.dup_lang_specific_decl (copy); -+ SET_DECL_RTL (copy, NULL_RTX); -+ TREE_USED (copy) = 1; -+ block = DECL_INITIAL (current_function_decl); -+ TREE_CHAIN (copy) = BLOCK_VARS (block); -+ BLOCK_VARS (block) = copy; -+ SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr)); -+ DECL_HAS_VALUE_EXPR_P (copy) = 1; -+ } -+ } -+ -+ *expr_p = unshare_expr (value_expr); - return GS_OK; - } - -@@ -7359,6 +7391,9 @@ gimplify_body (tree *body_p, tree fndecl - unshare_body (body_p, fndecl); - unvisit_body (body_p, fndecl); - -+ if (cgraph_node (fndecl)->origin) -+ nonlocal_vlas = pointer_set_create (); -+ - /* Make sure input_location isn't set to something weird. */ - input_location = DECL_SOURCE_LOCATION (fndecl); - -@@ -7394,6 +7429,12 @@ gimplify_body (tree *body_p, tree fndecl - gimple_bind_set_body (outer_bind, parm_stmts); - } - -+ if (nonlocal_vlas) -+ { -+ pointer_set_destroy (nonlocal_vlas); -+ nonlocal_vlas = NULL; -+ } -+ - pop_gimplify_context (outer_bind); - gcc_assert (gimplify_ctxp == NULL); - ---- gcc/fortran/Make-lang.in.jj 2008-12-11 13:30:28.000000000 +0100 -+++ gcc/fortran/Make-lang.in 2009-04-21 19:26:35.000000000 +0200 -@@ -319,7 +319,7 @@ fortran/convert.o: $(GFORTRAN_TRANS_DEPS - fortran/trans.o: $(GFORTRAN_TRANS_DEPS) tree-iterator.h - fortran/trans-decl.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-decl.h \ - $(CGRAPH_H) $(TARGET_H) $(FUNCTION_H) $(FLAGS_H) $(RTL_H) $(GIMPLE_H) \ -- $(TREE_DUMP_H) debug.h -+ $(TREE_DUMP_H) debug.h pointer-set.h - fortran/trans-types.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-types.h \ - $(REAL_H) toplev.h $(TARGET_H) $(FLAGS_H) dwarf2out.h - fortran/trans-const.o: $(GFORTRAN_TRANS_DEPS) ---- gcc/fortran/trans-decl.c.jj 2009-04-14 10:18:29.000000000 +0200 -+++ gcc/fortran/trans-decl.c 2009-04-21 19:26:35.000000000 +0200 -@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. - #include "cgraph.h" - #include "debug.h" - #include "gfortran.h" -+#include "pointer-set.h" - #include "trans.h" - #include "trans-types.h" - #include "trans-array.h" -@@ -60,6 +61,8 @@ static GTY(()) tree current_function_ret - static GTY(()) tree saved_function_decls; - static GTY(()) tree saved_parent_function_decls; - -+static struct pointer_set_t *nonlocal_dummy_decl_pset; -+static GTY(()) tree nonlocal_dummy_decls; - - /* The namespace of the module we're currently generating. Only used while - outputting decls for module variables. Do not rely on this being set. */ -@@ -870,6 +873,38 @@ gfc_build_dummy_array_decl (gfc_symbol * - return decl; - } - -+/* For symbol SYM with GFC_DECL_SAVED_DESCRIPTOR used in contained -+ function add a VAR_DECL to the current function with DECL_VALUE_EXPR -+ pointing to the artificial variable for debug info purposes. */ -+ -+static void -+gfc_nonlocal_dummy_array_decl (gfc_symbol *sym) -+{ -+ tree decl, dummy; -+ -+ if (! nonlocal_dummy_decl_pset) -+ nonlocal_dummy_decl_pset = pointer_set_create (); -+ -+ if (pointer_set_insert (nonlocal_dummy_decl_pset, sym->backend_decl)) -+ return; -+ -+ dummy = GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl); -+ decl = build_decl (VAR_DECL, DECL_NAME (dummy), -+ TREE_TYPE (sym->backend_decl)); -+ DECL_ARTIFICIAL (decl) = 0; -+ TREE_USED (decl) = 1; -+ TREE_PUBLIC (decl) = 0; -+ TREE_STATIC (decl) = 0; -+ DECL_EXTERNAL (decl) = 0; -+ if (DECL_BY_REFERENCE (dummy)) -+ DECL_BY_REFERENCE (decl) = 1; -+ DECL_LANG_SPECIFIC (decl) = DECL_LANG_SPECIFIC (sym->backend_decl); -+ SET_DECL_VALUE_EXPR (decl, sym->backend_decl); -+ DECL_HAS_VALUE_EXPR_P (decl) = 1; -+ DECL_CONTEXT (decl) = DECL_CONTEXT (sym->backend_decl); -+ TREE_CHAIN (decl) = nonlocal_dummy_decls; -+ nonlocal_dummy_decls = decl; -+} - - /* Return a constant or a variable to use as a string length. Does not - add the decl to the current scope. */ -@@ -1010,6 +1045,13 @@ gfc_get_symbol_decl (gfc_symbol * sym) - { - gfc_add_assign_aux_vars (sym); - } -+ -+ if (sym->attr.dimension -+ && DECL_LANG_SPECIFIC (sym->backend_decl) -+ && GFC_DECL_SAVED_DESCRIPTOR (sym->backend_decl) -+ && DECL_CONTEXT (sym->backend_decl) != current_function_decl) -+ gfc_nonlocal_dummy_array_decl (sym); -+ - return sym->backend_decl; - } - -@@ -1129,6 +1171,13 @@ gfc_get_symbol_decl (gfc_symbol * sym) - sym->attr.pointer || sym->attr.allocatable); - } - -+ if (!TREE_STATIC (decl) -+ && POINTER_TYPE_P (TREE_TYPE (decl)) -+ && !sym->attr.pointer -+ && !sym->attr.allocatable -+ && !sym->attr.proc_pointer) -+ DECL_BY_REFERENCE (decl) = 1; -+ - return decl; - } - -@@ -3852,6 +3901,9 @@ gfc_generate_function_code (gfc_namespac - - gfc_generate_contained_functions (ns); - -+ nonlocal_dummy_decls = NULL; -+ nonlocal_dummy_decl_pset = NULL; -+ - generate_local_vars (ns); - - /* Keep the parent fake result declaration in module functions -@@ -4111,6 +4163,15 @@ gfc_generate_function_code (gfc_namespac - = build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (fndecl), - DECL_INITIAL (fndecl)); - -+ if (nonlocal_dummy_decls) -+ { -+ BLOCK_VARS (DECL_INITIAL (fndecl)) -+ = chainon (BLOCK_VARS (DECL_INITIAL (fndecl)), nonlocal_dummy_decls); -+ pointer_set_destroy (nonlocal_dummy_decl_pset); -+ nonlocal_dummy_decls = NULL; -+ nonlocal_dummy_decl_pset = NULL; -+ } -+ - /* Output the GENERIC tree. */ - dump_function (TDI_original, fndecl); - diff --git a/sources b/sources index 9741493..52a1bdb 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 2659f09c2e43ef8b7d4406321753f1b2 fastjar-0.97.tar.gz -441af0d1283e61c52f241a06710f56a3 gcc-4.4.0-20090424.tar.bz2 +373986714230ac85e2d6d6e4abb107e0 gcc-4.4.0-20090427.tar.bz2