On Tue, 13 Oct 2026, Igor Shevlyakov wrote:

> The pattern that merges c = VEC_PERM_EXPR <a, b> into
> d = VEC_PERM_EXPR <c, c> also matches when c is view-converted before d
> uses it.  It asks can_vec_perm_const_p about the new permute and about
> both original ones with d's mode as the result mode and a's mode as the
> input mode.  When the conversion changes the element type, e.g. from
> short to _Float16, that is a permute between two different modes, which
> the pattern never emits and no target supports.  All three queries then
> fail, "one of the original permutes can't be handled" holds, and the
> permutes are merged even when both are supported and the merged one is
> not.  Vector lowering then expands the result element by element: on
> x86_64 with SSE2 the testcase goes from 3 to 13 instructions.
> 
> Query each permute with its own modes instead: the new one has a's
> type (it is view-converted to d's type afterwards), the inner one
> produces c from a and b, and the outer one produces d from the
> converted c.
> 
> Assisted-by: Claude Opus 5.5
> 
>       PR middle-end/127882
> 
> gcc/ChangeLog:
> 
>       * match.pd (vec_perm (view_convert? (vec_perm)) merge): Query
>       each permute with its own modes.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.target/i386/pr127882.c: New test.
> 
> Signed-off-by: Igor Shevlyakov <[email protected]>
> ---
>  gcc/match.pd                             | 13 ++++++++----
>  gcc/testsuite/gcc.target/i386/pr127882.c | 27 ++++++++++++++++++++++++
>  2 files changed, 36 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr127882.c
> 
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 6984af44582..fcb67a8dcc0 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -12875,7 +12875,11 @@ and,
>   (if (TYPE_VECTOR_SUBPARTS (type).is_constant ())
>    (with
>     {
> +     /* c may be view-converted before d uses it, so query each permute
> +     with its own modes.  The new permute has the type of a.  */
>       machine_mode result_mode = TYPE_MODE (type);
> +     machine_mode c_op_mode = TYPE_MODE (TREE_TYPE (@0));
> +     machine_mode c_mode = TYPE_MODE (TREE_TYPE (@1));
>       machine_mode op_mode = TYPE_MODE (TREE_TYPE (@2));

I think the naming is now confusing, result_mode would be d_mode,
op_mode is ab_mode and since the comment does not show the VIEW_CONVERT
c and c_op mode do not match anything.

I would suggest to use op{0,1,2}_mode to match the capture IDs
and to adjust the comment to mention the VIEW_CONVERT and replace
a,b,c,d with op{0,1,2} and result.

OK with that change or whatever similar change to make this more
obvious.

Richard.

>       int nelts = TYPE_VECTOR_SUBPARTS (type).to_constant ();
>       vec_perm_indices sel0, sel1;
> @@ -12898,11 +12902,12 @@ and,
>         If one or both of the original VEC_PERM_EXPRs can't be
>         handled and the new one can't be either, don't increase
>         number of VEC_PERM_EXPRs that can't be handled.  */
> -       if (can_vec_perm_const_p (result_mode, op_mode, sel2, false)
> +       if (can_vec_perm_const_p (op_mode, op_mode, sel2, false)
>          || (single_use (@0)
> -            ? (!can_vec_perm_const_p (result_mode, op_mode, sel0, true)
> -               || !can_vec_perm_const_p (result_mode, op_mode, sel1, true))
> -            : !can_vec_perm_const_p (result_mode, op_mode, sel1, true)))
> +            ? (!can_vec_perm_const_p (c_mode, op_mode, sel0, true)
> +               || !can_vec_perm_const_p (result_mode, c_op_mode, sel1,
> +                                         true))
> +            : !can_vec_perm_const_p (result_mode, c_op_mode, sel1, true)))
>        op0 = vec_perm_indices_to_tree (TREE_TYPE (@5), sel2);
>       }
>       (if (op0)
> diff --git a/gcc/testsuite/gcc.target/i386/pr127882.c 
> b/gcc/testsuite/gcc.target/i386/pr127882.c
> new file mode 100644
> index 00000000000..531a30b3c45
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr127882.c
> @@ -0,0 +1,27 @@
> +/* PR middle-end/127882 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -msse2 -mno-ssse3 -fdump-tree-optimized" } */
> +
> +typedef short v8hi __attribute__((vector_size(16)));
> +typedef _Float16 v8hf __attribute__((vector_size(16)));
> +
> +/* Both permutes are supported, but the merged one is not: keep them, also
> +   with a VIEW_CONVERT_EXPR between them.  */
> +
> +v8hi
> +f1 (v8hi a, v8hi b)
> +{
> +  v8hi c = __builtin_shufflevector (a, b, 8, 0, 9, 1, 10, 2, 11, 3);
> +  return __builtin_shufflevector (c, c, 1, 1, 0, 0, 4, 5, 7, 7);
> +}
> +
> +v8hf
> +f2 (v8hi a, v8hi b)
> +{
> +  v8hi c = __builtin_shufflevector (a, b, 8, 0, 9, 1, 10, 2, 11, 3);
> +  v8hf e = (v8hf) c;
> +  return __builtin_shufflevector (e, e, 1, 1, 0, 0, 4, 5, 7, 7);
> +}
> +
> +/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 4 "optimized" } } */
> +/* { dg-final { scan-tree-dump-not "BIT_FIELD_REF" "optimized" } } */
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to