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