> -----Original Message-----
> From: Richard Biener <[email protected]>
> Sent: Wednesday, August 12, 2026 3:58 PM
> To: [email protected]
> Cc: Liu, Hongtao <[email protected]>
> Subject: [PATCH] tree-optimization/126789 - MMX and SSE mask interaction
> with AVX512
>
> The following makes the vectorizer deal with the fact that the x86 backend can
> have a set of integer mode masks and a set of integer vector mode masks
> depending on active ISAs. To convert between both representations we have
> to use vcond_mask for integer mode to integer vector mode. For the case of
> V2SImode the backend currently misses patterns which the following adds.
> Now, when doing BB vectorization the vectorizer pattern recognition cannot
> know that we'll use V2SImode with a vector integer mask mode but it guesses
> V16SImode which would use DImode. So we cannot arrange for the mask
> representation conversion during pattern recognition, but it's easy to handle
> VECTOR_BOOLEAN_TYPE_P conversions with vcond_mask as option in
> vectorizable_conversion, so that's what the patch does.
>
> I don't have a testcase for the reverse which would need to use vcmp[_eq] to
> convert from integer vector mode to integer mode mask, so I'm not
> implementing that with this patch.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu. Are the x86 parts
> OK?
Ok for x86 parts.
>
> Thanks,
> Richard.
>
> PR tree-optimization/126789
> * config/i386/mmx.md (mmxxmmmode): Add V2SF and V2SI.
> (mmxxmmmodelower): Likewise.
> (vcond_mask_<mode>qi): New expander for V2SF and V2SI.
> * tree-vect-stmts.cc (vectorizable_conversion): Handle
> conversion via VEC_COND_EXPR.
> (supportable_indirect_convert_operation): For mask vector
> conversions to vector integer mode try using a VEC_COND_EXPR.
>
> * gcc.target/i386/vect-pr126789-2.c: New testcase.
> ---
> gcc/config/i386/mmx.md | 24 +++++++++-
> .../gcc.target/i386/vect-pr126789-2.c | 19 ++++++++
> gcc/tree-vect-stmts.cc | 48 +++++++++++++++++--
> 3 files changed, 84 insertions(+), 7 deletions(-) create mode 100644
> gcc/testsuite/gcc.target/i386/vect-pr126789-2.c
>
> diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index
> f61335af0b9..640b2c0e63f 100644
> --- a/gcc/config/i386/mmx.md
> +++ b/gcc/config/i386/mmx.md
> @@ -2085,11 +2085,13 @@
>
> (define_mode_attr mmxxmmmode
> [(V2HF "V8HF") (V2HI "V8HI") (V2BF "V8BF")
> - (V4HF "V8HF") (V4HI "V8HI") (V4BF "V8BF")])
> + (V4HF "V8HF") (V4HI "V8HI") (V4BF "V8BF")
> + (V2SF "V4SF") (V2SI "V4SI")])
>
> (define_mode_attr mmxxmmmodelower
> [(V2HF "v8hf") (V2HI "v8hi") (V2BF "v8bf")
> - (V4HF "v8hf") (V4HI "v8hi") (V4BF "v8bf")])
> + (V4HF "v8hf") (V4HI "v8hi") (V4BF "v8bf")
> + (V2SF "v4sf") (V2SI "v4si")])
>
> (define_expand "movd_<mode>_to_sse"
> [(set (match_operand:<mmxxmmmode> 0 "register_operand") @@ -2341,6
> +2343,24 @@
> DONE;
> })
>
> +(define_expand "vcond_mask_<mode>qi"
> + [(set (match_operand:V2FI 0 "register_operand")
> + (vec_merge:V2FI
> + (match_operand:V2FI 1 "register_operand")
> + (match_operand:V2FI 2 "register_operand")
> + (match_operand:QI 3 "register_operand")))]
> + "TARGET_MMX_WITH_SSE && TARGET_AVX512VL"
> +{
> + rtx op0 = gen_reg_rtx (<mmxxmmmode>mode);
> + operands[1] = lowpart_subreg (<mmxxmmmode>mode, operands[1],
> +<MODE>mode);
> + operands[2] = lowpart_subreg (<mmxxmmmode>mode, operands[2],
> +<MODE>mode);
> + emit_insn (gen_vcond_mask_<mmxxmmmodelower>qi (op0, operands[1],
> + operands[2], operands[3]));
> + emit_move_insn (operands[0],
> + lowpart_subreg (<MODE>mode, op0,
> <mmxxmmmode>mode));
> + DONE;
> +})
> +
> (define_expand "vec_cmpv2hfqi"
> [(set (match_operand:QI 0 "register_operand")
> (match_operator:QI 1 ""
> diff --git a/gcc/testsuite/gcc.target/i386/vect-pr126789-2.c
> b/gcc/testsuite/gcc.target/i386/vect-pr126789-2.c
> new file mode 100644
> index 00000000000..85d177bc3a4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/vect-pr126789-2.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target { ! ia32 } } } */
> +/* { dg-options "-O2 -mavx512vl -fno-vect-cost-model" } */
> +
> +int foo (double g, int f, double *r, int *s) {
> + int hu = 0;
> + bool test0 = r[0] < g;
> + bool test1 = r[1] < g;
> + bool test2 = s[0] < f;
> + bool test3 = s[1] < f;
> + hu += (test0 & test2) + (test1 & test3);
> + return hu;
> +}
> +
> +/* { dg-final { scan-assembler "vcmppd" } } */
> +/* That we use vpcmpgtd and not vpcmpd is because ix86_get_mask_mode
> + does not get us QImode for MMX modes. But we should be able to
> + inter-operate with mixed SSE/AVX512 masks and vectorize the
> +reduction. */
> +/* { dg-final { scan-assembler "vpcmpgtd" } } */
> diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc index
> 7ecbc8fb391..bbd510b3cb9 100644
> --- a/gcc/tree-vect-stmts.cc
> +++ b/gcc/tree-vect-stmts.cc
> @@ -5780,12 +5780,33 @@ vectorizable_conversion (vec_info *vinfo,
> vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
> vop0 = new_temp;
> }
> - new_stmt = vect_gimple_build (vec_dest, code1, vop0);
> - new_temp = make_ssa_name (vec_dest, new_stmt);
> - gimple_set_lhs (new_stmt, new_temp);
> - vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
> + if (code1 == COND_EXPR)
> + {
> + gcc_assert (!multi_step_cvt);
> + new_stmt
> + = gimple_build_assign (vec_dest, VEC_COND_EXPR, vop0,
> + build_minus_one_cst
> + (TREE_TYPE (vec_dest)),
> + build_zero_cst (TREE_TYPE (vec_dest)));
> + new_temp = make_ssa_name (vec_dest, new_stmt);
> + gimple_set_lhs (new_stmt, new_temp);
> + vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
> + tree new_temp2 = make_ssa_name (vectype_out);
> + new_stmt = gimple_build_assign (new_temp2,
> + build1 (VIEW_CONVERT_EXPR,
> + vectype_out, new_temp));
> + vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
> + slp_node->push_vec_def (new_temp2);
> + }
> + else
> + {
> + new_stmt = vect_gimple_build (vec_dest, code1, vop0);
> + new_temp = make_ssa_name (vec_dest, new_stmt);
> + gimple_set_lhs (new_stmt, new_temp);
> + vect_finish_stmt_generation (vinfo, stmt_info, new_stmt, gsi);
>
> - slp_node->push_vec_def (new_stmt);
> + slp_node->push_vec_def (new_stmt);
> + }
> }
> break;
>
> @@ -14578,6 +14599,23 @@ supportable_indirect_convert_operation
> (code_helper code,
> return true;
> }
>
> + /* For conversions between mask types where the destination has
> + a data mode attempt a vcond_mask conversion. */
> + if (VECTOR_BOOLEAN_TYPE_P (vectype_in)
> + && VECTOR_BOOLEAN_TYPE_P (vectype_out)
> + && GET_MODE_CLASS (TYPE_MODE (vectype_out)) ==
> MODE_VECTOR_INT)
> + {
> + tree scalar_datatype
> + = build_nonstandard_integer_type (element_precision (vectype_out),
> 0);
> + tree datatype_out = build_vector_type_for_mode (scalar_datatype,
> + TYPE_MODE
> (vectype_out));
> + if (expand_vec_cond_expr_p (datatype_out, vectype_in))
> + {
> + converts.safe_push (std::make_pair (datatype_out, COND_EXPR));
> + return true;
> + }
> + }
> +
> /* For conversions between float and integer types try whether
> we can use intermediate signed integer types to support the
> conversion. */
> --
> 2.51.0