From 8acb85754af19a055d7d00248ca869496dd4cda0 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Fri, 5 May 2017 20:21:15 +0000 Subject: [PATCH] re PR target/79038 (Improve PowerPC ISA 3.0 conversion between integers and hardware _Float128) [gcc] 2017-05-05 Michael Meissner PR target/79038 PR target/79202 PR target/79203 * config/rs6000/rs6000.md (u code attribute): Add FIX and UNSIGNED_FIX. (extendsi2): Add support for doing sign extension via VUPKHSW and XXPERMDI if the value is in Altivec registers and we don't have ISA 3.0 instructions. (extendsi2 splitter): Likewise. (fix_truncsi2): If we are at ISA 2.07 (VSX small integer), generate the normal insns since SImode can now go in vector registers. Disallow the special UNSPECs needed for previous machines to hide SImode being used. Add new insns fctiw{,w}__smallint if SImode can go in vector registers. (fix_truncsi2_stfiwx): Likewise. (fix_truncsi2_internal): Likewise. (fixuns_truncsi2): Likewise. (fixuns_truncsi2_stfiwx): Likewise. (fctiwz__smallint): Likewise. (fctiwz__mem): New combiner pattern to prevent conversion of floating point to 32-bit integer from doing a direct move to the GPR registers to do a store. (fctiwz_): Break long line. [gcc/testsuite] 2017-05-05 Michael Meissner PR target/79038 PR target/79202 PR target/79203 * gcc.target/powerpc/ppc-round3.c: New test. * gcc.target/powerpc/ppc-round2.c: Update expected code. From-SVN: r247657 --- gcc/ChangeLog | 26 +++++ gcc/config/rs6000/rs6000.md | 96 +++++++++++++++---- gcc/testsuite/ChangeLog | 8 ++ gcc/testsuite/gcc.target/powerpc/ppc-round2.c | 25 ++--- gcc/testsuite/gcc.target/powerpc/ppc-round3.c | 45 +++++++++ 5 files changed, 173 insertions(+), 27 deletions(-) create mode 100644 gcc/testsuite/gcc.target/powerpc/ppc-round3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5bcf2065a11..0a8bb93f326 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2017-05-05 Michael Meissner + + PR target/79038 + PR target/79202 + PR target/79203 + * config/rs6000/rs6000.md (u code attribute): Add FIX and + UNSIGNED_FIX. + (extendsi2): Add support for doing sign extension via + VUPKHSW and XXPERMDI if the value is in Altivec registers and we + don't have ISA 3.0 instructions. + (extendsi2 splitter): Likewise. + (fix_truncsi2): If we are at ISA 2.07 (VSX small integer), + generate the normal insns since SImode can now go in vector + registers. Disallow the special UNSPECs needed for previous + machines to hide SImode being used. Add new insns + fctiw{,w}__smallint if SImode can go in vector registers. + (fix_truncsi2_stfiwx): Likewise. + (fix_truncsi2_internal): Likewise. + (fixuns_truncsi2): Likewise. + (fixuns_truncsi2_stfiwx): Likewise. + (fctiwz__smallint): Likewise. + (fctiwz__mem): New combiner pattern to prevent conversion + of floating point to 32-bit integer from doing a direct move to + the GPR registers to do a store. + (fctiwz_): Break long line. + 2017-05-05 Bin Cheng * Makefile.in (GTFILES): Add tree-ssa-loop-ivopts.c. diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 6e73f9d9524..3d21ccc34a8 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -566,7 +566,9 @@ (define_code_iterator any_float [float unsigned_float]) (define_code_attr u [(sign_extend "") - (zero_extend "u")]) + (zero_extend "u") + (fix "") + (unsigned_fix "u")]) (define_code_attr su [(sign_extend "s") (zero_extend "u") @@ -1027,8 +1029,8 @@ (define_insn "extendsi2" - [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,wl,wu,wj,wK") - (sign_extend:EXTSI (match_operand:SI 1 "lwa_operand" "Y,r,Z,Z,r,wK")))] + [(set (match_operand:EXTSI 0 "gpc_reg_operand" "=r,r,wl,wu,wj,wK,wH") + (sign_extend:EXTSI (match_operand:SI 1 "lwa_operand" "Y,r,Z,Z,r,wK,wH")))] "" "@ lwa%U1%X1 %0,%1 @@ -1036,9 +1038,38 @@ lfiwax %0,%y1 lxsiwax %x0,%y1 mtvsrwa %x0,%1 - vextsw2d %0,%1" - [(set_attr "type" "load,exts,fpload,fpload,mffgpr,vecexts") - (set_attr "sign_extend" "yes")]) + vextsw2d %0,%1 + #" + [(set_attr "type" "load,exts,fpload,fpload,mffgpr,vecexts,vecperm") + (set_attr "sign_extend" "yes") + (set_attr "length" "4,4,4,4,4,4,8")]) + +(define_split + [(set (match_operand:DI 0 "altivec_register_operand") + (sign_extend:DI (match_operand:SI 1 "altivec_register_operand")))] + "TARGET_VSX_SMALL_INTEGER && TARGET_P8_VECTOR && !TARGET_P9_VECTOR + && reload_completed" + [(const_int 0)] +{ + rtx dest = operands[0]; + rtx src = operands[1]; + int dest_regno = REGNO (dest); + int src_regno = REGNO (src); + rtx dest_v2di = gen_rtx_REG (V2DImode, dest_regno); + rtx src_v4si = gen_rtx_REG (V4SImode, src_regno); + + if (VECTOR_ELT_ORDER_BIG) + { + emit_insn (gen_altivec_vupkhsw (dest_v2di, src_v4si)); + emit_insn (gen_vsx_xxspltd_v2di (dest_v2di, dest_v2di, const1_rtx)); + } + else + { + emit_insn (gen_altivec_vupklsw (dest_v2di, src_v4si)); + emit_insn (gen_vsx_xxspltd_v2di (dest_v2di, dest_v2di, const0_rtx)); + } + DONE; +}) (define_insn_and_split "*extendsi2_dot" [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y") @@ -5570,7 +5601,7 @@ "TARGET_HARD_FLOAT && ((TARGET_FPRS && ) || )" " { - if (!) + if (! && !TARGET_VSX_SMALL_INTEGER) { rtx src = force_reg (mode, operands[1]); @@ -5596,7 +5627,8 @@ (clobber (match_scratch:DI 2 "=d"))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && (mode != SFmode || TARGET_SINGLE_FLOAT) - && TARGET_STFIWX && can_create_pseudo_p ()" + && TARGET_STFIWX && can_create_pseudo_p () + && !TARGET_VSX_SMALL_INTEGER" "#" "" [(pc)] @@ -5637,7 +5669,8 @@ (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,"))) (clobber (match_operand:DI 2 "gpc_reg_operand" "=1,d")) (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o,o"))] - "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT + && !TARGET_VSX_SMALL_INTEGER" "#" "" [(pc)] @@ -5721,7 +5754,7 @@ || )" " { - if (!) + if (! && !TARGET_VSX_SMALL_INTEGER) { emit_insn (gen_fixuns_truncsi2_stfiwx (operands[0], operands[1])); DONE; @@ -5733,7 +5766,8 @@ (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))) (clobber (match_scratch:DI 2 "=d"))] "TARGET_HARD_FLOAT && TARGET_FPRS && && TARGET_FCTIWUZ - && TARGET_STFIWX && can_create_pseudo_p ()" + && TARGET_STFIWX && can_create_pseudo_p () + && !TARGET_VSX_SMALL_INTEGER" "#" "" [(pc)] @@ -5818,13 +5852,43 @@ } DONE; }) -; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ)) -; rather than (set (subreg:SI (reg)) (fix:SI ...)) -; because the first makes it clear that operand 0 is not live -; before the instruction. + +;; If -mvsx-small-integer, we can represent the FIX operation directly. On +;; older machines, we have to use an UNSPEC to produce a SImode and move it +;; to another location, since SImode is not allowed in vector registers. +(define_insn "*fctiwz__smallint" + [(set (match_operand:SI 0 "vsx_register_operand" "=d,wi") + (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" ",")))] + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT + && TARGET_VSX_SMALL_INTEGER" + "@ + fctiwz %0,%1 + xscvdpxws %x0,%x1" + [(set_attr "type" "fp")]) + +;; Combiner pattern to prevent moving the result of converting a floating point +;; value to 32-bit integer to GPR in order to save it. +(define_insn_and_split "*fctiwz__mem" + [(set (match_operand:SI 0 "memory_operand" "=Z") + (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "wa"))) + (clobber (match_scratch:SI 2 "=wa"))] + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT + && TARGET_VSX_SMALL_INTEGER" + "#" + "&& reload_completed" + [(set (match_dup 2) + (any_fix:SI (match_dup 1))) + (set (match_dup 0) + (match_dup 2))]) + +;; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ)) +;; rather than (set (subreg:SI (reg)) (fix:SI ...)) +;; because the first makes it clear that operand 0 is not live +;; before the instruction. (define_insn "fctiwz_" [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi") - (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" ","))] + (unspec:DI [(fix:SI + (match_operand:SFDF 1 "gpc_reg_operand" ","))] UNSPEC_FCTIWZ))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "@ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 99c237bafb9..5cd12864a5b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-05-05 Michael Meissner + + PR target/79038 + PR target/79202 + PR target/79203 + * gcc.target/powerpc/ppc-round3.c: New test. + * gcc.target/powerpc/ppc-round2.c: Update expected code. + 2017-05-05 Jakub Jelinek PR tree-optimization/80632 diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-round2.c b/gcc/testsuite/gcc.target/powerpc/ppc-round2.c index 1890fca10be..2b14fb402a3 100644 --- a/gcc/testsuite/gcc.target/powerpc/ppc-round2.c +++ b/gcc/testsuite/gcc.target/powerpc/ppc-round2.c @@ -3,18 +3,21 @@ /* { dg-require-effective-target powerpc_p8vector_ok } */ /* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ /* { dg-options "-O2 -mcpu=power8" } */ -/* { dg-final { scan-assembler-times "fcfid " 2 } } */ -/* { dg-final { scan-assembler-times "fcfids " 2 } } */ -/* { dg-final { scan-assembler-times "fctiwuz \|xscvdpuxws " 2 } } */ +/* { dg-final { scan-assembler-times "fcfid \|xscvsxddp " 2 } } */ +/* { dg-final { scan-assembler-times "fcfids \|xscvsxdsp " 2 } } */ /* { dg-final { scan-assembler-times "fctiwz \|xscvdpsxws " 2 } } */ -/* { dg-final { scan-assembler-times "mfvsrd " 4 } } */ -/* { dg-final { scan-assembler-times "mtvsrwa " 2 } } */ -/* { dg-final { scan-assembler-times "mtvsrwz " 2 } } */ -/* { dg-final { scan-assembler-not "lwz" } } */ -/* { dg-final { scan-assembler-not "lfiwax " } } */ -/* { dg-final { scan-assembler-not "lfiwzx " } } */ -/* { dg-final { scan-assembler-not "stw" } } */ -/* { dg-final { scan-assembler-not "stfiwx " } } */ +/* { dg-final { scan-assembler-times "fctiwuz \|xscvdpuxws " 2 } } */ +/* { dg-final { scan-assembler-times {\mmfvsrwz\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mmtvsrwz\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mvupkhsw\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxxpermdi\M} 2 } } */ +/* { dg-final { scan-assembler-not {\mmfvsrd\M} } } */ +/* { dg-final { scan-assembler-not {\mmtvsrwa\M} } } */ +/* { dg-final { scan-assembler-not {\mlwz\M} } } */ +/* { dg-final { scan-assembler-not {\mlfiwax\M} } } */ +/* { dg-final { scan-assembler-not {\mlfiwzx\M} } } */ +/* { dg-final { scan-assembler-not {\mstw\M} } } */ +/* { dg-final { scan-assembler-not {\mstfiwx\M} } } */ /* Make sure we don't have loads/stores to the GPR unit. */ double diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-round3.c b/gcc/testsuite/gcc.target/powerpc/ppc-round3.c new file mode 100644 index 00000000000..33954d7bb46 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/ppc-round3.c @@ -0,0 +1,45 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_p9vector_ok } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ +/* { dg-options "-O2 -mcpu=power9" } */ +/* { dg-final { scan-assembler-times "fcfid \|xscvsxddp " 2 } } */ +/* { dg-final { scan-assembler-times "fcfids \|xscvsxdsp " 2 } } */ +/* { dg-final { scan-assembler-times "fctiwz \|xscvdpsxws " 2 } } */ +/* { dg-final { scan-assembler-times "fctiwuz \|xscvdpuxws " 2 } } */ +/* { dg-final { scan-assembler-times {\mvextsw2d\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxxextractuw\M} 2 } } */ +/* { dg-final { scan-assembler-not {\mmfvsrd\M} } } */ +/* { dg-final { scan-assembler-not {\mmfvsrwz\M} } } */ +/* { dg-final { scan-assembler-not {\mmtvsrwa\M} } } */ +/* { dg-final { scan-assembler-not {\mmtvsrwz\M} } } */ +/* { dg-final { scan-assembler-not {\mlwz\M} } } */ +/* { dg-final { scan-assembler-not {\mlfiwax\M} } } */ +/* { dg-final { scan-assembler-not {\mlfiwzx\M} } } */ +/* { dg-final { scan-assembler-not {\mstw\M} } } */ +/* { dg-final { scan-assembler-not {\mstfiwx\M} } } */ + +/* Make sure we don't have loads/stores to the GPR unit. */ +double +round_double_int (double a) +{ + return (double)(int)a; +} + +float +round_float_int (float a) +{ + return (float)(int)a; +} + +double +round_double_uint (double a) +{ + return (double)(unsigned int)a; +} + +float +round_float_uint (float a) +{ + return (float)(unsigned int)a; +} -- 2.30.2