diff options
author | Alan Modra <amodra@gmail.com> | 2016-03-31 06:24:40 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2016-03-31 06:24:40 +0000 |
commit | 4aad210d64334f6cc850e3196fcb26fd0fef5066 (patch) | |
tree | e9885fb2cfdfd774d17a770b6d696bf9f785be4c | |
parent | 745e6dfeafc3659324c3bdc9ec2415874fec3aa3 (diff) |
[RS6000] reload_vsx_from_gprsf splitter
This is PR68973 part 2, caused by the reload_vsx_from_gprsf splitter
emitting an invalid move. Part 1 deferred for branch until it is
proven that the reload change is necessary.
Backport from mainline
2016-02-16 Alan Modra <amodra@gmail.com>
PR target/68973
* config/rs6000/rs6000.md (reload_vsx_from_gprsf): Rewrite splitter.
(p8_mtvsrd_df, p8_mtvsrd_sf): New.
(p8_mtvsrd_1, p8_mtvsrd_2): Delete.
(p8_mtvsrwz): New.
(p8_mtvsrwz_1, p8_mtvsrwz_2): Delete.
(p8_xxpermdi_<mode>): Take two DF inputs rather than one TF.
(p8_fmrgow_<mode>): Likewise.
(reload_vsx_from_gpr<mode>): Adjust for above. Use "wa" for
clobber constraint.
(reload_fpr_from_gpr<mode>): Adjust for above. Use "d" for
op0 constraint.
(reload_vsx_from_gprsf): Use p8_mtvsrd_sf rather than attempting
to use movdi_internal64. Remove op0_di.
* config/rs6000/vsx.md (vsx_xscvspdpn_directmove): Make op1 SFmode.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-5-branch@234608 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 92 | ||||
-rw-r--r-- | gcc/config/rs6000/vsx.md | 2 |
3 files changed, 63 insertions, 51 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bdfcd45cc57..724bb4465ab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2016-03-31 Alan Modra <amodra@gmail.com> + + Backport from mainline + 2016-02-16 Alan Modra <amodra@gmail.com> + PR target/68973 + * config/rs6000/rs6000.md (reload_vsx_from_gprsf): Rewrite splitter. + (p8_mtvsrd_df, p8_mtvsrd_sf): New. + (p8_mtvsrd_1, p8_mtvsrd_2): Delete. + (p8_mtvsrwz): New. + (p8_mtvsrwz_1, p8_mtvsrwz_2): Delete. + (p8_xxpermdi_<mode>): Take two DF inputs rather than one TF. + (p8_fmrgow_<mode>): Likewise. + (reload_vsx_from_gpr<mode>): Adjust for above. Use "wa" for + clobber constraint. + (reload_fpr_from_gpr<mode>): Adjust for above. Use "d" for + op0 constraint. + (reload_vsx_from_gprsf): Use p8_mtvsrd_sf rather than attempting + to use movdi_internal64. Remove op0_di. + * config/rs6000/vsx.md (vsx_xscvspdpn_directmove): Make op1 SFmode. + 2016-03-30 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> Backport from mainline diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 69c662db96a..7720e9c71c7 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -8739,38 +8739,28 @@ ;; value, since it is allocated in reload and not all of the flow information ;; is setup for it. We have two patterns to do the two moves between gprs and ;; fprs. There isn't a dependancy between the two, but we could potentially -;; schedule other instructions between the two instructions. TFmode is -;; currently limited to traditional FPR registers. If/when this is changed, we -;; will need to revist %L to make sure it works with VSX registers, or add an -;; %x version of %L. +;; schedule other instructions between the two instructions. (define_insn "p8_fmrgow_<mode>" [(set (match_operand:FMOVE64X 0 "register_operand" "=d") - (unspec:FMOVE64X [(match_operand:TF 1 "register_operand" "d")] + (unspec:FMOVE64X [ + (match_operand:DF 1 "register_operand" "d") + (match_operand:DF 2 "register_operand" "d")] UNSPEC_P8V_FMRGOW))] "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" - "fmrgow %0,%1,%L1" + "fmrgow %0,%1,%2" [(set_attr "type" "vecperm")]) -(define_insn "p8_mtvsrwz_1" - [(set (match_operand:TF 0 "register_operand" "=d") - (unspec:TF [(match_operand:SI 1 "register_operand" "r")] +(define_insn "p8_mtvsrwz" + [(set (match_operand:DF 0 "register_operand" "=d") + (unspec:DF [(match_operand:SI 1 "register_operand" "r")] UNSPEC_P8V_MTVSRWZ))] "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "mtvsrwz %x0,%1" [(set_attr "type" "mftgpr")]) -(define_insn "p8_mtvsrwz_2" - [(set (match_operand:TF 0 "register_operand" "+d") - (unspec:TF [(match_dup 0) - (match_operand:SI 1 "register_operand" "r")] - UNSPEC_P8V_MTVSRWZ))] - "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" - "mtvsrwz %L0,%1" - [(set_attr "type" "mftgpr")]) - (define_insn_and_split "reload_fpr_from_gpr<mode>" - [(set (match_operand:FMOVE64X 0 "register_operand" "=ws") + [(set (match_operand:FMOVE64X 0 "register_operand" "=d") (unspec:FMOVE64X [(match_operand:FMOVE64X 1 "register_operand" "r")] UNSPEC_P8V_RELOAD_FROM_GPR)) (clobber (match_operand:TF 2 "register_operand" "=d"))] @@ -8781,42 +8771,36 @@ { rtx dest = operands[0]; rtx src = operands[1]; - rtx tmp = operands[2]; + rtx tmp_hi = simplify_gen_subreg (DFmode, operands[2], TFmode, 0); + rtx tmp_lo = simplify_gen_subreg (DFmode, operands[2], TFmode, 8); rtx gpr_hi_reg = gen_highpart (SImode, src); rtx gpr_lo_reg = gen_lowpart (SImode, src); - emit_insn (gen_p8_mtvsrwz_1 (tmp, gpr_hi_reg)); - emit_insn (gen_p8_mtvsrwz_2 (tmp, gpr_lo_reg)); - emit_insn (gen_p8_fmrgow_<mode> (dest, tmp)); + emit_insn (gen_p8_mtvsrwz (tmp_hi, gpr_hi_reg)); + emit_insn (gen_p8_mtvsrwz (tmp_lo, gpr_lo_reg)); + emit_insn (gen_p8_fmrgow_<mode> (dest, tmp_hi, tmp_lo)); DONE; } [(set_attr "length" "12") (set_attr "type" "three")]) ;; Move 128 bit values from GPRs to VSX registers in 64-bit mode -(define_insn "p8_mtvsrd_1" - [(set (match_operand:TF 0 "register_operand" "=ws") - (unspec:TF [(match_operand:DI 1 "register_operand" "r")] +(define_insn "p8_mtvsrd_df" + [(set (match_operand:DF 0 "register_operand" "=wa") + (unspec:DF [(match_operand:DI 1 "register_operand" "r")] UNSPEC_P8V_MTVSRD))] "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" - "mtvsrd %0,%1" - [(set_attr "type" "mftgpr")]) - -(define_insn "p8_mtvsrd_2" - [(set (match_operand:TF 0 "register_operand" "+ws") - (unspec:TF [(match_dup 0) - (match_operand:DI 1 "register_operand" "r")] - UNSPEC_P8V_MTVSRD))] - "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" - "mtvsrd %L0,%1" + "mtvsrd %x0,%1" [(set_attr "type" "mftgpr")]) (define_insn "p8_xxpermdi_<mode>" [(set (match_operand:FMOVE128_GPR 0 "register_operand" "=wa") - (unspec:FMOVE128_GPR [(match_operand:TF 1 "register_operand" "ws")] - UNSPEC_P8V_XXPERMDI))] + (unspec:FMOVE128_GPR [ + (match_operand:DF 1 "register_operand" "wa") + (match_operand:DF 2 "register_operand" "wa")] + UNSPEC_P8V_XXPERMDI))] "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" - "xxpermdi %x0,%1,%L1,0" + "xxpermdi %x0,%x1,%x2,0" [(set_attr "type" "vecperm")]) (define_insn_and_split "reload_vsx_from_gpr<mode>" @@ -8824,7 +8808,7 @@ (unspec:FMOVE128_GPR [(match_operand:FMOVE128_GPR 1 "register_operand" "r")] UNSPEC_P8V_RELOAD_FROM_GPR)) - (clobber (match_operand:TF 2 "register_operand" "=ws"))] + (clobber (match_operand:TF 2 "register_operand" "=wa"))] "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "#" "&& reload_completed" @@ -8832,13 +8816,18 @@ { rtx dest = operands[0]; rtx src = operands[1]; - rtx tmp = operands[2]; + /* You might think that we could use op0 as one temp and a DF clobber + as op2, but you'd be wrong. Secondary reload move patterns don't + check for overlap of the clobber and the destination. */ + rtx tmp_hi = simplify_gen_subreg (DFmode, operands[2], TFmode, 0); + rtx tmp_lo = simplify_gen_subreg (DFmode, operands[2], TFmode, 8); rtx gpr_hi_reg = gen_highpart (DImode, src); rtx gpr_lo_reg = gen_lowpart (DImode, src); - emit_insn (gen_p8_mtvsrd_1 (tmp, gpr_hi_reg)); - emit_insn (gen_p8_mtvsrd_2 (tmp, gpr_lo_reg)); - emit_insn (gen_p8_xxpermdi_<mode> (dest, tmp)); + emit_insn (gen_p8_mtvsrd_df (tmp_hi, gpr_hi_reg)); + emit_insn (gen_p8_mtvsrd_df (tmp_lo, gpr_lo_reg)); + emit_insn (gen_p8_xxpermdi_<mode> (dest, tmp_hi, tmp_lo)); + DONE; } [(set_attr "length" "12") (set_attr "type" "three")]) @@ -8855,6 +8844,13 @@ ;; Move SFmode to a VSX from a GPR register. Because scalar floating point ;; type is stored internally as double precision in the VSX registers, we have ;; to convert it from the vector format. +(define_insn "p8_mtvsrd_sf" + [(set (match_operand:SF 0 "register_operand" "=wa") + (unspec:SF [(match_operand:DI 1 "register_operand" "r")] + UNSPEC_P8V_MTVSRD))] + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "mtvsrd %x0,%1" + [(set_attr "type" "mftgpr")]) (define_insn_and_split "reload_vsx_from_gprsf" [(set (match_operand:SF 0 "register_operand" "=wa") @@ -8869,16 +8865,12 @@ rtx op0 = operands[0]; rtx op1 = operands[1]; rtx op2 = operands[2]; - /* Also use the destination register to hold the unconverted DImode value. - This is conceptually a separate value from OP0, so we use gen_rtx_REG - rather than simplify_gen_subreg. */ - rtx op0_di = gen_rtx_REG (DImode, REGNO (op0)); rtx op1_di = simplify_gen_subreg (DImode, op1, SFmode, 0); /* Move SF value to upper 32-bits for xscvspdpn. */ emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32))); - emit_move_insn (op0_di, op2); - emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0_di)); + emit_insn (gen_p8_mtvsrd_sf (op0, op2)); + emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0)); DONE; } [(set_attr "length" "8") diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index d7a235e9137..f2abdcd846a 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -1354,7 +1354,7 @@ ;; Used by direct move to move a SFmode value from GPR to VSX register (define_insn "vsx_xscvspdpn_directmove" [(set (match_operand:SF 0 "vsx_register_operand" "=wa") - (unspec:SF [(match_operand:DI 1 "vsx_register_operand" "wa")] + (unspec:SF [(match_operand:SF 1 "vsx_register_operand" "wa")] UNSPEC_VSX_CVSPDPN))] "TARGET_XSCVSPDPN" "xscvspdpn %x0,%x1" |