[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;
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.