https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126328
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |segher at gcc dot gnu.org
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #2)
> (In reply to Hongtao Liu from comment #1)
> > We can have special handling for get_attr_type (insn) == sseadd1(only
> > *sse3_haddv2df3_low and *sse3_hsubv2df3_low) in ix86_insn_cost, directly
> > return insn cost instead of lowering to rtx_cost.
>
> Ah yes, that way we can up the original cost (hopefully always recog'ed).
> I'll give it a try.
Hmm, no, the original is *sse3_haddv2df3 and sse2_storelpd. If we adjust
the original cost of the former to 17 we get
insn_cost 17 for 7:
r106:V2DF=vec_concat(vec_select(r101:V2DF,parallel)+vec_select(r101:V2DF,parallel),vec_select(r101:V2DF,parallel)+vec_select(r101:V2DF,parallel))
...
Trying 2 -> 7:
2: r101:V2DF=r109:V2DF
REG_DEAD r109:V2DF
7:
r106:V2DF=vec_concat(vec_select(r101:V2DF,parallel)+vec_select(r101:V2DF,parallel),vec_select(r101:V2DF,parallel)+vec_select(r101:V2DF,parallel))
REG_DEAD r101:V2DF
Successfully matched this instruction:
...
allowing combination of insns 2 and 7
original costs 4 + 17 = 21
replacement cost 4
so we are back to a cost of 4, because combine_validate_cost doesn't
re-recog before costing :/
That means, at least for combine, a costing strategy based on insn
attributes or pattern names doesn't work.
My hack:
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 56a90333cfc..4de46225f79 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -22700,6 +22700,13 @@ ix86_insn_cost (rtx_insn *insn, bool speed)
== AVX_PARTIAL_XMM_UPDATE_TRUE)
insn_cost += COSTS_N_INSNS (3);
+ if (INSN_CODE (insn) >= 0
+ && (get_attr_type (insn) == TYPE_SSEADD1
+ || strcmp (insn_data[INSN_CODE (insn)].name, "*sse3_haddv2df3") ==
0))
+ {
+ return 17;
+ }
+
rtx pat = PATTERN (insn);
/* A USE of a memory is more expensive than a use of a REG.
For example *<absneg>mode2_1's use of a signbit mask. */
so we'd have to do a full pattern match in ix86_insn_cost then.
An alternative would be to not short-cut costing sub-rtx for VEC_CONCAT
in case there's PLUS/MINUS inside? That yields for original cost:
insn_cost 38 for 7:
r106:V2DF=vec_concat(vec_select(r101:V2DF,parallel)+vec_select(r101:V2DF,parallel),vec_select(r101:V2DF,parallel)+vec_select(r101:V2DF,parallel))
and
Trying 7 -> 8:
7:
r106:V2DF=vec_concat(vec_select(r109:V2DF,parallel)+vec_select(r109:V2DF,parallel),vec_select(r109:V2DF,parallel)+vec_select(r109:V2DF,parallel))
REG_DEAD r109:V2DF
8: r105:DF=vec_select(r106:V2DF,parallel)
REG_DEAD r106:V2DF
Successfully matched this instruction:
(set (reg:DF 105)
(plus:DF (vec_select:DF (reg:V2DF 109 [ p ])
(parallel [
(const_int 0 [0])
]))
(vec_select:DF (reg:V2DF 109 [ p ])
(parallel [
(const_int 1 [0x1])
]))))
allowing combination of insns 7 and 8
original costs 38 + 4 = 42
replacement cost 17
That works for the case at hand, but is still quite arbitrary cost,
but it avoids regressing gcc.target/i386/pr54400.c when we SLP vectorize
the horizontal reductions.
@@ -23538,8 +23547,10 @@ ix86_rtx_costs (rtx x, machine_mode mode, int
outer_code_i, int opno,
/* ??? Assume all of these vector manipulation patterns are
recognizable. In which case they all pretty much have the
same cost.
- ??? We should still recruse when computing cost. */
+ ??? We should still recurse when computing cost. */
*total = cost->sse_op;
+ if (GET_CODE (XEXP (x, 0)) == PLUS || GET_CODE (XEXP (x, 0)) == MINUS)
+ return false;
return true;
case VEC_SELECT: