This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[power7-meissner, committed] Rework store/load with update, Fix some reload issues


Today's patch fixes some reload issues found with power7 support, and reworks
the load/store with update to use multiple iterators.  I made the macro
REGNO_REG_CLASS to be an array index, instead of multiple ?: operations.
Finally, I made the vsx debug switches undocumented.

2009-04-08  Michael Meissner  <meissner@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.

Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 145474)
+++ gcc/doc/invoke.texi	(working copy)
@@ -729,9 +729,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 -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
@@ -13895,36 +13893,6 @@ Generate code that uses (does not use) v
 instructions, and also enable the use of built-in functions that allow
 more direct access to the VSX instruction set.
 
-@item -mvsx-vector-memory
-@itemx -mno-vsx-vector-memory
-If @option{-mvsx}, use VSX memory reference instructions for vectors
-instead of the Altivec instructions This option is a temporary switch
-to tune the compiler, and may not be supported in future versions.
-
-@item -mvsx-vector-float
-@itemx -mno-vsx-vector-float
-If @option{-mvsx}, use VSX arithmetic instructions for float vectors.
-This option is a temporary switch to tune the compiler, and may not be
-supported in future versions.
-
-@item -mvsx-vector-double
-@itemx -mno-vsx-vector-double
-If @option{-mvsx}, use VSX arithmetic instructions for double
-vectors.  This option is a temporary switch to tune the
-compiler, and may not be supported in future versions.
-
-@item -mvsx-scalar-double
-@itemx -mno-vsx-scalar-double
-If @option{-mvsx}, use VSX arithmetic instructions for scalar double.
-This option is a temporary switch to tune the compiler, and may not be
-supported in future versions.
-
-@item -mvsx-scalar-memory
-@itemx -mno-vsx-scalar-memory
-If @option{-mvsx}, use VSX memory reference instructions for scalar
-double.  This option is a temporary switch to tune the compiler, and
-may not be supported in future versions.
-
 @item -mfloat-gprs=@var{yes/single/double/no}
 @itemx -mfloat-gprs
 @opindex mfloat-gprs
Index: gcc/config/rs6000/vector.md
===================================================================
--- gcc/config/rs6000/vector.md	(revision 145474)
+++ gcc/config/rs6000/vector.md	(working copy)
@@ -39,6 +39,9 @@
 ;; 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")
@@ -61,15 +64,16 @@
 	(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
@@ -100,6 +104,49 @@
 })
 
 
+;; 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" "")
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h	(revision 145474)
+++ gcc/config/rs6000/rs6000-protos.h	(working copy)
@@ -72,7 +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 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[]);
Index: gcc/config/rs6000/rs6000.opt
===================================================================
--- gcc/config/rs6000/rs6000.opt	(revision 145474)
+++ gcc/config/rs6000/rs6000.opt	(working copy)
@@ -120,30 +120,40 @@ Target Report Mask(VSX)
 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 Var(TARGET_UPDATE) Init(1)
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 145474)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -237,8 +237,13 @@ unsigned char rs6000_class_max_nregs[NUM
 /* 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];
 tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
 
@@ -1569,12 +1574,43 @@ rs6000_init_hard_regno_mode_ok (void)
   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.  */
@@ -1651,8 +1687,13 @@ rs6000_init_hard_regno_mode_ok (void)
   /* 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
@@ -1670,6 +1711,41 @@ 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_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)
@@ -5129,6 +5205,11 @@ rs6000_mode_dependent_address (rtx addr)
       ret = (TARGET_UPDATE != 0);
       break;
 
+      /* AND is only allowed in Altivec loads.  */
+    case AND:
+      ret = true;
+      break;
+
     default:
       break;
     }
@@ -5482,6 +5563,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)
@@ -12317,9 +12412,37 @@ 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.  */
+   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,
@@ -12328,42 +12451,242 @@ rs6000_secondary_reload (bool in_p,
 			 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, in_p = %s, rclass = %s, mode = %s\n",
-	       in_p ? "true" : "false", reg_class_names[rclass],
+	       "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 default_secondary_reload (in_p, x, rclass, mode, sri);
+  return ret;
 }
 
 /* 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)
+rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
 {
-  rtx memref = to_mem_p ? op0 : op1;
-  gcc_assert (MEM_P (memref));
+  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_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, "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_unreachable ();
+  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
@@ -12453,14 +12776,22 @@ rs6000_preferred_reload_class (rtx x, en
   else if (GET_MODE_CLASS (mode) == MODE_INT && rclass == NON_SPECIAL_REGS)
     ret = GENERAL_REGS;
 
-  /* For VSX, prefer the traditional registers.  */
+  /* 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)
 	ret = FLOAT_REGS;
 
-      if (ALTIVEC_VECTOR_MODE (mode))
+      else if (altivec_indexed_or_indirect_operand (x, mode))
+	ret = ALTIVEC_REGS;
+
+      else if (ALTIVEC_VECTOR_MODE (mode))
 	ret = ALTIVEC_REGS;
+
+      else
+	ret = rclass;
     }
   else
     ret = rclass;
@@ -12489,16 +12820,23 @@ rs6000_secondary_memory_needed (enum reg
 				enum machine_mode mode)
 {
   bool ret;
-  bool vsx1;
-  bool vsx2;
 
   if (class1 == class2)
     ret = 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);
+  /* 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
@@ -12648,6 +12986,11 @@ rs6000_cannot_change_mode_class (enum ma
 		       || (((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)));
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md	(revision 145474)
+++ gcc/config/rs6000/vsx.md	(working copy)
@@ -28,6 +28,9 @@
 ;; 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")
@@ -68,17 +71,17 @@
 			 (DF    "!f#r")])
 
 ;; Same size integer type for floating point data
-(define_mode_attr VSi [(V2DF  "v2di")
-		       (V4SF  "v4si")
+(define_mode_attr VSi [(V4SF  "v4si")
+		       (V2DF  "v2di")
 		       (DF    "di")])
 
-(define_mode_attr VSI [(V2DF  "V2DI")
-		       (V4SF  "V4SI")
+(define_mode_attr VSI [(V4SF  "V4SI")
+		       (V2DF  "V2DI")
 		       (DF    "DI")])
 
 ;; Word size for same size conversion
-(define_mode_attr VSc [(V2DF "d")
-		       (V4SF "w")
+(define_mode_attr VSc [(V4SF "w")
+		       (V2DF "d")
 		       (DF   "d")])
 
 ;; Bitsize for DF load with update
@@ -87,9 +90,14 @@
 
 ;; Map into either s or v, depending on whether this is a scalar or vector
 ;; operation
-(define_mode_attr VSv	[(V2DF "v")
-			 (V4SF "v")
-			 (DF   "s")])
+(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")
@@ -129,6 +137,26 @@
 				 (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)
@@ -190,7 +218,7 @@
       gcc_unreachable ();
     }
 }
-  [(set_attr "type" "vecstore,vecload,vecsimple,vecstore,vecload,vecsimple,store,load,*,vecsimple,vecsimple,*,vecstore,vecload")])
+  [(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
@@ -202,71 +230,27 @@
 ;; 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.
@@ -1018,26 +1002,3 @@
   "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;
-})
Index: gcc/config/rs6000/rs6000.h
===================================================================
--- gcc/config/rs6000/rs6000.h	(revision 145474)
+++ gcc/config/rs6000/rs6000.h	(working copy)
@@ -1314,24 +1314,16 @@ 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) == 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[];
Index: gcc/config/rs6000/altivec.md
===================================================================
--- gcc/config/rs6000/altivec.md	(revision 145474)
+++ gcc/config/rs6000/altivec.md	(working copy)
@@ -2677,27 +2677,3 @@
   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;
-})
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md	(revision 145475)
+++ gcc/config/rs6000/rs6000.md	(working copy)
@@ -226,6 +226,12 @@
 (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.


-- 
Michael Meissner, IBM
4 Technology Place Drive, MS 2203A, Westford, MA, 01886, USA
meissner@linux.vnet.ibm.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]