From: Alan Modra Date: Thu, 31 Mar 2016 06:26:02 +0000 (+1030) Subject: [RS6000] reload_vsx_from_gprsf splitter X-Git-Tag: releases/gcc-4.9.4~248 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d60e6a53fb0a75574558dd447a64e81bf559b498;p=thirdparty%2Fgcc.git [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 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_): Take two DF inputs rather than one TF. (p8_fmrgow_): Likewise. (reload_vsx_from_gpr): Adjust for above. Use "wa" for clobber constraint. (reload_fpr_from_gpr): 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1f87f09e29df..b0db665b472b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2016-03-31 Alan Modra + + Backport from mainline + 2016-02-16 Alan Modra + 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_): Take two DF inputs rather than one TF. + (p8_fmrgow_): Likewise. + (reload_vsx_from_gpr): Adjust for above. Use "wa" for + clobber constraint. + (reload_fpr_from_gpr): 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 PR target/69875 diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 94637f72187e..bd43b1bd08a0 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -9976,38 +9976,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_" [(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" - [(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"))] @@ -10018,42 +10008,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_ (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_ (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_" [(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" @@ -10061,7 +10045,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" @@ -10069,13 +10053,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_ (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_ (dest, tmp_hi, tmp_lo)); + DONE; } [(set_attr "length" "12") (set_attr "type" "three")]) @@ -10092,6 +10081,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") @@ -10106,16 +10102,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 9aaf06428049..985077b82a65 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -1353,7 +1353,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"