From 3a1f863f50d8b632272aef9a16c1f3e38157fa60 Mon Sep 17 00:00:00 2001 From: David Edelsohn Date: Tue, 23 Sep 2003 02:03:55 +0000 Subject: [PATCH] rs6000.c (altivec_in_gprs_p): Rename to ... * config/rs6000/rs6000.c (altivec_in_gprs_p): Rename to ... (gpr_or_gpr_p): Change to bool. (rs6000_split_altivec_in_gprs): Rename to ... (rs6000_split_multireg_move): Add support for update addressing. * config/rs6000/rs6000-protos.h: Same. * config/rs6000/altivec.md: Same. * config/rs6000/rs6000.md (movdi_internal32): Use new splitter for multiple GPRs. (movti): Remove TARGET_STRING || TARGET_POWERPC64 final condition. (movti_power): Use new splitter for multiple GPRs. (movti_string): Same. (movti_ppc64): Same. Co-Authored-By: Hartmut Penner From-SVN: r71673 --- gcc/ChangeLog | 16 +++ gcc/config/rs6000/altivec.md | 32 +++--- gcc/config/rs6000/rs6000-protos.h | 8 +- gcc/config/rs6000/rs6000.c | 130 +++++++++++++++------- gcc/config/rs6000/rs6000.md | 172 +++++++++++------------------- 5 files changed, 194 insertions(+), 164 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a03deee37ed..a7b8b49bd62 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2003-09-22 David Edelsohn + Hartmut Penner + + * config/rs6000/rs6000.c (altivec_in_gprs_p): Rename to ... + (gpr_or_gpr_p): Change to bool. + (rs6000_split_altivec_in_gprs): Rename to ... + (rs6000_split_multireg_move): Add support for update addressing. + * config/rs6000/rs6000-protos.h: Same. + * config/rs6000/altivec.md: Same. + * config/rs6000/rs6000.md (movdi_internal32): Use new splitter for + multiple GPRs. + (movti): Remove TARGET_STRING || TARGET_POWERPC64 final condition. + (movti_power): Use new splitter for multiple GPRs. + (movti_string): Same. + (movti_ppc64): Same. + 2003-09-22 Bob Wilson * config/xtensa/xtensa-protos.h: Convert to ISO C90. diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 5b1dc369292..2b58d60ab84 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -114,24 +114,24 @@ [(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])" + && gpr_or_gpr_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); + rs6000_split_multireg_move (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])" + && gpr_or_gpr_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); + rs6000_split_multireg_move (operands); }") (define_split @@ -176,24 +176,24 @@ [(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])" + && gpr_or_gpr_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); + rs6000_split_multireg_move (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])" + && gpr_or_gpr_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); + rs6000_split_multireg_move (operands); }") (define_split @@ -238,24 +238,24 @@ [(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])" + && gpr_or_gpr_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); + rs6000_split_multireg_move (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])" + && gpr_or_gpr_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); + rs6000_split_multireg_move (operands); }") (define_split @@ -300,24 +300,24 @@ [(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])" + && gpr_or_gpr_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); + rs6000_split_multireg_move (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])" + && gpr_or_gpr_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); + rs6000_split_multireg_move (operands); }") (define_insn "get_vrsave_internal" diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 8340c2b5931..021c40cc761 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -100,16 +100,16 @@ extern int includes_rldic_lshift_p (rtx, rtx); extern int includes_rldicr_lshift_p (rtx, rtx); extern int registers_ok_for_quad_peep (rtx, rtx); extern int addrs_ok_for_quad_peep (rtx, rtx); -extern int altivec_in_gprs_p (rtx, rtx); +extern bool gpr_or_gpr_p (rtx, rtx); extern enum reg_class secondary_reload_class (enum reg_class, - enum machine_mode, rtx); + enum machine_mode, rtx); extern int ccr_bit (rtx, int); extern int extract_MB (rtx); extern int extract_ME (rtx); extern void print_operand (FILE *, rtx, int); extern void print_operand_address (FILE *, rtx); extern enum rtx_code rs6000_reverse_condition (enum machine_mode, - enum rtx_code); + enum rtx_code); extern void rs6000_emit_sCOND (enum rtx_code, rtx); extern void rs6000_emit_cbranch (enum rtx_code, rtx); extern char * output_cbranch (rtx, const char *, int, rtx); @@ -125,7 +125,7 @@ extern int mfcr_operation (rtx, enum machine_mode); extern int mtcrf_operation (rtx, enum machine_mode); extern int lmw_operation (rtx, enum machine_mode); extern struct rtx_def *create_TOC_reference (rtx); -extern void rs6000_split_altivec_in_gprs (rtx *); +extern void rs6000_split_multireg_move (rtx *); extern void rs6000_emit_move (rtx, rtx, enum machine_mode); extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode); extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode, diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ae702fc012b..0b7be5ac5e4 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -2200,18 +2200,13 @@ small_data_operand (rtx op ATTRIBUTE_UNUSED, #endif } -/* Return 1 for all valid move insn operand combination involving altivec - vectors in gprs. */ +/* Return true if either operand is a general purpose register. */ -int -altivec_in_gprs_p (rtx op0, rtx op1) +bool +gpr_or_gpr_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; + return ((REG_P (op0) && INT_REGNO_P (REGNO (op0))) + || (REG_P (op1) && INT_REGNO_P (REGNO (op1)))); } @@ -9462,14 +9457,16 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1) emit_move_insn (dest, target); } -/* Called by altivec splitter. +/* Called by splitter for multireg moves. 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 + operands[2-n] : Destination slots + operands[n-m] : Source slots + where n = 2 + HARD_REGNO_NREGS (reg, GET_MODE (operands[0])) + m = 2 + 2 * HARD_REGNO_NREGS (reg, GET_MODE (operands[0])) - 1 Splits the move of operands[1] to operands[0]. This is done, if GPRs are one of the operands. In this case @@ -9479,10 +9476,13 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1) */ void -rs6000_split_altivec_in_gprs (rtx *operands) +rs6000_split_multireg_move (rtx *operands) { - int nregs, reg, i, j; + int nregs, reg, i, j, used_update = 0; enum machine_mode mode; + rtx dst = operands[0]; + rtx src = operands[1]; + rtx insn = 0; /* Calculate number to move (2/4 for 32/64 bit mode). */ @@ -9500,8 +9500,8 @@ rs6000_split_altivec_in_gprs (rtx *operands) for (i = 0; i < nregs; i++) { j--; - operands[i + 2] = operand_subword (operands[0], j, 0, mode); - operands[i + 2 + nregs] = + operands[i+2] = operand_subword (operands[0], j, 0, mode); + operands[i+2+nregs] = operand_subword (operands[1], j, 0, mode); } } @@ -9512,29 +9512,87 @@ rs6000_split_altivec_in_gprs (rtx *operands) 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]); + + if (GET_CODE (XEXP (operands[1], 0)) == PRE_INC + || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) + { + rtx delta_rtx; + breg = XEXP (XEXP (operands[1], 0), 0); + delta_rtx = GET_CODE (XEXP (operands[1], 0)) == PRE_INC + ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1]))) + : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[1]))); + insn = emit_insn (TARGET_32BIT + ? gen_addsi3 (breg, breg, delta_rtx) + : gen_adddi3 (breg, breg, delta_rtx)); + src = gen_rtx_MEM (mode, breg); + } + + /* We have now address involving an base register only. + If we use one of the registers to address memory, + we have change that register last. */ + + breg = (GET_CODE (XEXP (src, 0)) == PLUS + ? XEXP (XEXP (src, 0), 0) + : XEXP (src, 0)); + + if (!REG_P (breg)) + abort(); + + if (REGNO (breg) >= REGNO (dst) + && REGNO (breg) < REGNO (dst) + nregs) + j = REGNO (breg) - REGNO (dst); } + if (GET_CODE (operands[0]) == MEM) + { + rtx breg; + + if (GET_CODE (XEXP (operands[0], 0)) == PRE_INC + || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + { + rtx delta_rtx; + breg = XEXP (XEXP (operands[0], 0), 0); + delta_rtx = GET_CODE (XEXP (operands[0], 0)) == PRE_INC + ? GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0]))) + : GEN_INT (-GET_MODE_SIZE (GET_MODE (operands[0]))); + + /* We have to update the breg before doing the store. + Use store with update, if available. */ + + if (TARGET_UPDATE) + { + insn = emit_insn (TARGET_32BIT + ? gen_movsi_update (breg, breg, delta_rtx, + operand_subword (src, 0, 0, mode)) + : gen_movdi_update (breg, breg, delta_rtx, + operand_subword (src, 0, 0, mode))); + used_update = 1; + } + else + insn = emit_insn (TARGET_32BIT + ? gen_addsi3 (breg, breg, delta_rtx) + : gen_adddi3 (breg, breg, delta_rtx)); + dst = gen_rtx_MEM (mode, breg); + } + } + for (i = 0; i < nregs; i++) - { - /* Calculate index to next subword. */ - j++; - if (j == nregs) - j = 0; + { + /* 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); + operands[i+2] = operand_subword (dst, j, 0, mode); + operands[i+2+nregs] = operand_subword (src, j, 0, mode); - } + if (j == 0 && used_update) + { + /* Already emited move of first word by + store with update -> emit dead insn instead (r := r). */ + operands[i+2] = operands[i+2+nregs]; + } + } } } diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 5f91155179f..d1264c68fd6 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -8462,25 +8462,9 @@ default: abort (); case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; case 1: - /* If the low-address word is used in the address, we must load it - last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is known to be - dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\"; - else - return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\"; case 2: - return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\"; + return \"#\"; case 3: return \"fmr %0,%1\"; case 4: @@ -8495,8 +8479,7 @@ return \"#\"; } }" - [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*") - (set_attr "length" "8,8,8,4,4,4,8,12,8,12,16")]) + [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")]) (define_split [(set (match_operand:DI 0 "gpc_reg_operand" "") @@ -8535,6 +8518,17 @@ operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); }") +(define_split + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (match_operand:DI 1 "input_operand" ""))] + "reload_completed && !TARGET_POWERPC64 + && gpr_or_gpr_p (operands[0], operands[1])" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] +"{ + rs6000_split_multireg_move (operands); +}") + (define_split [(set (match_operand:TI 0 "gpc_reg_operand" "") (match_operand:TI 1 "const_double_operand" ""))] @@ -8677,7 +8671,7 @@ [(parallel [(set (match_operand:TI 0 "general_operand" "") (match_operand:TI 1 "general_operand" "")) (clobber (scratch:SI))])] - "TARGET_STRING || TARGET_POWERPC64" + "" "{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }") ;; We say that MQ is clobbered in the last alternative because the first @@ -8685,11 +8679,12 @@ ;; while the 2nd alternative would not. We put memory cases first so they ;; are preferred. Otherwise, we'd try to reload the output instead of ;; giving the SCRATCH mq. + (define_insn "*movti_power" [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r") (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m")) (clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))] - "TARGET_STRING && TARGET_POWER && ! TARGET_POWERPC64 + "TARGET_POWER && ! TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))" "* { @@ -8699,18 +8694,12 @@ abort (); case 0: - return \"{stsi|stswi} %1,%P0,16\"; + if (TARGET_STRING) + return \"{stsi|stswi} %1,%P0,16\"; case 1: - return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\"; + return \"#\"; case 2: - /* Normally copy registers with lowest numbered register copied first. - But copy in the other order if the first register of the output - is the second, third, or fourth register in the input. */ - if (REGNO (operands[0]) >= REGNO (operands[1]) + 1 - && REGNO (operands[0]) <= REGNO (operands[1]) + 3) - return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\"; + return \"#\"; case 3: /* If the address is not used in the output, we can use lsi. Otherwise, fall through to generating four loads. */ @@ -8718,29 +8707,15 @@ return \"{lsi|lswi} %0,%P1,16\"; /* ... fall through ... */ case 4: - /* If the address register is the same as the register for the lowest- - addressed word, load it last. Similarly for the next two words. - Otherwise load lowest address to highest. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %0,%1\"; - else if (refers_to_regno_p (REGNO (operands[0]) + 1, - REGNO (operands[0]) + 2, operands[1], 0)) - return \"{l|lwz} %0,%1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %L0,%L1\"; - else if (refers_to_regno_p (REGNO (operands[0]) + 2, - REGNO (operands[0]) + 3, operands[1], 0)) - return \"{l|lwz} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Z0,%Z1\;{l|lwz} %Y0,%Y1\"; - else - return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\"; + return \"#\"; } }" - [(set_attr "type" "store,store,*,load,load") - (set_attr "length" "4,16,16,4,16")]) + [(set_attr "type" "store,store,*,load,load")]) (define_insn "*movti_string" [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r") (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))] - "TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64 + "! TARGET_POWER && ! TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))" "* { @@ -8748,81 +8723,62 @@ { default: abort (); - case 0: - return \"{stsi|stswi} %1,%P0,16\"; + if (TARGET_STRING) + return \"{stsi|stswi} %1,%P0,16\"; case 1: - return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\;{st|stw} %Y1,%Y0\;{st|stw} %Z1,%Z0\"; + return \"#\"; case 2: - /* Normally copy registers with lowest numbered register copied first. - But copy in the other order if the first register of the output - is the second, third, or fourth register in the input. */ - if (REGNO (operands[0]) >= REGNO (operands[1]) + 1 - && REGNO (operands[0]) <= REGNO (operands[1]) + 3) - return \"mr %Z0,%Z1\;mr %Y0,%Y1\;mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\"; + return \"#\"; case 3: /* If the address is not used in the output, we can use lsi. Otherwise, fall through to generating four loads. */ - if (! reg_overlap_mentioned_p (operands[0], operands[1])) + if (TARGET_STRING + && ! reg_overlap_mentioned_p (operands[0], operands[1])) return \"{lsi|lswi} %0,%P1,16\"; /* ... fall through ... */ case 4: - /* If the address register is the same as the register for the lowest- - addressed word, load it last. Similarly for the next two words. - Otherwise load lowest address to highest. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %0,%1\"; - else if (refers_to_regno_p (REGNO (operands[0]) + 1, - REGNO (operands[0]) + 2, operands[1], 0)) - return \"{l|lwz} %0,%1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\;{l|lwz} %L0,%L1\"; - else if (refers_to_regno_p (REGNO (operands[0]) + 2, - REGNO (operands[0]) + 3, operands[1], 0)) - return \"{l|lwz} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Z0,%Z1\;{l|lwz} %Y0,%Y1\"; - else - return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\;{l|lwz} %Y0,%Y1\;{l|lwz} %Z0,%Z1\"; + return \"#\"; } }" - [(set_attr "type" "store,store,*,load,load") - (set_attr "length" "4,16,16,4,16")]) + [(set_attr "type" "store,store,*,load,load")]) (define_insn "*movti_ppc64" - [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m") - (match_operand:TI 1 "input_operand" "r,m,r"))] + [(set (match_operand:TI 0 "nonimmediate_operand" "=r,m,r") + (match_operand:TI 1 "input_operand" "r,r,o"))] "TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))" - "* -{ - switch (which_alternative) - { - default: - abort (); - case 0: - /* We normally copy the low-numbered register first. However, if - the first register operand 0 is the same as the second register of - operand 1, we must copy in the opposite order. */ - if (REGNO (operands[0]) == REGNO (operands[1]) + 1) - return \"mr %L0,%L1\;mr %0,%1\"; - else - return \"mr %0,%1\;mr %L0,%L1\"; - case 1: - /* If the low-address word is used in the address, we must load it - last. Otherwise, load it first. Note that we cannot have - auto-increment in that case since the address register is known to be - dead. */ - if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, - operands[1], 0)) - return \"ld %L0,%L1\;ld %0,%1\"; - else - return \"ld%U1 %0,%1\;ld %L0,%L1\"; - case 2: - return \"std%U0 %1,%0\;std %L1,%L0\"; - } -}" - [(set_attr "type" "*,load,store") - (set_attr "length" "8,8,8")]) + "@ + # + # + #" + [(set_attr "type" "*,load,store")]) + +(define_split + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "input_operand" ""))] + "reload_completed && TARGET_POWERPC64 + && gpr_or_gpr_p (operands[0], operands[1])" + [(set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 5))] +"{ + rs6000_split_multireg_move (operands); +}") + +(define_split + [(set (match_operand:TI 0 "nonimmediate_operand" "") + (match_operand:TI 1 "input_operand" ""))] + "reload_completed && !TARGET_POWERPC64 + && gpr_or_gpr_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_multireg_move (operands); +}") + + (define_expand "load_multiple" [(match_par_dup 3 [(set (match_operand:SI 0 "" "") -- 2.30.2