This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[power7-meissner, committed] Rework store/load with update, Fix some reload issues
- From: Michael Meissner <meissner at linux dot vnet dot ibm dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 8 Apr 2009 16:42:06 -0400
- Subject: [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