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