Commit 46c07df8 by Hartmut Penner Committed by Hartmut Penner

rs6000.c (rs6000_split_altivec_in_gprs): New function.

2003-06-30 Hartmut Penner  <hpenner@de.ibm.com>

        * config/rs6000/rs6000.c (rs6000_split_altivec_in_gprs): New function.
        (altivec_in_gprs_p): New function.

	* config/rs6000/rs6000-protos (rs6000_split_altivec_in_gprs): New
	prototype.
	(altivec_in_gprs_p): New prototype.

	* config/rs6000/altivec.md (*movv4si_internal): Change
	multi-assembler alternative to '#'. Add postreload splitter to
	handle this cases.
	(*movv4hi_internal): Likewise.
	(*movv4qi_internal): Likewise.
	(*movv4sf_internal): Likewise.

From-SVN: r68704
parent 8fca31a2
2003-06-30 Hartmut Penner <hpenner@de.ibm.com>
* config/rs6000/rs6000.c (rs6000_split_altivec_in_gprs): New function.
(altivec_in_gprs_p): New function.
* config/rs6000/rs6000-protos (rs6000_split_altivec_in_gprs): New
prototype.
(altivec_in_gprs_p): New prototype.
* config/rs6000/altivec.md (*movv4si_internal): Change
multi-assembler alternative to '#'. Add postreload splitter to
handle this cases.
(*movv4hi_internal): Likewise.
(*movv4qi_internal): Likewise.
(*movv4sf_internal): Likewise.
2003-06-30 Jason Merrill <jason@redhat.com>
* defaults.h (PUSH_ARGS_REVERSED): Define default here.
......
......@@ -101,15 +101,38 @@
case 0: return \"stvx %1,%y0\";
case 1: return \"lvx %0,%y1\";
case 2: return \"vor %0,%1,%1\";
case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
case 3: return \"#\";
case 4: return \"#\";
case 5: return \"#\";
case 6: return output_vec_const_move (operands);
default: abort();
}
}"
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
(set_attr "length" "*,*,*,16,16,16,*")])
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
(define_split
[(set (match_operand:V4SI 0 "nonimmediate_operand" "")
(match_operand:V4SI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
&& altivec_in_gprs_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"{
rs6000_split_altivec_in_gprs (operands);
}")
(define_split
[(set (match_operand:V4SI 0 "nonimmediate_operand" "")
(match_operand:V4SI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
&& altivec_in_gprs_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 6))
(set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))]
"{
rs6000_split_altivec_in_gprs (operands);
}")
(define_split
[(set (match_operand:V4SI 0 "altivec_register_operand" "")
......@@ -140,15 +163,38 @@
case 0: return \"stvx %1,%y0\";
case 1: return \"lvx %0,%y1\";
case 2: return \"vor %0,%1,%1\";
case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
case 3: return \"#\";
case 4: return \"#\";
case 5: return \"#\";
case 6: return output_vec_const_move (operands);
default: abort ();
}
}"
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
(set_attr "length" "*,*,*,16,16,16,*")])
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
(define_split
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
(match_operand:V8HI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
&& altivec_in_gprs_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"{
rs6000_split_altivec_in_gprs (operands);
}")
(define_split
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
(match_operand:V8HI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
&& altivec_in_gprs_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 6))
(set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))]
"{
rs6000_split_altivec_in_gprs (operands);
}")
(define_split
[(set (match_operand:V8HI 0 "altivec_register_operand" "")
......@@ -179,15 +225,38 @@
case 0: return \"stvx %1,%y0\";
case 1: return \"lvx %0,%y1\";
case 2: return \"vor %0,%1,%1\";
case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
case 3: return \"#\";
case 4: return \"#\";
case 5: return \"#\";
case 6: return output_vec_const_move (operands);
default: abort ();
}
}"
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
(set_attr "length" "*,*,*,16,16,16,*")])
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
(define_split
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
(match_operand:V16QI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
&& altivec_in_gprs_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"{
rs6000_split_altivec_in_gprs (operands);
}")
(define_split
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
(match_operand:V16QI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
&& altivec_in_gprs_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 6))
(set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))]
"{
rs6000_split_altivec_in_gprs (operands);
}")
(define_split
[(set (match_operand:V16QI 0 "altivec_register_operand" "")
......@@ -218,15 +287,38 @@
case 0: return \"stvx %1,%y0\";
case 1: return \"lvx %0,%y1\";
case 2: return \"vor %0,%1,%1\";
case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
case 3: return \"#\";
case 4: return \"#\";
case 5: return \"#\";
case 6: return output_vec_const_move (operands);
default: abort ();
}
}"
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
(set_attr "length" "*,*,*,16,16,16,*")])
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
(define_split
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
(match_operand:V4SF 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64
&& altivec_in_gprs_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))]
"{
rs6000_split_altivec_in_gprs (operands);
}")
(define_split
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
(match_operand:V4SF 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64
&& altivec_in_gprs_p (operands[0], operands[1])"
[(set (match_dup 2) (match_dup 6))
(set (match_dup 3) (match_dup 7))
(set (match_dup 4) (match_dup 8))
(set (match_dup 5) (match_dup 9))]
"{
rs6000_split_altivec_in_gprs (operands);
}")
(define_insn "get_vrsave_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
......
......@@ -101,6 +101,7 @@ extern int includes_rldic_lshift_p PARAMS ((rtx, rtx));
extern int includes_rldicr_lshift_p PARAMS ((rtx, rtx));
extern int registers_ok_for_quad_peep PARAMS ((rtx, rtx));
extern int addrs_ok_for_quad_peep PARAMS ((rtx, rtx));
extern int altivec_in_gprs_p (rtx, rtx);
extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
enum machine_mode, rtx));
extern int ccr_bit PARAMS ((rtx, int));
......@@ -125,6 +126,7 @@ extern int mtcrf_operation PARAMS ((rtx, enum machine_mode));
extern int lmw_operation PARAMS ((rtx, enum machine_mode));
extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
extern void rs6000_emit_eh_toc_restore PARAMS ((rtx));
extern void rs6000_split_altivec_in_gprs (rtx *);
extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
extern rtx rs6000_legitimize_reload_address PARAMS ((rtx, enum machine_mode,
......
......@@ -2308,6 +2308,21 @@ small_data_operand (op, mode)
return 0;
#endif
}
/* Return 1 for all valid move insn operand combination involving altivec
vectors in gprs. */
int
altivec_in_gprs_p (rtx op0, rtx op1)
{
if (REG_P (op0) && REGNO_REG_CLASS (REGNO (op0)) == GENERAL_REGS)
return 1;
if (REG_P (op1) && REGNO_REG_CLASS (REGNO (op1)) == GENERAL_REGS)
return 1;
return 0;
}
/* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address. */
......@@ -9640,6 +9655,83 @@ rs6000_emit_minmax (dest, code, op0, op1)
if (target != dest)
emit_move_insn (dest, target);
}
/* Called by altivec splitter.
Input:
operands[0] : Destination of move
operands[1] : Source of move
noperands : Size of operands vector
Output:
operands[2-5] ([2-3] in 64 bit) : Destination slots
operands[6-9] ([4-5] in 64 bit) : Source slots
Splits the move of operands[1] to operands[0].
This is done, if GPRs are one of the operands. In this case
a sequence of simple move insns has to be issued. The sequence of these
move insns has to be done in correct order to avoid early clobber of the
base register or destructive overlap of registers.
*/
void
rs6000_split_altivec_in_gprs (rtx *operands)
{
int nregs, reg, i, j;
enum machine_mode mode;
/* Calculate number to move (2/4 for 32/64 bit mode). */
reg = REG_P (operands[0]) ? REGNO (operands[0]) : REGNO (operands[1]);
mode = GET_MODE (operands[0]);
nregs = HARD_REGNO_NREGS (reg, mode);
if (REG_P (operands[1])
&& REG_P (operands[0])
&& (REGNO (operands[1]) < REGNO (operands[0])))
{
/* Move register range backwards, if we have destructive overlap. */
j = nregs;
for (i = 0; i < nregs; i++)
{
j--;
operands[i + 2] = operand_subword (operands[0], j, 0, mode);
operands[i + 2 + nregs] =
operand_subword (operands[1], j, 0, mode);
}
}
else
{
j = -1;
if (GET_CODE (operands[1]) == MEM)
{
rtx breg;
/* We have offsettable addresses only. If we use one of the
registers to address memory, we have change that register last. */
breg = GET_CODE (XEXP (operands[1], 0)) == PLUS ?
XEXP (XEXP (operands[1], 0), 0) :
XEXP (operands[1], 0);
if (REGNO (breg) >= REGNO (operands[0])
&& REGNO (breg) < REGNO (operands[0]) + nregs)
j = REGNO (breg) - REGNO (operands[0]);
}
for (i = 0; i < nregs; i++)
{
/* Calculate index to next subword. */
j++;
if (j == nregs)
j = 0;
operands[i + 2] = operand_subword (operands[0], j, 0, mode);
operands[i + 2 + nregs] =
operand_subword (operands[1], j, 0, mode);
}
}
}
/* This page contains routines that are used to determine what the
function prologue and epilogue code will do and write them out. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment