aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHartmut Penner <hpenner@de.ibm.com>2003-06-30 13:30:45 +0000
committerHartmut Penner <hpenner@gcc.gnu.org>2003-06-30 13:30:45 +0000
commit46c07df8a17da325bab22f5f900e37fc2118e446 (patch)
tree52ab0108b953bee6751dd6f9ef466762f1ae4dcf
parent8fca31a21e9b6c1bfae0bd267b3a325d51155c53 (diff)
downloadgcc-46c07df8a17da325bab22f5f900e37fc2118e446.zip
gcc-46c07df8a17da325bab22f5f900e37fc2118e446.tar.gz
gcc-46c07df8a17da325bab22f5f900e37fc2118e446.tar.bz2
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
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config/rs6000/altivec.md132
-rw-r--r--gcc/config/rs6000/rs6000-protos.h2
-rw-r--r--gcc/config/rs6000/rs6000.c92
4 files changed, 222 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9b559e5..b78d3d8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+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.
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index d182744..5b1dc36 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -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")
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 051da02..327ab1f 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -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,
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 524772b..df5d775 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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. */