On Tue, Aug 11, 2026 at 2:06 PM Richard Biener
<[email protected]> wrote:
>
> 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.

Just to say, inside_float and friends _do_ include vector float types
(and complex float types).
So consistency would ask for the use of ANY_INTEGRAL_TYPE and opting
out of vectors
(and complex?) explicitly where needed.

> > [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