--- gcc/config/mips/mips.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 59 insertions(+), 0 deletions(-)
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index a1f06d4..0ac1096 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -16391,6 +16391,63 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1, return expand_vselect (target, x, perm, nelt); } +/* Recognize patterns for even-odd extraction. */ + +static bool +mips_expand_vpc_loongson_even_odd (struct expand_vec_perm_d *d) +{ + unsigned i, odd, nelt = d->nelt; + rtx t0, t1, t2, t3; + + if (!(TARGET_HARD_FLOAT && TARGET_LOONGSON_VECTORS)) + return false; + /* Even-odd for V2SI/V2SFmode is matched by interleave directly. */ + if (nelt < 4) + return false; + + odd = d->perm[0]; + if (odd > 1) + return false; + for (i = 1; i < nelt; ++i) + if (d->perm[i] != i * 2 + odd) + return false; + + if (d->testing_p) + return true; + + /* We need 2*log2(N)-1 operations to achieve odd/even with interleave. */ + t0 = gen_reg_rtx (d->vmode); + t1 = gen_reg_rtx (d->vmode); + switch (d->vmode) + { + case V4HImode: + emit_insn (gen_loongson_punpckhhw (t0, d->op0, d->op1)); + emit_insn (gen_loongson_punpcklhw (t1, d->op0, d->op1)); + if (odd) + emit_insn (gen_loongson_punpckhhw (d->target, t1, t0)); + else + emit_insn (gen_loongson_punpcklhw (d->target, t1, t0)); + break; + + case V8QImode: + t2 = gen_reg_rtx (d->vmode); + t3 = gen_reg_rtx (d->vmode); + emit_insn (gen_loongson_punpckhbh (t0, d->op0, d->op1)); + emit_insn (gen_loongson_punpcklbh (t1, d->op0, d->op1)); + emit_insn (gen_loongson_punpckhbh (t2, t1, t0)); + emit_insn (gen_loongson_punpcklbh (t3, t1, t0)); + if (odd) + emit_insn (gen_loongson_punpckhbh (d->target, t3, t2)); + else + emit_insn (gen_loongson_punpcklbh (d->target, t3, t2)); + break; + + default: + gcc_unreachable (); + } + return true; +} + /* Recognize patterns for the Loongson PSHUFH instruction. */ static bool @@ -16445,6 +16502,8 @@ mips_expand_vec_perm_const_1 (struct expand_vec_perm_d *d) return true; } + if (mips_expand_vpc_loongson_even_odd (d)) + return true; if (mips_expand_vpc_loongson_pshufh (d)) return true; return false; -- 1.7.7.4