[mingw-gcc: 8/36] 4.4.1-1

epienbro epienbro at fedoraproject.org
Tue Mar 6 19:19:02 UTC 2012


commit 7274853965fbf7a36d201b6b720fc27fad0301c3
Author: Kalev Lember <kalev at fedoraproject.org>
Date:   Tue Aug 25 20:26:28 2009 +0000

    4.4.1-1

 .cvsignore                    |    2 +-
 gcc44-atom.patch              | 2832 ---------------------------
 gcc44-hack.patch              |    6 +-
 gcc44-libstdc++-docs.patch    |   47 +
 gcc44-memmove-opt.patch       |  128 --
 gcc44-power7-2.patch          | 1574 +++-------------
 gcc44-power7-3.patch          | 3523 ++++++++++++++++++++++++++++++++++
 gcc44-power7.patch            | 4261 ++++++++++++++++++++++++++++++-----------
 gcc44-pr27898.patch           |   16 -
 gcc44-pr32139.patch           |   19 -
 gcc44-pr37959.patch           |  146 --
 gcc44-pr39226.patch           |  108 --
 gcc44-rh330771.patch          |   26 +-
 gcc44-rh503816-1.patch        |  827 ++++++++
 gcc44-rh503816-2.patch        |  491 +++++
 gcc44-unique-object.patch     |  142 ++
 gcc44-unwind-debug-hook.patch |   46 +
 mingw32-gcc.spec              |   64 +-
 sources                       |    2 +-
 19 files changed, 8464 insertions(+), 5796 deletions(-)
---
diff --git a/.cvsignore b/.cvsignore
index 12497ff..133dcdc 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1 +1 @@
-gcc-4.4.0-20090319.tar.bz2
+gcc-4.4.1-20090818.tar.bz2
diff --git a/gcc44-hack.patch b/gcc44-hack.patch
index da00568..c770339 100644
--- a/gcc44-hack.patch
+++ b/gcc44-hack.patch
@@ -1,8 +1,8 @@
 --- libada/Makefile.in.jj	2009-01-14 12:07:35.000000000 +0100
 +++ libada/Makefile.in	2009-01-15 14:25:33.000000000 +0100
-@@ -66,17 +66,39 @@ target_noncanonical:=@target_noncanonica
- version := $(shell cat $(srcdir)/../gcc/BASE-VER)
+@@ -67,17 +67,39 @@ version := $(shell cat $(srcdir)/../gcc/
  libsubdir := $(libdir)/gcc/$(target_noncanonical)/$(version)$(MULTISUBDIR)
+ ADA_RTS_DIR=$(GCC_DIR)/ada/rts$(subst /,_,$(MULTISUBDIR))
  
 +DEFAULTMULTIFLAGS :=
 +ifeq ($(MULTISUBDIR),)
@@ -43,7 +43,7 @@
          "TARGET_LIBGCC2_CFLAGS=$(TARGET_LIBGCC2_CFLAGS)" \
          "THREAD_KIND=$(THREAD_KIND)" \
          "TRACE=$(TRACE)" \
-@@ -87,7 +109,7 @@ LIBADA_FLAGS_TO_PASS = \
+@@ -88,7 +110,7 @@ LIBADA_FLAGS_TO_PASS = \
          "exeext=.exeext.should.not.be.used " \
  	'CC=the.host.compiler.should.not.be.needed' \
  	"GCC_FOR_TARGET=$(CC)" \
diff --git a/gcc44-libstdc++-docs.patch b/gcc44-libstdc++-docs.patch
new file mode 100644
index 0000000..45caafe
--- /dev/null
+++ b/gcc44-libstdc++-docs.patch
@@ -0,0 +1,47 @@
+--- libstdc++-v3/doc/html/index.html	2009-01-14 12:06:37.000000000 +0100
++++ libstdc++-v3/doc/html/index.html	2009-05-06 09:17:30.000000000 +0200
+@@ -12,7 +12,8 @@
+ <div>
+ <h1>The GNU C++ Library Documentation</h1>
+ 
+-<p>Copyright 2008 FSF</p>
++<p>Release 4.4.0</p>
++<p>Copyright 2008, 2009 FSF</p>
+ 
+ <p>
+   Permission is granted to copy, distribute and/or modify this
+--- libstdc++-v3/doc/html/api.html	2009-04-20 21:21:15.000000000 +0200
++++ libstdc++-v3/doc/html/api.html	2009-05-06 09:17:24.000000000 +0200
+@@ -17,27 +17,12 @@ useful for examining the signatures of p
+ the library classes, finding out what is in a particular include
+ file, looking at inheritance diagrams, etc.
+ </p><p>
+-The source-level documentation for the most recent releases can be
+-viewed online:
+-</p><div class="itemizedlist"><ul type="disc"><li><p>
+-      <a class="ulink" href="libstdc++-html-USERS-3.4/index.html" target="_top">for the 3.4 release
++The source-level documentation can be viewed here:
++</p>
++<div class="itemizedlist"><ul type="disc">
++    <li><p>
++      <a class="ulink" href="api/index.html" target="_top">for the 4.4 release
+       </a>
+-    </p></li><li><p>
+-      <a class="ulink" href="libstdc++-html-USERS-4.1/index.html" target="_top">for the 4.1 release
+-      </a>
+-    </p></li><li><p>
+-      <a class="ulink" href="libstdc++-html-USERS-4.2/index.html" target="_top">for the 4.2 release
+-      </a>
+-    </p></li><li><p>
+-      <a class="ulink" href="libstdc++-html-USERS-4.3/index.html" target="_top">for the 4.3 release
+-      </a>
+-    </p></li><li><p>
+-      <a class="ulink" href="libstdc++-html-USERS-4.4/index.html" target="_top">for the 4.4 release
+-      </a>
+-    </p></li><li><p>
+-      <a class="ulink" href="latest-doxygen/index.html" target="_top">"the latest collection"
+-      </a>
+-      (For the main development tree; see the date on the first page.)
+     </p></li></ul></div><p>
+ This generated HTML collection, as above, is also available for download in the libstdc++ snapshots directory at
+    <code class="literal">&lt;URL:ftp://gcc.gnu.org/pub/gcc/libstdc++/doxygen/&gt;</code>.
diff --git a/gcc44-power7-2.patch b/gcc44-power7-2.patch
index 519f8b9..a296217 100644
--- a/gcc44-power7-2.patch
+++ b/gcc44-power7-2.patch
@@ -1,1369 +1,267 @@
-2009-03-13  Michael Meissner  <meissner at linux.vnet.ibm.com>
+2009-04-14  Michael Meissner  <meissner at linux.vnet.ibm.com>
 
-	PR target/39457
-	* config/rs6000/rs6000.opt (-mdisallow-float-in-lr-ctr): Add
-	temporary debug switch.
+	* config/rs6000/rs6000.c (rs6000_secondary_reload_inner): Handle
+	more possible combinations of addresses.
 
-	* config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Revert
-	behavior of disallowing 
+	* config/rs6000/vector.md (vec_reload_and_plus_<mptrsize>): Allow
+	register+small constant in addition to register+register, and
+	restrict the insn to only match during reload and afterwards.
+	(vec_reload_and_reg_<mptrsize>): Allow for and of register
+	indirect to not generate insn not found message.
 
-2009-03-13  Michael Meissner  <meissner at linux.vnet.ibm.com>
-
-	* config/rs6000/vector.md (vec_extract_evenv2df): Delete, insn
-	causes problems in building spec 2006.
-	(vec_extract_oddv2df): Ditto.
-	(vec_pack_trunc_v2df): New expanders for VSX vectorized
-	conversions.
-	(vec_pack_sfix_trunc_v2df): Ditto.
-	(vec_pack_ufix_trunc_v2df): Ditto.
-	(vec_unpacks_hi_v4sf): Ditto.
-	(vec_unpacks_lo_v4sf): Ditto.
-	(vec_unpacks_float_hi_v4si): Ditto.
-	(vec_unpacks_float_lo_v4si): Ditto.
-	(vec_unpacku_float_hi_v4si): Ditto.
-	(vec_unpacku_float_lo_v4si): Ditto.
-
-	* config/rs6000/rs6000-protos.h (rs6000_vector_secondary_reload):
-	Declaration for new target hook.
-
-	* config/rs6000/rs6000.c (TARGET_SECONDARY_RELOAD): Add new target
-	hook for eventually fixing up the memory references for Altivec
-	and VSX reloads to be reg+reg instead of reg+offset.  Right now,
-	this is a stub function that prints debug information if
-	-mdebug=addr and then calls default_secondary_reload.
-	(rs6000_secondary_reload): Ditto.
-	(rs6000_vector_secondary_reload): Ditto.
-	(rs6000_builtin_conversion): Add support for V2DI/V2DF
-	conversions.
-	(rs6000_legitimate_offset_address_p): Test for the vector unit
-	doing the memory references.
-	(rs6000_legimize_reload_address): Ditto.
-	(rs6000_legitimize_address): Print extra \n if -mdebug=addr.
-	(rs6000_legitimize_reload_address): Ditto.
-	(rs6000_legitimate_address): Ditto.
-	(rs6000_mode_dependent_address): Ditto.
-	(bdesc_2arg): Add VSX builtins.
-	(bdesc_abs): Ditto.
-	(bdesc_1arg): Ditto.
-	(altivec_init_builtins): Ditto.
-	(rs6000_secondary_memory_needed_rtx): Add debug support if
-	-mdebug=addr.
-	(rs6000_preferred_reload_class): Ditto.
-	(rs6000_secondary_memory_needed): Ditto.
-	(rs6000_secondary_reload_class): Ditto.
-	(rs6000_cannot_change_mode_class): Ditto.
-
-	* config/rs6000/vsx.md (UNSPEC_VSX_*): Add unspecs for VSX
-	conversions.
-	(vsx_nabs<mode>): Add generator function.
-	(vsx_float<VSi><mode>2): Ditto.
-	(vsx_floatuns<VSi><mode>2): Ditto.
-	(vsx_xxmrghw): Ditto.
-	(vsx_xxmrglw): Ditto.
-	(vsx_xvcvdpsp): New VSX vector conversion insn.
-	(vsx_xvcvdpsxws): Ditto.
-	(vsx_xvcvdpuxws): Ditto.
-	(vsx_xvcvspdp): Ditto.
-	(vsx_xvcvsxwdp): Ditto.
-	(vsx_xvcvuxwdp): Ditto.
-	(vsx_reload_*): New insns for reload support.
-
-	* config/rs6000/rs6000.h: Fix a comment.
-
-	* config/rs6000/altivec.md (altivec_reload_*): New insns for
-	reload support.
-
-	* config/rs6000/rs6000.md (ptrsize): New mode attribute for the
-	pointer size.
-
-2009-03-10  Michael Meissner  <meissner at linux.vnet.ibm.com>
-
-	* config/rs6000/vsx.md (vsx_concat_v2df): Add explicit 'f'
-	register class for scalar data, correct uses of the xxpermdi
-	instruction.
-	(vsx_set_v2df): Ditto.
-	(vsx_extract_v2df): Ditto.
-	(vsx_xxpermdi): Ditto.
-	(vsx_splatv2df): Ditto.
-	(vsx_xxmrghw): Use wf instead of v constraints.
-	(vsx_xxmrglw): Ditto.
-testsuite/
-2009-03-13  Michael Meissner  <meissner at linux.vnet.ibm.com>
-
-	PR target/39457
-	* gcc.target/powerpc/pr39457.c: New test for PR39457.
-
-2009-03-13  Michael Meissner  <meissner at linux.vnet.ibm.com>
-
-	* gcc.target/powerpc/vsx-builtin-1.c: New test for builtins.
-	* gcc.target/powerpc/vsx-builtin-2.c: Ditto.
-
---- gcc/config/rs6000/vector.md	(revision 144758)
-+++ gcc/config/rs6000/vector.md	(revision 144843)
-@@ -496,23 +496,122 @@ (define_expand "vec_interleave_lowv2df"
-   "VECTOR_UNIT_VSX_P (V2DFmode)"
-   "")
- 
--;; For 2 element vectors, even/odd is the same as high/low
--(define_expand "vec_extract_evenv2df"
--  [(set (match_operand:V2DF 0 "vfloat_operand" "")
--	(vec_concat:V2DF
--	 (vec_select:DF (match_operand:V2DF 1 "vfloat_operand" "")
--			(parallel [(const_int 0)]))
--	 (vec_select:DF (match_operand:V2DF 2 "vfloat_operand" "")
--			(parallel [(const_int 0)]))))]
--  "VECTOR_UNIT_VSX_P (V2DFmode)"
--  "")
-+
-+;; Convert double word types to single word types
-+(define_expand "vec_pack_trunc_v2df"
-+  [(match_operand:V4SF 0 "vsx_register_operand" "")
-+   (match_operand:V2DF 1 "vsx_register_operand" "")
-+   (match_operand:V2DF 2 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
-+{
-+  rtx r1 = gen_reg_rtx (V4SFmode);
-+  rtx r2 = gen_reg_rtx (V4SFmode);
- 
--(define_expand "vec_extract_oddv2df"
--  [(set (match_operand:V2DF 0 "vfloat_operand" "")
--	(vec_concat:V2DF
--	 (vec_select:DF (match_operand:V2DF 1 "vfloat_operand" "")
--			(parallel [(const_int 1)]))
--	 (vec_select:DF (match_operand:V2DF 2 "vfloat_operand" "")
--			(parallel [(const_int 1)]))))]
--  "VECTOR_UNIT_VSX_P (V2DFmode)"
--  "")
-+  emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
-+  emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
-+  emit_insn (gen_vec_extract_evenv4sf (operands[0], r1, r2));
-+  DONE;
-+})
-+
-+(define_expand "vec_pack_sfix_trunc_v2df"
-+  [(match_operand:V4SI 0 "vsx_register_operand" "")
-+   (match_operand:V2DF 1 "vsx_register_operand" "")
-+   (match_operand:V2DF 2 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
-+{
-+  rtx r1 = gen_reg_rtx (V4SImode);
-+  rtx r2 = gen_reg_rtx (V4SImode);
-+
-+  emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
-+  emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
-+  emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
-+  DONE;
-+})
-+
-+(define_expand "vec_pack_ufix_trunc_v2df"
-+  [(match_operand:V4SI 0 "vsx_register_operand" "")
-+   (match_operand:V2DF 1 "vsx_register_operand" "")
-+   (match_operand:V2DF 2 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
-+{
-+  rtx r1 = gen_reg_rtx (V4SImode);
-+  rtx r2 = gen_reg_rtx (V4SImode);
-+
-+  emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
-+  emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
-+  emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
-+  DONE;
-+})
-+
-+;; Convert single word types to double word
-+(define_expand "vec_unpacks_hi_v4sf"
-+  [(match_operand:V2DF 0 "vsx_register_operand" "")
-+   (match_operand:V4SF 1 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
-+{
-+  rtx reg = gen_reg_rtx (V4SFmode);
-+
-+  emit_insn (gen_vec_interleave_highv4sf (reg, operands[1], operands[1]));
-+  emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
-+  DONE;
-+})
-+
-+(define_expand "vec_unpacks_lo_v4sf"
-+  [(match_operand:V2DF 0 "vsx_register_operand" "")
-+   (match_operand:V4SF 1 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
-+{
-+  rtx reg = gen_reg_rtx (V4SFmode);
-+
-+  emit_insn (gen_vec_interleave_lowv4sf (reg, operands[1], operands[1]));
-+  emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
-+  DONE;
-+})
-+
-+(define_expand "vec_unpacks_float_hi_v4si"
-+  [(match_operand:V2DF 0 "vsx_register_operand" "")
-+   (match_operand:V4SI 1 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
-+{
-+  rtx reg = gen_reg_rtx (V4SImode);
-+
-+  emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
-+  emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
-+  DONE;
-+})
-+
-+(define_expand "vec_unpacks_float_lo_v4si"
-+  [(match_operand:V2DF 0 "vsx_register_operand" "")
-+   (match_operand:V4SI 1 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
-+{
-+  rtx reg = gen_reg_rtx (V4SImode);
-+
-+  emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
-+  emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
-+  DONE;
-+})
-+
-+(define_expand "vec_unpacku_float_hi_v4si"
-+  [(match_operand:V2DF 0 "vsx_register_operand" "")
-+   (match_operand:V4SI 1 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
-+{
-+  rtx reg = gen_reg_rtx (V4SImode);
-+
-+  emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
-+  emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
-+  DONE;
-+})
-+
-+(define_expand "vec_unpacku_float_lo_v4si"
-+  [(match_operand:V2DF 0 "vsx_register_operand" "")
-+   (match_operand:V4SI 1 "vsx_register_operand" "")]
-+  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
-+{
-+  rtx reg = gen_reg_rtx (V4SImode);
-+
-+  emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
-+  emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
-+  DONE;
-+})
---- gcc/config/rs6000/rs6000-protos.h	(revision 144758)
-+++ gcc/config/rs6000/rs6000-protos.h	(revision 144843)
-@@ -72,6 +72,7 @@ extern bool rs6000_secondary_memory_need
- extern bool rs6000_cannot_change_mode_class (enum machine_mode,
- 					     enum machine_mode,
- 					     enum reg_class);
-+extern void rs6000_vector_secondary_reload (rtx, rtx, rtx, bool);
- extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,
-                                          rtx, rtx, rtx);
- extern void paired_expand_vector_move (rtx operands[]);
---- gcc/config/rs6000/rs6000.opt	(revision 144845)
-+++ gcc/config/rs6000/rs6000.opt	(revision 144857)
-@@ -139,6 +139,9 @@ mvsx-scalar-memory
- Target Report Var(TARGET_VSX_SCALAR_MEMORY)
- If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
- 
-+mdisallow-float-in-lr-ctr
-+Target Undocumented Var(TARGET_DISALLOW_FLOAT_IN_LR_CTR) Init(-1)
-+
- mupdate
- Target Report Var(TARGET_UPDATE) Init(1)
- Generate load/store with update instructions
---- gcc/config/rs6000/rs6000.c	(revision 144758)
-+++ gcc/config/rs6000/rs6000.c	(revision 144843)
-@@ -1004,6 +1004,10 @@ static rtx rs6000_emit_vector_compare (e
- 				       enum machine_mode);
- static tree rs6000_stack_protect_fail (void);
- 
-+static enum reg_class rs6000_secondary_reload (bool, rtx, enum reg_class,
-+					       enum machine_mode,
-+					       struct secondary_reload_info *);
-+
- const int INSN_NOT_AVAILABLE = -1;
- static enum machine_mode rs6000_eh_return_filter_mode (void);
- 
-@@ -1333,6 +1337,9 @@ static const char alt_reg_names[][8] =
- #undef TARGET_INSTANTIATE_DECLS
- #define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls
- 
-+#undef TARGET_SECONDARY_RELOAD
-+#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
-+
- struct gcc_target targetm = TARGET_INITIALIZER;
+--- gcc/config/rs6000/vector.md	(revision 146069)
++++ gcc/config/rs6000/vector.md	(revision 146118)
+@@ -129,14 +129,15 @@ (define_expand "reload_<VEC_R:mode>_<P:m
+ })
+ 
+ ;; Reload sometimes tries to move the address to a GPR, and can generate
+-;; invalid RTL for addresses involving AND -16.
++;; invalid RTL for addresses involving AND -16.  Allow addresses involving
++;; reg+reg, reg+small constant, or just reg, all wrapped in an AND -16.
+ 
+ (define_insn_and_split "*vec_reload_and_plus_<mptrsize>"
+   [(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_<mptrsize>"
++  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
++	(and:P (match_operand:P 1 "gpc_reg_operand" "r")
++	       (const_int -16)))]
++  "(TARGET_ALTIVEC || TARGET_VSX) && (reload_in_progress || reload_completed)"
++  "#"
++  "&& reload_completed"
++  [(parallel [(set (match_dup 0)
++		   (and:P (match_dup 1)
++			  (const_int -16)))
++	      (clobber:CC (scratch:CC))])])
  
- /* Return number of consecutive hard regs needed starting at reg REGNO
-@@ -1448,10 +1448,16 @@ rs6000_hard_regno_mode_ok (int regno, en
-   if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
-     return 1;
+ ;; Generic floating point vector arithmetic support
+ (define_expand "add<mode>3"
+--- gcc/config/rs6000/rs6000.c	(revision 146069)
++++ gcc/config/rs6000/rs6000.c	(revision 146118)
+@@ -12574,6 +12574,11 @@ rs6000_secondary_reload_inner (rtx reg, 
+   enum reg_class rclass;
+   rtx addr;
+   rtx and_op2 = NULL_RTX;
++  rtx addr_op1;
++  rtx addr_op2;
++  rtx scratch_or_premodify = scratch;
++  rtx and_rtx;
++  rtx cc_clobber;
  
--  /* Don't allow anything but word sized integers (aka pointers) in CTR/LR.  You
--     really don't want to spill your floating point values to those
--     registers.  Also do it for the old MQ register in the power.  */
--  if (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO)
-+  /* Don't allow anything but word sized integers (aka pointers) in CTR/LR.
-+     You really don't want to spill your floating point values to those
-+     registers.  Also do it for the old MQ register in the power.
-+
-+     While this is desirable in theory, disabling float to go in LR/CTR does
-+     cause some regressions, so until they are taken care of, revert to the old
-+     behavior by default for most power systems, but enable it for power7.  */
-+  if ((TARGET_DISALLOW_FLOAT_IN_LR_CTR > 0
-+       || (TARGET_DISALLOW_FLOAT_IN_LR_CTR < 0 && TARGET_VSX))
-+      && (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO))
-     return (GET_MODE_CLASS (mode) == MODE_INT
- 	    && GET_MODE_SIZE (mode) <= UNITS_PER_WORD);
+   if (TARGET_DEBUG_ADDR)
+     {
+@@ -12595,7 +12600,8 @@ rs6000_secondary_reload_inner (rtx reg, 
  
-@@ -2447,6 +2454,14 @@ rs6000_builtin_conversion (enum tree_cod
-     case FIX_TRUNC_EXPR:
-       switch (TYPE_MODE (type))
- 	{
-+	case V2DImode:
-+	  if (!VECTOR_UNIT_VSX_P (V2DFmode))
-+	    return NULL_TREE;
+   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);
+ 	}
 +
-+	  return TYPE_UNSIGNED (type)
-+	    ? rs6000_builtin_decls[VSX_BUILTIN_XVCVDPUXDS]
-+	    : rs6000_builtin_decls[VSX_BUILTIN_XVCVDPSXDS];
++      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);
++	}
 +
- 	case V4SImode:
- 	  if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
- 	    return NULL_TREE;
-@@ -2462,6 +2477,14 @@ rs6000_builtin_conversion (enum tree_cod
-     case FLOAT_EXPR:
-       switch (TYPE_MODE (type))
+       if (GET_CODE (addr) == PLUS
+ 	  && (!rs6000_legitimate_offset_address_p (TImode, addr, true)
+ 	      || and_op2 != NULL_RTX))
  	{
-+	case V2DImode:
-+	  if (!VECTOR_UNIT_VSX_P (V2DFmode))
-+	    return NULL_TREE;
-+
-+	  return TYPE_UNSIGNED (type)
-+	    ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDSP]
-+	    : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDSP];
+-	  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;
++	    }
 +
- 	case V4SImode:
- 	  if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
- 	    return NULL_TREE;
-@@ -2469,6 +2492,7 @@ rs6000_builtin_conversion (enum tree_cod
- 	  return TYPE_UNSIGNED (type)
- 	    ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF]
- 	    : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF];
++	  emit_insn (gen_rtx_SET (VOIDmode,
++				  scratch_or_premodify,
++				  gen_rtx_PLUS (Pmode,
++						addr_op1,
++						addr_op2)));
 +
- 	default:
- 	  return NULL_TREE;
++	  addr = scratch_or_premodify;
++	  scratch_or_premodify = scratch;
  	}
-@@ -4101,7 +4125,7 @@ rs6000_legitimate_offset_address_p (enum
-     case V2DImode:
-       /* AltiVec/VSX vector modes.  Only reg+reg addressing is valid and
- 	 constant offset zero should not occur due to canonicalization.  */
--      if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
-+      if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
- 	return false;
-       break;
- 
-@@ -4441,6 +4465,7 @@ rs6000_legitimize_address (rtx x, rtx ol
+-      else 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;
  	}
-       else
- 	fprintf (stderr, "NULL returned\n");
-+      fprintf (stderr, "\n");
-     }
+       break;
  
-   return ret;
-@@ -4776,8 +4801,7 @@ rs6000_legitimize_reload_address (rtx x,
- 	   && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
- 	   && GET_CODE (XEXP (x, 1)) == CONST_INT
- 	   && (INTVAL (XEXP (x, 1)) & 3) != 0
--	   && !ALTIVEC_VECTOR_MODE (mode)
--	   && !VSX_VECTOR_MODE (mode)
-+	   && VECTOR_MEM_NONE_P (mode)
- 	   && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
- 	   && TARGET_POWERPC64)
-     {
-@@ -4798,8 +4822,7 @@ rs6000_legitimize_reload_address (rtx x,
- 	   && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
- 				       || mode == DDmode || mode == TDmode
- 				       || mode == DImode))
--	   && !ALTIVEC_VECTOR_MODE (mode)
--	   && !VSX_VECTOR_MODE (mode))
-+	   && VECTOR_MEM_NONE_P (mode))
-     {
-       HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
-       HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
-@@ -4843,6 +4866,7 @@ rs6000_legitimize_reload_address (rtx x,
- 	   /* Don't do this for TFmode or TDmode, since the result isn't
- 	      offsettable.  The same goes for DImode without 64-bit gprs and
- 	      DFmode and DDmode without fprs.  */
-+	   && VECTOR_MEM_NONE_P (mode)
- 	   && mode != TFmode
- 	   && mode != TDmode
- 	   && (mode != DImode || TARGET_POWERPC64)
-@@ -4918,6 +4942,8 @@ rs6000_legitimize_reload_address (rtx x,
- 	  fprintf (stderr, "New address:\n");
- 	  debug_rtx (ret);
++      /* 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);
++	}
 +
-+      fprintf (stderr, "\n");
-     }
- 
-   return ret;
-@@ -5035,6 +5061,7 @@ rs6000_legitimate_address (enum machine_
- 	       GET_MODE_NAME (mode),
- 	       reg_ok_strict);
-       debug_rtx (orig_x);
-+      fprintf (stderr, "\n");
-     }
- 
-   return ret;
-@@ -5082,9 +5109,10 @@ rs6000_mode_dependent_address (rtx addr)
-   if (TARGET_DEBUG_ADDR)
-     {
-       fprintf (stderr,
--	       "\nrs6000_mode_dependent_address: ret = %d\n",
--	       (int)ret);
-+	       "\nrs6000_mode_dependent_address: ret = %s\n",
-+	       ret ? "true" : "false");
-       debug_rtx (addr);
-+      fprintf (stderr, "\n");
-     }
- 
-   return ret;
-@@ -7917,6 +7945,20 @@ static struct builtin_description bdesc_
-   { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
-   { MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
- 
-+  { MASK_VSX, CODE_FOR_addv2df3, "__builtin_vsx_xvadddp", VSX_BUILTIN_XVADDDP },
-+  { MASK_VSX, CODE_FOR_subv2df3, "__builtin_vsx_xvsubdp", VSX_BUILTIN_XVSUBDP },
-+  { MASK_VSX, CODE_FOR_mulv2df3, "__builtin_vsx_xvmuldp", VSX_BUILTIN_XVMULDP },
-+  { MASK_VSX, CODE_FOR_divv2df3, "__builtin_vsx_xvdivdp", VSX_BUILTIN_XVDIVDP },
-+  { MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP },
-+  { MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP },
-+
-+  { MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP },
-+  { MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP },
-+  { MASK_VSX, CODE_FOR_mulv4sf3, "__builtin_vsx_xvmulsp", VSX_BUILTIN_XVMULSP },
-+  { MASK_VSX, CODE_FOR_divv4sf3, "__builtin_vsx_xvdivsp", VSX_BUILTIN_XVDIVSP },
-+  { MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP },
-+  { MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP },
-+
-   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
-   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
-   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM },
-@@ -8288,7 +8330,11 @@ static const struct builtin_description 
-   { MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI },
-   { MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI },
-   { MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI },
--  { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI }
-+  { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI },
-+  { MASK_VSX, CODE_FOR_absv2df2, "__builtin_vsx_xvabsdp", VSX_BUILTIN_XVABSDP },
-+  { MASK_VSX, CODE_FOR_vsx_nabsv2df2, "__builtin_vsx_xvnabsdp", VSX_BUILTIN_XVNABSDP },
-+  { MASK_VSX, CODE_FOR_absv4sf2, "__builtin_vsx_xvabssp", VSX_BUILTIN_XVABSSP },
-+  { MASK_VSX, CODE_FOR_vsx_nabsv4sf2, "__builtin_vsx_xvnabssp", VSX_BUILTIN_XVNABSSP },
- };
- 
- /* Simple unary operations: VECb = foo (unsigned literal) or VECb =
-@@ -8314,6 +8360,11 @@ static struct builtin_description bdesc_
-   { MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
-   { MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
- 
-+  { MASK_VSX, CODE_FOR_negv2df2, "__builtin_vsx_xvnegdp", VSX_BUILTIN_XVNEGDP },
-+  { MASK_VSX, CODE_FOR_sqrtv2df2, "__builtin_vsx_xvsqrtdp", VSX_BUILTIN_XVSQRTDP },
-+  { MASK_VSX, CODE_FOR_negv4sf2, "__builtin_vsx_xvnegsp", VSX_BUILTIN_XVNEGSP },
-+  { MASK_VSX, CODE_FOR_sqrtv4sf2, "__builtin_vsx_xvsqrtsp", VSX_BUILTIN_XVSQRTSP },
-+
-   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS },
-   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS },
-   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL },
-@@ -8339,6 +8390,15 @@ static struct builtin_description bdesc_
-   { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI },
-   { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
- 
-+  { MASK_VSX, CODE_FOR_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP },
-+  { MASK_VSX, CODE_FOR_unsigned_floatv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP },
-+  { MASK_VSX, CODE_FOR_fix_truncv2dfv2di2, "__builtin_vsx_xvdpsxds", VSX_BUILTIN_XVCVDPSXDS },
-+  { MASK_VSX, CODE_FOR_fixuns_truncv2dfv2di2, "__builtin_vsx_xvdpuxds", VSX_BUILTIN_XVCVDPUXDS },
-+  { MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXDSP },
-+  { MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP },
-+  { MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vsx_xvspsxws", VSX_BUILTIN_XVCVSPSXWS },
-+  { MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vsx_xvspuxws", VSX_BUILTIN_XVCVSPUXWS },
-+
-   /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
-      end with SPE_BUILTIN_EVSUBFUSIAAW.  */
-   { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
-@@ -10484,6 +10544,8 @@ altivec_init_builtins (void)
-     = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE);
-   tree v4sf_ftype_v4sf
-     = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
-+  tree v2df_ftype_v2df
-+    = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE);
-   tree void_ftype_pcvoid_int_int
-     = build_function_type_list (void_type_node,
- 				pcvoid_type_node, integer_type_node,
-@@ -10641,6 +10703,9 @@ altivec_init_builtins (void)
- 	case V4SFmode:
- 	  type = v4sf_ftype_v4sf;
- 	  break;
-+	case V2DFmode:
-+	  type = v2df_ftype_v2df;
-+	  break;
- 	default:
- 	  gcc_unreachable ();
++      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;
  	}
-@@ -10960,6 +11025,18 @@ rs6000_common_init_builtins (void)
-   tree int_ftype_v8hi_v8hi
-     = build_function_type_list (integer_type_node,
- 				V8HI_type_node, V8HI_type_node, NULL_TREE);
-+  tree v2di_ftype_v2df
-+    = build_function_type_list (V2DI_type_node,
-+				V2DF_type_node, NULL_TREE);
-+  tree v2df_ftype_v2df
-+    = build_function_type_list (V2DF_type_node,
-+				V2DF_type_node, NULL_TREE);
-+  tree v2df_ftype_v2di
-+    = build_function_type_list (V2DF_type_node,
-+				V2DI_type_node, NULL_TREE);
-+  tree v2df_ftype_v2df_v2df
-+    = build_function_type_list (V2DF_type_node,
-+				V2DF_type_node, V2DF_type_node, NULL_TREE);
-   tree v2df_ftype_v2df_v2df_v2df
-     = build_function_type_list (V2DF_type_node,
- 				V2DF_type_node, V2DF_type_node,
-@@ -11136,6 +11213,9 @@ rs6000_common_init_builtins (void)
- 	    case VOIDmode:
- 	      type = opaque_ftype_opaque_opaque;
- 	      break;
-+	    case V2DFmode:
-+	      type = v2df_ftype_v2df_v2df;
-+	      break;
- 	    case V4SFmode:
- 	      type = v4sf_ftype_v4sf_v4sf;
- 	      break;
-@@ -11285,6 +11365,8 @@ rs6000_common_init_builtins (void)
- 	type = v16qi_ftype_int;
-       else if (mode0 == VOIDmode && mode1 == VOIDmode)
- 	type = opaque_ftype_opaque;
-+      else if (mode0 == V2DFmode && mode1 == V2DFmode)
-+	type = v2df_ftype_v2df;
-       else if (mode0 == V4SFmode && mode1 == V4SFmode)
- 	type = v4sf_ftype_v4sf;
-       else if (mode0 == V8HImode && mode1 == V16QImode)
-@@ -11310,6 +11392,10 @@ rs6000_common_init_builtins (void)
- 	type = v4si_ftype_v4sf;
-       else if (mode0 == V4SFmode && mode1 == V4SImode)
- 	type = v4sf_ftype_v4si;
-+      else if (mode0 == V2DImode && mode1 == V2DFmode)
-+	type = v2di_ftype_v2df;
-+      else if (mode0 == V2DFmode && mode1 == V2DImode)
-+	type = v2df_ftype_v2di;
-       else
- 	gcc_unreachable ();
- 
-@@ -12092,8 +12178,10 @@ rtx
- rs6000_secondary_memory_needed_rtx (enum machine_mode mode)
- {
-   static bool eliminated = false;
-+  rtx ret;
 +
-   if (mode != SDmode)
--    return assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
-+    ret = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
-   else
-     {
-       rtx mem = cfun->machine->sdmode_stack_slot;
-@@ -12105,8 +12193,21 @@ rs6000_secondary_memory_needed_rtx (enum
- 	  cfun->machine->sdmode_stack_slot = mem;
- 	  eliminated = true;
- 	}
--      return mem;
-+      ret = mem;
-+    }
++      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;
++	}
 +
-+  if (TARGET_DEBUG_ADDR)
-+    {
-+      fprintf (stderr, "rs6000_secondary_memory_needed_rtx, mode %s, rtx:\n",
-+	       GET_MODE_NAME (mode));
-+      if (!ret)
-+	fprintf (stderr, "\tNULL_RTX\n");
 +      else
-+	debug_rtx (ret);
-+      fprintf (stderr, "\n");
-     }
++	gcc_unreachable ();
 +
-+  return ret;
- }
+       break;
  
- static tree
-@@ -12140,6 +12241,54 @@ rs6000_check_sdmode (tree *tp, int *walk
-   return NULL_TREE;
- }
+     default:
+       gcc_unreachable ();
+     }
  
-+/* Inform reload about cases where moving X with a mode MODE to a register in
-+   RCLASS requires an extra scratch or immediate register.  Return the class
-+   needed for the immediate register.  */
-+
-+static enum reg_class
-+rs6000_secondary_reload (bool in_p,
-+			 rtx x,
-+			 enum reg_class rclass,
-+			 enum machine_mode mode,
-+			 secondary_reload_info *sri)
-+{
-+  if (TARGET_DEBUG_ADDR)
-+    {
-+      fprintf (stderr,
-+	       "rs6000_secondary_reload, in_p = %s, rclass = %s, mode = %s\n",
-+	       in_p ? "true" : "false", reg_class_names[rclass],
-+	       GET_MODE_NAME (mode));
-+      debug_rtx (x);
-+      fprintf (stderr, "\n");
-+    }
-+
-+  return default_secondary_reload (in_p, x, rclass, mode, sri);
-+}
-+
-+/* Fixup reload addresses for Altivec or VSX loads/stores to change SP+offset
-+   to SP+reg addressing.  */
-+
-+void
-+rs6000_vector_secondary_reload (rtx op0, rtx op1, rtx op2, bool to_mem_p)
-+{
-+  rtx memref = to_mem_p ? op0 : op1;
-+  gcc_assert (MEM_P (memref));
-+
-+  if (TARGET_DEBUG_ADDR)
+-  /* If the original address involved an AND -16 that is part of the Altivec
+-     addresses, recreate the and now.  */
++  /* If the original address involved a pre-modify that we couldn't use the VSX
++     memory instruction with update, and we haven't taken care of already,
++     store the address in the pre-modify register and use that as the
++     address.  */
++  if (scratch_or_premodify != scratch && scratch_or_premodify != addr)
 +    {
-+      fprintf (stderr, "rs6000_vector_secondary_reload, to_mem_p = %s\n",
-+	       to_mem_p ? "true" : "false");
-+      fprintf (stderr, "op0:\n");
-+      debug_rtx (op0);
-+      fprintf (stderr, "op1:\n");
-+      debug_rtx (op1);
-+      fprintf (stderr, "op2:\n");
-+      debug_rtx (op2);
-+      fprintf (stderr, "\n");
-+    }
-+
-+  gcc_unreachable ();
-+}
- 
- /* Allocate a 64-bit stack slot to be used for copying SDmode
-    values through if this function has any SDmode references.  */
-@@ -12212,32 +12361,44 @@ enum reg_class
- rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
- {
-   enum machine_mode mode = GET_MODE (x);
-+  enum reg_class ret;
- 
-   if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode)
-       && VSX_REG_CLASS_P (rclass))
--    return rclass;
-+    ret = rclass;
- 
--  if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) && rclass == ALTIVEC_REGS
--      && easy_vector_constant (x, mode))
--    return rclass;
-+  else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode)
-+	   && rclass == ALTIVEC_REGS && easy_vector_constant (x, mode))
-+    ret = rclass;
- 
--  if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
--    return NO_REGS;
-+  else if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
-+    ret = NO_REGS;
- 
--  if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
--    return GENERAL_REGS;
-+  else if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
-+    ret = GENERAL_REGS;
- 
-   /* For VSX, prefer the traditional registers.  */
--  if (rclass == VSX_REGS)
-+  else if (rclass == VSX_REGS)
-     {
-       if (mode == DFmode)
--	return FLOAT_REGS;
-+	ret = FLOAT_REGS;
- 
-       if (ALTIVEC_VECTOR_MODE (mode))
--	return ALTIVEC_REGS;
-+	ret = ALTIVEC_REGS;
++      emit_insn (gen_rtx_SET (VOIDmode, scratch_or_premodify, addr));
++      addr = scratch_or_premodify;
 +    }
-+  else
-+    ret = rclass;
-+
-+  if (TARGET_DEBUG_ADDR)
-+    {
-+      fprintf (stderr,
-+	       "rs6000_preferred_reload_class, return %s, rclass = %s, x:\n",
-+	       reg_class_names[ret], reg_class_names[rclass]);
-+      debug_rtx (x);
-+      fprintf (stderr, "\n");
-     }
- 
--  return rclass;
-+  return ret;
- }
- 
- /* If we are copying between FP or AltiVec registers and anything else, we need
-@@ -12251,31 +12412,46 @@ rs6000_secondary_memory_needed (enum reg
- 				enum reg_class class2,
- 				enum machine_mode mode)
- {
-+  bool ret;
-+  bool vsx1;
-+  bool vsx2;
-+
-   if (class1 == class2)
--    return false;
-+    ret = false;
- 
--  if (TARGET_VSX && VSX_MOVE_MODE (mode) && VSX_REG_CLASS_P (class1)
--      && VSX_REG_CLASS_P (class2))
--    return false;
-+  else if (TARGET_VSX && VECTOR_MEM_VSX_P (mode)
-+	   && ((vsx1 = VSX_REG_CLASS_P (class1))
-+	       || (vsx2 = VSX_REG_CLASS_P (class2))))
-+    ret = (vsx1 != vsx2);
 +
-+  else if (class1 == FLOAT_REGS
-+	   && (!TARGET_MFPGPR || !TARGET_POWERPC64
-+	       || ((mode != DFmode)
-+		   && (mode != DDmode)
-+		   && (mode != DImode))))
-+    ret = true;
-+
-+  else if (class2 == FLOAT_REGS
-+	   && (!TARGET_MFPGPR || !TARGET_POWERPC64
-+	       || ((mode != DFmode)
-+		   && (mode != DDmode)
-+		   && (mode != DImode))))
-+    ret = true;
- 
--  if (class1 == FLOAT_REGS
--       && (!TARGET_MFPGPR || !TARGET_POWERPC64
--	   || ((mode != DFmode)
--	       && (mode != DDmode)
--	       && (mode != DImode))))
--    return true;
-+  else if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS)
-+    ret = true;
- 
--  if (class2 == FLOAT_REGS
--      && (!TARGET_MFPGPR || !TARGET_POWERPC64
--	  || ((mode != DFmode)
--	      && (mode != DDmode)
--	      && (mode != DImode))))
--    return true;
-+  else
-+    ret = false;
- 
--  if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS)
--    return true;
-+  if (TARGET_DEBUG_ADDR)
-+    fprintf (stderr,
-+	     "rs6000_secondary_memory_needed, return: %s, class1 = %s, "
-+	     "class2 = %s, mode = %s\n",
-+	     ret ? "true" : "false", reg_class_names[class1],
-+	     reg_class_names[class2], GET_MODE_NAME (mode));
- 
--  return false;
-+  return ret;
- }
- 
- /* Return the register class of a scratch register needed to copy IN into
-@@ -12287,6 +12463,7 @@ rs6000_secondary_reload_class (enum reg_
- 			       enum machine_mode mode,
- 			       rtx in)
- {
-+  enum reg_class ret = NO_REGS;
-   int regno;
- 
-   if (TARGET_ELF || (DEFAULT_ABI == ABI_DARWIN
-@@ -12307,58 +12484,75 @@ rs6000_secondary_reload_class (enum reg_
- 	      || GET_CODE (in) == HIGH
- 	      || GET_CODE (in) == LABEL_REF
- 	      || GET_CODE (in) == CONST))
--	return BASE_REGS;
-+	ret = BASE_REGS;
-     }
- 
--  if (GET_CODE (in) == REG)
-+  if (ret == NO_REGS)
++  /* 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)
      {
--      regno = REGNO (in);
--      if (regno >= FIRST_PSEUDO_REGISTER)
-+      if (GET_CODE (in) == REG)
+-      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))
 +	{
-+	  regno = REGNO (in);
-+	  if (regno >= FIRST_PSEUDO_REGISTER)
-+	    {
-+	      regno = true_regnum (in);
-+	      if (regno >= FIRST_PSEUDO_REGISTER)
-+		regno = -1;
-+	    }
++	  emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
++	  addr = scratch;
 +	}
-+      else if (GET_CODE (in) == SUBREG)
- 	{
- 	  regno = true_regnum (in);
- 	  if (regno >= FIRST_PSEUDO_REGISTER)
- 	    regno = -1;
- 	}
--    }
--  else if (GET_CODE (in) == SUBREG)
--    {
--      regno = true_regnum (in);
--      if (regno >= FIRST_PSEUDO_REGISTER)
-+      else
- 	regno = -1;
--    }
--  else
--    regno = -1;
- 
--  /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
--     into anything.  */
--  if (rclass == GENERAL_REGS || rclass == BASE_REGS
--      || (regno >= 0 && INT_REGNO_P (regno)))
--    return NO_REGS;
--
--  /* Constants, memory, and FP registers can go into FP registers.  */
--  if ((regno == -1 || FP_REGNO_P (regno))
--      && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
--    return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
--
--  /* Memory, and FP/altivec registers can go into fp/altivec registers under
--     VSX.  */
--  if (TARGET_VSX
--      && (regno == -1 || VSX_REGNO_P (regno))
--      && VSX_REG_CLASS_P (rclass))
--    return NO_REGS;
-+      /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
-+	 into anything.  */
-+      if (rclass == GENERAL_REGS || rclass == BASE_REGS
-+	  || (regno >= 0 && INT_REGNO_P (regno)))
-+	ret = NO_REGS;
-+
-+      /* Constants, memory, and FP registers can go into FP registers.  */
-+      else if ((regno == -1 || FP_REGNO_P (regno))
-+	       && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
-+	ret = (mode != SDmode) ? NO_REGS : GENERAL_REGS;
-+
-+      /* Memory, and FP/altivec registers can go into fp/altivec registers under
-+	 VSX.  */
-+      else if (TARGET_VSX
-+	       && (regno == -1 || VSX_REGNO_P (regno))
-+	       && VSX_REG_CLASS_P (rclass))
-+	ret = NO_REGS;
-+
-+      /* Memory, and AltiVec registers can go into AltiVec registers.  */
-+      else if ((regno == -1 || ALTIVEC_REGNO_P (regno))
-+	       && rclass == ALTIVEC_REGS)
-+	ret = NO_REGS;
-+
-+      /* We can copy among the CR registers.  */
-+      else if ((rclass == CR_REGS || rclass == CR0_REGS)
-+	       && regno >= 0 && CR_REGNO_P (regno))
-+	ret = NO_REGS;
-+
-+      /* Otherwise, we need GENERAL_REGS.  */
-+      else
-+	ret = GENERAL_REGS;
-+    }
- 
--  /* Memory, and AltiVec registers can go into AltiVec registers.  */
--  if ((regno == -1 || ALTIVEC_REGNO_P (regno))
--      && rclass == ALTIVEC_REGS)
--    return NO_REGS;
--
--  /* We can copy among the CR registers.  */
--  if ((rclass == CR_REGS || rclass == CR0_REGS)
--      && regno >= 0 && CR_REGNO_P (regno))
--    return NO_REGS;
-+  if (TARGET_DEBUG_ADDR)
-+    {
-+      fprintf (stderr,
-+	       "rs6000_secondary_reload_class, return %s, rclass = %s, "
-+	       "mode = %s, input rtx:\n",
-+	       reg_class_names[ret], reg_class_names[rclass],
-+	       GET_MODE_NAME (mode));
-+      debug_rtx (in);
-+      fprintf (stderr, "\n");
-+    }
- 
--  /* Otherwise, we need GENERAL_REGS.  */
--  return GENERAL_REGS;
-+  return ret;
- }
- 
- /* Return nonzero if for CLASS a mode change from FROM to TO is invalid.  */
-@@ -12368,19 +12562,29 @@ rs6000_cannot_change_mode_class (enum ma
- 				 enum machine_mode to,
- 				 enum reg_class rclass)
- {
--  return (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)
--	  ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8
--	      || TARGET_IEEEQUAD)
--	     && reg_classes_intersect_p (FLOAT_REGS, rclass))
--	  : (((TARGET_E500_DOUBLE
--	       && ((((to) == DFmode) + ((from) == DFmode)) == 1
--		   || (((to) == TFmode) + ((from) == TFmode)) == 1
--		   || (((to) == DDmode) + ((from) == DDmode)) == 1
--		   || (((to) == TDmode) + ((from) == TDmode)) == 1
--		   || (((to) == DImode) + ((from) == DImode)) == 1))
--	      || (TARGET_SPE
--		  && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1))
--	     && reg_classes_intersect_p (GENERAL_REGS, rclass)));
-+  bool ret = (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)
-+	      ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8
-+		  || TARGET_IEEEQUAD)
-+		 && reg_classes_intersect_p (FLOAT_REGS, rclass))
-+	      : (((TARGET_E500_DOUBLE
-+		   && ((((to) == DFmode) + ((from) == DFmode)) == 1
-+		       || (((to) == TFmode) + ((from) == TFmode)) == 1
-+		       || (((to) == DDmode) + ((from) == DDmode)) == 1
-+		       || (((to) == TDmode) + ((from) == TDmode)) == 1
-+		       || (((to) == DImode) + ((from) == DImode)) == 1))
-+		  || (TARGET_SPE
-+		      && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1))
-+		 && reg_classes_intersect_p (GENERAL_REGS, rclass)));
-+
-+  if (TARGET_DEBUG_ADDR)
-+    fprintf (stderr,
-+	     "rs6000_cannot_change_mode_class, return %s, from = %s, "
-+	     "to = %s, rclass = %s\n",
-+	     ret ? "true" : "false",
-+	     GET_MODE_NAME (from), GET_MODE_NAME (to),
-+	     reg_class_names[rclass]);
-+
-+  return ret;
- }
- 
- /* Given a comparison operation, return the bit number in CCR to test.  We
---- gcc/config/rs6000/vsx.md	(revision 144758)
-+++ gcc/config/rs6000/vsx.md	(revision 144843)
-@@ -68,7 +68,13 @@ (define_mode_attr VSbit [(SI "32")
- 			 (DI "64")])
- 
- (define_constants
--  [(UNSPEC_VSX_CONCAT_V2DF	500)])
-+  [(UNSPEC_VSX_CONCAT_V2DF	500)
-+   (UNSPEC_VSX_XVCVDPSP		501)
-+   (UNSPEC_VSX_XVCVDPSXWS	502)
-+   (UNSPEC_VSX_XVCVDPUXWS	503)
-+   (UNSPEC_VSX_XVCVSPDP		504)
-+   (UNSPEC_VSX_XVCVSXWDP	505)
-+   (UNSPEC_VSX_XVCVUXWDP	506)])
- 
- ;; VSX moves
- (define_insn "*vsx_mov<mode>"
-@@ -245,7 +251,7 @@ (define_insn "*vsx_abs<mode>2"
-   "xvabs<VSs> %x0,%x1"
-   [(set_attr "type" "vecfloat")])
- 
--(define_insn "*vsx_nabs<mode>2"
-+(define_insn "vsx_nabs<mode>2"
-   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-         (neg:VSX_F
- 	 (abs:VSX_F
-@@ -417,14 +423,14 @@ (define_insn "*vsx_ftrunc<mode>2"
-   "xvr<VSs>piz %x0,%x1"
-   [(set_attr "type" "vecperm")])
- 
--(define_insn "*vsx_float<VSi><mode>2"
-+(define_insn "vsx_float<VSi><mode>2"
-   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
- 	(float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
-   "VECTOR_UNIT_VSX_P (<MODE>mode)"
-   "xvcvsx<VSc><VSs> %x0,%x1"
-   [(set_attr "type" "vecfloat")])
- 
--(define_insn "*vsx_floatuns<VSi><mode>2"
-+(define_insn "vsx_floatuns<VSi><mode>2"
-   [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
- 	(unsigned_float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
-   "VECTOR_UNIT_VSX_P (<MODE>mode)"
-@@ -446,6 +452,62 @@ (define_insn "*vsx_fixuns_trunc<mode><VS
-   [(set_attr "type" "vecfloat")])
- 
- 
-+;; VSX convert to/from double vector
-+
-+;; Convert from 64-bit to 32-bit types
-+;; Note, favor the Altivec registers since the usual use of these instructions
-+;; is in vector converts and we need to use the Altivec vperm instruction.
-+
-+(define_insn "vsx_xvcvdpsp"
-+  [(set (match_operand:V4SF 0 "vsx_register_operand" "=v,?wa")
-+	(unspec:V4SF [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
-+		     UNSPEC_VSX_XVCVDPSP))]
-+  "VECTOR_UNIT_VSX_P (V2DFmode)"
-+  "xvcvdpsp %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
-+
-+(define_insn "vsx_xvcvdpsxws"
-+  [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
-+	(unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
-+		     UNSPEC_VSX_XVCVDPSXWS))]
-+  "VECTOR_UNIT_VSX_P (V2DFmode)"
-+  "xvcvdpsxws %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
-+
-+(define_insn "vsx_xvcvdpuxws"
-+  [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
-+	(unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
-+		     UNSPEC_VSX_XVCVDPUXWS))]
-+  "VECTOR_UNIT_VSX_P (V2DFmode)"
-+  "xvcvdpuxws %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
-+
-+;; Convert from 32-bit to 64-bit types
-+(define_insn "vsx_xvcvspdp"
-+  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
-+	(unspec:V2DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")]
-+		     UNSPEC_VSX_XVCVSPDP))]
-+  "VECTOR_UNIT_VSX_P (V2DFmode)"
-+  "xvcvspdp %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
-+
-+(define_insn "vsx_xvcvsxwdp"
-+  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
-+	(unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
-+		     UNSPEC_VSX_XVCVSXWDP))]
-+  "VECTOR_UNIT_VSX_P (V2DFmode)"
-+  "xvcvsxwdp %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
-+
-+(define_insn "vsx_xvcvuxwdp"
-+  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
-+	(unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
-+		     UNSPEC_VSX_XVCVUXWDP))]
-+  "VECTOR_UNIT_VSX_P (V2DFmode)"
-+  "xvcvuxwdp %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
-+
-+
- ;; VSX scalar double precision floating point operations
- (define_insn"*vsx_adddf3"
-   [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-@@ -753,8 +815,8 @@ (define_insn "*vsx_andc<mode>3"
- (define_insn "vsx_concat_v2df"
-   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
- 	(unspec:V2DF
--	 [(match_operand:DF 1 "vsx_register_operand" "f,wa")
--	  (match_operand:DF 2 "vsx_register_operand" "f,wa")]
-+	 [(match_operand:DF 1 "vsx_register_operand" "ws,wa")
-+	  (match_operand:DF 2 "vsx_register_operand" "ws,wa")]
- 	 UNSPEC_VSX_CONCAT_V2DF))]
-   "VECTOR_UNIT_VSX_P (V2DFmode)"
-   "xxpermdi %x0,%x1,%x2,0"
-@@ -762,32 +824,37 @@ (define_insn "vsx_concat_v2df"
- 
- ;; Set a double into one element
- (define_insn "vsx_set_v2df"
--  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
-+  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
- 	(vec_merge:V2DF
--	 (match_operand:V2DF 1 "vsx_register_operand" "wd")
--	 (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws"))
--	 (match_operand:QI 3 "u5bit_cint_operand" "i")))]
-+	 (match_operand:V2DF 1 "vsx_register_operand" "wd,wa")
-+	 (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws,f"))
-+	 (match_operand:QI 3 "u5bit_cint_operand" "i,i")))]
-   "VECTOR_UNIT_VSX_P (V2DFmode)"
- {
--  operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
--  return \"xxpermdi %x0,%x1,%x2,%3\";
-+  if (INTVAL (operands[3]) == 0)
-+    return \"xxpermdi %x0,%x1,%x2,1\";
-+  else if (INTVAL (operands[3]) == 1)
-+    return \"xxpermdi %x0,%x2,%x1,0\";
-+  else
-+    gcc_unreachable ();
- }
-   [(set_attr "type" "vecperm")])
- 
- ;; Extract a DF element from V2DF
- (define_insn "vsx_extract_v2df"
--  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
--	(vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws,f,?wa")
-+	(vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd,wd,wa")
- 		       (parallel
--			[(match_operand:QI 2 "u5bit_cint_operand" "i")])))]
-+			[(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
-   "VECTOR_UNIT_VSX_P (V2DFmode)"
- {
--  operands[3] = GEN_INT (INTVAL (operands[2]) & 1);
-+  gcc_assert (UINTVAL (operands[2]) <= 1);
-+  operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
-   return \"xxpermdi %x0,%x1,%x1,%3\";
- }
-   [(set_attr "type" "vecperm")])
- 
--;; General V2DF permute
-+;; General V2DF permute, extract_{high,low,even,odd}
- (define_insn "vsx_xxpermdi"
-   [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
- 	(vec_concat:V2DF
-@@ -799,6 +866,7 @@ (define_insn "vsx_xxpermdi"
- 			 [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
-   "VECTOR_UNIT_VSX_P (V2DFmode)"
- {
-+  gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
-   operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
- 			 | (INTVAL (operands[4]) & 1));
-   return \"xxpermdi %x0,%x1,%x3,%5\";
-@@ -807,14 +875,15 @@ (define_insn "vsx_xxpermdi"
- 
- ;; V2DF splat
- (define_insn "vsx_splatv2df"
--  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd")
-+  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,wd")
- 	(vec_duplicate:V2DF
--	 (match_operand:DF 1 "input_operand" "ws,Z")))]
-+	 (match_operand:DF 1 "input_operand" "ws,f,Z")))]
-   "VECTOR_UNIT_VSX_P (V2DFmode)"
-   "@
-    xxpermdi %x0,%x1,%x1,0
-+   xxpermdi %x0,%x1,%x1,0
-    lxvdsx %x0,%y1"
--  [(set_attr "type" "vecperm,vecload")])
-+  [(set_attr "type" "vecperm,vecperm,vecload")])
- 
- ;; V4SF splat
- (define_insn "*vsx_xxspltw"
-@@ -828,14 +897,14 @@ (define_insn "*vsx_xxspltw"
-   [(set_attr "type" "vecperm")])
- 
- ;; V4SF interleave
--(define_insn "*vsx_xxmrghw"
--  [(set (match_operand:V4SF 0 "register_operand" "=v")
--        (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
-+(define_insn "vsx_xxmrghw"
-+  [(set (match_operand:V4SF 0 "register_operand" "=wf")
-+        (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "wf")
-                                          (parallel [(const_int 0)
-                                                     (const_int 2)
-                                                     (const_int 1)
-                                                     (const_int 3)]))
--                        (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
-+                        (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "wf")
-                                          (parallel [(const_int 2)
-                                                     (const_int 0)
-                                                     (const_int 3)
-@@ -845,15 +914,15 @@ (define_insn "*vsx_xxmrghw"
-   "xxmrghw %x0,%x1,%x2"
-   [(set_attr "type" "vecperm")])
- 
--(define_insn "*vsx_xxmrglw"
--  [(set (match_operand:V4SF 0 "register_operand" "=v")
-+(define_insn "vsx_xxmrglw"
-+  [(set (match_operand:V4SF 0 "register_operand" "=wf")
-         (vec_merge:V4SF
--	 (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
-+	 (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "wf")
- 			  (parallel [(const_int 2)
- 				     (const_int 0)
- 				     (const_int 3)
- 				     (const_int 1)]))
--	 (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
-+	 (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "wf")
- 			  (parallel [(const_int 0)
- 				     (const_int 2)
- 				     (const_int 1)
-@@ -862,3 +931,26 @@ (define_insn "*vsx_xxmrglw"
-   "VECTOR_UNIT_VSX_P (V4SFmode)"
-   "xxmrglw %x0,%x1,%x2"
-   [(set_attr "type" "vecperm")])
-+
-+
-+;; Reload patterns for VSX loads/stores.  We need a scratch register to convert
-+;; the stack temporary address from reg+offset to reg+reg addressing.
-+(define_expand "vsx_reload_<VSX_L:mode>_<P:ptrsize>_to_mem"
-+  [(parallel [(match_operand:VSX_L 0 "memory_operand" "")
-+              (match_operand:VSX_L 1 "register_operand" "=wa")
-+              (match_operand:P 2 "register_operand" "=&b")])]
-+  "VECTOR_MEM_VSX_P (<MODE>mode)"
-+{
-+  rs6000_vector_secondary_reload (operands[0], operands[1], operands[2], true);
-+  DONE;
-+})
-+
-+(define_expand "vsx_reload_<VSX_L:mode>_<P:ptrsize>_to_reg"
-+  [(parallel [(match_operand:VSX_L 0 "register_operand" "=wa")
-+              (match_operand:VSX_L 1 "memory_operand" "")
-+              (match_operand:P 2 "register_operand" "=&b")])]
-+  "VECTOR_MEM_VSX_P (<MODE>mode)"
-+{
-+  rs6000_vector_secondary_reload (operands[0], operands[1], operands[2], false);
-+  DONE;
-+})
---- gcc/config/rs6000/rs6000.h	(revision 144758)
-+++ gcc/config/rs6000/rs6000.h	(revision 144843)
-@@ -3388,7 +3388,7 @@ enum rs6000_builtins
-   VSX_BUILTIN_XXSPLTW,
-   VSX_BUILTIN_XXSWAPD,
- 
--  /* Combine VSX/Altivec builtins.  */
-+  /* Combined VSX/Altivec builtins.  */
-   VECTOR_BUILTIN_FLOAT_V4SI_V4SF,
-   VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF,
-   VECTOR_BUILTIN_FIX_V4SF_V4SI,
---- gcc/config/rs6000/altivec.md	(revision 144758)
-+++ gcc/config/rs6000/altivec.md	(revision 144843)
-@@ -2685,3 +2685,27 @@ (define_expand "vec_unpacku_float_lo_v8h
-   emit_insn (gen_altivec_vcfux (operands[0], tmp, const0_rtx));
-   DONE;
- }")
-+
-+
-+;; Reload patterns for Altivec loads/stores.  We need a scratch register to
-+;; convert the stack temporary address from reg+offset to reg+reg addressing.
-+
-+(define_expand "altivec_reload_<V:mode>_<P:ptrsize>_to_mem"
-+  [(parallel [(match_operand:V 0 "memory_operand" "")
-+              (match_operand:V 1 "register_operand" "=v")
-+              (match_operand:P 2 "register_operand" "=&b")])]
-+  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
-+{
-+  rs6000_vector_secondary_reload (operands[0], operands[1], operands[2], true);
-+  DONE;
-+})
-+
-+(define_expand "altivec_reload_<V:mode>_<P:ptrsize>_to_reg"
-+  [(parallel [(match_operand:V 0 "register_operand" "=v")
-+              (match_operand:V 1 "memory_operand" "")
-+              (match_operand:P 2 "register_operand" "=&b")])]
-+  "VECTOR_MEM_ALTIVEC_P (<MODE>mode)"
-+{
-+  rs6000_vector_secondary_reload (operands[0], operands[1], operands[2], false);
-+  DONE;
-+})
---- gcc/config/rs6000/rs6000.md	(revision 144758)
-+++ gcc/config/rs6000/rs6000.md	(revision 144843)
-@@ -222,6 +222,10 @@ (define_mode_attr dbits [(QI "56") (HI "
- ;; ISEL/ISEL64 target selection
- (define_mode_attr sel [(SI "") (DI "64")])
- 
-+;; Suffix for reload patterns
-+(define_mode_attr ptrsize [(SI "32bit")
-+			   (DI "64bit")])
-+
- 
- ;; Start with fixed-point load and store insns.  Here we put only the more
- ;; complex forms.  Basic data transfer is done later.
---- gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c	(revision 144843)
-@@ -0,0 +1,29 @@
-+/* { dg-do compile { target { powerpc*-*-* } } } */
-+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
-+/* { dg-require-effective-target powerpc_vsx_ok } */
-+/* { dg-options "-O2 -mcpu=power7" } */
-+/* { dg-final { scan-assembler "xvaddsp" } } */
-+/* { dg-final { scan-assembler "xvsubsp" } } */
-+/* { dg-final { scan-assembler "xvmulsp" } } */
-+/* { dg-final { scan-assembler "xvdivsp" } } */
-+/* { dg-final { scan-assembler "xvmaxsp" } } */
-+/* { dg-final { scan-assembler "xvminsp" } } */
-+/* { dg-final { scan-assembler "xvsqrtsp" } } */
-+/* { dg-final { scan-assembler "xvabssp" } } */
-+/* { dg-final { scan-assembler "xvnabssp" } } */
-+
-+void use_builtins (__vector float *p, __vector float *q, __vector float *r)
-+{
-+  __vector float tmp1 = *q;
-+  __vector float tmp2 = *r;
-+
-+  *p++ = __builtin_vsx_xvaddsp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvsubsp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvmulsp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvdivsp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvmaxsp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvminsp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvabssp (tmp1);
-+  *p++ = __builtin_vsx_xvnabssp (tmp1);
-+  *p   = __builtin_vsx_xvsqrtsp (tmp1);
-+}
---- gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c	(revision 144843)
-@@ -0,0 +1,29 @@
-+/* { dg-do compile { target { powerpc*-*-* } } } */
-+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
-+/* { dg-require-effective-target powerpc_vsx_ok } */
-+/* { dg-options "-O2 -mcpu=power7" } */
-+/* { dg-final { scan-assembler "xvadddp" } } */
-+/* { dg-final { scan-assembler "xvsubdp" } } */
-+/* { dg-final { scan-assembler "xvmuldp" } } */
-+/* { dg-final { scan-assembler "xvdivdp" } } */
-+/* { dg-final { scan-assembler "xvmaxdp" } } */
-+/* { dg-final { scan-assembler "xvmindp" } } */
-+/* { dg-final { scan-assembler "xvsqrtdp" } } */
-+/* { dg-final { scan-assembler "xvabsdp" } } */
-+/* { dg-final { scan-assembler "xvnabsdp" } } */
-+
-+void use_builtins (__vector double *p, __vector double *q, __vector double *r)
-+{
-+  __vector double tmp1 = *q;
-+  __vector double tmp2 = *r;
-+
-+  *p++ = __builtin_vsx_xvadddp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvsubdp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvmuldp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvdivdp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvmaxdp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvmindp (tmp1, tmp2);
-+  *p++ = __builtin_vsx_xvabsdp (tmp1);
-+  *p++ = __builtin_vsx_xvnabsdp (tmp1);
-+  *p   = __builtin_vsx_xvsqrtdp (tmp1);
-+}
---- gcc/testsuite/gcc.target/powerpc/pr39457.c	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/pr39457.c	(revision 144857)
-@@ -0,0 +1,56 @@
-+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
-+/* { dg-options "-m64 -O2 -mminimal-toc" } */
-+
-+/* PR 39457 -- fix breakage because the compiler ran out of registers and
-+   wanted to stash a floating point value to the LR/CTR register.  */
 +
-+/* -O2 -m64 -mminimal-toc */
-+typedef struct { void *s; } S;
-+typedef void (*T1) (void);
-+typedef void (*T2) (void *, void *, int, void *);
-+char *fn1 (const char *, ...);
-+void *fn2 (void);
-+int fn3 (char *, int);
-+int fn4 (const void *);
-+int fn5 (const void *);
-+long fn6 (void) __attribute__ ((__const__));
-+int fn7 (void *, void *, void *);
-+void *fn8 (void *, long);
-+void *fn9 (void *, long, const char *, ...);
-+void *fn10 (void *);
-+long fn11 (void) __attribute__ ((__const__));
-+long fn12 (void *, const char *, T1, T2, void *);
-+void *fn13 (void *);
-+long fn14 (void) __attribute__ ((__const__));
-+extern void *v1;
-+extern char *v2;
-+extern int v3;
++      and_rtx = gen_rtx_SET (VOIDmode,
++			     scratch,
++			     gen_rtx_AND (Pmode,
++					  addr,
++					  and_op2));
 +
-+void
-+foo (void *x, char *z)
-+{
-+  void *i1, *i2;
-+  int y;
-+  if (v1)
-+    return;
-+  v1 = fn9 (fn10 (fn2 ()), fn6 (), "x", 0., "y", 0., 0);
-+  y = 520 - (520 - fn4 (x)) / 2;
-+  fn9 (fn8 (v1, fn6 ()), fn6 (), "wig", fn8 (v1, fn14 ()), "x", 18.0,
-+       "y", 16.0, "wid", 80.0, "hi", 500.0, 0);
-+  fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 80.0, "y2",
-+       500.0, "f", fn3 ("fff", 0x0D0DFA00), 0);
-+  fn13 (((S *) fn8 (v1, fn6 ()))->s);
-+  fn12 (fn8 (v1, fn11 ()), "ev", (T1) fn7, 0, fn8 (v1, fn6 ()));
-+  fn9 (fn8 (v1, fn6 ()), fn6 (), "wig",
-+       fn8 (v1, fn14 ()), "x", 111.0, "y", 14.0, "wid", 774.0, "hi",
-+       500.0, 0);
-+  v1 = fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 774.0, "y2",
-+            500.0, "f", fn3 ("gc", 0x0D0DFA00), 0);
-+  fn1 (z, 0);
-+  i1 = fn9 (fn8 (v1, fn6 ()), fn6 (), "pixbuf", x, "x",
-+            800 - fn5 (x) / 2, "y", y - fn4 (x), 0);
-+  fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, "/ok/");
-+  fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, 0);
-+  i2 = fn9 (fn8 (v1, fn6 ()), fn6 (), "txt", "OK", "fnt", v2, "x",
-+            800, "y", y - fn4 (x) + 15, "ar", 0, "f", v3, 0);
-+}
++      cc_clobber = gen_rtx_CLOBBER (CCmode, gen_rtx_SCRATCH (CCmode));
+       emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ 				   gen_rtvec (2, and_rtx, cc_clobber)));
+       addr = scratch;
diff --git a/gcc44-power7-3.patch b/gcc44-power7-3.patch
new file mode 100644
index 0000000..3dd8afe
--- /dev/null
+++ b/gcc44-power7-3.patch
@@ -0,0 +1,3523 @@
+2009-04-26  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	* config/rs6000/vector.md (vector_vsel<mode>): 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<mode>): Add support for all vector types, including
+	Altivec types.
+	(vsx_ftrunc<mode>2): Emit the correct instruction.
+	(vsx_x<VSv>r<VSs>i): New builtin rounding mode insns.
+	(vsx_x<VSv>r<VSs>ic): Ditto.
+	(vsx_concat_<mode>): Key off of VSX memory instructions being
+	generated instead of the vector arithmetic unit to enable V2DI
+	mode.
+	(vsx_extract_<mode>): Ditto.
+	(vsx_set_<mode>): Rewrite as an unspec.
+	(vsx_xxpermdi2_<mode>): Rename old vsx_xxpermdi_<mode> here.  Key
+	off of VSX memory instructions instead of arithmetic unit.
+	(vsx_xxpermdi_<mode>): New insn for __builtin_vsx_xxpermdi.
+	(vsx_splat_<mode>): Rename from vsx_splat<mode>.
+	(vsx_xxspltw_<mode>): 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_<mode>): Ditto.
+	(vsx_xxmrglw_<mode>): Ditto.
+	(vsx_xxsldwi_<mode>): 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<mode>): 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  <meissner at linux.vnet.ibm.com>
+
+	* config/rs6000/vector.md (VEC_E): New iterator to add V2DImode.
+	(vec_init<mode>): Use VEC_E instead of VEC_C iterator, to add
+	V2DImode support.
+	(vec_set<mode>): Ditto.
+	(vec_extract<mode>): 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<mode>): Drop TImode support here.
+	(vsx_movti): New TImode support, allow GPRs, but favor VSX
+	registers.
+	(vsx_<VS_spdp_insn>): New support for float<->double conversions.
+	(vsx_xvcvdpsp): Delete, move into vsx_<VS_spdp_insn>.
+	(vsx_xvcvspdp): Ditto.
+	(vsx_xvcvuxdsp): New conversion insn.
+	(vsx_xvcvspsxds): Ditto.
+	(vsx_xvcvspuxds): Ditto.
+	(vsx_concat_<mode>): Generalize V2DF permute/splat operations to
+	include V2DI.
+	(vsx_set_<mode>): Ditto.
+	(vsx_extract_<mode>): Ditto.
+	(vsx_xxpermdi_<mode>): Ditto.
+	(vsx_splat<mode>): 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<mode>): Drop movti mode here.
+	(altivec_movti): Add movti insn, and allow GPRs, but favor altivec
+	registers.
+
+2009-04-16  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	* config/rs6000/rs6000-protos.h (rs6000_has_indirect_jump_p): New
+	declaration.
+	(rs6000_set_indirect_jump): Ditto.
+
+	* config/rs6000/rs6000.c (struct machine_function): Add
+	indirect_jump_p field.
+	(rs6000_override_options): Wrap warning messages in N_().  If
+	-mvsx was implicitly set, don't give a warning for -msoft-float,
+	just silently turn off vsx.
+	(rs6000_secondary_reload_inner): Don't use strict register
+	checking, since pseudos may still be present.
+	(register_move_cost): If -mdebug=cost, print out cost information.
+	(rs6000_memory_move_cost): Ditto.
+	(rs6000_has_indirect_jump_p): New function, return true if
+	current function has an indirect jump.
+	(rs6000_set_indirect_jump): New function, note that an indirect
+	jump has been generated.
+
+	* config/rs6000/rs6000.md (indirect_jump): Note that we've
+	generated an indirect jump.
+	(tablejump): Ditto.
+	(doloop_end): Do not generate decrement ctr and branch
+	instructions if an indirect jump has been generated.
+
+--- gcc/doc/extend.texi	(revision 146119)
++++ gcc/doc/extend.texi	(revision 146798)
+@@ -7094,7 +7094,7 @@ instructions, but allow the compiler to 
+ * MIPS Loongson Built-in Functions::
+ * Other MIPS Built-in Functions::
+ * picoChip Built-in Functions::
+-* PowerPC AltiVec Built-in Functions::
++* PowerPC AltiVec/VSX Built-in Functions::
+ * SPARC VIS Built-in Functions::
+ * SPU Built-in Functions::
+ @end menu
+@@ -9571,7 +9571,7 @@ GCC defines the preprocessor macro @code
+ when this function is available.
+ @end table
+ 
+- at node PowerPC AltiVec Built-in Functions
++ at 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.
++
++ at smallexample
++vector unsigned long
++vector signed long
++vector double
++ at end smallexample
++
++The long types are only implemented for 64-bit code generation, and
++the long type is only used in the floating point/integer conversion
++instructions.
++
+ GCC's implementation of the high-level language interface available from
+ C and C++ code differs from Motorola's documentation in several ways.
+ 
+--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c	(revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-3.c	(revision 146798)
+@@ -0,0 +1,212 @@
++/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_vsx_ok } */
++/* { dg-options "-O2 -mcpu=power7" } */
++/* { dg-final { scan-assembler "xxsel" } } */
++/* { dg-final { scan-assembler "vperm" } } */
++/* { dg-final { scan-assembler "xvrdpi" } } */
++/* { dg-final { scan-assembler "xvrdpic" } } */
++/* { dg-final { scan-assembler "xvrdpim" } } */
++/* { dg-final { scan-assembler "xvrdpip" } } */
++/* { dg-final { scan-assembler "xvrdpiz" } } */
++/* { dg-final { scan-assembler "xvrspi" } } */
++/* { dg-final { scan-assembler "xvrspic" } } */
++/* { dg-final { scan-assembler "xvrspim" } } */
++/* { dg-final { scan-assembler "xvrspip" } } */
++/* { dg-final { scan-assembler "xvrspiz" } } */
++/* { dg-final { scan-assembler "xsrdpi" } } */
++/* { dg-final { scan-assembler "xsrdpic" } } */
++/* { dg-final { scan-assembler "xsrdpim" } } */
++/* { dg-final { scan-assembler "xsrdpip" } } */
++/* { dg-final { scan-assembler "xsrdpiz" } } */
++/* { dg-final { scan-assembler "xsmaxdp" } } */
++/* { dg-final { scan-assembler "xsmindp" } } */
++/* { dg-final { scan-assembler "xxland" } } */
++/* { dg-final { scan-assembler "xxlandc" } } */
++/* { dg-final { scan-assembler "xxlnor" } } */
++/* { dg-final { scan-assembler "xxlor" } } */
++/* { dg-final { scan-assembler "xxlxor" } } */
++/* { dg-final { scan-assembler "xvcmpeqdp" } } */
++/* { dg-final { scan-assembler "xvcmpgtdp" } } */
++/* { dg-final { scan-assembler "xvcmpgedp" } } */
++/* { dg-final { scan-assembler "xvcmpeqsp" } } */
++/* { dg-final { scan-assembler "xvcmpgtsp" } } */
++/* { dg-final { scan-assembler "xvcmpgesp" } } */
++/* { dg-final { scan-assembler "xxsldwi" } } */
++/* { dg-final { scan-assembler-not "call" } } */
++
++extern __vector int si[][4];
++extern __vector short ss[][4];
++extern __vector signed char sc[][4];
++extern __vector float f[][4];
++extern __vector unsigned int ui[][4];
++extern __vector unsigned short us[][4];
++extern __vector unsigned char uc[][4];
++extern __vector __bool int bi[][4];
++extern __vector __bool short bs[][4];
++extern __vector __bool char bc[][4];
++extern __vector __pixel p[][4];
++#ifdef __VSX__
++extern __vector double d[][4];
++extern __vector long sl[][4];
++extern __vector unsigned long ul[][4];
++extern __vector __bool long bl[][4];
++#endif
++
++int do_sel(void)
++{
++  int i = 0;
++
++  si[i][0] = __builtin_vsx_xxsel_4si (si[i][1], si[i][2], si[i][3]); i++;
++  ss[i][0] = __builtin_vsx_xxsel_8hi (ss[i][1], ss[i][2], ss[i][3]); i++;
++  sc[i][0] = __builtin_vsx_xxsel_16qi (sc[i][1], sc[i][2], sc[i][3]); i++;
++  f[i][0] = __builtin_vsx_xxsel_4sf (f[i][1], f[i][2], f[i][3]); i++;
++  d[i][0] = __builtin_vsx_xxsel_2df (d[i][1], d[i][2], d[i][3]); i++;
++
++  si[i][0] = __builtin_vsx_xxsel (si[i][1], si[i][2], bi[i][3]); i++;
++  ss[i][0] = __builtin_vsx_xxsel (ss[i][1], ss[i][2], bs[i][3]); i++;
++  sc[i][0] = __builtin_vsx_xxsel (sc[i][1], sc[i][2], bc[i][3]); i++;
++  f[i][0] = __builtin_vsx_xxsel (f[i][1], f[i][2], bi[i][3]); i++;
++  d[i][0] = __builtin_vsx_xxsel (d[i][1], d[i][2], bl[i][3]); i++;
++
++  si[i][0] = __builtin_vsx_xxsel (si[i][1], si[i][2], ui[i][3]); i++;
++  ss[i][0] = __builtin_vsx_xxsel (ss[i][1], ss[i][2], us[i][3]); i++;
++  sc[i][0] = __builtin_vsx_xxsel (sc[i][1], sc[i][2], uc[i][3]); i++;
++  f[i][0] = __builtin_vsx_xxsel (f[i][1], f[i][2], ui[i][3]); i++;
++  d[i][0] = __builtin_vsx_xxsel (d[i][1], d[i][2], ul[i][3]); i++;
++
++  return i;
++}
++
++int do_perm(void)
++{
++  int i = 0;
++
++  si[i][0] = __builtin_vsx_vperm_4si (si[i][1], si[i][2], sc[i][3]); i++;
++  ss[i][0] = __builtin_vsx_vperm_8hi (ss[i][1], ss[i][2], sc[i][3]); i++;
++  sc[i][0] = __builtin_vsx_vperm_16qi (sc[i][1], sc[i][2], sc[i][3]); i++;
++  f[i][0] = __builtin_vsx_vperm_4sf (f[i][1], f[i][2], sc[i][3]); i++;
++  d[i][0] = __builtin_vsx_vperm_2df (d[i][1], d[i][2], sc[i][3]); i++;
++
++  si[i][0] = __builtin_vsx_vperm (si[i][1], si[i][2], uc[i][3]); i++;
++  ss[i][0] = __builtin_vsx_vperm (ss[i][1], ss[i][2], uc[i][3]); i++;
++  sc[i][0] = __builtin_vsx_vperm (sc[i][1], sc[i][2], uc[i][3]); i++;
++  f[i][0] = __builtin_vsx_vperm (f[i][1], f[i][2], uc[i][3]); i++;
++  d[i][0] = __builtin_vsx_vperm (d[i][1], d[i][2], uc[i][3]); i++;
++
++  return i;
++}
++
++int do_xxperm (void)
++{
++  int i = 0;
++
++  d[i][0] = __builtin_vsx_xxpermdi_2df (d[i][1], d[i][2], 0); i++;
++  d[i][0] = __builtin_vsx_xxpermdi (d[i][1], d[i][2], 1); i++;
++  return i;
++}
++
++double x, y;
++void do_concat (void)
++{
++  d[0][0] = __builtin_vsx_concat_2df (x, y);
++}
++
++void do_set (void)
++{
++  d[0][0] = __builtin_vsx_set_2df (d[0][1], x, 0);
++  d[1][0] = __builtin_vsx_set_2df (d[1][1], y, 1);
++}
++
++extern double z[][4];
++
++int do_math (void)
++{
++  int i = 0;
++
++  d[i][0] = __builtin_vsx_xvrdpi  (d[i][1]); i++;
++  d[i][0] = __builtin_vsx_xvrdpic (d[i][1]); i++;
++  d[i][0] = __builtin_vsx_xvrdpim (d[i][1]); i++;
++  d[i][0] = __builtin_vsx_xvrdpip (d[i][1]); i++;
++  d[i][0] = __builtin_vsx_xvrdpiz (d[i][1]); i++;
++
++  f[i][0] = __builtin_vsx_xvrspi  (f[i][1]); i++;
++  f[i][0] = __builtin_vsx_xvrspic (f[i][1]); i++;
++  f[i][0] = __builtin_vsx_xvrspim (f[i][1]); i++;
++  f[i][0] = __builtin_vsx_xvrspip (f[i][1]); i++;
++  f[i][0] = __builtin_vsx_xvrspiz (f[i][1]); i++;
++
++  z[i][0] = __builtin_vsx_xsrdpi  (z[i][1]); i++;
++  z[i][0] = __builtin_vsx_xsrdpic (z[i][1]); i++;
++  z[i][0] = __builtin_vsx_xsrdpim (z[i][1]); i++;
++  z[i][0] = __builtin_vsx_xsrdpip (z[i][1]); i++;
++  z[i][0] = __builtin_vsx_xsrdpiz (z[i][1]); i++;
++  z[i][0] = __builtin_vsx_xsmaxdp (z[i][1], z[i][0]); i++;
++  z[i][0] = __builtin_vsx_xsmindp (z[i][1], z[i][0]); i++;
++  return i;
++}
++
++int do_cmp (void)
++{
++  int i = 0;
++
++  d[i][0] = __builtin_vsx_xvcmpeqdp (d[i][1], d[i][2]); i++;
++  d[i][0] = __builtin_vsx_xvcmpgtdp (d[i][1], d[i][2]); i++;
++  d[i][0] = __builtin_vsx_xvcmpgedp (d[i][1], d[i][2]); i++;
++
++  f[i][0] = __builtin_vsx_xvcmpeqsp (f[i][1], f[i][2]); i++;
++  f[i][0] = __builtin_vsx_xvcmpgtsp (f[i][1], f[i][2]); i++;
++  f[i][0] = __builtin_vsx_xvcmpgesp (f[i][1], f[i][2]); i++;
++  return i;
++}
++
++int do_logical (void)
++{
++  int i = 0;
++
++  si[i][0] = __builtin_vsx_xxland (si[i][1], si[i][2]); i++;
++  si[i][0] = __builtin_vsx_xxlandc (si[i][1], si[i][2]); i++;
++  si[i][0] = __builtin_vsx_xxlnor (si[i][1], si[i][2]); i++;
++  si[i][0] = __builtin_vsx_xxlor (si[i][1], si[i][2]); i++;
++  si[i][0] = __builtin_vsx_xxlxor (si[i][1], si[i][2]); i++;
++
++  ss[i][0] = __builtin_vsx_xxland (ss[i][1], ss[i][2]); i++;
++  ss[i][0] = __builtin_vsx_xxlandc (ss[i][1], ss[i][2]); i++;
++  ss[i][0] = __builtin_vsx_xxlnor (ss[i][1], ss[i][2]); i++;
++  ss[i][0] = __builtin_vsx_xxlor (ss[i][1], ss[i][2]); i++;
++  ss[i][0] = __builtin_vsx_xxlxor (ss[i][1], ss[i][2]); i++;
++
++  sc[i][0] = __builtin_vsx_xxland (sc[i][1], sc[i][2]); i++;
++  sc[i][0] = __builtin_vsx_xxlandc (sc[i][1], sc[i][2]); i++;
++  sc[i][0] = __builtin_vsx_xxlnor (sc[i][1], sc[i][2]); i++;
++  sc[i][0] = __builtin_vsx_xxlor (sc[i][1], sc[i][2]); i++;
++  sc[i][0] = __builtin_vsx_xxlxor (sc[i][1], sc[i][2]); i++;
++
++  d[i][0] = __builtin_vsx_xxland (d[i][1], d[i][2]); i++;
++  d[i][0] = __builtin_vsx_xxlandc (d[i][1], d[i][2]); i++;
++  d[i][0] = __builtin_vsx_xxlnor (d[i][1], d[i][2]); i++;
++  d[i][0] = __builtin_vsx_xxlor (d[i][1], d[i][2]); i++;
++  d[i][0] = __builtin_vsx_xxlxor (d[i][1], d[i][2]); i++;
++
++  f[i][0] = __builtin_vsx_xxland (f[i][1], f[i][2]); i++;
++  f[i][0] = __builtin_vsx_xxlandc (f[i][1], f[i][2]); i++;
++  f[i][0] = __builtin_vsx_xxlnor (f[i][1], f[i][2]); i++;
++  f[i][0] = __builtin_vsx_xxlor (f[i][1], f[i][2]); i++;
++  f[i][0] = __builtin_vsx_xxlxor (f[i][1], f[i][2]); i++;
++  return i;
++}
++
++int do_xxsldwi (void)
++{
++  int i = 0;
++
++  si[i][0] = __builtin_vsx_xxsldwi (si[i][1], si[i][2], 0); i++;
++  ss[i][0] = __builtin_vsx_xxsldwi (ss[i][1], ss[i][2], 1); i++;
++  sc[i][0] = __builtin_vsx_xxsldwi (sc[i][1], sc[i][2], 2); i++;
++  ui[i][0] = __builtin_vsx_xxsldwi (ui[i][1], ui[i][2], 3); i++;
++  us[i][0] = __builtin_vsx_xxsldwi (us[i][1], us[i][2], 0); i++;
++  uc[i][0] = __builtin_vsx_xxsldwi (uc[i][1], uc[i][2], 1); i++;
++  f[i][0] = __builtin_vsx_xxsldwi (f[i][1], f[i][2], 2); i++;
++  d[i][0] = __builtin_vsx_xxsldwi (d[i][1], d[i][2], 3); i++;
++  return i;
++}
+--- gcc/config/rs6000/vector.md	(revision 146119)
++++ gcc/config/rs6000/vector.md	(revision 146798)
+@@ -39,6 +39,9 @@ (define_mode_iterator VEC_M [V16QI V8HI 
+ ;; Vector comparison modes
+ (define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
+ 
++;; Vector init/extract modes
++(define_mode_iterator VEC_E [V16QI V8HI V4SI V2DI V4SF V2DF])
++
+ ;; Vector reload iterator
+ (define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF DF TI])
+ 
+@@ -347,34 +350,13 @@ (define_expand "vector_geu<mode>"
+ ;; Note the arguments for __builtin_altivec_vsel are op2, op1, mask
+ ;; which is in the reverse order that we want
+ (define_expand "vector_vsel<mode>"
+-  [(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>mode)"
+-  "
+-{
+-  if (VECTOR_UNIT_VSX_P (<MODE>mode))
+-    emit_insn (gen_vsx_vsel<mode> (operands[0], operands[3],
+-				   operands[2], operands[1]));
+-  else
+-    emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
+-				       operands[2], operands[1]));
+-  DONE;
+-}")
+-
+-(define_expand "vector_vsel<mode>"
+-  [(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>mode)"
+-  "
+-{
+-  emit_insn (gen_altivec_vsel<mode> (operands[0], operands[3],
+-				     operands[2], operands[1]));
+-  DONE;
+-}")
++  "")
+ 
+ 
+ ;; Vector logical instructions
+@@ -475,19 +457,23 @@ (define_expand "fixuns_trunc<mode><VEC_i
+ 
+ ;; Vector initialization, set, extract
+ (define_expand "vec_init<mode>"
+-  [(match_operand:VEC_C 0 "vlogical_operand" "")
+-   (match_operand:VEC_C 1 "vec_init_operand" "")]
+-  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++  [(match_operand:VEC_E 0 "vlogical_operand" "")
++   (match_operand:VEC_E 1 "vec_init_operand" "")]
++  "(<MODE>mode == V2DImode
++    ? VECTOR_MEM_VSX_P (V2DImode)
++    : VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode))"
+ {
+   rs6000_expand_vector_init (operands[0], operands[1]);
+   DONE;
+ })
+ 
+ (define_expand "vec_set<mode>"
+-  [(match_operand:VEC_C 0 "vlogical_operand" "")
++  [(match_operand:VEC_E 0 "vlogical_operand" "")
+    (match_operand:<VEC_base> 1 "register_operand" "")
+    (match_operand 2 "const_int_operand" "")]
+-  "VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode)"
++  "(<MODE>mode == V2DImode
++    ? VECTOR_MEM_VSX_P (V2DImode)
++    : VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode))"
+ {
+   rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+   DONE;
+@@ -495,9 +481,11 @@ (define_expand "vec_set<mode>"
+ 
+ (define_expand "vec_extract<mode>"
+   [(match_operand:<VEC_base> 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)"
++  "(<MODE>mode == V2DImode
++    ? VECTOR_MEM_VSX_P (V2DImode)
++    : VECTOR_UNIT_ALTIVEC_OR_VSX_P (<MODE>mode))"
+ {
+   rs6000_expand_vector_extract (operands[0], operands[1],
+ 				INTVAL (operands[2]));
+--- gcc/config/rs6000/predicates.md	(revision 146119)
++++ gcc/config/rs6000/predicates.md	(revision 146798)
+@@ -327,6 +327,9 @@ (define_predicate "easy_vector_constant"
+   if (TARGET_PAIRED_FLOAT)
+     return false;
+ 
++  if ((VSX_VECTOR_MODE (mode) || mode == TImode) && zero_constant (op, mode))
++    return true;
++
+   if (ALTIVEC_VECTOR_MODE (mode))
+     {
+       if (zero_constant (op, mode))
+--- gcc/config/rs6000/rs6000-protos.h	(revision 146119)
++++ gcc/config/rs6000/rs6000-protos.h	(revision 146798)
+@@ -176,6 +176,8 @@ extern int rs6000_register_move_cost (en
+ 				      enum reg_class, enum reg_class);
+ extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int);
+ extern bool rs6000_tls_referenced_p (rtx);
++extern bool rs6000_has_indirect_jump_p (void);
++extern void rs6000_set_indirect_jump (void);
+ extern void rs6000_conditional_register_usage (void);
+ 
+ /* Declare functions in rs6000-c.c */
+--- gcc/config/rs6000/rs6000-c.c	(revision 146119)
++++ gcc/config/rs6000/rs6000-c.c	(revision 146798)
+@@ -336,7 +336,20 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+   if (TARGET_NO_LWSYNC)
+     builtin_define ("__NO_LWSYNC__");
+   if (TARGET_VSX)
+-    builtin_define ("__VSX__");
++    {
++      builtin_define ("__VSX__");
++
++      /* For the VSX builtin functions identical to Altivec functions, just map
++	 the altivec builtin into the vsx version (the altivec functions
++	 generate VSX code if -mvsx).  */
++      builtin_define ("__builtin_vsx_xxland=__builtin_vec_and");
++      builtin_define ("__builtin_vsx_xxlandc=__builtin_vec_andc");
++      builtin_define ("__builtin_vsx_xxlnor=__builtin_vec_nor");
++      builtin_define ("__builtin_vsx_xxlor=__builtin_vec_or");
++      builtin_define ("__builtin_vsx_xxlxor=__builtin_vec_xor");
++      builtin_define ("__builtin_vsx_xxsel=__builtin_vec_sel");
++      builtin_define ("__builtin_vsx_vperm=__builtin_vec_perm");
++    }
+ 
+   /* May be overridden by target configuration.  */
+   RS6000_CPU_CPP_ENDIAN_BUILTINS();
+@@ -400,7 +413,7 @@ struct altivec_builtin_types
+ };
+ 
+ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
+-  /* Unary AltiVec builtins.  */
++  /* Unary AltiVec/VSX builtins.  */
+   { ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V16QI,
+     RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
+   { ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V8HI,
+@@ -496,7 +509,7 @@ const struct altivec_builtin_types altiv
+   { ALTIVEC_BUILTIN_VEC_VUPKLSB, ALTIVEC_BUILTIN_VUPKLSB,
+     RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V16QI, 0, 0 },
+ 
+-  /* Binary AltiVec builtins.  */
++  /* Binary AltiVec/VSX builtins.  */
+   { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+     RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+   { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+@@ -2206,7 +2219,7 @@ const struct altivec_builtin_types altiv
+   { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+     RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ 
+-  /* Ternary AltiVec builtins.  */
++  /* Ternary AltiVec/VSX builtins.  */
+   { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+     RS6000_BTI_void, ~RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+   { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+@@ -2407,6 +2420,10 @@ const struct altivec_builtin_types altiv
+     RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI },
+   { ALTIVEC_BUILTIN_VEC_NMSUB, ALTIVEC_BUILTIN_VNMSUBFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
++  { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DF,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_unsigned_V16QI },
++  { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DI,
++    RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_unsigned_V16QI },
+   { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SF,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V16QI },
+   { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SI,
+@@ -2433,11 +2450,29 @@ const struct altivec_builtin_types altiv
+     RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI },
+   { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_16QI,
+     RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_unsigned_V2DI },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DI },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DF,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI,
++    RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI,
++    RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_unsigned_V2DI },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI,
++    RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI },
+   { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI },
+   { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI },
+   { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
++    RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
++    RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SI },
++  { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
+     RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI },
+   { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
+     RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI },
+@@ -2805,6 +2840,37 @@ const struct altivec_builtin_types altiv
+     RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
+   { ALTIVEC_BUILTIN_VEC_STVRXL, ALTIVEC_BUILTIN_STVRXL,
+     RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI,
++    RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_16QI,
++    RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI,
++    RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_8HI,
++    RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_8HI,
++    RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI,
++    RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SI,
++    RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SI,
++    RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI,
++    RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DI,
++    RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DI,
++    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
++    RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_4SF,
++    RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXSLDWI, VSX_BUILTIN_XXSLDWI_2DF,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DF,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DI,
++    RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_NOT_OPAQUE },
++  { VSX_BUILTIN_VEC_XXPERMDI, VSX_BUILTIN_XXPERMDI_2DI,
++    RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
++    RS6000_BTI_NOT_OPAQUE },
+ 
+   /* Predicates.  */
+   { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
+@@ -3108,6 +3174,10 @@ altivec_resolve_overloaded_builtin (tree
+ 	goto bad;
+       switch (TYPE_MODE (type))
+ 	{
++	  case DImode:
++	    type = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node);
++	    size = 2;
++	    break;
+ 	  case SImode:
+ 	    type = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
+ 	    size = 4;
+@@ -3121,6 +3191,7 @@ altivec_resolve_overloaded_builtin (tree
+ 	    size = 16;
+ 	    break;
+ 	  case SFmode: type = V4SF_type_node; size = 4; break;
++	  case DFmode: type = V2DF_type_node; size = 2; break;
+ 	  default:
+ 	    goto bad;
+ 	}
+--- gcc/config/rs6000/rs6000.opt	(revision 146119)
++++ gcc/config/rs6000/rs6000.opt	(revision 146798)
+@@ -119,18 +119,6 @@ mvsx
+ Target Report Mask(VSX)
+ Use vector/scalar (VSX) instructions
+ 
+-mvsx-vector-memory
+-Target Undocumented Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1)
+-; If -mvsx, use VSX vector load/store instructions instead of Altivec instructions
+-
+-mvsx-vector-float
+-Target Undocumented Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1)
+-; If -mvsx, use VSX arithmetic instructions for float vectors (on by default)
+-
+-mvsx-vector-double
+-Target Undocumented Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1)
+-; If -mvsx, use VSX arithmetic instructions for double vectors (on by default)
+-
+ mvsx-scalar-double
+ Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
+ ; If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
+@@ -139,18 +127,14 @@ mvsx-scalar-memory
+ Target Undocumented Report Var(TARGET_VSX_SCALAR_MEMORY)
+ ; If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
+ 
+-mvsx-v4sf-altivec-regs
+-Target Undocumented Report Var(TARGET_V4SF_ALTIVEC_REGS) Init(-1)
+-; If -mvsx, prefer V4SF types to use Altivec regs and not the floating registers
+-
+-mreload-functions
+-Target Undocumented Report Var(TARGET_RELOAD_FUNCTIONS) Init(-1)
+-; If -mvsx or -maltivec, enable reload functions
+-
+ mpower7-adjust-cost
+ Target Undocumented Var(TARGET_POWER7_ADJUST_COST)
+ ; Add extra cost for setting CR registers before a branch like is done for Power5
+ 
++mallow-timode
++Target Undocumented Var(TARGET_ALLOW_TIMODE)
++; Allow VSX/Altivec to target loading TImode variables.
++
+ mdisallow-float-in-lr-ctr
+ Target Undocumented Var(TARGET_DISALLOW_FLOAT_IN_LR_CTR) Init(-1)
+ ; Disallow floating point in LR or CTR, causes some reload bugs
+--- gcc/config/rs6000/rs6000.c	(revision 146119)
++++ gcc/config/rs6000/rs6000.c	(revision 146798)
+@@ -130,6 +130,8 @@ typedef struct machine_function GTY(())
+      64-bits wide and is allocated early enough so that the offset
+      does not overflow the 16-bit load/store offset field.  */
+   rtx sdmode_stack_slot;
++  /* Whether an indirect jump or table jump was generated.  */
++  bool indirect_jump_p;
+ } machine_function;
+ 
+ /* Target cpu type */
+@@ -917,6 +919,11 @@ static rtx rs6000_expand_binop_builtin (
+ static rtx rs6000_expand_ternop_builtin (enum insn_code, tree, rtx);
+ static rtx rs6000_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+ static void altivec_init_builtins (void);
++static unsigned builtin_hash_function (const void *);
++static int builtin_hash_eq (const void *, const void *);
++static tree builtin_function_type (enum machine_mode, enum machine_mode,
++				   enum machine_mode, enum machine_mode,
++				   const char *name);
+ static void rs6000_common_init_builtins (void);
+ static void rs6000_init_libfuncs (void);
+ 
+@@ -1018,6 +1025,8 @@ static enum reg_class rs6000_secondary_r
+ 					       enum machine_mode,
+ 					       struct secondary_reload_info *);
+ 
++static const enum reg_class *rs6000_ira_cover_classes (void);
++
+ const int INSN_NOT_AVAILABLE = -1;
+ static enum machine_mode rs6000_eh_return_filter_mode (void);
+ 
+@@ -1033,6 +1042,16 @@ struct toc_hash_struct GTY(())
+ };
+ 
+ static GTY ((param_is (struct toc_hash_struct))) htab_t toc_hash_table;
++
++/* Hash table to keep track of the argument types for builtin functions.  */
++
++struct builtin_hash_struct GTY(())
++{
++  tree type;
++  enum machine_mode mode[4];	/* return value + 3 arguments */
++};
++
++static GTY ((param_is (struct builtin_hash_struct))) htab_t builtin_hash_table;
+ 
+ /* Default register names.  */
+ char rs6000_reg_names[][8] =
+@@ -1350,6 +1369,9 @@ static const char alt_reg_names[][8] =
+ #undef TARGET_SECONDARY_RELOAD
+ #define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
+ 
++#undef TARGET_IRA_COVER_CLASSES
++#define TARGET_IRA_COVER_CLASSES rs6000_ira_cover_classes
++
+ struct gcc_target targetm = TARGET_INITIALIZER;
+ 
+ /* Return number of consecutive hard regs needed starting at reg REGNO
+@@ -1370,7 +1392,7 @@ rs6000_hard_regno_nregs_internal (int re
+   unsigned HOST_WIDE_INT reg_size;
+ 
+   if (FP_REGNO_P (regno))
+-    reg_size = (VECTOR_UNIT_VSX_P (mode)
++    reg_size = (VECTOR_MEM_VSX_P (mode)
+ 		? UNITS_PER_VSX_WORD
+ 		: UNITS_PER_FP_WORD);
+ 
+@@ -1452,7 +1474,7 @@ rs6000_hard_regno_mode_ok (int regno, en
+ 
+   /* AltiVec only in AldyVec registers.  */
+   if (ALTIVEC_REGNO_P (regno))
+-    return VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode);
++    return VECTOR_MEM_ALTIVEC_OR_VSX_P (mode);
+ 
+   /* ...but GPRs can hold SIMD data on the SPE in one register.  */
+   if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
+@@ -1613,10 +1635,8 @@ rs6000_init_hard_regno_mode_ok (void)
+       rs6000_vector_reload[m][1] = CODE_FOR_nothing;
+     }
+ 
+-  /* TODO, add TI/V2DI mode for moving data if Altivec or VSX.  */
+-
+   /* V2DF mode, VSX only.  */
+-  if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_DOUBLE)
++  if (float_p && TARGET_VSX)
+     {
+       rs6000_vector_unit[V2DFmode] = VECTOR_VSX;
+       rs6000_vector_mem[V2DFmode] = VECTOR_VSX;
+@@ -1624,17 +1644,11 @@ rs6000_init_hard_regno_mode_ok (void)
+     }
+ 
+   /* V4SF mode, either VSX or Altivec.  */
+-  if (float_p && TARGET_VSX && TARGET_VSX_VECTOR_FLOAT)
++  if (float_p && TARGET_VSX)
+     {
+       rs6000_vector_unit[V4SFmode] = VECTOR_VSX;
+-      if (TARGET_VSX_VECTOR_MEMORY || !TARGET_ALTIVEC)
+-	{
+-	  rs6000_vector_align[V4SFmode] = 32;
+-	  rs6000_vector_mem[V4SFmode] = VECTOR_VSX;
+-	} else {
+-	  rs6000_vector_align[V4SFmode] = 128;
+-	  rs6000_vector_mem[V4SFmode] = VECTOR_ALTIVEC;
+-      }
++      rs6000_vector_align[V4SFmode] = 32;
++      rs6000_vector_mem[V4SFmode] = VECTOR_VSX;
+     }
+   else if (float_p && TARGET_ALTIVEC)
+     {
+@@ -1655,7 +1669,7 @@ rs6000_init_hard_regno_mode_ok (void)
+       rs6000_vector_reg_class[V8HImode] = ALTIVEC_REGS;
+       rs6000_vector_reg_class[V4SImode] = ALTIVEC_REGS;
+ 
+-      if (TARGET_VSX && TARGET_VSX_VECTOR_MEMORY)
++      if (TARGET_VSX)
+ 	{
+ 	  rs6000_vector_mem[V4SImode] = VECTOR_VSX;
+ 	  rs6000_vector_mem[V8HImode] = VECTOR_VSX;
+@@ -1675,6 +1689,23 @@ rs6000_init_hard_regno_mode_ok (void)
+ 	}
+     }
+ 
++  /* V2DImode, prefer vsx over altivec, since the main use will be for
++     vectorized floating point conversions.  */
++  if (float_p && TARGET_VSX)
++    {
++      rs6000_vector_mem[V2DImode] = VECTOR_VSX;
++      rs6000_vector_unit[V2DImode] = VECTOR_NONE;
++      rs6000_vector_reg_class[V2DImode] = vsx_rc;
++      rs6000_vector_align[V2DImode] = 64;
++    }
++  else if (TARGET_ALTIVEC)
++    {
++      rs6000_vector_mem[V2DImode] = VECTOR_ALTIVEC;
++      rs6000_vector_unit[V2DImode] = VECTOR_NONE;
++      rs6000_vector_reg_class[V2DImode] = ALTIVEC_REGS;
++      rs6000_vector_align[V2DImode] = 128;
++    }
++
+   /* DFmode, see if we want to use the VSX unit.  */
+   if (float_p && TARGET_VSX && TARGET_VSX_SCALAR_DOUBLE)
+     {
+@@ -1684,16 +1715,30 @@ rs6000_init_hard_regno_mode_ok (void)
+ 	= (TARGET_VSX_SCALAR_MEMORY ? VECTOR_VSX : VECTOR_NONE);
+     }
+ 
+-  /* TODO, add SPE and paired floating point vector support.  */
++  /* TImode.  Until this is debugged, only add it under switch control.  */
++  if (TARGET_ALLOW_TIMODE)
++    {
++      if (float_p && TARGET_VSX)
++	{
++	  rs6000_vector_mem[TImode] = VECTOR_VSX;
++	  rs6000_vector_unit[TImode] = VECTOR_NONE;
++	  rs6000_vector_reg_class[TImode] = vsx_rc;
++	  rs6000_vector_align[TImode] = 64;
++	}
++      else if (TARGET_ALTIVEC)
++	{
++	  rs6000_vector_mem[TImode] = VECTOR_ALTIVEC;
++	  rs6000_vector_unit[TImode] = VECTOR_NONE;
++	  rs6000_vector_reg_class[TImode] = ALTIVEC_REGS;
++	  rs6000_vector_align[TImode] = 128;
++	}
++    }
++
++  /* TODO add SPE and paired floating point vector support.  */
+ 
+   /* Set the VSX register classes.  */
+-
+-  /* For V4SF, prefer the Altivec registers, because there are a few operations
+-     that want to use Altivec operations instead of VSX.  */
+   rs6000_vector_reg_class[V4SFmode]
+-    = ((VECTOR_UNIT_VSX_P (V4SFmode)
+-	&& VECTOR_MEM_VSX_P (V4SFmode)
+-	&& !TARGET_V4SF_ALTIVEC_REGS)
++    = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode))
+        ? vsx_rc
+        : (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
+ 	  ? ALTIVEC_REGS
+@@ -1712,7 +1757,7 @@ rs6000_init_hard_regno_mode_ok (void)
+   rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS;
+ 
+   /* Set up the reload helper functions.  */
+-  if (TARGET_RELOAD_FUNCTIONS && (TARGET_VSX || TARGET_ALTIVEC))
++  if (TARGET_VSX || TARGET_ALTIVEC)
+     {
+       if (TARGET_64BIT)
+ 	{
+@@ -1728,6 +1773,11 @@ rs6000_init_hard_regno_mode_ok (void)
+ 	  rs6000_vector_reload[V4SFmode][1]  = CODE_FOR_reload_v4sf_di_load;
+ 	  rs6000_vector_reload[V2DFmode][0]  = CODE_FOR_reload_v2df_di_store;
+ 	  rs6000_vector_reload[V2DFmode][1]  = CODE_FOR_reload_v2df_di_load;
++	  if (TARGET_ALLOW_TIMODE)
++	    {
++	      rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_di_store;
++	      rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_di_load;
++	    }
+ 	}
+       else
+ 	{
+@@ -1743,6 +1793,11 @@ rs6000_init_hard_regno_mode_ok (void)
+ 	  rs6000_vector_reload[V4SFmode][1]  = CODE_FOR_reload_v4sf_si_load;
+ 	  rs6000_vector_reload[V2DFmode][0]  = CODE_FOR_reload_v2df_si_store;
+ 	  rs6000_vector_reload[V2DFmode][1]  = CODE_FOR_reload_v2df_si_load;
++	  if (TARGET_ALLOW_TIMODE)
++	    {
++	      rs6000_vector_reload[TImode][0] = CODE_FOR_reload_ti_si_store;
++	      rs6000_vector_reload[TImode][1] = CODE_FOR_reload_ti_si_load;
++	    }
+ 	}
+     }
+ 
+@@ -2132,23 +2187,29 @@ rs6000_override_options (const char *def
+       const char *msg = NULL;
+       if (!TARGET_HARD_FLOAT || !TARGET_FPRS
+ 	  || !TARGET_SINGLE_FLOAT || !TARGET_DOUBLE_FLOAT)
+-	msg = "-mvsx requires hardware floating point";
++	{
++	  if (target_flags_explicit & MASK_VSX)
++	    msg = N_("-mvsx requires hardware floating point");
++	  else
++	    target_flags &= ~ MASK_VSX;
++	}
+       else if (TARGET_PAIRED_FLOAT)
+-	msg = "-mvsx and -mpaired are incompatible";
++	msg = N_("-mvsx and -mpaired are incompatible");
+       /* The hardware will allow VSX and little endian, but until we make sure
+ 	 things like vector select, etc. work don't allow VSX on little endian
+ 	 systems at this point.  */
+       else if (!BYTES_BIG_ENDIAN)
+-	msg = "-mvsx used with little endian code";
++	msg = N_("-mvsx used with little endian code");
+       else if (TARGET_AVOID_XFORM > 0)
+-	msg = "-mvsx needs indexed addressing";
++	msg = N_("-mvsx needs indexed addressing");
+ 
+       if (msg)
+ 	{
+ 	  warning (0, msg);
+-	  target_flags &= MASK_VSX;
++	  target_flags &= ~ MASK_VSX;
+ 	}
+-      else if (!TARGET_ALTIVEC && (target_flags_explicit & MASK_ALTIVEC) == 0)
++      else if (TARGET_VSX && !TARGET_ALTIVEC
++	       && (target_flags_explicit & MASK_ALTIVEC) == 0)
+ 	target_flags |= MASK_ALTIVEC;
+     }
+ 
+@@ -2581,8 +2642,8 @@ rs6000_builtin_conversion (enum tree_cod
+ 	    return NULL_TREE;
+ 
+ 	  return TYPE_UNSIGNED (type)
+-	    ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDSP]
+-	    : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDSP];
++	    ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDDP]
++	    : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDDP];
+ 
+ 	case V4SImode:
+ 	  if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
+@@ -3780,15 +3841,28 @@ rs6000_expand_vector_init (rtx target, r
+ 	}
+     }
+ 
+-  if (mode == V2DFmode)
++  if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode))
+     {
+-      gcc_assert (TARGET_VSX);
++      rtx (*splat) (rtx, rtx);
++      rtx (*concat) (rtx, rtx, rtx);
++
++      if (mode == V2DFmode)
++	{
++	  splat = gen_vsx_splat_v2df;
++	  concat = gen_vsx_concat_v2df;
++	}
++      else
++	{
++	  splat = gen_vsx_splat_v2di;
++	  concat = gen_vsx_concat_v2di;
++	}
++
+       if (all_same)
+-	emit_insn (gen_vsx_splatv2df (target, XVECEXP (vals, 0, 0)));
++	emit_insn (splat (target, XVECEXP (vals, 0, 0)));
+       else
+-	emit_insn (gen_vsx_concat_v2df (target,
+-					copy_to_reg (XVECEXP (vals, 0, 0)),
+-					copy_to_reg (XVECEXP (vals, 0, 1))));
++	emit_insn (concat (target,
++			   copy_to_reg (XVECEXP (vals, 0, 0)),
++			   copy_to_reg (XVECEXP (vals, 0, 1))));
+       return;
+     }
+ 
+@@ -3851,10 +3925,12 @@ rs6000_expand_vector_set (rtx target, rt
+   int width = GET_MODE_SIZE (inner_mode);
+   int i;
+ 
+-  if (mode == V2DFmode)
++  if (mode == V2DFmode || mode == V2DImode)
+     {
++      rtx (*set_func) (rtx, rtx, rtx, rtx)
++	= ((mode == V2DFmode) ? gen_vsx_set_v2df : gen_vsx_set_v2di);
+       gcc_assert (TARGET_VSX);
+-      emit_insn (gen_vsx_set_v2df (target, val, target, GEN_INT (elt)));
++      emit_insn (set_func (target, val, target, GEN_INT (elt)));
+       return;
+     }
+ 
+@@ -3895,10 +3971,12 @@ rs6000_expand_vector_extract (rtx target
+   enum machine_mode inner_mode = GET_MODE_INNER (mode);
+   rtx mem, x;
+ 
+-  if (mode == V2DFmode)
++  if (mode == V2DFmode || mode == V2DImode)
+     {
++      rtx (*extract_func) (rtx, rtx, rtx)
++	= ((mode == V2DFmode) ? gen_vsx_extract_v2df : gen_vsx_extract_v2di);
+       gcc_assert (TARGET_VSX);
+-      emit_insn (gen_vsx_extract_v2df (target, vec, GEN_INT (elt)));
++      emit_insn (extract_func (target, vec, GEN_INT (elt)));
+       return;
+     }
+ 
+@@ -4318,9 +4396,7 @@ avoiding_indexed_address_p (enum machine
+ {
+   /* Avoid indexed addressing for modes that have non-indexed
+      load/store instruction forms.  */
+-  return (TARGET_AVOID_XFORM
+-	  && (!TARGET_ALTIVEC || !ALTIVEC_VECTOR_MODE (mode))
+-	  && (!TARGET_VSX || !VSX_VECTOR_MODE (mode)));
++  return (TARGET_AVOID_XFORM && VECTOR_MEM_NONE_P (mode));
+ }
+ 
+ inline bool
+@@ -4443,6 +4519,16 @@ rs6000_legitimize_address (rtx x, rtx ol
+       ret = rs6000_legitimize_tls_address (x, model);
+     }
+ 
++  else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
++    {
++      /* Make sure both operands are registers.  */
++      if (GET_CODE (x) == PLUS)
++	ret = gen_rtx_PLUS (Pmode,
++			    force_reg (Pmode, XEXP (x, 0)),
++			    force_reg (Pmode, XEXP (x, 1)));
++      else
++	ret = force_reg (Pmode, x);
++    }
+   else if (GET_CODE (x) == PLUS
+ 	   && GET_CODE (XEXP (x, 0)) == REG
+ 	   && GET_CODE (XEXP (x, 1)) == CONST_INT
+@@ -4452,8 +4538,6 @@ rs6000_legitimize_address (rtx x, rtx ol
+ 		 && (mode == DImode || mode == TImode)
+ 		 && (INTVAL (XEXP (x, 1)) & 3) != 0)
+ 		|| (TARGET_SPE && SPE_VECTOR_MODE (mode))
+-		|| (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
+-		|| (TARGET_VSX && VSX_VECTOR_MODE (mode))
+ 		|| (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+ 					   || mode == DImode || mode == DDmode
+ 					   || mode == TDmode))))
+@@ -4485,15 +4569,6 @@ rs6000_legitimize_address (rtx x, rtx ol
+       ret = gen_rtx_PLUS (Pmode, XEXP (x, 0),
+ 			  force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
+     }
+-  else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
+-    {
+-      /* Make sure both operands are registers.  */
+-      if (GET_CODE (x) == PLUS)
+-	ret = gen_rtx_PLUS (Pmode, force_reg (Pmode, XEXP (x, 0)),
+-			    force_reg (Pmode, XEXP (x, 1)));
+-      else
+-	ret = force_reg (Pmode, x);
+-    }
+   else if ((TARGET_SPE && SPE_VECTOR_MODE (mode))
+ 	   || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+ 				      || mode == DDmode || mode == TDmode
+@@ -5131,7 +5206,7 @@ rs6000_legitimate_address (enum machine_
+     ret = 1;
+   else if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
+     ret = 1;
+-  else if (mode != TImode
++  else if ((mode != TImode || !VECTOR_MEM_NONE_P (TImode))
+ 	   && mode != TFmode
+ 	   && mode != TDmode
+ 	   && ((TARGET_HARD_FLOAT && TARGET_FPRS)
+@@ -5971,7 +6046,13 @@ rs6000_emit_move (rtx dest, rtx source, 
+ 
+     case TImode:
+       if (VECTOR_MEM_ALTIVEC_OR_VSX_P (TImode))
+-	break;
++	{
++	  if (CONSTANT_P (operands[1])
++	      && !easy_vector_constant (operands[1], mode))
++	    operands[1] = force_const_mem (mode, operands[1]);
++
++	  break;
++	}
+ 
+       rs6000_eliminate_indexed_memrefs (operands);
+ 
+@@ -7888,7 +7969,8 @@ def_builtin (int mask, const char *name,
+   if ((mask & target_flags) || TARGET_PAIRED_FLOAT)
+     {
+       if (rs6000_builtin_decls[code])
+-	abort ();
++	fatal_error ("internal error: builtin function to %s already processed.",
++		     name);
+ 
+       rs6000_builtin_decls[code] =
+         add_builtin_function (name, type, code, BUILT_IN_MD,
+@@ -7953,6 +8035,34 @@ static const struct builtin_description 
+   { MASK_VSX, CODE_FOR_vsx_fnmaddv4sf4, "__builtin_vsx_xvnmaddsp", VSX_BUILTIN_XVNMADDSP },
+   { MASK_VSX, CODE_FOR_vsx_fnmsubv4sf4, "__builtin_vsx_xvnmsubsp", VSX_BUILTIN_XVNMSUBSP },
+ 
++  { MASK_VSX, CODE_FOR_vector_vselv2di, "__builtin_vsx_xxsel_2di", VSX_BUILTIN_XXSEL_2DI },
++  { MASK_VSX, CODE_FOR_vector_vselv2df, "__builtin_vsx_xxsel_2df", VSX_BUILTIN_XXSEL_2DF },
++  { MASK_VSX, CODE_FOR_vector_vselv4sf, "__builtin_vsx_xxsel_4sf", VSX_BUILTIN_XXSEL_4SF },
++  { MASK_VSX, CODE_FOR_vector_vselv4si, "__builtin_vsx_xxsel_4si", VSX_BUILTIN_XXSEL_4SI },
++  { MASK_VSX, CODE_FOR_vector_vselv8hi, "__builtin_vsx_xxsel_8hi", VSX_BUILTIN_XXSEL_8HI },
++  { MASK_VSX, CODE_FOR_vector_vselv16qi, "__builtin_vsx_xxsel_16qi", VSX_BUILTIN_XXSEL_16QI },
++
++  { MASK_VSX, CODE_FOR_altivec_vperm_v2di, "__builtin_vsx_vperm_2di", VSX_BUILTIN_VPERM_2DI },
++  { MASK_VSX, CODE_FOR_altivec_vperm_v2df, "__builtin_vsx_vperm_2df", VSX_BUILTIN_VPERM_2DF },
++  { MASK_VSX, CODE_FOR_altivec_vperm_v4sf, "__builtin_vsx_vperm_4sf", VSX_BUILTIN_VPERM_4SF },
++  { MASK_VSX, CODE_FOR_altivec_vperm_v4si, "__builtin_vsx_vperm_4si", VSX_BUILTIN_VPERM_4SI },
++  { MASK_VSX, CODE_FOR_altivec_vperm_v8hi, "__builtin_vsx_vperm_8hi", VSX_BUILTIN_VPERM_8HI },
++  { MASK_VSX, CODE_FOR_altivec_vperm_v16qi, "__builtin_vsx_vperm_16qi", VSX_BUILTIN_VPERM_16QI },
++
++  { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2df, "__builtin_vsx_xxpermdi_2df", VSX_BUILTIN_XXPERMDI_2DF },
++  { MASK_VSX, CODE_FOR_vsx_xxpermdi_v2di, "__builtin_vsx_xxpermdi_2di", VSX_BUILTIN_XXPERMDI_2DI },
++  { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxpermdi", VSX_BUILTIN_VEC_XXPERMDI },
++  { MASK_VSX, CODE_FOR_vsx_set_v2df, "__builtin_vsx_set_2df", VSX_BUILTIN_SET_2DF },
++  { MASK_VSX, CODE_FOR_vsx_set_v2di, "__builtin_vsx_set_2di", VSX_BUILTIN_SET_2DI },
++
++  { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2di, "__builtin_vsx_xxsldwi_2di", VSX_BUILTIN_XXSLDWI_2DI },
++  { MASK_VSX, CODE_FOR_vsx_xxsldwi_v2df, "__builtin_vsx_xxsldwi_2df", VSX_BUILTIN_XXSLDWI_2DF },
++  { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4sf, "__builtin_vsx_xxsldwi_4sf", VSX_BUILTIN_XXSLDWI_4SF },
++  { MASK_VSX, CODE_FOR_vsx_xxsldwi_v4si, "__builtin_vsx_xxsldwi_4si", VSX_BUILTIN_XXSLDWI_4SI },
++  { MASK_VSX, CODE_FOR_vsx_xxsldwi_v8hi, "__builtin_vsx_xxsldwi_8hi", VSX_BUILTIN_XXSLDWI_8HI },
++  { MASK_VSX, CODE_FOR_vsx_xxsldwi_v16qi, "__builtin_vsx_xxsldwi_16qi", VSX_BUILTIN_XXSLDWI_16QI },
++  { MASK_VSX, CODE_FOR_nothing, "__builtin_vsx_xxsldwi", VSX_BUILTIN_VEC_XXSLDWI },
++
+   { 0, CODE_FOR_paired_msub, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB },
+   { 0, CODE_FOR_paired_madd, "__builtin_paired_madd", PAIRED_BUILTIN_MADD },
+   { 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 },
+@@ -8102,6 +8212,9 @@ static struct builtin_description bdesc_
+   { MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP },
+   { MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP },
+   { MASK_VSX, CODE_FOR_vsx_tdivv2df3, "__builtin_vsx_xvtdivdp", VSX_BUILTIN_XVTDIVDP },
++  { MASK_VSX, CODE_FOR_vector_eqv2df, "__builtin_vsx_xvcmpeqdp", VSX_BUILTIN_XVCMPEQDP },
++  { MASK_VSX, CODE_FOR_vector_gtv2df, "__builtin_vsx_xvcmpgtdp", VSX_BUILTIN_XVCMPGTDP },
++  { MASK_VSX, CODE_FOR_vector_gev2df, "__builtin_vsx_xvcmpgedp", VSX_BUILTIN_XVCMPGEDP },
+ 
+   { MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP },
+   { MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP },
+@@ -8110,6 +8223,21 @@ static struct builtin_description bdesc_
+   { MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP },
+   { MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP },
+   { MASK_VSX, CODE_FOR_vsx_tdivv4sf3, "__builtin_vsx_xvtdivsp", VSX_BUILTIN_XVTDIVSP },
++  { MASK_VSX, CODE_FOR_vector_eqv4sf, "__builtin_vsx_xvcmpeqsp", VSX_BUILTIN_XVCMPEQSP },
++  { MASK_VSX, CODE_FOR_vector_gtv4sf, "__builtin_vsx_xvcmpgtsp", VSX_BUILTIN_XVCMPGTSP },
++  { MASK_VSX, CODE_FOR_vector_gev4sf, "__builtin_vsx_xvcmpgesp", VSX_BUILTIN_XVCMPGESP },
++
++  { MASK_VSX, CODE_FOR_smindf3, "__builtin_vsx_xsmindp", VSX_BUILTIN_XSMINDP },
++  { MASK_VSX, CODE_FOR_smaxdf3, "__builtin_vsx_xsmaxdp", VSX_BUILTIN_XSMAXDP },
++
++  { MASK_VSX, CODE_FOR_vsx_concat_v2df, "__builtin_vsx_concat_2df", VSX_BUILTIN_CONCAT_2DF },
++  { MASK_VSX, CODE_FOR_vsx_concat_v2di, "__builtin_vsx_concat_2di", VSX_BUILTIN_CONCAT_2DI },
++  { MASK_VSX, CODE_FOR_vsx_splat_v2df, "__builtin_vsx_splat_2df", VSX_BUILTIN_SPLAT_2DF },
++  { MASK_VSX, CODE_FOR_vsx_splat_v2di, "__builtin_vsx_splat_2di", VSX_BUILTIN_SPLAT_2DI },
++  { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4sf, "__builtin_vsx_xxmrghw", VSX_BUILTIN_XXMRGHW_4SF },
++  { MASK_VSX, CODE_FOR_vsx_xxmrghw_v4si, "__builtin_vsx_xxmrghw_4si", VSX_BUILTIN_XXMRGHW_4SI },
++  { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4sf, "__builtin_vsx_xxmrglw", VSX_BUILTIN_XXMRGLW_4SF },
++  { MASK_VSX, CODE_FOR_vsx_xxmrglw_v4si, "__builtin_vsx_xxmrglw_4si", VSX_BUILTIN_XXMRGLW_4SI },
+ 
+   { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
+   { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
+@@ -8527,6 +8655,47 @@ static struct builtin_description bdesc_
+   { MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2, "__builtin_vsx_xvtsqrtsp", VSX_BUILTIN_XVTSQRTSP },
+   { MASK_VSX, CODE_FOR_vsx_frev4sf2, "__builtin_vsx_xvresp", VSX_BUILTIN_XVRESP },
+ 
++  { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvdpsp", VSX_BUILTIN_XSCVDPSP },
++  { MASK_VSX, CODE_FOR_vsx_xscvdpsp, "__builtin_vsx_xscvspdp", VSX_BUILTIN_XSCVSPDP },
++  { MASK_VSX, CODE_FOR_vsx_xvcvdpsp, "__builtin_vsx_xvcvdpsp", VSX_BUILTIN_XVCVDPSP },
++  { MASK_VSX, CODE_FOR_vsx_xvcvspdp, "__builtin_vsx_xvcvspdp", VSX_BUILTIN_XVCVSPDP },
++
++  { MASK_VSX, CODE_FOR_vsx_fix_truncv2dfv2di2, "__builtin_vsx_xvcvdpsxds", VSX_BUILTIN_XVCVDPSXDS },
++  { MASK_VSX, CODE_FOR_vsx_fixuns_truncv2dfv2di2, "__builtin_vsx_xvcvdpuxds", VSX_BUILTIN_XVCVDPUXDS },
++  { MASK_VSX, CODE_FOR_vsx_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP },
++  { MASK_VSX, CODE_FOR_vsx_floatunsv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP },
++
++  { MASK_VSX, CODE_FOR_vsx_fix_truncv4sfv4si2, "__builtin_vsx_xvcvspsxws", VSX_BUILTIN_XVCVSPSXWS },
++  { MASK_VSX, CODE_FOR_vsx_fixuns_truncv4sfv4si2, "__builtin_vsx_xvcvspuxws", VSX_BUILTIN_XVCVSPUXWS },
++  { MASK_VSX, CODE_FOR_vsx_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXWSP },
++  { MASK_VSX, CODE_FOR_vsx_floatunsv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP },
++
++  { MASK_VSX, CODE_FOR_vsx_xvcvdpsxws, "__builtin_vsx_xvcvdpsxws", VSX_BUILTIN_XVCVDPSXWS },
++  { MASK_VSX, CODE_FOR_vsx_xvcvdpuxws, "__builtin_vsx_xvcvdpuxws", VSX_BUILTIN_XVCVDPUXWS },
++  { MASK_VSX, CODE_FOR_vsx_xvcvsxwdp, "__builtin_vsx_xvcvsxwdp", VSX_BUILTIN_XVCVSXWDP },
++  { MASK_VSX, CODE_FOR_vsx_xvcvuxwdp, "__builtin_vsx_xvcvuxwdp", VSX_BUILTIN_XVCVUXWDP },
++  { MASK_VSX, CODE_FOR_vsx_xvrdpi, "__builtin_vsx_xvrdpi", VSX_BUILTIN_XVRDPI },
++  { MASK_VSX, CODE_FOR_vsx_xvrdpic, "__builtin_vsx_xvrdpic", VSX_BUILTIN_XVRDPIC },
++  { MASK_VSX, CODE_FOR_vsx_floorv2df2, "__builtin_vsx_xvrdpim", VSX_BUILTIN_XVRDPIM },
++  { MASK_VSX, CODE_FOR_vsx_ceilv2df2, "__builtin_vsx_xvrdpip", VSX_BUILTIN_XVRDPIP },
++  { MASK_VSX, CODE_FOR_vsx_btruncv2df2, "__builtin_vsx_xvrdpiz", VSX_BUILTIN_XVRDPIZ },
++
++  { MASK_VSX, CODE_FOR_vsx_xvcvspsxds, "__builtin_vsx_xvcvspsxds", VSX_BUILTIN_XVCVSPSXDS },
++  { MASK_VSX, CODE_FOR_vsx_xvcvspuxds, "__builtin_vsx_xvcvspuxds", VSX_BUILTIN_XVCVSPUXDS },
++  { MASK_VSX, CODE_FOR_vsx_xvcvsxdsp, "__builtin_vsx_xvcvsxdsp", VSX_BUILTIN_XVCVSXDSP },
++  { MASK_VSX, CODE_FOR_vsx_xvcvuxdsp, "__builtin_vsx_xvcvuxdsp", VSX_BUILTIN_XVCVUXDSP },
++  { MASK_VSX, CODE_FOR_vsx_xvrspi, "__builtin_vsx_xvrspi", VSX_BUILTIN_XVRSPI },
++  { MASK_VSX, CODE_FOR_vsx_xvrspic, "__builtin_vsx_xvrspic", VSX_BUILTIN_XVRSPIC },
++  { MASK_VSX, CODE_FOR_vsx_floorv4sf2, "__builtin_vsx_xvrspim", VSX_BUILTIN_XVRSPIM },
++  { MASK_VSX, CODE_FOR_vsx_ceilv4sf2, "__builtin_vsx_xvrspip", VSX_BUILTIN_XVRSPIP },
++  { MASK_VSX, CODE_FOR_vsx_btruncv4sf2, "__builtin_vsx_xvrspiz", VSX_BUILTIN_XVRSPIZ },
++
++  { MASK_VSX, CODE_FOR_vsx_xsrdpi, "__builtin_vsx_xsrdpi", VSX_BUILTIN_XSRDPI },
++  { MASK_VSX, CODE_FOR_vsx_xsrdpic, "__builtin_vsx_xsrdpic", VSX_BUILTIN_XSRDPIC },
++  { MASK_VSX, CODE_FOR_vsx_floordf2, "__builtin_vsx_xsrdpim", VSX_BUILTIN_XSRDPIM },
++  { MASK_VSX, CODE_FOR_vsx_ceildf2, "__builtin_vsx_xsrdpip", VSX_BUILTIN_XSRDPIP },
++  { MASK_VSX, CODE_FOR_vsx_btruncdf2, "__builtin_vsx_xsrdpiz", VSX_BUILTIN_XSRDPIZ },
++
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL },
+@@ -8552,15 +8721,6 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI },
+   { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
+ 
+-  { MASK_VSX, CODE_FOR_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP },
+-  { MASK_VSX, CODE_FOR_unsigned_floatv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP },
+-  { MASK_VSX, CODE_FOR_fix_truncv2dfv2di2, "__builtin_vsx_xvdpsxds", VSX_BUILTIN_XVCVDPSXDS },
+-  { MASK_VSX, CODE_FOR_fixuns_truncv2dfv2di2, "__builtin_vsx_xvdpuxds", VSX_BUILTIN_XVCVDPUXDS },
+-  { MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXDSP },
+-  { MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP },
+-  { MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vsx_xvspsxws", VSX_BUILTIN_XVCVSPSXWS },
+-  { MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vsx_xvspuxws", VSX_BUILTIN_XVCVSPUXWS },
+-
+   /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
+      end with SPE_BUILTIN_EVSUBFUSIAAW.  */
+   { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
+@@ -9065,11 +9225,12 @@ rs6000_expand_ternop_builtin (enum insn_
+       || arg2 == error_mark_node)
+     return const0_rtx;
+ 
+-  if (icode == CODE_FOR_altivec_vsldoi_v4sf
+-      || icode == CODE_FOR_altivec_vsldoi_v4si
+-      || icode == CODE_FOR_altivec_vsldoi_v8hi
+-      || icode == CODE_FOR_altivec_vsldoi_v16qi)
++  switch (icode)
+     {
++    case CODE_FOR_altivec_vsldoi_v4sf:
++    case CODE_FOR_altivec_vsldoi_v4si:
++    case CODE_FOR_altivec_vsldoi_v8hi:
++    case CODE_FOR_altivec_vsldoi_v16qi:
+       /* Only allow 4-bit unsigned literals.  */
+       STRIP_NOPS (arg2);
+       if (TREE_CODE (arg2) != INTEGER_CST
+@@ -9078,6 +9239,40 @@ rs6000_expand_ternop_builtin (enum insn_
+ 	  error ("argument 3 must be a 4-bit unsigned literal");
+ 	  return const0_rtx;
+ 	}
++      break;
++
++    case CODE_FOR_vsx_xxpermdi_v2df:
++    case CODE_FOR_vsx_xxpermdi_v2di:
++    case CODE_FOR_vsx_xxsldwi_v16qi:
++    case CODE_FOR_vsx_xxsldwi_v8hi:
++    case CODE_FOR_vsx_xxsldwi_v4si:
++    case CODE_FOR_vsx_xxsldwi_v4sf:
++    case CODE_FOR_vsx_xxsldwi_v2di:
++    case CODE_FOR_vsx_xxsldwi_v2df:
++      /* Only allow 2-bit unsigned literals.  */
++      STRIP_NOPS (arg2);
++      if (TREE_CODE (arg2) != INTEGER_CST
++	  || TREE_INT_CST_LOW (arg2) & ~0x3)
++	{
++	  error ("argument 3 must be a 2-bit unsigned literal");
++	  return const0_rtx;
++	}
++      break;
++
++    case CODE_FOR_vsx_set_v2df:
++    case CODE_FOR_vsx_set_v2di:
++      /* Only allow 1-bit unsigned literals.  */
++      STRIP_NOPS (arg2);
++      if (TREE_CODE (arg2) != INTEGER_CST
++	  || TREE_INT_CST_LOW (arg2) & ~0x1)
++	{
++	  error ("argument 3 must be a 1-bit unsigned literal");
++	  return const0_rtx;
++	}
++      break;
++
++    default:
++      break;
+     }
+ 
+   if (target == 0
+@@ -9385,8 +9580,10 @@ altivec_expand_builtin (tree exp, rtx ta
+   enum machine_mode tmode, mode0;
+   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ 
+-  if (fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+-      && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
++  if ((fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
++       && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
++      || (fcode >= VSX_BUILTIN_OVERLOADED_FIRST
++	  && fcode <= VSX_BUILTIN_OVERLOADED_LAST))
+     {
+       *expandedp = true;
+       error ("unresolved overload for Altivec builtin %qF", fndecl);
+@@ -10175,6 +10372,7 @@ rs6000_init_builtins (void)
+   unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16);
+   unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8);
+   unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4);
++  unsigned_V2DI_type_node = build_vector_type (unsigned_intDI_type_node, 2);
+ 
+   opaque_V2SF_type_node = build_opaque_vector_type (float_type_node, 2);
+   opaque_V2SI_type_node = build_opaque_vector_type (intSI_type_node, 2);
+@@ -10188,6 +10386,7 @@ rs6000_init_builtins (void)
+   bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node);
+   bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
+   bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node);
++  bool_long_type_node = build_distinct_type_copy (unsigned_intDI_type_node);
+   pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
+ 
+   long_integer_type_internal_node = long_integer_type_node;
+@@ -10220,6 +10419,7 @@ rs6000_init_builtins (void)
+   bool_V16QI_type_node = build_vector_type (bool_char_type_node, 16);
+   bool_V8HI_type_node = build_vector_type (bool_short_type_node, 8);
+   bool_V4SI_type_node = build_vector_type (bool_int_type_node, 4);
++  bool_V2DI_type_node = build_vector_type (bool_long_type_node, 2);
+   pixel_V8HI_type_node = build_vector_type (pixel_type_node, 8);
+ 
+   (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+@@ -10260,9 +10460,17 @@ rs6000_init_builtins (void)
+ 					    pixel_V8HI_type_node));
+ 
+   if (TARGET_VSX)
+-    (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
+-					      get_identifier ("__vector double"),
+-					      V2DF_type_node));
++    {
++      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
++						get_identifier ("__vector double"),
++						V2DF_type_node));
++      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
++						get_identifier ("__vector long"),
++						V2DI_type_node));
++      (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
++						get_identifier ("__vector __bool long"),
++						bool_V2DI_type_node));
++    }
+ 
+   if (TARGET_PAIRED_FLOAT)
+     paired_init_builtins ();
+@@ -10837,8 +11045,10 @@ altivec_init_builtins (void)
+     {
+       enum machine_mode mode1;
+       tree type;
+-      bool is_overloaded = dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+-			   && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
++      bool is_overloaded = ((dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
++			     && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
++			    || (dp->code >= VSX_BUILTIN_OVERLOADED_FIRST
++				&& dp->code <= VSX_BUILTIN_OVERLOADED_LAST));
+ 
+       if (is_overloaded)
+ 	mode1 = VOIDmode;
+@@ -11001,592 +11211,302 @@ altivec_init_builtins (void)
+ 	       ALTIVEC_BUILTIN_VEC_EXT_V4SF);
+ }
+ 
+-static void
+-rs6000_common_init_builtins (void)
++/* Hash function for builtin functions with up to 3 arguments and a return
++   type.  */
++static unsigned
++builtin_hash_function (const void *hash_entry)
+ {
+-  const struct builtin_description *d;
+-  size_t i;
++  unsigned ret = 0;
++  int i;
++  const struct builtin_hash_struct *bh =
++    (const struct builtin_hash_struct *) hash_entry;
+ 
+-  tree v2sf_ftype_v2sf_v2sf_v2sf
+-    = build_function_type_list (V2SF_type_node,
+-                                V2SF_type_node, V2SF_type_node,
+-                                V2SF_type_node, NULL_TREE);
+-
+-  tree v4sf_ftype_v4sf_v4sf_v16qi
+-    = build_function_type_list (V4SF_type_node,
+-				V4SF_type_node, V4SF_type_node,
+-				V16QI_type_node, NULL_TREE);
+-  tree v4si_ftype_v4si_v4si_v16qi
+-    = build_function_type_list (V4SI_type_node,
+-				V4SI_type_node, V4SI_type_node,
+-				V16QI_type_node, NULL_TREE);
+-  tree v8hi_ftype_v8hi_v8hi_v16qi
+-    = build_function_type_list (V8HI_type_node,
+-				V8HI_type_node, V8HI_type_node,
+-				V16QI_type_node, NULL_TREE);
+-  tree v16qi_ftype_v16qi_v16qi_v16qi
+-    = build_function_type_list (V16QI_type_node,
+-				V16QI_type_node, V16QI_type_node,
+-				V16QI_type_node, NULL_TREE);
+-  tree v4si_ftype_int
+-    = build_function_type_list (V4SI_type_node, integer_type_node, NULL_TREE);
+-  tree v8hi_ftype_int
+-    = build_function_type_list (V8HI_type_node, integer_type_node, NULL_TREE);
+-  tree v16qi_ftype_int
+-    = build_function_type_list (V16QI_type_node, integer_type_node, NULL_TREE);
+-  tree v8hi_ftype_v16qi
+-    = build_function_type_list (V8HI_type_node, V16QI_type_node, NULL_TREE);
+-  tree v4sf_ftype_v4sf
+-    = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
++  for (i = 0; i < 4; i++)
++    ret = (ret * (unsigned)MAX_MACHINE_MODE) + ((unsigned)bh->mode[i]);
+ 
+-  tree v2si_ftype_v2si_v2si
+-    = build_function_type_list (opaque_V2SI_type_node,
+-				opaque_V2SI_type_node,
+-				opaque_V2SI_type_node, NULL_TREE);
+-
+-  tree v2sf_ftype_v2sf_v2sf_spe
+-    = build_function_type_list (opaque_V2SF_type_node,
+-				opaque_V2SF_type_node,
+-				opaque_V2SF_type_node, NULL_TREE);
+-
+-  tree v2sf_ftype_v2sf_v2sf
+-    = build_function_type_list (V2SF_type_node,
+-                                V2SF_type_node,
+-                                V2SF_type_node, NULL_TREE);
+-
+-
+-  tree v2si_ftype_int_int
+-    = build_function_type_list (opaque_V2SI_type_node,
+-				integer_type_node, integer_type_node,
+-				NULL_TREE);
++  return ret;
++}
+ 
+-  tree opaque_ftype_opaque
+-    = build_function_type_list (opaque_V4SI_type_node,
+-				opaque_V4SI_type_node, NULL_TREE);
++/* Compare builtin hash entries H1 and H2 for equivalence.  */
++static int
++builtin_hash_eq (const void *h1, const void *h2)
++{
++  const struct builtin_hash_struct *p1 = (const struct builtin_hash_struct *) h1;
++  const struct builtin_hash_struct *p2 = (const struct builtin_hash_struct *) h2;
+ 
+-  tree v2si_ftype_v2si
+-    = build_function_type_list (opaque_V2SI_type_node,
+-				opaque_V2SI_type_node, NULL_TREE);
+-
+-  tree v2sf_ftype_v2sf_spe
+-    = build_function_type_list (opaque_V2SF_type_node,
+-				opaque_V2SF_type_node, NULL_TREE);
+-
+-  tree v2sf_ftype_v2sf
+-    = build_function_type_list (V2SF_type_node,
+-                                V2SF_type_node, NULL_TREE);
+-
+-  tree v2sf_ftype_v2si
+-    = build_function_type_list (opaque_V2SF_type_node,
+-				opaque_V2SI_type_node, NULL_TREE);
+-
+-  tree v2si_ftype_v2sf
+-    = build_function_type_list (opaque_V2SI_type_node,
+-				opaque_V2SF_type_node, NULL_TREE);
+-
+-  tree v2si_ftype_v2si_char
+-    = build_function_type_list (opaque_V2SI_type_node,
+-				opaque_V2SI_type_node,
+-				char_type_node, NULL_TREE);
+-
+-  tree v2si_ftype_int_char
+-    = build_function_type_list (opaque_V2SI_type_node,
+-				integer_type_node, char_type_node, NULL_TREE);
+-
+-  tree v2si_ftype_char
+-    = build_function_type_list (opaque_V2SI_type_node,
+-				char_type_node, NULL_TREE);
++  return ((p1->mode[0] == p2->mode[0])
++	  && (p1->mode[1] == p2->mode[1])
++	  && (p1->mode[2] == p2->mode[2])
++	  && (p1->mode[3] == p2->mode[3]));
++}
+ 
+-  tree int_ftype_int_int
+-    = build_function_type_list (integer_type_node,
+-				integer_type_node, integer_type_node,
+-				NULL_TREE);
++/* Map selected modes to types for builtins.  */
++static tree builtin_mode_to_type[MAX_MACHINE_MODE];
+ 
+-  tree opaque_ftype_opaque_opaque
+-    = build_function_type_list (opaque_V4SI_type_node,
+-                                opaque_V4SI_type_node, opaque_V4SI_type_node, NULL_TREE);
+-  tree v4si_ftype_v4si_v4si
+-    = build_function_type_list (V4SI_type_node,
+-				V4SI_type_node, V4SI_type_node, NULL_TREE);
+-  tree v4sf_ftype_v4si_int
+-    = build_function_type_list (V4SF_type_node,
+-				V4SI_type_node, integer_type_node, NULL_TREE);
+-  tree v4si_ftype_v4sf_int
+-    = build_function_type_list (V4SI_type_node,
+-				V4SF_type_node, integer_type_node, NULL_TREE);
+-  tree v4si_ftype_v4si_int
+-    = build_function_type_list (V4SI_type_node,
+-				V4SI_type_node, integer_type_node, NULL_TREE);
+-  tree v8hi_ftype_v8hi_int
+-    = build_function_type_list (V8HI_type_node,
+-				V8HI_type_node, integer_type_node, NULL_TREE);
+-  tree v16qi_ftype_v16qi_int
+-    = build_function_type_list (V16QI_type_node,
+-				V16QI_type_node, integer_type_node, NULL_TREE);
+-  tree v16qi_ftype_v16qi_v16qi_int
+-    = build_function_type_list (V16QI_type_node,
+-				V16QI_type_node, V16QI_type_node,
+-				integer_type_node, NULL_TREE);
+-  tree v8hi_ftype_v8hi_v8hi_int
+-    = build_function_type_list (V8HI_type_node,
+-				V8HI_type_node, V8HI_type_node,
+-				integer_type_node, NULL_TREE);
+-  tree v4si_ftype_v4si_v4si_int
+-    = build_function_type_list (V4SI_type_node,
+-				V4SI_type_node, V4SI_type_node,
+-				integer_type_node, NULL_TREE);
+-  tree v4sf_ftype_v4sf_v4sf_int
+-    = build_function_type_list (V4SF_type_node,
+-				V4SF_type_node, V4SF_type_node,
+-				integer_type_node, NULL_TREE);
+-  tree v4sf_ftype_v4sf_v4sf
+-    = build_function_type_list (V4SF_type_node,
+-				V4SF_type_node, V4SF_type_node, NULL_TREE);
+-  tree opaque_ftype_opaque_opaque_opaque
+-    = build_function_type_list (opaque_V4SI_type_node,
+-                                opaque_V4SI_type_node, opaque_V4SI_type_node,
+-                                opaque_V4SI_type_node, NULL_TREE);
+-  tree v4sf_ftype_v4sf_v4sf_v4si
+-    = build_function_type_list (V4SF_type_node,
+-				V4SF_type_node, V4SF_type_node,
+-				V4SI_type_node, NULL_TREE);
+-  tree v4sf_ftype_v4sf_v4sf_v4sf
+-    = build_function_type_list (V4SF_type_node,
+-				V4SF_type_node, V4SF_type_node,
+-				V4SF_type_node, NULL_TREE);
+-  tree v4si_ftype_v4si_v4si_v4si
+-    = build_function_type_list (V4SI_type_node,
+-				V4SI_type_node, V4SI_type_node,
+-				V4SI_type_node, NULL_TREE);
+-  tree v8hi_ftype_v8hi_v8hi
+-    = build_function_type_list (V8HI_type_node,
+-				V8HI_type_node, V8HI_type_node, NULL_TREE);
+-  tree v8hi_ftype_v8hi_v8hi_v8hi
+-    = build_function_type_list (V8HI_type_node,
+-				V8HI_type_node, V8HI_type_node,
+-				V8HI_type_node, NULL_TREE);
+-  tree v4si_ftype_v8hi_v8hi_v4si
+-    = build_function_type_list (V4SI_type_node,
+-				V8HI_type_node, V8HI_type_node,
+-				V4SI_type_node, NULL_TREE);
+-  tree v4si_ftype_v16qi_v16qi_v4si
+-    = build_function_type_list (V4SI_type_node,
+-				V16QI_type_node, V16QI_type_node,
+-				V4SI_type_node, NULL_TREE);
+-  tree v16qi_ftype_v16qi_v16qi
+-    = build_function_type_list (V16QI_type_node,
+-				V16QI_type_node, V16QI_type_node, NULL_TREE);
+-  tree v4si_ftype_v4sf_v4sf
+-    = build_function_type_list (V4SI_type_node,
+-				V4SF_type_node, V4SF_type_node, NULL_TREE);
+-  tree v8hi_ftype_v16qi_v16qi
+-    = build_function_type_list (V8HI_type_node,
+-				V16QI_type_node, V16QI_type_node, NULL_TREE);
+-  tree v4si_ftype_v8hi_v8hi
+-    = build_function_type_list (V4SI_type_node,
+-				V8HI_type_node, V8HI_type_node, NULL_TREE);
+-  tree v8hi_ftype_v4si_v4si
+-    = build_function_type_list (V8HI_type_node,
+-				V4SI_type_node, V4SI_type_node, NULL_TREE);
+-  tree v16qi_ftype_v8hi_v8hi
+-    = build_function_type_list (V16QI_type_node,
+-				V8HI_type_node, V8HI_type_node, NULL_TREE);
+-  tree v4si_ftype_v16qi_v4si
+-    = build_function_type_list (V4SI_type_node,
+-				V16QI_type_node, V4SI_type_node, NULL_TREE);
+-  tree v4si_ftype_v16qi_v16qi
+-    = build_function_type_list (V4SI_type_node,
+-				V16QI_type_node, V16QI_type_node, NULL_TREE);
+-  tree v4si_ftype_v8hi_v4si
+-    = build_function_type_list (V4SI_type_node,
+-				V8HI_type_node, V4SI_type_node, NULL_TREE);
+-  tree v4si_ftype_v8hi
+-    = build_function_type_list (V4SI_type_node, V8HI_type_node, NULL_TREE);
+-  tree int_ftype_v4si_v4si
+-    = build_function_type_list (integer_type_node,
+-				V4SI_type_node, V4SI_type_node, NULL_TREE);
+-  tree int_ftype_v4sf_v4sf
+-    = build_function_type_list (integer_type_node,
+-				V4SF_type_node, V4SF_type_node, NULL_TREE);
+-  tree int_ftype_v16qi_v16qi
+-    = build_function_type_list (integer_type_node,
+-				V16QI_type_node, V16QI_type_node, NULL_TREE);
+-  tree int_ftype_v8hi_v8hi
+-    = build_function_type_list (integer_type_node,
+-				V8HI_type_node, V8HI_type_node, NULL_TREE);
+-  tree v2di_ftype_v2df
+-    = build_function_type_list (V2DI_type_node,
+-				V2DF_type_node, NULL_TREE);
+-  tree v2df_ftype_v2df
+-    = build_function_type_list (V2DF_type_node,
+-				V2DF_type_node, NULL_TREE);
+-  tree v2df_ftype_v2di
+-    = build_function_type_list (V2DF_type_node,
+-				V2DI_type_node, NULL_TREE);
+-  tree v2df_ftype_v2df_v2df
+-    = build_function_type_list (V2DF_type_node,
+-				V2DF_type_node, V2DF_type_node, NULL_TREE);
+-  tree v2df_ftype_v2df_v2df_v2df
+-    = build_function_type_list (V2DF_type_node,
+-				V2DF_type_node, V2DF_type_node,
+-				V2DF_type_node, NULL_TREE);
+-  tree v2di_ftype_v2di_v2di_v2di
+-    = build_function_type_list (V2DI_type_node,
+-				V2DI_type_node, V2DI_type_node,
+-				V2DI_type_node, NULL_TREE);
+-  tree v2df_ftype_v2df_v2df_v16qi
+-    = build_function_type_list (V2DF_type_node,
+-				V2DF_type_node, V2DF_type_node,
+-				V16QI_type_node, NULL_TREE);
+-  tree v2di_ftype_v2di_v2di_v16qi
+-    = build_function_type_list (V2DI_type_node,
+-				V2DI_type_node, V2DI_type_node,
+-				V16QI_type_node, NULL_TREE);
+-  tree v4sf_ftype_v4si
+-    = build_function_type_list (V4SF_type_node, V4SI_type_node, NULL_TREE);
+-  tree v4si_ftype_v4sf
+-    = build_function_type_list (V4SI_type_node, V4SF_type_node, NULL_TREE);
++/* Map types for builtin functions with an explicit return type and up to 3
++   arguments.  Functions with fewer than 3 arguments use VOIDmode as the type
++   of the argument.  */
++static tree
++builtin_function_type (enum machine_mode mode_ret, enum machine_mode mode_arg0,
++		       enum machine_mode mode_arg1, enum machine_mode mode_arg2,
++		       const char *name)
++{
++  struct builtin_hash_struct h;
++  struct builtin_hash_struct *h2;
++  void **found;
++  int num_args = 3;
++  int i;
+ 
+-  /* Add the simple ternary operators.  */
++  /* Create builtin_hash_table.  */
++  if (builtin_hash_table == NULL)
++    builtin_hash_table = htab_create_ggc (1500, builtin_hash_function,
++					  builtin_hash_eq, NULL);
++
++  h.type = NULL_TREE;
++  h.mode[0] = mode_ret;
++  h.mode[1] = mode_arg0;
++  h.mode[2] = mode_arg1;
++  h.mode[3] = mode_arg2;
++
++  /* Figure out how many args are present.  */
++  while (num_args > 0 && h.mode[num_args] == VOIDmode)
++    num_args--;
++
++  if (num_args == 0)
++    fatal_error ("internal error: builtin function %s had no type", name);
++
++  if (!builtin_mode_to_type[h.mode[0]])
++    fatal_error ("internal error: builtin function %s had an unexpected "
++		 "return type %s", name, GET_MODE_NAME (h.mode[0]));
++
++  for (i = 0; i < num_args; i++)
++    if (!builtin_mode_to_type[h.mode[i+1]])
++      fatal_error ("internal error: builtin function %s, argument %d "
++		   "had unexpected argument type %s", name, i,
++		   GET_MODE_NAME (h.mode[i+1]));
++
++  found = htab_find_slot (builtin_hash_table, &h, 1);
++  if (*found == NULL)
++    {
++      h2 = GGC_NEW (struct builtin_hash_struct);
++      *h2 = h;
++      *found = (void *)h2;
++
++      switch (num_args)
++	{
++	case 1:
++	  h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
++					       builtin_mode_to_type[mode_arg0],
++					       NULL_TREE);
++	  break;
++
++	case 2:
++	  h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
++					       builtin_mode_to_type[mode_arg0],
++					       builtin_mode_to_type[mode_arg1],
++					       NULL_TREE);
++	  break;
++
++	case 3:
++	  h2->type = build_function_type_list (builtin_mode_to_type[mode_ret],
++					       builtin_mode_to_type[mode_arg0],
++					       builtin_mode_to_type[mode_arg1],
++					       builtin_mode_to_type[mode_arg2],
++					       NULL_TREE);
++	  break;
++
++	default:
++	  gcc_unreachable ();
++	}
++    }
++
++  return ((struct builtin_hash_struct *)(*found))->type;
++}
++
++static void
++rs6000_common_init_builtins (void)
++{
++  const struct builtin_description *d;
++  size_t i;
++
++  tree opaque_ftype_opaque = NULL_TREE;
++  tree opaque_ftype_opaque_opaque = NULL_TREE;
++  tree opaque_ftype_opaque_opaque_opaque = NULL_TREE;
++  tree v2si_ftype_qi = NULL_TREE;
++  tree v2si_ftype_v2si_qi = NULL_TREE;
++  tree v2si_ftype_int_qi = NULL_TREE;
++
++  /* Initialize the tables for the unary, binary, and ternary ops.  */
++  builtin_mode_to_type[QImode] = integer_type_node;
++  builtin_mode_to_type[HImode] = integer_type_node;
++  builtin_mode_to_type[SImode] = intSI_type_node;
++  builtin_mode_to_type[DImode] = intDI_type_node;
++  builtin_mode_to_type[SFmode] = float_type_node;
++  builtin_mode_to_type[DFmode] = double_type_node;
++  builtin_mode_to_type[V2SImode] = V2SI_type_node;
++  builtin_mode_to_type[V2SFmode] = V2SF_type_node;
++  builtin_mode_to_type[V2DImode] = V2DI_type_node;
++  builtin_mode_to_type[V2DFmode] = V2DF_type_node;
++  builtin_mode_to_type[V4HImode] = V4HI_type_node;
++  builtin_mode_to_type[V4SImode] = V4SI_type_node;
++  builtin_mode_to_type[V4SFmode] = V4SF_type_node;
++  builtin_mode_to_type[V8HImode] = V8HI_type_node;
++  builtin_mode_to_type[V16QImode] = V16QI_type_node;
++
++  if (!TARGET_PAIRED_FLOAT)
++    {
++      builtin_mode_to_type[V2SImode] = opaque_V2SI_type_node;
++      builtin_mode_to_type[V2SFmode] = opaque_V2SF_type_node;
++    }
++
++  /* Add the ternary operators.  */
+   d = bdesc_3arg;
+   for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
+     {
+-      enum machine_mode mode0, mode1, mode2, mode3;
+       tree type;
+-      bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+-			   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
++      int mask = d->mask;
+ 
+-      if (is_overloaded)
+-	{
+-          mode0 = VOIDmode;
+-          mode1 = VOIDmode;
+-          mode2 = VOIDmode;
+-          mode3 = VOIDmode;
++      if ((mask != 0 && (mask & target_flags) == 0)
++	  || (mask == 0 && !TARGET_PAIRED_FLOAT))
++	continue;
++
++      if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
++	   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
++	  || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
++	      && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
++	{
++	  if (! (type = opaque_ftype_opaque_opaque_opaque))
++	    type = opaque_ftype_opaque_opaque_opaque
++	      = build_function_type_list (opaque_V4SI_type_node,
++					  opaque_V4SI_type_node,
++					  opaque_V4SI_type_node,
++					  opaque_V4SI_type_node,
++					  NULL_TREE);
+ 	}
+       else
+ 	{
+-          if (d->name == 0 || d->icode == CODE_FOR_nothing)
++	  enum insn_code icode = d->icode;
++          if (d->name == 0 || icode == CODE_FOR_nothing)
+ 	    continue;
+ 
+-          mode0 = insn_data[d->icode].operand[0].mode;
+-          mode1 = insn_data[d->icode].operand[1].mode;
+-          mode2 = insn_data[d->icode].operand[2].mode;
+-          mode3 = insn_data[d->icode].operand[3].mode;
++	  type = builtin_function_type (insn_data[icode].operand[0].mode,
++					insn_data[icode].operand[1].mode,
++					insn_data[icode].operand[2].mode,
++					insn_data[icode].operand[3].mode,
++					d->name);
+ 	}
+ 
+-      /* When all four are of the same mode.  */
+-      if (mode0 == mode1 && mode1 == mode2 && mode2 == mode3)
+-	{
+-	  switch (mode0)
+-	    {
+-	    case VOIDmode:
+-	      type = opaque_ftype_opaque_opaque_opaque;
+-	      break;
+-	    case V2DImode:
+-	      type = v2di_ftype_v2di_v2di_v2di;
+-	      break;
+-	    case V2DFmode:
+-	      type = v2df_ftype_v2df_v2df_v2df;
+-	      break;
+-	    case V4SImode:
+-	      type = v4si_ftype_v4si_v4si_v4si;
+-	      break;
+-	    case V4SFmode:
+-	      type = v4sf_ftype_v4sf_v4sf_v4sf;
+-	      break;
+-	    case V8HImode:
+-	      type = v8hi_ftype_v8hi_v8hi_v8hi;
+-	      break;
+-	    case V16QImode:
+-	      type = v16qi_ftype_v16qi_v16qi_v16qi;
+-	      break;
+-            case V2SFmode:
+-                type = v2sf_ftype_v2sf_v2sf_v2sf;
+-              break;
+-	    default:
+-	      gcc_unreachable ();
+-	    }
+-	}
+-      else if (mode0 == mode1 && mode1 == mode2 && mode3 == V16QImode)
+-	{
+-	  switch (mode0)
+-	    {
+-	    case V2DImode:
+-	      type = v2di_ftype_v2di_v2di_v16qi;
+-	      break;
+-	    case V2DFmode:
+-	      type = v2df_ftype_v2df_v2df_v16qi;
+-	      break;
+-	    case V4SImode:
+-	      type = v4si_ftype_v4si_v4si_v16qi;
+-	      break;
+-	    case V4SFmode:
+-	      type = v4sf_ftype_v4sf_v4sf_v16qi;
+-	      break;
+-	    case V8HImode:
+-	      type = v8hi_ftype_v8hi_v8hi_v16qi;
+-	      break;
+-	    case V16QImode:
+-	      type = v16qi_ftype_v16qi_v16qi_v16qi;
+-	      break;
+-	    default:
+-	      gcc_unreachable ();
+-	    }
+-	}
+-      else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode
+-	       && mode3 == V4SImode)
+-	type = v4si_ftype_v16qi_v16qi_v4si;
+-      else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode
+-	       && mode3 == V4SImode)
+-	type = v4si_ftype_v8hi_v8hi_v4si;
+-      else if (mode0 == V4SFmode && mode1 == V4SFmode && mode2 == V4SFmode
+-	       && mode3 == V4SImode)
+-	type = v4sf_ftype_v4sf_v4sf_v4si;
+-
+-      /* vchar, vchar, vchar, 4-bit literal.  */
+-      else if (mode0 == V16QImode && mode1 == mode0 && mode2 == mode0
+-	       && mode3 == QImode)
+-	type = v16qi_ftype_v16qi_v16qi_int;
+-
+-      /* vshort, vshort, vshort, 4-bit literal.  */
+-      else if (mode0 == V8HImode && mode1 == mode0 && mode2 == mode0
+-	       && mode3 == QImode)
+-	type = v8hi_ftype_v8hi_v8hi_int;
+-
+-      /* vint, vint, vint, 4-bit literal.  */
+-      else if (mode0 == V4SImode && mode1 == mode0 && mode2 == mode0
+-	       && mode3 == QImode)
+-	type = v4si_ftype_v4si_v4si_int;
+-
+-      /* vfloat, vfloat, vfloat, 4-bit literal.  */
+-      else if (mode0 == V4SFmode && mode1 == mode0 && mode2 == mode0
+-	       && mode3 == QImode)
+-	type = v4sf_ftype_v4sf_v4sf_int;
+-
+-      else
+-	gcc_unreachable ();
+-
+       def_builtin (d->mask, d->name, type, d->code);
+     }
+ 
+-  /* Add the simple binary operators.  */
++  /* Add the binary operators.  */
+   d = (struct builtin_description *) bdesc_2arg;
+   for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
+     {
+       enum machine_mode mode0, mode1, mode2;
+       tree type;
+-      bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+-			   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
++      int mask = d->mask;
+ 
+-      if (is_overloaded)
+-	{
+-	  mode0 = VOIDmode;
+-	  mode1 = VOIDmode;
+-	  mode2 = VOIDmode;
++      if ((mask != 0 && (mask & target_flags) == 0)
++	  || (mask == 0 && !TARGET_PAIRED_FLOAT))
++	continue;
++
++      if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
++	   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
++	  || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
++	      && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
++	{
++	  if (! (type = opaque_ftype_opaque_opaque))
++	    type = opaque_ftype_opaque_opaque
++	      = build_function_type_list (opaque_V4SI_type_node,
++					  opaque_V4SI_type_node,
++					  opaque_V4SI_type_node,
++					  NULL_TREE);
+ 	}
+       else
+ 	{
+-          if (d->name == 0 || d->icode == CODE_FOR_nothing)
++	  enum insn_code icode = d->icode;
++          if (d->name == 0 || icode == CODE_FOR_nothing)
+ 	    continue;
+ 
+-          mode0 = insn_data[d->icode].operand[0].mode;
+-          mode1 = insn_data[d->icode].operand[1].mode;
+-          mode2 = insn_data[d->icode].operand[2].mode;
+-	}
++          mode0 = insn_data[icode].operand[0].mode;
++          mode1 = insn_data[icode].operand[1].mode;
++          mode2 = insn_data[icode].operand[2].mode;
+ 
+-      /* When all three operands are of the same mode.  */
+-      if (mode0 == mode1 && mode1 == mode2)
+-	{
+-	  switch (mode0)
++	  if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode)
+ 	    {
+-	    case VOIDmode:
+-	      type = opaque_ftype_opaque_opaque;
+-	      break;
+-	    case V2DFmode:
+-	      type = v2df_ftype_v2df_v2df;
+-	      break;
+-	    case V4SFmode:
+-	      type = v4sf_ftype_v4sf_v4sf;
+-	      break;
+-	    case V4SImode:
+-	      type = v4si_ftype_v4si_v4si;
+-	      break;
+-	    case V16QImode:
+-	      type = v16qi_ftype_v16qi_v16qi;
+-	      break;
+-	    case V8HImode:
+-	      type = v8hi_ftype_v8hi_v8hi;
+-	      break;
+-	    case V2SImode:
+-	      type = v2si_ftype_v2si_v2si;
+-	      break;
+-            case V2SFmode:
+-              if (TARGET_PAIRED_FLOAT)
+-                type = v2sf_ftype_v2sf_v2sf;
+-              else
+-                type = v2sf_ftype_v2sf_v2sf_spe;
+-	      break;
+-	    case SImode:
+-	      type = int_ftype_int_int;
+-	      break;
+-	    default:
+-	      gcc_unreachable ();
++	      if (! (type = v2si_ftype_v2si_qi))
++		type = v2si_ftype_v2si_qi
++		  = build_function_type_list (opaque_V2SI_type_node,
++					      opaque_V2SI_type_node,
++					      char_type_node,
++					      NULL_TREE);
+ 	    }
+-	}
+-
+-      /* A few other combos we really don't want to do manually.  */
+-
+-      /* vint, vfloat, vfloat.  */
+-      else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode)
+-	type = v4si_ftype_v4sf_v4sf;
+-
+-      /* vshort, vchar, vchar.  */
+-      else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode)
+-	type = v8hi_ftype_v16qi_v16qi;
+-
+-      /* vint, vshort, vshort.  */
+-      else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode)
+-	type = v4si_ftype_v8hi_v8hi;
+-
+-      /* vshort, vint, vint.  */
+-      else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode)
+-	type = v8hi_ftype_v4si_v4si;
+-
+-      /* vchar, vshort, vshort.  */
+-      else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode)
+-	type = v16qi_ftype_v8hi_v8hi;
+-
+-      /* vint, vchar, vint.  */
+-      else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode)
+-	type = v4si_ftype_v16qi_v4si;
+-
+-      /* vint, vchar, vchar.  */
+-      else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode)
+-	type = v4si_ftype_v16qi_v16qi;
+-
+-      /* vint, vshort, vint.  */
+-      else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
+-	type = v4si_ftype_v8hi_v4si;
+ 
+-      /* vint, vint, 5-bit literal.  */
+-      else if (mode0 == V4SImode && mode1 == V4SImode && mode2 == QImode)
+-	type = v4si_ftype_v4si_int;
+-
+-      /* vshort, vshort, 5-bit literal.  */
+-      else if (mode0 == V8HImode && mode1 == V8HImode && mode2 == QImode)
+-	type = v8hi_ftype_v8hi_int;
+-
+-      /* vchar, vchar, 5-bit literal.  */
+-      else if (mode0 == V16QImode && mode1 == V16QImode && mode2 == QImode)
+-	type = v16qi_ftype_v16qi_int;
+-
+-      /* vfloat, vint, 5-bit literal.  */
+-      else if (mode0 == V4SFmode && mode1 == V4SImode && mode2 == QImode)
+-	type = v4sf_ftype_v4si_int;
+-
+-      /* vint, vfloat, 5-bit literal.  */
+-      else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == QImode)
+-	type = v4si_ftype_v4sf_int;
+-
+-      else if (mode0 == V2SImode && mode1 == SImode && mode2 == SImode)
+-	type = v2si_ftype_int_int;
+-
+-      else if (mode0 == V2SImode && mode1 == V2SImode && mode2 == QImode)
+-	type = v2si_ftype_v2si_char;
+-
+-      else if (mode0 == V2SImode && mode1 == SImode && mode2 == QImode)
+-	type = v2si_ftype_int_char;
+-
+-      else
+-	{
+-	  /* int, x, x.  */
+-	  gcc_assert (mode0 == SImode);
+-	  switch (mode1)
++	  else if (mode0 == V2SImode && GET_MODE_CLASS (mode1) == MODE_INT
++		   && mode2 == QImode)
+ 	    {
+-	    case V4SImode:
+-	      type = int_ftype_v4si_v4si;
+-	      break;
+-	    case V4SFmode:
+-	      type = int_ftype_v4sf_v4sf;
+-	      break;
+-	    case V16QImode:
+-	      type = int_ftype_v16qi_v16qi;
+-	      break;
+-	    case V8HImode:
+-	      type = int_ftype_v8hi_v8hi;
+-	      break;
+-	    default:
+-	      gcc_unreachable ();
++	      if (! (type = v2si_ftype_int_qi))
++		type = v2si_ftype_int_qi
++		  = build_function_type_list (opaque_V2SI_type_node,
++					      integer_type_node,
++					      char_type_node,
++					      NULL_TREE);
+ 	    }
++
++	  else
++	    type = builtin_function_type (mode0, mode1, mode2, VOIDmode,
++					  d->name);
+ 	}
+ 
+       def_builtin (d->mask, d->name, type, d->code);
+     }
+ 
+-  /* Add the simple unary operators.  */
++  /* Add the unary operators.  */
+   d = (struct builtin_description *) bdesc_1arg;
+   for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
+     {
+       enum machine_mode mode0, mode1;
+       tree type;
+-      bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+-			   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
++      int mask = d->mask;
+ 
+-      if (is_overloaded)
+-        {
+-          mode0 = VOIDmode;
+-          mode1 = VOIDmode;
+-        }
++      if ((mask != 0 && (mask & target_flags) == 0)
++	  || (mask == 0 && !TARGET_PAIRED_FLOAT))
++	continue;
++
++      if ((d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
++	   && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
++	  || (d->code >= VSX_BUILTIN_OVERLOADED_FIRST
++	      && d->code <= VSX_BUILTIN_OVERLOADED_LAST))
++	{
++	  if (! (type = opaque_ftype_opaque))
++	    type = opaque_ftype_opaque
++	      = build_function_type_list (opaque_V4SI_type_node,
++					  opaque_V4SI_type_node,
++					  NULL_TREE);
++	}
+       else
+         {
+-          if (d->name == 0 || d->icode == CODE_FOR_nothing)
++	  enum insn_code icode = d->icode;
++          if (d->name == 0 || icode == CODE_FOR_nothing)
+ 	    continue;
+ 
+-          mode0 = insn_data[d->icode].operand[0].mode;
+-          mode1 = insn_data[d->icode].operand[1].mode;
+-        }
++          mode0 = insn_data[icode].operand[0].mode;
++          mode1 = insn_data[icode].operand[1].mode;
+ 
+-      if (mode0 == V4SImode && mode1 == QImode)
+-	type = v4si_ftype_int;
+-      else if (mode0 == V8HImode && mode1 == QImode)
+-	type = v8hi_ftype_int;
+-      else if (mode0 == V16QImode && mode1 == QImode)
+-	type = v16qi_ftype_int;
+-      else if (mode0 == VOIDmode && mode1 == VOIDmode)
+-	type = opaque_ftype_opaque;
+-      else if (mode0 == V2DFmode && mode1 == V2DFmode)
+-	type = v2df_ftype_v2df;
+-      else if (mode0 == V4SFmode && mode1 == V4SFmode)
+-	type = v4sf_ftype_v4sf;
+-      else if (mode0 == V8HImode && mode1 == V16QImode)
+-	type = v8hi_ftype_v16qi;
+-      else if (mode0 == V4SImode && mode1 == V8HImode)
+-	type = v4si_ftype_v8hi;
+-      else if (mode0 == V2SImode && mode1 == V2SImode)
+-	type = v2si_ftype_v2si;
+-      else if (mode0 == V2SFmode && mode1 == V2SFmode)
+-        {
+-          if (TARGET_PAIRED_FLOAT)
+-            type = v2sf_ftype_v2sf;
+-          else
+-            type = v2sf_ftype_v2sf_spe;
+-        }
+-      else if (mode0 == V2SFmode && mode1 == V2SImode)
+-	type = v2sf_ftype_v2si;
+-      else if (mode0 == V2SImode && mode1 == V2SFmode)
+-	type = v2si_ftype_v2sf;
+-      else if (mode0 == V2SImode && mode1 == QImode)
+-	type = v2si_ftype_char;
+-      else if (mode0 == V4SImode && mode1 == V4SFmode)
+-	type = v4si_ftype_v4sf;
+-      else if (mode0 == V4SFmode && mode1 == V4SImode)
+-	type = v4sf_ftype_v4si;
+-      else if (mode0 == V2DImode && mode1 == V2DFmode)
+-	type = v2di_ftype_v2df;
+-      else if (mode0 == V2DFmode && mode1 == V2DImode)
+-	type = v2df_ftype_v2di;
+-      else
+-	gcc_unreachable ();
++	  if (mode0 == V2SImode && mode1 == QImode)
++	    {
++	      if (! (type = v2si_ftype_qi))
++		type = v2si_ftype_qi
++		  = build_function_type_list (opaque_V2SI_type_node,
++					      char_type_node,
++					      NULL_TREE);
++	    }
++
++	  else
++	    type = builtin_function_type (mode0, mode1, VOIDmode, VOIDmode,
++					  d->name);
++	}
+ 
+       def_builtin (d->mask, d->name, type, d->code);
+     }
+@@ -12637,12 +12557,12 @@ rs6000_secondary_reload_inner (rtx reg, 
+ 	}
+ 
+       if (GET_CODE (addr) == PLUS
+-	  && (!rs6000_legitimate_offset_address_p (TImode, addr, true)
++	  && (!rs6000_legitimate_offset_address_p (TImode, addr, false)
+ 	      || and_op2 != NULL_RTX))
+ 	{
+ 	  addr_op1 = XEXP (addr, 0);
+ 	  addr_op2 = XEXP (addr, 1);
+-	  gcc_assert (legitimate_indirect_address_p (addr_op1, true));
++	  gcc_assert (legitimate_indirect_address_p (addr_op1, false));
+ 
+ 	  if (!REG_P (addr_op2)
+ 	      && (GET_CODE (addr_op2) != CONST_INT
+@@ -12661,8 +12581,8 @@ rs6000_secondary_reload_inner (rtx reg, 
+ 	  addr = scratch_or_premodify;
+ 	  scratch_or_premodify = scratch;
+ 	}
+-      else if (!legitimate_indirect_address_p (addr, true)
+-	       && !rs6000_legitimate_offset_address_p (TImode, addr, true))
++      else if (!legitimate_indirect_address_p (addr, false)
++	       && !rs6000_legitimate_offset_address_p (TImode, addr, false))
+ 	{
+ 	  rs6000_emit_move (scratch_or_premodify, addr, Pmode);
+ 	  addr = scratch_or_premodify;
+@@ -12691,24 +12611,24 @@ rs6000_secondary_reload_inner (rtx reg, 
+       if (GET_CODE (addr) == PRE_MODIFY
+ 	  && (!VECTOR_MEM_VSX_P (mode)
+ 	      || and_op2 != NULL_RTX
+-	      || !legitimate_indexed_address_p (XEXP (addr, 1), true)))
++	      || !legitimate_indexed_address_p (XEXP (addr, 1), false)))
+ 	{
+ 	  scratch_or_premodify = XEXP (addr, 0);
+ 	  gcc_assert (legitimate_indirect_address_p (scratch_or_premodify,
+-						     true));
++						     false));
+ 	  gcc_assert (GET_CODE (XEXP (addr, 1)) == PLUS);
+ 	  addr = XEXP (addr, 1);
+ 	}
+ 
+-      if (legitimate_indirect_address_p (addr, true)	/* reg */
+-	  || legitimate_indexed_address_p (addr, true)	/* reg+reg */
++      if (legitimate_indirect_address_p (addr, false)	/* reg */
++	  || legitimate_indexed_address_p (addr, false)	/* reg+reg */
+ 	  || GET_CODE (addr) == PRE_MODIFY		/* VSX pre-modify */
+ 	  || GET_CODE (addr) == AND			/* Altivec memory */
+ 	  || (rclass == FLOAT_REGS			/* legacy float mem */
+ 	      && GET_MODE_SIZE (mode) == 8
+ 	      && and_op2 == NULL_RTX
+ 	      && scratch_or_premodify == scratch
+-	      && rs6000_legitimate_offset_address_p (mode, addr, true)))
++	      && rs6000_legitimate_offset_address_p (mode, addr, false)))
+ 	;
+ 
+       else if (GET_CODE (addr) == PLUS)
+@@ -12728,7 +12648,7 @@ rs6000_secondary_reload_inner (rtx reg, 
+ 	}
+ 
+       else if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
+-	       || GET_CODE (addr) == CONST_INT)
++	       || GET_CODE (addr) == CONST_INT || REG_P (addr))
+ 	{
+ 	  rs6000_emit_move (scratch_or_premodify, addr, Pmode);
+ 	  addr = scratch_or_premodify;
+@@ -12760,7 +12680,7 @@ rs6000_secondary_reload_inner (rtx reg, 
+      andi. instruction.  */
+   if (and_op2 != NULL_RTX)
+     {
+-      if (! legitimate_indirect_address_p (addr, true))
++      if (! legitimate_indirect_address_p (addr, false))
+ 	{
+ 	  emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
+ 	  addr = scratch;
+@@ -12795,6 +12715,26 @@ rs6000_secondary_reload_inner (rtx reg, 
+   return;
+ }
+ 
++/* Target hook to return the cover classes for Integrated Register Allocator.
++   Cover classes is a set of non-intersected register classes covering all hard
++   registers used for register allocation purpose.  Any move between two
++   registers of a cover class should be cheaper than load or store of the
++   registers.  The value is array of register classes with LIM_REG_CLASSES used
++   as the end marker.
++
++   We need two IRA_COVER_CLASSES, one for pre-VSX, and the other for VSX to
++   account for the Altivec and Floating registers being subsets of the VSX
++   register set under VSX, but distinct register sets on pre-VSX machines.  */
++
++static const enum reg_class *
++rs6000_ira_cover_classes (void)
++{
++  static const enum reg_class cover_pre_vsx[] = IRA_COVER_CLASSES_PRE_VSX;
++  static const enum reg_class cover_vsx[]     = IRA_COVER_CLASSES_VSX;
++
++  return (TARGET_VSX) ? cover_vsx : cover_pre_vsx;
++}
++
+ /* Allocate a 64-bit stack slot to be used for copying SDmode
+    values through if this function has any SDmode references.  */
+ 
+@@ -12868,13 +12808,15 @@ rs6000_preferred_reload_class (rtx x, en
+   enum machine_mode mode = GET_MODE (x);
+   enum reg_class ret;
+ 
+-  if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode)
+-      && VSX_REG_CLASS_P (rclass))
++  if (TARGET_VSX
++      && (VSX_VECTOR_MODE (mode) || mode == TImode)
++      && x == CONST0_RTX (mode) && VSX_REG_CLASS_P (rclass))
+     ret = rclass;
+ 
+-  else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode)
+-	   && rclass == ALTIVEC_REGS && easy_vector_constant (x, mode))
+-    ret = rclass;
++  else if (TARGET_ALTIVEC && (ALTIVEC_VECTOR_MODE (mode) || mode == TImode)
++	   && (rclass == ALTIVEC_REGS || rclass == VSX_REGS)
++	   && easy_vector_constant (x, mode))
++    ret = ALTIVEC_REGS;
+ 
+   else if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
+     ret = NO_REGS;
+@@ -13093,8 +13035,10 @@ rs6000_cannot_change_mode_class (enum ma
+ 		       || (((to) == TDmode) + ((from) == TDmode)) == 1
+ 		       || (((to) == DImode) + ((from) == DImode)) == 1))
+ 		  || (TARGET_VSX
+-		      && (VSX_VECTOR_MODE (from) + VSX_VECTOR_MODE (to)) == 1)
++		      && (VSX_MOVE_MODE (from) + VSX_MOVE_MODE (to)) == 1
++		      && VSX_REG_CLASS_P (rclass))
+ 		  || (TARGET_ALTIVEC
++		      && rclass == ALTIVEC_REGS
+ 		      && (ALTIVEC_VECTOR_MODE (from)
+ 			  + ALTIVEC_VECTOR_MODE (to)) == 1)
+ 		  || (TARGET_SPE
+@@ -14972,7 +14916,7 @@ rs6000_emit_vector_cond_expr (rtx dest, 
+   if (!mask)
+     return 0;
+ 
+-  if ((TARGET_VSX && VSX_VECTOR_MOVE_MODE (dest_mode))
++  if ((TARGET_VSX && VSX_MOVE_MODE (dest_mode))
+       || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (dest_mode)))
+     {
+       rtx cond2 = gen_rtx_fmt_ee (NE, VOIDmode, mask, const0_rtx);
+@@ -22161,7 +22105,8 @@ rs6000_handle_altivec_attribute (tree *n
+   mode = TYPE_MODE (type);
+ 
+   /* Check for invalid AltiVec type qualifiers.  */
+-  if (type == long_unsigned_type_node || type == long_integer_type_node)
++  if ((type == long_unsigned_type_node || type == long_integer_type_node)
++      && !TARGET_VSX)
+     {
+     if (TARGET_64BIT)
+       error ("use of %<long%> in AltiVec types is invalid for 64-bit code");
+@@ -22199,6 +22144,7 @@ rs6000_handle_altivec_attribute (tree *n
+ 	  break;
+ 	case SFmode: result = V4SF_type_node; break;
+ 	case DFmode: result = V2DF_type_node; break;
++	case DImode: result = V2DI_type_node; break;
+ 	  /* If the user says 'vector int bool', we may be handed the 'bool'
+ 	     attribute _before_ the 'vector' attribute, and so select the
+ 	     proper type in the 'b' case below.  */
+@@ -22210,6 +22156,7 @@ rs6000_handle_altivec_attribute (tree *n
+     case 'b':
+       switch (mode)
+ 	{
++	case DImode: case V2DImode: result = bool_V2DI_type_node; break;
+ 	case SImode: case V4SImode: result = bool_V4SI_type_node; break;
+ 	case HImode: case V8HImode: result = bool_V8HI_type_node; break;
+ 	case QImode: case V16QImode: result = bool_V16QI_type_node;
+@@ -22254,6 +22201,7 @@ rs6000_mangle_type (const_tree type)
+   if (type == bool_short_type_node) return "U6__bools";
+   if (type == pixel_type_node) return "u7__pixel";
+   if (type == bool_int_type_node) return "U6__booli";
++  if (type == bool_long_type_node) return "U6__booll";
+ 
+   /* Mangle IBM extended float long double as `g' (__float128) on
+      powerpc*-linux where long-double-64 previously was the default.  */
+@@ -23781,6 +23729,8 @@ int
+ rs6000_register_move_cost (enum machine_mode mode,
+ 			   enum reg_class from, enum reg_class to)
+ {
++  int ret;
++
+   /*  Moves from/to GENERAL_REGS.  */
+   if (reg_classes_intersect_p (to, GENERAL_REGS)
+       || reg_classes_intersect_p (from, GENERAL_REGS))
+@@ -23789,39 +23739,47 @@ rs6000_register_move_cost (enum machine_
+ 	from = to;
+ 
+       if (from == FLOAT_REGS || from == ALTIVEC_REGS || from == VSX_REGS)
+-	return (rs6000_memory_move_cost (mode, from, 0)
+-		+ rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
++	ret = (rs6000_memory_move_cost (mode, from, 0)
++	       + rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
+ 
+       /* It's more expensive to move CR_REGS than CR0_REGS because of the
+ 	 shift.  */
+       else if (from == CR_REGS)
+-	return 4;
++	ret = 4;
+ 
+       /* Power6 has slower LR/CTR moves so make them more expensive than
+ 	 memory in order to bias spills to memory .*/
+       else if (rs6000_cpu == PROCESSOR_POWER6
+ 	       && reg_classes_intersect_p (from, LINK_OR_CTR_REGS))
+-        return 6 * hard_regno_nregs[0][mode];
++        ret = 6 * hard_regno_nregs[0][mode];
+ 
+       else
+ 	/* A move will cost one instruction per GPR moved.  */
+-	return 2 * hard_regno_nregs[0][mode];
++	ret = 2 * hard_regno_nregs[0][mode];
+     }
+ 
+   /* If we have VSX, we can easily move between FPR or Altivec registers.  */
+-  else if (TARGET_VSX
+-	   && ((from == VSX_REGS || from == FLOAT_REGS || from == ALTIVEC_REGS)
+-	       || (to == VSX_REGS || to == FLOAT_REGS || to == ALTIVEC_REGS)))
+-    return 2;
++  else if (VECTOR_UNIT_VSX_P (mode)
++	   && reg_classes_intersect_p (to, VSX_REGS)
++	   && reg_classes_intersect_p (from, VSX_REGS))
++    ret = 2 * hard_regno_nregs[32][mode];
+ 
+   /* Moving between two similar registers is just one instruction.  */
+   else if (reg_classes_intersect_p (to, from))
+-    return (mode == TFmode || mode == TDmode) ? 4 : 2;
++    ret = (mode == TFmode || mode == TDmode) ? 4 : 2;
+ 
+   /* Everything else has to go through GENERAL_REGS.  */
+   else
+-    return (rs6000_register_move_cost (mode, GENERAL_REGS, to)
+-	    + rs6000_register_move_cost (mode, from, GENERAL_REGS));
++    ret = (rs6000_register_move_cost (mode, GENERAL_REGS, to)
++	   + rs6000_register_move_cost (mode, from, GENERAL_REGS));
++
++  if (TARGET_DEBUG_COST)
++    fprintf (stderr,
++	     "rs6000_register_move_cost:, ret=%d, mode=%s, from=%s, to=%s\n",
++	     ret, GET_MODE_NAME (mode), reg_class_names[from],
++	     reg_class_names[to]);
++
++  return ret;
+ }
+ 
+ /* A C expressions returning the cost of moving data of MODE from a register to
+@@ -23831,14 +23789,23 @@ int
+ rs6000_memory_move_cost (enum machine_mode mode, enum reg_class rclass,
+ 			 int in ATTRIBUTE_UNUSED)
+ {
++  int ret;
++
+   if (reg_classes_intersect_p (rclass, GENERAL_REGS))
+-    return 4 * hard_regno_nregs[0][mode];
++    ret = 4 * hard_regno_nregs[0][mode];
+   else if (reg_classes_intersect_p (rclass, FLOAT_REGS))
+-    return 4 * hard_regno_nregs[32][mode];
++    ret = 4 * hard_regno_nregs[32][mode];
+   else if (reg_classes_intersect_p (rclass, ALTIVEC_REGS))
+-    return 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode];
++    ret = 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode];
+   else
+-    return 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS);
++    ret = 4 + rs6000_register_move_cost (mode, rclass, GENERAL_REGS);
++
++  if (TARGET_DEBUG_COST)
++    fprintf (stderr,
++	     "rs6000_memory_move_cost: ret=%d, mode=%s, rclass=%s, in=%d\n",
++	     ret, GET_MODE_NAME (mode), reg_class_names[rclass], in);
++
++  return ret;
+ }
+ 
+ /* Returns a code for a target-specific builtin that implements
+@@ -24546,4 +24513,24 @@ rs6000_final_prescan_insn (rtx insn, rtx
+     }
+ }
+ 
++/* Return true if the function has an indirect jump or a table jump.  The compiler
++   prefers the ctr register for such jumps, which interferes with using the decrement
++   ctr register and branch.  */
++
++bool
++rs6000_has_indirect_jump_p (void)
++{
++  gcc_assert (cfun && cfun->machine);
++  return cfun->machine->indirect_jump_p;
++}
++
++/* Remember when we've generated an indirect jump.  */
++
++void
++rs6000_set_indirect_jump (void)
++{
++  gcc_assert (cfun && cfun->machine);
++  cfun->machine->indirect_jump_p = true;
++}
++
+ #include "gt-rs6000.h"
+--- gcc/config/rs6000/vsx.md	(revision 146119)
++++ gcc/config/rs6000/vsx.md	(revision 146798)
+@@ -22,12 +22,22 @@
+ ;; Iterator for both scalar and vector floating point types supported by VSX
+ (define_mode_iterator VSX_B [DF V4SF V2DF])
+ 
++;; Iterator for the 2 64-bit vector types
++(define_mode_iterator VSX_D [V2DF V2DI])
++
++;; Iterator for the 2 32-bit vector types
++(define_mode_iterator VSX_W [V4SF V4SI])
++
+ ;; Iterator for vector floating point types supported by VSX
+ (define_mode_iterator VSX_F [V4SF V2DF])
+ 
+ ;; Iterator for logical types supported by VSX
+ (define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
+ 
++;; Iterator for memory move.  Handle TImode specially to allow
++;; it to use gprs as well as vsx registers.
++(define_mode_iterator VSX_M [V16QI V8HI V4SI V2DI V4SF V2DF])
++
+ ;; Iterator for types for load/store with update
+ (define_mode_iterator VSX_U [V16QI V8HI V4SI V2DI V4SF V2DF TI DF])
+ 
+@@ -49,9 +59,10 @@ (define_mode_attr VSs	[(V16QI "sp")
+ 			 (V2DF  "dp")
+ 			 (V2DI  "dp")
+ 			 (DF    "dp")
++			 (SF	"sp")
+ 			 (TI    "sp")])
+ 
+-;; Map into the register class used
++;; Map the register class used
+ (define_mode_attr VSr	[(V16QI "v")
+ 			 (V8HI  "v")
+ 			 (V4SI  "v")
+@@ -59,9 +70,10 @@ (define_mode_attr VSr	[(V16QI "v")
+ 			 (V2DI  "wd")
+ 			 (V2DF  "wd")
+ 			 (DF    "ws")
++			 (SF	"f")
+ 			 (TI    "wd")])
+ 
+-;; Map into the register class used for float<->int conversions
++;; Map the register class used for float<->int conversions
+ (define_mode_attr VSr2	[(V2DF  "wd")
+ 			 (V4SF  "wf")
+ 			 (DF    "!f#r")])
+@@ -70,6 +82,18 @@ (define_mode_attr VSr3	[(V2DF  "wa")
+ 			 (V4SF  "wa")
+ 			 (DF    "!f#r")])
+ 
++;; Map the register class for sp<->dp float conversions, destination
++(define_mode_attr VSr4	[(SF	"ws")
++			 (DF	"f")
++			 (V2DF  "wd")
++			 (V4SF	"v")])
++
++;; Map the register class for sp<->dp float conversions, destination
++(define_mode_attr VSr5	[(SF	"ws")
++			 (DF	"f")
++			 (V2DF  "v")
++			 (V4SF	"wd")])
++
+ ;; Same size integer type for floating point data
+ (define_mode_attr VSi [(V4SF  "v4si")
+ 		       (V2DF  "v2di")
+@@ -137,6 +161,32 @@ (define_mode_attr VSfptype_sqrt	[(V2DF "
+ 				 (V4SF "fp_sqrt_s")
+ 				 (DF   "fp_sqrt_d")])
+ 
++;; Iterator and modes for sp<->dp conversions
++(define_mode_iterator VSX_SPDP [SF DF V4SF V2DF])
++
++(define_mode_attr VS_spdp_res [(SF	"DF")
++			       (DF	"SF")
++			       (V4SF	"V2DF")
++			       (V2DF	"V4SF")])
++
++(define_mode_attr VS_spdp_insn [(SF	"xscvspdp")
++				(DF	"xscvdpsp")
++				(V4SF	"xvcvspdp")
++				(V2DF	"xvcvdpsp")])
++
++(define_mode_attr VS_spdp_type [(SF	"fp")
++				(DF	"fp")
++				(V4SF	"vecfloat")
++				(V2DF	"vecfloat")])
++
++;; Map the scalar mode for a vector type
++(define_mode_attr VS_scalar [(V2DF	"DF")
++			     (V2DI	"DI")
++			     (V4SF	"SF")
++			     (V4SI	"SI")
++			     (V8HI	"HI")
++			     (V16QI	"QI")])
++			     
+ ;; Appropriate type for load + update
+ (define_mode_attr VStype_load_update [(V16QI "vecload")
+ 				      (V8HI  "vecload")
+@@ -159,25 +209,33 @@ (define_mode_attr VStype_store_update [(
+ 
+ ;; Constants for creating unspecs
+ (define_constants
+-  [(UNSPEC_VSX_CONCAT_V2DF	500)
+-   (UNSPEC_VSX_XVCVDPSP		501)
+-   (UNSPEC_VSX_XVCVDPSXWS	502)
+-   (UNSPEC_VSX_XVCVDPUXWS	503)
+-   (UNSPEC_VSX_XVCVSPDP		504)
+-   (UNSPEC_VSX_XVCVSXWDP	505)
+-   (UNSPEC_VSX_XVCVUXWDP	506)
+-   (UNSPEC_VSX_XVMADD		507)
+-   (UNSPEC_VSX_XVMSUB		508)
+-   (UNSPEC_VSX_XVNMADD		509)
+-   (UNSPEC_VSX_XVNMSUB		510)
+-   (UNSPEC_VSX_XVRSQRTE		511)
+-   (UNSPEC_VSX_XVTDIV		512)
+-   (UNSPEC_VSX_XVTSQRT		513)])
++  [(UNSPEC_VSX_CONCAT		500)
++   (UNSPEC_VSX_CVDPSXWS		501)
++   (UNSPEC_VSX_CVDPUXWS		502)
++   (UNSPEC_VSX_CVSPDP		503)
++   (UNSPEC_VSX_CVSXWDP		504)
++   (UNSPEC_VSX_CVUXWDP		505)
++   (UNSPEC_VSX_CVSXDSP		506)
++   (UNSPEC_VSX_CVUXDSP		507)
++   (UNSPEC_VSX_CVSPSXDS		508)
++   (UNSPEC_VSX_CVSPUXDS		509)
++   (UNSPEC_VSX_MADD		510)
++   (UNSPEC_VSX_MSUB		511)
++   (UNSPEC_VSX_NMADD		512)
++   (UNSPEC_VSX_NMSUB		513)
++   (UNSPEC_VSX_RSQRTE		514)
++   (UNSPEC_VSX_TDIV		515)
++   (UNSPEC_VSX_TSQRT		516)
++   (UNSPEC_VSX_XXPERMDI		517)
++   (UNSPEC_VSX_SET		518)
++   (UNSPEC_VSX_ROUND_I		519)
++   (UNSPEC_VSX_ROUND_IC		520)
++   (UNSPEC_VSX_SLDWI		521)])
+ 
+ ;; VSX moves
+ (define_insn "*vsx_mov<mode>"
+-  [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
+-	(match_operand:VSX_L 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
++  [(set (match_operand:VSX_M 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
++	(match_operand:VSX_M 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
+   "VECTOR_MEM_VSX_P (<MODE>mode)
+    && (register_operand (operands[0], <MODE>mode) 
+        || register_operand (operands[1], <MODE>mode))"
+@@ -220,6 +278,49 @@ (define_insn "*vsx_mov<mode>"
+ }
+   [(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_tdiv<mode>3"
+   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ 	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
+ 		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
+-		      UNSPEC_VSX_XVTDIV))]
++		      UNSPEC_VSX_TDIV))]
+   "VECTOR_UNIT_VSX_P (<MODE>mode)"
+   "x<VSv>tdiv<VSs> %x0,%x1,%x2"
+   [(set_attr "type" "<VStype_simple>")
+@@ -367,7 +468,7 @@ (define_insn "*vsx_sqrt<mode>2"
+ (define_insn "vsx_rsqrte<mode>2"
+   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ 	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+-		      UNSPEC_VSX_XVRSQRTE))]
++		      UNSPEC_VSX_RSQRTE))]
+   "VECTOR_UNIT_VSX_P (<MODE>mode)"
+   "x<VSv>rsqrte<VSs> %x0,%x1"
+   [(set_attr "type" "<VStype_simple>")
+@@ -376,7 +477,7 @@ (define_insn "vsx_rsqrte<mode>2"
+ (define_insn "vsx_tsqrt<mode>2"
+   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ 	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+-		      UNSPEC_VSX_XVTSQRT))]
++		      UNSPEC_VSX_TSQRT))]
+   "VECTOR_UNIT_VSX_P (<MODE>mode)"
+   "x<VSv>tsqrt<VSs> %x0,%x1"
+   [(set_attr "type" "<VStype_simple>")
+@@ -426,7 +527,7 @@ (define_insn "vsx_fmadd<mode>4_2"
+ 	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ 		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ 		       (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
+-		      UNSPEC_VSX_XVMADD))]
++		      UNSPEC_VSX_MADD))]
+   "VECTOR_UNIT_VSX_P (<MODE>mode)"
+   "@
+    x<VSv>madda<VSs> %x0,%x1,%x2
+@@ -474,7 +575,7 @@ (define_insn "vsx_fmsub<mode>4_2"
+ 	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ 		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ 		       (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
+-		      UNSPEC_VSX_XVMSUB))]
++		      UNSPEC_VSX_MSUB))]
+   "VECTOR_UNIT_VSX_P (<MODE>mode)"
+   "@
+    x<VSv>msuba<VSs> %x0,%x1,%x2
+@@ -552,7 +653,7 @@ (define_insn "vsx_fnmadd<mode>4_3"
+ 	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
+ 		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ 		       (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
+-		      UNSPEC_VSX_XVNMADD))]
++		      UNSPEC_VSX_NMADD))]
+   "VECTOR_UNIT_VSX_P (<MODE>mode)"
+   "@
+    x<VSv>nmadda<VSs> %x0,%x1,%x2
+@@ -629,7 +730,7 @@ (define_insn "vsx_fnmsub<mode>4_3"
+ 	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
+ 		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
+ 		       (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
+-		      UNSPEC_VSX_XVNMSUB))]
++		      UNSPEC_VSX_NMSUB))]
+   "VECTOR_UNIT_VSX_P (<MODE>mode)"
+   "@
+    x<VSv>nmsuba<VSs> %x0,%x1,%x2
+@@ -667,13 +768,13 @@ (define_insn "*vsx_ge<mode>"
+   [(set_attr "type" "<VStype_simple>")
+    (set_attr "fp_type" "<VSfptype_simple>")])
+ 
+-(define_insn "vsx_vsel<mode>"
+-  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
+-	(if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
++(define_insn "*vsx_vsel<mode>"
++  [(set (match_operand:VSX_L 0 "vsx_register_operand" "=<VSr>,?wa")
++	(if_then_else:VSX_L (ne (match_operand:VSX_L 1 "vsx_register_operand" "<VSr>,wa")
+ 				(const_int 0))
+-			    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")
+-			    (match_operand:VSX_F 3 "vsx_register_operand" "<VSr>,wa")))]
+-  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++			    (match_operand:VSX_L 2 "vsx_register_operand" "<VSr>,wa")
++			    (match_operand:VSX_L 3 "vsx_register_operand" "<VSr>,wa")))]
++  "VECTOR_MEM_VSX_P (<MODE>mode)"
+   "xxsel %x0,%x3,%x2,%x1"
+   [(set_attr "type" "vecperm")])
+ 
+@@ -698,7 +799,7 @@ (define_insn "vsx_ftrunc<mode>2"
+   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+   	(fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
+   "VECTOR_UNIT_VSX_P (<MODE>mode)"
+-  "x<VSv>r<VSs>piz %x0,%x1"
++  "x<VSv>r<VSs>iz %x0,%x1"
+   [(set_attr "type" "<VStype_simple>")
+    (set_attr "fp_type" "<VSfptype_simple>")])
+ 
+@@ -735,6 +836,24 @@ (define_insn "vsx_fixuns_trunc<mode><VSi
+    (set_attr "fp_type" "<VSfptype_simple>")])
+ 
+ ;; Math rounding functions
++(define_insn "vsx_x<VSv>r<VSs>i"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
++		      UNSPEC_VSX_ROUND_I))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>r<VSs>i %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
++
++(define_insn "vsx_x<VSv>r<VSs>ic"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
++		      UNSPEC_VSX_ROUND_IC))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>r<VSs>ic %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
++
+ (define_insn "vsx_btrunc<mode>2"
+   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
+ 	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
+@@ -765,22 +884,26 @@ (define_insn "vsx_ceil<mode>2"
+ 
+ ;; 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_<VS_spdp_insn>"
++  [(set (match_operand:<VS_spdp_res> 0 "vsx_register_operand" "=<VSr4>,?wa")
++	(unspec:<VS_spdp_res> [(match_operand:VSX_SPDP 1 "vsx_register_operand" "<VSr5>,wa")]
++			      UNSPEC_VSX_CVSPDP))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "<VS_spdp_insn> %x0,%x1"
++  [(set_attr "type" "<VS_spdp_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_and<mode>3"
+@@ -877,24 +1023,25 @@ (define_insn "*vsx_andc<mode>3"
+ 
+ ;; 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_<mode>"
++  [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,?wa")
++	(unspec:VSX_D
++	 [(match_operand:<VS_scalar> 1 "vsx_register_operand" "ws,wa")
++	  (match_operand:<VS_scalar> 2 "vsx_register_operand" "ws,wa")]
++	 UNSPEC_VSX_CONCAT))]
++  "VECTOR_MEM_VSX_P (<MODE>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_<mode>"
++  [(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:<VS_scalar> 2 "vsx_register_operand" "ws,wa")
++		       (match_operand:QI 3 "u5bit_cint_operand" "i,i")]
++		      UNSPEC_VSX_SET))]
++  "VECTOR_MEM_VSX_P (<MODE>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_<mode>"
++  [(set (match_operand:<VS_scalar> 0 "vsx_register_operand" "=ws,f,?wa")
++	(vec_select:<VS_scalar> (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>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_<mode>"
++  [(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>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_<mode>"
++  [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd")
++	(vec_concat:VSX_D
++	 (vec_select:<VS_scalar>
++	  (match_operand:VSX_D 1 "vsx_register_operand" "wd")
++	  (parallel
++	   [(match_operand:QI 2 "u5bit_cint_operand" "i")]))
++	 (vec_select:<VS_scalar>
++	  (match_operand:VSX_D 3 "vsx_register_operand" "wd")
++	  (parallel
++	   [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
++  "VECTOR_MEM_VSX_P (<MODE>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_<mode>"
++  [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
++	(vec_duplicate:VSX_D
++	 (match_operand:<VS_scalar> 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
++  "VECTOR_UNIT_VSX_P (<MODE>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_<mode>"
++  [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?wa")
++	(vec_duplicate:VSX_W
++	 (vec_select:<VS_scalar>
++	  (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>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_<mode>"
++  [(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>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_<mode>"
++  [(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>mode)"
+   "xxmrglw %x0,%x1,%x2"
+   [(set_attr "type" "vecperm")])
++
++;; Shift left double by word immediate
++(define_insn "vsx_xxsldwi_<mode>"
++  [(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>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<mode>"
+-  [(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>mode)
+    && (register_operand (operands[0], <MODE>mode) 
+        || register_operand (operands[1], <MODE>mode))"
+@@ -191,6 +194,31 @@ (define_insn "*altivec_mov<mode>"
+ }
+   [(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<mode>"
++(define_insn "*altivec_vsel<mode>"
+   [(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>mode)"
++  "VECTOR_MEM_ALTIVEC_P (<MODE>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<mode>"
+   [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))]
+@@ -14682,14 +14686,14 @@ (define_expand "tablejump"
+   [(use (match_operand 0 "" ""))
+    (use (label_ref (match_operand 1 "" "")))]
+   ""
+-  "
+ {
++  rs6000_set_indirect_jump ();
+   if (TARGET_32BIT)
+     emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+   else
+     emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+   DONE;
+-}")
++})
+ 
+ (define_expand "tablejumpsi"
+   [(set (match_dup 3)
+@@ -14749,6 +14753,11 @@ (define_expand "doloop_end"
+   /* Only use this on innermost loops.  */
+   if (INTVAL (operands[3]) > 1)
+     FAIL;
++  /* Do not try to use decrement and count on code that has an indirect
++     jump or a table jump, because the ctr register is preferred over the
++     lr register.  */
++  if (rs6000_has_indirect_jump_p ())
++    FAIL;
+   if (TARGET_64BIT)
+     {
+       if (GET_MODE (operands[0]) != DImode)
diff --git a/gcc44-power7.patch b/gcc44-power7.patch
index 42f8088..04c3d9c 100644
--- a/gcc44-power7.patch
+++ b/gcc44-power7.patch
@@ -1,3 +1,247 @@
+2009-04-08  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	* doc/invoke.texi (-mvsx-vector-memory): Make debug switches
+	undoucmented.
+	(-mvsx-vector-float): Ditto.
+	(-mvsx-vector-double): Ditto.
+	(-mvsx-scalar-double): Ditto.
+	(-mvsx-scalar-memory): Ditto.
+
+	* config/rs6000/vector.md (VEC_R): New iterator for reload
+	patterns.
+	(mov<mode>): Don't call rs6000_emit_move.
+	(reload_<VEC_R:mode>_<P:mptrsize>_*): New insns for
+	secondary_reload support.
+	(vec_reload_and_plus_<mptrsize>): New insns in case reload needs
+	to move a VSX/Altivec (and (plus reg reg) -16) type address to a
+	base register.
+
+	* config/rs6000/rs6000-protos.h (rs6000_secondary_reload_inner):
+	Rename from rs6000_vector_secondary_reload.
+
+	* config/rs6000/rs6000.opt (-mvsx-vector-memory): Make debug
+	switches undoucmented.
+	(-mvsx-vector-float): Ditto.
+	(-mvsx-vector-double): Ditto.
+	(-mvsx-scalar-double): Ditto.
+	(-mvsx-scalar-memory): Ditto.
+	(-mvsx-v4sf-altivec-regs): New undocumented debug switch to
+	control whether V4SF types prefer the Altivec registers or all of
+	the VSX registers.
+	(-mreload-functions): New undocumented debug switch to
+	enable/disable the secondary reload support.
+
+	* config/rs6000/rs6000.c (rs6000_regno_regclass): New global to
+	map register number to regclass.
+	(rs6000_vector_reload): New array to hold the secondary reload
+	insn codes for the vector types.
+	(rs6000_init_hard_regno_mode_ok): Fill in rs6000_regno_regclass
+	and rs6000_vector_reload.
+	(rs6000_mode_dependent_address): Using AND in addresses is mode
+	dependent.
+	(rs6000_emit_move): Add debug information if -mdebug=addr.
+	(rs6000_reload_register_type): Classify register classes for
+	secondary reload.
+	(rs6000_secondary_reload): For the vector types, add reload
+	support to support reg+reg addressing for gprs, and reg+offset
+	addressing for vector registers.
+	(rs6000_secondary_reload_inner): Rename from
+	rs6000_vector_secondary_reload.  Fixup gpr addressing to just reg
+	or reg+offset, and vector addressing to just reg or reg+reg.
+	(rs6000_preferred_reload_class): Make sure all cases set the
+	return value.  If VSX/Altivec address with AND -16, prefer using
+	an Altivec register.
+	(rs6000_secondary_memory_needed): Handle things like SFmode that
+	can go in floating registers, but not altivec registers under
+	-mvsx.
+
+	* config/rs6000/vsx.md (VSX_U): New iterator for load/store with
+	update.
+	(VSi, VSI): Reorder fields.
+	(VSd): Add support for load/store with update rewrite.
+	(VSv): Ditto.
+	(VStype_load_update): New mode attribute for load/store with
+	update.
+	(VStype_store_update): Ditto.
+	(vsx_mov<type>): Use * instead of store/load attributes for
+	multi-instruction gpr loads/stores.
+	(vsx_reload**): Delete unused reload patterns.
+
+	* config/rs6000/rs6000.h (REGNO_REG_CLASS): Change from a bunch of
+	if statements to using a lookup table.
+	(rs6000_regno_regclass): Lookup table for REGNO_REG_CLASS.
+
+	* config/rs6000/altivec.md (altivec_reload*): Delete unused reload
+	patterns.
+
+	* config/rs6000/rs6000.md (tptrsize, mptrsize): New mode
+	attributes for -m32/-m64 support.
+
+2009-03-27  Jakub Jelinek  <jakub at redhat.com>
+
+	PR target/39558
+	* macro.c (cpp_get_token): If macro_to_expand returns NULL
+	and used some tokens, add CPP_PADDING before next token.
+
+	* gcc.target/powerpc/altivec-29.c: New test.
+
+2009-03-27  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	* config/rs6000/constraints.md ("wZ" constraint): New constraint
+	for using Altivec loads/stores under VSX for vector realignment.
+
+	* config/rs6000/predicates.md
+	(altivec_indexed_or_indirect_operand): New predicate to recognize
+	Altivec load/stores with an explicit AND -16.
+
+	* config/rs6000/power7.md: Whitespace change.
+
+	* config/rs6000/rs6000.opt (-mpower7-adjust-cost): New debug
+	switch.
+
+	* config/rs6000/rs6000-c.c (altivec_categorize_keyword): If -mvsx
+	and -mno-altivec, recognize the 'vector' keyword, but do not
+	recognize 'bool' or 'pixel'.  Recognize vector double under VSX.
+	(init_vector_keywords): Ditto.
+	(rs6000_macro_to_expand): Ditto.
+	(altivec_overloaded_builtins): Add VSX overloaded builtins.
+	(altivec_resolve_overloaded_builtin): Ditto.
+
+	* config/rs6000/rs6000.c (rs6000_debug_cost): New global for
+	-mdebug=cost.
+	(rs6000_debug_address_cost): New function for printing costs if
+	-mdebug=cost.
+	(rs6000_debug_rtx_costs): Ditto.
+	(rs6000_debug_adjust_cost): Ditto.
+	(rs6000_override_options): Add -mdebug=cost support.
+	(rs6000_legitimize_reload_address): Allow Altivec loads and stores
+	with an explicit AND -16, in VSX for vector realignment.
+	(rs6000_legitimize_reload_address): Ditto.
+	(rs6000_legitimate_address): Ditto.
+	(print_operand): Ditto.
+	(bdesc_3arg): Add VSX builtins.
+	(bdesc_2arg): Ditto.
+	(bdesc_1arg): Ditto.
+	(bdesc_abs): Ditto.
+	(vsx_expand_builtin): Stub function for expanding VSX builtins.
+	(rs6000_expand_builtin): Call vsx_expand_builtin.
+
+	* config/rs6000/vsx.md (most DF insns): Merge DF insns in with
+	V2DF and V4SF insns, rather than duplicating much of the code.
+	(all insns): Go through all insns, and alternatives to address the
+	full VSX register set, as a non-preferred option.
+	(vsx_mod<mode>): Add support for using Altivec load/store with
+	explicit AND -16.  Use xxlor to copy registers, not copy sign.
+	(multiply/add insns): Add an expander and unspec so the insn can
+	be used directly even if -mno-fused-madd.
+	(vsx_tdiv<mode>3): New insn for use as a builtin function.
+	(vsx_tsqrt<mode>2): Ditto.
+	(vsx_rsqrte<mode>2): Ditto.
+
+	* config/rs6000/rs6000.h (rs6000_debug_cost): New for
+	-mdebug=cost.
+	(TARGET_DEBUG_COST): Ditto.
+	(VSX_BUILTIN_*): Merge the two forms of multiply/add instructions
+	into a single insn.  Start to add overloaded VSX builtins.
+
+	* config/rs6000/altivec.md (build_vector_mask_for_load): Delete
+	VSX code.
+
+	* config/rs6000/rs6000.md (btruncsf2): Delete extra space.
+	(movdf_hardfloat32): Use xxlor instead of xscpsgndp to copy data.
+	(movdf_hardfloat64_mfpgpr): Ditto.
+	(movdf_hardfloat64): Ditto.
+
+2009-03-13  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	PR target/39457
+	* config/rs6000/rs6000.opt (-mdisallow-float-in-lr-ctr): Add
+	temporary debug switch.
+
+	* config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Revert
+	behavior of disallowing 
+
+2009-03-13  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	* config/rs6000/vector.md (vec_extract_evenv2df): Delete, insn
+	causes problems in building spec 2006.
+	(vec_extract_oddv2df): Ditto.
+	(vec_pack_trunc_v2df): New expanders for VSX vectorized
+	conversions.
+	(vec_pack_sfix_trunc_v2df): Ditto.
+	(vec_pack_ufix_trunc_v2df): Ditto.
+	(vec_unpacks_hi_v4sf): Ditto.
+	(vec_unpacks_lo_v4sf): Ditto.
+	(vec_unpacks_float_hi_v4si): Ditto.
+	(vec_unpacks_float_lo_v4si): Ditto.
+	(vec_unpacku_float_hi_v4si): Ditto.
+	(vec_unpacku_float_lo_v4si): Ditto.
+
+	* config/rs6000/rs6000-protos.h (rs6000_vector_secondary_reload):
+	Declaration for new target hook.
+
+	* config/rs6000/rs6000.c (TARGET_SECONDARY_RELOAD): Add new target
+	hook for eventually fixing up the memory references for Altivec
+	and VSX reloads to be reg+reg instead of reg+offset.  Right now,
+	this is a stub function that prints debug information if
+	-mdebug=addr and then calls default_secondary_reload.
+	(rs6000_secondary_reload): Ditto.
+	(rs6000_vector_secondary_reload): Ditto.
+	(rs6000_builtin_conversion): Add support for V2DI/V2DF
+	conversions.
+	(rs6000_legitimate_offset_address_p): Test for the vector unit
+	doing the memory references.
+	(rs6000_legimize_reload_address): Ditto.
+	(rs6000_legitimize_address): Print extra \n if -mdebug=addr.
+	(rs6000_legitimize_reload_address): Ditto.
+	(rs6000_legitimate_address): Ditto.
+	(rs6000_mode_dependent_address): Ditto.
+	(bdesc_2arg): Add VSX builtins.
+	(bdesc_abs): Ditto.
+	(bdesc_1arg): Ditto.
+	(altivec_init_builtins): Ditto.
+	(rs6000_secondary_memory_needed_rtx): Add debug support if
+	-mdebug=addr.
+	(rs6000_preferred_reload_class): Ditto.
+	(rs6000_secondary_memory_needed): Ditto.
+	(rs6000_secondary_reload_class): Ditto.
+	(rs6000_cannot_change_mode_class): Ditto.
+
+	* config/rs6000/vsx.md (UNSPEC_VSX_*): Add unspecs for VSX
+	conversions.
+	(vsx_nabs<mode>): Add generator function.
+	(vsx_float<VSi><mode>2): Ditto.
+	(vsx_floatuns<VSi><mode>2): Ditto.
+	(vsx_xxmrghw): Ditto.
+	(vsx_xxmrglw): Ditto.
+	(vsx_xvcvdpsp): New VSX vector conversion insn.
+	(vsx_xvcvdpsxws): Ditto.
+	(vsx_xvcvdpuxws): Ditto.
+	(vsx_xvcvspdp): Ditto.
+	(vsx_xvcvsxwdp): Ditto.
+	(vsx_xvcvuxwdp): Ditto.
+	(vsx_reload_*): New insns for reload support.
+
+	* config/rs6000/rs6000.h: Fix a comment.
+
+	* config/rs6000/altivec.md (altivec_reload_*): New insns for
+	reload support.
+
+	* config/rs6000/rs6000.md (ptrsize): New mode attribute for the
+	pointer size.
+
+2009-03-10  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	* config/rs6000/vsx.md (vsx_concat_v2df): Add explicit 'f'
+	register class for scalar data, correct uses of the xxpermdi
+	instruction.
+	(vsx_set_v2df): Ditto.
+	(vsx_extract_v2df): Ditto.
+	(vsx_xxpermdi): Ditto.
+	(vsx_splatv2df): Ditto.
+	(vsx_xxmrghw): Use wf instead of v constraints.
+	(vsx_xxmrglw): Ditto.
+
 2009-03-09  Michael Meissner  <meissner at linux.vnet.ibm.com>
 
 	* config/rs6000/vsx.md (vsx_store<mode>_update64): Use correct
@@ -868,7 +1112,27 @@
 	(popcntwsi2): Add popcntw support.
 	(popcntddi2): Add popcntd support.
 
-testsuite/
+2009-03-27  Jakub Jelinek  <jakub at redhat.com>
+
+	PR target/39558
+	* gcc.target/powerpc/altivec-29.c: New test.
+
+2009-03-27  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	* gcc.target/powerpc/vsx-builtin-1.c: Add more VSX builtins.
+	Prevent the optimizer from combining the various multiplies.
+	* gcc.target/powerpc/vsx-builtin-2.c: Ditto.
+
+2009-03-13  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	PR target/39457
+	* gcc.target/powerpc/pr39457.c: New test for PR39457.
+
+2009-03-13  Michael Meissner  <meissner at linux.vnet.ibm.com>
+
+	* gcc.target/powerpc/vsx-builtin-1.c: New test for builtins.
+	* gcc.target/powerpc/vsx-builtin-2.c: Ditto.
+
 2009-03-01  Michael Meissner  <meissner at linux.vnet.ibm.com>
 
 	* gcc.target/powerpc/vsx-vector-1.c: Fix typos.
@@ -899,9 +1163,9 @@ testsuite/
 	* gcc.target/powerpc/popcount-2.c: New file for power7 support.
 	* gcc.target/powerpc/popcount-3.c: Ditto.
 
---- gcc/doc/invoke.texi	(.../trunk)	(revision 144557)
-+++ gcc/doc/invoke.texi	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -712,7 +712,8 @@ See RS/6000 and PowerPC Options.
+--- gcc/doc/invoke.texi	(.../trunk)	(revision 145777)
++++ gcc/doc/invoke.texi	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -715,7 +715,8 @@ See RS/6000 and PowerPC Options.
  -maltivec  -mno-altivec @gol
  -mpowerpc-gpopt  -mno-powerpc-gpopt @gol
  -mpowerpc-gfxopt  -mno-powerpc-gfxopt @gol
@@ -911,18 +1175,16 @@ testsuite/
  -mcmpb -mno-cmpb -mmfpgpr -mno-mfpgpr -mhard-dfp -mno-hard-dfp @gol
  -mnew-mnemonics  -mold-mnemonics @gol
  -mfull-toc   -mminimal-toc  -mno-fp-in-toc  -mno-sum-in-toc @gol
-@@ -726,7 +727,9 @@ See RS/6000 and PowerPC Options.
+@@ -729,7 +730,7 @@ See RS/6000 and PowerPC Options.
  -mstrict-align  -mno-strict-align  -mrelocatable @gol
  -mno-relocatable  -mrelocatable-lib  -mno-relocatable-lib @gol
  -mtoc  -mno-toc  -mlittle  -mlittle-endian  -mbig  -mbig-endian @gol
 --mdynamic-no-pic  -maltivec  -mswdiv @gol
-+-mdynamic-no-pic  -maltivec -mswdiv -mvsx -mvsx-vector-memory @gol
-+-mvsx-vector-float -mvsx-vector-double @gol
-+-mvsx-scalar-double -mvsx-scalar-memory @gol
++-mdynamic-no-pic  -maltivec -mswdiv @gol
  -mprioritize-restricted-insns=@var{priority} @gol
  -msched-costly-dep=@var{dependence_type} @gol
  -minsert-sched-nops=@var{scheme} @gol
-@@ -13512,6 +13515,8 @@ These @samp{-m} options are defined for 
+@@ -13614,6 +13615,8 @@ These @samp{-m} options are defined for 
  @itemx -mno-mfcrf
  @itemx -mpopcntb
  @itemx -mno-popcntb
@@ -931,7 +1193,7 @@ testsuite/
  @itemx -mfprnd
  @itemx -mno-fprnd
  @itemx -mcmpb
-@@ -13536,6 +13541,8 @@ These @samp{-m} options are defined for 
+@@ -13638,6 +13641,8 @@ These @samp{-m} options are defined for 
  @opindex mno-mfcrf
  @opindex mpopcntb
  @opindex mno-popcntb
@@ -940,7 +1202,7 @@ testsuite/
  @opindex mfprnd
  @opindex mno-fprnd
  @opindex mcmpb
-@@ -13585,6 +13592,9 @@ The @option{-mpopcntb} option allows GCC
+@@ -13687,6 +13692,9 @@ The @option{-mpopcntb} option allows GCC
  double precision FP reciprocal estimate instruction implemented on the
  POWER5 processor and other processors that support the PowerPC V2.02
  architecture.
@@ -950,7 +1212,7 @@ testsuite/
  The @option{-mfprnd} option allows GCC to generate the FP round to
  integer instructions implemented on the POWER5+ processor and other
  processors that support the PowerPC V2.03 architecture.
-@@ -13663,9 +13673,9 @@ The @option{-mcpu} options automatically
+@@ -13765,9 +13773,9 @@ The @option{-mcpu} options automatically
  following options:
  
  @gccoptlist{-maltivec  -mfprnd  -mhard-float  -mmfcrf  -mmultiple @gol
@@ -962,7 +1224,7 @@ testsuite/
  
  The particular options set for any particular CPU will vary between
  compiler versions, depending on what setting seems to produce optimal
-@@ -13766,6 +13776,44 @@ instructions.
+@@ -13868,6 +13876,14 @@ instructions.
  This option has been deprecated.  Use @option{-mspe} and
  @option{-mno-spe} instead.
  
@@ -974,42 +1236,12 @@ testsuite/
 +instructions, and also enable the use of built-in functions that allow
 +more direct access to the VSX instruction set.
 +
-+ at item -mvsx-vector-memory
-+ at itemx -mno-vsx-vector-memory
-+If @option{-mvsx}, use VSX memory reference instructions for vectors
-+instead of the Altivec instructions This option is a temporary switch
-+to tune the compiler, and may not be supported in future versions.
-+
-+ at item -mvsx-vector-float
-+ at itemx -mno-vsx-vector-float
-+If @option{-mvsx}, use VSX arithmetic instructions for float vectors.
-+This option is a temporary switch to tune the compiler, and may not be
-+supported in future versions.
-+
-+ at item -mvsx-vector-double
-+ at itemx -mno-vsx-vector-double
-+If @option{-mvsx}, use VSX arithmetic instructions for double
-+vectors.  This option is a temporary switch to tune the
-+compiler, and may not be supported in future versions.
-+
-+ at item -mvsx-scalar-double
-+ at itemx -mno-vsx-scalar-double
-+If @option{-mvsx}, use VSX arithmetic instructions for scalar double.
-+This option is a temporary switch to tune the compiler, and may not be
-+supported in future versions.
-+
-+ at item -mvsx-scalar-memory
-+ at itemx -mno-vsx-scalar-memory
-+If @option{-mvsx}, use VSX memory reference instructions for scalar
-+double.  This option is a temporary switch to tune the compiler, and
-+may not be supported in future versions.
-+
  @item -mfloat-gprs=@var{yes/single/double/no}
  @itemx -mfloat-gprs
  @opindex mfloat-gprs
---- gcc/doc/md.texi	(.../trunk)	(revision 144557)
-+++ gcc/doc/md.texi	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -1905,7 +1905,19 @@ Address base register
+--- gcc/doc/md.texi	(.../trunk)	(revision 145777)
++++ gcc/doc/md.texi	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -1913,7 +1913,19 @@ Address base register
  Floating point register
  
  @item v
@@ -1030,7 +1262,7 @@ testsuite/
  
  @item h
  @samp{MQ}, @samp{CTR}, or @samp{LINK} register
-@@ -1991,6 +2003,9 @@ AND masks that can be performed by two r
+@@ -1999,6 +2011,9 @@ AND masks that can be performed by two r
  @item W
  Vector constant that does not require memory
  
@@ -1040,8 +1272,8 @@ testsuite/
  @end table
  
  @item Intel 386--- at file{config/i386/constraints.md}
---- gcc/reload.c	(.../trunk)	(revision 144557)
-+++ gcc/reload.c	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/reload.c	(.../trunk)	(revision 145777)
++++ gcc/reload.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -6255,8 +6255,14 @@ subst_reloads (rtx insn)
  	    *r->where = reloadreg;
  	}
@@ -1059,8 +1291,144 @@ testsuite/
      }
  }
  
+--- gcc/configure	(.../trunk)	(revision 145777)
++++ gcc/configure	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -23075,7 +23075,7 @@ if test "${gcc_cv_as_powerpc_mfpgpr+set}
+ else
+   gcc_cv_as_powerpc_mfpgpr=no
+     if test $in_tree_gas = yes; then
+-    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+   then gcc_cv_as_powerpc_mfpgpr=yes
+ fi
+   elif test x$gcc_cv_as != x; then
+@@ -23171,7 +23171,7 @@ if test "${gcc_cv_as_powerpc_cmpb+set}" 
+ else
+   gcc_cv_as_powerpc_cmpb=no
+     if test $in_tree_gas = yes; then
+-    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+   then gcc_cv_as_powerpc_cmpb=yes
+ fi
+   elif test x$gcc_cv_as != x; then
+@@ -23217,7 +23217,7 @@ if test "${gcc_cv_as_powerpc_dfp+set}" =
+ else
+   gcc_cv_as_powerpc_dfp=no
+     if test $in_tree_gas = yes; then
+-    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+   then gcc_cv_as_powerpc_dfp=yes
+ fi
+   elif test x$gcc_cv_as != x; then
+@@ -23263,7 +23263,7 @@ if test "${gcc_cv_as_powerpc_vsx+set}" =
+ else
+   gcc_cv_as_powerpc_vsx=no
+     if test $in_tree_gas = yes; then
+-    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
++    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
+   then gcc_cv_as_powerpc_vsx=yes
+ fi
+   elif test x$gcc_cv_as != x; then
+@@ -23293,6 +23293,52 @@ _ACEOF
+ 
+ fi
+ 
++    case $target in
++      *-*-aix*) conftest_s='	.machine "pwr7"
++	.csect .text[PR]
++	popcntd 3,3';;
++      *) conftest_s='	.machine power7
++	.text
++	popcntd 3,3';;
++    esac
++
++    echo "$as_me:$LINENO: checking assembler for popcntd support" >&5
++echo $ECHO_N "checking assembler for popcntd support... $ECHO_C" >&6
++if test "${gcc_cv_as_powerpc_popcntd+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  gcc_cv_as_powerpc_popcntd=no
++    if test $in_tree_gas = yes; then
++    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
++  then gcc_cv_as_powerpc_popcntd=yes
++fi
++  elif test x$gcc_cv_as != x; then
++    echo "$conftest_s" > conftest.s
++    if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }
++    then
++	gcc_cv_as_powerpc_popcntd=yes
++    else
++      echo "configure: failed program was" >&5
++      cat conftest.s >&5
++    fi
++    rm -f conftest.o conftest.s
++  fi
++fi
++echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntd" >&5
++echo "${ECHO_T}$gcc_cv_as_powerpc_popcntd" >&6
++if test $gcc_cv_as_powerpc_popcntd = yes; then
++
++cat >>confdefs.h <<\_ACEOF
++#define HAVE_AS_POPCNTD 1
++_ACEOF
++
++fi
++
+     echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5
+ echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6
+ if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then
+--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c	(.../trunk)	(revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-2.c	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -0,0 +1,42 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_vsx_ok } */
++/* { dg-options "-O2 -mcpu=power7" } */
++/* { dg-final { scan-assembler "xvaddsp" } } */
++/* { dg-final { scan-assembler "xvsubsp" } } */
++/* { dg-final { scan-assembler "xvmulsp" } } */
++/* { dg-final { scan-assembler "xvmadd" } } */
++/* { dg-final { scan-assembler "xvmsub" } } */
++/* { dg-final { scan-assembler "xvnmadd" } } */
++/* { dg-final { scan-assembler "xvnmsub" } } */
++/* { dg-final { scan-assembler "xvdivsp" } } */
++/* { dg-final { scan-assembler "xvmaxsp" } } */
++/* { dg-final { scan-assembler "xvminsp" } } */
++/* { dg-final { scan-assembler "xvsqrtsp" } } */
++/* { dg-final { scan-assembler "xvabssp" } } */
++/* { dg-final { scan-assembler "xvnabssp" } } */
++/* { dg-final { scan-assembler "xvresp" } } */
++/* { dg-final { scan-assembler "xvrsqrtesp" } } */
++/* { dg-final { scan-assembler "xvtsqrtsp" } } */
++/* { dg-final { scan-assembler "xvtdivsp" } } */
++
++void use_builtins (__vector float *p, __vector float *q, __vector float *r, __vector float *s)
++{
++  p[0] = __builtin_vsx_xvaddsp (q[0], r[0]);
++  p[1] = __builtin_vsx_xvsubsp (q[1], r[1]);
++  p[2] = __builtin_vsx_xvmulsp (q[2], r[2]);
++  p[3] = __builtin_vsx_xvdivsp (q[3], r[3]);
++  p[4] = __builtin_vsx_xvmaxsp (q[4], r[4]);
++  p[5] = __builtin_vsx_xvminsp (q[5], r[5]);
++  p[6] = __builtin_vsx_xvabssp (q[6]);
++  p[7] = __builtin_vsx_xvnabssp (q[7]);
++  p[8] = __builtin_vsx_xvsqrtsp (q[8]);
++  p[9] = __builtin_vsx_xvmaddsp (q[9], r[9], s[9]);
++  p[10] = __builtin_vsx_xvmsubsp (q[10], r[10], s[10]);
++  p[11] = __builtin_vsx_xvnmaddsp (q[11], r[11], s[11]);
++  p[12] = __builtin_vsx_xvnmsubsp (q[12], r[12], s[12]);
++  p[13] = __builtin_vsx_xvresp (q[13]);
++  p[14] = __builtin_vsx_xvrsqrtesp (q[14]);
++  p[15] = __builtin_vsx_xvtsqrtsp (q[15]);
++  p[16] = __builtin_vsx_xvtdivsp (q[16], r[16]);
++}
 --- gcc/testsuite/gcc.target/powerpc/popcount-3.c	(.../trunk)	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/popcount-3.c	(.../branches/ibm/power7-meissner)	(revision 144730)
++++ gcc/testsuite/gcc.target/powerpc/popcount-3.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -0,0 +1,9 @@
 +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
 +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
@@ -1072,7 +1440,7 @@ testsuite/
 +  return __builtin_popcountl(x);
 +}
 --- gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c	(.../trunk)	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c	(.../branches/ibm/power7-meissner)	(revision 144730)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-1.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -0,0 +1,74 @@
 +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
 +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
@@ -1149,7 +1517,7 @@ testsuite/
 +    a[i] = b[i] / c[i];
 +}
 --- gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c	(.../trunk)	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c	(.../branches/ibm/power7-meissner)	(revision 144730)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-2.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -0,0 +1,74 @@
 +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
 +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
@@ -1225,8 +1593,67 @@ testsuite/
 +  for (i = 0; i < SIZE; i++)
 +    a[i] = b[i] / c[i];
 +}
+--- gcc/testsuite/gcc.target/powerpc/pr39457.c	(.../trunk)	(revision 0)
++++ gcc/testsuite/gcc.target/powerpc/pr39457.c	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -0,0 +1,56 @@
++/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
++/* { dg-options "-m64 -O2 -mminimal-toc" } */
++
++/* PR 39457 -- fix breakage because the compiler ran out of registers and
++   wanted to stash a floating point value to the LR/CTR register.  */
++
++/* -O2 -m64 -mminimal-toc */
++typedef struct { void *s; } S;
++typedef void (*T1) (void);
++typedef void (*T2) (void *, void *, int, void *);
++char *fn1 (const char *, ...);
++void *fn2 (void);
++int fn3 (char *, int);
++int fn4 (const void *);
++int fn5 (const void *);
++long fn6 (void) __attribute__ ((__const__));
++int fn7 (void *, void *, void *);
++void *fn8 (void *, long);
++void *fn9 (void *, long, const char *, ...);
++void *fn10 (void *);
++long fn11 (void) __attribute__ ((__const__));
++long fn12 (void *, const char *, T1, T2, void *);
++void *fn13 (void *);
++long fn14 (void) __attribute__ ((__const__));
++extern void *v1;
++extern char *v2;
++extern int v3;
++
++void
++foo (void *x, char *z)
++{
++  void *i1, *i2;
++  int y;
++  if (v1)
++    return;
++  v1 = fn9 (fn10 (fn2 ()), fn6 (), "x", 0., "y", 0., 0);
++  y = 520 - (520 - fn4 (x)) / 2;
++  fn9 (fn8 (v1, fn6 ()), fn6 (), "wig", fn8 (v1, fn14 ()), "x", 18.0,
++       "y", 16.0, "wid", 80.0, "hi", 500.0, 0);
++  fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 80.0, "y2",
++       500.0, "f", fn3 ("fff", 0x0D0DFA00), 0);
++  fn13 (((S *) fn8 (v1, fn6 ()))->s);
++  fn12 (fn8 (v1, fn11 ()), "ev", (T1) fn7, 0, fn8 (v1, fn6 ()));
++  fn9 (fn8 (v1, fn6 ()), fn6 (), "wig",
++       fn8 (v1, fn14 ()), "x", 111.0, "y", 14.0, "wid", 774.0, "hi",
++       500.0, 0);
++  v1 = fn9 (fn10 (v1), fn6 (), "x1", 0., "y1", 0., "x2", 774.0, "y2",
++            500.0, "f", fn3 ("gc", 0x0D0DFA00), 0);
++  fn1 (z, 0);
++  i1 = fn9 (fn8 (v1, fn6 ()), fn6 (), "pixbuf", x, "x",
++            800 - fn5 (x) / 2, "y", y - fn4 (x), 0);
++  fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, "/ok/");
++  fn12 (fn8 (i1, fn11 ()), "ev", (T1) fn7, 0, 0);
++  i2 = fn9 (fn8 (v1, fn6 ()), fn6 (), "txt", "OK", "fnt", v2, "x",
++            800, "y", y - fn4 (x) + 15, "ar", 0, "f", v3, 0);
++}
 --- gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c	(.../trunk)	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c	(.../branches/ibm/power7-meissner)	(revision 144730)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-3.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -0,0 +1,48 @@
 +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
 +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
@@ -1276,8 +1703,53 @@ testsuite/
 +{
 +  a = b / c;
 +}
+--- gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c	(.../trunk)	(revision 0)
++++ gcc/testsuite/gcc.target/powerpc/vsx-builtin-1.c	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -0,0 +1,42 @@
++/* { dg-do compile { target { powerpc*-*-* } } } */
++/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
++/* { dg-require-effective-target powerpc_vsx_ok } */
++/* { dg-options "-O2 -mcpu=power7" } */
++/* { dg-final { scan-assembler "xvadddp" } } */
++/* { dg-final { scan-assembler "xvsubdp" } } */
++/* { dg-final { scan-assembler "xvmuldp" } } */
++/* { dg-final { scan-assembler "xvmadd" } } */
++/* { dg-final { scan-assembler "xvmsub" } } */
++/* { dg-final { scan-assembler "xvnmadd" } } */
++/* { dg-final { scan-assembler "xvnmsub" } } */
++/* { dg-final { scan-assembler "xvdivdp" } } */
++/* { dg-final { scan-assembler "xvmaxdp" } } */
++/* { dg-final { scan-assembler "xvmindp" } } */
++/* { dg-final { scan-assembler "xvsqrtdp" } } */
++/* { dg-final { scan-assembler "xvrsqrtedp" } } */
++/* { dg-final { scan-assembler "xvtsqrtdp" } } */
++/* { dg-final { scan-assembler "xvabsdp" } } */
++/* { dg-final { scan-assembler "xvnabsdp" } } */
++/* { dg-final { scan-assembler "xvredp" } } */
++/* { dg-final { scan-assembler "xvtdivdp" } } */
++
++void use_builtins (__vector double *p, __vector double *q, __vector double *r, __vector double *s)
++{
++  p[0] = __builtin_vsx_xvadddp (q[0], r[0]);
++  p[1] = __builtin_vsx_xvsubdp (q[1], r[1]);
++  p[2] = __builtin_vsx_xvmuldp (q[2], r[2]);
++  p[3] = __builtin_vsx_xvdivdp (q[3], r[3]);
++  p[4] = __builtin_vsx_xvmaxdp (q[4], r[4]);
++  p[5] = __builtin_vsx_xvmindp (q[5], r[5]);
++  p[6] = __builtin_vsx_xvabsdp (q[6]);
++  p[7] = __builtin_vsx_xvnabsdp (q[7]);
++  p[8] = __builtin_vsx_xvsqrtdp (q[8]);
++  p[9] = __builtin_vsx_xvmadddp (q[9], r[9], s[9]);
++  p[10] = __builtin_vsx_xvmsubdp (q[10], r[10], s[10]);
++  p[11] = __builtin_vsx_xvnmadddp (q[11], r[11], s[11]);
++  p[12] = __builtin_vsx_xvnmsubdp (q[12], r[12], s[12]);
++  p[13] = __builtin_vsx_xvredp (q[13]);
++  p[14] = __builtin_vsx_xvrsqrtedp (q[14]);
++  p[15] = __builtin_vsx_xvtsqrtdp (q[15]);
++  p[16] = __builtin_vsx_xvtdivdp (q[16], r[16]);
++}
 --- gcc/testsuite/gcc.target/powerpc/popcount-2.c	(.../trunk)	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/popcount-2.c	(.../branches/ibm/power7-meissner)	(revision 144730)
++++ gcc/testsuite/gcc.target/powerpc/popcount-2.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -0,0 +1,9 @@
 +/* { dg-do compile { target { ilp32 } } } */
 +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
@@ -1289,7 +1761,7 @@ testsuite/
 +  return __builtin_popcount(x);
 +}
 --- gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c	(.../trunk)	(revision 0)
-+++ gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c	(.../branches/ibm/power7-meissner)	(revision 144730)
++++ gcc/testsuite/gcc.target/powerpc/vsx-vector-4.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -0,0 +1,48 @@
 +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
 +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
@@ -1339,8 +1811,8 @@ testsuite/
 +{
 +  a = b / c;
 +}
---- gcc/testsuite/gcc.dg/vmx/vmx.exp	(.../trunk)	(revision 144557)
-+++ gcc/testsuite/gcc.dg/vmx/vmx.exp	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/testsuite/gcc.dg/vmx/vmx.exp	(.../trunk)	(revision 145777)
++++ gcc/testsuite/gcc.dg/vmx/vmx.exp	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -31,7 +31,7 @@ if {![istarget powerpc*-*-*]
  # nothing but extensions.
  global DEFAULT_VMXCFLAGS
@@ -1350,8 +1822,8 @@ testsuite/
  }
  
  # If the target system supports AltiVec instructions, the default action
---- gcc/testsuite/lib/target-supports.exp	(.../trunk)	(revision 144557)
-+++ gcc/testsuite/lib/target-supports.exp	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/testsuite/lib/target-supports.exp	(.../trunk)	(revision 145777)
++++ gcc/testsuite/lib/target-supports.exp	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -873,6 +873,32 @@ proc check_sse2_hw_available { } {
      }]
  }
@@ -1436,9 +1908,9 @@ testsuite/
  # Return 1 if this is a PowerPC target supporting -mcpu=cell.
  
  proc check_effective_target_powerpc_ppu_ok { } {
---- gcc/config.in	(.../trunk)	(revision 144557)
-+++ gcc/config.in	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -334,12 +334,18 @@
+--- gcc/config.in	(.../trunk)	(revision 145777)
++++ gcc/config.in	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -327,12 +327,18 @@
  #endif
  
  
@@ -1458,18 +1930,9 @@ testsuite/
  /* Define if your assembler supports .register. */
  #ifndef USED_FOR_TARGET
  #undef HAVE_AS_REGISTER_PSEUDO_OP
---- gcc/configure.ac	(.../trunk)	(revision 144557)
-+++ gcc/configure.ac	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -2,7 +2,7 @@
- # Process this file with autoconf to generate a configuration script.
- 
- # Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
--# 2007, 2008 Free Software Foundation, Inc.
-+# 2007, 2008, 2009 Free Software Foundation, Inc.
- 
- #This file is part of GCC.
- 
-@@ -3080,7 +3080,7 @@ foo:	nop
+--- gcc/configure.ac	(.../trunk)	(revision 145777)
++++ gcc/configure.ac	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -3054,7 +3054,7 @@ foo:	nop
      esac
  
      gcc_GAS_CHECK_FEATURE([move fp gpr support],
@@ -1478,7 +1941,7 @@ testsuite/
        [$conftest_s],,
        [AC_DEFINE(HAVE_AS_MFPGPR, 1,
  	  [Define if your assembler supports mffgpr and mftgpr.])])
-@@ -3114,7 +3114,7 @@ LCF0:
+@@ -3088,7 +3088,7 @@ LCF0:
      esac
  
      gcc_GAS_CHECK_FEATURE([compare bytes support],
@@ -1487,7 +1950,7 @@ testsuite/
        [$conftest_s],,
        [AC_DEFINE(HAVE_AS_CMPB, 1,
  	  [Define if your assembler supports cmpb.])])
-@@ -3129,7 +3129,7 @@ LCF0:
+@@ -3103,7 +3103,7 @@ LCF0:
      esac
  
      gcc_GAS_CHECK_FEATURE([decimal float support],
@@ -1496,7 +1959,7 @@ testsuite/
        [$conftest_s],,
        [AC_DEFINE(HAVE_AS_DFP, 1,
  	  [Define if your assembler supports DFP instructions.])])
-@@ -3144,11 +3144,26 @@ LCF0:
+@@ -3118,11 +3118,26 @@ LCF0:
      esac
  
      gcc_GAS_CHECK_FEATURE([vector-scalar support],
@@ -1524,99 +1987,8 @@ testsuite/
      gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
        gcc_cv_as_powerpc_gnu_attribute, [2,18,0],,
        [.gnu_attribute 4,1],,
---- gcc/configure	(.../trunk)	(revision 144557)
-+++ gcc/configure	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -23225,7 +23225,7 @@ if test "${gcc_cv_as_powerpc_mfpgpr+set}
- else
-   gcc_cv_as_powerpc_mfpgpr=no
-     if test $in_tree_gas = yes; then
--    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
-+    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
-   then gcc_cv_as_powerpc_mfpgpr=yes
- fi
-   elif test x$gcc_cv_as != x; then
-@@ -23321,7 +23321,7 @@ if test "${gcc_cv_as_powerpc_cmpb+set}" 
- else
-   gcc_cv_as_powerpc_cmpb=no
-     if test $in_tree_gas = yes; then
--    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
-+    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
-   then gcc_cv_as_powerpc_cmpb=yes
- fi
-   elif test x$gcc_cv_as != x; then
-@@ -23367,7 +23367,7 @@ if test "${gcc_cv_as_powerpc_dfp+set}" =
- else
-   gcc_cv_as_powerpc_dfp=no
-     if test $in_tree_gas = yes; then
--    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
-+    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
-   then gcc_cv_as_powerpc_dfp=yes
- fi
-   elif test x$gcc_cv_as != x; then
-@@ -23413,7 +23413,7 @@ if test "${gcc_cv_as_powerpc_vsx+set}" =
- else
-   gcc_cv_as_powerpc_vsx=no
-     if test $in_tree_gas = yes; then
--    if test $gcc_cv_gas_vers -ge `expr \( \( 9 \* 1000 \) + 99 \) \* 1000 + 0`
-+    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
-   then gcc_cv_as_powerpc_vsx=yes
- fi
-   elif test x$gcc_cv_as != x; then
-@@ -23443,6 +23443,52 @@ _ACEOF
- 
- fi
- 
-+    case $target in
-+      *-*-aix*) conftest_s='	.machine "pwr7"
-+	.csect .text[PR]
-+	popcntd 3,3';;
-+      *) conftest_s='	.machine power7
-+	.text
-+	popcntd 3,3';;
-+    esac
-+
-+    echo "$as_me:$LINENO: checking assembler for popcntd support" >&5
-+echo $ECHO_N "checking assembler for popcntd support... $ECHO_C" >&6
-+if test "${gcc_cv_as_powerpc_popcntd+set}" = set; then
-+  echo $ECHO_N "(cached) $ECHO_C" >&6
-+else
-+  gcc_cv_as_powerpc_popcntd=no
-+    if test $in_tree_gas = yes; then
-+    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 2`
-+  then gcc_cv_as_powerpc_popcntd=yes
-+fi
-+  elif test x$gcc_cv_as != x; then
-+    echo "$conftest_s" > conftest.s
-+    if { ac_try='$gcc_cv_as -a32 -o conftest.o conftest.s >&5'
-+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
-+  (eval $ac_try) 2>&5
-+  ac_status=$?
-+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-+  (exit $ac_status); }; }
-+    then
-+	gcc_cv_as_powerpc_popcntd=yes
-+    else
-+      echo "configure: failed program was" >&5
-+      cat conftest.s >&5
-+    fi
-+    rm -f conftest.o conftest.s
-+  fi
-+fi
-+echo "$as_me:$LINENO: result: $gcc_cv_as_powerpc_popcntd" >&5
-+echo "${ECHO_T}$gcc_cv_as_powerpc_popcntd" >&6
-+if test $gcc_cv_as_powerpc_popcntd = yes; then
-+
-+cat >>confdefs.h <<\_ACEOF
-+#define HAVE_AS_POPCNTD 1
-+_ACEOF
-+
-+fi
-+
-     echo "$as_me:$LINENO: checking assembler for .gnu_attribute support" >&5
- echo $ECHO_N "checking assembler for .gnu_attribute support... $ECHO_C" >&6
- if test "${gcc_cv_as_powerpc_gnu_attribute+set}" = set; then
---- gcc/config/rs6000/aix53.h	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/aix53.h	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/aix53.h	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/aix53.h	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -57,20 +57,24 @@ do {									\
  #undef ASM_SPEC
  #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
@@ -1645,8 +2017,8 @@ testsuite/
  %{mcpu=rs64a: -mppc} \
  %{mcpu=603: -m603} \
 --- gcc/config/rs6000/vector.md	(.../trunk)	(revision 0)
-+++ gcc/config/rs6000/vector.md	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -0,0 +1,518 @@
++++ gcc/config/rs6000/vector.md	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -0,0 +1,664 @@
 +;; Expander definitions for vector support between altivec & vsx.  No
 +;; instructions are in this file, this file provides the generic vector
 +;; expander, and the actual vector instructions will be in altivec.md and
@@ -1688,6 +2060,9 @@ testsuite/
 +;; Vector comparison modes
 +(define_mode_iterator VEC_C [V16QI V8HI V4SI V4SF V2DF])
 +
++;; Vector reload iterator
++(define_mode_iterator VEC_R [V16QI V8HI V4SI V2DI V4SF V2DF DF TI])
++
 +;; Base type from vector mode
 +(define_mode_attr VEC_base [(V16QI "QI")
 +			    (V8HI  "HI")
@@ -1710,15 +2085,16 @@ testsuite/
 +	(match_operand:VEC_M 1 "any_operand" ""))]
 +  "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)"
 +{
-+  /* modes without special handling just generate the normal SET operation.  */
-+  if (<MODE>mode != TImode && <MODE>mode != V2DImode && <MODE>mode != V2DFmode)
++  if (can_create_pseudo_p ())
 +    {
-+      rs6000_emit_move (operands[0], operands[1], <MODE>mode);
-+      DONE;
++      if (CONSTANT_P (operands[1])
++	  && !easy_vector_constant (operands[1], <MODE>mode))
++	operands[1] = force_const_mem (<MODE>mode, operands[1]);
++
++      else if (!vlogical_operand (operands[0], <MODE>mode)
++	       && !vlogical_operand (operands[1], <MODE>mode))
++	operands[1] = force_reg (<MODE>mode, operands[1]);
 +    }
-+  else if (!vlogical_operand (operands[0], <MODE>mode)
-+	   && !vlogical_operand (operands[1], <MODE>mode))
-+    operands[1] = force_reg (<MODE>mode, operands[1]);
 +})
 +
 +;; Generic vector floating point load/store instructions.  These will match
@@ -1749,6 +2125,49 @@ testsuite/
 +})
 +
 +
++;; Reload patterns for vector operations.  We may need an addtional base
++;; register to convert the reg+offset addressing to reg+reg for vector
++;; registers and reg+reg or (reg+reg)&(-16) addressing to just an index
++;; register for gpr registers.
++(define_expand "reload_<VEC_R:mode>_<P:mptrsize>_store"
++  [(parallel [(match_operand:VEC_R 0 "memory_operand" "m")
++              (match_operand:VEC_R 1 "gpc_reg_operand" "r")
++              (match_operand:P 2 "register_operand" "=&b")])]
++  "<P:tptrsize>"
++{
++  rs6000_secondary_reload_inner (operands[1], operands[0], operands[2], true);
++  DONE;
++})
++
++(define_expand "reload_<VEC_R:mode>_<P:mptrsize>_load"
++  [(parallel [(match_operand:VEC_R 0 "gpc_reg_operand" "=&r")
++              (match_operand:VEC_R 1 "memory_operand" "m")
++              (match_operand:P 2 "register_operand" "=&b")])]
++  "<P:tptrsize>"
++{
++  rs6000_secondary_reload_inner (operands[0], operands[1], operands[2], false);
++  DONE;
++})
++
++;; Reload sometimes tries to move the address to a GPR, and can generate
++;; invalid RTL for addresses involving AND -16.
++
++(define_insn_and_split "*vec_reload_and_plus_<mptrsize>"
++  [(set (match_operand:P 0 "gpc_reg_operand" "=b")
++	(and:P (plus:P (match_operand:P 1 "gpc_reg_operand" "r")
++		       (match_operand:P 2 "gpc_reg_operand" "r"))
++	       (const_int -16)))]
++  "TARGET_ALTIVEC || TARGET_VSX"
++  "#"
++  "&& reload_completed"
++  [(set (match_dup 0)
++	(plus:P (match_dup 1)
++		(match_dup 2)))
++   (parallel [(set (match_dup 0)
++		   (and:P (match_dup 0)
++			  (const_int -16)))
++	      (clobber:CC (scratch:CC))])])
++
 +;; Generic floating point vector arithmetic support
 +(define_expand "add<mode>3"
 +  [(set (match_operand:VEC_F 0 "vfloat_operand" "")
@@ -2145,28 +2564,127 @@ testsuite/
 +  "VECTOR_UNIT_VSX_P (V2DFmode)"
 +  "")
 +
-+;; For 2 element vectors, even/odd is the same as high/low
-+(define_expand "vec_extract_evenv2df"
-+  [(set (match_operand:V2DF 0 "vfloat_operand" "")
-+	(vec_concat:V2DF
-+	 (vec_select:DF (match_operand:V2DF 1 "vfloat_operand" "")
-+			(parallel [(const_int 0)]))
-+	 (vec_select:DF (match_operand:V2DF 2 "vfloat_operand" "")
-+			(parallel [(const_int 0)]))))]
-+  "VECTOR_UNIT_VSX_P (V2DFmode)"
-+  "")
++
++;; Convert double word types to single word types
++(define_expand "vec_pack_trunc_v2df"
++  [(match_operand:V4SF 0 "vsx_register_operand" "")
++   (match_operand:V2DF 1 "vsx_register_operand" "")
++   (match_operand:V2DF 2 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
++{
++  rtx r1 = gen_reg_rtx (V4SFmode);
++  rtx r2 = gen_reg_rtx (V4SFmode);
 +
-+(define_expand "vec_extract_oddv2df"
-+  [(set (match_operand:V2DF 0 "vfloat_operand" "")
-+	(vec_concat:V2DF
-+	 (vec_select:DF (match_operand:V2DF 1 "vfloat_operand" "")
-+			(parallel [(const_int 1)]))
-+	 (vec_select:DF (match_operand:V2DF 2 "vfloat_operand" "")
-+			(parallel [(const_int 1)]))))]
-+  "VECTOR_UNIT_VSX_P (V2DFmode)"
-+  "")
---- gcc/config/rs6000/spe.md	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/spe.md	(.../branches/ibm/power7-meissner)	(revision 144730)
++  emit_insn (gen_vsx_xvcvdpsp (r1, operands[1]));
++  emit_insn (gen_vsx_xvcvdpsp (r2, operands[2]));
++  emit_insn (gen_vec_extract_evenv4sf (operands[0], r1, r2));
++  DONE;
++})
++
++(define_expand "vec_pack_sfix_trunc_v2df"
++  [(match_operand:V4SI 0 "vsx_register_operand" "")
++   (match_operand:V2DF 1 "vsx_register_operand" "")
++   (match_operand:V2DF 2 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
++{
++  rtx r1 = gen_reg_rtx (V4SImode);
++  rtx r2 = gen_reg_rtx (V4SImode);
++
++  emit_insn (gen_vsx_xvcvdpsxws (r1, operands[1]));
++  emit_insn (gen_vsx_xvcvdpsxws (r2, operands[2]));
++  emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
++  DONE;
++})
++
++(define_expand "vec_pack_ufix_trunc_v2df"
++  [(match_operand:V4SI 0 "vsx_register_operand" "")
++   (match_operand:V2DF 1 "vsx_register_operand" "")
++   (match_operand:V2DF 2 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && TARGET_ALTIVEC"
++{
++  rtx r1 = gen_reg_rtx (V4SImode);
++  rtx r2 = gen_reg_rtx (V4SImode);
++
++  emit_insn (gen_vsx_xvcvdpuxws (r1, operands[1]));
++  emit_insn (gen_vsx_xvcvdpuxws (r2, operands[2]));
++  emit_insn (gen_vec_extract_evenv4si (operands[0], r1, r2));
++  DONE;
++})
++
++;; Convert single word types to double word
++(define_expand "vec_unpacks_hi_v4sf"
++  [(match_operand:V2DF 0 "vsx_register_operand" "")
++   (match_operand:V4SF 1 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
++{
++  rtx reg = gen_reg_rtx (V4SFmode);
++
++  emit_insn (gen_vec_interleave_highv4sf (reg, operands[1], operands[1]));
++  emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
++  DONE;
++})
++
++(define_expand "vec_unpacks_lo_v4sf"
++  [(match_operand:V2DF 0 "vsx_register_operand" "")
++   (match_operand:V4SF 1 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)"
++{
++  rtx reg = gen_reg_rtx (V4SFmode);
++
++  emit_insn (gen_vec_interleave_lowv4sf (reg, operands[1], operands[1]));
++  emit_insn (gen_vsx_xvcvspdp (operands[0], reg));
++  DONE;
++})
++
++(define_expand "vec_unpacks_float_hi_v4si"
++  [(match_operand:V2DF 0 "vsx_register_operand" "")
++   (match_operand:V4SI 1 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
++{
++  rtx reg = gen_reg_rtx (V4SImode);
++
++  emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
++  emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
++  DONE;
++})
++
++(define_expand "vec_unpacks_float_lo_v4si"
++  [(match_operand:V2DF 0 "vsx_register_operand" "")
++   (match_operand:V4SI 1 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
++{
++  rtx reg = gen_reg_rtx (V4SImode);
++
++  emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
++  emit_insn (gen_vsx_xvcvsxwdp (operands[0], reg));
++  DONE;
++})
++
++(define_expand "vec_unpacku_float_hi_v4si"
++  [(match_operand:V2DF 0 "vsx_register_operand" "")
++   (match_operand:V4SI 1 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
++{
++  rtx reg = gen_reg_rtx (V4SImode);
++
++  emit_insn (gen_vec_interleave_highv4si (reg, operands[1], operands[1]));
++  emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
++  DONE;
++})
++
++(define_expand "vec_unpacku_float_lo_v4si"
++  [(match_operand:V2DF 0 "vsx_register_operand" "")
++   (match_operand:V4SI 1 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (V2DFmode) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SImode)"
++{
++  rtx reg = gen_reg_rtx (V4SImode);
++
++  emit_insn (gen_vec_interleave_lowv4si (reg, operands[1], operands[1]));
++  emit_insn (gen_vsx_xvcvuxwdp (operands[0], reg));
++  DONE;
++})
+--- gcc/config/rs6000/spe.md	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/spe.md	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -99,7 +99,7 @@ (define_insn "*divsf3_gpr"
  
  ;; Floating point conversion instructions.
@@ -2176,8 +2694,8 @@ testsuite/
    [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
  	(unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "r")))]
    "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
---- gcc/config/rs6000/constraints.md	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/constraints.md	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/constraints.md	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/constraints.md	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -17,6 +17,8 @@
  ;; along with GCC; see the file COPYING3.  If not see
  ;; <http://www.gnu.org/licenses/>.
@@ -2187,7 +2705,7 @@ testsuite/
  ;; Register constraints
  
  (define_register_constraint "f" "TARGET_HARD_FLOAT && TARGET_FPRS
-@@ -50,6 +52,23 @@ (define_register_constraint "y" "CR_REGS
+@@ -50,6 +52,28 @@ (define_register_constraint "y" "CR_REGS
  (define_register_constraint "z" "XER_REGS"
    "@internal")
  
@@ -2208,10 +2726,15 @@ testsuite/
 +(define_register_constraint "wa" "rs6000_vsx_reg_class"
 +  "@internal")
 +
++;; Altivec style load/store that ignores the bottom bits of the address
++(define_memory_constraint "wZ"
++  "Indexed or indirect memory operand, ignoring the bottom 4 bits"
++  (match_operand 0 "altivec_indexed_or_indirect_operand"))
++
  ;; Integer constraints
  
  (define_constraint "I"
-@@ -159,3 +178,7 @@ (define_constraint "t"
+@@ -159,3 +183,7 @@ (define_constraint "t"
  (define_constraint "W"
    "vector constant that does not require memory"
    (match_operand 0 "easy_vector_constant"))
@@ -2219,8 +2742,8 @@ testsuite/
 +(define_constraint "j"
 +  "Zero vector constant"
 +  (match_test "(op == const0_rtx || op == CONST0_RTX (GET_MODE (op)))"))
---- gcc/config/rs6000/predicates.md	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/predicates.md	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/predicates.md	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/predicates.md	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -38,6 +38,37 @@ (define_predicate "altivec_register_oper
  		     || ALTIVEC_REGNO_P (REGNO (op))
  		     || REGNO (op) > LAST_VIRTUAL_REGISTER")))
@@ -2270,7 +2793,7 @@ testsuite/
        /* Force constants to memory before reload to utilize
  	 compress_float_constant.
  	 Avoid this when flag_unsafe_math_optimizations is enabled
-@@ -396,13 +431,16 @@ (define_predicate "indexed_or_indirect_o
+@@ -396,16 +431,36 @@ (define_predicate "indexed_or_indirect_o
    (match_code "mem")
  {
    op = XEXP (op, 0);
@@ -2289,7 +2812,27 @@ testsuite/
    return indexed_or_indirect_address (op, mode);
  })
  
-@@ -1336,3 +1374,19 @@ (define_predicate "stmw_operation"
++;; Return 1 if the operand is an indexed or indirect memory operand with an
++;; AND -16 in it, used to recognize when we need to switch to Altivec loads
++;; to realign loops instead of VSX (altivec silently ignores the bottom bits,
++;; while VSX uses the full address and traps)
++(define_predicate "altivec_indexed_or_indirect_operand"
++  (match_code "mem")
++{
++  op = XEXP (op, 0);
++  if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
++      && GET_CODE (op) == AND
++      && GET_CODE (XEXP (op, 1)) == CONST_INT
++      && INTVAL (XEXP (op, 1)) == -16)
++    return indexed_or_indirect_address (XEXP (op, 0), mode);
++
++  return 0;
++})
++
+ ;; Return 1 if the operand is an indexed or indirect address.
+ (define_special_predicate "indexed_or_indirect_address"
+   (and (match_test "REG_P (op)
+@@ -1336,3 +1391,19 @@ (define_predicate "stmw_operation"
  
    return 1;
  })
@@ -2309,8 +2852,8 @@ testsuite/
 +
 +  return 1;
 +})
---- gcc/config/rs6000/ppc-asm.h	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/ppc-asm.h	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/ppc-asm.h	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/ppc-asm.h	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -63,7 +63,7 @@
  #define f16	16
  #define f17	17
@@ -2464,8 +3007,8 @@ testsuite/
  /*
   * Macros to glue together two tokens.
   */
---- gcc/config/rs6000/linux64.opt	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/linux64.opt	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/linux64.opt	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/linux64.opt	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -20,5 +20,5 @@
  ; <http://www.gnu.org/licenses/>.
  
@@ -2473,8 +3016,8 @@ testsuite/
 -Target Report Mask(PROFILE_KERNEL)
 +Target Report Var(TARGET_PROFILE_KERNEL)
  Call mcount for profiling before a function prologue
---- gcc/config/rs6000/sysv4.opt	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/sysv4.opt	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/sysv4.opt	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/sysv4.opt	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -32,7 +32,7 @@ Target RejectNegative Joined
  Specify bit size of immediate TLS offsets
  
@@ -2498,9 +3041,9 @@ testsuite/
  Use alternate register names
  
  ;; FIXME: Does nothing.
---- gcc/config/rs6000/rs6000-protos.h	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/rs6000-protos.h	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -64,9 +64,14 @@ extern int insvdi_rshift_rlwimi_p (rtx, 
+--- gcc/config/rs6000/rs6000-protos.h	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/rs6000-protos.h	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -64,9 +64,15 @@ extern int insvdi_rshift_rlwimi_p (rtx, 
  extern int registers_ok_for_quad_peep (rtx, rtx);
  extern int mems_ok_for_quad_peep (rtx, rtx);
  extern bool gpr_or_gpr_p (rtx, rtx);
@@ -2513,10 +3056,11 @@ testsuite/
 +extern bool rs6000_cannot_change_mode_class (enum machine_mode,
 +					     enum machine_mode,
 +					     enum reg_class);
++extern void rs6000_secondary_reload_inner (rtx, rtx, rtx, bool);
  extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,
                                           rtx, rtx, rtx);
  extern void paired_expand_vector_move (rtx operands[]);
-@@ -170,7 +175,6 @@ extern int rs6000_register_move_cost (en
+@@ -170,7 +176,6 @@ extern int rs6000_register_move_cost (en
  				      enum reg_class, enum reg_class);
  extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int);
  extern bool rs6000_tls_referenced_p (rtx);
@@ -2524,15 +3068,15 @@ testsuite/
  extern void rs6000_conditional_register_usage (void);
  
  /* Declare functions in rs6000-c.c */
-@@ -189,4 +193,6 @@ const char * rs6000_xcoff_strip_dollar (
+@@ -189,4 +194,6 @@ const char * rs6000_xcoff_strip_dollar (
  void rs6000_final_prescan_insn (rtx, rtx *operand, int num_operands);
  
  extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER];
 +extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES];
 +extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER];
  #endif  /* rs6000-protos.h */
---- gcc/config/rs6000/t-rs6000	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/t-rs6000	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/t-rs6000	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/t-rs6000	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -16,3 +16,33 @@ rs6000-c.o: $(srcdir)/config/rs6000/rs60
  
  # The rs6000 backend doesn't cause warnings in these files.
@@ -2568,8 +3112,8 @@ testsuite/
 +	$(srcdir)/config/rs6000/dfp.md \
 +	$(srcdir)/config/rs6000/paired.md
 --- gcc/config/rs6000/power7.md	(.../trunk)	(revision 0)
-+++ gcc/config/rs6000/power7.md	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -0,0 +1,320 @@
++++ gcc/config/rs6000/power7.md	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -0,0 +1,318 @@
 +;; Scheduling description for IBM POWER7 processor.
 +;; Copyright (C) 2009 Free Software Foundation, Inc.
 +;;
@@ -2888,11 +3432,82 @@ testsuite/
 +  (and (eq_attr "type" "vecperm")
 +       (eq_attr "cpu" "power7"))
 +  "du2_power7,VSU_power7")
+--- gcc/config/rs6000/rs6000-c.c	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/rs6000-c.c	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -106,14 +106,17 @@ altivec_categorize_keyword (const cpp_to
+       if (ident == C_CPP_HASHNODE (vector_keyword))
+ 	return C_CPP_HASHNODE (__vector_keyword);
+ 
+-      if (ident == C_CPP_HASHNODE (pixel_keyword))
+-	return C_CPP_HASHNODE (__pixel_keyword);
++      if (TARGET_ALTIVEC)
++	{
++	  if (ident == C_CPP_HASHNODE (pixel_keyword))
++	    return C_CPP_HASHNODE (__pixel_keyword);
+ 
+-      if (ident == C_CPP_HASHNODE (bool_keyword))
+-	return C_CPP_HASHNODE (__bool_keyword);
++	  if (ident == C_CPP_HASHNODE (bool_keyword))
++	    return C_CPP_HASHNODE (__bool_keyword);
+ 
+-      if (ident == C_CPP_HASHNODE (_Bool_keyword))
+-	return C_CPP_HASHNODE (__bool_keyword);
++	  if (ident == C_CPP_HASHNODE (_Bool_keyword))
++	    return C_CPP_HASHNODE (__bool_keyword);
++	}
+ 
+       return ident;
+     }
+@@ -131,23 +134,26 @@ init_vector_keywords (void)
+   __vector_keyword = get_identifier ("__vector");
+   C_CPP_HASHNODE (__vector_keyword)->flags |= NODE_CONDITIONAL;
+ 
+-  __pixel_keyword = get_identifier ("__pixel");
+-  C_CPP_HASHNODE (__pixel_keyword)->flags |= NODE_CONDITIONAL;
+-
+-  __bool_keyword = get_identifier ("__bool");
+-  C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
+-
+   vector_keyword = get_identifier ("vector");
+   C_CPP_HASHNODE (vector_keyword)->flags |= NODE_CONDITIONAL;
+ 
+-  pixel_keyword = get_identifier ("pixel");
+-  C_CPP_HASHNODE (pixel_keyword)->flags |= NODE_CONDITIONAL;
++  if (TARGET_ALTIVEC)
++    {
++      __pixel_keyword = get_identifier ("__pixel");
++      C_CPP_HASHNODE (__pixel_keyword)->flags |= NODE_CONDITIONAL;
 +
++      __bool_keyword = get_identifier ("__bool");
++      C_CPP_HASHNODE (__bool_keyword)->flags |= NODE_CONDITIONAL;
+ 
+-  bool_keyword = get_identifier ("bool");
+-  C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
++      pixel_keyword = get_identifier ("pixel");
++      C_CPP_HASHNODE (pixel_keyword)->flags |= NODE_CONDITIONAL;
+ 
+-  _Bool_keyword = get_identifier ("_Bool");
+-  C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
++      bool_keyword = get_identifier ("bool");
++      C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
 +
---- gcc/config/rs6000/rs6000-c.c	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/rs6000-c.c	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -265,6 +265,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
++      _Bool_keyword = get_identifier ("_Bool");
++      C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
++    }
+ }
+ 
+ /* Called to decide whether a conditional macro should be expanded.
+@@ -214,7 +220,8 @@ rs6000_macro_to_expand (cpp_reader *pfil
+ 	  if (rid_code == RID_UNSIGNED || rid_code == RID_LONG
+ 	      || rid_code == RID_SHORT || rid_code == RID_SIGNED
+ 	      || rid_code == RID_INT || rid_code == RID_CHAR
+-	      || rid_code == RID_FLOAT)
++	      || rid_code == RID_FLOAT
++	      || (rid_code == RID_DOUBLE && TARGET_VSX))
+ 	    {
+ 	      expand_this = C_CPP_HASHNODE (__vector_keyword);
+ 	      /* If the next keyword is bool or pixel, it
+@@ -284,13 +291,14 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
      builtin_define ("_ARCH_PWR6X");
    if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC)
      builtin_define ("_ARCH_COM");
@@ -2901,7 +3516,37 @@ testsuite/
    if (TARGET_ALTIVEC)
      {
        builtin_define ("__ALTIVEC__");
-@@ -306,6 +308,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+       builtin_define ("__VEC__=10206");
+ 
+       /* Define the AltiVec syntactic elements.  */
+-      builtin_define ("__vector=__attribute__((altivec(vector__)))");
+       builtin_define ("__pixel=__attribute__((altivec(pixel__))) unsigned short");
+       builtin_define ("__bool=__attribute__((altivec(bool__))) unsigned");
+ 
+@@ -298,11 +306,20 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
+ 	{
+ 	  /* Define this when supporting context-sensitive keywords.  */
+ 	  builtin_define ("__APPLE_ALTIVEC__");
+-	  
+-	  builtin_define ("vector=vector");
++
+ 	  builtin_define ("pixel=pixel");
+ 	  builtin_define ("bool=bool");
+ 	  builtin_define ("_Bool=_Bool");
++	}
++    }
++  if (TARGET_ALTIVEC || TARGET_VSX)
++    {
++      /* Define the AltiVec/VSX syntactic elements.  */
++      builtin_define ("__vector=__attribute__((altivec(vector__)))");
++
++      if (!flag_iso)
++	{
++	  builtin_define ("vector=vector");
+ 	  init_vector_keywords ();
+ 
+ 	  /* Enable context-sensitive macros.  */
+@@ -326,6 +343,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi
    /* Used by libstdc++.  */
    if (TARGET_NO_LWSYNC)
      builtin_define ("__NO_LWSYNC__");
@@ -2910,9 +3555,119 @@ testsuite/
  
    /* May be overridden by target configuration.  */
    RS6000_CPU_CPP_ENDIAN_BUILTINS();
---- gcc/config/rs6000/rs6000.opt	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/rs6000.opt	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -111,24 +111,44 @@ mhard-float
+@@ -504,6 +523,8 @@ const struct altivec_builtin_types altiv
+     RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
++  { ALTIVEC_BUILTIN_VEC_ADD, VSX_BUILTIN_XVADDDP,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+   { ALTIVEC_BUILTIN_VEC_VADDFP, ALTIVEC_BUILTIN_VADDFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+@@ -647,6 +668,12 @@ const struct altivec_builtin_types altiv
+   { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+     RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
++  { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
++    RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+     RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+     RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+@@ -695,6 +722,12 @@ const struct altivec_builtin_types altiv
+   { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+     RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
++  { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
++    RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+     RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+     RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+@@ -1198,6 +1231,8 @@ const struct altivec_builtin_types altiv
+     RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
++  { ALTIVEC_BUILTIN_VEC_MAX, VSX_BUILTIN_XVMAXDP,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+   { ALTIVEC_BUILTIN_VEC_VMAXFP, ALTIVEC_BUILTIN_VMAXFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_VMAXSW, ALTIVEC_BUILTIN_VMAXSW,
+@@ -1374,6 +1409,8 @@ const struct altivec_builtin_types altiv
+     RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
++  { ALTIVEC_BUILTIN_VEC_MIN, VSX_BUILTIN_XVMINDP,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+   { ALTIVEC_BUILTIN_VEC_VMINFP, ALTIVEC_BUILTIN_VMINFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_VMINSW, ALTIVEC_BUILTIN_VMINSW,
+@@ -1459,6 +1496,8 @@ const struct altivec_builtin_types altiv
+   { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+     RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+     RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+@@ -1483,6 +1522,12 @@ const struct altivec_builtin_types altiv
+   { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+     RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
++  { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
++    RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+     RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+     RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+@@ -1940,6 +1985,8 @@ const struct altivec_builtin_types altiv
+     RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
++  { ALTIVEC_BUILTIN_VEC_SUB, VSX_BUILTIN_XVSUBDP,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
+   { ALTIVEC_BUILTIN_VEC_VSUBFP, ALTIVEC_BUILTIN_VSUBFP,
+     RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+@@ -2099,6 +2146,12 @@ const struct altivec_builtin_types altiv
+   { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+     RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
+   { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
++    RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, 0 },
++  { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
++    RS6000_BTI_V2DF, RS6000_BTI_bool_V4SI, RS6000_BTI_V2DF, 0 },
++  { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+     RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+   { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+     RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+@@ -2989,8 +3042,10 @@ altivec_resolve_overloaded_builtin (tree
+   const struct altivec_builtin_types *desc;
+   int n;
+ 
+-  if (fcode < ALTIVEC_BUILTIN_OVERLOADED_FIRST
+-      || fcode > ALTIVEC_BUILTIN_OVERLOADED_LAST)
++  if ((fcode < ALTIVEC_BUILTIN_OVERLOADED_FIRST
++       || fcode > ALTIVEC_BUILTIN_OVERLOADED_LAST)
++      && (fcode < VSX_BUILTIN_OVERLOADED_FIRST
++	  || fcode > VSX_BUILTIN_OVERLOADED_LAST))
+     return NULL_TREE;
+ 
+   /* For now treat vec_splats and vec_promote as the same.  */
+--- gcc/config/rs6000/rs6000.opt	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/rs6000.opt	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -111,24 +111,60 @@ mhard-float
  Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
  Use hardware floating point
  
@@ -2928,24 +3683,40 @@ testsuite/
 +Use vector/scalar (VSX) instructions
 +
 +mvsx-vector-memory
-+Target Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1)
-+If -mvsx, use VSX vector load/store instructions instead of Altivec instructions
++Target Undocumented Report Var(TARGET_VSX_VECTOR_MEMORY) Init(-1)
++; If -mvsx, use VSX vector load/store instructions instead of Altivec instructions
 +
 +mvsx-vector-float
-+Target Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1)
-+If -mvsx, use VSX arithmetic instructions for float vectors (on by default)
++Target Undocumented Report Var(TARGET_VSX_VECTOR_FLOAT) Init(-1)
++; If -mvsx, use VSX arithmetic instructions for float vectors (on by default)
 +
 +mvsx-vector-double
-+Target Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1)
-+If -mvsx, use VSX arithmetic instructions for double vectors (on by default)
++Target Undocumented Report Var(TARGET_VSX_VECTOR_DOUBLE) Init(-1)
++; If -mvsx, use VSX arithmetic instructions for double vectors (on by default)
 +
 +mvsx-scalar-double
-+Target Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
-+If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
++Target Undocumented Report Var(TARGET_VSX_SCALAR_DOUBLE) Init(-1)
++; If -mvsx, use VSX arithmetic instructions for scalar double (on by default)
 +
 +mvsx-scalar-memory
-+Target Report Var(TARGET_VSX_SCALAR_MEMORY)
-+If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
++Target Undocumented Report Var(TARGET_VSX_SCALAR_MEMORY)
++; If -mvsx, use VSX scalar memory reference instructions for scalar double (off by default)
++
++mvsx-v4sf-altivec-regs
++Target Undocumented Report Var(TARGET_V4SF_ALTIVEC_REGS) Init(-1)
++; If -mvsx, prefer V4SF types to use Altivec regs and not the floating registers
++
++mreload-functions
++Target Undocumented Report Var(TARGET_RELOAD_FUNCTIONS) Init(-1)
++; If -mvsx or -maltivec, enable reload functions
++
++mpower7-adjust-cost
++Target Undocumented Var(TARGET_POWER7_ADJUST_COST)
++; Add extra cost for setting CR registers before a branch like is done for Power5
++
++mdisallow-float-in-lr-ctr
++Target Undocumented Var(TARGET_DISALLOW_FLOAT_IN_LR_CTR) Init(-1)
++; Disallow floating point in LR or CTR, causes some reload bugs
  
  mupdate
 -Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE)
@@ -2966,7 +3737,7 @@ testsuite/
  Generate fused multiply/add instructions
  
  msched-prolog
-@@ -194,7 +214,7 @@ Target RejectNegative Joined
+@@ -194,7 +230,7 @@ Target RejectNegative Joined
  -mvrsave=yes/no	Deprecated option.  Use -mvrsave/-mno-vrsave instead
  
  misel
@@ -2975,8 +3746,8 @@ testsuite/
  Generate isel instructions
  
  misel=
---- gcc/config/rs6000/linux64.h	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/linux64.h	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/linux64.h	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/linux64.h	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -114,7 +114,7 @@ extern int dot_symbols;
  	    error (INVALID_32BIT, "32");			\
  	  if (TARGET_PROFILE_KERNEL)				\
@@ -2986,8 +3757,8 @@ testsuite/
  	      error (INVALID_32BIT, "profile-kernel");		\
  	    }							\
  	}							\
---- gcc/config/rs6000/rs6000.c	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/rs6000.c	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/rs6000.c	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/rs6000.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -178,9 +178,6 @@ int rs6000_spe;
  /* Nonzero if we want SPE ABI extensions.  */
  int rs6000_spe_abi;
@@ -2998,26 +3769,35 @@ testsuite/
  /* Nonzero if floating point operations are done in the GPRs.  */
  int rs6000_float_gprs = 0;
  
-@@ -227,10 +224,18 @@ int dot_symbols;
+@@ -227,12 +224,26 @@ int dot_symbols;
  const char *rs6000_debug_name;
  int rs6000_debug_stack;		/* debug stack applications */
  int rs6000_debug_arg;		/* debug argument handling */
 +int rs6000_debug_reg;		/* debug register classes */
 +int rs6000_debug_addr;		/* debug memory addressing */
++int rs6000_debug_cost;		/* debug rtx_costs */
  
  /* Value is TRUE if register/mode pair is acceptable.  */
  bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
  
+-/* Built in types.  */
 +/* Maximum number of registers needed for a given register class and mode.  */
 +unsigned char rs6000_class_max_nregs[NUM_MACHINE_MODES][LIM_REG_CLASSES];
 +
 +/* How many registers are needed for a given register and mode.  */
 +unsigned char rs6000_hard_regno_nregs[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
 +
- /* Built in types.  */
++/* Map register number to register class.  */
++enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER];
  
++/* Reload functions based on the type and the vector unit.  */
++static enum insn_code rs6000_vector_reload[NUM_MACHINE_MODES][2];
++
++/* Built in types.  */
  tree rs6000_builtin_types[RS6000_BTI_MAX];
-@@ -270,7 +275,6 @@ struct {
+ tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
+ 
+@@ -270,7 +281,6 @@ struct {
    bool altivec_abi;		/* True if -mabi=altivec/no-altivec used.  */
    bool spe;			/* True if -mspe= was used.  */
    bool float_gprs;		/* True if -mfloat-gprs= was used.  */
@@ -3025,7 +3805,7 @@ testsuite/
    bool long_double;	        /* True if -mlong-double- was used.  */
    bool ieee;			/* True if -mabi=ieee/ibmlongdouble used.  */
    bool vrsave;			/* True if -mvrsave was used.  */
-@@ -286,6 +290,18 @@ struct builtin_description
+@@ -286,6 +296,18 @@ struct builtin_description
    const char *const name;
    const enum rs6000_builtins code;
  };
@@ -3044,7 +3824,7 @@ testsuite/
  
  /* Target cpu costs.  */
  
-@@ -749,6 +765,25 @@ struct processor_costs power6_cost = {
+@@ -749,6 +771,25 @@ struct processor_costs power6_cost = {
    16,			/* prefetch streams */
  };
  
@@ -3070,7 +3850,26 @@ testsuite/
  
  static bool rs6000_function_ok_for_sibcall (tree, tree);
  static const char *rs6000_invalid_within_doloop (const_rtx);
-@@ -963,12 +998,10 @@ static tree rs6000_gimplify_va_arg (tree
+@@ -827,7 +868,10 @@ static void rs6000_xcoff_file_end (void)
+ #endif
+ static int rs6000_variable_issue (FILE *, int, rtx, int);
+ static bool rs6000_rtx_costs (rtx, int, int, int *, bool);
++static bool rs6000_debug_rtx_costs (rtx, int, int, int *, bool);
++static int rs6000_debug_address_cost (rtx, bool);
+ static int rs6000_adjust_cost (rtx, rtx, rtx, int);
++static int rs6000_debug_adjust_cost (rtx, rtx, rtx, int);
+ static void rs6000_sched_init (FILE *, int, int);
+ static bool is_microcoded_insn (rtx);
+ static bool is_nonpipeline_insn (rtx);
+@@ -906,6 +950,7 @@ static rtx altivec_expand_stv_builtin (e
+ static rtx altivec_expand_vec_init_builtin (tree, tree, rtx);
+ static rtx altivec_expand_vec_set_builtin (tree);
+ static rtx altivec_expand_vec_ext_builtin (tree, rtx);
++static rtx vsx_expand_builtin (tree, rtx, bool *);
+ static int get_element_number (tree, tree);
+ static bool rs6000_handle_option (size_t, const char *, int);
+ static void rs6000_parse_tls_size_option (void);
+@@ -963,14 +1008,16 @@ static tree rs6000_gimplify_va_arg (tree
  static bool rs6000_must_pass_in_stack (enum machine_mode, const_tree);
  static bool rs6000_scalar_mode_supported_p (enum machine_mode);
  static bool rs6000_vector_mode_supported_p (enum machine_mode);
@@ -3084,8 +3883,14 @@ testsuite/
 -static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
  static tree rs6000_stack_protect_fail (void);
  
++static enum reg_class rs6000_secondary_reload (bool, rtx, enum reg_class,
++					       enum machine_mode,
++					       struct secondary_reload_info *);
++
  const int INSN_NOT_AVAILABLE = -1;
-@@ -1045,6 +1078,9 @@ static const char alt_reg_names[][8] =
+ static enum machine_mode rs6000_eh_return_filter_mode (void);
+ 
+@@ -1045,6 +1092,9 @@ static const char alt_reg_names[][8] =
  #endif
  #ifndef TARGET_PROFILE_KERNEL
  #define TARGET_PROFILE_KERNEL 0
@@ -3095,8 +3900,13 @@ testsuite/
  #endif
  
  /* The VRSAVE bitmask puts bit %v0 as the most significant bit.  */
-@@ -1299,28 +1335,96 @@ static const char alt_reg_names[][8] =
+@@ -1297,30 +1347,101 @@ static const char alt_reg_names[][8] =
+ #undef TARGET_INSTANTIATE_DECLS
+ #define TARGET_INSTANTIATE_DECLS rs6000_instantiate_decls
  
++#undef TARGET_SECONDARY_RELOAD
++#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
++
  struct gcc_target targetm = TARGET_INITIALIZER;
  
 +/* Return number of consecutive hard regs needed starting at reg REGNO
@@ -3202,7 +4012,7 @@ testsuite/
  
    /* The CR register can only hold CC modes.  */
    if (CR_REGNO_P (regno))
-@@ -1331,28 +1435,312 @@ rs6000_hard_regno_mode_ok (int regno, en
+@@ -1331,28 +1452,389 @@ rs6000_hard_regno_mode_ok (int regno, en
  
    /* AltiVec only in AldyVec registers.  */
    if (ALTIVEC_REGNO_P (regno))
@@ -3215,10 +4025,16 @@ testsuite/
  
 -  /* We cannot put TImode anywhere except general register and it must be
 -     able to fit within the register set.  */
-+  /* Don't allow anything but word sized integers (aka pointers) in CTR/LR.  You
-+     really don't want to spill your floating point values to those
-+     registers.  Also do it for the old MQ register in the power.  */
-+  if (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO)
++  /* Don't allow anything but word sized integers (aka pointers) in CTR/LR.
++     You really don't want to spill your floating point values to those
++     registers.  Also do it for the old MQ register in the power.
++
++     While this is desirable in theory, disabling float to go in LR/CTR does
++     cause some regressions, so until they are taken care of, revert to the old
++     behavior by default for most power systems, but enable it for power7.  */
++  if ((TARGET_DISALLOW_FLOAT_IN_LR_CTR > 0
++       || (TARGET_DISALLOW_FLOAT_IN_LR_CTR < 0 && TARGET_VSX))
++      && (regno == CTR_REGNO || regno == LR_REGNO || regno == MQ_REGNO))
 +    return (GET_MODE_CLASS (mode) == MODE_INT
 +	    && GET_MODE_SIZE (mode) <= UNITS_PER_WORD);
 +
@@ -3327,12 +4143,43 @@ testsuite/
 +  enum reg_class vsx_rc = (TARGET_ALTIVEC ? VSX_REGS : FLOAT_REGS);
 +  bool float_p = (TARGET_HARD_FLOAT && TARGET_FPRS);
 +
++  /* Precalculate REGNO_REG_CLASS.  */
++  rs6000_regno_regclass[0] = GENERAL_REGS;
++  for (r = 1; r < 32; ++r)
++    rs6000_regno_regclass[r] = BASE_REGS;
++
++  for (r = 32; r < 64; ++r)
++    rs6000_regno_regclass[r] = FLOAT_REGS;
++
++  for (r = 64; r < FIRST_PSEUDO_REGISTER; ++r)
++    rs6000_regno_regclass[r] = NO_REGS;
++
++  for (r = FIRST_ALTIVEC_REGNO; r <= LAST_ALTIVEC_REGNO; ++r)
++    rs6000_regno_regclass[r] = ALTIVEC_REGS;
++
++  rs6000_regno_regclass[CR0_REGNO] = CR0_REGS;
++  for (r = CR1_REGNO; r <= CR7_REGNO; ++r)
++    rs6000_regno_regclass[r] = CR_REGS;
++
++  rs6000_regno_regclass[MQ_REGNO] = MQ_REGS;
++  rs6000_regno_regclass[LR_REGNO] = LINK_REGS;
++  rs6000_regno_regclass[CTR_REGNO] = CTR_REGS;
++  rs6000_regno_regclass[XER_REGNO] = XER_REGS;
++  rs6000_regno_regclass[VRSAVE_REGNO] = VRSAVE_REGS;
++  rs6000_regno_regclass[VSCR_REGNO] = VRSAVE_REGS;
++  rs6000_regno_regclass[SPE_ACC_REGNO] = SPE_ACC_REGS;
++  rs6000_regno_regclass[SPEFSCR_REGNO] = SPEFSCR_REGS;
++  rs6000_regno_regclass[ARG_POINTER_REGNUM] = BASE_REGS;
++  rs6000_regno_regclass[FRAME_POINTER_REGNUM] = BASE_REGS;
++
 +  /* Precalculate vector information, this must be set up before the
 +     rs6000_hard_regno_nregs_internal below.  */
 +  for (m = 0; m < NUM_MACHINE_MODES; ++m)
 +    {
 +      rs6000_vector_unit[m] = rs6000_vector_mem[m] = VECTOR_NONE;
 +      rs6000_vector_reg_class[m] = NO_REGS;
++      rs6000_vector_reload[m][0] = CODE_FOR_nothing;
++      rs6000_vector_reload[m][1] = CODE_FOR_nothing;
 +    }
 +
 +  /* TODO, add TI/V2DI mode for moving data if Altivec or VSX.  */
@@ -3409,8 +4256,13 @@ testsuite/
 +  /* TODO, add SPE and paired floating point vector support.  */
 +
 +  /* Set the VSX register classes.  */
++
++  /* For V4SF, prefer the Altivec registers, because there are a few operations
++     that want to use Altivec operations instead of VSX.  */
 +  rs6000_vector_reg_class[V4SFmode]
-+    = ((VECTOR_UNIT_VSX_P (V4SFmode) && VECTOR_MEM_VSX_P (V4SFmode))
++    = ((VECTOR_UNIT_VSX_P (V4SFmode)
++	&& VECTOR_MEM_VSX_P (V4SFmode)
++	&& !TARGET_V4SF_ALTIVEC_REGS)
 +       ? vsx_rc
 +       : (VECTOR_UNIT_ALTIVEC_OR_VSX_P (V4SFmode)
 +	  ? ALTIVEC_REGS
@@ -3428,6 +4280,41 @@ testsuite/
 +
 +  rs6000_vsx_reg_class = (float_p && TARGET_VSX) ? vsx_rc : NO_REGS;
 +
++  /* Set up the reload helper functions.  */
++  if (TARGET_RELOAD_FUNCTIONS && (TARGET_VSX || TARGET_ALTIVEC))
++    {
++      if (TARGET_64BIT)
++	{
++	  rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_di_store;
++	  rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_di_load;
++	  rs6000_vector_reload[V8HImode][0]  = CODE_FOR_reload_v8hi_di_store;
++	  rs6000_vector_reload[V8HImode][1]  = CODE_FOR_reload_v8hi_di_load;
++	  rs6000_vector_reload[V4SImode][0]  = CODE_FOR_reload_v4si_di_store;
++	  rs6000_vector_reload[V4SImode][1]  = CODE_FOR_reload_v4si_di_load;
++	  rs6000_vector_reload[V2DImode][0]  = CODE_FOR_reload_v2di_di_store;
++	  rs6000_vector_reload[V2DImode][1]  = CODE_FOR_reload_v2di_di_load;
++	  rs6000_vector_reload[V4SFmode][0]  = CODE_FOR_reload_v4sf_di_store;
++	  rs6000_vector_reload[V4SFmode][1]  = CODE_FOR_reload_v4sf_di_load;
++	  rs6000_vector_reload[V2DFmode][0]  = CODE_FOR_reload_v2df_di_store;
++	  rs6000_vector_reload[V2DFmode][1]  = CODE_FOR_reload_v2df_di_load;
++	}
++      else
++	{
++	  rs6000_vector_reload[V16QImode][0] = CODE_FOR_reload_v16qi_si_store;
++	  rs6000_vector_reload[V16QImode][1] = CODE_FOR_reload_v16qi_si_load;
++	  rs6000_vector_reload[V8HImode][0]  = CODE_FOR_reload_v8hi_si_store;
++	  rs6000_vector_reload[V8HImode][1]  = CODE_FOR_reload_v8hi_si_load;
++	  rs6000_vector_reload[V4SImode][0]  = CODE_FOR_reload_v4si_si_store;
++	  rs6000_vector_reload[V4SImode][1]  = CODE_FOR_reload_v4si_si_load;
++	  rs6000_vector_reload[V2DImode][0]  = CODE_FOR_reload_v2di_si_store;
++	  rs6000_vector_reload[V2DImode][1]  = CODE_FOR_reload_v2di_si_load;
++	  rs6000_vector_reload[V4SFmode][0]  = CODE_FOR_reload_v4sf_si_store;
++	  rs6000_vector_reload[V4SFmode][1]  = CODE_FOR_reload_v4sf_si_load;
++	  rs6000_vector_reload[V2DFmode][0]  = CODE_FOR_reload_v2df_si_store;
++	  rs6000_vector_reload[V2DFmode][1]  = CODE_FOR_reload_v2df_si_load;
++	}
++    }
++
 +  /* Precalculate HARD_REGNO_NREGS.  */
 +  for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
 +    for (m = 0; m < NUM_MACHINE_MODES; ++m)
@@ -3520,7 +4407,7 @@ testsuite/
  }
  
  #if TARGET_MACHO
-@@ -1482,12 +1870,15 @@ rs6000_override_options (const char *def
+@@ -1482,12 +1964,15 @@ rs6000_override_options (const char *def
  	 {"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
  	 {"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
  	 {"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
@@ -3539,7 +4426,7 @@ testsuite/
  	 {"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
  	 {"970", PROCESSOR_POWER4,
  	  POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
-@@ -1520,9 +1911,10 @@ rs6000_override_options (const char *def
+@@ -1520,9 +2005,10 @@ rs6000_override_options (const char *def
  	  POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT
  	  | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP
  	  | MASK_MFPGPR},
@@ -3552,7 +4439,7 @@ testsuite/
  	 {"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
  	 {"powerpc64", PROCESSOR_POWERPC64,
  	  POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
-@@ -1549,7 +1941,8 @@ rs6000_override_options (const char *def
+@@ -1549,7 +2035,8 @@ rs6000_override_options (const char *def
      POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
  		     | MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
  		     | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
@@ -3562,7 +4449,7 @@ testsuite/
    };
  
    set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT;
-@@ -1594,10 +1987,6 @@ rs6000_override_options (const char *def
+@@ -1594,10 +2081,6 @@ rs6000_override_options (const char *def
  	}
      }
  
@@ -3573,7 +4460,7 @@ testsuite/
    if (rs6000_cpu == PROCESSOR_PPCE300C2 || rs6000_cpu == PROCESSOR_PPCE300C3
        || rs6000_cpu == PROCESSOR_PPCE500MC)
      {
-@@ -1642,15 +2031,47 @@ rs6000_override_options (const char *def
+@@ -1642,17 +2125,61 @@ rs6000_override_options (const char *def
  	}
      }
  
@@ -3610,7 +4497,7 @@ testsuite/
        if (! strcmp (rs6000_debug_name, "all"))
 -	rs6000_debug_stack = rs6000_debug_arg = 1;
 +	rs6000_debug_stack = rs6000_debug_arg = rs6000_debug_reg
-+	  = rs6000_debug_addr = 1;
++	  = rs6000_debug_addr = rs6000_debug_cost = 1;
        else if (! strcmp (rs6000_debug_name, "stack"))
  	rs6000_debug_stack = 1;
        else if (! strcmp (rs6000_debug_name, "arg"))
@@ -3619,10 +4506,24 @@ testsuite/
 +	rs6000_debug_reg = 1;
 +      else if (! strcmp (rs6000_debug_name, "addr"))
 +	rs6000_debug_addr = 1;
++      else if (! strcmp (rs6000_debug_name, "cost"))
++	rs6000_debug_cost = 1;
        else
  	error ("unknown -mdebug-%s switch", rs6000_debug_name);
++
++      /* If -mdebug=cost or -mdebug=all, replace the cost target hooks with
++	 debug versions that call the real version and then prints debugging
++	 information.  */
++      if (TARGET_DEBUG_COST)
++	{
++	  targetm.rtx_costs = rs6000_debug_rtx_costs;
++	  targetm.address_cost = rs6000_debug_address_cost;
++	  targetm.sched.adjust_cost = rs6000_debug_adjust_cost;
++	}
      }
-@@ -1741,8 +2162,8 @@ rs6000_override_options (const char *def
+ 
+   if (rs6000_traceback_name)
+@@ -1741,8 +2268,8 @@ rs6000_override_options (const char *def
  	rs6000_spe = 0;
        if (!rs6000_explicit_options.float_gprs)
  	rs6000_float_gprs = 0;
@@ -3633,7 +4534,7 @@ testsuite/
      }
  
    /* Detect invalid option combinations with E500.  */
-@@ -1751,12 +2172,14 @@ rs6000_override_options (const char *def
+@@ -1751,12 +2278,14 @@ rs6000_override_options (const char *def
    rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4
  			&& rs6000_cpu != PROCESSOR_POWER5
                          && rs6000_cpu != PROCESSOR_POWER6
@@ -3649,7 +4550,7 @@ testsuite/
  
    rs6000_sched_restricted_insns_priority
      = (rs6000_sched_groups ? 1 : 0);
-@@ -1951,6 +2374,10 @@ rs6000_override_options (const char *def
+@@ -1951,6 +2480,10 @@ rs6000_override_options (const char *def
  	rs6000_cost = &power6_cost;
  	break;
  
@@ -3660,7 +4561,7 @@ testsuite/
        default:
  	gcc_unreachable ();
        }
-@@ -2001,7 +2428,7 @@ rs6000_override_options (const char *def
+@@ -2001,7 +2534,7 @@ rs6000_override_options (const char *def
  static tree
  rs6000_builtin_mask_for_load (void)
  {
@@ -3669,7 +4570,7 @@ testsuite/
      return altivec_builtin_mask_for_load;
    else
      return 0;
-@@ -2015,18 +2442,19 @@ rs6000_builtin_mask_for_load (void)
+@@ -2015,18 +2548,27 @@ rs6000_builtin_mask_for_load (void)
  static tree
  rs6000_builtin_conversion (enum tree_code code, tree type)
  {
@@ -3681,6 +4582,14 @@ testsuite/
      case FIX_TRUNC_EXPR:
        switch (TYPE_MODE (type))
  	{
++	case V2DImode:
++	  if (!VECTOR_UNIT_VSX_P (V2DFmode))
++	    return NULL_TREE;
++
++	  return TYPE_UNSIGNED (type)
++	    ? rs6000_builtin_decls[VSX_BUILTIN_XVCVDPUXDS]
++	    : rs6000_builtin_decls[VSX_BUILTIN_XVCVDPSXDS];
++
  	case V4SImode:
 +	  if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
 +	    return NULL_TREE;
@@ -3694,9 +4603,18 @@ testsuite/
  	default:
  	  return NULL_TREE;
  	}
-@@ -2035,9 +2463,12 @@ rs6000_builtin_conversion (enum tree_cod
+@@ -2034,10 +2576,22 @@ rs6000_builtin_conversion (enum tree_cod
+     case FLOAT_EXPR:
        switch (TYPE_MODE (type))
  	{
++	case V2DImode:
++	  if (!VECTOR_UNIT_VSX_P (V2DFmode))
++	    return NULL_TREE;
++
++	  return TYPE_UNSIGNED (type)
++	    ? rs6000_builtin_decls[VSX_BUILTIN_XVCVUXDSP]
++	    : rs6000_builtin_decls[VSX_BUILTIN_XVCVSXDSP];
++
  	case V4SImode:
 +	  if (VECTOR_UNIT_NONE_P (V4SImode) || VECTOR_UNIT_NONE_P (V4SFmode))
 +	    return NULL_TREE;
@@ -3706,10 +4624,11 @@ testsuite/
 -	    : rs6000_builtin_decls[ALTIVEC_BUILTIN_VCFSX];
 +	    ? rs6000_builtin_decls[VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF]
 +	    : rs6000_builtin_decls[VECTOR_BUILTIN_FLOAT_V4SI_V4SF];
++
  	default:
  	  return NULL_TREE;
  	}
-@@ -2150,6 +2581,14 @@ rs6000_builtin_vec_perm (tree type, tree
+@@ -2150,6 +2704,14 @@ rs6000_builtin_vec_perm (tree type, tree
        d = rs6000_builtin_decls[ALTIVEC_BUILTIN_VPERM_4SF];
        break;
  
@@ -3724,7 +4643,7 @@ testsuite/
      default:
        return NULL_TREE;
      }
-@@ -2229,6 +2668,7 @@ static bool
+@@ -2229,6 +2791,7 @@ static bool
  rs6000_handle_option (size_t code, const char *arg, int value)
  {
    enum fpu_type_t fpu_type = FPU_NONE;
@@ -3732,7 +4651,7 @@ testsuite/
  
    switch (code)
      {
-@@ -2331,14 +2771,14 @@ rs6000_handle_option (size_t code, const
+@@ -2331,14 +2894,14 @@ rs6000_handle_option (size_t code, const
        rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE));
        break;
  
@@ -3754,7 +4673,7 @@ testsuite/
        break;
  
      case OPT_mspe:
-@@ -2967,6 +3407,9 @@ output_vec_const_move (rtx *operands)
+@@ -2967,6 +3530,9 @@ output_vec_const_move (rtx *operands)
    vec = operands[1];
    mode = GET_MODE (dest);
  
@@ -3764,7 +4683,7 @@ testsuite/
    if (TARGET_ALTIVEC)
      {
        rtx splat_vec;
-@@ -3190,20 +3633,21 @@ rs6000_expand_vector_init (rtx target, r
+@@ -3190,20 +3756,21 @@ rs6000_expand_vector_init (rtx target, r
    if (n_var == 0)
      {
        rtx const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0));
@@ -3789,7 +4708,7 @@ testsuite/
  	;	/* Splat vector element.  */
        else
  	{
-@@ -3213,6 +3657,18 @@ rs6000_expand_vector_init (rtx target, r
+@@ -3213,6 +3780,18 @@ rs6000_expand_vector_init (rtx target, r
  	}
      }
  
@@ -3808,7 +4727,7 @@ testsuite/
    /* Store value to stack temp.  Load vector element.  Splat.  */
    if (all_same)
      {
-@@ -3272,6 +3728,13 @@ rs6000_expand_vector_set (rtx target, rt
+@@ -3272,6 +3851,13 @@ rs6000_expand_vector_set (rtx target, rt
    int width = GET_MODE_SIZE (inner_mode);
    int i;
  
@@ -3822,7 +4741,7 @@ testsuite/
    /* Load single variable value.  */
    mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
    emit_move_insn (adjust_address_nv (mem, inner_mode, 0), val);
-@@ -3309,6 +3772,13 @@ rs6000_expand_vector_extract (rtx target
+@@ -3309,6 +3895,13 @@ rs6000_expand_vector_extract (rtx target
    enum machine_mode inner_mode = GET_MODE_INNER (mode);
    rtx mem, x;
  
@@ -3836,7 +4755,7 @@ testsuite/
    /* Allocate mode-sized buffer.  */
    mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
  
-@@ -3627,9 +4097,13 @@ rs6000_legitimate_offset_address_p (enum
+@@ -3627,9 +4220,13 @@ rs6000_legitimate_offset_address_p (enum
      case V8HImode:
      case V4SFmode:
      case V4SImode:
@@ -3846,13 +4765,13 @@ testsuite/
 +      /* AltiVec/VSX vector modes.  Only reg+reg addressing is valid and
  	 constant offset zero should not occur due to canonicalization.  */
 -      return false;
-+      if (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
++      if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode))
 +	return false;
 +      break;
  
      case V4HImode:
      case V2SImode:
-@@ -3646,6 +4120,11 @@ rs6000_legitimate_offset_address_p (enum
+@@ -3646,6 +4243,11 @@ rs6000_legitimate_offset_address_p (enum
        if (TARGET_E500_DOUBLE)
  	return SPE_CONST_OFFSET_OK (offset);
  
@@ -3864,7 +4783,7 @@ testsuite/
      case DDmode:
      case DImode:
        /* On e500v2, we may have:
-@@ -3716,7 +4195,9 @@ avoiding_indexed_address_p (enum machine
+@@ -3716,7 +4318,9 @@ avoiding_indexed_address_p (enum machine
  {
    /* Avoid indexed addressing for modes that have non-indexed
       load/store instruction forms.  */
@@ -3875,25 +4794,33 @@ testsuite/
  }
  
  inline bool
-@@ -3808,25 +4289,30 @@ rtx
+@@ -3808,15 +4412,10 @@ rtx
  rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
  			   enum machine_mode mode)
  {
 +  rtx ret = NULL_RTX;
 +  rtx orig_x = x;
-+
-   if (GET_CODE (x) == SYMBOL_REF)
-     {
-       enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
-       if (model != 0)
+   unsigned int extra = 0;
+ 
+-  if (GET_CODE (x) == SYMBOL_REF)
+-    {
+-      enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
+-      if (model != 0)
 -	return rs6000_legitimize_tls_address (x, model);
-+	ret = rs6000_legitimize_tls_address (x, model);
+-    }
+-
+   switch (mode)
+     {
+     case DFmode:
+@@ -3838,19 +4437,26 @@ rs6000_legitimize_address (rtx x, rtx ol
+       break;
      }
  
 -  if (GET_CODE (x) == PLUS
 -      && GET_CODE (XEXP (x, 0)) == REG
 -      && GET_CODE (XEXP (x, 1)) == CONST_INT
--      && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000
+-      && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000)
+-	  >= 0x10000 - extra)
 -      && !((TARGET_POWERPC64
 -	    && (mode == DImode || mode == TImode)
 -	    && (INTVAL (XEXP (x, 1)) & 3) != 0)
@@ -3902,11 +4829,17 @@ testsuite/
 -	   || (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
 -				      || mode == DImode || mode == DDmode
 -				      || mode == TDmode))))
++  if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x))
++    {
++      enum tls_model model = SYMBOL_REF_TLS_MODEL (x);
++      ret = rs6000_legitimize_tls_address (x, model);
++    }
++
 +  else if (GET_CODE (x) == PLUS
 +	   && GET_CODE (XEXP (x, 0)) == REG
 +	   && GET_CODE (XEXP (x, 1)) == CONST_INT
 +	   && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000)
-+	       >= 0x10000)
++	       >= 0x10000 - extra)
 +	   && !((TARGET_POWERPC64
 +		 && (mode == DImode || mode == TImode)
 +		 && (INTVAL (XEXP (x, 1)) & 3) != 0)
@@ -3919,16 +4852,16 @@ testsuite/
      {
        HOST_WIDE_INT high_int, low_int;
        rtx sum;
-@@ -3834,7 +4320,7 @@ rs6000_legitimize_address (rtx x, rtx ol
+@@ -3860,7 +4466,7 @@ rs6000_legitimize_address (rtx x, rtx ol
        high_int = INTVAL (XEXP (x, 1)) - low_int;
        sum = force_operand (gen_rtx_PLUS (Pmode, XEXP (x, 0),
  					 GEN_INT (high_int)), 0);
--      return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
-+      ret = gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
+-      return plus_constant (sum, low_int);
++      ret = plus_constant (sum, low_int);
      }
    else if (GET_CODE (x) == PLUS
  	   && GET_CODE (XEXP (x, 0)) == REG
-@@ -3850,32 +4336,29 @@ rs6000_legitimize_address (rtx x, rtx ol
+@@ -3876,32 +4482,29 @@ rs6000_legitimize_address (rtx x, rtx ol
  	   && mode != TFmode
  	   && mode != TDmode)
      {
@@ -3973,7 +4906,7 @@ testsuite/
           rtx op1 = XEXP (x, 0);
           rtx op2 = XEXP (x, 1);
           rtx y;
-@@ -3894,12 +4377,12 @@ rs6000_legitimize_address (rtx x, rtx ol
+@@ -3920,12 +4523,12 @@ rs6000_legitimize_address (rtx x, rtx ol
           y = gen_rtx_PLUS (Pmode, op1, op2);
  
           if ((GET_MODE_SIZE (mode) > 8 || mode == DDmode) && REG_P (op2))
@@ -3990,7 +4923,7 @@ testsuite/
      }
    else if (TARGET_ELF
  	   && TARGET_32BIT
-@@ -3915,7 +4398,7 @@ rs6000_legitimize_address (rtx x, rtx ol
+@@ -3941,7 +4544,7 @@ rs6000_legitimize_address (rtx x, rtx ol
      {
        rtx reg = gen_reg_rtx (Pmode);
        emit_insn (gen_elf_high (reg, x));
@@ -3999,7 +4932,7 @@ testsuite/
      }
    else if (TARGET_MACHO && TARGET_32BIT && TARGET_NO_TOC
  	   && ! flag_pic
-@@ -3933,17 +4416,34 @@ rs6000_legitimize_address (rtx x, rtx ol
+@@ -3959,17 +4562,35 @@ rs6000_legitimize_address (rtx x, rtx ol
      {
        rtx reg = gen_reg_rtx (Pmode);
        emit_insn (gen_macho_high (reg, x));
@@ -4031,13 +4964,14 @@ testsuite/
 +	}
 +      else
 +	fprintf (stderr, "NULL returned\n");
++      fprintf (stderr, "\n");
 +    }
 +
 +  return ret;
  }
  
  /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
-@@ -4232,6 +4732,9 @@ rs6000_legitimize_reload_address (rtx x,
+@@ -4258,6 +4879,9 @@ rs6000_legitimize_reload_address (rtx x,
  				  int opnum, int type,
  				  int ind_levels ATTRIBUTE_UNUSED, int *win)
  {
@@ -4047,7 +4981,7 @@ testsuite/
    /* We must recognize output that we have already generated ourselves.  */
    if (GET_CODE (x) == PLUS
        && GET_CODE (XEXP (x, 0)) == PLUS
-@@ -4243,17 +4746,17 @@ rs6000_legitimize_reload_address (rtx x,
+@@ -4269,17 +4893,17 @@ rs6000_legitimize_reload_address (rtx x,
  		   BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
  		   opnum, (enum reload_type)type);
        *win = 1;
@@ -4073,7 +5007,7 @@ testsuite/
      {
        /* Result of previous invocation of this function on Darwin
  	 floating point constant.  */
-@@ -4261,40 +4764,42 @@ rs6000_legitimize_reload_address (rtx x,
+@@ -4287,40 +4911,40 @@ rs6000_legitimize_reload_address (rtx x,
  		   BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
  		   opnum, (enum reload_type)type);
        *win = 1;
@@ -4099,8 +5033,7 @@ testsuite/
 +	   && REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
 +	   && GET_CODE (XEXP (x, 1)) == CONST_INT
 +	   && (INTVAL (XEXP (x, 1)) & 3) != 0
-+	   && !ALTIVEC_VECTOR_MODE (mode)
-+	   && !VSX_VECTOR_MODE (mode)
++	   && VECTOR_MEM_NONE_P (mode)
 +	   && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
 +	   && TARGET_POWERPC64)
      {
@@ -4132,12 +5065,11 @@ testsuite/
 +	   && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
 +				       || mode == DDmode || mode == TDmode
 +				       || mode == DImode))
-+	   && !ALTIVEC_VECTOR_MODE (mode)
-+	   && !VSX_VECTOR_MODE (mode))
++	   && VECTOR_MEM_NONE_P (mode))
      {
        HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
        HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
-@@ -4305,42 +4810,44 @@ rs6000_legitimize_reload_address (rtx x,
+@@ -4331,42 +4955,45 @@ rs6000_legitimize_reload_address (rtx x,
        if (high + low != val)
  	{
  	  *win = 0;
@@ -4202,6 +5134,7 @@ testsuite/
 +	   /* Don't do this for TFmode or TDmode, since the result isn't
 +	      offsettable.  The same goes for DImode without 64-bit gprs and
 +	      DFmode and DDmode without fprs.  */
++	   && VECTOR_MEM_NONE_P (mode)
 +	   && mode != TFmode
 +	   && mode != TDmode
 +	   && (mode != DImode || TARGET_POWERPC64)
@@ -4210,7 +5143,7 @@ testsuite/
      {
  #if TARGET_MACHO
        if (flag_pic)
-@@ -4359,37 +4866,61 @@ rs6000_legitimize_reload_address (rtx x,
+@@ -4385,37 +5012,63 @@ rs6000_legitimize_reload_address (rtx x,
  		   BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
  		   opnum, (enum reload_type)type);
        *win = 1;
@@ -4229,7 +5162,7 @@ testsuite/
 -      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
 -      && GET_CODE (XEXP (x, 1)) == CONST_INT
 -      && INTVAL (XEXP (x, 1)) == -16)
-+  else if (VECTOR_MEM_ALTIVEC_P (mode)
++  else if (VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
 +	   && GET_CODE (x) == AND
 +	   && GET_CODE (XEXP (x, 0)) == PLUS
 +	   && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
@@ -4262,9 +5195,7 @@ testsuite/
 +    {
 +      *win = 0;
 +      ret = x;
-     }
--  *win = 0;
--  return x;
++    }
 +
 +  if (TARGET_DEBUG_ADDR)
 +    {
@@ -4283,13 +5214,17 @@ testsuite/
 +	  fprintf (stderr, "New address:\n");
 +	  debug_rtx (ret);
 +	}
-+    }
++
++      fprintf (stderr, "\n");
+     }
+-  *win = 0;
+-  return x;
 +
 +  return ret;
  }
  
  /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
-@@ -4412,77 +4943,101 @@ rs6000_legitimize_reload_address (rtx x,
+@@ -4438,77 +5091,101 @@ rs6000_legitimize_reload_address (rtx x,
  int
  rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
  {
@@ -4297,9 +5232,10 @@ testsuite/
 +  rtx orig_x = x;
 +
    /* If this is an unaligned stvx/ldvx type address, discard the outer AND.  */
-   if (TARGET_ALTIVEC
+-  if (TARGET_ALTIVEC
 -      && ALTIVEC_VECTOR_MODE (mode)
-+      && (ALTIVEC_VECTOR_MODE (mode) || VSX_VECTOR_MODE (mode))
++  if ((TARGET_ALTIVEC || TARGET_VSX)
++      && VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
        && GET_CODE (x) == AND
        && GET_CODE (XEXP (x, 1)) == CONST_INT
        && INTVAL (XEXP (x, 1)) == -16)
@@ -4328,8 +5264,7 @@ testsuite/
 +  else if (legitimate_indirect_address_p (x, reg_ok_strict))
 +    ret = 1;
 +  else if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
-+	   && !VECTOR_MEM_ALTIVEC_P (mode)
-+	   /* && !VECTOR_MEM_VSX_P (mode) */
++	   && !VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)
 +	   && (TARGET_SPE && !SPE_VECTOR_MODE (mode))
 +	   && mode != TFmode
 +	   && mode != TDmode
@@ -4447,13 +5382,14 @@ testsuite/
 +	       GET_MODE_NAME (mode),
 +	       reg_ok_strict);
 +      debug_rtx (orig_x);
++      fprintf (stderr, "\n");
 +    }
 +
 +  return ret;
  }
  
  /* Go to LABEL if ADDR (a legitimate address expression)
-@@ -4499,28 +5054,40 @@ rs6000_legitimate_address (enum machine_
+@@ -4525,28 +5202,46 @@ rs6000_legitimate_address (enum machine_
  bool
  rs6000_mode_dependent_address (rtx addr)
  {
@@ -4480,6 +5416,11 @@ testsuite/
 -      return TARGET_UPDATE;
 +      ret = (TARGET_UPDATE != 0);
 +      break;
++
++      /* AND is only allowed in Altivec loads.  */
++    case AND:
++      ret = true;
++      break;
  
      default:
        break;
@@ -4489,16 +5430,17 @@ testsuite/
 +  if (TARGET_DEBUG_ADDR)
 +    {
 +      fprintf (stderr,
-+	       "\nrs6000_mode_dependent_address: ret = %d\n",
-+	       (int)ret);
++	       "\nrs6000_mode_dependent_address: ret = %s\n",
++	       ret ? "true" : "false");
 +      debug_rtx (addr);
++      fprintf (stderr, "\n");
 +    }
 +
 +  return ret;
  }
  
  /* Implement FIND_BASE_TERM.  */
-@@ -4571,43 +5138,6 @@ rs6000_offsettable_memref_p (rtx op)
+@@ -4597,43 +5292,6 @@ rs6000_offsettable_memref_p (rtx op)
    return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1);
  }
  
@@ -4542,7 +5484,7 @@ testsuite/
  /* Change register usage conditional on target flags.  */
  void
  rs6000_conditional_register_usage (void)
-@@ -4672,14 +5202,14 @@ rs6000_conditional_register_usage (void)
+@@ -4698,14 +5356,14 @@ rs6000_conditional_register_usage (void)
  	= call_really_used_regs[14] = 1;
      }
  
@@ -4559,7 +5501,28 @@ testsuite/
      global_regs[VSCR_REGNO] = 1;
  
    if (TARGET_ALTIVEC_ABI)
-@@ -5101,6 +5631,8 @@ rs6000_emit_move (rtx dest, rtx source, 
+@@ -4923,6 +5581,20 @@ rs6000_emit_move (rtx dest, rtx source, 
+   operands[0] = dest;
+   operands[1] = source;
+ 
++  if (TARGET_DEBUG_ADDR)
++    {
++      fprintf (stderr,
++	       "\nrs6000_emit_move: mode = %s, reload_in_progress = %d, "
++	       "reload_completed = %d, can_create_pseudos = %d.\ndest:\n",
++	       GET_MODE_NAME (mode),
++	       reload_in_progress,
++	       reload_completed,
++	       can_create_pseudo_p ());
++      debug_rtx (dest);
++      fprintf (stderr, "source:\n");
++      debug_rtx (source);
++    }
++
+   /* Sanity checks.  Check that we get CONST_DOUBLE only when we should.  */
+   if (GET_CODE (operands[1]) == CONST_DOUBLE
+       && ! FLOAT_MODE_P (mode)
+@@ -5127,6 +5799,8 @@ rs6000_emit_move (rtx dest, rtx source, 
      case V2SFmode:
      case V2SImode:
      case V1DImode:
@@ -4568,7 +5531,7 @@ testsuite/
        if (CONSTANT_P (operands[1])
  	  && !easy_vector_constant (operands[1], mode))
  	operands[1] = force_const_mem (mode, operands[1]);
-@@ -5270,6 +5802,9 @@ rs6000_emit_move (rtx dest, rtx source, 
+@@ -5296,6 +5970,9 @@ rs6000_emit_move (rtx dest, rtx source, 
        break;
  
      case TImode:
@@ -4578,7 +5541,7 @@ testsuite/
        rs6000_eliminate_indexed_memrefs (operands);
  
        if (TARGET_POWER)
-@@ -5285,7 +5820,7 @@ rs6000_emit_move (rtx dest, rtx source, 
+@@ -5311,7 +5988,7 @@ rs6000_emit_move (rtx dest, rtx source, 
        break;
  
      default:
@@ -4587,7 +5550,7 @@ testsuite/
      }
  
    /* Above, we may have called force_const_mem which may have returned
-@@ -5305,10 +5840,10 @@ rs6000_emit_move (rtx dest, rtx source, 
+@@ -5331,10 +6008,10 @@ rs6000_emit_move (rtx dest, rtx source, 
     && TARGET_HARD_FLOAT && TARGET_FPRS)
  
  /* Nonzero if we can use an AltiVec register to pass this arg.  */
@@ -4602,7 +5565,7 @@ testsuite/
     && (NAMED))
  
  /* Return a nonzero value to say to return the function value in
-@@ -5549,7 +6084,7 @@ function_arg_boundary (enum machine_mode
+@@ -5575,7 +6252,7 @@ function_arg_boundary (enum machine_mode
  	       && int_size_in_bytes (type) >= 8
  	       && int_size_in_bytes (type) < 16))
      return 64;
@@ -4611,7 +5574,7 @@ testsuite/
  	   || (type && TREE_CODE (type) == VECTOR_TYPE
  	       && int_size_in_bytes (type) >= 16))
      return 128;
-@@ -5694,7 +6229,7 @@ function_arg_advance (CUMULATIVE_ARGS *c
+@@ -5720,7 +6397,7 @@ function_arg_advance (CUMULATIVE_ARGS *c
      cum->nargs_prototype--;
  
    if (TARGET_ALTIVEC_ABI
@@ -4620,7 +5583,7 @@ testsuite/
  	  || (type && TREE_CODE (type) == VECTOR_TYPE
  	      && int_size_in_bytes (type) == 16)))
      {
-@@ -6288,7 +6823,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum
+@@ -6314,7 +6991,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum
      else
        return gen_rtx_REG (mode, cum->vregno);
    else if (TARGET_ALTIVEC_ABI
@@ -4629,7 +5592,7 @@ testsuite/
  	       || (type && TREE_CODE (type) == VECTOR_TYPE
  		   && int_size_in_bytes (type) == 16)))
      {
-@@ -7212,10 +7747,13 @@ static const struct builtin_description 
+@@ -7238,10 +7915,13 @@ static const struct builtin_description 
    { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
    { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
    { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
@@ -4647,7 +5610,24 @@ testsuite/
    { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
    { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
    { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
-@@ -7289,18 +7827,18 @@ static struct builtin_description bdesc_
+@@ -7263,6 +7943,16 @@ static const struct builtin_description 
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL },
+ 
++  { MASK_VSX, CODE_FOR_vsx_fmaddv2df4, "__builtin_vsx_xvmadddp", VSX_BUILTIN_XVMADDDP },
++  { MASK_VSX, CODE_FOR_vsx_fmsubv2df4, "__builtin_vsx_xvmsubdp", VSX_BUILTIN_XVMSUBDP },
++  { MASK_VSX, CODE_FOR_vsx_fnmaddv2df4, "__builtin_vsx_xvnmadddp", VSX_BUILTIN_XVNMADDDP },
++  { MASK_VSX, CODE_FOR_vsx_fnmsubv2df4, "__builtin_vsx_xvnmsubdp", VSX_BUILTIN_XVNMSUBDP },
++
++  { MASK_VSX, CODE_FOR_vsx_fmaddv4sf4, "__builtin_vsx_xvmaddsp", VSX_BUILTIN_XVMADDSP },
++  { MASK_VSX, CODE_FOR_vsx_fmsubv4sf4, "__builtin_vsx_xvmsubsp", VSX_BUILTIN_XVMSUBSP },
++  { MASK_VSX, CODE_FOR_vsx_fnmaddv4sf4, "__builtin_vsx_xvnmaddsp", VSX_BUILTIN_XVNMADDSP },
++  { MASK_VSX, CODE_FOR_vsx_fnmsubv4sf4, "__builtin_vsx_xvnmsubsp", VSX_BUILTIN_XVNMSUBSP },
++
+   { 0, CODE_FOR_paired_msub, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB },
+   { 0, CODE_FOR_paired_madd, "__builtin_paired_madd", PAIRED_BUILTIN_MADD },
+   { 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 },
+@@ -7315,18 +8005,18 @@ static struct builtin_description bdesc_
    { MASK_ALTIVEC, CODE_FOR_altivec_vcfux, "__builtin_altivec_vcfux", ALTIVEC_BUILTIN_VCFUX },
    { MASK_ALTIVEC, CODE_FOR_altivec_vcfsx, "__builtin_altivec_vcfsx", ALTIVEC_BUILTIN_VCFSX },
    { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
@@ -4678,7 +5658,7 @@ testsuite/
    { MASK_ALTIVEC, CODE_FOR_altivec_vctsxs, "__builtin_altivec_vctsxs", ALTIVEC_BUILTIN_VCTSXS },
    { MASK_ALTIVEC, CODE_FOR_altivec_vctuxs, "__builtin_altivec_vctuxs", ALTIVEC_BUILTIN_VCTUXS },
    { MASK_ALTIVEC, CODE_FOR_umaxv16qi3, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
-@@ -7331,7 +7869,7 @@ static struct builtin_description bdesc_
+@@ -7357,7 +8047,7 @@ static struct builtin_description bdesc_
    { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
    { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
    { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
@@ -4687,7 +5667,133 @@ testsuite/
    { MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
    { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
    { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
-@@ -7796,6 +8334,11 @@ static struct builtin_description bdesc_
+@@ -7405,8 +8095,24 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
+   { MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
+ 
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
++  { MASK_VSX, CODE_FOR_addv2df3, "__builtin_vsx_xvadddp", VSX_BUILTIN_XVADDDP },
++  { MASK_VSX, CODE_FOR_subv2df3, "__builtin_vsx_xvsubdp", VSX_BUILTIN_XVSUBDP },
++  { MASK_VSX, CODE_FOR_mulv2df3, "__builtin_vsx_xvmuldp", VSX_BUILTIN_XVMULDP },
++  { MASK_VSX, CODE_FOR_divv2df3, "__builtin_vsx_xvdivdp", VSX_BUILTIN_XVDIVDP },
++  { MASK_VSX, CODE_FOR_sminv2df3, "__builtin_vsx_xvmindp", VSX_BUILTIN_XVMINDP },
++  { MASK_VSX, CODE_FOR_smaxv2df3, "__builtin_vsx_xvmaxdp", VSX_BUILTIN_XVMAXDP },
++  { MASK_VSX, CODE_FOR_vsx_tdivv2df3, "__builtin_vsx_xvtdivdp", VSX_BUILTIN_XVTDIVDP },
++
++  { MASK_VSX, CODE_FOR_addv4sf3, "__builtin_vsx_xvaddsp", VSX_BUILTIN_XVADDSP },
++  { MASK_VSX, CODE_FOR_subv4sf3, "__builtin_vsx_xvsubsp", VSX_BUILTIN_XVSUBSP },
++  { MASK_VSX, CODE_FOR_mulv4sf3, "__builtin_vsx_xvmulsp", VSX_BUILTIN_XVMULSP },
++  { MASK_VSX, CODE_FOR_divv4sf3, "__builtin_vsx_xvdivsp", VSX_BUILTIN_XVDIVSP },
++  { MASK_VSX, CODE_FOR_sminv4sf3, "__builtin_vsx_xvminsp", VSX_BUILTIN_XVMINSP },
++  { MASK_VSX, CODE_FOR_smaxv4sf3, "__builtin_vsx_xvmaxsp", VSX_BUILTIN_XVMAXSP },
++  { MASK_VSX, CODE_FOR_vsx_tdivv4sf3, "__builtin_vsx_xvtdivsp", VSX_BUILTIN_XVTDIVSP },
++
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhm", ALTIVEC_BUILTIN_VEC_VADDUHM },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubm", ALTIVEC_BUILTIN_VEC_VADDUBM },
+@@ -7418,8 +8124,8 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhs", ALTIVEC_BUILTIN_VEC_VADDUHS },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsbs", ALTIVEC_BUILTIN_VEC_VADDSBS },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubs", ALTIVEC_BUILTIN_VEC_VADDUBS },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_avg", ALTIVEC_BUILTIN_VEC_AVG },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsw", ALTIVEC_BUILTIN_VEC_VAVGSW },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguw", ALTIVEC_BUILTIN_VEC_VAVGUW },
+@@ -7444,8 +8150,8 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtub", ALTIVEC_BUILTIN_VEC_VCMPGTUB },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmple", ALTIVEC_BUILTIN_VEC_CMPLE },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmplt", ALTIVEC_BUILTIN_VEC_CMPLT },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsw", ALTIVEC_BUILTIN_VEC_VMAXSW },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuw", ALTIVEC_BUILTIN_VEC_VMAXUW },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsh", ALTIVEC_BUILTIN_VEC_VMAXSH },
+@@ -7460,8 +8166,8 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglw", ALTIVEC_BUILTIN_VEC_VMRGLW },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglh", ALTIVEC_BUILTIN_VEC_VMRGLH },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglb", ALTIVEC_BUILTIN_VEC_VMRGLB },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsw", ALTIVEC_BUILTIN_VEC_VMINSW },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuw", ALTIVEC_BUILTIN_VEC_VMINUW },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsh", ALTIVEC_BUILTIN_VEC_VMINSH },
+@@ -7478,8 +8184,8 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulouh", ALTIVEC_BUILTIN_VEC_VMULOUH },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosb", ALTIVEC_BUILTIN_VEC_VMULOSB },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuloub", ALTIVEC_BUILTIN_VEC_VMULOUB },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_pack", ALTIVEC_BUILTIN_VEC_PACK },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwum", ALTIVEC_BUILTIN_VEC_VPKUWUM },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhum", ALTIVEC_BUILTIN_VEC_VPKUHUM },
+@@ -7512,8 +8218,8 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrab", ALTIVEC_BUILTIN_VEC_VSRAB },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_srl", ALTIVEC_BUILTIN_VEC_SRL },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sro", ALTIVEC_BUILTIN_VEC_SRO },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuwm", ALTIVEC_BUILTIN_VEC_VSUBUWM },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhm", ALTIVEC_BUILTIN_VEC_VSUBUHM },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububm", ALTIVEC_BUILTIN_VEC_VSUBUBM },
+@@ -7531,7 +8237,10 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4ubs", ALTIVEC_BUILTIN_VEC_VSUM4UBS },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum2s", ALTIVEC_BUILTIN_VEC_SUM2S },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS },
+-  { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
++  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
++
++  { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_mul", VSX_BUILTIN_VEC_MUL },
++  { MASK_VSX, CODE_FOR_nothing, "__builtin_vec_div", VSX_BUILTIN_VEC_DIV },
+ 
+   { 0, CODE_FOR_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 },
+   { 0, CODE_FOR_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 },
+@@ -7776,7 +8485,11 @@ static const struct builtin_description 
+   { MASK_ALTIVEC, CODE_FOR_absv16qi2, "__builtin_altivec_abs_v16qi", ALTIVEC_BUILTIN_ABS_V16QI },
+   { MASK_ALTIVEC, CODE_FOR_altivec_abss_v4si, "__builtin_altivec_abss_v4si", ALTIVEC_BUILTIN_ABSS_V4SI },
+   { MASK_ALTIVEC, CODE_FOR_altivec_abss_v8hi, "__builtin_altivec_abss_v8hi", ALTIVEC_BUILTIN_ABSS_V8HI },
+-  { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI }
++  { MASK_ALTIVEC, CODE_FOR_altivec_abss_v16qi, "__builtin_altivec_abss_v16qi", ALTIVEC_BUILTIN_ABSS_V16QI },
++  { MASK_VSX, CODE_FOR_absv2df2, "__builtin_vsx_xvabsdp", VSX_BUILTIN_XVABSDP },
++  { MASK_VSX, CODE_FOR_vsx_nabsv2df2, "__builtin_vsx_xvnabsdp", VSX_BUILTIN_XVNABSDP },
++  { MASK_VSX, CODE_FOR_absv4sf2, "__builtin_vsx_xvabssp", VSX_BUILTIN_XVABSSP },
++  { MASK_VSX, CODE_FOR_vsx_nabsv4sf2, "__builtin_vsx_xvnabssp", VSX_BUILTIN_XVNABSSP },
+ };
+ 
+ /* Simple unary operations: VECb = foo (unsigned literal) or VECb =
+@@ -7802,6 +8515,18 @@ static struct builtin_description bdesc_
+   { MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
+   { MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
+ 
++  { MASK_VSX, CODE_FOR_negv2df2, "__builtin_vsx_xvnegdp", VSX_BUILTIN_XVNEGDP },
++  { MASK_VSX, CODE_FOR_sqrtv2df2, "__builtin_vsx_xvsqrtdp", VSX_BUILTIN_XVSQRTDP },
++  { MASK_VSX, CODE_FOR_vsx_rsqrtev2df2, "__builtin_vsx_xvrsqrtedp", VSX_BUILTIN_XVRSQRTEDP },
++  { MASK_VSX, CODE_FOR_vsx_tsqrtv2df2, "__builtin_vsx_xvtsqrtdp", VSX_BUILTIN_XVTSQRTDP },
++  { MASK_VSX, CODE_FOR_vsx_frev2df2, "__builtin_vsx_xvredp", VSX_BUILTIN_XVREDP },
++
++  { MASK_VSX, CODE_FOR_negv4sf2, "__builtin_vsx_xvnegsp", VSX_BUILTIN_XVNEGSP },
++  { MASK_VSX, CODE_FOR_sqrtv4sf2, "__builtin_vsx_xvsqrtsp", VSX_BUILTIN_XVSQRTSP },
++  { MASK_VSX, CODE_FOR_vsx_rsqrtev4sf2, "__builtin_vsx_xvrsqrtesp", VSX_BUILTIN_XVRSQRTESP },
++  { MASK_VSX, CODE_FOR_vsx_tsqrtv4sf2, "__builtin_vsx_xvtsqrtsp", VSX_BUILTIN_XVTSQRTSP },
++  { MASK_VSX, CODE_FOR_vsx_frev4sf2, "__builtin_vsx_xvresp", VSX_BUILTIN_XVRESP },
++
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS },
+   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL },
+@@ -7822,6 +8547,20 @@ static struct builtin_description bdesc_
    { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsh", ALTIVEC_BUILTIN_VEC_VUPKLSH },
    { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsb", ALTIVEC_BUILTIN_VEC_VUPKLSB },
  
@@ -4696,10 +5802,19 @@ testsuite/
 +  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vec_fix_sfsi", VECTOR_BUILTIN_FIX_V4SF_V4SI },
 +  { MASK_ALTIVEC|MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vec_fixuns_sfsi", VECTOR_BUILTIN_FIXUNS_V4SF_V4SI },
 +
++  { MASK_VSX, CODE_FOR_floatv2div2df2, "__builtin_vsx_xvcvsxddp", VSX_BUILTIN_XVCVSXDDP },
++  { MASK_VSX, CODE_FOR_unsigned_floatv2div2df2, "__builtin_vsx_xvcvuxddp", VSX_BUILTIN_XVCVUXDDP },
++  { MASK_VSX, CODE_FOR_fix_truncv2dfv2di2, "__builtin_vsx_xvdpsxds", VSX_BUILTIN_XVCVDPSXDS },
++  { MASK_VSX, CODE_FOR_fixuns_truncv2dfv2di2, "__builtin_vsx_xvdpuxds", VSX_BUILTIN_XVCVDPUXDS },
++  { MASK_VSX, CODE_FOR_floatv4siv4sf2, "__builtin_vsx_xvcvsxwsp", VSX_BUILTIN_XVCVSXDSP },
++  { MASK_VSX, CODE_FOR_unsigned_floatv4siv4sf2, "__builtin_vsx_xvcvuxwsp", VSX_BUILTIN_XVCVUXWSP },
++  { MASK_VSX, CODE_FOR_fix_truncv4sfv4si2, "__builtin_vsx_xvspsxws", VSX_BUILTIN_XVCVSPSXWS },
++  { MASK_VSX, CODE_FOR_fixuns_truncv4sfv4si2, "__builtin_vsx_xvspuxws", VSX_BUILTIN_XVCVSPUXWS },
++
    /* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
       end with SPE_BUILTIN_EVSUBFUSIAAW.  */
    { 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
-@@ -8352,16 +8895,16 @@ altivec_expand_ld_builtin (tree exp, rtx
+@@ -8378,16 +9117,16 @@ altivec_expand_ld_builtin (tree exp, rtx
    switch (fcode)
      {
      case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
@@ -4720,7 +5835,7 @@ testsuite/
        break;
      default:
        *expandedp = false;
-@@ -8405,16 +8948,16 @@ altivec_expand_st_builtin (tree exp, rtx
+@@ -8431,16 +9170,16 @@ altivec_expand_st_builtin (tree exp, rtx
    switch (fcode)
      {
      case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
@@ -4741,7 +5856,57 @@ testsuite/
        break;
      default:
        *expandedp = false;
-@@ -9372,6 +9915,8 @@ rs6000_init_builtins (void)
+@@ -8835,6 +9574,26 @@ altivec_expand_builtin (tree exp, rtx ta
+ /* Expand the builtin in EXP and store the result in TARGET.  Store
+    true in *EXPANDEDP if we found a builtin to expand.  */
+ static rtx
++vsx_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, bool *expandedp)
++{
++  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
++  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
++
++  if (fcode >= VSX_BUILTIN_OVERLOADED_FIRST
++      && fcode <= VSX_BUILTIN_OVERLOADED_LAST)
++    {
++      *expandedp = true;
++      error ("unresolved overload for vsx builtin %qF", fndecl);
++      return const0_rtx;
++    }
++
++  *expandedp = false;
++  return NULL_RTX;
++}
++
++/* Expand the builtin in EXP and store the result in TARGET.  Store
++   true in *EXPANDEDP if we found a builtin to expand.  */
++static rtx
+ paired_expand_builtin (tree exp, rtx target, bool * expandedp)
+ {
+   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+@@ -9346,6 +10105,13 @@ rs6000_expand_builtin (tree exp, rtx tar
+       if (success)
+ 	return ret;
+     }
++  if (TARGET_VSX)
++    {
++      ret = vsx_expand_builtin (exp, target, &success);
++
++      if (success)
++	return ret;
++    }
+   if (TARGET_SPE)
+     {
+       ret = spe_expand_builtin (exp, target, &success);
+@@ -9361,7 +10127,7 @@ rs6000_expand_builtin (tree exp, rtx tar
+ 	return ret;
+     }  
+ 
+-  gcc_assert (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT);
++  gcc_assert (TARGET_ALTIVEC || TARGET_VSX || TARGET_SPE || TARGET_PAIRED_FLOAT);
+ 
+   /* Handle simple unary operations.  */
+   d = (struct builtin_description *) bdesc_1arg;
+@@ -9398,6 +10164,8 @@ rs6000_init_builtins (void)
  {
    V2SI_type_node = build_vector_type (intSI_type_node, 2);
    V2SF_type_node = build_vector_type (float_type_node, 2);
@@ -4750,7 +5915,7 @@ testsuite/
    V4HI_type_node = build_vector_type (intHI_type_node, 4);
    V4SI_type_node = build_vector_type (intSI_type_node, 4);
    V4SF_type_node = build_vector_type (float_type_node, 4);
-@@ -9404,7 +9949,10 @@ rs6000_init_builtins (void)
+@@ -9430,7 +10198,10 @@ rs6000_init_builtins (void)
    uintHI_type_internal_node = unsigned_intHI_type_node;
    intSI_type_internal_node = intSI_type_node;
    uintSI_type_internal_node = unsigned_intSI_type_node;
@@ -4761,7 +5926,7 @@ testsuite/
    void_type_internal_node = void_type_node;
  
    (*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
-@@ -9462,13 +10010,18 @@ rs6000_init_builtins (void)
+@@ -9488,13 +10259,18 @@ rs6000_init_builtins (void)
  					    get_identifier ("__vector __pixel"),
  					    pixel_V8HI_type_node));
  
@@ -4781,10 +5946,41 @@ testsuite/
      rs6000_common_init_builtins ();
    if (TARGET_PPC_GFXOPT)
      {
-@@ -10407,6 +10960,26 @@ rs6000_common_init_builtins (void)
+@@ -9957,6 +10733,8 @@ altivec_init_builtins (void)
+     = build_function_type_list (V16QI_type_node, V16QI_type_node, NULL_TREE);
+   tree v4sf_ftype_v4sf
+     = build_function_type_list (V4SF_type_node, V4SF_type_node, NULL_TREE);
++  tree v2df_ftype_v2df
++    = build_function_type_list (V2DF_type_node, V2DF_type_node, NULL_TREE);
+   tree void_ftype_pcvoid_int_int
+     = build_function_type_list (void_type_node,
+ 				pcvoid_type_node, integer_type_node,
+@@ -10114,6 +10892,9 @@ altivec_init_builtins (void)
+ 	case V4SFmode:
+ 	  type = v4sf_ftype_v4sf;
+ 	  break;
++	case V2DFmode:
++	  type = v2df_ftype_v2df;
++	  break;
+ 	default:
+ 	  gcc_unreachable ();
+ 	}
+@@ -10433,6 +11214,38 @@ rs6000_common_init_builtins (void)
    tree int_ftype_v8hi_v8hi
      = build_function_type_list (integer_type_node,
  				V8HI_type_node, V8HI_type_node, NULL_TREE);
++  tree v2di_ftype_v2df
++    = build_function_type_list (V2DI_type_node,
++				V2DF_type_node, NULL_TREE);
++  tree v2df_ftype_v2df
++    = build_function_type_list (V2DF_type_node,
++				V2DF_type_node, NULL_TREE);
++  tree v2df_ftype_v2di
++    = build_function_type_list (V2DF_type_node,
++				V2DI_type_node, NULL_TREE);
++  tree v2df_ftype_v2df_v2df
++    = build_function_type_list (V2DF_type_node,
++				V2DF_type_node, V2DF_type_node, NULL_TREE);
 +  tree v2df_ftype_v2df_v2df_v2df
 +    = build_function_type_list (V2DF_type_node,
 +				V2DF_type_node, V2DF_type_node,
@@ -4808,7 +6004,7 @@ testsuite/
  
    /* Add the simple ternary operators.  */
    d = bdesc_3arg;
-@@ -10443,6 +11016,12 @@ rs6000_common_init_builtins (void)
+@@ -10469,6 +11282,12 @@ rs6000_common_init_builtins (void)
  	    case VOIDmode:
  	      type = opaque_ftype_opaque_opaque_opaque;
  	      break;
@@ -4821,7 +6017,7 @@ testsuite/
  	    case V4SImode:
  	      type = v4si_ftype_v4si_v4si_v4si;
  	      break;
-@@ -10466,6 +11045,12 @@ rs6000_common_init_builtins (void)
+@@ -10492,6 +11311,12 @@ rs6000_common_init_builtins (void)
  	{
  	  switch (mode0)
  	    {
@@ -4834,7 +6030,26 @@ testsuite/
  	    case V4SImode:
  	      type = v4si_ftype_v4si_v4si_v16qi;
  	      break;
-@@ -10721,6 +11306,10 @@ rs6000_common_init_builtins (void)
+@@ -10577,6 +11402,9 @@ rs6000_common_init_builtins (void)
+ 	    case VOIDmode:
+ 	      type = opaque_ftype_opaque_opaque;
+ 	      break;
++	    case V2DFmode:
++	      type = v2df_ftype_v2df_v2df;
++	      break;
+ 	    case V4SFmode:
+ 	      type = v4sf_ftype_v4sf_v4sf;
+ 	      break;
+@@ -10726,6 +11554,8 @@ rs6000_common_init_builtins (void)
+ 	type = v16qi_ftype_int;
+       else if (mode0 == VOIDmode && mode1 == VOIDmode)
+ 	type = opaque_ftype_opaque;
++      else if (mode0 == V2DFmode && mode1 == V2DFmode)
++	type = v2df_ftype_v2df;
+       else if (mode0 == V4SFmode && mode1 == V4SFmode)
+ 	type = v4sf_ftype_v4sf;
+       else if (mode0 == V8HImode && mode1 == V16QImode)
+@@ -10747,6 +11577,14 @@ rs6000_common_init_builtins (void)
  	type = v2si_ftype_v2sf;
        else if (mode0 == V2SImode && mode1 == QImode)
  	type = v2si_ftype_char;
@@ -4842,10 +6057,332 @@ testsuite/
 +	type = v4si_ftype_v4sf;
 +      else if (mode0 == V4SFmode && mode1 == V4SImode)
 +	type = v4sf_ftype_v4si;
++      else if (mode0 == V2DImode && mode1 == V2DFmode)
++	type = v2di_ftype_v2df;
++      else if (mode0 == V2DFmode && mode1 == V2DImode)
++	type = v2df_ftype_v2di;
        else
  	gcc_unreachable ();
  
-@@ -11601,13 +12190,101 @@ rs6000_instantiate_decls (void)
+@@ -11529,8 +12367,10 @@ rtx
+ rs6000_secondary_memory_needed_rtx (enum machine_mode mode)
+ {
+   static bool eliminated = false;
++  rtx ret;
++
+   if (mode != SDmode)
+-    return assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
++    ret = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
+   else
+     {
+       rtx mem = cfun->machine->sdmode_stack_slot;
+@@ -11542,8 +12382,21 @@ rs6000_secondary_memory_needed_rtx (enum
+ 	  cfun->machine->sdmode_stack_slot = mem;
+ 	  eliminated = true;
+ 	}
+-      return mem;
++      ret = mem;
++    }
++
++  if (TARGET_DEBUG_ADDR)
++    {
++      fprintf (stderr, "rs6000_secondary_memory_needed_rtx, mode %s, rtx:\n",
++	       GET_MODE_NAME (mode));
++      if (!ret)
++	fprintf (stderr, "\tNULL_RTX\n");
++      else
++	debug_rtx (ret);
++      fprintf (stderr, "\n");
+     }
++
++  return ret;
+ }
+ 
+ static tree
+@@ -11577,6 +12430,282 @@ rs6000_check_sdmode (tree *tp, int *walk
+   return NULL_TREE;
+ }
+ 
++enum reload_reg_type {
++  GPR_REGISTER_TYPE,
++  VECTOR_REGISTER_TYPE,
++  OTHER_REGISTER_TYPE
++};
++
++static enum reload_reg_type
++rs6000_reload_register_type (enum reg_class rclass)
++{
++  switch (rclass)
++    {
++    case GENERAL_REGS:
++    case BASE_REGS:
++      return GPR_REGISTER_TYPE;
++
++    case FLOAT_REGS:
++    case ALTIVEC_REGS:
++    case VSX_REGS:
++      return VECTOR_REGISTER_TYPE;
++
++    default:
++      return OTHER_REGISTER_TYPE;
++    }
++}
++
++/* Inform reload about cases where moving X with a mode MODE to a register in
++   RCLASS requires an extra scratch or immediate register.  Return the class
++   needed for the immediate register.
++
++   For VSX and Altivec, we may need a register to convert sp+offset into
++   reg+sp.  */
++
++static enum reg_class
++rs6000_secondary_reload (bool in_p,
++			 rtx x,
++			 enum reg_class rclass,
++			 enum machine_mode mode,
++			 secondary_reload_info *sri)
++{
++  enum reg_class ret;
++  enum insn_code icode;
++
++  /* Convert vector loads and stores into gprs to use an additional base
++     register.  */
++  icode = rs6000_vector_reload[mode][in_p != false];
++  if (icode != CODE_FOR_nothing)
++    {
++      ret = NO_REGS;
++      sri->icode = CODE_FOR_nothing;
++      sri->extra_cost = 0;
++
++      if (GET_CODE (x) == MEM)
++	{
++	  rtx addr = XEXP (x, 0);
++
++	  /* Loads to and stores from gprs can do reg+offset, and wouldn't need
++	     an extra register in that case, but it would need an extra
++	     register if the addressing is reg+reg or (reg+reg)&(-16).  */
++	  if (rclass == GENERAL_REGS || rclass == BASE_REGS)
++	    {
++	      if (! rs6000_legitimate_offset_address_p (TImode, addr, true))
++		{
++		  sri->icode = icode;
++		  /* account for splitting the loads, and converting the
++		     address from reg+reg to reg.  */
++		  sri->extra_cost = (((TARGET_64BIT) ? 3 : 5)
++				     + ((GET_CODE (addr) == AND) ? 1 : 0));
++		}
++	    }
++	  /* Loads to and stores from vector registers can only do reg+reg
++	     addressing.  Altivec registers can also do (reg+reg)&(-16).  */
++	  else if (rclass == VSX_REGS || rclass == ALTIVEC_REGS
++		   || rclass == FLOAT_REGS)
++	    {
++	      if (rclass != ALTIVEC_REGS
++		  && GET_CODE (addr) == AND
++		  && GET_CODE (XEXP (addr, 1)) == CONST_INT
++		  && INTVAL (XEXP (addr, 1)) == -16
++		  && (legitimate_indirect_address_p (XEXP (addr, 0), true)
++		      || legitimate_indexed_address_p (XEXP (addr, 0), true)))
++		{
++		  sri->icode = icode;
++		  sri->extra_cost = ((GET_CODE (XEXP (addr, 0)) == PLUS)
++				     ? 2 : 1);
++		}
++	      else if (!legitimate_indexed_address_p (addr, true)
++		       && !legitimate_indirect_address_p (addr, true))
++		{
++		  sri->icode = icode;
++		  sri->extra_cost = 1;
++		}
++	      else
++		icode = CODE_FOR_nothing;
++	    }
++	  /* Any other loads, including to pseudo registers which haven't been
++	     assigned to a register yet, default to require a scratch
++	     register.  */
++	  else
++	    {
++	      sri->icode = icode;
++	      sri->extra_cost = 2;
++	    }
++	}
++      else
++	{
++	  int regno = true_regnum (x);
++
++	  icode = CODE_FOR_nothing;
++	  if (regno < 0 || regno >= FIRST_PSEUDO_REGISTER)
++	    ret = default_secondary_reload (in_p, x, rclass, mode, sri);
++	  else
++	    {
++	      enum reg_class xclass = REGNO_REG_CLASS (regno);
++	      enum reload_reg_type rtype1 = rs6000_reload_register_type (rclass);
++	      enum reload_reg_type rtype2 = rs6000_reload_register_type (xclass);
++
++	      /* If memory is needed, use default_secondary_reload to create the
++		 stack slot.  */
++	      if (rtype1 != rtype2 || rtype1 == OTHER_REGISTER_TYPE)
++		ret = default_secondary_reload (in_p, x, rclass, mode, sri);
++	      else
++		ret = NO_REGS;
++	    }
++	}
++    }
++  else
++    ret = default_secondary_reload (in_p, x, rclass, mode, sri);
++
++  if (TARGET_DEBUG_ADDR)
++    {
++      fprintf (stderr,
++	       "rs6000_secondary_reload, return %s, in_p = %s, rclass = %s, "
++	       "mode = %s",
++	       reg_class_names[ret],
++	       in_p ? "true" : "false",
++	       reg_class_names[rclass],
++	       GET_MODE_NAME (mode));
++
++      if (icode != CODE_FOR_nothing)
++	fprintf (stderr, ", reload func = %s, extra cost = %d\n",
++		 insn_data[icode].name, sri->extra_cost);
++      else
++	fprintf (stderr, "\n");
++
++      debug_rtx (x);
++      fprintf (stderr, "\n");
++    }
++
++  return ret;
++}
++
++/* Fixup reload addresses for Altivec or VSX loads/stores to change SP+offset
++   to SP+reg addressing.  */
++
++void
++rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
++{
++  int regno = true_regnum (reg);
++  enum machine_mode mode = GET_MODE (reg);
++  enum reg_class rclass;
++  rtx addr;
++  rtx and_op2 = NULL_RTX;
++
++  if (TARGET_DEBUG_ADDR)
++    {
++      fprintf (stderr, "rs6000_secondary_reload_inner, type = %s\n",
++	       store_p ? "store" : "load");
++      fprintf (stderr, "reg:\n");
++      debug_rtx (reg);
++      fprintf (stderr, "mem:\n");
++      debug_rtx (mem);
++      fprintf (stderr, "scratch:\n");
++      debug_rtx (scratch);
++      fprintf (stderr, "\n");
++    }
++
++  gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER);
++  gcc_assert (GET_CODE (mem) == MEM);
++  rclass = REGNO_REG_CLASS (regno);
++  addr = XEXP (mem, 0);
++
++  switch (rclass)
++    {
++      /* Move reg+reg addresses into a scratch register for GPRs.  */
++    case GENERAL_REGS:
++    case BASE_REGS:
++      if (GET_CODE (addr) == AND)
++	{
++	  and_op2 = XEXP (addr, 1);
++	  addr = XEXP (addr, 0);
++	}
++      if (GET_CODE (addr) == PLUS
++	  && (!rs6000_legitimate_offset_address_p (TImode, addr, true)
++	      || and_op2 != NULL_RTX))
++	{
++	  if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
++	      || GET_CODE (addr) == CONST_INT)
++	    rs6000_emit_move (scratch, addr, GET_MODE (addr));
++	  else
++	    emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
++	  addr = scratch;
++	}
++      else if (GET_CODE (addr) == PRE_MODIFY
++	       && REG_P (XEXP (addr, 0))
++	       && GET_CODE (XEXP (addr, 1)) == PLUS)
++	{
++	  emit_insn (gen_rtx_SET (VOIDmode, XEXP (addr, 0), XEXP (addr, 1)));
++	  addr = XEXP (addr, 0);
++	}
++      break;
++
++      /* With float regs, we need to handle the AND ourselves, since we can't
++	 use the Altivec instruction with an implicit AND -16.  Allow scalar
++	 loads to float registers to use reg+offset even if VSX.  */
++    case FLOAT_REGS:
++    case VSX_REGS:
++      if (GET_CODE (addr) == AND)
++	{
++	  and_op2 = XEXP (addr, 1);
++	  addr = XEXP (addr, 0);
++	}
++      /* fall through */
++
++      /* Move reg+offset addresses into a scratch register.  */
++    case ALTIVEC_REGS:
++      if (!legitimate_indirect_address_p (addr, true)
++	  && !legitimate_indexed_address_p (addr, true)
++	  && (GET_CODE (addr) != PRE_MODIFY
++	      || !legitimate_indexed_address_p (XEXP (addr, 1), true))
++	  && (rclass != FLOAT_REGS
++	      || GET_MODE_SIZE (mode) != 8
++	      || and_op2 != NULL_RTX
++	      || !rs6000_legitimate_offset_address_p (mode, addr, true)))
++	{
++	  if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == CONST
++	      || GET_CODE (addr) == CONST_INT)
++	    rs6000_emit_move (scratch, addr, GET_MODE (addr));
++	  else
++	    emit_insn (gen_rtx_SET (VOIDmode, scratch, addr));
++	  addr = scratch;
++	}
++      break;
++
++    default:
++      gcc_unreachable ();
++    }
++
++  /* If the original address involved an AND -16 that is part of the Altivec
++     addresses, recreate the and now.  */
++  if (and_op2 != NULL_RTX)
++    {
++      rtx and_rtx = gen_rtx_SET (VOIDmode,
++				 scratch,
++				 gen_rtx_AND (Pmode, addr, and_op2));
++      rtx cc_clobber = gen_rtx_CLOBBER (CCmode, gen_rtx_SCRATCH (CCmode));
++      emit_insn (gen_rtx_PARALLEL (VOIDmode,
++				   gen_rtvec (2, and_rtx, cc_clobber)));
++      addr = scratch;
++    }
++
++  /* Adjust the address if it changed.  */
++  if (addr != XEXP (mem, 0))
++    {
++      mem = change_address (mem, mode, addr);
++      if (TARGET_DEBUG_ADDR)
++	fprintf (stderr, "rs6000_secondary_reload_inner, mem adjusted.\n");
++    }
++
++  /* Now create the move.  */
++  if (store_p)
++    emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
++  else
++    emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
++
++  return;
++}
+ 
+ /* Allocate a 64-bit stack slot to be used for copying SDmode
+    values through if this function has any SDmode references.  */
+@@ -11627,15 +12756,146 @@ rs6000_instantiate_decls (void)
      instantiate_decl_rtl (cfun->machine->sdmode_stack_slot);
  }
  
@@ -4871,32 +6408,52 @@ testsuite/
 +rs6000_preferred_reload_class (rtx x, enum reg_class rclass)
 +{
 +  enum machine_mode mode = GET_MODE (x);
++  enum reg_class ret;
 +
 +  if (TARGET_VSX && VSX_VECTOR_MODE (mode) && x == CONST0_RTX (mode)
 +      && VSX_REG_CLASS_P (rclass))
-+    return rclass;
++    ret = rclass;
 +
-+  if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode) && rclass == ALTIVEC_REGS
-+      && easy_vector_constant (x, mode))
-+    return rclass;
++  else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode)
++	   && rclass == ALTIVEC_REGS && easy_vector_constant (x, mode))
++    ret = rclass;
 +
-+  if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
-+    return NO_REGS;
++  else if (CONSTANT_P (x) && reg_classes_intersect_p (rclass, FLOAT_REGS))
++    ret = NO_REGS;
 +
-+  if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
-+    return GENERAL_REGS;
++  else if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
++    ret = GENERAL_REGS;
 +
-+  /* For VSX, prefer the traditional registers.  */
-+  if (rclass == VSX_REGS)
++  /* For VSX, prefer the traditional registers unless the address involves AND
++     -16, where we prefer to use the Altivec register so we don't have to break
++     down the AND.  */
++  else if (rclass == VSX_REGS)
 +    {
 +      if (mode == DFmode)
-+	return FLOAT_REGS;
++	ret = FLOAT_REGS;
++
++      else if (altivec_indexed_or_indirect_operand (x, mode))
++	ret = ALTIVEC_REGS;
 +
-+      if (ALTIVEC_VECTOR_MODE (mode))
-+	return ALTIVEC_REGS;
++      else if (ALTIVEC_VECTOR_MODE (mode))
++	ret = ALTIVEC_REGS;
++
++      else
++	ret = rclass;
 +    }
++  else
++    ret = rclass;
 +
-+  return rclass;
++  if (TARGET_DEBUG_ADDR)
++    {
++      fprintf (stderr,
++	       "rs6000_preferred_reload_class, return %s, rclass = %s, x:\n",
++	       reg_class_names[ret], reg_class_names[rclass]);
++      debug_rtx (x);
++      fprintf (stderr, "\n");
++    }
++
++  return ret;
 +}
 +
 +/* If we are copying between FP or AltiVec registers and anything else, we need
@@ -4910,31 +6467,53 @@ testsuite/
 +				enum reg_class class2,
 +				enum machine_mode mode)
 +{
++  bool ret;
++
 +  if (class1 == class2)
-+    return false;
-+
-+  if (TARGET_VSX && VSX_MOVE_MODE (mode) && VSX_REG_CLASS_P (class1)
-+      && VSX_REG_CLASS_P (class2))
-+    return false;
-+
-+  if (class1 == FLOAT_REGS
-+       && (!TARGET_MFPGPR || !TARGET_POWERPC64
-+	   || ((mode != DFmode)
-+	       && (mode != DDmode)
-+	       && (mode != DImode))))
-+    return true;
-+
-+  if (class2 == FLOAT_REGS
-+      && (!TARGET_MFPGPR || !TARGET_POWERPC64
-+	  || ((mode != DFmode)
-+	      && (mode != DDmode)
-+	      && (mode != DImode))))
-+    return true;
-+
-+  if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS)
-+    return true;
-+
-+  return false;
++    ret = false;
++
++  /* Under VSX, there are 3 register classes that values could be in (VSX_REGS,
++     ALTIVEC_REGS, and FLOAT_REGS).  We don't need to use memory to copy
++     between these classes.  But we need memory for other things that can go in
++     FLOAT_REGS like SFmode.  */
++  else if (TARGET_VSX
++	   && (VECTOR_MEM_VSX_P (mode) || VECTOR_UNIT_VSX_P (mode))
++	   && (class1 == VSX_REGS || class1 == ALTIVEC_REGS
++	       || class1 == FLOAT_REGS))
++    ret = (class2 != VSX_REGS && class2 != ALTIVEC_REGS
++	   && class2 != FLOAT_REGS);
++
++  else if (class1 == VSX_REGS || class2 == VSX_REGS)
++    ret = true;
++
++  else if (class1 == FLOAT_REGS
++	   && (!TARGET_MFPGPR || !TARGET_POWERPC64
++	       || ((mode != DFmode)
++		   && (mode != DDmode)
++		   && (mode != DImode))))
++    ret = true;
++
++  else if (class2 == FLOAT_REGS
++	   && (!TARGET_MFPGPR || !TARGET_POWERPC64
++	       || ((mode != DFmode)
++		   && (mode != DDmode)
++		   && (mode != DImode))))
++    ret = true;
++
++  else if (class1 == ALTIVEC_REGS || class2 == ALTIVEC_REGS)
++    ret = true;
++
++  else
++    ret = false;
++
++  if (TARGET_DEBUG_ADDR)
++    fprintf (stderr,
++	     "rs6000_secondary_memory_needed, return: %s, class1 = %s, "
++	     "class2 = %s, mode = %s\n",
++	     ret ? "true" : "false", reg_class_names[class1],
++	     reg_class_names[class2], GET_MODE_NAME (mode));
++
++  return ret;
 +}
 +
  /* Return the register class of a scratch register needed to copy IN into
@@ -4947,51 +6526,157 @@ testsuite/
 +			       enum machine_mode mode,
  			       rtx in)
  {
++  enum reg_class ret = NO_REGS;
    int regno;
-@@ -11663,6 +12340,13 @@ rs6000_secondary_reload_class (enum reg_
-       && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
-     return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
- 
-+  /* Memory, and FP/altivec registers can go into fp/altivec registers under
-+     VSX.  */
-+  if (TARGET_VSX
-+      && (regno == -1 || VSX_REGNO_P (regno))
-+      && VSX_REG_CLASS_P (rclass))
-+    return NO_REGS;
-+
-   /* Memory, and AltiVec registers can go into AltiVec registers.  */
-   if ((regno == -1 || ALTIVEC_REGNO_P (regno))
-       && rclass == ALTIVEC_REGS)
-@@ -11676,6 +12360,28 @@ rs6000_secondary_reload_class (enum reg_
-   /* Otherwise, we need GENERAL_REGS.  */
-   return GENERAL_REGS;
- }
+ 
+   if (TARGET_ELF || (DEFAULT_ABI == ABI_DARWIN
+@@ -11656,51 +12916,112 @@ rs6000_secondary_reload_class (enum reg_
+ 	      || GET_CODE (in) == HIGH
+ 	      || GET_CODE (in) == LABEL_REF
+ 	      || GET_CODE (in) == CONST))
+-	return BASE_REGS;
++	ret = BASE_REGS;
+     }
+ 
+-  if (GET_CODE (in) == REG)
++  if (ret == NO_REGS)
+     {
+-      regno = REGNO (in);
+-      if (regno >= FIRST_PSEUDO_REGISTER)
++      if (GET_CODE (in) == REG)
++	{
++	  regno = REGNO (in);
++	  if (regno >= FIRST_PSEUDO_REGISTER)
++	    {
++	      regno = true_regnum (in);
++	      if (regno >= FIRST_PSEUDO_REGISTER)
++		regno = -1;
++	    }
++	}
++      else if (GET_CODE (in) == SUBREG)
+ 	{
+ 	  regno = true_regnum (in);
+ 	  if (regno >= FIRST_PSEUDO_REGISTER)
+ 	    regno = -1;
+ 	}
+-    }
+-  else if (GET_CODE (in) == SUBREG)
+-    {
+-      regno = true_regnum (in);
+-      if (regno >= FIRST_PSEUDO_REGISTER)
++      else
+ 	regno = -1;
++
++      /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
++	 into anything.  */
++      if (rclass == GENERAL_REGS || rclass == BASE_REGS
++	  || (regno >= 0 && INT_REGNO_P (regno)))
++	ret = NO_REGS;
++
++      /* Constants, memory, and FP registers can go into FP registers.  */
++      else if ((regno == -1 || FP_REGNO_P (regno))
++	       && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
++	ret = (mode != SDmode) ? NO_REGS : GENERAL_REGS;
++
++      /* Memory, and FP/altivec registers can go into fp/altivec registers under
++	 VSX.  */
++      else if (TARGET_VSX
++	       && (regno == -1 || VSX_REGNO_P (regno))
++	       && VSX_REG_CLASS_P (rclass))
++	ret = NO_REGS;
++
++      /* Memory, and AltiVec registers can go into AltiVec registers.  */
++      else if ((regno == -1 || ALTIVEC_REGNO_P (regno))
++	       && rclass == ALTIVEC_REGS)
++	ret = NO_REGS;
++
++      /* We can copy among the CR registers.  */
++      else if ((rclass == CR_REGS || rclass == CR0_REGS)
++	       && regno >= 0 && CR_REGNO_P (regno))
++	ret = NO_REGS;
++
++      /* Otherwise, we need GENERAL_REGS.  */
++      else
++	ret = GENERAL_REGS;
++    }
 +
-+/* Return nonzero if for CLASS a mode change from FROM to TO is invalid.  */
++  if (TARGET_DEBUG_ADDR)
++    {
++      fprintf (stderr,
++	       "rs6000_secondary_reload_class, return %s, rclass = %s, "
++	       "mode = %s, input rtx:\n",
++	       reg_class_names[ret], reg_class_names[rclass],
++	       GET_MODE_NAME (mode));
++      debug_rtx (in);
++      fprintf (stderr, "\n");
+     }
+-  else
+-    regno = -1;
+ 
+-  /* We can place anything into GENERAL_REGS and can put GENERAL_REGS
+-     into anything.  */
+-  if (rclass == GENERAL_REGS || rclass == BASE_REGS
+-      || (regno >= 0 && INT_REGNO_P (regno)))
+-    return NO_REGS;
+-
+-  /* Constants, memory, and FP registers can go into FP registers.  */
+-  if ((regno == -1 || FP_REGNO_P (regno))
+-      && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
+-    return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
+-
+-  /* Memory, and AltiVec registers can go into AltiVec registers.  */
+-  if ((regno == -1 || ALTIVEC_REGNO_P (regno))
+-      && rclass == ALTIVEC_REGS)
+-    return NO_REGS;
+-
+-  /* We can copy among the CR registers.  */
+-  if ((rclass == CR_REGS || rclass == CR0_REGS)
+-      && regno >= 0 && CR_REGNO_P (regno))
+-    return NO_REGS;
++  return ret;
++}
 +
++/* Return nonzero if for CLASS a mode change from FROM to TO is invalid.  */
+ 
+-  /* Otherwise, we need GENERAL_REGS.  */
+-  return GENERAL_REGS;
 +bool
 +rs6000_cannot_change_mode_class (enum machine_mode from,
 +				 enum machine_mode to,
 +				 enum reg_class rclass)
 +{
-+  return (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)
-+	  ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8
-+	      || TARGET_IEEEQUAD)
-+	     && reg_classes_intersect_p (FLOAT_REGS, rclass))
-+	  : (((TARGET_E500_DOUBLE
-+	       && ((((to) == DFmode) + ((from) == DFmode)) == 1
-+		   || (((to) == TFmode) + ((from) == TFmode)) == 1
-+		   || (((to) == DDmode) + ((from) == DDmode)) == 1
-+		   || (((to) == TDmode) + ((from) == TDmode)) == 1
-+		   || (((to) == DImode) + ((from) == DImode)) == 1))
-+	      || (TARGET_SPE
-+		  && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1))
-+	     && reg_classes_intersect_p (GENERAL_REGS, rclass)));
-+}
++  bool ret = (GET_MODE_SIZE (from) != GET_MODE_SIZE (to)
++	      ? ((GET_MODE_SIZE (from) < 8 || GET_MODE_SIZE (to) < 8
++		  || TARGET_IEEEQUAD)
++		 && reg_classes_intersect_p (FLOAT_REGS, rclass))
++	      : (((TARGET_E500_DOUBLE
++		   && ((((to) == DFmode) + ((from) == DFmode)) == 1
++		       || (((to) == TFmode) + ((from) == TFmode)) == 1
++		       || (((to) == DDmode) + ((from) == DDmode)) == 1
++		       || (((to) == TDmode) + ((from) == TDmode)) == 1
++		       || (((to) == DImode) + ((from) == DImode)) == 1))
++		  || (TARGET_VSX
++		      && (VSX_VECTOR_MODE (from) + VSX_VECTOR_MODE (to)) == 1)
++		  || (TARGET_ALTIVEC
++		      && (ALTIVEC_VECTOR_MODE (from)
++			  + ALTIVEC_VECTOR_MODE (to)) == 1)
++		  || (TARGET_SPE
++		      && (SPE_VECTOR_MODE (from) + SPE_VECTOR_MODE (to)) == 1))
++		 && reg_classes_intersect_p (GENERAL_REGS, rclass)));
++
++  if (TARGET_DEBUG_ADDR)
++    fprintf (stderr,
++	     "rs6000_cannot_change_mode_class, return %s, from = %s, "
++	     "to = %s, rclass = %s\n",
++	     ret ? "true" : "false",
++	     GET_MODE_NAME (from), GET_MODE_NAME (to),
++	     reg_class_names[rclass]);
++
++  return ret;
+ }
  
  /* Given a comparison operation, return the bit number in CCR to test.  We
-    know this is a valid comparison.
-@@ -12406,6 +13112,26 @@ print_operand (FILE *file, rtx x, int co
+@@ -12432,6 +13753,26 @@ print_operand (FILE *file, rtx x, int co
        fprintf (file, "%d", i + 1);
        return;
  
@@ -5018,12 +6703,12 @@ testsuite/
      case 'X':
        if (GET_CODE (x) == MEM
  	  && (legitimate_indexed_address_p (XEXP (x, 0), 0)
-@@ -12518,13 +13244,16 @@ print_operand (FILE *file, rtx x, int co
+@@ -12544,13 +13885,16 @@ print_operand (FILE *file, rtx x, int co
  
  	    /* Fall through.  Must be [reg+reg].  */
  	  }
 -	if (TARGET_ALTIVEC
-+	if (VECTOR_MEM_ALTIVEC_P (GET_MODE (x))
++	if (VECTOR_MEM_ALTIVEC_OR_VSX_P (GET_MODE (x))
  	    && GET_CODE (tmp) == AND
  	    && GET_CODE (XEXP (tmp, 1)) == CONST_INT
  	    && INTVAL (XEXP (tmp, 1)) == -16)
@@ -5037,7 +6722,7 @@ testsuite/
  	else
  	  {
  	    if (!GET_CODE (tmp) == PLUS
-@@ -13296,55 +14025,62 @@ output_e500_flip_gt_bit (rtx dst, rtx sr
+@@ -13322,55 +14666,62 @@ output_e500_flip_gt_bit (rtx dst, rtx sr
    return string;
  }
  
@@ -5139,7 +6824,7 @@ testsuite/
  }
  
  /* Emit vector compare for operands OP0 and OP1 using code RCODE.
-@@ -13355,129 +14091,111 @@ rs6000_emit_vector_compare (enum rtx_cod
+@@ -13381,129 +14732,111 @@ rs6000_emit_vector_compare (enum rtx_cod
  			    rtx op0, rtx op1,
  			    enum machine_mode dmode)
  {
@@ -5358,7 +7043,7 @@ testsuite/
        if (swap_operands)
  	{
  	  rtx tmp;
-@@ -13485,69 +14203,23 @@ rs6000_emit_vector_compare (enum rtx_cod
+@@ -13511,69 +14844,23 @@ rs6000_emit_vector_compare (enum rtx_cod
  	  op0 = op1;
  	  op1 = tmp;
  	}
@@ -5376,10 +7061,10 @@ testsuite/
 -    }
 -  return mask;
 -}
--
+ 
 -/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if
 -   valid insn doesn exist for given mode.  */
- 
+-
 -static int
 -get_vsel_insn (enum machine_mode mode)
 -{
@@ -5424,10 +7109,10 @@ testsuite/
 -{
 -  rtx t, temp;
 -  enum machine_mode dest_mode = GET_MODE (dest);
--  int vsel_insn_index  = get_vsel_insn (GET_MODE (dest));
- 
--  temp = gen_reg_rtx (dest_mode);
+-  int vsel_insn_index  = get_vsel_insn (GET_MODE (dest));
 -
+-  temp = gen_reg_rtx (dest_mode);
+ 
 -  /* For each vector element, select op1 when mask is 1 otherwise
 -     select op2.  */
 -  t = gen_rtx_SET (VOIDmode, temp,
@@ -5442,7 +7127,7 @@ testsuite/
  }
  
  /* Emit vector conditional expression.
-@@ -13562,15 +14234,29 @@ rs6000_emit_vector_cond_expr (rtx dest, 
+@@ -13588,15 +14875,29 @@ rs6000_emit_vector_cond_expr (rtx dest, 
    enum rtx_code rcode = GET_CODE (cond);
    rtx mask;
  
@@ -5475,7 +7160,7 @@ testsuite/
  }
  
  /* Emit a conditional move: move TRUE_COND to DEST if OP of the
-@@ -13766,8 +14452,8 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
+@@ -13792,8 +15093,8 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
  {
    rtx condition_rtx, cr;
  
@@ -5486,7 +7171,7 @@ testsuite/
      return 0;
  
    /* We still have to do the compare, because isel doesn't do a
-@@ -13776,12 +14462,24 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
+@@ -13802,12 +15103,24 @@ rs6000_emit_int_cmove (rtx dest, rtx op,
    condition_rtx = rs6000_generate_compare (GET_CODE (op));
    cr = XEXP (condition_rtx, 0);
  
@@ -5516,7 +7201,7 @@ testsuite/
  
    return 1;
  }
-@@ -13808,6 +14506,15 @@ rs6000_emit_minmax (rtx dest, enum rtx_c
+@@ -13834,6 +15147,15 @@ rs6000_emit_minmax (rtx dest, enum rtx_c
    enum rtx_code c;
    rtx target;
  
@@ -5532,7 +7217,7 @@ testsuite/
    if (code == SMAX || code == SMIN)
      c = GE;
    else
-@@ -15785,6 +16492,7 @@ emit_frame_save (rtx frame_reg, rtx fram
+@@ -15811,6 +17133,7 @@ emit_frame_save (rtx frame_reg, rtx fram
  
    /* Some cases that need register indexed addressing.  */
    if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
@@ -5540,7 +7225,51 @@ testsuite/
        || (TARGET_E500_DOUBLE && mode == DFmode)
        || (TARGET_SPE_ABI
  	  && SPE_VECTOR_MODE (mode)
-@@ -19320,6 +20028,7 @@ rs6000_issue_rate (void)
+@@ -18923,6 +20246,7 @@ rs6000_adjust_cost (rtx insn, rtx link, 
+                  || rs6000_cpu_attr == CPU_PPC7450
+                  || rs6000_cpu_attr == CPU_POWER4
+                  || rs6000_cpu_attr == CPU_POWER5
++		 || (rs6000_cpu_attr == CPU_POWER7 && TARGET_POWER7_ADJUST_COST)
+                  || rs6000_cpu_attr == CPU_CELL)
+                 && recog_memoized (dep_insn)
+                 && (INSN_CODE (dep_insn) >= 0))
+@@ -19162,6 +20486,35 @@ rs6000_adjust_cost (rtx insn, rtx link, 
+   return cost;
+ }
+ 
++/* Debug version of rs6000_adjust_cost.  */
++
++static int
++rs6000_debug_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
++{
++  int ret = rs6000_adjust_cost (insn, link, dep_insn, cost);
++
++  if (ret != cost)
++    {
++      const char *dep;
++
++      switch (REG_NOTE_KIND (link))
++	{
++	default:	     dep = "unknown depencency"; break;
++	case REG_DEP_TRUE:   dep = "data dependency";	 break;
++	case REG_DEP_OUTPUT: dep = "output dependency";  break;
++	case REG_DEP_ANTI:   dep = "anti depencency";	 break;
++	}
++
++      fprintf (stderr,
++	       "\nrs6000_adjust_cost, final cost = %d, orig cost = %d, "
++	       "%s, insn:\n", ret, cost, dep);
++
++      debug_rtx (insn);
++    }
++
++  return ret;
++}
++
+ /* The function returns a true if INSN is microcoded.
+    Return false otherwise.  */
+ 
+@@ -19443,6 +20796,7 @@ rs6000_issue_rate (void)
    case CPU_POWER4:
    case CPU_POWER5:
    case CPU_POWER6:
@@ -5548,7 +7277,7 @@ testsuite/
      return 5;
    default:
      return 1;
-@@ -19921,6 +20630,41 @@ insn_must_be_first_in_group (rtx insn)
+@@ -20044,6 +21398,41 @@ insn_must_be_first_in_group (rtx insn)
            break;
          }
        break;
@@ -5590,7 +7319,7 @@ testsuite/
      default:
        break;
      }
-@@ -19982,6 +20726,23 @@ insn_must_be_last_in_group (rtx insn)
+@@ -20105,6 +21494,23 @@ insn_must_be_last_in_group (rtx insn)
          break;
      }
      break;
@@ -5614,7 +7343,7 @@ testsuite/
    default:
      break;
    }
-@@ -20554,8 +21315,8 @@ rs6000_handle_altivec_attribute (tree *n
+@@ -20677,8 +22083,8 @@ rs6000_handle_altivec_attribute (tree *n
    else if (type == long_long_unsigned_type_node
             || type == long_long_integer_type_node)
      error ("use of %<long long%> in AltiVec types is invalid");
@@ -5625,7 +7354,7 @@ testsuite/
    else if (type == long_double_type_node)
      error ("use of %<long double%> in AltiVec types is invalid");
    else if (type == boolean_type_node)
-@@ -20581,6 +21342,7 @@ rs6000_handle_altivec_attribute (tree *n
+@@ -20704,6 +22110,7 @@ rs6000_handle_altivec_attribute (tree *n
  	  result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
  	  break;
  	case SFmode: result = V4SF_type_node; break;
@@ -5633,7 +7362,51 @@ testsuite/
  	  /* If the user says 'vector int bool', we may be handed the 'bool'
  	     attribute _before_ the 'vector' attribute, and so select the
  	     proper type in the 'b' case below.  */
-@@ -22116,7 +22878,7 @@ rs6000_register_move_cost (enum machine_
+@@ -22242,6 +23649,43 @@ rs6000_rtx_costs (rtx x, int code, int o
+   return false;
+ }
+ 
++/* Debug form of r6000_rtx_costs that is selected if -mdebug=cost.  */
++
++static bool
++rs6000_debug_rtx_costs (rtx x, int code, int outer_code, int *total,
++			bool speed)
++{
++  bool ret = rs6000_rtx_costs (x, code, outer_code, total, speed);
++
++  fprintf (stderr,
++	   "\nrs6000_rtx_costs, return = %s, code = %s, outer_code = %s, "
++	   "total = %d, speed = %s, x:\n",
++	   ret ? "complete" : "scan inner",
++	   GET_RTX_NAME (code),
++	   GET_RTX_NAME (outer_code),
++	   *total,
++	   speed ? "true" : "false");
++
++  debug_rtx (x);
++
++  return ret;
++}
++
++/* Debug form of ADDRESS_COST that is selected if -mdebug=cost.  */
++
++static int
++rs6000_debug_address_cost (rtx x, bool speed)
++{
++  int ret = TARGET_ADDRESS_COST (x, speed);
++
++  fprintf (stderr, "\nrs6000_address_cost, return = %d, speed = %s, x:\n",
++	   ret, speed ? "true" : "false");
++  debug_rtx (x);
++
++  return ret;
++}
++
++
+ /* A C expression returning the cost of moving data from a register of class
+    CLASS1 to one of CLASS2.  */
+ 
+@@ -22256,7 +23700,7 @@ rs6000_register_move_cost (enum machine_
        if (! reg_classes_intersect_p (to, GENERAL_REGS))
  	from = to;
  
@@ -5642,7 +7415,7 @@ testsuite/
  	return (rs6000_memory_move_cost (mode, from, 0)
  		+ rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
  
-@@ -22136,6 +22898,12 @@ rs6000_register_move_cost (enum machine_
+@@ -22276,6 +23720,12 @@ rs6000_register_move_cost (enum machine_
  	return 2 * hard_regno_nregs[0][mode];
      }
  
@@ -5655,7 +7428,7 @@ testsuite/
    /* Moving between two similar registers is just one instruction.  */
    else if (reg_classes_intersect_p (to, from))
      return (mode == TFmode || mode == TDmode) ? 4 : 2;
-@@ -22376,8 +23144,8 @@ rs6000_emit_swrsqrtsf (rtx dst, rtx src)
+@@ -22516,8 +23966,8 @@ rs6000_emit_swrsqrtsf (rtx dst, rtx src)
    emit_label (XEXP (label, 0));
  }
  
@@ -5666,7 +7439,7 @@ testsuite/
  
  void
  rs6000_emit_popcount (rtx dst, rtx src)
-@@ -22385,6 +23153,16 @@ rs6000_emit_popcount (rtx dst, rtx src)
+@@ -22525,6 +23975,16 @@ rs6000_emit_popcount (rtx dst, rtx src)
    enum machine_mode mode = GET_MODE (dst);
    rtx tmp1, tmp2;
  
@@ -5683,7 +7456,7 @@ testsuite/
    tmp1 = gen_reg_rtx (mode);
  
    if (mode == SImode)
-@@ -22797,7 +23575,7 @@ rs6000_vector_mode_supported_p (enum mac
+@@ -22937,7 +24397,7 @@ rs6000_vector_mode_supported_p (enum mac
    if (TARGET_SPE && SPE_VECTOR_MODE (mode))
      return true;
  
@@ -5693,8 +7466,8 @@ testsuite/
  
    else
 --- gcc/config/rs6000/vsx.md	(.../trunk)	(revision 0)
-+++ gcc/config/rs6000/vsx.md	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -0,0 +1,864 @@
++++ gcc/config/rs6000/vsx.md	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -0,0 +1,1004 @@
 +;; VSX patterns.
 +;; Copyright (C) 2009
 +;; Free Software Foundation, Inc.
@@ -5716,12 +7489,18 @@ testsuite/
 +;; along with GCC; see the file COPYING3.  If not see
 +;; <http://www.gnu.org/licenses/>.
 +
++;; Iterator for both scalar and vector floating point types supported by VSX
++(define_mode_iterator VSX_B [DF V4SF V2DF])
++
 +;; Iterator for vector floating point types supported by VSX
 +(define_mode_iterator VSX_F [V4SF V2DF])
 +
 +;; Iterator for logical types supported by VSX
 +(define_mode_iterator VSX_L [V16QI V8HI V4SI V2DI V4SF V2DF TI])
 +
++;; Iterator for types for load/store with update
++(define_mode_iterator VSX_U [V16QI V8HI V4SI V2DI V4SF V2DF TI DF])
++
 +;; Map into the appropriate load/store name based on the type
 +(define_mode_attr VSm  [(V16QI "vw4")
 +			(V8HI  "vw4")
@@ -5729,6 +7508,7 @@ testsuite/
 +			(V4SF  "vw4")
 +			(V2DF  "vd2")
 +			(V2DI  "vd2")
++			(DF    "d")
 +			(TI    "vw4")])
 +
 +;; Map into the appropriate suffix based on the type
@@ -5738,6 +7518,7 @@ testsuite/
 +			 (V4SF  "sp")
 +			 (V2DF  "dp")
 +			 (V2DI  "dp")
++			 (DF    "dp")
 +			 (TI    "sp")])
 +
 +;; Map into the register class used
@@ -5747,30 +7528,126 @@ testsuite/
 +			 (V4SF  "wf")
 +			 (V2DI  "wd")
 +			 (V2DF  "wd")
++			 (DF    "ws")
 +			 (TI    "wd")])
 +
++;; Map into the register class used for float<->int conversions
++(define_mode_attr VSr2	[(V2DF  "wd")
++			 (V4SF  "wf")
++			 (DF    "!f#r")])
++
++(define_mode_attr VSr3	[(V2DF  "wa")
++			 (V4SF  "wa")
++			 (DF    "!f#r")])
++
 +;; Same size integer type for floating point data
 +(define_mode_attr VSi [(V4SF  "v4si")
-+		       (V2DF  "v2di")])
++		       (V2DF  "v2di")
++		       (DF    "di")])
 +
 +(define_mode_attr VSI [(V4SF  "V4SI")
-+		       (V2DF  "V2DI")])
++		       (V2DF  "V2DI")
++		       (DF    "DI")])
 +
 +;; Word size for same size conversion
 +(define_mode_attr VSc [(V4SF "w")
-+		       (V2DF "d")])
++		       (V2DF "d")
++		       (DF   "d")])
 +
 +;; Bitsize for DF load with update
 +(define_mode_attr VSbit [(SI "32")
 +			 (DI "64")])
 +
++;; Map into either s or v, depending on whether this is a scalar or vector
++;; operation
++(define_mode_attr VSv	[(V16QI "v")
++			 (V8HI  "v")
++			 (V4SI  "v")
++			 (V4SF  "v")
++			 (V2DI  "v")
++			 (V2DF  "v")
++			 (TI    "v")
++			 (DF    "s")])
++
++;; Appropriate type for add ops (and other simple FP ops)
++(define_mode_attr VStype_simple	[(V2DF "vecfloat")
++				 (V4SF "vecfloat")
++				 (DF   "fp")])
++
++(define_mode_attr VSfptype_simple [(V2DF "fp_addsub_d")
++				   (V4SF "fp_addsub_s")
++				   (DF   "fp_addsub_d")])
++
++;; Appropriate type for multiply ops
++(define_mode_attr VStype_mul	[(V2DF "vecfloat")
++				 (V4SF "vecfloat")
++				 (DF   "dmul")])
++
++(define_mode_attr VSfptype_mul	[(V2DF "fp_mul_d")
++				 (V4SF "fp_mul_s")
++				 (DF   "fp_mul_d")])
++
++;; Appropriate type for divide ops.  For now, just lump the vector divide with
++;; the scalar divides
++(define_mode_attr VStype_div	[(V2DF "ddiv")
++				 (V4SF "sdiv")
++				 (DF   "ddiv")])
++
++(define_mode_attr VSfptype_div	[(V2DF "fp_div_d")
++				 (V4SF "fp_div_s")
++				 (DF   "fp_div_d")])
++
++;; Appropriate type for sqrt ops.  For now, just lump the vector sqrt with
++;; the scalar sqrt
++(define_mode_attr VStype_sqrt	[(V2DF "dsqrt")
++				 (V4SF "sdiv")
++				 (DF   "ddiv")])
++
++(define_mode_attr VSfptype_sqrt	[(V2DF "fp_sqrt_d")
++				 (V4SF "fp_sqrt_s")
++				 (DF   "fp_sqrt_d")])
++
++;; Appropriate type for load + update
++(define_mode_attr VStype_load_update [(V16QI "vecload")
++				      (V8HI  "vecload")
++				      (V4SI  "vecload")
++				      (V4SF  "vecload")
++				      (V2DI  "vecload")
++				      (V2DF  "vecload")
++				      (TI    "vecload")
++				      (DF    "fpload")])
++
++;; Appropriate type for store + update
++(define_mode_attr VStype_store_update [(V16QI "vecstore")
++				       (V8HI  "vecstore")
++				       (V4SI  "vecstore")
++				       (V4SF  "vecstore")
++				       (V2DI  "vecstore")
++				       (V2DF  "vecstore")
++				       (TI    "vecstore")
++				       (DF    "fpstore")])
++
++;; Constants for creating unspecs
 +(define_constants
-+  [(UNSPEC_VSX_CONCAT_V2DF	500)])
++  [(UNSPEC_VSX_CONCAT_V2DF	500)
++   (UNSPEC_VSX_XVCVDPSP		501)
++   (UNSPEC_VSX_XVCVDPSXWS	502)
++   (UNSPEC_VSX_XVCVDPUXWS	503)
++   (UNSPEC_VSX_XVCVSPDP		504)
++   (UNSPEC_VSX_XVCVSXWDP	505)
++   (UNSPEC_VSX_XVCVUXWDP	506)
++   (UNSPEC_VSX_XVMADD		507)
++   (UNSPEC_VSX_XVMSUB		508)
++   (UNSPEC_VSX_XVNMADD		509)
++   (UNSPEC_VSX_XVNMSUB		510)
++   (UNSPEC_VSX_XVRSQRTE		511)
++   (UNSPEC_VSX_XVTDIV		512)
++   (UNSPEC_VSX_XVTSQRT		513)])
 +
 +;; VSX moves
 +(define_insn "*vsx_mov<mode>"
-+  [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v")
-+	(match_operand:VSX_L 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W"))]
++  [(set (match_operand:VSX_L 0 "nonimmediate_operand" "=Z,<VSr>,<VSr>,?Z,?wa,?wa,*o,*r,*r,<VSr>,?wa,v,wZ,v")
++	(match_operand:VSX_L 1 "input_operand" "<VSr>,Z,<VSr>,wa,Z,wa,r,o,r,j,j,W,v,wZ"))]
 +  "VECTOR_MEM_VSX_P (<MODE>mode)
 +   && (register_operand (operands[0], <MODE>mode) 
 +       || register_operand (operands[1], <MODE>mode))"
@@ -5787,7 +7664,7 @@ testsuite/
 +
 +    case 2:
 +    case 5:
-+      return "xvmov<VSs> %x0,%x1";
++      return "xxlor %x0,%x1,%x1";
 +
 +    case 6:
 +    case 7:
@@ -5801,11 +7678,17 @@ testsuite/
 +    case 11:
 +      return output_vec_const_move (operands);
 +
++    case 12:
++      return "stvx %1,%y0";
++
++    case 13:
++      return "lvx %0,%y1";
++
 +    default:
 +      gcc_unreachable ();
 +    }
 +}
-+  [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,store,load,*,vecsimple,vecsimple,*")])
++  [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,*,*,*,vecsimple,vecsimple,*,vecstore,vecload")])
 +
 +;; Load/store with update
 +;; Define insns that do load or store with update.  Because VSX only has
@@ -5817,575 +7700,592 @@ testsuite/
 +;; tie and these are the pair most likely to be tieable (and the ones
 +;; that will benefit the most).
 +
-+(define_insn "*vsx_load<mode>_update64"
-+  [(set (match_operand:VSX_L 3 "vsx_register_operand" "=<VSr>,?wa")
-+	(mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
-+			    (match_operand:DI 2 "gpc_reg_operand" "r,r"))))
-+   (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
-+	(plus:DI (match_dup 1)
-+		 (match_dup 2)))]
-+  "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
-+  "lx<VSm>ux %x3,%0,%2"
-+  [(set_attr "type" "vecload")])
-+
-+(define_insn "*vsx_load<mode>_update32"
-+  [(set (match_operand:VSX_L 3 "vsx_register_operand" "=<VSr>,?wa")
-+	(mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
-+			    (match_operand:SI 2 "gpc_reg_operand" "r,r"))))
-+   (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
-+	(plus:SI (match_dup 1)
-+		 (match_dup 2)))]
-+  "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
-+  "lx<VSm>ux %x3,%0,%2"
-+  [(set_attr "type" "vecload")])
-+
-+(define_insn "*vsx_store<mode>_update64"
-+  [(set (mem:VSX_L (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
-+			    (match_operand:DI 2 "gpc_reg_operand" "r,r")))
-+	(match_operand:VSX_L 3 "gpc_reg_operand" "<VSr>,?wa"))
-+   (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
-+	(plus:DI (match_dup 1)
-+		 (match_dup 2)))]
-+  "TARGET_64BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
-+  "stx<VSm>ux %x3,%0,%2"
-+  [(set_attr "type" "vecstore")])
-+
-+(define_insn "*vsx_store<mode>_update32"
-+  [(set (mem:VSX_L (plus:SI (match_operand:SI 1 "gpc_reg_operand" "0,0")
-+			    (match_operand:SI 2 "gpc_reg_operand" "r,r")))
-+	(match_operand:VSX_L 3 "gpc_reg_operand" "<VSr>,?wa"))
-+   (set (match_operand:SI 0 "gpc_reg_operand" "=b,b")
-+	(plus:SI (match_dup 1)
-+		 (match_dup 2)))]
-+  "TARGET_32BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
-+  "stx<VSm>ux %x3,%0,%2"
-+  [(set_attr "type" "vecstore")])
-+
-+(define_insn "*vsx_loaddf_update<VSbit>"
-+  [(set (match_operand:DF 3 "vsx_register_operand" "=ws,?wa")
-+	(mem:DF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
-+			(match_operand:P 2 "gpc_reg_operand" "r,r"))))
++(define_insn "*vsx_load<VSX_U:mode>_update_<P:mptrsize>"
++  [(set (match_operand:VSX_U 3 "vsx_register_operand" "=<VSr>,?wa")
++	(mem:VSX_U (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
++			   (match_operand:P 2 "gpc_reg_operand" "r,r"))))
 +   (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
 +	(plus:P (match_dup 1)
 +		(match_dup 2)))]
-+  "TARGET_<VSbit>BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)"
-+  "lxsdux %x3,%0,%2"
-+  [(set_attr "type" "vecload")])
-+
-+(define_insn "*vsx_storedf_update<VSbit>"
-+  [(set (mem:DF (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
-+			(match_operand:P 2 "gpc_reg_operand" "r,r")))
-+	(match_operand:DF 3 "gpc_reg_operand" "ws,?wa"))
++  "<P:tptrsize> && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++  "lx<VSm>ux %x3,%0,%2"
++  [(set_attr "type" "<VSX_U:VStype_load_update>")])
++
++(define_insn "*vsx_store<mode>_update_<P:mptrsize>"
++  [(set (mem:VSX_U (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
++			   (match_operand:P 2 "gpc_reg_operand" "r,r")))
++	(match_operand:VSX_U 3 "gpc_reg_operand" "<VSr>,?wa"))
 +   (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
 +	(plus:P (match_dup 1)
 +		(match_dup 2)))]
-+  "TARGET_<VSbit>BIT && TARGET_UPDATE && VECTOR_MEM_VSX_P (DFmode)"
-+  "stxsdux %x3,%0,%2"
-+  [(set_attr "type" "vecstore")])
++  "<P:tptrsize> && TARGET_UPDATE && VECTOR_MEM_VSX_P (<MODE>mode)"
++  "stx<VSm>ux %x3,%0,%2"
++  [(set_attr "type" "<VSX_U:VStype_store_update>")])
 +
 +;; We may need to have a varient on the pattern for use in the prologue
 +;; that doesn't depend on TARGET_UPDATE.
 +
 +
-+;; VSX vector floating point arithmetic instructions
++;; VSX scalar and vector floating point arithmetic instructions
 +(define_insn "*vsx_add<mode>3"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (plus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+		    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (plus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
++		    (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvadd<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "vecfloat")])
++  "x<VSv>add<VSs> %x0,%x1,%x2"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +(define_insn "*vsx_sub<mode>3"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (minus:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+		     (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (minus:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
++		     (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvsub<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "vecfloat")])
++  "x<VSv>sub<VSs> %x0,%x1,%x2"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +(define_insn "*vsx_mul<mode>3"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (mult:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+		    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (mult:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
++		    (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvmul<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "vecfloat")])
++  "x<VSv>mul<VSs> %x0,%x1,%x2"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
 +
 +(define_insn "*vsx_div<mode>3"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+	 	   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (div:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
++	 	   (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvdiv<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "vecfdiv")])
++  "x<VSv>div<VSs> %x0,%x1,%x2"
++  [(set_attr "type" "<VStype_div>")
++   (set_attr "fp_type" "<VSfptype_div>")])
++
++(define_insn "vsx_tdiv<mode>3"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
++		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")]
++		      UNSPEC_VSX_XVTDIV))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>tdiv<VSs> %x0,%x1,%x2"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
-+(define_insn "*vsx_fre<mode>2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+	(unspec:VSX_F [(match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")]
++(define_insn "vsx_fre<mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
 +		      UNSPEC_FRES))]
-+  "flag_finite_math_only && VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvre<VSs> %x0,%x1"
-+  [(set_attr "type" "fp")])
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>re<VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +(define_insn "*vsx_neg<mode>2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (neg:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (neg:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvneg<VSs> %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
++  "x<VSv>neg<VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +(define_insn "*vsx_abs<mode>2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvabs<VSs> %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_nabs<mode>2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (neg:VSX_F
-+	 (abs:VSX_F
-+	  (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>"))))]
++  "x<VSv>abs<VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
++
++(define_insn "vsx_nabs<mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (neg:VSX_B
++	 (abs:VSX_B
++	  (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvnabs<VSs> %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_smax<mode>3"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (smax:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+		    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++  "x<VSv>nabs<VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
++
++(define_insn "vsx_smax<mode>3"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (smax:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
++		    (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvmax<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "veccmp")])
++  "x<VSv>max<VSs> %x0,%x1,%x2"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +(define_insn "*vsx_smin<mode>3"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (smin:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+		    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (smin:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")
++		    (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvmin<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "veccmp")])
++  "x<VSv>min<VSs> %x0,%x1,%x2"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +(define_insn "*vsx_sqrt<mode>2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+        (sqrt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++        (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>sqrt<VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_sqrt>")
++   (set_attr "fp_type" "<VSfptype_sqrt>")])
++
++(define_insn "vsx_rsqrte<mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
++		      UNSPEC_VSX_XVRSQRTE))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvsqrt<VSs> %x0,%x1"
-+  [(set_attr "type" "vecfdiv")])
++  "x<VSv>rsqrte<VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
++
++(define_insn "vsx_tsqrt<mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
++		      UNSPEC_VSX_XVTSQRT))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>tsqrt<VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +;; Fused vector multiply/add instructions
-+(define_insn "*vsx_fmadd<mode>4"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+	(plus:VSX_F
-+	 (mult:VSX_F
-+	  (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+	  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
-+	 (match_operand:VSX_F 3 "gpc_reg_operand" "0,<VSr>")))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++
++;; Note we have a pattern for the multiply/add operations that uses unspec and
++;; does not check -mfused-madd to allow users to use these ops when they know
++;; they want the fused multiply/add.
++
++(define_expand "vsx_fmadd<mode>4"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
++	(plus:VSX_B
++	 (mult:VSX_B
++	  (match_operand:VSX_B 1 "vsx_register_operand" "")
++	  (match_operand:VSX_B 2 "vsx_register_operand" ""))
++	 (match_operand:VSX_B 3 "vsx_register_operand" "")))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++{
++  if (!TARGET_FUSED_MADD)
++    {
++      emit_insn (gen_vsx_fmadd<mode>4_2 (operands[0], operands[1], operands[2],
++					 operands[3]));
++      DONE;
++    }
++})
++
++(define_insn "*vsx_fmadd<mode>4_1"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(plus:VSX_B
++	 (mult:VSX_B
++	  (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
++	  (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
++	 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
 +  "@
-+   xvmadda<VSs> %x0,%x1,%x2
-+   xvmaddm<VSs> %x0,%x1,%x3"
-+  [(set_attr "type" "vecfloat")])
++   x<VSv>madda<VSs> %x0,%x1,%x2
++   x<VSv>maddm<VSs> %x0,%x1,%x3
++   x<VSv>madda<VSs> %x0,%x1,%x2
++   x<VSv>maddm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_insn "vsx_fmadd<mode>4_2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
++		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
++		       (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
++		      UNSPEC_VSX_XVMADD))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "@
++   x<VSv>madda<VSs> %x0,%x1,%x2
++   x<VSv>maddm<VSs> %x0,%x1,%x3
++   x<VSv>madda<VSs> %x0,%x1,%x2
++   x<VSv>maddm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_expand "vsx_fmsub<mode>4"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "")
++	(minus:VSX_B
++	 (mult:VSX_B
++	  (match_operand:VSX_B 1 "vsx_register_operand" "")
++	  (match_operand:VSX_B 2 "vsx_register_operand" ""))
++	 (match_operand:VSX_B 3 "vsx_register_operand" "")))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++{
++  if (!TARGET_FUSED_MADD)
++    {
++      emit_insn (gen_vsx_fmsub<mode>4_2 (operands[0], operands[1], operands[2],
++					 operands[3]));
++      DONE;
++    }
++})
 +
-+(define_insn "*vsx_fmsub<mode>4"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+	(minus:VSX_F
-+	 (mult:VSX_F
-+	  (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+	  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
-+	 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
++(define_insn "*vsx_fmsub<mode>4_1"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(minus:VSX_B
++	 (mult:VSX_B
++	  (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
++	  (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
++	 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD"
 +  "@
-+   xvmsuba<VSs> %x0,%x1,%x2
-+   xvmsubm<VSs> %x0,%x1,%x3"
-+  [(set_attr "type" "vecfloat")])
++   x<VSv>msuba<VSs> %x0,%x1,%x2
++   x<VSv>msubm<VSs> %x0,%x1,%x3
++   x<VSv>msuba<VSs> %x0,%x1,%x2
++   x<VSv>msubm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_insn "vsx_fmsub<mode>4_2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
++		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
++		       (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
++		      UNSPEC_VSX_XVMSUB))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "@
++   x<VSv>msuba<VSs> %x0,%x1,%x2
++   x<VSv>msubm<VSs> %x0,%x1,%x3
++   x<VSv>msuba<VSs> %x0,%x1,%x2
++   x<VSv>msubm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_expand "vsx_fnmadd<mode>4"
++  [(match_operand:VSX_B 0 "vsx_register_operand" "")
++   (match_operand:VSX_B 1 "vsx_register_operand" "")
++   (match_operand:VSX_B 2 "vsx_register_operand" "")
++   (match_operand:VSX_B 3 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++{
++  if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
++    {
++       emit_insn (gen_vsx_fnmadd<mode>4_1 (operands[0], operands[1],
++					   operands[2], operands[3]));
++       DONE;
++    }
++  else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
++    {
++       emit_insn (gen_vsx_fnmadd<mode>4_2 (operands[0], operands[1],
++					   operands[2], operands[3]));
++       DONE;
++    }
++  else
++    {
++       emit_insn (gen_vsx_fnmadd<mode>4_3 (operands[0], operands[1],
++					   operands[2], operands[3]));
++       DONE;
++    }
++})
 +
-+(define_insn "*vsx_fnmadd<mode>4_1"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+	(neg:VSX_F
-+	 (plus:VSX_F
-+	  (mult:VSX_F
-+	   (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+	   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
-+	  (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>"))))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++(define_insn "vsx_fnmadd<mode>4_1"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(neg:VSX_B
++	 (plus:VSX_B
++	  (mult:VSX_B
++	   (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
++	   (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
++	  (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
 +   && HONOR_SIGNED_ZEROS (DFmode)"
 +  "@
-+   xvnmadda<VSs> %x0,%x1,%x2
-+   xvnmaddm<VSs> %x0,%x1,%x3"
-+  [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fnmadd<mode>4_2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+	(minus:VSX_F
-+	 (mult:VSX_F
-+	  (neg:VSX_F
-+	   (match_operand:VSX_F 1 "gpc_reg_operand" "%<VSr>,<VSr>"))
-+	  (match_operand:VSX_F 2 "gpc_reg_operand" "<VSr>,0"))
-+	 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++   x<VSv>nmadda<VSs> %x0,%x1,%x2
++   x<VSv>nmaddm<VSs> %x0,%x1,%x3
++   x<VSv>nmadda<VSs> %x0,%x1,%x2
++   x<VSv>nmaddm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_insn "vsx_fnmadd<mode>4_2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(minus:VSX_B
++	 (mult:VSX_B
++	  (neg:VSX_B
++	   (match_operand:VSX_B 1 "gpc_reg_operand" "<VSr>,<VSr>,wa,wa"))
++	  (match_operand:VSX_B 2 "gpc_reg_operand" "<VSr>,0,wa,0"))
++	 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
 +   && !HONOR_SIGNED_ZEROS (DFmode)"
 +  "@
-+   xvnmadda<VSs> %x0,%x1,%x2
-+   xvnmaddm<VSs> %x0,%x1,%x3"
-+  [(set_attr "type" "vecfloat")])
++   x<VSv>nmadda<VSs> %x0,%x1,%x2
++   x<VSv>nmaddm<VSs> %x0,%x1,%x3
++   x<VSv>nmadda<VSs> %x0,%x1,%x2
++   x<VSv>nmaddm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_insn "vsx_fnmadd<mode>4_3"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,<VSr>,wa,wa")
++		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
++		       (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
++		      UNSPEC_VSX_XVNMADD))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "@
++   x<VSv>nmadda<VSs> %x0,%x1,%x2
++   x<VSv>nmaddm<VSs> %x0,%x1,%x3
++   x<VSv>nmadda<VSs> %x0,%x1,%x2
++   x<VSv>nmaddm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_expand "vsx_fnmsub<mode>4"
++  [(match_operand:VSX_B 0 "vsx_register_operand" "")
++   (match_operand:VSX_B 1 "vsx_register_operand" "")
++   (match_operand:VSX_B 2 "vsx_register_operand" "")
++   (match_operand:VSX_B 3 "vsx_register_operand" "")]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++{
++  if (TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (DFmode))
++    {
++       emit_insn (gen_vsx_fnmsub<mode>4_1 (operands[0], operands[1],
++					   operands[2], operands[3]));
++       DONE;
++    }
++  else if (TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (DFmode))
++    {
++       emit_insn (gen_vsx_fnmsub<mode>4_2 (operands[0], operands[1],
++					   operands[2], operands[3]));
++       DONE;
++    }
++  else
++    {
++       emit_insn (gen_vsx_fnmsub<mode>4_3 (operands[0], operands[1],
++					   operands[2], operands[3]));
++       DONE;
++    }
++})
 +
-+(define_insn "*vsx_fnmsub<mode>4_1"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+	(neg:VSX_F
-+	 (minus:VSX_F
-+	  (mult:VSX_F
-+	   (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+	   (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))
-+	  (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>"))))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++(define_insn "vsx_fnmsub<mode>4_1"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(neg:VSX_B
++	 (minus:VSX_B
++	  (mult:VSX_B
++	   (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
++	   (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))
++	  (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa"))))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
 +   && HONOR_SIGNED_ZEROS (DFmode)"
 +  "@
-+   xvnmsuba<VSs> %x0,%x1,%x2
-+   xvnmsubm<VSs> %x0,%x1,%x3"
-+  [(set_attr "type" "vecfloat")])
-+
-+(define_insn "*vsx_fnmsub<mode>4_2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,<VSr>")
-+	(minus:VSX_F
-+	 (match_operand:VSX_F 3 "vsx_register_operand" "0,<VSr>")
-+	 (mult:VSX_F
-+	  (match_operand:VSX_F 1 "vsx_register_operand" "%<VSr>,<VSr>")
-+	  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,0"))))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
++   x<VSv>nmsuba<VSs> %x0,%x1,%x2
++   x<VSv>nmsubm<VSs> %x0,%x1,%x3
++   x<VSv>nmsuba<VSs> %x0,%x1,%x2
++   x<VSv>nmsubm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_insn "vsx_fnmsub<mode>4_2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(minus:VSX_B
++	 (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")
++	 (mult:VSX_B
++	  (match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
++	  (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0"))))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode) && TARGET_FUSED_MADD
 +   && !HONOR_SIGNED_ZEROS (DFmode)"
 +  "@
-+   xvnmsuba<VSs> %x0,%x1,%x2
-+   xvnmsubm<VSs> %x0,%x1,%x3"
-+  [(set_attr "type" "vecfloat")])
-+
-+;; Vector conditional expressions
-+(define_insn "*vsx_eq<mode>"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+	(eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+		  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++   x<VSv>nmsuba<VSs> %x0,%x1,%x2
++   x<VSv>nmsubm<VSs> %x0,%x1,%x3
++   x<VSv>nmsuba<VSs> %x0,%x1,%x2
++   x<VSv>nmsubm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++(define_insn "vsx_fnmsub<mode>4_3"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,<VSr>,?wa,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "%<VSr>,<VSr>,wa,wa")
++		       (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,0,wa,0")
++		       (match_operand:VSX_B 3 "vsx_register_operand" "0,<VSr>,0,wa")]
++		      UNSPEC_VSX_XVNMSUB))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "@
++   x<VSv>nmsuba<VSs> %x0,%x1,%x2
++   x<VSv>nmsubm<VSs> %x0,%x1,%x3
++   x<VSv>nmsuba<VSs> %x0,%x1,%x2
++   x<VSv>nmsubm<VSs> %x0,%x1,%x3"
++  [(set_attr "type" "<VStype_mul>")
++   (set_attr "fp_type" "<VSfptype_mul>")])
++
++;; Vector conditional expressions (no scalar version for these instructions)
++(define_insn "vsx_eq<mode>"
++  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
++	(eq:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
++		  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
 +  "xvcmpeq<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "veccmp")])
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
-+(define_insn "*vsx_gt<mode>"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+	(gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+		  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++(define_insn "vsx_gt<mode>"
++  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
++	(gt:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
++		  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
 +  "xvcmpgt<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "veccmp")])
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +(define_insn "*vsx_ge<mode>"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+	(ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
-+		  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")))]
++  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
++	(ge:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
++		  (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
 +  "xvcmpge<VSs> %x0,%x1,%x2"
-+  [(set_attr "type" "veccmp")])
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +(define_insn "vsx_vsel<mode>"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+	(if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")
++  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>,?wa")
++	(if_then_else:VSX_F (ne (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>,wa")
 +				(const_int 0))
-+			    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")
-+			    (match_operand:VSX_F 3 "vsx_register_operand" "<VSr>")))]
++			    (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>,wa")
++			    (match_operand:VSX_F 3 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
 +  "xxsel %x0,%x3,%x2,%x1"
 +  [(set_attr "type" "vecperm")])
 +
 +;; Copy sign
-+(define_insn "*vsx_copysign<mode>3"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+	(if_then_else:VSX_F
-+	 (ge:VSX_F (match_operand:VSX_F 2 "vsx_register_operand" "<VSr>")
++(define_insn "vsx_copysign<mode>3"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(if_then_else:VSX_B
++	 (ge:VSX_B (match_operand:VSX_B 2 "vsx_register_operand" "<VSr>,wa")
 +		   (const_int 0))
-+	 (abs:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>"))
-+	 (neg:VSX_F (abs:VSX_F (match_dup 1)))))]
++	 (abs:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa"))
++	 (neg:VSX_B (abs:VSX_B (match_dup 1)))))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvcpsgn<VSs> %x0,%x2,%x1"
-+  [(set_attr "type" "vecsimple")])
++  "x<VSv>cpsgn<VSs> %x0,%x2,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
-+(define_insn "*vsx_ftrunc<mode>2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+  	(fix:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++;; For the conversions, limit the register class for the integer value to be
++;; the fprs because we don't want to add the altivec registers to movdi/movsi.
++;; For the unsigned tests, there isn't a generic double -> unsigned conversion
++;; in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against VSX.
++(define_insn "vsx_ftrunc<mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++  	(fix:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvr<VSs>piz %x0,%x1"
-+  [(set_attr "type" "vecperm")])
++  "x<VSv>r<VSs>piz %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
-+(define_insn "*vsx_float<VSi><mode>2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+	(float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
++(define_insn "vsx_float<VSi><mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvcvsx<VSc><VSs> %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
++  "x<VSv>cvsx<VSc><VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
-+(define_insn "*vsx_floatuns<VSi><mode>2"
-+  [(set (match_operand:VSX_F 0 "vsx_register_operand" "=<VSr>")
-+	(unsigned_float:VSX_F (match_operand:<VSI> 1 "vsx_register_operand" "<VSr>")))]
++(define_insn "vsx_floatuns<VSi><mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unsigned_float:VSX_B (match_operand:<VSI> 1 "vsx_register_operand" "<VSr2>,<VSr3>")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvcvux<VSc><VSs> %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
++  "x<VSv>cvux<VSc><VSs> %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
-+(define_insn "*vsx_fix_trunc<mode><VSi>2"
-+  [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr>")
-+	(fix:<VSI> (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++(define_insn "vsx_fix_trunc<mode><VSi>2"
++  [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
++	(fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvcv<VSs>sx<VSc>s %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
++  "x<VSv>cv<VSs>sx<VSc>s %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
-+(define_insn "*vsx_fixuns_trunc<mode><VSi>2"
-+  [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr>")
-+	(unsigned_fix:<VSI> (match_operand:VSX_F 1 "vsx_register_operand" "<VSr>")))]
++(define_insn "vsx_fixuns_trunc<mode><VSi>2"
++  [(set (match_operand:<VSI> 0 "vsx_register_operand" "=<VSr2>,?<VSr3>")
++	(unsigned_fix:<VSI> (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
 +  "VECTOR_UNIT_VSX_P (<MODE>mode)"
-+  "xvcv<VSs>ux<VSc>s %x0,%x1"
-+  [(set_attr "type" "vecfloat")])
++  "x<VSv>cv<VSs>ux<VSc>s %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
++
++;; Math rounding functions
++(define_insn "vsx_btrunc<mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
++		      UNSPEC_FRIZ))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>r<VSs>iz %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
++
++(define_insn "vsx_floor<mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
++		      UNSPEC_FRIM))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>r<VSs>im %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
++
++(define_insn "vsx_ceil<mode>2"
++  [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
++	(unspec:VSX_B [(match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")]
++		      UNSPEC_FRIP))]
++  "VECTOR_UNIT_VSX_P (<MODE>mode)"
++  "x<VSv>r<VSs>ip %x0,%x1"
++  [(set_attr "type" "<VStype_simple>")
++   (set_attr "fp_type" "<VSfptype_simple>")])
 +
 +
-+;; VSX scalar double precision floating point operations
-+(define_insn"*vsx_adddf3"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(plus:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+		     (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsadddp %x0,%x1,%x2"
-+  [(set_attr "type" "fp")
-+   (set_attr "fp_type" "fp_addsub_d")])
-+
-+(define_insn"*vsx_subdf3"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(minus:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+		      (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xssubdp %x0,%x1,%x2"
-+  [(set_attr "type" "fp")
-+   (set_attr "fp_type" "fp_addsub_d")])
-+
-+(define_insn"*vsx_muldf3"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(mult:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+		     (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsmuldp %x0,%x1,%x2"
-+  [(set_attr "type" "dmul")
-+   (set_attr "fp_type" "fp_mul_d")])
-+
-+(define_insn"*vsx_divdf3"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(div:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+		    (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsdivdp %x0,%x1,%x2"
-+  [(set_attr "type" "ddiv")])
-+
-+(define_insn "*vsx_fredf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
-+		   UNSPEC_FRES))]
-+  "flag_finite_math_only && VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsredp %x0,%x1"
-+  [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_sqrtdf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+        (sqrt:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xssqrtdp %x0,%x1"
-+  [(set_attr "type" "dsqrt")])
-+
-+(define_insn"*vsx_negdf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(neg:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsnegdp %x0,%x1"
-+  [(set_attr "type" "fp")])
-+
-+(define_insn"vsx_absdf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(abs:DF (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsabsdp %x0,%x1"
-+  [(set_attr "type" "fp")])
-+
-+(define_insn"*vsx_nabsdf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(neg:DF (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsnabsdp %x0,%x1"
-+  [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_smaxdf3"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+        (smax:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+		 (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsmaxdp %x0,%x1,%x2"
-+  [(set_attr "type" "fp")])
-+
-+
-+(define_insn "*vsx_smindf3"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+        (smin:DF (match_operand:DF 1 "vsx_register_operand" "ws")
-+		 (match_operand:DF 2 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsmindp %x0,%x1,%x2"
-+  [(set_attr "type" "fp")])
-+
-+;; Fused vector multiply/add instructions
-+(define_insn "*vsx_fmadddf4"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+	(plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+			  (match_operand:DF 2 "vsx_register_operand" "ws,0"))
-+		 (match_operand:DF 3 "gpc_reg_operand" "0,ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
-+  "@
-+   xsmaddadp %x0,%x1,%x2
-+   xsmaddmdp %x0,%x1,%x3"
-+  [(set_attr "type" "dmul")
-+   (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fmsubdf4"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+	(minus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+			   (match_operand:DF 2 "vsx_register_operand" "ws,0"))
-+		  (match_operand:DF 3 "vsx_register_operand" "0,ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD"
-+  "@
-+   xsmsubadp %x0,%x1,%x2
-+   xsmsubmdp %x0,%x1,%x3"
-+  [(set_attr "type" "dmul")
-+   (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fnmadddf4_1"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+	(neg:DF
-+	 (plus:DF (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+			   (match_operand:DF 2 "vsx_register_operand" "ws,0"))
-+		  (match_operand:DF 3 "vsx_register_operand" "0,ws"))))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+   && HONOR_SIGNED_ZEROS (DFmode)"
-+  "@
-+   xsnmaddadp %x0,%x1,%x2
-+   xsnmaddmdp %x0,%x1,%x3"
-+  [(set_attr "type" "dmul")
-+   (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fnmadddf4_2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+	(minus:DF (mult:DF (neg:DF
-+			    (match_operand:DF 1 "gpc_reg_operand" "%ws,ws"))
-+			   (match_operand:DF 2 "gpc_reg_operand" "ws,0"))
-+		  (match_operand:DF 3 "vsx_register_operand" "0,ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+   && !HONOR_SIGNED_ZEROS (DFmode)"
-+  "@
-+   xsnmaddadp %x0,%x1,%x2
-+   xsnmaddmdp %x0,%x1,%x3"
-+  [(set_attr "type" "dmul")
-+   (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fnmsubdf4_1"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+	(neg:DF
-+	 (minus:DF
-+	  (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+		   (match_operand:DF 2 "vsx_register_operand" "ws,0"))
-+	  (match_operand:DF 3 "vsx_register_operand" "0,ws"))))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+   && HONOR_SIGNED_ZEROS (DFmode)"
-+  "@
-+   xsnmsubadp %x0,%x1,%x2
-+   xsnmsubmdp %x0,%x1,%x3"
-+  [(set_attr "type" "dmul")
-+   (set_attr "fp_type" "fp_maddsub_d")])
-+
-+(define_insn "*vsx_fnmsubdf4_2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws,ws")
-+	(minus:DF
-+	 (match_operand:DF 3 "vsx_register_operand" "0,ws")
-+	 (mult:DF (match_operand:DF 1 "vsx_register_operand" "%ws,ws")
-+		  (match_operand:DF 2 "vsx_register_operand" "ws,0"))))]
-+  "VECTOR_UNIT_VSX_P (DFmode) && TARGET_FUSED_MADD
-+   && !HONOR_SIGNED_ZEROS (DFmode)"
-+  "@
-+   xsnmsubadp %x0,%x1,%x2
-+   xsnmsubmdp %x0,%x1,%x3"
-+  [(set_attr "type" "dmul")
-+   (set_attr "fp_type" "fp_maddsub_d")])
-+
-+;; For the conversions, limit the register class for the integer value to be
-+;; the fprs.  For the unsigned tests, there isn't a generic double -> unsigned
-+;; conversion in rs6000.md so don't test VECTOR_UNIT_VSX_P, just test against
-+;; VSX.
-+
-+(define_insn "*vsx_floatdidf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xscvsxddp %x0,%x1"
-+  [(set_attr "type" "fp")])
-+
-+(define_insn "*vsx_floatunsdidf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(unsigned_float:DF (match_operand:DI 1 "vsx_register_operand" "!f#r")))]
-+  "TARGET_HARD_FLOAT && TARGET_VSX"
-+  "xscvuxddp %x0,%x1"
-+  [(set_attr "type" "fp")])
++;; VSX convert to/from double vector
 +
-+(define_insn "*vsx_fix_truncdfdi2"
-+  [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r")
-+	(fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xscvdpsxds %x0,%x1"
-+  [(set_attr "type" "fp")])
++;; 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_fixuns_truncdfdi2"
-+  [(set (match_operand:DI 0 "vsx_register_operand" "=!f#r")
-+	(unsigned_fix:DI (match_operand:DF 1 "vsx_register_operand" "ws")))]
-+  "TARGET_HARD_FLOAT && TARGET_VSX"
-+  "xscvdpuxds %x0,%x1"
-+  [(set_attr "type" "fp")])
++(define_insn "vsx_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_btruncdf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
-+		   UNSPEC_FRIZ))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsrdpiz %x0,%x1"
-+  [(set_attr "type" "fp")])
++(define_insn "vsx_xvcvdpsxws"
++  [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
++	(unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
++		     UNSPEC_VSX_XVCVDPSXWS))]
++  "VECTOR_UNIT_VSX_P (V2DFmode)"
++  "xvcvdpsxws %x0,%x1"
++  [(set_attr "type" "vecfloat")])
 +
-+(define_insn "*vsx_floordf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
-+		   UNSPEC_FRIM))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsrdpim %x0,%x1"
-+  [(set_attr "type" "fp")])
++(define_insn "vsx_xvcvdpuxws"
++  [(set (match_operand:V4SI 0 "vsx_register_operand" "=v,?wa")
++	(unspec:V4SI [(match_operand:V2DF 1 "vsx_register_operand" "wd,wa")]
++		     UNSPEC_VSX_XVCVDPUXWS))]
++  "VECTOR_UNIT_VSX_P (V2DFmode)"
++  "xvcvdpuxws %x0,%x1"
++  [(set_attr "type" "vecfloat")])
 +
-+(define_insn "*vsx_ceildf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(unspec:DF [(match_operand:DF 1 "vsx_register_operand" "ws")]
-+		   UNSPEC_FRIP))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsrdpip %x0,%x1"
-+  [(set_attr "type" "fp")])
++;; Convert from 32-bit to 64-bit types
++(define_insn "vsx_xvcvspdp"
++  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
++	(unspec:V2DF [(match_operand:V4SF 1 "vsx_register_operand" "wf,wa")]
++		     UNSPEC_VSX_XVCVSPDP))]
++  "VECTOR_UNIT_VSX_P (V2DFmode)"
++  "xvcvspdp %x0,%x1"
++  [(set_attr "type" "vecfloat")])
 +
-+(define_insn "vsx_copysigndf3"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(if_then_else:DF (ge:DF (match_operand:DF 2 "vsx_register_operand" "ws")
-+				(const_int 0))
-+			 (abs:DF (match_operand:DF 1 "vsx_register_operand" "ws"))
-+			 (neg:DF (abs:DF (match_dup 1)))))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xscpsgndp %x0,%x2,%x1"
-+  [(set_attr "type" "fp")])
++(define_insn "vsx_xvcvsxwdp"
++  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
++	(unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
++		     UNSPEC_VSX_XVCVSXWDP))]
++  "VECTOR_UNIT_VSX_P (V2DFmode)"
++  "xvcvsxwdp %x0,%x1"
++  [(set_attr "type" "vecfloat")])
 +
-+(define_insn "*vsx_ftruncdf2"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+  	(fix:DF (match_operand:DF 1 "register_operand" "ws")))]
-+  "VECTOR_UNIT_VSX_P (DFmode)"
-+  "xsrdppiz %x0,%x1"
++(define_insn "vsx_xvcvuxwdp"
++  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
++	(unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
++		     UNSPEC_VSX_XVCVUXWDP))]
++  "VECTOR_UNIT_VSX_P (V2DFmode)"
++  "xvcvuxwdp %x0,%x1"
 +  [(set_attr "type" "vecfloat")])
 +
 +
@@ -6450,8 +8350,8 @@ testsuite/
 +(define_insn "vsx_concat_v2df"
 +  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
 +	(unspec:V2DF
-+	 [(match_operand:DF 1 "vsx_register_operand" "f,wa")
-+	  (match_operand:DF 2 "vsx_register_operand" "f,wa")]
++	 [(match_operand:DF 1 "vsx_register_operand" "ws,wa")
++	  (match_operand:DF 2 "vsx_register_operand" "ws,wa")]
 +	 UNSPEC_VSX_CONCAT_V2DF))]
 +  "VECTOR_UNIT_VSX_P (V2DFmode)"
 +  "xxpermdi %x0,%x1,%x2,0"
@@ -6459,32 +8359,37 @@ testsuite/
 +
 +;; Set a double into one element
 +(define_insn "vsx_set_v2df"
-+  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
++  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
 +	(vec_merge:V2DF
-+	 (match_operand:V2DF 1 "vsx_register_operand" "wd")
-+	 (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws"))
-+	 (match_operand:QI 3 "u5bit_cint_operand" "i")))]
++	 (match_operand:V2DF 1 "vsx_register_operand" "wd,wa")
++	 (vec_duplicate:V2DF (match_operand:DF 2 "vsx_register_operand" "ws,f"))
++	 (match_operand:QI 3 "u5bit_cint_operand" "i,i")))]
 +  "VECTOR_UNIT_VSX_P (V2DFmode)"
 +{
-+  operands[3] = GEN_INT (INTVAL (operands[3]) & 1);
-+  return \"xxpermdi %x0,%x1,%x2,%3\";
++  if (INTVAL (operands[3]) == 0)
++    return \"xxpermdi %x0,%x1,%x2,1\";
++  else if (INTVAL (operands[3]) == 1)
++    return \"xxpermdi %x0,%x2,%x1,0\";
++  else
++    gcc_unreachable ();
 +}
 +  [(set_attr "type" "vecperm")])
 +
 +;; Extract a DF element from V2DF
 +(define_insn "vsx_extract_v2df"
-+  [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
-+	(vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd")
++  [(set (match_operand:DF 0 "vsx_register_operand" "=ws,f,?wa")
++	(vec_select:DF (match_operand:V2DF 1 "vsx_register_operand" "wd,wd,wa")
 +		       (parallel
-+			[(match_operand:QI 2 "u5bit_cint_operand" "i")])))]
++			[(match_operand:QI 2 "u5bit_cint_operand" "i,i,i")])))]
 +  "VECTOR_UNIT_VSX_P (V2DFmode)"
 +{
-+  operands[3] = GEN_INT (INTVAL (operands[2]) & 1);
++  gcc_assert (UINTVAL (operands[2]) <= 1);
++  operands[3] = GEN_INT (INTVAL (operands[2]) << 1);
 +  return \"xxpermdi %x0,%x1,%x1,%3\";
 +}
 +  [(set_attr "type" "vecperm")])
 +
-+;; General V2DF permute
++;; General V2DF permute, extract_{high,low,even,odd}
 +(define_insn "vsx_xxpermdi"
 +  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd")
 +	(vec_concat:V2DF
@@ -6496,6 +8401,7 @@ testsuite/
 +			 [(match_operand:QI 4 "u5bit_cint_operand" "i")]))))]
 +  "VECTOR_UNIT_VSX_P (V2DFmode)"
 +{
++  gcc_assert ((UINTVAL (operands[2]) <= 1) && (UINTVAL (operands[4]) <= 1));
 +  operands[5] = GEN_INT (((INTVAL (operands[2]) & 1) << 1)
 +			 | (INTVAL (operands[4]) & 1));
 +  return \"xxpermdi %x0,%x1,%x3,%5\";
@@ -6504,71 +8410,70 @@ testsuite/
 +
 +;; V2DF splat
 +(define_insn "vsx_splatv2df"
-+  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd")
++  [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,wd,?wa,?wa,?wa")
 +	(vec_duplicate:V2DF
-+	 (match_operand:DF 1 "input_operand" "ws,Z")))]
++	 (match_operand:DF 1 "input_operand" "ws,f,Z,wa,wa,Z")))]
 +  "VECTOR_UNIT_VSX_P (V2DFmode)"
 +  "@
 +   xxpermdi %x0,%x1,%x1,0
++   xxpermdi %x0,%x1,%x1,0
++   lxvdsx %x0,%y1
++   xxpermdi %x0,%x1,%x1,0
++   xxpermdi %x0,%x1,%x1,0
 +   lxvdsx %x0,%y1"
-+  [(set_attr "type" "vecperm,vecload")])
++  [(set_attr "type" "vecperm,vecperm,vecload,vecperm,vecperm,vecload")])
 +
 +;; V4SF splat
 +(define_insn "*vsx_xxspltw"
-+  [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf")
++  [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,?wa")
 +	(vec_duplicate:V4SF
-+	 (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf")
++	 (vec_select:SF (match_operand:V4SF 1 "vsx_register_operand" "wf,wa")
 +			(parallel
-+			 [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
++			 [(match_operand:QI 2 "u5bit_cint_operand" "i,i")]))))]
 +  "VECTOR_UNIT_VSX_P (V4SFmode)"
 +  "xxspltw %x0,%x1,%2"
 +  [(set_attr "type" "vecperm")])
 +
 +;; V4SF interleave
-+(define_insn "*vsx_xxmrghw"
-+  [(set (match_operand:V4SF 0 "register_operand" "=v")
-+        (vec_merge:V4SF (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
-+                                         (parallel [(const_int 0)
-+                                                    (const_int 2)
-+                                                    (const_int 1)
-+                                                    (const_int 3)]))
-+                        (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
-+                                         (parallel [(const_int 2)
-+                                                    (const_int 0)
-+                                                    (const_int 3)
-+                                                    (const_int 1)]))
-+                      (const_int 5)))]
-+  "VECTOR_UNIT_VSX_P (V4SFmode)"
-+  "xxmrghw %x0,%x1,%x2"
-+  [(set_attr "type" "vecperm")])
-+
-+(define_insn "*vsx_xxmrglw"
-+  [(set (match_operand:V4SF 0 "register_operand" "=v")
++(define_insn "vsx_xxmrghw"
++  [(set (match_operand:V4SF 0 "register_operand" "=wf,?wa")
 +        (vec_merge:V4SF
-+	 (vec_select:V4SF (match_operand:V4SF 1 "register_operand" "v")
-+			  (parallel [(const_int 2)
-+				     (const_int 0)
-+				     (const_int 3)
-+				     (const_int 1)]))
-+	 (vec_select:V4SF (match_operand:V4SF 2 "register_operand" "v")
++	 (vec_select:V4SF (match_operand:V4SF 1 "vsx_register_operand" "wf,wa")
 +			  (parallel [(const_int 0)
 +				     (const_int 2)
 +				     (const_int 1)
 +				     (const_int 3)]))
++	 (vec_select:V4SF (match_operand:V4SF 2 "vsx_register_operand" "wf,wa")
++			  (parallel [(const_int 2)
++				     (const_int 0)
++				     (const_int 3)
++				     (const_int 1)]))
++	 (const_int 5)))]
++  "VECTOR_UNIT_VSX_P (V4SFmode)"
++  "xxmrghw %x0,%x1,%x2"
++  [(set_attr "type" "vecperm")])
++
++(define_insn "vsx_xxmrglw"
++  [(set (match_operand:V4SF 0 "register_operand" "=wf,?wa")
++        (vec_merge:V4SF
++	 (vec_select:V4SF
++	  (match_operand:V4SF 1 "register_operand" "wf,wa")
++	  (parallel [(const_int 2)
++		     (const_int 0)
++		     (const_int 3)
++		     (const_int 1)]))
++	 (vec_select:V4SF
++	  (match_operand:V4SF 2 "register_operand" "wf,?wa")
++	  (parallel [(const_int 0)
++		     (const_int 2)
++		     (const_int 1)
++		     (const_int 3)]))
 +	 (const_int 5)))]
 +  "VECTOR_UNIT_VSX_P (V4SFmode)"
 +  "xxmrglw %x0,%x1,%x2"
 +  [(set_attr "type" "vecperm")])
---- gcc/config/rs6000/rs6000.h	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/rs6000.h	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -1,6 +1,6 @@
- /* Definitions of target machine for GNU compiler, for IBM RS/6000.
-    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
--   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
-+   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-    Free Software Foundation, Inc.
-    Contributed by Richard Kenner (kenner at vlsi1.ultra.nyu.edu)
- 
+--- gcc/config/rs6000/rs6000.h	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/rs6000.h	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -72,14 +72,16 @@
  #define ASM_CPU_POWER6_SPEC "-mpower4 -maltivec"
  #endif
@@ -6616,22 +8521,25 @@ testsuite/
  #endif
  
  #ifndef CC1_CPU_SPEC
-@@ -240,6 +248,14 @@ extern const char *host_detect_local_cpu
- #define TARGET_DFP 0
+@@ -233,11 +241,12 @@ extern const char *host_detect_local_cpu
+ #define TARGET_MFPGPR 0
  #endif
  
+-/* Define TARGET_DFP if the target assembler does not support decimal
+-   floating point instructions.  */
+-#ifndef HAVE_AS_DFP
+-#undef  TARGET_DFP
+-#define TARGET_DFP 0
 +/* Define TARGET_POPCNTD if the target assembler does not support the
 +   popcount word and double word instructions.  */
 +
 +#ifndef HAVE_AS_POPCNTD
 +#undef  TARGET_POPCNTD
 +#define TARGET_POPCNTD 0
-+#endif
-+
- #ifndef TARGET_SECURE_PLT
- #define TARGET_SECURE_PLT 0
  #endif
-@@ -295,6 +311,7 @@ enum processor_type
+ 
+ #ifndef TARGET_SECURE_PLT
+@@ -295,6 +304,7 @@ enum processor_type
     PROCESSOR_POWER4,
     PROCESSOR_POWER5,
     PROCESSOR_POWER6,
@@ -6639,21 +8547,23 @@ testsuite/
     PROCESSOR_CELL
  };
  
-@@ -388,9 +405,13 @@ extern struct rs6000_cpu_select rs6000_s
+@@ -388,9 +398,15 @@ extern struct rs6000_cpu_select rs6000_s
  extern const char *rs6000_debug_name;	/* Name for -mdebug-xxxx option */
  extern int rs6000_debug_stack;		/* debug stack applications */
  extern int rs6000_debug_arg;		/* debug argument handling */
 +extern int rs6000_debug_reg;		/* debug register handling */
 +extern int rs6000_debug_addr;		/* debug memory addressing */
++extern int rs6000_debug_cost;		/* debug rtx_costs */
  
  #define	TARGET_DEBUG_STACK	rs6000_debug_stack
  #define	TARGET_DEBUG_ARG	rs6000_debug_arg
 +#define TARGET_DEBUG_REG	rs6000_debug_reg
 +#define TARGET_DEBUG_ADDR	rs6000_debug_addr
++#define TARGET_DEBUG_COST	rs6000_debug_cost
  
  extern const char *rs6000_traceback_name; /* Type of traceback table.  */
  
-@@ -401,13 +422,65 @@ extern int rs6000_ieeequad;
+@@ -401,13 +417,65 @@ extern int rs6000_ieeequad;
  extern int rs6000_altivec_abi;
  extern int rs6000_spe_abi;
  extern int rs6000_spe;
@@ -6720,7 +8630,7 @@ testsuite/
  /* Alignment options for fields in structures for sub-targets following
     AIX-like ABI.
     ALIGN_POWER word-aligns FP doubles (default AIX ABI).
-@@ -432,7 +505,7 @@ extern int rs6000_xilinx_fpu;
+@@ -432,7 +500,7 @@ extern int rs6000_xilinx_fpu;
  #define TARGET_SPE_ABI 0
  #define TARGET_SPE 0
  #define TARGET_E500 0
@@ -6729,7 +8639,7 @@ testsuite/
  #define TARGET_FPRS 1
  #define TARGET_E500_SINGLE 0
  #define TARGET_E500_DOUBLE 0
-@@ -530,6 +603,7 @@ extern int rs6000_xilinx_fpu;
+@@ -530,6 +598,7 @@ extern int rs6000_xilinx_fpu;
  #endif
  #define UNITS_PER_FP_WORD 8
  #define UNITS_PER_ALTIVEC_WORD 16
@@ -6737,7 +8647,7 @@ testsuite/
  #define UNITS_PER_SPE_WORD 8
  #define UNITS_PER_PAIRED_WORD 8
  
-@@ -600,8 +674,9 @@ extern int rs6000_xilinx_fpu;
+@@ -600,8 +669,9 @@ extern int rs6000_xilinx_fpu;
  #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
  
  /* Boundary (in *bits*) on which stack pointer should be aligned.  */
@@ -6749,7 +8659,7 @@ testsuite/
  
  /* Allocation boundary (in *bits*) for the code of a function.  */
  #define FUNCTION_BOUNDARY 32
-@@ -613,10 +688,11 @@ extern int rs6000_xilinx_fpu;
+@@ -613,10 +683,11 @@ extern int rs6000_xilinx_fpu;
     local store.  TYPE is the data type, and ALIGN is the alignment
     that the object would ordinarily have.  */
  #define LOCAL_ALIGNMENT(TYPE, ALIGN)				\
@@ -6764,7 +8674,7 @@ testsuite/
       && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \
          && TREE_CODE (TYPE) == VECTOR_TYPE \
          && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN)
-@@ -674,15 +750,17 @@ extern int rs6000_xilinx_fpu;
+@@ -674,15 +745,17 @@ extern int rs6000_xilinx_fpu;
  /* Define this macro to be the value 1 if unaligned accesses have a cost
     many times greater than aligned accesses, for example if they are
     emulated in a trap handler.  */
@@ -6785,7 +8695,7 @@ testsuite/
  
  /* Standard register usage.  */
  
-@@ -909,16 +987,60 @@ extern int rs6000_xilinx_fpu;
+@@ -909,16 +982,60 @@ extern int rs6000_xilinx_fpu;
  /* True if register is an AltiVec register.  */
  #define ALTIVEC_REGNO_P(N) ((N) >= FIRST_ALTIVEC_REGNO && (N) <= LAST_ALTIVEC_REGNO)
  
@@ -6847,7 +8757,7 @@ testsuite/
  #define ALTIVEC_VECTOR_MODE(MODE)	\
  	 ((MODE) == V16QImode		\
  	  || (MODE) == V8HImode		\
-@@ -934,10 +1056,12 @@ extern int rs6000_xilinx_fpu;
+@@ -934,10 +1051,12 @@ extern int rs6000_xilinx_fpu;
  #define PAIRED_VECTOR_MODE(MODE)        \
           ((MODE) == V2SFmode)            
  
@@ -6864,7 +8774,7 @@ testsuite/
  
  /* Value is TRUE if hard register REGNO can hold a value of
     machine-mode MODE.  */
-@@ -965,6 +1089,10 @@ extern int rs6000_xilinx_fpu;
+@@ -965,6 +1084,10 @@ extern int rs6000_xilinx_fpu;
     ? ALTIVEC_VECTOR_MODE (MODE2)		\
     : ALTIVEC_VECTOR_MODE (MODE2)		\
     ? ALTIVEC_VECTOR_MODE (MODE1)		\
@@ -6875,7 +8785,7 @@ testsuite/
     : 1)
  
  /* Post-reload, we can't use any new AltiVec registers, as we already
-@@ -1056,9 +1184,10 @@ extern int rs6000_xilinx_fpu;
+@@ -1056,9 +1179,10 @@ extern int rs6000_xilinx_fpu;
     For any two classes, it is very desirable that there be another
     class that represents their union.  */
  
@@ -6889,7 +8799,7 @@ testsuite/
  
     However, r0 is special in that it cannot be used as a base register.
     So make a class for registers valid as base registers.
-@@ -1073,6 +1202,7 @@ enum reg_class
+@@ -1073,6 +1197,7 @@ enum reg_class
    GENERAL_REGS,
    FLOAT_REGS,
    ALTIVEC_REGS,
@@ -6897,7 +8807,7 @@ testsuite/
    VRSAVE_REGS,
    VSCR_REGS,
    SPE_ACC_REGS,
-@@ -1103,6 +1233,7 @@ enum reg_class
+@@ -1103,6 +1228,7 @@ enum reg_class
    "GENERAL_REGS",							\
    "FLOAT_REGS",								\
    "ALTIVEC_REGS",							\
@@ -6905,7 +8815,7 @@ testsuite/
    "VRSAVE_REGS",							\
    "VSCR_REGS",								\
    "SPE_ACC_REGS",                                                       \
-@@ -1132,6 +1263,7 @@ enum reg_class
+@@ -1132,6 +1258,7 @@ enum reg_class
    { 0xffffffff, 0x00000000, 0x00000008, 0x00020000 }, /* GENERAL_REGS */     \
    { 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FLOAT_REGS */       \
    { 0x00000000, 0x00000000, 0xffffe000, 0x00001fff }, /* ALTIVEC_REGS */     \
@@ -6913,25 +8823,43 @@ testsuite/
    { 0x00000000, 0x00000000, 0x00000000, 0x00002000 }, /* VRSAVE_REGS */	     \
    { 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */	     \
    { 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */     \
-@@ -1179,8 +1311,8 @@ enum reg_class
-   : (REGNO) == CR0_REGNO ? CR0_REGS		\
-   : CR_REGNO_P (REGNO) ? CR_REGS		\
-   : (REGNO) == MQ_REGNO ? MQ_REGS		\
+@@ -1171,29 +1298,29 @@ enum reg_class
+    reg number REGNO.  This could be a conditional expression
+    or could index an array.  */
+ 
+-#define REGNO_REG_CLASS(REGNO)			\
+- ((REGNO) == 0 ? GENERAL_REGS			\
+-  : (REGNO) < 32 ? BASE_REGS			\
+-  : FP_REGNO_P (REGNO) ? FLOAT_REGS		\
+-  : ALTIVEC_REGNO_P (REGNO) ? ALTIVEC_REGS	\
+-  : (REGNO) == CR0_REGNO ? CR0_REGS		\
+-  : CR_REGNO_P (REGNO) ? CR_REGS		\
+-  : (REGNO) == MQ_REGNO ? MQ_REGS		\
 -  : (REGNO) == LR_REGNO ? LINK_REGS	\
 -  : (REGNO) == CTR_REGNO ? CTR_REGS	\
-+  : (REGNO) == LR_REGNO ? LINK_REGS		\
-+  : (REGNO) == CTR_REGNO ? CTR_REGS		\
-   : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS	\
-   : (REGNO) == XER_REGNO ? XER_REGS		\
-   : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS	\
-@@ -1190,10 +1322,18 @@ enum reg_class
-   : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS	\
-   : NO_REGS)
- 
+-  : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS	\
+-  : (REGNO) == XER_REGNO ? XER_REGS		\
+-  : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS	\
+-  : (REGNO) == VSCR_REGNO ? VRSAVE_REGS		\
+-  : (REGNO) == SPE_ACC_REGNO ? SPE_ACC_REGS	\
+-  : (REGNO) == SPEFSCR_REGNO ? SPEFSCR_REGS	\
+-  : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS	\
+-  : NO_REGS)
++extern enum reg_class rs6000_regno_regclass[FIRST_PSEUDO_REGISTER];
++
++#if ENABLE_CHECKING
++#define REGNO_REG_CLASS(REGNO) 						\
++  (gcc_assert (IN_RANGE ((REGNO), 0, FIRST_PSEUDO_REGISTER-1)),		\
++   rs6000_regno_regclass[(REGNO)])
++
++#else
++#define REGNO_REG_CLASS(REGNO) rs6000_regno_regclass[(REGNO)]
++#endif
++
 +/* VSX register classes.  */
 +extern enum reg_class rs6000_vector_reg_class[];
 +extern enum reg_class rs6000_vsx_reg_class;
-+
+ 
  /* The class value for index registers, and the one for base regs.  */
  #define INDEX_REG_CLASS GENERAL_REGS
  #define BASE_REG_CLASS BASE_REGS
@@ -6943,7 +8871,7 @@ testsuite/
  /* Given an rtx X being reloaded into a reg required to be
     in class CLASS, return the class of reg to actually use.
     In general this is just CLASS; but on some machines
-@@ -1213,13 +1353,7 @@ enum reg_class
+@@ -1213,13 +1340,7 @@ enum reg_class
   */
  
  #define PREFERRED_RELOAD_CLASS(X,CLASS)			\
@@ -6958,7 +8886,7 @@ testsuite/
  
  /* Return the register class of a scratch register needed to copy IN into
     or out of a register in CLASS in MODE.  If it can be done directly,
-@@ -1234,18 +1368,7 @@ enum reg_class
+@@ -1234,18 +1355,7 @@ enum reg_class
     are available.*/
  
  #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE)			\
@@ -6978,7 +8906,7 @@ testsuite/
  
  /* For cpus that cannot load/store SDmode values from the 64-bit
     FP registers without using a full 64-bit load/store, we need
-@@ -1257,32 +1380,15 @@ enum reg_class
+@@ -1257,32 +1367,15 @@ enum reg_class
  /* Return the maximum number of consecutive registers
     needed to represent mode MODE in a register of class CLASS.
  
@@ -7016,7 +8944,7 @@ testsuite/
  
  /* Stack layout; function entry, exit and calling.  */
  
-@@ -1343,8 +1449,8 @@ extern enum rs6000_abi rs6000_current_ab
+@@ -1343,8 +1436,8 @@ extern enum rs6000_abi rs6000_current_ab
  #define STARTING_FRAME_OFFSET						\
    (FRAME_GROWS_DOWNWARD							\
     ? 0									\
@@ -7027,7 +8955,7 @@ testsuite/
        + RS6000_SAVE_AREA))
  
  /* Offset from the stack pointer register to an item dynamically
-@@ -1354,8 +1460,8 @@ extern enum rs6000_abi rs6000_current_ab
+@@ -1354,8 +1447,8 @@ extern enum rs6000_abi rs6000_current_ab
     length of the outgoing arguments.  The default is correct for most
     machines.  See `function.c' for details.  */
  #define STACK_DYNAMIC_OFFSET(FUNDECL)					\
@@ -7038,7 +8966,7 @@ testsuite/
     + (STACK_POINTER_OFFSET))
  
  /* If we generate an insn to push BYTES bytes,
-@@ -1605,7 +1711,7 @@ typedef struct rs6000_args
+@@ -1605,7 +1698,7 @@ typedef struct rs6000_args
  #define	EPILOGUE_USES(REGNO)					\
    ((reload_completed && (REGNO) == LR_REGNO)			\
     || (TARGET_ALTIVEC && (REGNO) == VRSAVE_REGNO)		\
@@ -7047,7 +8975,7 @@ testsuite/
         && TARGET_AIX						\
         && (REGNO) == 2))
  
-@@ -2316,7 +2422,24 @@ extern char rs6000_reg_names[][8];	/* re
+@@ -2316,7 +2409,24 @@ extern char rs6000_reg_names[][8];	/* re
    /* no additional names for: mq, lr, ctr, ap */		\
    {"cr0",  68}, {"cr1",  69}, {"cr2",  70}, {"cr3",  71},	\
    {"cr4",  72}, {"cr5",  73}, {"cr6",  74}, {"cr7",  75},	\
@@ -7073,7 +9001,7 @@ testsuite/
  
  /* Text to write out after a CALL that may be replaced by glue code by
     the loader.  This depends on the AIX version.  */
-@@ -2480,10 +2603,14 @@ enum rs6000_builtins
+@@ -2480,10 +2590,14 @@ enum rs6000_builtins
    ALTIVEC_BUILTIN_VSEL_4SF,
    ALTIVEC_BUILTIN_VSEL_8HI,
    ALTIVEC_BUILTIN_VSEL_16QI,
@@ -7088,7 +9016,15 @@ testsuite/
    ALTIVEC_BUILTIN_VPKUHUM,
    ALTIVEC_BUILTIN_VPKUWUM,
    ALTIVEC_BUILTIN_VPKPX,
-@@ -3110,6 +3237,163 @@ enum rs6000_builtins
+@@ -2839,6 +2953,7 @@ enum rs6000_builtins
+   ALTIVEC_BUILTIN_VEC_PROMOTE,
+   ALTIVEC_BUILTIN_VEC_INSERT,
+   ALTIVEC_BUILTIN_VEC_SPLATS,
++
+   ALTIVEC_BUILTIN_OVERLOADED_LAST = ALTIVEC_BUILTIN_VEC_SPLATS,
+ 
+   /* SPE builtins.  */
+@@ -3110,6 +3225,163 @@ enum rs6000_builtins
    RS6000_BUILTIN_RECIPF,
    RS6000_BUILTIN_RSQRTF,
  
@@ -7177,34 +9113,24 @@ testsuite/
 +  VSX_BUILTIN_XVCVUXWSP,
 +  VSX_BUILTIN_XVDIVDP,
 +  VSX_BUILTIN_XVDIVSP,
-+  VSX_BUILTIN_XVMADDADP,
-+  VSX_BUILTIN_XVMADDASP,
-+  VSX_BUILTIN_XVMADDMDP,
-+  VSX_BUILTIN_XVMADDMSP,
++  VSX_BUILTIN_XVMADDDP,
++  VSX_BUILTIN_XVMADDSP,
 +  VSX_BUILTIN_XVMAXDP,
 +  VSX_BUILTIN_XVMAXSP,
 +  VSX_BUILTIN_XVMINDP,
 +  VSX_BUILTIN_XVMINSP,
-+  VSX_BUILTIN_XVMOVDP,
-+  VSX_BUILTIN_XVMOVSP,
-+  VSX_BUILTIN_XVMSUBADP,
-+  VSX_BUILTIN_XVMSUBASP,
-+  VSX_BUILTIN_XVMSUBMDP,
-+  VSX_BUILTIN_XVMSUBMSP,
++  VSX_BUILTIN_XVMSUBDP,
++  VSX_BUILTIN_XVMSUBSP,
 +  VSX_BUILTIN_XVMULDP,
 +  VSX_BUILTIN_XVMULSP,
 +  VSX_BUILTIN_XVNABSDP,
 +  VSX_BUILTIN_XVNABSSP,
 +  VSX_BUILTIN_XVNEGDP,
 +  VSX_BUILTIN_XVNEGSP,
-+  VSX_BUILTIN_XVNMADDADP,
-+  VSX_BUILTIN_XVNMADDASP,
-+  VSX_BUILTIN_XVNMADDMDP,
-+  VSX_BUILTIN_XVNMADDMSP,
-+  VSX_BUILTIN_XVNMSUBADP,
-+  VSX_BUILTIN_XVNMSUBASP,
-+  VSX_BUILTIN_XVNMSUBMDP,
-+  VSX_BUILTIN_XVNMSUBMSP,
++  VSX_BUILTIN_XVNMADDDP,
++  VSX_BUILTIN_XVNMADDSP,
++  VSX_BUILTIN_XVNMSUBDP,
++  VSX_BUILTIN_XVNMSUBSP,
 +  VSX_BUILTIN_XVRDPI,
 +  VSX_BUILTIN_XVRDPIC,
 +  VSX_BUILTIN_XVRDPIM,
@@ -7243,7 +9169,17 @@ testsuite/
 +  VSX_BUILTIN_XXSPLTW,
 +  VSX_BUILTIN_XXSWAPD,
 +
-+  /* Combine VSX/Altivec builtins.  */
++  /* VSX overloaded builtins, add the overloaded functions not present in
++     Altivec.  */
++  VSX_BUILTIN_VEC_MUL,
++  VSX_BUILTIN_OVERLOADED_FIRST = VSX_BUILTIN_VEC_MUL,
++  VSX_BUILTIN_VEC_MSUB,
++  VSX_BUILTIN_VEC_NMADD,
++  VSX_BUITLIN_VEC_NMSUB,
++  VSX_BUILTIN_VEC_DIV,
++  VSX_BUILTIN_OVERLOADED_LAST = VSX_BUILTIN_VEC_DIV,
++
++  /* Combined VSX/Altivec builtins.  */
 +  VECTOR_BUILTIN_FLOAT_V4SI_V4SF,
 +  VECTOR_BUILTIN_UNSFLOAT_V4SI_V4SF,
 +  VECTOR_BUILTIN_FIX_V4SF_V4SI,
@@ -7252,7 +9188,7 @@ testsuite/
    RS6000_BUILTIN_COUNT
  };
  
-@@ -3123,6 +3407,8 @@ enum rs6000_builtin_type_index
+@@ -3123,6 +3395,8 @@ enum rs6000_builtin_type_index
    RS6000_BTI_V16QI,
    RS6000_BTI_V2SI,
    RS6000_BTI_V2SF,
@@ -7261,7 +9197,7 @@ testsuite/
    RS6000_BTI_V4HI,
    RS6000_BTI_V4SI,
    RS6000_BTI_V4SF,
-@@ -3146,7 +3432,10 @@ enum rs6000_builtin_type_index
+@@ -3146,7 +3420,10 @@ enum rs6000_builtin_type_index
    RS6000_BTI_UINTHI,		 /* unsigned_intHI_type_node */
    RS6000_BTI_INTSI,		 /* intSI_type_node */
    RS6000_BTI_UINTSI,		 /* unsigned_intSI_type_node */
@@ -7272,7 +9208,7 @@ testsuite/
    RS6000_BTI_void,	         /* void_type_node */
    RS6000_BTI_MAX
  };
-@@ -3157,6 +3446,8 @@ enum rs6000_builtin_type_index
+@@ -3157,6 +3434,8 @@ enum rs6000_builtin_type_index
  #define opaque_p_V2SI_type_node       (rs6000_builtin_types[RS6000_BTI_opaque_p_V2SI])
  #define opaque_V4SI_type_node         (rs6000_builtin_types[RS6000_BTI_opaque_V4SI])
  #define V16QI_type_node               (rs6000_builtin_types[RS6000_BTI_V16QI])
@@ -7281,7 +9217,7 @@ testsuite/
  #define V2SI_type_node                (rs6000_builtin_types[RS6000_BTI_V2SI])
  #define V2SF_type_node                (rs6000_builtin_types[RS6000_BTI_V2SF])
  #define V4HI_type_node                (rs6000_builtin_types[RS6000_BTI_V4HI])
-@@ -3183,7 +3474,10 @@ enum rs6000_builtin_type_index
+@@ -3183,7 +3462,10 @@ enum rs6000_builtin_type_index
  #define uintHI_type_internal_node	 (rs6000_builtin_types[RS6000_BTI_UINTHI])
  #define intSI_type_internal_node	 (rs6000_builtin_types[RS6000_BTI_INTSI])
  #define uintSI_type_internal_node	 (rs6000_builtin_types[RS6000_BTI_UINTSI])
@@ -7292,8 +9228,8 @@ testsuite/
  #define void_type_internal_node		 (rs6000_builtin_types[RS6000_BTI_void])
  
  extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
---- gcc/config/rs6000/altivec.md	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/altivec.md	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/altivec.md	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/altivec.md	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -21,18 +21,7 @@
  
  (define_constants
@@ -7398,8 +9334,9 @@ testsuite/
      }
  }
 -  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
--
--(define_split
++  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
+ 
+ (define_split
 -  [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
 -        (match_operand:V4SI 1 "input_operand" ""))]
 -  "TARGET_ALTIVEC && reload_completed
@@ -7416,9 +9353,8 @@ testsuite/
 -   && gpr_or_gpr_p (operands[0], operands[1])"
 -  [(pc)]
 -{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
-+  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,vecsimple,*")])
- 
- (define_split
+-
+-(define_split
 -  [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
 -        (match_operand:V16QI 1 "input_operand" ""))]
 -  "TARGET_ALTIVEC && reload_completed
@@ -8088,22 +10024,7 @@ testsuite/
  (define_insn "altivec_vsldoi_<mode>"
    [(set (match_operand:V 0 "register_operand" "=v")
          (unspec:V [(match_operand:V 1 "register_operand" "v")
-@@ -1878,6 +1570,14 @@ (define_expand "build_vector_mask_for_lo
-   gcc_assert (GET_CODE (operands[1]) == MEM);
- 
-   addr = XEXP (operands[1], 0);
-+  if (VECTOR_MEM_VSX_P (GET_MODE (operands[1])))
-+    {
-+      /* VSX doesn't and off the bottom address bits, and memory
-+	 operations are aligned to the natural data type.  */
-+      emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
-+      DONE;
-+    }
-+
-   temp = gen_reg_rtx (GET_MODE (addr));
-   emit_insn (gen_rtx_SET (VOIDmode, temp, 
- 			  gen_rtx_NEG (GET_MODE (addr), addr)));
-@@ -1959,95 +1659,6 @@ (define_insn "*altivec_stvesfx"
+@@ -1959,95 +1651,6 @@ (define_insn "*altivec_stvesfx"
    "stvewx %1,%y0"
    [(set_attr "type" "vecstore")])
  
@@ -8199,7 +10120,7 @@ testsuite/
  ;; Generate
  ;;    vspltis? SCRATCH0,0
  ;;    vsubu?m SCRATCH2,SCRATCH1,%1
-@@ -2069,7 +1680,7 @@ (define_expand "abs<mode>2"
+@@ -2069,7 +1672,7 @@ (define_expand "abs<mode>2"
  ;;    vspltisw SCRATCH1,-1
  ;;    vslw SCRATCH2,SCRATCH1,SCRATCH1
  ;;    vandc %0,%1,SCRATCH2
@@ -8208,7 +10129,7 @@ testsuite/
    [(set (match_dup 2)
  	(vec_duplicate:V4SI (const_int -1)))
     (set (match_dup 3)
-@@ -2132,7 +1743,7 @@ (define_expand "vec_shl_<mode>"
+@@ -2132,7 +1735,7 @@ (define_expand "vec_shl_<mode>"
    DONE;
  }")
  
@@ -8217,7 +10138,7 @@ testsuite/
  ;; amounts that can be expressed as byte shifts (divisible by 8).
  ;; General shift amounts can be supported using vsro + vsr. We're
  ;; not expecting to see these yet (the vectorizer currently
-@@ -2665,7 +2276,7 @@ (define_expand "vec_pack_trunc_v4si"
+@@ -2665,7 +2268,7 @@ (define_expand "vec_pack_trunc_v4si"
    DONE;
  }")
  
@@ -8226,7 +10147,7 @@ testsuite/
    [(use (match_operand:V4SF 0 "register_operand" ""))
     (use (match_operand:V4SF 1 "register_operand" ""))]
    "TARGET_ALTIVEC"
-@@ -2994,29 +2605,6 @@ (define_expand "vec_extract_oddv16qi"
+@@ -2994,29 +2597,6 @@ (define_expand "vec_extract_oddv16qi"
    emit_insn (gen_vpkuhum_nomode (operands[0], operands[1], operands[2]));
    DONE;
  }")
@@ -8256,8 +10177,8 @@ testsuite/
  
  (define_expand "vec_interleave_high<mode>"
   [(set (match_operand:VI 0 "register_operand" "")
---- gcc/config/rs6000/aix61.h	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/aix61.h	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/aix61.h	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/aix61.h	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -57,20 +57,24 @@ do {									\
  #undef ASM_SPEC
  #define ASM_SPEC "-u %{maix64:-a64 %{!mcpu*:-mppc64}} %(asm_cpu)"
@@ -8285,9 +10206,9 @@ testsuite/
  %{mcpu=powerpc: -mppc} \
  %{mcpu=rs64a: -mppc} \
  %{mcpu=603: -m603} \
---- gcc/config/rs6000/rs6000.md	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/rs6000.md	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -138,7 +138,7 @@ (define_attr "length" ""
+--- gcc/config/rs6000/rs6000.md	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/rs6000.md	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -138,7 +138,7 @@
  ;; Processor type -- this attribute must exactly match the processor_type
  ;; enumeration in rs6000.h.
  
@@ -8296,7 +10217,7 @@ testsuite/
    (const (symbol_ref "rs6000_cpu_attr")))
  
  
-@@ -167,6 +167,7 @@ (define_attr "cell_micro" "not,condition
+@@ -167,6 +167,7 @@
  (include "power4.md")
  (include "power5.md")
  (include "power6.md")
@@ -8304,17 +10225,27 @@ testsuite/
  (include "cell.md")
  (include "xfpu.md")
  
-@@ -218,6 +219,9 @@ (define_mode_attr wd [(QI "b") (HI "h") 
+@@ -218,6 +219,19 @@
  ; DImode bits
  (define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
  
 +;; ISEL/ISEL64 target selection
 +(define_mode_attr sel [(SI "") (DI "64")])
 +
++;; Suffix for reload patterns
++(define_mode_attr ptrsize [(SI "32bit")
++			   (DI "64bit")])
++
++(define_mode_attr tptrsize [(SI "TARGET_32BIT")
++			    (DI "TARGET_64BIT")])
++
++(define_mode_attr mptrsize [(SI "si")
++			    (DI "di")])
++
  
  ;; Start with fixed-point load and store insns.  Here we put only the more
  ;; complex forms.  Basic data transfer is done later.
-@@ -520,7 +524,7 @@ (define_insn ""
+@@ -520,7 +534,7 @@
    "@
     {andil.|andi.} %2,%1,0xff
     #"
@@ -8323,7 +10254,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -546,7 +550,7 @@ (define_insn ""
+@@ -546,7 +560,7 @@
    "@
     {andil.|andi.} %0,%1,0xff
     #"
@@ -8332,7 +10263,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -687,7 +691,7 @@ (define_insn ""
+@@ -687,7 +701,7 @@
    "@
     {andil.|andi.} %2,%1,0xff
     #"
@@ -8341,7 +10272,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -713,7 +717,7 @@ (define_insn ""
+@@ -713,7 +727,7 @@
    "@
     {andil.|andi.} %0,%1,0xff
     #"
@@ -8350,7 +10281,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -856,7 +860,7 @@ (define_insn ""
+@@ -856,7 +870,7 @@
    "@
     {andil.|andi.} %2,%1,0xffff
     #"
@@ -8359,7 +10290,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -882,7 +886,7 @@ (define_insn ""
+@@ -882,7 +896,7 @@
    "@
     {andil.|andi.} %0,%1,0xffff
     #"
@@ -8368,7 +10299,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -1670,7 +1674,7 @@ (define_insn ""
+@@ -1670,7 +1684,7 @@
    "@
     nor. %2,%1,%1
     #"
@@ -8377,7 +10308,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -1696,7 +1700,7 @@ (define_insn ""
+@@ -1696,7 +1710,7 @@
    "@
     nor. %0,%1,%1
     #"
@@ -8386,7 +10317,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -2221,10 +2225,22 @@ (define_insn "popcntb<mode>2"
+@@ -2221,10 +2235,22 @@
    "TARGET_POPCNTB"
    "popcntb %0,%1")
  
@@ -8410,7 +10341,7 @@ testsuite/
    {
      rs6000_emit_popcount (operands[0], operands[1]);
      DONE;
-@@ -2852,7 +2868,7 @@ (define_insn "andsi3_mc"
+@@ -2852,7 +2878,7 @@
     {rlinm|rlwinm} %0,%1,0,%m2,%M2
     {andil.|andi.} %0,%1,%b2
     {andiu.|andis.} %0,%1,%u2"
@@ -8419,7 +10350,7 @@ testsuite/
  
  (define_insn "andsi3_nomc"
    [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
-@@ -2895,7 +2911,8 @@ (define_insn "*andsi3_internal2_mc"
+@@ -2895,7 +2921,8 @@
     #
     #
     #"
@@ -8429,7 +10360,7 @@ testsuite/
     (set_attr "length" "4,4,4,4,8,8,8,8")])
  
  (define_insn "*andsi3_internal3_mc"
-@@ -2915,7 +2932,8 @@ (define_insn "*andsi3_internal3_mc"
+@@ -2915,7 +2942,8 @@
     #
     #
     #"
@@ -8439,7 +10370,7 @@ testsuite/
     (set_attr "length" "8,4,4,4,8,8,8,8")])
  
  (define_split
-@@ -2974,7 +2992,8 @@ (define_insn "*andsi3_internal4"
+@@ -2974,7 +3002,8 @@
     #
     #
     #"
@@ -8449,17 +10380,17 @@ testsuite/
     (set_attr "length" "4,4,4,4,8,8,8,8")])
  
  (define_insn "*andsi3_internal5_mc"
-@@ -2996,7 +3015,8 @@ (define_insn "*andsi3_internal5_mc"
+@@ -2996,7 +3025,8 @@
     #
     #
     #"
 -  [(set_attr "type" "compare,compare,compare,delayed_compare,compare,compare,compare,compare")
 +  [(set_attr "type" "compare,fast_compare,fast_compare,delayed_compare,compare,\
-+		    compare,compare,compare")
++		     compare,compare,compare")
     (set_attr "length" "8,4,4,4,8,8,8,8")])
  
  (define_split
-@@ -3127,7 +3147,7 @@ (define_insn "*boolsi3_internal2"
+@@ -3127,7 +3157,7 @@
    "@
     %q4. %3,%1,%2
     #"
@@ -8468,7 +10399,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -3156,7 +3176,7 @@ (define_insn "*boolsi3_internal3"
+@@ -3156,7 +3186,7 @@
    "@
     %q4. %0,%1,%2
     #"
@@ -8477,7 +10408,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -3281,7 +3301,7 @@ (define_insn "*boolccsi3_internal2"
+@@ -3281,7 +3311,7 @@
    "@
     %q4. %3,%1,%2
     #"
@@ -8486,7 +10417,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -3310,7 +3330,7 @@ (define_insn "*boolccsi3_internal3"
+@@ -3310,7 +3340,7 @@
    "@
     %q4. %0,%1,%2
     #"
@@ -8495,7 +10426,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -5303,7 +5323,7 @@ (define_insn "fres"
+@@ -5303,7 +5333,7 @@
    "fres %0,%1"
    [(set_attr "type" "fp")])
  
@@ -8504,7 +10435,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
  			  (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5314,7 +5334,7 @@ (define_insn ""
+@@ -5314,7 +5344,7 @@
    [(set_attr "type" "fp")
     (set_attr "fp_type" "fp_maddsub_s")])
  
@@ -8513,7 +10444,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
  			  (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5323,7 +5343,7 @@ (define_insn ""
+@@ -5323,7 +5353,7 @@
    "{fma|fmadd} %0,%1,%2,%3"
    [(set_attr "type" "dmul")])
  
@@ -8522,7 +10453,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
  			   (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5334,7 +5354,7 @@ (define_insn ""
+@@ -5334,7 +5364,7 @@
    [(set_attr "type" "fp")
     (set_attr "fp_type" "fp_maddsub_s")])
  
@@ -8531,7 +10462,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
  			   (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5343,7 +5363,7 @@ (define_insn ""
+@@ -5343,7 +5373,7 @@
    "{fms|fmsub} %0,%1,%2,%3"
    [(set_attr "type" "dmul")])
  
@@ -8540,7 +10471,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
  				  (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5354,7 +5374,7 @@ (define_insn ""
+@@ -5354,7 +5384,7 @@
    [(set_attr "type" "fp")
     (set_attr "fp_type" "fp_maddsub_s")])
  
@@ -8549,7 +10480,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
  			   (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5365,7 +5385,7 @@ (define_insn ""
+@@ -5365,7 +5395,7 @@
    [(set_attr "type" "fp")
     (set_attr "fp_type" "fp_maddsub_s")])
  
@@ -8558,7 +10489,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(neg:SF (plus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
  				  (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5374,7 +5394,7 @@ (define_insn ""
+@@ -5374,7 +5404,7 @@
    "{fnma|fnmadd} %0,%1,%2,%3"
    [(set_attr "type" "dmul")])
  
@@ -8567,7 +10498,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(minus:SF (mult:SF (neg:SF (match_operand:SF 1 "gpc_reg_operand" "f"))
  			   (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5384,7 +5404,7 @@ (define_insn ""
+@@ -5384,7 +5414,7 @@
    "{fnma|fnmadd} %0,%1,%2,%3"
    [(set_attr "type" "dmul")])
  
@@ -8576,7 +10507,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
  				   (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5395,7 +5415,7 @@ (define_insn ""
+@@ -5395,7 +5425,7 @@
    [(set_attr "type" "fp")
     (set_attr "fp_type" "fp_maddsub_s")])
  
@@ -8585,7 +10516,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
  		  (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
-@@ -5406,7 +5426,7 @@ (define_insn ""
+@@ -5406,7 +5436,7 @@
    [(set_attr "type" "fp")
     (set_attr "fp_type" "fp_maddsub_s")])
  
@@ -8594,7 +10525,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(neg:SF (minus:SF (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
  				   (match_operand:SF 2 "gpc_reg_operand" "f"))
-@@ -5415,7 +5435,7 @@ (define_insn ""
+@@ -5415,7 +5445,7 @@
    "{fnms|fnmsub} %0,%1,%2,%3"
    [(set_attr "type" "dmul")])
  
@@ -8603,7 +10534,7 @@ testsuite/
    [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
  	(minus:SF (match_operand:SF 3 "gpc_reg_operand" "f")
  		  (mult:SF (match_operand:SF 1 "gpc_reg_operand" "%f")
-@@ -5496,9 +5516,18 @@ (define_expand "copysigndf3"
+@@ -5496,9 +5526,18 @@
  	                     (match_dup 5))
  			 (match_dup 3)
  			 (match_dup 4)))]
@@ -8624,7 +10555,7 @@ testsuite/
       operands[3] = gen_reg_rtx (DFmode);
       operands[4] = gen_reg_rtx (DFmode);
       operands[5] = CONST0_RTX (DFmode);
-@@ -5542,12 +5571,12 @@ (define_split
+@@ -5542,12 +5581,12 @@
    DONE;
  }")
  
@@ -8643,7 +10574,7 @@ testsuite/
    "
  {
    if (rs6000_emit_cmove (operands[0], operands[1], operands[2], operands[3]))
-@@ -5564,28 +5593,28 @@ (define_expand "movsicc"
+@@ -5564,28 +5603,28 @@
  ;; leave out the mode in operand 4 and use one pattern, but reload can
  ;; change the mode underneath our feet and then gets confused trying
  ;; to reload the value.
@@ -8684,7 +10615,7 @@ testsuite/
    "*
  { return output_isel (operands); }"
    [(set_attr "length" "4")])
-@@ -5633,7 +5662,8 @@ (define_expand "negdf2"
+@@ -5633,7 +5672,8 @@
  (define_insn "*negdf2_fpr"
    [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
  	(neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
@@ -8694,7 +10625,7 @@ testsuite/
    "fneg %0,%1"
    [(set_attr "type" "fp")])
  
-@@ -5646,14 +5676,16 @@ (define_expand "absdf2"
+@@ -5646,14 +5686,16 @@
  (define_insn "*absdf2_fpr"
    [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
  	(abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
@@ -8713,7 +10644,7 @@ testsuite/
    "fnabs %0,%1"
    [(set_attr "type" "fp")])
  
-@@ -5668,7 +5700,8 @@ (define_insn "*adddf3_fpr"
+@@ -5668,7 +5710,8 @@
    [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
  	(plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
  		 (match_operand:DF 2 "gpc_reg_operand" "f")))]
@@ -8723,7 +10654,7 @@ testsuite/
    "{fa|fadd} %0,%1,%2"
    [(set_attr "type" "fp")
     (set_attr "fp_type" "fp_addsub_d")])
-@@ -5684,7 +5717,8 @@ (define_insn "*subdf3_fpr"
+@@ -5684,7 +5727,8 @@
    [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
  	(minus:DF (match_operand:DF 1 "gpc_reg_operand" "f")
  		  (match_operand:DF 2 "gpc_reg_operand" "f")))]
@@ -8733,7 +10664,7 @@ testsuite/
    "{fs|fsub} %0,%1,%2"
    [(set_attr "type" "fp")
     (set_attr "fp_type" "fp_addsub_d")])
-@@ -5700,7 +5734,8 @@ (define_insn "*muldf3_fpr"
+@@ -5700,7 +5744,8 @@
    [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
  	(mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
  		 (match_operand:DF 2 "gpc_reg_operand" "f")))]
@@ -8743,7 +10674,7 @@ testsuite/
    "{fm|fmul} %0,%1,%2"
    [(set_attr "type" "dmul")
     (set_attr "fp_type" "fp_mul_d")])
-@@ -5718,7 +5753,8 @@ (define_insn "*divdf3_fpr"
+@@ -5718,7 +5763,8 @@
    [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
  	(div:DF (match_operand:DF 1 "gpc_reg_operand" "f")
  		(match_operand:DF 2 "gpc_reg_operand" "f")))]
@@ -8753,7 +10684,7 @@ testsuite/
    "{fd|fdiv} %0,%1,%2"
    [(set_attr "type" "ddiv")])
  
-@@ -5734,73 +5770,81 @@ (define_expand "recipdf3"
+@@ -5734,73 +5780,81 @@
     DONE;
  })
  
@@ -8849,7 +10780,7 @@ testsuite/
    "{fnms|fnmsub} %0,%1,%2,%3"
    [(set_attr "type" "dmul")
     (set_attr "fp_type" "fp_maddsub_d")])
-@@ -5809,7 +5853,8 @@ (define_insn "sqrtdf2"
+@@ -5809,7 +5863,8 @@
    [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
  	(sqrt:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
    "(TARGET_PPC_GPOPT || TARGET_POWER2) && TARGET_HARD_FLOAT && TARGET_FPRS 
@@ -8859,7 +10790,7 @@ testsuite/
    "fsqrt %0,%1"
    [(set_attr "type" "dsqrt")])
  
-@@ -5898,6 +5943,18 @@ (define_expand "fix_truncsfsi2"
+@@ -5898,6 +5953,18 @@
   "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT"
   "")
  
@@ -8878,7 +10809,7 @@ testsuite/
  ; For each of these conversions, there is a define_expand, a define_insn
  ; with a '#' template, and a define_split (with C code).  The idea is
  ; to allow constant folding with the template of the define_insn,
-@@ -6139,10 +6196,17 @@ (define_insn "fctiwz"
+@@ -6139,24 +6206,38 @@
    "{fcirz|fctiwz} %0,%1"
    [(set_attr "type" "fp")])
  
@@ -8897,7 +10828,11 @@ testsuite/
    "friz %0,%1"
    [(set_attr "type" "fp")])
  
-@@ -6153,10 +6217,17 @@ (define_insn "btruncsf2"
+ (define_insn "btruncsf2"
+   [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ 	(unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
+-  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT "
++  "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT"
    "friz %0,%1"
    [(set_attr "type" "fp")])
  
@@ -8917,7 +10852,7 @@ testsuite/
    "frip %0,%1"
    [(set_attr "type" "fp")])
  
-@@ -6167,10 +6238,17 @@ (define_insn "ceilsf2"
+@@ -6167,10 +6248,17 @@
    "frip %0,%1"
    [(set_attr "type" "fp")])
  
@@ -8937,7 +10872,7 @@ testsuite/
    "frim %0,%1"
    [(set_attr "type" "fp")])
  
-@@ -6181,6 +6259,7 @@ (define_insn "floorsf2"
+@@ -6181,6 +6269,7 @@
    "frim %0,%1"
    [(set_attr "type" "fp")])
  
@@ -8945,7 +10880,7 @@ testsuite/
  (define_insn "rounddf2"
    [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
  	(unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
-@@ -6195,6 +6274,12 @@ (define_insn "roundsf2"
+@@ -6195,6 +6284,12 @@
    "frin %0,%1"
    [(set_attr "type" "fp")])
  
@@ -8958,7 +10893,7 @@ testsuite/
  ; An UNSPEC is used so we don't have to support SImode in FP registers.
  (define_insn "stfiwx"
    [(set (match_operand:SI 0 "memory_operand" "=Z")
-@@ -6210,17 +6295,40 @@ (define_expand "floatsisf2"
+@@ -6210,17 +6305,40 @@
    "TARGET_HARD_FLOAT && !TARGET_FPRS"
    "")
  
@@ -9003,7 +10938,7 @@ testsuite/
    "fctidz %0,%1"
    [(set_attr "type" "fp")])
  
-@@ -7609,7 +7717,7 @@ (define_insn "anddi3_mc"
+@@ -7609,7 +7727,7 @@
     andi. %0,%1,%b2
     andis. %0,%1,%u2
     #"
@@ -9012,7 +10947,7 @@ testsuite/
     (set_attr "length" "4,4,4,4,4,8")])
  
  (define_insn "anddi3_nomc"
-@@ -7667,7 +7775,9 @@ (define_insn "*anddi3_internal2_mc"
+@@ -7667,7 +7785,9 @@
     #
     #
     #"
@@ -9023,7 +10958,7 @@ testsuite/
     (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
  
  (define_split
-@@ -7718,7 +7828,9 @@ (define_insn "*anddi3_internal3_mc"
+@@ -7718,7 +7838,9 @@
     #
     #
     #"
@@ -9034,7 +10969,7 @@ testsuite/
     (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
  
  (define_split
-@@ -7858,7 +7970,7 @@ (define_insn "*booldi3_internal2"
+@@ -7858,7 +7980,7 @@
    "@
     %q4. %3,%1,%2
     #"
@@ -9043,7 +10978,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -7887,7 +7999,7 @@ (define_insn "*booldi3_internal3"
+@@ -7887,7 +8009,7 @@
    "@
     %q4. %0,%1,%2
     #"
@@ -9052,7 +10987,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -7958,7 +8070,7 @@ (define_insn "*boolcdi3_internal2"
+@@ -7958,7 +8080,7 @@
    "@
     %q4. %3,%2,%1
     #"
@@ -9061,7 +10996,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -7987,7 +8099,7 @@ (define_insn "*boolcdi3_internal3"
+@@ -7987,7 +8109,7 @@
    "@
     %q4. %0,%2,%1
     #"
@@ -9070,7 +11005,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -8024,7 +8136,7 @@ (define_insn "*boolccdi3_internal2"
+@@ -8024,7 +8146,7 @@
    "@
     %q4. %3,%1,%2
     #"
@@ -9079,7 +11014,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -8053,7 +8165,7 @@ (define_insn "*boolccdi3_internal3"
+@@ -8053,7 +8175,7 @@
    "@
     %q4. %0,%1,%2
     #"
@@ -9088,7 +11023,7 @@ testsuite/
     (set_attr "length" "4,8")])
  
  (define_split
-@@ -8070,6 +8182,51 @@ (define_split
+@@ -8070,6 +8192,51 @@
  	(compare:CC (match_dup 0)
  		    (const_int 0)))]
    "")
@@ -9140,7 +11075,7 @@ testsuite/
  
  ;; Now define ways of moving data around.
  
-@@ -8473,8 +8630,8 @@ (define_split
+@@ -8473,8 +8640,8 @@
  ;; The "??" is a kludge until we can figure out a more reasonable way
  ;; of handling these non-offsettable values.
  (define_insn "*movdf_hardfloat32"
@@ -9151,14 +11086,14 @@ testsuite/
    "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
     && (gpc_reg_operand (operands[0], DFmode)
         || gpc_reg_operand (operands[1], DFmode))"
-@@ -8553,19 +8710,30 @@ (define_insn "*movdf_hardfloat32"
+@@ -8553,19 +8720,30 @@
  	  return \"\";
  	}
      case 3:
 -      return \"fmr %0,%1\";
      case 4:
 -      return \"lfd%U1%X1 %0,%1\";
-+      return \"xscpsgndp %x0,%x1,%x1\";
++      return \"xxlor %x0,%x1,%x1\";
      case 5:
 -      return \"stfd%U0%X0 %1,%0\";
      case 6:
@@ -9187,7 +11122,7 @@ testsuite/
  
  (define_insn "*movdf_softfloat32"
    [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r")
-@@ -8613,19 +8781,26 @@ (define_insn "*movdf_softfloat32"
+@@ -8613,19 +8791,26 @@
  ; ld/std require word-aligned displacements -> 'Y' constraint.
  ; List Y->r and r->Y before r->r for reload.
  (define_insn "*movdf_hardfloat64_mfpgpr"
@@ -9204,8 +11139,8 @@ testsuite/
     std%U0%X0 %1,%0
     ld%U1%X1 %0,%1
     mr %0,%1
-+   xscpsgndp %x0,%x1,%x1
-+   xscpsgndp %x0,%x1,%x1
++   xxlor %x0,%x1,%x1
++   xxlor %x0,%x1,%x1
 +   lxsd%U1x %x0,%y1
 +   lxsd%U1x %x0,%y1
 +   stxsd%U0x %x1,%y0
@@ -9217,7 +11152,7 @@ testsuite/
     mt%0 %1
     mf%1 %0
     {cror 0,0,0|nop}
-@@ -8634,33 +8809,40 @@ (define_insn "*movdf_hardfloat64_mfpgpr"
+@@ -8634,33 +8819,40 @@
     #
     mftgpr %0,%1
     mffgpr %0,%1"
@@ -9242,8 +11177,8 @@ testsuite/
     std%U0%X0 %1,%0
     ld%U1%X1 %0,%1
     mr %0,%1
-+   xscpsgndp %x0,%x1,%x1
-+   xscpsgndp %x0,%x1,%x1
++   xxlor %x0,%x1,%x1
++   xxlor %x0,%x1,%x1
 +   lxsd%U1x %x0,%y1
 +   lxsd%U1x %x0,%y1
 +   stxsd%U0x %x1,%y0
@@ -9265,7 +11200,7 @@ testsuite/
  
  (define_insn "*movdf_softfloat64"
    [(set (match_operand:DF 0 "nonimmediate_operand" "=r,Y,r,cl,r,r,r,r,*h")
-@@ -9237,15 +9419,16 @@ (define_insn "*movti_string"
+@@ -9237,15 +9429,16 @@
  (define_insn "*movti_ppc64"
    [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o<>,r")
  	(match_operand:TI 1 "input_operand" "r,r,m"))]
@@ -9285,7 +11220,7 @@ testsuite/
    [(set (match_dup 2) (match_dup 4))
     (set (match_dup 3) (match_dup 5))]
    "
-@@ -9271,7 +9454,7 @@ (define_split
+@@ -9271,7 +9464,7 @@
  (define_split
    [(set (match_operand:TI 0 "nonimmediate_operand" "")
          (match_operand:TI 1 "input_operand" ""))]
@@ -9294,7 +11229,7 @@ testsuite/
     && gpr_or_gpr_p (operands[0], operands[1])"
    [(pc)]
  { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
-@@ -14891,6 +15074,8 @@ (define_insn "prefetch"
+@@ -14891,6 +15084,8 @@
  
  
  (include "sync.md")
@@ -9303,8 +11238,8 @@ testsuite/
  (include "altivec.md")
  (include "spe.md")
  (include "dfp.md")
---- gcc/config/rs6000/e500.h	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/e500.h	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/e500.h	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/e500.h	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -37,6 +37,8 @@
        {									\
  	if (TARGET_ALTIVEC)						\
@@ -9314,8 +11249,8 @@ testsuite/
  	if (TARGET_64BIT)						\
  	  error ("64-bit E500 not supported");				\
  	if (TARGET_HARD_FLOAT && TARGET_FPRS)				\
---- gcc/config/rs6000/driver-rs6000.c	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/driver-rs6000.c	(.../branches/ibm/power7-meissner)	(revision 144730)
+--- gcc/config/rs6000/driver-rs6000.c	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/driver-rs6000.c	(.../branches/ibm/power7-meissner)	(revision 146027)
 @@ -343,11 +343,115 @@ detect_processor_aix (void)
  #endif /* _AIX */
  
@@ -9496,9 +11431,9 @@ testsuite/
    return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
  }
  
---- gcc/config/rs6000/sysv4.h	(.../trunk)	(revision 144557)
-+++ gcc/config/rs6000/sysv4.h	(.../branches/ibm/power7-meissner)	(revision 144730)
-@@ -119,9 +119,9 @@ do {									\
+--- gcc/config/rs6000/sysv4.h	(.../trunk)	(revision 145777)
++++ gcc/config/rs6000/sysv4.h	(.../branches/ibm/power7-meissner)	(revision 146027)
+@@ -120,9 +120,9 @@ do {									\
    else if (!strcmp (rs6000_abi_name, "i960-old"))			\
      {									\
        rs6000_current_abi = ABI_V4;					\
diff --git a/gcc44-rh330771.patch b/gcc44-rh330771.patch
index f52b919..f7c365d 100644
--- a/gcc44-rh330771.patch
+++ b/gcc44-rh330771.patch
@@ -3,20 +3,20 @@
 	* Makefile.am (libgcj_tools_la_LIBADD): Add.
 	* Makefile.in: Regenerated.
 
---- libjava/Makefile.am.jj	2007-03-17 09:20:30.000000000 +0100
-+++ libjava/Makefile.am	2007-10-16 15:45:14.000000000 +0200
-@@ -277,6 +277,8 @@ EXTRA_libgcj_la_SOURCES = java/lang/Obje
- 
- libgcj_tools_la_SOURCES = classpath/tools/tools.zip
- libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS) -findirect-dispatch -fno-indirect-classes  -fsource-filename=$(here)/classpath/tools/all-classes.lst
+--- libjava/Makefile.am.jj	2009-05-06 08:14:50.000000000 +0200
++++ libjava/Makefile.am	2009-05-06 10:26:43.000000000 +0200
+@@ -314,6 +314,8 @@ libgcj_tools_la_SOURCES = classpath/tool
+ libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS) -findirect-dispatch \
+  -fno-bootstrap-classes -fno-indirect-classes \
+  -fsource-filename=$(here)/classpath/tools/all-classes.lst
 +## See jv_convert_LDADD.
 +libgcj_tools_la_LIBADD = -L$(here)/.libs libgcj.la
  libgcj_tools_la_LDFLAGS = -rpath $(toolexeclibdir) \
   -version-info `grep -v '^\#' $(srcdir)/libtool-version` \
   $(LIBGCJ_LD_SYMBOLIC_FUNCTIONS)
---- libjava/Makefile.in.jj	2007-07-04 21:11:11.000000000 +0200
-+++ libjava/Makefile.in	2007-10-16 15:56:07.000000000 +0200
-@@ -153,7 +153,6 @@ am__objects_1 = gnu/gcj/xlib/lib_gnu_awt
+--- libjava/Makefile.in.jj	2009-05-06 08:14:49.000000000 +0200
++++ libjava/Makefile.in	2009-05-06 10:27:18.000000000 +0200
+@@ -160,7 +160,6 @@ am__objects_1 = gnu/gcj/xlib/lib_gnu_awt
  am_lib_gnu_awt_xlib_la_OBJECTS = $(am__objects_1)
  lib_gnu_awt_xlib_la_OBJECTS = $(am_lib_gnu_awt_xlib_la_OBJECTS)
  @XLIB_AWT_TRUE at am_lib_gnu_awt_xlib_la_rpath = -rpath $(toolexeclibdir)
@@ -24,10 +24,10 @@
  am_libgcj_tools_la_OBJECTS = classpath/tools/libgcj_tools_la-tools.lo
  libgcj_tools_la_OBJECTS = $(am_libgcj_tools_la_OBJECTS)
  @INTERPRETER_TRUE at am__DEPENDENCIES_1 = gnu/classpath/jdwp.lo \
-@@ -941,6 +940,7 @@ libgcj_la_LINK = $(LIBLINK)
- EXTRA_libgcj_la_SOURCES = java/lang/Object.java
- libgcj_tools_la_SOURCES = classpath/tools/tools.zip
- libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS) -findirect-dispatch -fno-indirect-classes  -fsource-filename=$(here)/classpath/tools/all-classes.lst
+@@ -1041,6 +1040,7 @@ libgcj_tools_la_GCJFLAGS = $(AM_GCJFLAGS
+  -fno-bootstrap-classes -fno-indirect-classes \
+  -fsource-filename=$(here)/classpath/tools/all-classes.lst
+ 
 +libgcj_tools_la_LIBADD = -L$(here)/.libs libgcj.la
  libgcj_tools_la_LDFLAGS = -rpath $(toolexeclibdir) \
   -version-info `grep -v '^\#' $(srcdir)/libtool-version` \
diff --git a/gcc44-rh503816-1.patch b/gcc44-rh503816-1.patch
new file mode 100644
index 0000000..7516f85
--- /dev/null
+++ b/gcc44-rh503816-1.patch
@@ -0,0 +1,827 @@
+2009-06-21  Jakub Jelinek  <jakub at redhat.com>
+
+	* var-tracking.c (struct shared_hash_def, shared_hash): New types.
+	(dataflow_set): Change vars type from htab_t to shared_hash.
+	(shared_hash_pool, empty_shared_hash): New variables.
+	(vars_clear): Removed.
+	(shared_hash_shared, shared_hash_htab, shared_hash_copy,
+	shared_hash_find_slot_unshare, shared_hash_find_slot,
+	shared_hash_find_slot_noinsert, shared_hash_find): New
+	static inlines.
+	(shared_hash_unshare, shared_hash_destroy): New functions.
+	(unshare_variable): Unshare set->vars if shared, use
+	shared_hash_htab.
+	(vars_copy): Use htab_traverse_noresize instead of htab_traverse.
+	(get_init_value, find_src_set_src, dump_dataflow_set,
+	clobber_variable_part, emit_notes_for_differences): Use
+	shared_hash_htab.
+	(dataflow_set_init): Remove second argument, set vars to
+	empty_shared_hash instead of creating a new htab.
+	(dataflow_set_clear): Call shared_hash_destroy and set vars
+	to empty_shared_hash instead of calling vars_clear.
+	(dataflow_set_copy): Don't call vars_copy, instead just share
+	the src htab with dst.
+	(variable_union): Use shared_hash_*, use initially NO_INSERT
+	lookup if set->vars is shared.  Don't keep slot cleared before
+	calling unshare_variable.  Unshare set->vars if needed.
+	Even ->refcount == 1 vars must be unshared if set->vars is shared
+	and var needs to be modified.
+	(variable_canonicalize): New function.
+	(dataflow_set_union): If dst->vars is empty, just share src->vars
+	with dst->vars and traverse with variable_canonicalize to canonicalize
+	and unshare what is needed.
+	(dataflow_set_different): If old_set and new_set use the same shared
+	htab, they aren't different.  If number of htab elements is different,
+	htabs are different.  Use shared_hash_*.
+	(dataflow_set_destroy): Call shared_hash_destroy instead of
+	htab_delete.
+	(compute_bb_dataflow, emit_notes_in_bb, vt_emit_notes): Don't pass
+	second argument to dataflow_set_init.
+	(vt_initialize): Likewise.  Initialize shared_hash_pool and
+	empty_shared_hash, move bb in/out initialization afterwards.
+	Use variable_htab_free instead of NULL as changed_variables del hook.
+	(variable_was_changed): Change type of second argument to pointer to
+	dataflow_set.  When inserting var into changed_variables, bump
+	refcount.  Unshare set->vars if set is shared htab and slot needs to
+	be cleared.
+	(set_variable_part): Use shared_hash_*, use initially NO_INSERT
+	lookup if set->vars is shared.  Unshare set->vars if needed.
+	Even ->refcount == 1 vars must be unshared if set->vars is shared
+	and var needs to be modified.  Adjust variable_was_changed caller.
+	(delete_variable_part): Use shared_hash_*.  Even ->refcount == 1
+	vars must be unshared if set->vars is shared and var needs to be
+	modified.  Adjust variable_was_changed caller.
+	(emit_note_insn_var_location): Don't pool_free var.
+	(emit_notes_for_differences_1): Initialize empty_var->refcount to 0
+	instead of 1.
+	(vt_finalize): Call htab_delete on empty_shared_hash->htab and
+	free_alloc_pool on shared_hash_pool.
+
+	* hashtab.c (htab_traverse): Don't call htab_expand for
+	nearly empty hashtabs with sizes 7, 13 or 31.
+
+--- gcc/var-tracking.c	(revision 148758)
++++ gcc/var-tracking.c	(revision 148760)
+@@ -182,6 +182,17 @@ typedef struct attrs_def
+   HOST_WIDE_INT offset;
+ } *attrs;
+ 
++/* Structure holding a refcounted hash table.  If refcount > 1,
++   it must be first unshared before modified.  */
++typedef struct shared_hash_def
++{
++  /* Reference count.  */
++  int refcount;
++
++  /* Actual hash table.  */
++  htab_t htab;
++} *shared_hash;
++
+ /* Structure holding the IN or OUT set for a basic block.  */
+ typedef struct dataflow_set_def
+ {
+@@ -192,7 +203,7 @@ typedef struct dataflow_set_def
+   attrs regs[FIRST_PSEUDO_REGISTER];
+ 
+   /* Variable locations.  */
+-  htab_t vars;
++  shared_hash vars;
+ } dataflow_set;
+ 
+ /* The structure (one for each basic block) containing the information
+@@ -280,12 +291,18 @@ static alloc_pool var_pool;
+ /* Alloc pool for struct location_chain_def.  */
+ static alloc_pool loc_chain_pool;
+ 
++/* Alloc pool for struct shared_hash_def.  */
++static alloc_pool shared_hash_pool;
++
+ /* Changed variables, notes will be emitted for them.  */
+ static htab_t changed_variables;
+ 
+ /* Shall notes be emitted?  */
+ static bool emit_notes;
+ 
++/* Empty shared hashtable.  */
++static shared_hash empty_shared_hash;
++
+ /* Local function prototypes.  */
+ static void stack_adjust_offset_pre_post (rtx, HOST_WIDE_INT *,
+ 					  HOST_WIDE_INT *);
+@@ -305,7 +322,6 @@ static void attrs_list_insert (attrs *, 
+ static void attrs_list_copy (attrs *, attrs);
+ static void attrs_list_union (attrs *, attrs);
+ 
+-static void vars_clear (htab_t);
+ static variable unshare_variable (dataflow_set *set, variable var, 
+ 				  enum var_init_status);
+ static int vars_copy_1 (void **, void *);
+@@ -321,11 +337,12 @@ static void var_mem_delete_and_set (data
+ 				    enum var_init_status, rtx);
+ static void var_mem_delete (dataflow_set *, rtx, bool);
+ 
+-static void dataflow_set_init (dataflow_set *, int);
++static void dataflow_set_init (dataflow_set *);
+ static void dataflow_set_clear (dataflow_set *);
+ static void dataflow_set_copy (dataflow_set *, dataflow_set *);
+ static int variable_union_info_cmp_pos (const void *, const void *);
+ static int variable_union (void **, void *);
++static int variable_canonicalize (void **, void *);
+ static void dataflow_set_union (dataflow_set *, dataflow_set *);
+ static bool variable_part_different_p (variable_part *, variable_part *);
+ static bool variable_different_p (variable, variable, bool);
+@@ -352,7 +369,7 @@ static void dump_vars (htab_t);
+ static void dump_dataflow_set (dataflow_set *);
+ static void dump_dataflow_sets (void);
+ 
+-static void variable_was_changed (variable, htab_t);
++static void variable_was_changed (variable, dataflow_set *);
+ static void set_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT, 
+ 			       enum var_init_status, rtx);
+ static void clobber_variable_part (dataflow_set *, rtx, tree, HOST_WIDE_INT, 
+@@ -742,12 +759,107 @@ attrs_list_union (attrs *dstp, attrs src
+     }
+ }
+ 
+-/* Delete all variables from hash table VARS.  */
++/* Shared hashtable support.  */
++
++/* Return true if VARS is shared.  */
++
++static inline bool
++shared_hash_shared (shared_hash vars)
++{
++  return vars->refcount > 1;
++}
++
++/* Return the hash table for VARS.  */
++
++static inline htab_t
++shared_hash_htab (shared_hash vars)
++{
++  return vars->htab;
++}
++
++/* Copy variables into a new hash table.  */
++
++static shared_hash
++shared_hash_unshare (shared_hash vars)
++{
++  shared_hash new_vars = (shared_hash) pool_alloc (shared_hash_pool);
++  gcc_assert (vars->refcount > 1);
++  new_vars->refcount = 1;
++  new_vars->htab
++    = htab_create (htab_elements (vars->htab) + 3, variable_htab_hash,
++		   variable_htab_eq, variable_htab_free);
++  vars_copy (new_vars->htab, vars->htab);
++  vars->refcount--;
++  return new_vars;
++}
++
++/* Increment reference counter on VARS and return it.  */
++
++static inline shared_hash
++shared_hash_copy (shared_hash vars)
++{
++  vars->refcount++;
++  return vars;
++}
++
++/* Decrement reference counter and destroy hash table if not shared
++   anymore.  */
+ 
+ static void
+-vars_clear (htab_t vars)
++shared_hash_destroy (shared_hash vars)
+ {
+-  htab_empty (vars);
++  gcc_assert (vars->refcount > 0);
++  if (--vars->refcount == 0)
++    {
++      htab_delete (vars->htab);
++      pool_free (shared_hash_pool, vars);
++    }
++}
++
++/* Unshare *PVARS if shared and return slot for DECL.  If INS is
++   INSERT, insert it if not already present.  */
++
++static inline void **
++shared_hash_find_slot_unshare (shared_hash *pvars, tree decl,
++			       enum insert_option ins)
++{
++  if (shared_hash_shared (*pvars))
++    *pvars = shared_hash_unshare (*pvars);
++  return htab_find_slot_with_hash (shared_hash_htab (*pvars), decl,
++				   VARIABLE_HASH_VAL (decl), ins);
++}
++
++/* Return slot for DECL, if it is already present in the hash table.
++   If it is not present, insert it only VARS is not shared, otherwise
++   return NULL.  */
++
++static inline void **
++shared_hash_find_slot (shared_hash vars, tree decl)
++{
++  return htab_find_slot_with_hash (shared_hash_htab (vars), decl,
++				   VARIABLE_HASH_VAL (decl),
++				   shared_hash_shared (vars)
++				   ? NO_INSERT : INSERT);
++}
++
++/* Return slot for DECL only if it is already present in the hash table.  */
++
++static inline void **
++shared_hash_find_slot_noinsert (shared_hash vars, tree decl)
++{
++  return htab_find_slot_with_hash (shared_hash_htab (vars), decl,
++				   VARIABLE_HASH_VAL (decl), NO_INSERT);
++}
++
++/* Return variable for DECL or NULL if not already present in the hash
++   table.  */
++
++static inline variable
++shared_hash_find (shared_hash vars, tree decl)
++{
++  return (variable)
++	 htab_find_with_hash (shared_hash_htab (vars), decl,
++			      VARIABLE_HASH_VAL (decl));
+ }
+ 
+ /* Return a copy of a variable VAR and insert it to dataflow set SET.  */
+@@ -801,9 +913,7 @@ unshare_variable (dataflow_set *set, var
+ 	new_var->var_part[i].cur_loc = NULL;
+     }
+ 
+-  slot = htab_find_slot_with_hash (set->vars, new_var->decl,
+-				   VARIABLE_HASH_VAL (new_var->decl),
+-				   INSERT);
++  slot = shared_hash_find_slot_unshare (&set->vars, new_var->decl, INSERT);
+   *slot = new_var;
+   return new_var;
+ }
+@@ -834,8 +944,7 @@ vars_copy_1 (void **slot, void *data)
+ static void
+ vars_copy (htab_t dst, htab_t src)
+ {
+-  vars_clear (dst);
+-  htab_traverse (src, vars_copy_1, dst);
++  htab_traverse_noresize (src, vars_copy_1, dst);
+ }
+ 
+ /* Map a decl to its main debug decl.  */
+@@ -874,7 +983,6 @@ var_reg_set (dataflow_set *set, rtx loc,
+ static int
+ get_init_value (dataflow_set *set, rtx loc, tree decl)
+ {
+-  void **slot;
+   variable var;
+   int i;
+   int ret_val = VAR_INIT_STATUS_UNKNOWN;
+@@ -882,11 +990,9 @@ get_init_value (dataflow_set *set, rtx l
+   if (! flag_var_tracking_uninit)
+     return VAR_INIT_STATUS_INITIALIZED;
+ 
+-  slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
+-				   NO_INSERT);
+-  if (slot)
++  var = shared_hash_find (set->vars, decl);
++  if (var)
+     {
+-      var = * (variable *) slot;
+       for (i = 0; i < var->n_var_parts && ret_val == VAR_INIT_STATUS_UNKNOWN; i++)
+ 	{
+ 	  location_chain nextp;
+@@ -1050,11 +1156,10 @@ var_mem_delete (dataflow_set *set, rtx l
+    VARS_SIZE is the initial size of hash table VARS.  */
+ 
+ static void
+-dataflow_set_init (dataflow_set *set, int vars_size)
++dataflow_set_init (dataflow_set *set)
+ {
+   init_attrs_list_set (set->regs);
+-  set->vars = htab_create (vars_size, variable_htab_hash, variable_htab_eq,
+-			   variable_htab_free);
++  set->vars = shared_hash_copy (empty_shared_hash);
+   set->stack_adjust = 0;
+ }
+ 
+@@ -1068,7 +1173,8 @@ dataflow_set_clear (dataflow_set *set)
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     attrs_list_clear (&set->regs[i]);
+ 
+-  vars_clear (set->vars);
++  shared_hash_destroy (set->vars);
++  set->vars = shared_hash_copy (empty_shared_hash);
+ }
+ 
+ /* Copy the contents of dataflow set SRC to DST.  */
+@@ -1081,7 +1187,8 @@ dataflow_set_copy (dataflow_set *dst, da
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     attrs_list_copy (&dst->regs[i], src->regs[i]);
+ 
+-  vars_copy (dst->vars, src->vars);
++  shared_hash_destroy (dst->vars);
++  dst->vars = shared_hash_copy (src->vars);
+   dst->stack_adjust = src->stack_adjust;
+ }
+ 
+@@ -1129,15 +1236,14 @@ variable_union_info_cmp_pos (const void 
+ static int
+ variable_union (void **slot, void *data)
+ {
+-  variable src, dst, *dstp;
++  variable src, dst;
++  void **dstp;
+   dataflow_set *set = (dataflow_set *) data;
+   int i, j, k;
+ 
+   src = *(variable *) slot;
+-  dstp = (variable *) htab_find_slot_with_hash (set->vars, src->decl,
+-						VARIABLE_HASH_VAL (src->decl),
+-						INSERT);
+-  if (!*dstp)
++  dstp = shared_hash_find_slot (set->vars, src->decl);
++  if (!dstp || !*dstp)
+     {
+       src->refcount++;
+ 
+@@ -1162,16 +1268,23 @@ variable_union (void **slot, void *data)
+ 	  if (! flag_var_tracking_uninit)
+ 	    status = VAR_INIT_STATUS_INITIALIZED;
+ 
++	  if (dstp)
++	    *dstp = (void *) src;
+ 	  unshare_variable (set, src, status);
+ 	}
+       else
+-	*dstp = src;
++	{
++	  if (!dstp)
++	    dstp = shared_hash_find_slot_unshare (&set->vars, src->decl,
++						  INSERT);
++	  *dstp = (void *) src;
++	}
+ 
+       /* Continue traversing the hash table.  */
+       return 1;
+     }
+   else
+-    dst = *dstp;
++    dst = (variable) *dstp;
+ 
+   gcc_assert (src->n_var_parts);
+ 
+@@ -1196,7 +1309,8 @@ variable_union (void **slot, void *data)
+      thus there are at most MAX_VAR_PARTS different offsets.  */
+   gcc_assert (k <= MAX_VAR_PARTS);
+ 
+-  if (dst->refcount > 1 && dst->n_var_parts != k)
++  if ((dst->refcount > 1 || shared_hash_shared (set->vars))
++      && dst->n_var_parts != k)
+     {
+       enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
+       
+@@ -1226,7 +1340,7 @@ variable_union (void **slot, void *data)
+ 	  /* If DST is shared compare the location chains.
+ 	     If they are different we will modify the chain in DST with
+ 	     high probability so make a copy of DST.  */
+-	  if (dst->refcount > 1)
++	  if (dst->refcount > 1 || shared_hash_shared (set->vars))
+ 	    {
+ 	      for (node = src->var_part[i].loc_chain,
+ 		   node2 = dst->var_part[j].loc_chain; node && node2;
+@@ -1379,6 +1493,46 @@ variable_union (void **slot, void *data)
+   return 1;
+ }
+ 
++/* Like variable_union, but only used when doing dataflow_set_union
++   into an empty hashtab.  To allow sharing, dst is initially shared
++   with src (so all variables are "copied" from src to dst hashtab),
++   so only unshare_variable for variables that need canonicalization
++   are needed.  */
++
++static int
++variable_canonicalize (void **slot, void *data)
++{
++  variable src;
++  dataflow_set *set = (dataflow_set *) data;
++  int k;
++
++  src = *(variable *) slot;
++
++  /* If CUR_LOC of some variable part is not the first element of
++     the location chain we are going to change it so we have to make
++     a copy of the variable.  */
++  for (k = 0; k < src->n_var_parts; k++)
++    {
++      gcc_assert (!src->var_part[k].loc_chain == !src->var_part[k].cur_loc);
++      if (src->var_part[k].loc_chain)
++	{
++	  gcc_assert (src->var_part[k].cur_loc);
++	  if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
++	    break;
++	}
++    }
++  if (k < src->n_var_parts)
++    {
++      enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
++
++      if (! flag_var_tracking_uninit)
++	status = VAR_INIT_STATUS_INITIALIZED;
++
++      unshare_variable (set, src, status);
++    }
++  return 1;
++}
++
+ /* Compute union of dataflow sets SRC and DST and store it to DST.  */
+ 
+ static void
+@@ -1389,7 +1543,14 @@ dataflow_set_union (dataflow_set *dst, d
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     attrs_list_union (&dst->regs[i], src->regs[i]);
+ 
+-  htab_traverse (src->vars, variable_union, dst);
++  if (dst->vars == empty_shared_hash)
++    {
++      shared_hash_destroy (dst->vars);
++      dst->vars = shared_hash_copy (src->vars);
++      htab_traverse (shared_hash_htab (src->vars), variable_canonicalize, dst);
++    }
++  else
++    htab_traverse (shared_hash_htab (src->vars), variable_union, dst);
+ }
+ 
+ /* Flag whether two dataflow sets being compared contain different data.  */
+@@ -1522,15 +1683,24 @@ dataflow_set_different_2 (void **slot, v
+ static bool
+ dataflow_set_different (dataflow_set *old_set, dataflow_set *new_set)
+ {
++  if (old_set->vars == new_set->vars)
++    return false;
++
++  if (htab_elements (shared_hash_htab (old_set->vars))
++      != htab_elements (shared_hash_htab (new_set->vars)))
++    return true;
++
+   dataflow_set_different_value = false;
+ 
+-  htab_traverse (old_set->vars, dataflow_set_different_1, new_set->vars);
++  htab_traverse (shared_hash_htab (old_set->vars), dataflow_set_different_1,
++		 shared_hash_htab (new_set->vars));
+   if (!dataflow_set_different_value)
+     {
+       /* We have compared the variables which are in both hash tables
+ 	 so now only check whether there are some variables in NEW_SET->VARS
+ 	 which are not in OLD_SET->VARS.  */
+-      htab_traverse (new_set->vars, dataflow_set_different_2, old_set->vars);
++      htab_traverse (shared_hash_htab (new_set->vars), dataflow_set_different_2,
++		     shared_hash_htab (old_set->vars));
+     }
+   return dataflow_set_different_value;
+ }
+@@ -1545,7 +1715,7 @@ dataflow_set_destroy (dataflow_set *set)
+   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+     attrs_list_clear (&set->regs[i]);
+ 
+-  htab_delete (set->vars);
++  shared_hash_destroy (set->vars);
+   set->vars = NULL;
+ }
+ 
+@@ -1985,7 +2155,6 @@ find_src_set_src (dataflow_set *set, rtx
+ {
+   tree decl = NULL_TREE;   /* The variable being copied around.          */
+   rtx set_src = NULL_RTX;  /* The value for "decl" stored in "src".      */
+-  void **slot;
+   variable var;
+   location_chain nextp;
+   int i;
+@@ -1998,12 +2167,9 @@ find_src_set_src (dataflow_set *set, rtx
+ 
+   if (src && decl)
+     {
+-      slot = htab_find_slot_with_hash (set->vars, decl, 
+-				       VARIABLE_HASH_VAL (decl), NO_INSERT);
+-
+-      if (slot)
++      var = shared_hash_find (set->vars, decl);
++      if (var)
+ 	{
+-	  var = *(variable *) slot;
+ 	  found = false;
+ 	  for (i = 0; i < var->n_var_parts && !found; i++)
+ 	    for (nextp = var->var_part[i].loc_chain; nextp && !found; 
+@@ -2031,7 +2197,7 @@ compute_bb_dataflow (basic_block bb)
+   dataflow_set *in = &VTI (bb)->in;
+   dataflow_set *out = &VTI (bb)->out;
+ 
+-  dataflow_set_init (&old_out, htab_elements (VTI (bb)->out.vars) + 3);
++  dataflow_set_init (&old_out);
+   dataflow_set_copy (&old_out, out);
+   dataflow_set_copy (out, in);
+ 
+@@ -2323,7 +2489,7 @@ dump_dataflow_set (dataflow_set *set)
+ 	  dump_attrs_list (set->regs[i]);
+ 	}
+     }
+-  dump_vars (set->vars);
++  dump_vars (shared_hash_htab (set->vars));
+   fprintf (dump_file, "\n");
+ }
+ 
+@@ -2345,10 +2511,10 @@ dump_dataflow_sets (void)
+ }
+ 
+ /* Add variable VAR to the hash table of changed variables and
+-   if it has no locations delete it from hash table HTAB.  */
++   if it has no locations delete it from SET's hash table.  */
+ 
+ static void
+-variable_was_changed (variable var, htab_t htab)
++variable_was_changed (variable var, dataflow_set *set)
+ {
+   hashval_t hash = VARIABLE_HASH_VAL (var->decl);
+ 
+@@ -2359,36 +2525,39 @@ variable_was_changed (variable var, htab
+       slot = (variable *) htab_find_slot_with_hash (changed_variables,
+ 						    var->decl, hash, INSERT);
+ 
+-      if (htab && var->n_var_parts == 0)
++      if (set && var->n_var_parts == 0)
+ 	{
+ 	  variable empty_var;
+-	  void **old;
+ 
+ 	  empty_var = (variable) pool_alloc (var_pool);
+ 	  empty_var->decl = var->decl;
+ 	  empty_var->refcount = 1;
+ 	  empty_var->n_var_parts = 0;
+ 	  *slot = empty_var;
+-
+-	  old = htab_find_slot_with_hash (htab, var->decl, hash,
+-					  NO_INSERT);
+-	  if (old)
+-	    htab_clear_slot (htab, old);
++	  goto drop_var;
+ 	}
+       else
+ 	{
++	  var->refcount++;
+ 	  *slot = var;
+ 	}
+     }
+   else
+     {
+-      gcc_assert (htab);
++      gcc_assert (set);
+       if (var->n_var_parts == 0)
+ 	{
+-	  void **slot = htab_find_slot_with_hash (htab, var->decl, hash,
+-						  NO_INSERT);
++	  void **slot;
++
++	drop_var:
++	  slot = shared_hash_find_slot_noinsert (set->vars, var->decl);
+ 	  if (slot)
+-	    htab_clear_slot (htab, slot);
++	    {
++	      if (shared_hash_shared (set->vars))
++		slot = shared_hash_find_slot_unshare (&set->vars, var->decl,
++						      NO_INSERT);
++	      htab_clear_slot (shared_hash_htab (set->vars), slot);
++	    }
+ 	}
+     }
+ }
+@@ -2438,12 +2607,12 @@ set_variable_part (dataflow_set *set, rt
+   location_chain node, next;
+   location_chain *nextp;
+   variable var;
+-  void **slot;
+-  
+-  slot = htab_find_slot_with_hash (set->vars, decl,
+-				   VARIABLE_HASH_VAL (decl), INSERT);
+-  if (!*slot)
++  void **slot = shared_hash_find_slot (set->vars, decl);
++
++  if (!slot || !*slot)
+     {
++      if (!slot)
++	slot = shared_hash_find_slot_unshare (&set->vars, decl, INSERT);
+       /* Create new variable information.  */
+       var = (variable) pool_alloc (var_pool);
+       var->decl = decl;
+@@ -2479,13 +2648,12 @@ set_variable_part (dataflow_set *set, rt
+ 	      if (set_src != NULL)
+ 		node->set_src = set_src;
+ 
+-	      *slot = var;
+ 	      return;
+ 	    }
+ 	  else
+ 	    {
+ 	      /* We have to make a copy of a shared variable.  */
+-	      if (var->refcount > 1)
++	      if (var->refcount > 1 || shared_hash_shared (set->vars))
+ 		var = unshare_variable (set, var, initialized);
+ 	    }
+ 	}
+@@ -2494,7 +2662,7 @@ set_variable_part (dataflow_set *set, rt
+ 	  /* We have not found the location part, new one will be created.  */
+ 
+ 	  /* We have to make a copy of the shared variable.  */
+-	  if (var->refcount > 1)
++	  if (var->refcount > 1 || shared_hash_shared (set->vars))
+ 	    var = unshare_variable (set, var, initialized);
+ 
+ 	  /* We track only variables whose size is <= MAX_VAR_PARTS bytes
+@@ -2548,7 +2716,7 @@ set_variable_part (dataflow_set *set, rt
+   if (var->var_part[pos].cur_loc == NULL)
+     {
+       var->var_part[pos].cur_loc = loc;
+-      variable_was_changed (var, set->vars);
++      variable_was_changed (var, set);
+     }
+ }
+ 
+@@ -2561,16 +2729,14 @@ static void
+ clobber_variable_part (dataflow_set *set, rtx loc, tree decl,
+ 		       HOST_WIDE_INT offset, rtx set_src)
+ {
+-  void **slot;
++  variable var;
+ 
+   if (! decl || ! DECL_P (decl))
+     return;
+ 
+-  slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
+-				   NO_INSERT);
+-  if (slot)
++  var = shared_hash_find (set->vars, decl);
++  if (var)
+     {
+-      variable var = (variable) *slot;
+       int pos = find_variable_location_part (var, offset, NULL);
+ 
+       if (pos >= 0)
+@@ -2627,13 +2793,9 @@ static void
+ delete_variable_part (dataflow_set *set, rtx loc, tree decl,
+ 		      HOST_WIDE_INT offset)
+ {
+-  void **slot;
+-    
+-  slot = htab_find_slot_with_hash (set->vars, decl, VARIABLE_HASH_VAL (decl),
+-				   NO_INSERT);
+-  if (slot)
++  variable var = shared_hash_find (set->vars, decl);;
++  if (var)
+     {
+-      variable var = (variable) *slot;
+       int pos = find_variable_location_part (var, offset, NULL);
+ 
+       if (pos >= 0)
+@@ -2642,7 +2804,7 @@ delete_variable_part (dataflow_set *set,
+ 	  location_chain *nextp;
+ 	  bool changed;
+ 
+-	  if (var->refcount > 1)
++	  if (var->refcount > 1 || shared_hash_shared (set->vars))
+ 	    {
+ 	      /* If the variable contains the location part we have to
+ 		 make a copy of the variable.  */
+@@ -2705,7 +2867,7 @@ delete_variable_part (dataflow_set *set,
+ 		}
+ 	    }
+ 	  if (changed)
+-	    variable_was_changed (var, set->vars);
++	    variable_was_changed (var, set);
+ 	}
+     }
+ }
+@@ -2864,14 +3026,6 @@ emit_note_insn_var_location (void **varp
+ 
+   htab_clear_slot (changed_variables, varp);
+ 
+-  /* When there are no location parts the variable has been already
+-     removed from hash table and a new empty variable was created.
+-     Free the empty variable.  */
+-  if (var->n_var_parts == 0)
+-    {
+-      pool_free (var_pool, var);
+-    }
+-
+   /* Continue traversing the hash table.  */
+   return 1;
+ }
+@@ -2910,7 +3064,7 @@ emit_notes_for_differences_1 (void **slo
+ 
+       empty_var = (variable) pool_alloc (var_pool);
+       empty_var->decl = old_var->decl;
+-      empty_var->refcount = 1;
++      empty_var->refcount = 0;
+       empty_var->n_var_parts = 0;
+       variable_was_changed (empty_var, NULL);
+     }
+@@ -2952,8 +3106,12 @@ static void
+ emit_notes_for_differences (rtx insn, dataflow_set *old_set,
+ 			    dataflow_set *new_set)
+ {
+-  htab_traverse (old_set->vars, emit_notes_for_differences_1, new_set->vars);
+-  htab_traverse (new_set->vars, emit_notes_for_differences_2, old_set->vars);
++  htab_traverse (shared_hash_htab (old_set->vars),
++		 emit_notes_for_differences_1,
++		 shared_hash_htab (new_set->vars));
++  htab_traverse (shared_hash_htab (new_set->vars),
++		 emit_notes_for_differences_2,
++		 shared_hash_htab (old_set->vars));
+   emit_notes_for_changes (insn, EMIT_NOTE_BEFORE_INSN);
+ }
+ 
+@@ -2965,7 +3123,7 @@ emit_notes_in_bb (basic_block bb)
+   int i;
+   dataflow_set set;
+ 
+-  dataflow_set_init (&set, htab_elements (VTI (bb)->in.vars) + 3);
++  dataflow_set_init (&set);
+   dataflow_set_copy (&set, &VTI (bb)->in);
+ 
+   for (i = 0; i < VTI (bb)->n_mos; i++)
+@@ -3098,7 +3256,7 @@ vt_emit_notes (void)
+      delete_variable_part).  */
+   emit_notes = true;
+ 
+-  dataflow_set_init (&empty, 7);
++  dataflow_set_init (&empty);
+   last_out = &empty;
+ 
+   FOR_EACH_BB (bb)
+@@ -3343,14 +3501,6 @@ vt_initialize (void)
+ 	}
+     }
+ 
+-  /* Init the IN and OUT sets.  */
+-  FOR_ALL_BB (bb)
+-    {
+-      VTI (bb)->visited = false;
+-      dataflow_set_init (&VTI (bb)->in, 7);
+-      dataflow_set_init (&VTI (bb)->out, 7);
+-    }
+-
+   attrs_pool = create_alloc_pool ("attrs_def pool",
+ 				  sizeof (struct attrs_def), 1024);
+   var_pool = create_alloc_pool ("variable_def pool",
+@@ -3358,8 +3508,24 @@ vt_initialize (void)
+   loc_chain_pool = create_alloc_pool ("location_chain_def pool",
+ 				      sizeof (struct location_chain_def),
+ 				      1024);
++  shared_hash_pool = create_alloc_pool ("shared_hash_def pool",
++					sizeof (struct shared_hash_def), 256);
++  empty_shared_hash = (shared_hash) pool_alloc (shared_hash_pool);
++  empty_shared_hash->refcount = 1;
++  empty_shared_hash->htab
++    = htab_create (1, variable_htab_hash, variable_htab_eq,
++		   variable_htab_free);
+   changed_variables = htab_create (10, variable_htab_hash, variable_htab_eq,
+-				   NULL);
++				   variable_htab_free);
++
++  /* Init the IN and OUT sets.  */
++  FOR_ALL_BB (bb)
++    {
++      VTI (bb)->visited = false;
++      dataflow_set_init (&VTI (bb)->in);
++      dataflow_set_init (&VTI (bb)->out);
++    }
++
+   vt_add_function_parameters ();
+ }
+ 
+@@ -3381,10 +3547,12 @@ vt_finalize (void)
+       dataflow_set_destroy (&VTI (bb)->out);
+     }
+   free_aux_for_blocks ();
++  htab_delete (empty_shared_hash->htab);
++  htab_delete (changed_variables);
+   free_alloc_pool (attrs_pool);
+   free_alloc_pool (var_pool);
+   free_alloc_pool (loc_chain_pool);
+-  htab_delete (changed_variables);
++  free_alloc_pool (shared_hash_pool);
+ }
+ 
+ /* The entry point to variable tracking pass.  */
+--- libiberty/hashtab.c	(revision 148758)
++++ libiberty/hashtab.c	(revision 148760)
+@@ -759,7 +759,8 @@ htab_traverse_noresize (htab_t htab, hta
+ void
+ htab_traverse (htab_t htab, htab_trav callback, PTR info)
+ {
+-  if (htab_elements (htab) * 8 < htab_size (htab))
++  size_t size = htab_size (htab);
++  if (htab_elements (htab) * 8 < size && size > 32)
+     htab_expand (htab);
+ 
+   htab_traverse_noresize (htab, callback, info);
diff --git a/gcc44-rh503816-2.patch b/gcc44-rh503816-2.patch
new file mode 100644
index 0000000..5ee452a
--- /dev/null
+++ b/gcc44-rh503816-2.patch
@@ -0,0 +1,491 @@
+2009-06-23  Jakub Jelinek  <jakub at redhat.com>
+
+	* var-tracking.c (unshare_variable): Force initialized to
+	be VAR_INIT_STATUS_INITIALIZED unless flag_var_tracking_uninit.
+	(set_variable_part): Likewise.
+	(struct variable_union_info): Remove pos_src field.
+	(vui_vec, vui_allocated): New variables.
+	(variable_union): Pass VAR_INIT_STATUS_UNKNOWN to unshare_variable
+	unconditionally.  Avoid XCVECNEW/free for every sorting, for dst_l
+	== 1 use a simpler sorting algorithm.  Compute pos field right
+	away, don't fill in pos_src.  For dst_l == 2 avoid qsort.
+	Avoid quadratic comparison if !flag_var_tracking_uninit.
+	(variable_canonicalize): Pass VAR_INIT_STATUS_UNKNOWN to
+	unshare_variable unconditionally.   
+	(dataflow_set_different_2): Removed.
+	(dataflow_set_different): Don't traverse second hash table.
+	(compute_bb_dataflow): Pass VAR_INIT_STATUS_UNINITIALIZED
+	unconditionally to var_reg_set or var_mem_set.
+	(emit_notes_in_bb): Likewise.
+	(delete_variable_part): Pass VAR_INIT_STATUS_UNKNOWN to
+	unshare_variable.
+	(emit_note_insn_var_location): Don't set initialized to
+	VAR_INIT_STATUS_INITIALIZED early.
+	(vt_finalize): Free vui_vec if needed, clear vui_vec and
+	vui_allocated.
+
+--- gcc/var-tracking.c	(revision 148851)
++++ gcc/var-tracking.c	(revision 148852)
+@@ -347,7 +347,6 @@ static void dataflow_set_union (dataflow
+ static bool variable_part_different_p (variable_part *, variable_part *);
+ static bool variable_different_p (variable, variable, bool);
+ static int dataflow_set_different_1 (void **, void *);
+-static int dataflow_set_different_2 (void **, void *);
+ static bool dataflow_set_different (dataflow_set *, dataflow_set *);
+ static void dataflow_set_destroy (dataflow_set *);
+ 
+@@ -878,6 +877,9 @@ unshare_variable (dataflow_set *set, var
+   var->refcount--;
+   new_var->n_var_parts = var->n_var_parts;
+ 
++  if (! flag_var_tracking_uninit)
++    initialized = VAR_INIT_STATUS_INITIALIZED;
++
+   for (i = 0; i < var->n_var_parts; i++)
+     {
+       location_chain node;
+@@ -1202,11 +1204,14 @@ struct variable_union_info
+   /* The sum of positions in the input chains.  */
+   int pos;
+ 
+-  /* The position in the chains of SRC and DST dataflow sets.  */
+-  int pos_src;
++  /* The position in the chain of DST dataflow set.  */
+   int pos_dst;
+ };
+ 
++/* Buffer for location list sorting and its allocated size.  */
++static struct variable_union_info *vui_vec;
++static int vui_allocated;
++
+ /* Compare function for qsort, order the structures by POS element.  */
+ 
+ static int
+@@ -1263,14 +1268,9 @@ variable_union (void **slot, void *data)
+ 	}
+       if (k < src->n_var_parts)
+ 	{
+-	  enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
+-	  
+-	  if (! flag_var_tracking_uninit)
+-	    status = VAR_INIT_STATUS_INITIALIZED;
+-
+ 	  if (dstp)
+ 	    *dstp = (void *) src;
+-	  unshare_variable (set, src, status);
++	  unshare_variable (set, src, VAR_INIT_STATUS_UNKNOWN);
+ 	}
+       else
+ 	{
+@@ -1311,13 +1311,7 @@ variable_union (void **slot, void *data)
+ 
+   if ((dst->refcount > 1 || shared_hash_shared (set->vars))
+       && dst->n_var_parts != k)
+-    {
+-      enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
+-      
+-      if (! flag_var_tracking_uninit)
+-	status = VAR_INIT_STATUS_INITIALIZED;
+-      dst = unshare_variable (set, dst, status);
+-    }
++    dst = unshare_variable (set, dst, VAR_INIT_STATUS_UNKNOWN);
+ 
+   i = src->n_var_parts - 1;
+   j = dst->n_var_parts - 1;
+@@ -1366,70 +1360,152 @@ variable_union (void **slot, void *data)
+ 	  dst_l = 0;
+ 	  for (node = dst->var_part[j].loc_chain; node; node = node->next)
+ 	    dst_l++;
+-	  vui = XCNEWVEC (struct variable_union_info, src_l + dst_l);
+ 
+-	  /* Fill in the locations from DST.  */
+-	  for (node = dst->var_part[j].loc_chain, jj = 0; node;
+-	       node = node->next, jj++)
++	  if (dst_l == 1)
+ 	    {
+-	      vui[jj].lc = node;
+-	      vui[jj].pos_dst = jj;
++	      /* The most common case, much simpler, no qsort is needed.  */
++	      location_chain dstnode = dst->var_part[j].loc_chain;
++	      dst->var_part[k].loc_chain = dstnode;
++	      dst->var_part[k].offset = dst->var_part[j].offset;
++	      node2 = dstnode;
++	      for (node = src->var_part[i].loc_chain; node; node = node->next)
++		if (!((REG_P (dstnode->loc)
++		       && REG_P (node->loc)
++		       && REGNO (dstnode->loc) == REGNO (node->loc))
++		      || rtx_equal_p (dstnode->loc, node->loc)))
++		  {
++		    location_chain new_node;
+ 
+-	      /* Value larger than a sum of 2 valid positions.  */
+-	      vui[jj].pos_src = src_l + dst_l;
++		    /* Copy the location from SRC.  */
++		    new_node = (location_chain) pool_alloc (loc_chain_pool);
++		    new_node->loc = node->loc;
++		    new_node->init = node->init;
++		    if (!node->set_src || MEM_P (node->set_src))
++		      new_node->set_src = NULL;
++		    else
++		      new_node->set_src = node->set_src;
++		    node2->next = new_node;
++		    node2 = new_node;
++		  }
++	      node2->next = NULL;
+ 	    }
+-
+-	  /* Fill in the locations from SRC.  */
+-	  n = dst_l;
+-	  for (node = src->var_part[i].loc_chain, ii = 0; node;
+-	       node = node->next, ii++)
++	  else
+ 	    {
+-	      /* Find location from NODE.  */
+-	      for (jj = 0; jj < dst_l; jj++)
++	      if (src_l + dst_l > vui_allocated)
+ 		{
+-		  if ((REG_P (vui[jj].lc->loc)
+-		       && REG_P (node->loc)
+-		       && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
+-		      || rtx_equal_p (vui[jj].lc->loc, node->loc))
+-		    {
+-		      vui[jj].pos_src = ii;
+-		      break;
+-		    }
++		  vui_allocated = MAX (vui_allocated * 2, src_l + dst_l);
++		  vui_vec = XRESIZEVEC (struct variable_union_info, vui_vec,
++					vui_allocated);
+ 		}
+-	      if (jj >= dst_l)	/* The location has not been found.  */
++	      vui = vui_vec;
++
++	      /* Fill in the locations from DST.  */
++	      for (node = dst->var_part[j].loc_chain, jj = 0; node;
++		   node = node->next, jj++)
+ 		{
+-		  location_chain new_node;
++		  vui[jj].lc = node;
++		  vui[jj].pos_dst = jj;
+ 
+-		  /* Copy the location from SRC.  */
+-		  new_node = (location_chain) pool_alloc (loc_chain_pool);
+-		  new_node->loc = node->loc;
+-		  new_node->init = node->init;
+-		  if (!node->set_src || MEM_P (node->set_src))
+-		    new_node->set_src = NULL;
+-		  else
+-		    new_node->set_src = node->set_src;
+-		  vui[n].lc = new_node;
+-		  vui[n].pos_src = ii;
+-		  vui[n].pos_dst = src_l + dst_l;
+-		  n++;
++		  /* Pos plus value larger than a sum of 2 valid positions.  */
++		  vui[jj].pos = jj + src_l + dst_l;
+ 		}
+-	    }
+ 
+-	  for (ii = 0; ii < src_l + dst_l; ii++)
+-	    vui[ii].pos = vui[ii].pos_src + vui[ii].pos_dst;
++	      /* Fill in the locations from SRC.  */
++	      n = dst_l;
++	      for (node = src->var_part[i].loc_chain, ii = 0; node;
++		   node = node->next, ii++)
++		{
++		  /* Find location from NODE.  */
++		  for (jj = 0; jj < dst_l; jj++)
++		    {
++		      if ((REG_P (vui[jj].lc->loc)
++			   && REG_P (node->loc)
++			   && REGNO (vui[jj].lc->loc) == REGNO (node->loc))
++			  || rtx_equal_p (vui[jj].lc->loc, node->loc))
++			{
++			  vui[jj].pos = jj + ii;
++			  break;
++			}
++		    }
++		  if (jj >= dst_l)	/* The location has not been found.  */
++		    {
++		      location_chain new_node;
+ 
+-	  qsort (vui, n, sizeof (struct variable_union_info),
+-		 variable_union_info_cmp_pos);
++		      /* Copy the location from SRC.  */
++		      new_node = (location_chain) pool_alloc (loc_chain_pool);
++		      new_node->loc = node->loc;
++		      new_node->init = node->init;
++		      if (!node->set_src || MEM_P (node->set_src))
++			new_node->set_src = NULL;
++		      else
++			new_node->set_src = node->set_src;
++		      vui[n].lc = new_node;
++		      vui[n].pos_dst = src_l + dst_l;
++		      vui[n].pos = ii + src_l + dst_l;
++		      n++;
++		    }
++		}
+ 
+-	  /* Reconnect the nodes in sorted order.  */
+-	  for (ii = 1; ii < n; ii++)
+-	    vui[ii - 1].lc->next = vui[ii].lc;
+-	  vui[n - 1].lc->next = NULL;
++	      if (dst_l == 2)
++		{
++		  /* Special case still very common case.  For dst_l == 2
++		     all entries dst_l ... n-1 are sorted, with for i >= dst_l
++		     vui[i].pos == i + src_l + dst_l.  */
++		  if (vui[0].pos > vui[1].pos)
++		    {
++		      /* Order should be 1, 0, 2... */
++		      dst->var_part[k].loc_chain = vui[1].lc;
++		      vui[1].lc->next = vui[0].lc;
++		      if (n >= 3)
++			{
++			  vui[0].lc->next = vui[2].lc;
++			  vui[n - 1].lc->next = NULL;
++			}
++		      else
++			vui[0].lc->next = NULL;
++		      ii = 3;
++		    }
++		  else
++		    {
++		      dst->var_part[k].loc_chain = vui[0].lc;
++		      if (n >= 3 && vui[2].pos < vui[1].pos)
++			{
++			  /* Order should be 0, 2, 1, 3... */
++			  vui[0].lc->next = vui[2].lc;
++			  vui[2].lc->next = vui[1].lc;
++			  if (n >= 4)
++			    {
++			      vui[1].lc->next = vui[3].lc;
++			      vui[n - 1].lc->next = NULL;
++			    }
++			  else
++			    vui[1].lc->next = NULL;
++			  ii = 4;
++			}
++		      else
++			{
++			  /* Order should be 0, 1, 2... */
++			  ii = 1;
++			  vui[n - 1].lc->next = NULL;
++			}
++		    }
++		  for (; ii < n; ii++)
++		    vui[ii - 1].lc->next = vui[ii].lc;
++		}
++	      else
++		{
++		  qsort (vui, n, sizeof (struct variable_union_info),
++			 variable_union_info_cmp_pos);
+ 
+-	  dst->var_part[k].loc_chain = vui[0].lc;
+-	  dst->var_part[k].offset = dst->var_part[j].offset;
++		  /* Reconnect the nodes in sorted order.  */
++		  for (ii = 1; ii < n; ii++)
++		    vui[ii - 1].lc->next = vui[ii].lc;
++		  vui[n - 1].lc->next = NULL;
++		  dst->var_part[k].loc_chain = vui[0].lc;
++		}
+ 
+-	  free (vui);
++	      dst->var_part[k].offset = dst->var_part[j].offset;
++	    }
+ 	  i--;
+ 	  j--;
+ 	}
+@@ -1477,17 +1553,18 @@ variable_union (void **slot, void *data)
+ 	dst->var_part[k].cur_loc = NULL;
+     }
+ 
+-  for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
+-    {
+-      location_chain node, node2;
+-      for (node = src->var_part[i].loc_chain; node; node = node->next)
+-	for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
+-	  if (rtx_equal_p (node->loc, node2->loc))
+-	    {
+-	      if (node->init > node2->init)
+-		node2->init = node->init;
+-	    }
+-    }
++  if (flag_var_tracking_uninit)
++    for (i = 0; i < src->n_var_parts && i < dst->n_var_parts; i++)
++      {
++	location_chain node, node2;
++	for (node = src->var_part[i].loc_chain; node; node = node->next)
++	  for (node2 = dst->var_part[i].loc_chain; node2; node2 = node2->next)
++	    if (rtx_equal_p (node->loc, node2->loc))
++	      {
++		if (node->init > node2->init)
++		  node2->init = node->init;
++	      }
++      }
+ 
+   /* Continue traversing the hash table.  */
+   return 1;
+@@ -1522,14 +1599,7 @@ variable_canonicalize (void **slot, void
+ 	}
+     }
+   if (k < src->n_var_parts)
+-    {
+-      enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
+-
+-      if (! flag_var_tracking_uninit)
+-	status = VAR_INIT_STATUS_INITIALIZED;
+-
+-      unshare_variable (set, src, status);
+-    }
++    unshare_variable (set, src, VAR_INIT_STATUS_UNKNOWN);
+   return 1;
+ }
+ 
+@@ -1650,34 +1720,6 @@ dataflow_set_different_1 (void **slot, v
+   return 1;
+ }
+ 
+-/* Compare variable *SLOT with the same variable in hash table DATA
+-   and set DATAFLOW_SET_DIFFERENT_VALUE if they are different.  */
+-
+-static int
+-dataflow_set_different_2 (void **slot, void *data)
+-{
+-  htab_t htab = (htab_t) data;
+-  variable var1, var2;
+-
+-  var1 = *(variable *) slot;
+-  var2 = (variable) htab_find_with_hash (htab, var1->decl,
+-			      VARIABLE_HASH_VAL (var1->decl));
+-  if (!var2)
+-    {
+-      dataflow_set_different_value = true;
+-
+-      /* Stop traversing the hash table.  */
+-      return 0;
+-    }
+-
+-  /* If both variables are defined they have been already checked for
+-     equivalence.  */
+-  gcc_assert (!variable_different_p (var1, var2, false));
+-
+-  /* Continue traversing the hash table.  */
+-  return 1;
+-}
+-
+ /* Return true if dataflow sets OLD_SET and NEW_SET differ.  */
+ 
+ static bool
+@@ -1694,14 +1736,9 @@ dataflow_set_different (dataflow_set *ol
+ 
+   htab_traverse (shared_hash_htab (old_set->vars), dataflow_set_different_1,
+ 		 shared_hash_htab (new_set->vars));
+-  if (!dataflow_set_different_value)
+-    {
+-      /* We have compared the variables which are in both hash tables
+-	 so now only check whether there are some variables in NEW_SET->VARS
+-	 which are not in OLD_SET->VARS.  */
+-      htab_traverse (shared_hash_htab (new_set->vars), dataflow_set_different_2,
+-		     shared_hash_htab (old_set->vars));
+-    }
++  /* No need to traverse the second hashtab, if both have the same number
++     of elements and the second one had all entries found in the first one,
++     then it can't have any extra entries.  */
+   return dataflow_set_different_value;
+ }
+ 
+@@ -2215,15 +2252,11 @@ compute_bb_dataflow (basic_block bb)
+ 	  case MO_USE:
+ 	    {
+ 	      rtx loc = VTI (bb)->mos[i].u.loc;
+-	      enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
+-
+-	      if (! flag_var_tracking_uninit)
+-		status = VAR_INIT_STATUS_INITIALIZED;
+ 
+ 	      if (GET_CODE (loc) == REG)
+-		var_reg_set (out, loc, status, NULL);
++		var_reg_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
+ 	      else if (GET_CODE (loc) == MEM)
+-		var_mem_set (out, loc, status, NULL);
++		var_mem_set (out, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
+ 	    }
+ 	    break;
+ 
+@@ -2262,10 +2295,12 @@ compute_bb_dataflow (basic_block bb)
+ 	      if (! flag_var_tracking_uninit)
+ 		src_status = VAR_INIT_STATUS_INITIALIZED;
+ 	      else
+-		src_status = find_src_status (in, set_src);
++		{
++		  src_status = find_src_status (in, set_src);
+ 
+-	      if (src_status == VAR_INIT_STATUS_UNKNOWN)
+-		src_status = find_src_status (out, set_src);
++		  if (src_status == VAR_INIT_STATUS_UNKNOWN)
++		    src_status = find_src_status (out, set_src);
++		}
+ 
+ 	      set_src = find_src_set_src (in, set_src);
+ 
+@@ -2609,6 +2644,9 @@ set_variable_part (dataflow_set *set, rt
+   variable var;
+   void **slot = shared_hash_find_slot (set->vars, decl);
+ 
++  if (! flag_var_tracking_uninit)
++    initialized = VAR_INIT_STATUS_INITIALIZED;
++
+   if (!slot || !*slot)
+     {
+       if (!slot)
+@@ -2815,10 +2853,8 @@ delete_variable_part (dataflow_set *set,
+ 		       && REGNO (node->loc) == REGNO (loc))
+ 		      || rtx_equal_p (node->loc, loc))
+ 		    {
+-		      enum var_init_status status = VAR_INIT_STATUS_UNKNOWN;
+-		      if (! flag_var_tracking_uninit)
+-			status = VAR_INIT_STATUS_INITIALIZED;
+-		      var = unshare_variable (set, var, status);
++		      var = unshare_variable (set, var,
++					      VAR_INIT_STATUS_UNKNOWN);
+ 		      break;
+ 		    }
+ 		}
+@@ -2893,9 +2929,6 @@ emit_note_insn_var_location (void **varp
+ 
+   gcc_assert (var->decl);
+ 
+-  if (! flag_var_tracking_uninit)
+-    initialized = VAR_INIT_STATUS_INITIALIZED;
+-
+   complete = true;
+   last_limit = 0;
+   n_var_parts = 0;
+@@ -3148,14 +3181,11 @@ emit_notes_in_bb (basic_block bb)
+ 	  case MO_USE:
+ 	    {
+ 	      rtx loc = VTI (bb)->mos[i].u.loc;
+-      
+-	      enum var_init_status status = VAR_INIT_STATUS_UNINITIALIZED;
+-	      if (! flag_var_tracking_uninit)
+-		status = VAR_INIT_STATUS_INITIALIZED;
++
+ 	      if (GET_CODE (loc) == REG)
+-		var_reg_set (&set, loc, status, NULL);
++		var_reg_set (&set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
+ 	      else
+-		var_mem_set (&set, loc, status, NULL);
++		var_mem_set (&set, loc, VAR_INIT_STATUS_UNINITIALIZED, NULL);
+ 
+ 	      emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN);
+ 	    }
+@@ -3553,6 +3583,10 @@ vt_finalize (void)
+   free_alloc_pool (var_pool);
+   free_alloc_pool (loc_chain_pool);
+   free_alloc_pool (shared_hash_pool);
++  if (vui_vec)
++    free (vui_vec);
++  vui_vec = NULL;
++  vui_allocated = 0;
+ }
+ 
+ /* The entry point to variable tracking pass.  */
diff --git a/gcc44-unique-object.patch b/gcc44-unique-object.patch
new file mode 100644
index 0000000..1396e69
--- /dev/null
+++ b/gcc44-unique-object.patch
@@ -0,0 +1,142 @@
+2009-07-22  Jason Merrill  <jason at redhat.com>
+
+	* config/elfos.h (ASM_DECLARE_OBJECT_NAME): Use gnu_unique_object
+	type if available.
+	* configure.ac: Test for it.
+	* configure, config.in: Regenerate.
+
+--- gcc/config/elfos.h.jj	2009-04-14 15:51:24.000000000 +0200
++++ gcc/config/elfos.h	2009-07-23 09:25:46.000000000 +0200
+@@ -289,24 +289,37 @@ see the files COPYING3 and COPYING.RUNTI
+ 
+ /* Write the extra assembler code needed to declare an object properly.  */
+ 
+-#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL)		\
+-  do								\
+-    {								\
+-      HOST_WIDE_INT size;					\
+-								\
+-      ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");		\
+-								\
+-      size_directive_output = 0;				\
+-      if (!flag_inhibit_size_directive				\
+-	  && (DECL) && DECL_SIZE (DECL))			\
+-	{							\
+-	  size_directive_output = 1;				\
+-	  size = int_size_in_bytes (TREE_TYPE (DECL));		\
+-	  ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size);		\
+-	}							\
+-								\
+-      ASM_OUTPUT_LABEL (FILE, NAME);				\
+-    }								\
++#ifdef HAVE_GAS_GNU_UNIQUE_OBJECT
++#define USE_GNU_UNIQUE_OBJECT 1
++#else
++#define USE_GNU_UNIQUE_OBJECT 0
++#endif
++
++#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL)			\
++  do									\
++    {									\
++      HOST_WIDE_INT size;						\
++									\
++      /* For template static data member instantiations or		\
++	 inline fn local statics, use gnu_unique_object so that		\
++	 they will be combined even under RTLD_LOCAL.  */		\
++      if (USE_GNU_UNIQUE_OBJECT						\
++	  && !DECL_ARTIFICIAL (DECL) && DECL_ONE_ONLY (DECL))		\
++	ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "gnu_unique_object");	\
++      else								\
++	ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object");		\
++									\
++      size_directive_output = 0;					\
++      if (!flag_inhibit_size_directive					\
++	  && (DECL) && DECL_SIZE (DECL))				\
++	{								\
++	  size_directive_output = 1;					\
++	  size = int_size_in_bytes (TREE_TYPE (DECL));			\
++	  ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, size);			\
++	}								\
++									\
++      ASM_OUTPUT_LABEL (FILE, NAME);					\
++    }									\
+   while (0)
+ 
+ /* Output the size directive for a decl in rest_of_decl_compilation
+--- gcc/configure.ac.jj	2009-03-28 09:53:59.000000000 +0100
++++ gcc/configure.ac	2009-07-23 09:25:46.000000000 +0200
+@@ -3299,6 +3299,12 @@ gcc_GAS_CHECK_FEATURE([.lcomm with align
+ [AC_DEFINE(HAVE_GAS_LCOMM_WITH_ALIGNMENT, 1,
+   [Define if your assembler supports .lcomm with an alignment field.])])
+ 
++gcc_GAS_CHECK_FEATURE([gnu_unique_object], gcc_cv_as_gnu_unique_object,
++ [elf,2,19,52],,
++[.type foo, @gnu_unique_object],,
++[AC_DEFINE(HAVE_GAS_GNU_UNIQUE_OBJECT, 1,
++  [Define if your assembler supports @gnu_unique_object.])])
++
+ AC_CACHE_CHECK([assembler for tolerance to line number 0],
+  [gcc_cv_as_line_zero],
+  [gcc_cv_as_line_zero=no
+--- gcc/configure.jj	2009-03-28 09:53:37.000000000 +0100
++++ gcc/configure	2009-07-23 09:26:52.000000000 +0200
+@@ -24288,6 +24288,44 @@ _ACEOF
+ 
+ fi
+ 
++echo "$as_me:$LINENO: checking assembler for gnu_unique_object" >&5
++echo $ECHO_N "checking assembler for gnu_unique_object... $ECHO_C" >&6
++if test "${gcc_cv_as_gnu_unique_object+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  gcc_cv_as_gnu_unique_object=no
++    if test $in_tree_gas = yes; then
++    if test $in_tree_gas_is_elf = yes \
++  && test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 52`
++  then gcc_cv_as_gnu_unique_object=yes
++fi
++  elif test x$gcc_cv_as != x; then
++    echo '.type foo, @gnu_unique_object' > conftest.s
++    if { ac_try='$gcc_cv_as  -o conftest.o conftest.s >&5'
++  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
++  (eval $ac_try) 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }
++    then
++	gcc_cv_as_gnu_unique_object=yes
++    else
++      echo "configure: failed program was" >&5
++      cat conftest.s >&5
++    fi
++    rm -f conftest.o conftest.s
++  fi
++fi
++echo "$as_me:$LINENO: result: $gcc_cv_as_gnu_unique_object" >&5
++echo "${ECHO_T}$gcc_cv_as_gnu_unique_object" >&6
++if test $gcc_cv_as_gnu_unique_object = yes; then
++
++cat >>confdefs.h <<\_ACEOF
++#define HAVE_GAS_GNU_UNIQUE_OBJECT 1
++_ACEOF
++
++fi
++
+ echo "$as_me:$LINENO: checking assembler for tolerance to line number 0" >&5
+ echo $ECHO_N "checking assembler for tolerance to line number 0... $ECHO_C" >&6
+ if test "${gcc_cv_as_line_zero+set}" = set; then
+--- gcc/config.in.jj	2009-02-16 22:48:20.000000000 +0100
++++ gcc/config.in	2009-07-23 09:26:56.000000000 +0200
+@@ -845,6 +845,12 @@
+ #endif
+ 
+ 
++/* Define if your assembler supports @gnu_unique_object. */
++#ifndef USED_FOR_TARGET
++#undef HAVE_GAS_GNU_UNIQUE_OBJECT
++#endif
++
++
+ /* Define if your assembler and linker support .hidden. */
+ #undef HAVE_GAS_HIDDEN
+ 
diff --git a/gcc44-unwind-debug-hook.patch b/gcc44-unwind-debug-hook.patch
new file mode 100644
index 0000000..e084be5
--- /dev/null
+++ b/gcc44-unwind-debug-hook.patch
@@ -0,0 +1,46 @@
+2009-05-27  Tom Tromey  <tromey at redhat.com>
+
+	* unwind-dw2.c (_Unwind_DebugHook): New function.
+	(uw_install_context): Call _Unwind_DebugHook.
+
+--- gcc/unwind-dw2.c	(revision 147933)
++++ gcc/unwind-dw2.c	(revision 147934)
+@@ -1473,18 +1473,31 @@ uw_init_context_1 (struct _Unwind_Contex
+   context->ra = __builtin_extract_return_addr (outer_ra);
+ }
+ 
++static void _Unwind_DebugHook (void *, void *) __attribute__ ((__noinline__));
++
++/* This function is called during unwinding.  It is intended as a hook
++   for a debugger to intercept exceptions.  CFA is the CFA of the
++   target frame.  HANDLER is the PC to which control will be
++   transferred.  */
++static void
++_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
++		   void *handler __attribute__ ((__unused__)))
++{
++  asm ("");
++}
+ 
+ /* Install TARGET into CURRENT so that we can return to it.  This is a
+    macro because __builtin_eh_return must be invoked in the context of
+    our caller.  */
+ 
+-#define uw_install_context(CURRENT, TARGET)				 \
+-  do									 \
+-    {									 \
+-      long offset = uw_install_context_1 ((CURRENT), (TARGET));		 \
+-      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	 \
+-      __builtin_eh_return (offset, handler);				 \
+-    }									 \
++#define uw_install_context(CURRENT, TARGET)				\
++  do									\
++    {									\
++      long offset = uw_install_context_1 ((CURRENT), (TARGET));		\
++      void *handler = __builtin_frob_return_addr ((TARGET)->ra);	\
++      _Unwind_DebugHook ((TARGET)->cfa, handler);			\
++      __builtin_eh_return (offset, handler);				\
++    }									\
+   while (0)
+ 
+ static long
diff --git a/mingw32-gcc.spec b/mingw32-gcc.spec
index 51ccd31..0e380b2 100644
--- a/mingw32-gcc.spec
+++ b/mingw32-gcc.spec
@@ -1,14 +1,14 @@
-%define __os_install_post /usr/lib/rpm/brp-compress %{nil}
+%global __os_install_post /usr/lib/rpm/brp-compress %{nil}
 
-%define DATE 20090319
-%define SVNREV 144967
+%global DATE 20090818
+%global SVNREV 150873
 
 Name:           mingw32-gcc
-Version:        4.4.0
-Release:        0.8%{?dist}
+Version:        4.4.1
+Release:        1%{?dist}
 Summary:        MinGW Windows cross-compiler (GCC) for C
 
-License:        GPLv3+ and GPLv2+ with exceptions
+License:        GPLv3+, GPLv3+ with exceptions and GPLv2+ with exceptions
 Group:          Development/Languages
 
 # We use the same source as Fedora's native gcc.
@@ -25,8 +25,6 @@ Patch2:         gcc44-c++-builtin-redecl.patch
 Patch3:         gcc44-ia64-libunwind.patch
 Patch4:         gcc44-java-nomulti.patch
 Patch5:         gcc44-ppc32-retaddr.patch
-Patch7:         gcc44-pr27898.patch
-Patch8:         gcc44-pr32139.patch
 Patch9:         gcc44-pr33763.patch
 Patch10:        gcc44-rh330771.patch
 Patch11:        gcc44-rh341221.patch
@@ -37,13 +35,15 @@ Patch16:        gcc44-libgomp-omp_h-multilib.patch
 Patch20:        gcc44-libtool-no-rpath.patch
 Patch21:        gcc44-cloog-dl.patch
 Patch22:        gcc44-raw-string.patch
-Patch24:        gcc44-atom.patch
-Patch25:        gcc44-pr39226.patch
-Patch26:        gcc44-power7.patch
-Patch27:        gcc44-power7-2.patch
+Patch24:        gcc44-unwind-debug-hook.patch
+Patch25:        gcc44-power7.patch
+Patch26:        gcc44-power7-2.patch
+Patch27:        gcc44-power7-3.patch
 Patch28:        gcc44-pr38757.patch
-Patch29:        gcc44-pr37959.patch
-Patch30:        gcc44-memmove-opt.patch
+#Patch29:        gcc44-libstdc++-docs.patch
+Patch30:        gcc44-rh503816-1.patch
+Patch31:        gcc44-rh503816-2.patch
+Patch32:        gcc44-unique-object.patch
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -128,8 +128,6 @@ MinGW Windows cross-compiler for FORTRAN.
 %patch3 -p0 -b .ia64-libunwind~
 %patch4 -p0 -b .java-nomulti~
 %patch5 -p0 -b .ppc32-retaddr~
-%patch7 -p0 -b .pr27898~
-%patch8 -p0 -b .pr32139~
 %patch9 -p0 -b .pr33763~
 %patch10 -p0 -b .rh330771~
 %patch11 -p0 -b .rh341221~
@@ -140,13 +138,17 @@ MinGW Windows cross-compiler for FORTRAN.
 %patch20 -p0 -b .libtool-no-rpath~
 %patch21 -p0 -b .cloog-dl~
 %patch22 -p0 -b .raw-string~
-%patch24 -p0 -b .atom~
-%patch25 -p0 -b .pr39226~
-%patch26 -p0 -b .power7~
-%patch27 -p0 -b .power7-2~
+%patch24 -p0 -b .unwind-debug-hook~
+%patch25 -p0 -b .power7~
+%patch26 -p0 -b .power7-2~
+%patch27 -p0 -b .power7-3~
 %patch28 -p0 -b .pr38757~
-%patch29 -p0 -b .pr37959~
-%patch30 -p0 -b .memmove-opt~
+%patch30 -p0 -b .rh503816-1~
+%patch31 -p0 -b .rh503816-2~
+%patch32 -p0 -b .unique-object~
+
+sed -i -e 's/4\.4\.2/%{version}/' gcc/BASE-VER
+echo 'Fedora MinGW %{version}-%{release}' > gcc/DEV-PHASE
 
 
 %build
@@ -216,7 +218,7 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %files
-%defattr(-,root,root)
+%defattr(-,root,root,-)
 %{_bindir}/i686-pc-mingw32-gcc
 %{_bindir}/i686-pc-mingw32-gcc-%{version}
 %{_bindir}/i686-pc-mingw32-gccbug
@@ -253,7 +255,7 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %files -n mingw32-cpp
-%defattr(-,root,root)
+%defattr(-,root,root,-)
 /lib/i686-pc-mingw32-cpp
 %{_bindir}/i686-pc-mingw32-cpp
 %{_mandir}/man1/i686-pc-mingw32-cpp.1*
@@ -263,7 +265,7 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %files c++
-%defattr(-,root,root)
+%defattr(-,root,root,-)
 %{_bindir}/i686-pc-mingw32-g++
 %{_bindir}/i686-pc-mingw32-c++
 %{_mandir}/man1/i686-pc-mingw32-g++.1*
@@ -275,19 +277,19 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %files objc
-%defattr(-,root,root)
+%defattr(-,root,root,-)
 %{_libdir}/gcc/i686-pc-mingw32/%{version}/include/objc/
 %{_libdir}/gcc/i686-pc-mingw32/%{version}/libobjc.a
 %{_libexecdir}/gcc/i686-pc-mingw32/%{version}/cc1obj
 
 
 %files objc++
-%defattr(-,root,root)
+%defattr(-,root,root,-)
 %{_libexecdir}/gcc/i686-pc-mingw32/%{version}/cc1objplus
 
 
 %files gfortran
-%defattr(-,root,root)
+%defattr(-,root,root,-)
 %{_bindir}/i686-pc-mingw32-gfortran
 %{_mandir}/man1/i686-pc-mingw32-gfortran.1*
 %{_libdir}/gcc/i686-pc-mingw32/%{version}/libgfortran.a
@@ -296,6 +298,12 @@ rm -rf $RPM_BUILD_ROOT
 
 
 %changelog
+* Sun Aug 23 2009 Kalev Lember <kalev at smartlink.ee> - 4.4.1-1
+- Update to gcc 4.4.1 20090818 svn 150873.
+- Patches taken from native Fedora gcc-4.4.1-6.
+- Replaced %%define with %%global and updated %%defattr.
+- Changed license to match native Fedora gcc package.
+
 * Sat Jul 25 2009 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 4.4.0-0.8
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
 
diff --git a/sources b/sources
index 155c3d1..7fd7eb9 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-2992035eaf092d72eb98ad16b173f737  gcc-4.4.0-20090319.tar.bz2
+a280c87e7d0a44a99a6bc84bbe3eb86d  gcc-4.4.1-20090818.tar.bz2


More information about the scm-commits mailing list