This patch like the previous 2 pages combines the decimal and binary floating point moves, this time for 128-bit floating point.
In doing this patch, I discovered that I left out the code in the previous patch to enable the wg constraint to enable -mcpu=power6x to utilize the direct move instructions. So, I added the code in this patch, and also created a test to make sure that direct moves are generated in the future. I also added the reload helper for DDmode to rs6000_vector_reload that was missed in the last patch. This was harmless, since that is only used with an undocumented debug switch. Hopefully sometime in the future, I will scalar floating point to be able to be loaded in the upper 32 VSX registers that are overlaid over the Altivec registers. Like the previous 2 patches, I've bootstrapped this, and ran make check with no regressions. Is it ok to apply when GCC 4.9 opens up? I have one more patch in the insn combination to post, combining movdi on systems with normal floating point and with the power6 direct move instructions. [gcc] 2013-01-30 Michael Meissner <meiss...@linux.vnet.ibm.com> * config/rs6000/rs6000.c (rs6000_debug_reg_global): Print out wg constraint if -mdebug=reg. (rs6000_initi_hard_regno_mode_ok): Enable wg constraint if -mfpgpr. Enable using dd reload support if needed. * config/rs6000/dfp.md (movtd): Delete, combine with 128-bit binary and decimal floating point moves in rs6000.md. (movtd_internal): Likewise. * config/rs6000/rs6000.md (FMOVE128): Combine 128-bit binary and decimal floating point moves. (movtf): Likewise. (movtf_internal): Likewise. (mov<mode>_internal, TDmode/TFmode): Likewise. (movtf_softfloat): Likewise. (mov<mode>_softfloat, TDmode/TFmode): Likewise. [gcc/testsuite] 2013-01-30 Michael Meissner <meiss...@linux.vnet.ibm.com> * gcc.target/powerpc/mmfpgpr.c: New test. -- Michael Meissner, IBM 5 Technology Place Drive, M/S 2757, Westford, MA 01886-3141, USA meiss...@linux.vnet.ibm.com fax +1 (978) 399-6899
Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 195586) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1737,6 +1737,7 @@ rs6000_debug_reg_global (void) "wa reg_class = %s\n" "wd reg_class = %s\n" "wf reg_class = %s\n" + "wg reg_class = %s\n" "wl reg_class = %s\n" "ws reg_class = %s\n" "wx reg_class = %s\n" @@ -1748,6 +1749,7 @@ rs6000_debug_reg_global (void) reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wa]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wd]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wf]], + reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wg]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wl]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_ws]], reg_class_names[rs6000_constraints[RS6000_CONSTRAINT_wx]], @@ -2120,6 +2122,9 @@ rs6000_init_hard_regno_mode_ok (bool glo if (TARGET_ALTIVEC) rs6000_constraints[RS6000_CONSTRAINT_v] = ALTIVEC_REGS; + if (TARGET_MFPGPR) + rs6000_constraints[RS6000_CONSTRAINT_wg] = FLOAT_REGS; + if (TARGET_LFIWAX) rs6000_constraints[RS6000_CONSTRAINT_wl] = FLOAT_REGS; @@ -2150,6 +2155,8 @@ rs6000_init_hard_regno_mode_ok (bool glo { rs6000_vector_reload[DFmode][0] = CODE_FOR_reload_df_di_store; rs6000_vector_reload[DFmode][1] = CODE_FOR_reload_df_di_load; + rs6000_vector_reload[DDmode][0] = CODE_FOR_reload_dd_di_store; + rs6000_vector_reload[DDmode][1] = CODE_FOR_reload_dd_di_load; } } else @@ -2170,6 +2177,8 @@ rs6000_init_hard_regno_mode_ok (bool glo { rs6000_vector_reload[DFmode][0] = CODE_FOR_reload_df_si_store; rs6000_vector_reload[DFmode][1] = CODE_FOR_reload_df_si_load; + rs6000_vector_reload[DDmode][0] = CODE_FOR_reload_dd_si_store; + rs6000_vector_reload[DDmode][1] = CODE_FOR_reload_dd_si_load; } } } Index: gcc/config/rs6000/dfp.md =================================================================== --- gcc/config/rs6000/dfp.md (revision 195590) +++ gcc/config/rs6000/dfp.md (working copy) @@ -144,27 +144,6 @@ (define_insn "*nabstd2_fpr" "fnabs %0,%1" [(set_attr "type" "fp")]) -(define_expand "movtd" - [(set (match_operand:TD 0 "general_operand" "") - (match_operand:TD 1 "any_operand" ""))] - "TARGET_HARD_FLOAT && TARGET_FPRS" - "{ rs6000_emit_move (operands[0], operands[1], TDmode); DONE; }") - -; It's important to list the Y->r and r->Y moves before r->r because -; otherwise reload, given m->r, will try to pick r->r and reload it, -; which doesn't make progress. -(define_insn_and_split "*movtd_internal" - [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r") - (match_operand:TD 1 "input_operand" "d,m,d,r,YGHF,r"))] - "TARGET_HARD_FLOAT && TARGET_FPRS - && (gpc_reg_operand (operands[0], TDmode) - || gpc_reg_operand (operands[1], TDmode))" - "#" - "&& reload_completed" - [(pc)] -{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; } - [(set_attr "length" "8,8,8,20,20,16")]) - ;; Hardware support for decimal floating point operations. (define_insn "extendddtd2" Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 195590) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -257,6 +257,8 @@ (define_mode_iterator FMA_F [ (define_mode_iterator FMOVE32 [SF SD]) (define_mode_iterator FMOVE64 [DF DD]) (define_mode_iterator FMOVE64X [DI DF DD]) +(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128") + (TD "TARGET_HARD_FLOAT && TARGET_FPRS")]) ; Whether a floating point move is ok, don't allow SD without hardware FP (define_mode_attr fmove_ok [(SF "") @@ -8148,35 +8150,33 @@ (define_insn "*mov<mode>_softfloat64" [(set_attr "type" "store,load,*,mtjmpr,mfjmpr,*,*,*,*") (set_attr "length" "4,4,4,4,4,8,12,16,4")]) -(define_expand "movtf" - [(set (match_operand:TF 0 "general_operand" "") - (match_operand:TF 1 "any_operand" ""))] - "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" - "{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }") +(define_expand "mov<mode>" + [(set (match_operand:FMOVE128 0 "general_operand" "") + (match_operand:FMOVE128 1 "any_operand" ""))] + "" + "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }") ;; It's important to list Y->r and r->Y before r->r because otherwise ;; reload, given m->r, will try to pick r->r and reload it, which ;; doesn't make progress. -(define_insn_and_split "*movtf_internal" - [(set (match_operand:TF 0 "nonimmediate_operand" "=m,d,d,Y,r,r") - (match_operand:TF 1 "input_operand" "d,m,d,r,YGHF,r"))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128 - && (gpc_reg_operand (operands[0], TFmode) - || gpc_reg_operand (operands[1], TFmode))" +(define_insn_and_split "*mov<mode>_internal" + [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,Y,r,r") + (match_operand:FMOVE128 1 "input_operand" "d,m,d,r,YGHF,r"))] + "TARGET_HARD_FLOAT && TARGET_FPRS + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "#" "&& reload_completed" [(pc)] { rs6000_split_multireg_move (operands[0], operands[1]); DONE; } [(set_attr "length" "8,8,8,20,20,16")]) -(define_insn_and_split "*movtf_softfloat" - [(set (match_operand:TF 0 "rs6000_nonimmediate_operand" "=Y,r,r") - (match_operand:TF 1 "input_operand" "r,YGHF,r"))] - "!TARGET_IEEEQUAD - && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_LONG_DOUBLE_128 - && (gpc_reg_operand (operands[0], TFmode) - || gpc_reg_operand (operands[1], TFmode))" +(define_insn_and_split "*mov<mode>_softfloat" + [(set (match_operand:FMOVE128 0 "rs6000_nonimmediate_operand" "=Y,r,r") + (match_operand:FMOVE128 1 "input_operand" "r,YGHF,r"))] + "(TARGET_SOFT_FLOAT || !TARGET_FPRS) + && (gpc_reg_operand (operands[0], <MODE>mode) + || gpc_reg_operand (operands[1], <MODE>mode))" "#" "&& reload_completed" [(pc)] Index: gcc/testsuite/gcc.target/powerpc/mmfpgpr.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/mmfpgpr.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/mmfpgpr.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-O2 -mcpu=power6x -mmfpgpr" } */ +/* { dg-final { scan-assembler "mffgpr" } } */ +/* { dg-final { scan-assembler "mftgpr" } } */ + +/* Test that we generate the instructions to move between the GPR and FPR + registers under power6x. */ + +extern long return_long (void); +extern double return_double (void); + +double return_double2 (void) +{ + return (double) return_long (); +} + +long return_long2 (void) +{ + return (long) return_double (); +}