From: Hartmut Penner Date: Mon, 30 Jun 2003 13:30:45 +0000 (+0000) Subject: rs6000.c (rs6000_split_altivec_in_gprs): New function. X-Git-Tag: releases/gcc-3.4.0~5321 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46c07df8a17da325bab22f5f900e37fc2118e446;p=thirdparty%2Fgcc.git rs6000.c (rs6000_split_altivec_in_gprs): New function. 2003-06-30 Hartmut Penner * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9b559e5fb9f3..b78d3d8aa949 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2003-06-30 Hartmut Penner + + * 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 * defaults.h (PUSH_ARGS_REVERSED): Define default here. diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index d182744ab785..5b1dc3692929 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 051da0206a7e..327ab1fa216c 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 524772b5ffe7..df5d775ee16a 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. */