Commit b306ab3a by Alan Modra Committed by Alan Modra

[RS6000] reload_vsx_from_gprsf splitter

This is PR68973 part 2, caused by the reload_vsx_from_gprsf splitter
emitting an invalid move.  The patch also fixes uses of TFmode, which
cannot now be assumed to be IBM double-double.

	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>): Make clobber IF.  Adjust for above
	changes.
	(reload_fpr_from_gpr<mode>): Similarly. 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.

From-SVN: r233438
parent a16bdb4e
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>): Make clobber IF. Adjust for above
changes.
(reload_fpr_from_gpr<mode>): Similarly. 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-02-15 Evandro Menezes <e.menezes@samsung.com> 2016-02-15 Evandro Menezes <e.menezes@samsung.com>
Add support for the FCCMP insn types Add support for the FCCMP insn types
* config/aarch64/aarch64.md (fccmp): Change insn type. * config/aarch64/aarch64.md (fccmp): Change insn type.
......
...@@ -7488,41 +7488,31 @@ ...@@ -7488,41 +7488,31 @@
;; value, since it is allocated in reload and not all of the flow information ;; 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 ;; 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 ;; fprs. There isn't a dependancy between the two, but we could potentially
;; schedule other instructions between the two instructions. TFmode is ;; schedule other instructions between the two instructions.
;; 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.
(define_insn "p8_fmrgow_<mode>" (define_insn "p8_fmrgow_<mode>"
[(set (match_operand:FMOVE64X 0 "register_operand" "=d") [(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))] UNSPEC_P8V_FMRGOW))]
"!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"fmrgow %0,%1,%L1" "fmrgow %0,%1,%2"
[(set_attr "type" "vecperm")]) [(set_attr "type" "vecperm")])
(define_insn "p8_mtvsrwz_1" (define_insn "p8_mtvsrwz"
[(set (match_operand:TF 0 "register_operand" "=d") [(set (match_operand:DF 0 "register_operand" "=d")
(unspec:TF [(match_operand:SI 1 "register_operand" "r")] (unspec:DF [(match_operand:SI 1 "register_operand" "r")]
UNSPEC_P8V_MTVSRWZ))] UNSPEC_P8V_MTVSRWZ))]
"!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"mtvsrwz %x0,%1" "mtvsrwz %x0,%1"
[(set_attr "type" "mftgpr")]) [(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>" (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:FMOVE64X [(match_operand:FMOVE64X 1 "register_operand" "r")]
UNSPEC_P8V_RELOAD_FROM_GPR)) UNSPEC_P8V_RELOAD_FROM_GPR))
(clobber (match_operand:TF 2 "register_operand" "=d"))] (clobber (match_operand:IF 2 "register_operand" "=d"))]
"!TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "!TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"#" "#"
"&& reload_completed" "&& reload_completed"
...@@ -7530,42 +7520,36 @@ ...@@ -7530,42 +7520,36 @@
{ {
rtx dest = operands[0]; rtx dest = operands[0];
rtx src = operands[1]; rtx src = operands[1];
rtx tmp = operands[2]; rtx tmp_hi = simplify_gen_subreg (DFmode, operands[2], IFmode, 0);
rtx tmp_lo = simplify_gen_subreg (DFmode, operands[2], IFmode, 8);
rtx gpr_hi_reg = gen_highpart (SImode, src); rtx gpr_hi_reg = gen_highpart (SImode, src);
rtx gpr_lo_reg = gen_lowpart (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 (tmp_hi, gpr_hi_reg));
emit_insn (gen_p8_mtvsrwz_2 (tmp, gpr_lo_reg)); emit_insn (gen_p8_mtvsrwz (tmp_lo, gpr_lo_reg));
emit_insn (gen_p8_fmrgow_<mode> (dest, tmp)); emit_insn (gen_p8_fmrgow_<mode> (dest, tmp_hi, tmp_lo));
DONE; DONE;
} }
[(set_attr "length" "12") [(set_attr "length" "12")
(set_attr "type" "three")]) (set_attr "type" "three")])
;; Move 128 bit values from GPRs to VSX registers in 64-bit mode ;; Move 128 bit values from GPRs to VSX registers in 64-bit mode
(define_insn "p8_mtvsrd_1" (define_insn "p8_mtvsrd_df"
[(set (match_operand:TF 0 "register_operand" "=ws") [(set (match_operand:DF 0 "register_operand" "=wa")
(unspec:TF [(match_operand:DI 1 "register_operand" "r")] (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))] UNSPEC_P8V_MTVSRD))]
"TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"mtvsrd %L0,%1" "mtvsrd %x0,%1"
[(set_attr "type" "mftgpr")]) [(set_attr "type" "mftgpr")])
(define_insn "p8_xxpermdi_<mode>" (define_insn "p8_xxpermdi_<mode>"
[(set (match_operand:FMOVE128_GPR 0 "register_operand" "=wa") [(set (match_operand:FMOVE128_GPR 0 "register_operand" "=wa")
(unspec:FMOVE128_GPR [(match_operand:TF 1 "register_operand" "ws")] (unspec:FMOVE128_GPR [
UNSPEC_P8V_XXPERMDI))] (match_operand:DF 1 "register_operand" "wa")
(match_operand:DF 2 "register_operand" "wa")]
UNSPEC_P8V_XXPERMDI))]
"TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"xxpermdi %x0,%1,%L1,0" "xxpermdi %x0,%x1,%x2,0"
[(set_attr "type" "vecperm")]) [(set_attr "type" "vecperm")])
(define_insn_and_split "reload_vsx_from_gpr<mode>" (define_insn_and_split "reload_vsx_from_gpr<mode>"
...@@ -7573,7 +7557,7 @@ ...@@ -7573,7 +7557,7 @@
(unspec:FMOVE128_GPR (unspec:FMOVE128_GPR
[(match_operand:FMOVE128_GPR 1 "register_operand" "r")] [(match_operand:FMOVE128_GPR 1 "register_operand" "r")]
UNSPEC_P8V_RELOAD_FROM_GPR)) UNSPEC_P8V_RELOAD_FROM_GPR))
(clobber (match_operand:TF 2 "register_operand" "=ws"))] (clobber (match_operand:IF 2 "register_operand" "=wa"))]
"TARGET_POWERPC64 && TARGET_DIRECT_MOVE" "TARGET_POWERPC64 && TARGET_DIRECT_MOVE"
"#" "#"
"&& reload_completed" "&& reload_completed"
...@@ -7581,13 +7565,17 @@ ...@@ -7581,13 +7565,17 @@
{ {
rtx dest = operands[0]; rtx dest = operands[0];
rtx src = operands[1]; 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], IFmode, 0);
rtx tmp_lo = simplify_gen_subreg (DFmode, operands[2], IFmode, 8);
rtx gpr_hi_reg = gen_highpart (DImode, src); rtx gpr_hi_reg = gen_highpart (DImode, src);
rtx gpr_lo_reg = gen_lowpart (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_df (tmp_hi, gpr_hi_reg));
emit_insn (gen_p8_mtvsrd_2 (tmp, gpr_lo_reg)); emit_insn (gen_p8_mtvsrd_df (tmp_lo, gpr_lo_reg));
emit_insn (gen_p8_xxpermdi_<mode> (dest, tmp)); emit_insn (gen_p8_xxpermdi_<mode> (dest, tmp_hi, tmp_lo));
DONE; DONE;
} }
[(set_attr "length" "12") [(set_attr "length" "12")
...@@ -7608,6 +7596,13 @@ ...@@ -7608,6 +7596,13 @@
;; Move SFmode to a VSX from a GPR register. Because scalar floating point ;; 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 ;; type is stored internally as double precision in the VSX registers, we have
;; to convert it from the vector format. ;; 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" (define_insn_and_split "reload_vsx_from_gprsf"
[(set (match_operand:SF 0 "register_operand" "=wa") [(set (match_operand:SF 0 "register_operand" "=wa")
...@@ -7622,16 +7617,12 @@ ...@@ -7622,16 +7617,12 @@
rtx op0 = operands[0]; rtx op0 = operands[0];
rtx op1 = operands[1]; rtx op1 = operands[1];
rtx op2 = operands[2]; 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); rtx op1_di = simplify_gen_subreg (DImode, op1, SFmode, 0);
/* Move SF value to upper 32-bits for xscvspdpn. */ /* Move SF value to upper 32-bits for xscvspdpn. */
emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32))); emit_insn (gen_ashldi3 (op2, op1_di, GEN_INT (32)));
emit_move_insn (op0_di, op2); emit_insn (gen_p8_mtvsrd_sf (op0, op2));
emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0_di)); emit_insn (gen_vsx_xscvspdpn_directmove (op0, op0));
DONE; DONE;
} }
[(set_attr "length" "8") [(set_attr "length" "8")
......
...@@ -1521,7 +1521,7 @@ ...@@ -1521,7 +1521,7 @@
;; Used by direct move to move a SFmode value from GPR to VSX register ;; Used by direct move to move a SFmode value from GPR to VSX register
(define_insn "vsx_xscvspdpn_directmove" (define_insn "vsx_xscvspdpn_directmove"
[(set (match_operand:SF 0 "vsx_register_operand" "=wa") [(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))] UNSPEC_VSX_CVSPDPN))]
"TARGET_XSCVSPDPN" "TARGET_XSCVSPDPN"
"xscvspdpn %x0,%x1" "xscvspdpn %x0,%x1"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment