diff mbox

Add VSX fmaxf/fminf optimization on rs6000

Message ID 20101022202633.GA24114@hungry-tiger.westford.ibm.com
State New
Headers show

Commit Message

Michael Meissner Oct. 22, 2010, 8:26 p.m. UTC
I've carried the following patch in my sandbox for the next round of floating
point conversion fixes for some time, and I'm submitting it as a stand alone
patch.  On VSX power systems, scalar single precision floating point values are
kept internally as double precision.  For min/max, there is no need to do a
rounding step, since the compiler believes both values are single precision, so
we can use the double precision min/max instructions instead of doing a
floating point compare and select.

I've done a bootstrap and make check with no regressions.  Is it ok to install
this patch?

[gcc]
2010-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* config/rs6000/rs6000.c (rs6000_emit_minmax): Add support to use
	xsmindp/xsmaxdp on VSX for single precision min/max.
	* config/rs6000/vsx.md (vsx_smaxsf3): Ditto.
	(vsx_sminsf3): Ditto.

[gcc/testsuite]
2010-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* gcc.target/powerpc/vsx-sfminmax.c: New test for using double
	precision min/max for single precision on VSX.

Comments

David Edelsohn Nov. 2, 2010, 7:20 p.m. UTC | #1
On Fri, Oct 22, 2010 at 4:26 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> I've carried the following patch in my sandbox for the next round of floating
> point conversion fixes for some time, and I'm submitting it as a stand alone
> patch.  On VSX power systems, scalar single precision floating point values are
> kept internally as double precision.  For min/max, there is no need to do a
> rounding step, since the compiler believes both values are single precision, so
> we can use the double precision min/max instructions instead of doing a
> floating point compare and select.
>
> I've done a bootstrap and make check with no regressions.  Is it ok to install
> this patch?
>
> [gcc]
> 2010-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>        * config/rs6000/rs6000.c (rs6000_emit_minmax): Add support to use
>        xsmindp/xsmaxdp on VSX for single precision min/max.
>        * config/rs6000/vsx.md (vsx_smaxsf3): Ditto.
>        (vsx_sminsf3): Ditto.
>
> [gcc/testsuite]
> 2010-10-22  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>        * gcc.target/powerpc/vsx-sfminmax.c: New test for using double
>        precision min/max for single precision on VSX.

Okay.

Thanks, David
diff mbox

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 165844)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -17211,7 +17211,9 @@  rs6000_emit_minmax (rtx dest, enum rtx_c
   rtx target;
 
   /* VSX/altivec have direct min/max insns.  */
-  if ((code == SMAX || code == SMIN) && VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode))
+  if ((code == SMAX || code == SMIN)
+      && (VECTOR_UNIT_ALTIVEC_OR_VSX_P (mode)
+	  || (mode == SFmode && VECTOR_UNIT_VSX_P (DFmode))))
     {
       emit_insn (gen_rtx_SET (VOIDmode,
 			      dest,
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md	(revision 165844)
+++ gcc/config/rs6000/vsx.md	(working copy)
@@ -437,6 +437,28 @@  (define_insn "*vsx_smin<mode>3"
   [(set_attr "type" "<VStype_simple>")
    (set_attr "fp_type" "<VSfptype_simple>")])
 
+;; Special VSX version of smin/smax for single precision floating point.  Since
+;; both numbers are rounded to single precision, we can just use the DP version
+;; of the instruction.
+
+(define_insn "*vsx_smaxsf3"
+  [(set (match_operand:SF 0 "vsx_register_operand" "=f")
+        (smax:SF (match_operand:SF 1 "vsx_register_operand" "f")
+		 (match_operand:SF 2 "vsx_register_operand" "f")))]
+  "VECTOR_UNIT_VSX_P (DFmode)"
+  "xsmaxdp %x0,%x1,%x2"
+  [(set_attr "type" "fp")
+   (set_attr "fp_type" "fp_addsub_d")])
+
+(define_insn "*vsx_sminsf3"
+  [(set (match_operand:SF 0 "vsx_register_operand" "=f")
+        (smin:SF (match_operand:SF 1 "vsx_register_operand" "f")
+		 (match_operand:SF 2 "vsx_register_operand" "f")))]
+  "VECTOR_UNIT_VSX_P (DFmode)"
+  "xsmindp %x0,%x1,%x2"
+  [(set_attr "type" "fp")
+   (set_attr "fp_type" "fp_addsub_d")])
+
 (define_insn "*vsx_sqrt<mode>2"
   [(set (match_operand:VSX_B 0 "vsx_register_operand" "=<VSr>,?wa")
         (sqrt:VSX_B (match_operand:VSX_B 1 "vsx_register_operand" "<VSr>,wa")))]
Index: gcc/testsuite/gcc.target/powerpc/vsx-sfminmax.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/vsx-sfminmax.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/vsx-sfminmax.c	(revision 0)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mcpu=power7" } */
+/* { dg-final { scan-assembler "xsmaxdp" } } */
+/* { dg-final { scan-assembler "xsmindp" } } */
+
+float
+do_fmin (float a, float b)
+{
+  return __builtin_fminf (a, b);
+}
+
+float
+do_fmax (float a, float b)
+{
+  return __builtin_fmaxf (a, b);
+}