On Fri, Sep 23, 2011 at 12:09:18AM +0200, Uros Bizjak wrote:
> > --- gcc/config/i386/i386.c.jj   2011-09-02 16:29:38.000000000 +0200
> > +++ gcc/config/i386/i386.c      2011-09-07 21:57:52.000000000 +0200
> > @@ -18304,6 +18304,11 @@ ix86_prepare_sse_fp_compare_args (rtx de
> >  {
> >   rtx tmp;
> >
> > +  /* AVX supports all the needed comparisons, no need to swap arguments
> > +     nor help reload.  */
> > +  if (TARGET_AVX)
> > +    return code;
> > +
> 
> Unfortunately, this part prevents generation of vmin/vmax instructions
> for TARGET_AVX. In ix86_expand_fp_movcc, we call
> ix86_prepare_sse_fp_compare_args, where we previously converted GT
> into LT. LT is recognized in ix86_expand_sse_fp_minmax as valid
> operand for MIN/MAX, whereas GT is not.
> 
> I'm not sure if we can swap operands in ix86_expand_sse_fp_minmax,
> there is a scary comment  in front of ix86_expand_sse_fp_minmax w.r.t.
> to IEEE safety.

swap_condition is documented to be IEEE safe:
/* Similar, but return the code when two operands of a comparison are swapped.
   This IS safe for IEEE floating-point.  */

So, do you prefer this?

2011-09-23  Jakub Jelinek  <ja...@redhat.com>

        * config/i386/i386.c (ix86_prepare_sse_fp_compare_args): For
        GE/GT/UNLE/UNLT swap arguments and condition even for TARGET_AVX.

        * gcc.target/i386/avxfp-1.c: New test.
        * gcc.target/i386/avxfp-2.c: New test.

--- gcc/config/i386/i386.c.jj   2011-09-22 18:55:45.000000000 +0200
+++ gcc/config/i386/i386.c      2011-09-23 10:04:35.000000000 +0200
@@ -18739,15 +18739,13 @@ ix86_prepare_sse_fp_compare_args (rtx de
 {
   rtx tmp;
 
-  /* AVX supports all the needed comparisons, no need to swap arguments
-     nor help reload.  */
-  if (TARGET_AVX)
-    return code;
-
   switch (code)
     {
     case LTGT:
     case UNEQ:
+      /* AVX supports all the needed comparisons.  */
+      if (TARGET_AVX)
+       break;
       /* We have no LTGT as an operator.  We could implement it with
         NE & ORDERED, but this requires an extra temporary.  It's
         not clear that it's worth it.  */
@@ -18764,6 +18762,9 @@ ix86_prepare_sse_fp_compare_args (rtx de
     case NE:
     case UNORDERED:
     case ORDERED:
+      /* AVX has 3 operand comparisons, no need to swap anything.  */
+      if (TARGET_AVX)
+       break;
       /* For commutative operators, try to canonicalize the destination
         operand to be first in the comparison - this helps reload to
         avoid extra moves.  */
@@ -18775,8 +18776,10 @@ ix86_prepare_sse_fp_compare_args (rtx de
     case GT:
     case UNLE:
     case UNLT:
-      /* These are not supported directly.  Swap the comparison operands
-        to transform into something that is supported.  */
+      /* These are not supported directly before AVX, and furthermore
+        ix86_expand_sse_fp_minmax only optimizes LT/UNGE.  Swap the
+        comparison operands to transform into something that is
+        supported.  */
       tmp = *pop0;
       *pop0 = *pop1;
       *pop1 = tmp;
--- gcc/testsuite/gcc.target/i386/avxfp-1.c.jj  2011-09-23 10:07:48.000000000 
+0200
+++ gcc/testsuite/gcc.target/i386/avxfp-1.c     2011-09-23 10:08:02.000000000 
+0200
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx -mfpmath=sse" } */
+/* { dg-final { scan-assembler "vmaxsd" } } */
+/* { dg-final { scan-assembler "vminsd" } } */
+double x;
+t()
+{
+  x=x>5?x:5;
+}
+
+double x;
+q()
+{
+  x=x<5?x:5;
+}
--- gcc/testsuite/gcc.target/i386/avxfp-2.c.jj  2011-09-23 10:07:51.000000000 
+0200
+++ gcc/testsuite/gcc.target/i386/avxfp-2.c     2011-09-23 10:08:17.000000000 
+0200
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx -mfpmath=sse" } */
+/* { dg-final { scan-assembler "vmaxsd" } } */
+/* { dg-final { scan-assembler "vminsd" } } */
+double x;
+q()
+{
+  x=x<5?5:x;
+}
+
+double x;
+q1()
+{
+  x=x>5?5:x;
+}

        Jakub

Reply via email to