On Tue, Aug 11, 2026 at 1:53 PM H.J. Lu <[email protected]> wrote:
>
> On Tue, Aug 11, 2026 at 7:20 PM Richard Biener
> <[email protected]> wrote:
> >
> > On Tue, Aug 11, 2026 at 1:13 PM H.J. Lu <[email protected]> wrote:
> > >
> > > "(type) minmax ((wide_type) a, (wide_type) b) to minmax (a, b)" is limited
> > > to the single use of the result. It doesn't support:
> > >
> > > typedef int v2si __attribute__((vector_size (8)));
> > > typedef long long v2di __attribute__((vector_size (16)));
> > >
> > > v2si
> > > func (v2si a, v2si b, v2di *p)
> > > {
> > >   v2di x = __builtin_convertvector (a, v2di);
> > >   v2di y = __builtin_convertvector (b, v2di);
> > >   v2di z = x < y ? x : y;
> > >   *p = z;
> > >   return __builtin_convertvector (z, v2si);
> > > }
> > >
> > > Change it to
> > >
> > > minmax ((wide_type) a, (wide_type) b) -> (wide_type) minmax (a, b)
> > >
> > > instead and add "(type) ((wide_type) a) -> a" for integer types.  Now
> > > we generate
> > >
> > > pminsd %xmm1, %xmm0
> > > pmovsxdq %xmm0, %xmm1
> > > movaps %xmm1, (%rdi)
> > >
> > > instead of
> > >
> > > pmovsxdq %xmm0, %xmm2
> > > pmovsxdq %xmm1, %xmm1
> > > movdqa %xmm2, %xmm0
> > > movdqa %xmm2, %xmm3
> > > pcmpgtq %xmm1, %xmm0
> > > pblendvb %xmm0, %xmm1, %xmm3
> > > movdqa %xmm3, %xmm0
> > > movaps %xmm3, (%rdi)
> > > shufps $232, %xmm3, %xmm0
> > >
> > > gcc/
> >
> >   (simplify
> > -  (convert (minmax:c@4 (convert@2 @0) (convert@3 @1)))
> > +  (minmax:c (convert@2 @0) (convert@3 @1))
> >
> > no need for :c on minmax
>
> Removed.
>
> >    (if (ANY_INTEGRAL_TYPE_P (type)
> > -       && ANY_INTEGRAL_TYPE_P (TREE_TYPE (@2))
> > -       && types_match (type, TREE_TYPE (@0))
> > -       && types_match (type, TREE_TYPE (@1))
> > -       && types_match (TREE_TYPE (@2), TREE_TYPE (@3))
> > -       && element_precision (TREE_TYPE (@2)) > element_precision (type)
> > -       && TYPE_UNSIGNED (TREE_TYPE (@2)) == TYPE_UNSIGNED (type)
> > +       && ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
> > +       && types_match (type, TREE_TYPE (@2))
> > +       && types_match (type, TREE_TYPE (@3))
> >
> > the last two are redundant
>
> Removed.
>
> > +       && types_match (TREE_TYPE (@0), TREE_TYPE (@1))
> > +       && element_precision (TREE_TYPE (@0)) < element_precision (type)
> > +       && TYPE_UNSIGNED (TREE_TYPE (@0)) == TYPE_UNSIGNED (type)
> >
> > +/* (type) ((wide_type) a) -> a.  */
> > +(simplify
> > + (convert (convert@1 @0))
> > +  (if (ANY_INTEGRAL_TYPE_P (type)
> > +       && ANY_INTEGRAL_TYPE_P (TREE_TYPE (@1))
> > +       && types_match (type, TREE_TYPE (@0))
> > +       && element_precision (type) < element_precision (TREE_TYPE (@1)))
> > +   @0))
> >
> > two-level conversions are already handled elsewhere, no need to add a
> > new pattern.
>
> Where is it handled?  Without it, I got

It should be handled by

/* Handle cases of two conversions in a row.  */
(for ocvt (convert float fix_trunc)
 (for icvt (convert float)
  (simplify
   (ocvt (icvt@1 @0))
   (with
    {
...

Possibly

    /* In addition to the cases of two conversions in a row
       handled below, if we are converting something to its own
       type via an object of identical or wider precision, neither
       conversion is needed.  */
    (if (((GIMPLE && useless_type_conversion_p (type, inside_type))
          || (GENERIC
              && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (inside_type)))
         && (((inter_int || inter_ptr) && final_int)
             || (inter_float && final_float))
         && inter_prec >= final_prec)
     (ocvt @0))

is too strict in that inter_int checks INTEGRAL_TYPE_P, not ANY_INTEGRAL_TYPE_P.
To avoid adjusting everything I'd add inside_any_int, etc. variables, otherwise
a conservative transform would be to use ANY_INTEGRAL_TYPE_P for
inside_int, etc.
and replace uses with inside_int && !inside_vec, omitting !inside_vec
for cases we have
convinced ourselves are fine.

> [hjl@gnu-zen4-1 vect-1]$ cat f.c
> typedef int  v2si __attribute__((vector_size (8)));
> typedef long long v2di __attribute__((vector_size (16)));
> v2si
> f2 (v2si a)
> {
>   v2di z = __builtin_convertvector (a, v2di);
>   return __builtin_convertvector (z, v2si);
> }
> [hjl@gnu-zen4-1 vect-1]$
> /export/build/gnu/tools-build/gcc-gitlab-debug/build-x86_64-linux/gcc/xgcc
> -B/export/build/gnu/tools-build/gcc-gitlab-debug/build-x86_64-linux/gcc/
> -O2 -msse4 -S f.c
> [hjl@gnu-zen4-1 vect-1]$ cat f.s
> .file "f.c"
> .text
> .p2align 4
> .globl f2
> .type f2, @function
> f2:
> .LFB0:
> .cfi_startproc
> pmovsxdq %xmm0, %xmm0
> shufps $232, %xmm0, %xmm0
> ret
> .cfi_endproc
> .LFE0:
> .size f2, .-f2
> .ident "GCC: (GNU) 17.0.0 20260811 (experimental)"
> .section .note.GNU-stack,"",@progbits
> [hjl@gnu-zen4-1 vect-1]$
>
> > Richard.
> >
> >
> > > PR middle-end/126784
> > > * match.pd ((type) minmax ((wide_type) a, (wide_type) b)): Changed
> > > to ...
> > > (minmax ((wide_type) a, (wide_type) b)): This.
> > > ((type) ((wide_type) a) -> a) New.
> > >
> > > gcc/testsuite/
> > >
> > > PR middle-end/126784
> > > * g++.dg/tree-ssa/vec-narrow-1.C: Use -msse4 and require int128
> > > for x86.
> > > * g++.dg/tree-ssa/vec-narrow-minmax-2.C: Likewise.
> > > * g++.target/i386/pr126784-1.C: New test.
> > > * g++.target/i386/pr126784-2.C: Likewise.
> > > * gcc.target/i386/pr126784-1.c: Likewise.
> > > * gcc.target/i386/pr126784-2.c: Likewise.
> > > * gcc.target/i386/pr126788-1.c: Likewise.
> > >
> > > --
> > > H.J.
>
>
>
> --
> H.J.

Reply via email to