diff options
author | Hartmut Penner <hpenner@de.ibm.com> | 2003-06-30 13:30:45 +0000 |
---|---|---|
committer | Hartmut Penner <hpenner@gcc.gnu.org> | 2003-06-30 13:30:45 +0000 |
commit | 46c07df8a17da325bab22f5f900e37fc2118e446 (patch) | |
tree | 52ab0108b953bee6751dd6f9ef466762f1ae4dcf | |
parent | 8fca31a21e9b6c1bfae0bd267b3a325d51155c53 (diff) | |
download | gcc-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/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/rs6000/altivec.md | 132 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 92 |
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. */ |