aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2016-03-31 06:24:40 +0000
committerAlan Modra <amodra@gmail.com>2016-03-31 06:24:40 +0000
commit4aad210d64334f6cc850e3196fcb26fd0fef5066 (patch)
treee9885fb2cfdfd774d17a770b6d696bf9f785be4c
parent745e6dfeafc3659324c3bdc9ec2415874fec3aa3 (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/ChangeLog20
-rw-r--r--gcc/config/rs6000/rs6000.md92
-rw-r--r--gcc/config/rs6000/vsx.md2
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"