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