[gcc r17-3355] match.pd: Change the MIN/MAX narrowing to MIN/MAX + convert
"H.J. Lu via Gcc-cvs" <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:a6173e867de7f9e7a6f060e5a208a4290d19ba51 commit r17-3355-ga6173e867de7f9e7a6f060e5a208a4290d19ba51 Author: H.J. Lu <[email protected]> Date: Tue Aug 18 17:57:08 2026 +0800 match.pd: Change the MIN/MAX narrowing to MIN/MAX + convert "(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. 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/ PR middle-end/126784 * match.pd ((type) minmax ((wide_type) a, (wide_type) b)): Changed to ... (minmax ((wide_type) a, (wide_type) b)): This. gcc/testsuite/ PR middle-end/126784 * 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/pr126784-3.c: Likewise. * gcc.target/i386/pr126784-4.c: Likewise. * gcc.target/i386/pr126784-5.c: Likewise. * gcc.target/i386/pr126784-6.c: Likewise. Signed-off-by: H.J. Lu <[email protected]> Diff: --- gcc/match.pd | 19 ++++++++----------- gcc/testsuite/g++.target/i386/pr126784-1.C | 26 ++++++++++++++++++++++++++ gcc/testsuite/g++.target/i386/pr126784-2.C | 28 ++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr126784-1.c | 24 ++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr126784-2.c | 27 +++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr126784-3.c | 11 +++++++++++ gcc/testsuite/gcc.target/i386/pr126784-4.c | 26 ++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr126784-5.c | 21 +++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr126784-6.c | 25 +++++++++++++++++++++++++ 9 files changed, 196 insertions(+), 11 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index 0c399a11f8de..680f15cc89d5 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -4753,7 +4753,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && !TYPE_OVERFLOW_SANITIZED (type)) (minus (minmax @0 @1) @2)))) -/* (type) minmax ((wide_type) a, (wide_type) b) -> minmax (a, b) +/* minmax ((wide_type) a, (wide_type) b) -> (wide_type) minmax (a, b) when type matches the type of a and b, and wide_type is a wider type with the same signedness as type. Extension is monotone, so it commutes with the comparison, and the truncation is then exact. The @@ -4763,18 +4763,15 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (for minmax (min max) MINMAX (MIN_EXPR MAX_EXPR) (simplify - (convert (minmax:c@4 (convert@2 @0) (convert@3 @1))) + (minmax (convert @0) (convert @1)) (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 (TREE_TYPE (@0), TREE_TYPE (@1)) + && element_precision (TREE_TYPE (@0)) < element_precision (type) + && TYPE_UNSIGNED (TREE_TYPE (@0)) == TYPE_UNSIGNED (type) && (!VECTOR_TYPE_P (type) - || (single_use (@4) - && target_supports_op_p (type, MINMAX, optab_vector)))) - (minmax @0 @1)))) + || target_supports_op_p (TREE_TYPE (@0), MINMAX, optab_vector))) + (convert (minmax @0 @1))))) /* max (a, a + CST) -> a + CST where CST is positive. */ /* max (a, a + CST) -> a where CST is negative. */ diff --git a/gcc/testsuite/g++.target/i386/pr126784-1.C b/gcc/testsuite/g++.target/i386/pr126784-1.C new file mode 100644 index 000000000000..611d67ed37ab --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr126784-1.C @@ -0,0 +1,26 @@ +/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-options "-O2 -march=x86-64 -msse4 -std=c++17" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**_Z4funcDv2_iS_: +**.LFB0: +** .cfi_startproc +** pminsd %xmm1, %xmm0 +** ret +** .cfi_endproc +**... +*/ + +typedef int v2si __attribute__((vector_size (8))); +typedef long long v2di __attribute__((vector_size (16))); + +v2si +func (v2si a, v2si b) +{ + v2di x = __builtin_convertvector (a, v2di); + v2di y = __builtin_convertvector (b, v2di); + v2di z = x < y ? x : y; + return __builtin_convertvector (z, v2si); +} diff --git a/gcc/testsuite/g++.target/i386/pr126784-2.C b/gcc/testsuite/g++.target/i386/pr126784-2.C new file mode 100644 index 000000000000..d93762f95dd1 --- /dev/null +++ b/gcc/testsuite/g++.target/i386/pr126784-2.C @@ -0,0 +1,28 @@ +/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-options "-O2 -march=x86-64 -msse4 -std=c++17" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**_Z4funcDv2_iS_PDv2_x: +**.LFB0: +** .cfi_startproc +** pminsd %xmm1, %xmm0 +** pmovsxdq %xmm0, %xmm1 +** movaps %xmm1, \(%[er]di\) +** ret +**... +*/ + +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); +} diff --git a/gcc/testsuite/gcc.target/i386/pr126784-1.c b/gcc/testsuite/gcc.target/i386/pr126784-1.c new file mode 100644 index 000000000000..73b581b0e7c1 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126784-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-options "-O2" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** cmpl %esi, %edi +** movl %esi, %eax +** cmovle %edi, %eax +** ret +**... +*/ + +int +func (int a, int b) +{ + long long int x = a; + long long int y = b; + long long int z = x < y ? x : y; + return z; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126784-2.c b/gcc/testsuite/gcc.target/i386/pr126784-2.c new file mode 100644 index 000000000000..660e98c76f35 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126784-2.c @@ -0,0 +1,27 @@ +/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-options "-O2" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** cmpl %esi, %edi +** movl %esi, %eax +** cmovle %edi, %eax +** movslq %eax, %rcx +** movq %rcx, \(%[er]dx\) +** ret +**... +*/ + +int +func (int a, int b, long long int *p) +{ + long long int x = a; + long long int y = b; + long long int z = x < y ? x : y; + *p = z; + return z; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126784-3.c b/gcc/testsuite/gcc.target/i386/pr126784-3.c new file mode 100644 index 000000000000..928140e64eec --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126784-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=x86-64" } */ + +extern char *var1; +extern int var2; + +void +func (void) +{ + var2 = var1[1] + var1[0]; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126784-4.c b/gcc/testsuite/gcc.target/i386/pr126784-4.c new file mode 100644 index 000000000000..e344480c3baf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126784-4.c @@ -0,0 +1,26 @@ +/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-options "-O2 -march=x86-64" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movdqa .LC0\(%rip\), %xmm0 +** movups %xmm0, var\(%rip\) +** movdqa .LC1\(%rip\), %xmm0 +** movups %xmm0, var\+16\(%rip\) +** ret +**... +*/ + +extern unsigned int var[8]; + +void +func (void) +{ + int i; + for (i = 0; i < 8; i++) + var[i] = (float) i; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126784-5.c b/gcc/testsuite/gcc.target/i386/pr126784-5.c new file mode 100644 index 000000000000..3b6a26e2e70b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126784-5.c @@ -0,0 +1,21 @@ +/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-options "-O2 -march=x86-64" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movl \$34, var\(%rip\) +** ret +**... +*/ + +extern unsigned int var; + +void +func (void) +{ + var = (float) 34; +} diff --git a/gcc/testsuite/gcc.target/i386/pr126784-6.c b/gcc/testsuite/gcc.target/i386/pr126784-6.c new file mode 100644 index 000000000000..403239039c03 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr126784-6.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target { *-*-linux* && { ! ia32 } } } } */ +/* { dg-options "-O2 -march=x86-64" } */ +/* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ +/* { dg-final { check-function-bodies "**" "" "" { target "*-*-*" } {^\t?\.} } } */ + +/* +**func: +**.LFB0: +** .cfi_startproc +** movl %edi, %edi +** pxor %xmm0, %xmm0 +** cvtsi2ssq %rdi, %xmm0 +** cvttss2siq %xmm0, %rax +** movl %eax, var\(%rip\) +** ret +**... +*/ + +extern unsigned int var; + +void +func (unsigned int i) +{ + var = (float) i; +}