re PR target/79038 (Improve PowerPC ISA 3.0 conversion between integers and hardware...
authorMichael Meissner <meissner@linux.vnet.ibm.com>
Fri, 5 May 2017 20:21:15 +0000 (20:21 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Fri, 5 May 2017 20:21:15 +0000 (20:21 +0000)
[gcc]
2017-05-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

PR target/79038
PR target/79202
PR target/79203
* config/rs6000/rs6000.md (u code attribute): Add FIX and
UNSIGNED_FIX.
(extendsi<mode>2): 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.
(extendsi<mode>2 splitter): Likewise.
(fix_trunc<mode>si2): 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}_<mode>_smallint if SImode can go in vector registers.
(fix_trunc<mode>si2_stfiwx): Likewise.
(fix_trunc<mode>si2_internal): Likewise.
(fixuns_trunc<mode>si2): Likewise.
(fixuns_trunc<mode>si2_stfiwx): Likewise.
(fctiw<u>z_<mode>_smallint): Likewise.
(fctiw<u>z_<mode>_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_<mode>): Break long line.

[gcc/testsuite]
2017-05-05  Michael Meissner  <meissner@linux.vnet.ibm.com>

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
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/ppc-round2.c
gcc/testsuite/gcc.target/powerpc/ppc-round3.c [new file with mode: 0644]

index 5bcf2065a1125031165479292f638885368ab421..0a8bb93f326d5270248413ddcb866e0267449101 100644 (file)
@@ -1,3 +1,29 @@
+2017-05-05  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/79038
+       PR target/79202
+       PR target/79203
+       * config/rs6000/rs6000.md (u code attribute): Add FIX and
+       UNSIGNED_FIX.
+       (extendsi<mode>2): 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.
+       (extendsi<mode>2 splitter): Likewise.
+       (fix_trunc<mode>si2): 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}_<mode>_smallint if SImode can go in vector registers.
+       (fix_trunc<mode>si2_stfiwx): Likewise.
+       (fix_trunc<mode>si2_internal): Likewise.
+       (fixuns_trunc<mode>si2): Likewise.
+       (fixuns_trunc<mode>si2_stfiwx): Likewise.
+       (fctiw<u>z_<mode>_smallint): Likewise.
+       (fctiw<u>z_<mode>_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_<mode>): Break long line.
+
 2017-05-05  Bin Cheng  <bin.cheng@arm.com>
 
        * Makefile.in (GTFILES): Add tree-ssa-loop-ivopts.c.
index 6e73f9d952486de304de1cea3824f38979dadb8d..3d21ccc34a8787622b4a5086027f23bbe59a441e 100644 (file)
 (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")
 
 
 (define_insn "extendsi<mode>2"
-  [(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
    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 "*extendsi<mode>2_dot"
   [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
   "TARGET_HARD_FLOAT && ((TARGET_FPRS && <TARGET_FLOAT>) || <E500_CONVERT>)"
   "
 {
-  if (!<E500_CONVERT>)
+  if (!<E500_CONVERT> && !TARGET_VSX_SMALL_INTEGER)
     {
       rtx src = force_reg (<MODE>mode, operands[1]);
 
    (clobber (match_scratch:DI 2 "=d"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
    && (<MODE>mode != SFmode || TARGET_SINGLE_FLOAT)
-   && TARGET_STFIWX && can_create_pseudo_p ()"
+   && TARGET_STFIWX && can_create_pseudo_p ()
+   && !TARGET_VSX_SMALL_INTEGER"
   "#"
   ""
   [(pc)]
        (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d,<rreg>")))
    (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)]
        || <E500_CONVERT>)"
   "
 {
-  if (!<E500_CONVERT>)
+  if (!<E500_CONVERT> && !TARGET_VSX_SMALL_INTEGER)
     {
       emit_insn (gen_fixuns_trunc<mode>si2_stfiwx (operands[0], operands[1]));
       DONE;
        (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d")))
    (clobber (match_scratch:DI 2 "=d"))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && <TARGET_FLOAT> && TARGET_FCTIWUZ
-   && TARGET_STFIWX && can_create_pseudo_p ()"
+   && TARGET_STFIWX && can_create_pseudo_p ()
+   && !TARGET_VSX_SMALL_INTEGER"
   "#"
   ""
   [(pc)]
     }
   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 "*fctiw<u>z_<mode>_smallint"
+  [(set (match_operand:SI 0 "vsx_register_operand" "=d,wi")
+       (any_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>")))]
+  "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
+   && TARGET_VSX_SMALL_INTEGER"
+  "@
+   fctiw<u>z %0,%1
+   xscvdp<su>xws %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 "*fctiw<u>z_<mode>_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_<mode>"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=d,wi")
-       (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
+       (unspec:DI [(fix:SI
+                    (match_operand:SFDF 1 "gpc_reg_operand" "<Ff>,<Fv>"))]
                   UNSPEC_FCTIWZ))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
   "@
index 99c237bafb9276cfd41e51dfa893823beb8e9d02..5cd12864a5b7d51bbcb4471fb6156e90db1aa706 100644 (file)
@@ -1,3 +1,11 @@
+2017-05-05  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       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  <jakub@redhat.com>
 
        PR tree-optimization/80632
index 1890fca10be085b36111aa2b495a9ab9b6b4e73e..2b14fb402a379e0332b51f41da54f71a09e99590 100644 (file)
@@ -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 (file)
index 0000000..33954d7
--- /dev/null
@@ -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;
+}