I run into issues with gcc.target/i386/pr54400.c when SLP vectorizing
a horizontal reduction of a V2DF vector.  The following plugs the
remaining hole in costing which prevents combine from doing its work
to recover the single hadd instruction for { p[0] + p[1], q[0] + q[1] }

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

OK for trunk if testing succeeds?

To have an effect it depends on the prerequesite
[v2] Simplify (vec_select:<scalar> (vec_concat ..))
and unless
Support two-lane vector BB reductions without target support
is installed gcc.target/i386/pr54400.c is passing anyway.

        PR target/126328
        * config/i386/i386.cc (ix86_insn_cost): Match
        *sse3_h{add,sub}v2df3[_low] and cost it like an add.
---
 gcc/config/i386/i386.cc | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 56a90333cfc..ab04290bf7c 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -22714,6 +22714,27 @@ ix86_insn_cost (rtx_insn *insn, bool speed)
                                               : COSTS_N_INSNS (3) + 1;
        }
     }
+  if (rtx set = single_set (insn))
+    {
+      rtx src = SET_SRC (set);
+      /* ix86_rtx_cost makes VEC_CONCAT artificially cheap by not recursing
+        into operands.  That makes *sse3_haddv2df3 win over
+        *sse3_haddv2df3_low, preventing combine from doing its work for
+        gcc.target/i386/pr54400.c.  Cost both the same explicitly.  */
+      if ((GET_MODE (src) == V2DFmode
+          && GET_CODE (src) == VEC_CONCAT
+          && (GET_CODE (XEXP (src, 0)) == PLUS
+              || GET_CODE (XEXP (src, 0)) == MINUS)
+          && GET_CODE (XEXP (XEXP (src, 0), 0)) == VEC_SELECT)
+         || (GET_MODE (src) == DFmode
+             && (GET_CODE (src) == PLUS || GET_CODE (src) == MINUS)
+             && GET_CODE (XEXP (src, 0)) == VEC_SELECT
+             && GET_CODE (XEXP (src, 1)) == VEC_SELECT))
+       /* Assume this is only recognized as *sse3_h{add,sub}v2df3[_low].  */
+       return insn_cost + ix86_vec_cost (GET_MODE (pat),
+                                         (speed ? ix86_tune_cost
+                                          : &ix86_size_cost)->addss);
+    }
 
   return insn_cost + pattern_cost (pat, speed);
 }
-- 
2.51.0

Reply via email to