]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[RS6000] reload_vsx_from_gprsf splitter
authorAlan Modra <amodra@gmail.com>
Thu, 31 Mar 2016 06:26:02 +0000 (16:56 +1030)
committerAlan Modra <amodra@gcc.gnu.org>
Thu, 31 Mar 2016 06:26:02 +0000 (16:56 +1030)
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.

From-SVN: r234609

gcc/ChangeLog
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/vsx.md

index 1f87f09e29df425d638c93b93daf57e455cc5f57..b0db665b472bac69180669c965f56f3c0e305732 100644 (file)
@@ -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-29  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        PR target/69875
index 94637f72187e6d8b49df2eb69b229323b3ccf9a3..bd43b1bd08a025387a2ca469ed0086232a3d093e 100644 (file)
 ;; 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"))]
 {
   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>"
        (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"
 {
   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")])
 ;; 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")
   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")
index 9aaf06428049367dd84a1e91160b7e699e1260d5..985077b82a65f7e137ac29357b1be0f8d4b36ef9 100644 (file)
 ;; 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"