]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Fix FAIL of gcc.target/i386/pr78794.c on ia32.
authorRoger Sayle <roger@nextmovesoftware.com>
Wed, 28 Jun 2023 10:07:47 +0000 (11:07 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Wed, 28 Jun 2023 10:07:47 +0000 (11:07 +0100)
This patch fixes that FAIL of gcc.target/i386/pr78794.c on ia32, which
is caused by minor STV rtx_cost differences with -march=silvermont.
It turns out that generic tuning results in pandn, but the lack of
accurate parameterization for COMPARE in compute_convert_gain combined
with small differences in scalar<->SSE costs on silvermont results in
this DImode chain not being converted.

The solution is to provide more accurate costs/gains for converting
(DImode and SImode) comparisons.

I'd been holding off of doing this as I'd thought it would be possible
to turn pandn;ptestz into ptestc (for an even bigger scalar-to-vector
win) but I've recently realized that these optimizations (as I've
implemented them) occur in the wrong order (stv2 occurs after
combine), so it isn't easy for STV to convert CCZmode into CCCmode.
Doh!  Perhaps something can be done in peephole2.

2023-06-28  Roger Sayle  <roger@nextmovesoftware.com>

gcc/ChangeLog
PR target/78794
* config/i386/i386-features.cc (compute_convert_gain): Provide
more accurate gains for conversion of scalar comparisons to
PTEST.

gcc/config/i386/i386-features.cc

index 92ae08d442e1610de35f96544a030afb16bd1af6..c676a90f51b6ef261cef5064e8543137c35e1494 100644 (file)
@@ -631,7 +631,31 @@ general_scalar_chain::compute_convert_gain ()
            break;
 
          case COMPARE:
-           /* Assume comparison cost is the same.  */
+           if (XEXP (src, 1) != const0_rtx)
+             {
+               /* cmp vs. pxor;pshufd;ptest.  */
+               igain += COSTS_N_INSNS (m - 3);
+             }
+           else if (GET_CODE (XEXP (src, 0)) != AND)
+             {
+               /* test vs. pshufd;ptest.  */
+               igain += COSTS_N_INSNS (m - 2);
+             }
+           else if (GET_CODE (XEXP (XEXP (src, 0), 0)) != NOT)
+             {
+               /* and;test vs. pshufd;ptest.  */
+               igain += COSTS_N_INSNS (2 * m - 2);
+             }
+           else if (TARGET_BMI)
+             {
+               /* andn;test vs. pandn;pshufd;ptest.  */
+               igain += COSTS_N_INSNS (2 * m - 3);
+             }
+           else
+             {
+               /* not;and;test vs. pandn;pshufd;ptest.  */
+               igain += COSTS_N_INSNS (3 * m - 3);
+             }
            break;
 
          case CONST_INT: