[PATCH v2] match.pd: Change the MIN/MAX narrowing to MIN/MAX + convert

"H.J. Lu" <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CAMe9rOqPQwO=6trLH5BGbwE8hY4zg0guNWR5LDVKWEqiDZxo1w@mail.gmail.com>
On Tue, Aug 11, 2026 at 8:09 PM Richard Biener
<[email protected]> wrote:
>
> 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.
>

Here is the v2 patch.   There are no regressions on Linux/x86-64.

-- 
H.J.
"(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 update "for ocvt (convert float fix_trunc)" to replace
INTEGRAL_TYPE_P with ANY_INTEGRAL_TYPE_P to include vector int types
when supported by target, matching float conditionals which include
vector float 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/

PR middle-end/126784
PR middle-end/126788
* match.pd ((type) minmax ((wide_type) a, (wide_type) b)): Changed
to ...
(minmax ((wide_type) a, (wide_type) b)): This.
(for ocvt (convert float fix_trunc)): Replace INTEGRAL_TYPE_P
with ANY_INTEGRAL_TYPE_P and check if vector conversion is
supported.

gcc/testsuite/

PR middle-end/126784
PR middle-end/126788
* 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/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.
* gcc.target/i386/pr126788-1.c: Likewise.
v2-0001-match.pd-Change-the-MIN-MAX-narrowing-to-MIN-MAX-.patch (text/x-patch, 15.7 KB)
From 736b3afa2128386d961d651bb5599dfc96fabc60 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Tue, 11 Aug 2026 12:39:54 +0800
Subject: [PATCH v2] 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 and update "for ocvt (convert float fix_trunc)" to replace
INTEGRAL_TYPE_P with ANY_INTEGRAL_TYPE_P to include vector int types
when supported by target, matching float conditionals which include
vector float 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/

	PR middle-end/126784
	PR middle-end/126788
	* match.pd ((type) minmax ((wide_type) a, (wide_type) b)): Changed
	to ...
	(minmax ((wide_type) a, (wide_type) b)): This.
	(for ocvt (convert float fix_trunc)): Replace INTEGRAL_TYPE_P
	with ANY_INTEGRAL_TYPE_P and check if vector conversion is
	supported.

gcc/testsuite/

	PR middle-end/126784
	PR middle-end/126788
	* 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/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.
	* gcc.target/i386/pr126788-1.c: Likewise.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/match.pd                                  | 38 ++++++++++---------
 gcc/testsuite/g++.dg/tree-ssa/vec-narrow-1.C  |  3 +-
 .../g++.dg/tree-ssa/vec-narrow-minmax-2.C     |  2 +
 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 ++++++++++++
 gcc/testsuite/gcc.target/i386/pr126788-1.c    | 22 +++++++++++
 12 files changed, 234 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/i386/pr126784-1.C
 create mode 100644 gcc/testsuite/g++.target/i386/pr126784-2.C
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126784-1.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126784-2.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126784-3.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126784-4.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126784-5.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126784-6.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr126788-1.c

diff --git a/gcc/match.pd b/gcc/match.pd
index beea45357e2..0ec8636b60f 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4683,7 +4683,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
@@ -4693,18 +4693,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.  */
@@ -5816,19 +5813,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     {
       tree inside_type = TREE_TYPE (@0);
       tree inter_type = TREE_TYPE (@1);
-      int inside_int = INTEGRAL_TYPE_P (inside_type);
+      int inside_int = ANY_INTEGRAL_TYPE_P (inside_type);
       int inside_ptr = POINTER_TYPE_P (inside_type);
       int inside_float = FLOAT_TYPE_P (inside_type);
       int inside_vec = VECTOR_TYPE_P (inside_type);
       unsigned int inside_prec = element_precision (inside_type);
       int inside_unsignedp = TYPE_UNSIGNED (inside_type);
-      int inter_int = INTEGRAL_TYPE_P (inter_type);
+      int inter_int = ANY_INTEGRAL_TYPE_P (inter_type);
       int inter_ptr = POINTER_TYPE_P (inter_type);
       int inter_float = FLOAT_TYPE_P (inter_type);
       int inter_vec = VECTOR_TYPE_P (inter_type);
       unsigned int inter_prec = element_precision (inter_type);
       int inter_unsignedp = TYPE_UNSIGNED (inter_type);
-      int final_int = INTEGRAL_TYPE_P (type);
+      int final_int = ANY_INTEGRAL_TYPE_P (type);
       int final_ptr = POINTER_TYPE_P (type);
       int final_float = FLOAT_TYPE_P (type);
       int final_vec = VECTOR_TYPE_P (type);
@@ -5856,7 +5853,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (if (((inter_int && inside_int) || (inter_float && inside_float))
 	 && (final_int || final_float)
 	 && inter_prec >= inside_prec
-	 && (inter_float || inter_unsignedp == inside_unsignedp))
+	 && (inter_float
+	     || ((!inter_vec
+		  || target_supports_op_p (TREE_TYPE (@0), ocvt, optab_vector))
+		 && inter_unsignedp == inside_unsignedp)))
      (ocvt @0))
 
     /* If we have a sign-extension of a zero-extended value, we can
@@ -5921,9 +5921,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
        represent it exactly and back to an integer, we can skip the
        floating-point conversion.  */
     (if (GIMPLE /* PR66211 */
-	 && inside_int && inter_float && final_int &&
-	 (unsigned) significand_size (TYPE_MODE (inter_type))
-	 >= inside_prec - !inside_unsignedp)
+	 && inside_int && inter_float && final_int
+	 && (!inside_vec
+	     || target_supports_op_p (TREE_TYPE (@0), ocvt, optab_vector))
+	 && (unsigned) significand_size (TYPE_MODE (inter_type))
+	    >= inside_prec - !inside_unsignedp)
      (convert @0)))))))
 
 /* (float_type)(integer_type) x -> trunc (x) if the type of x matches
diff --git a/gcc/testsuite/g++.dg/tree-ssa/vec-narrow-1.C b/gcc/testsuite/g++.dg/tree-ssa/vec-narrow-1.C
index cec5b0ba345..1f863b1d4a2 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/vec-narrow-1.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/vec-narrow-1.C
@@ -1,6 +1,7 @@
 // { dg-do compile }
 // { dg-options "-O2 -fdump-tree-optimized" }
-// { dg-additional-options "-mavx512vl -mavx512dq" { target { i?86-*-* x86_64-*-* } } }
+// { dg-additional-options "-msse4" { target { i?86-*-* x86_64-*-* } } }
+// { dg-require-effective-target int128 { target { i?86-*-* x86_64-*-* } } }
 // Extension is monotone, so it commutes with the comparison and the outer
 // truncation is exact.  The argument is lanewise, so a widened vector
 // MIN/MAX feeding a truncating conversion narrows.
diff --git a/gcc/testsuite/g++.dg/tree-ssa/vec-narrow-minmax-2.C b/gcc/testsuite/g++.dg/tree-ssa/vec-narrow-minmax-2.C
index d7fb7f06f16..7df25de0942 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/vec-narrow-minmax-2.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/vec-narrow-minmax-2.C
@@ -1,5 +1,7 @@
 // { dg-do compile }
 // { dg-options "-O2 -fdump-tree-optimized" }
+// { dg-additional-options "-msse4" { target { i?86-*-* x86_64-*-* } } }
+// { dg-require-effective-target int128 { target { i?86-*-* x86_64-*-* } } }
 
 typedef int v2si __attribute__((vector_size (8)));
 typedef long long v2di __attribute__((vector_size (16)));
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 00000000000..611d67ed37a
--- /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 00000000000..3255b39b9a1
--- /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, \(%rdi\)
+**	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 00000000000..73b581b0e7c
--- /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 00000000000..f72495be5f9
--- /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, \(%rdx\)
+**	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 00000000000..928140e64ee
--- /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 00000000000..e344480c3ba
--- /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 00000000000..3b6a26e2e70
--- /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 00000000000..403239039c0
--- /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;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr126788-1.c b/gcc/testsuite/gcc.target/i386/pr126788-1.c
new file mode 100644
index 00000000000..8a76b1045db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr126788-1.c
@@ -0,0 +1,22 @@
+/* { 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
+**	ret
+**...
+*/
+
+typedef int  v2si __attribute__((vector_size (8)));
+typedef long long v2di __attribute__((vector_size (16)));
+
+v2si
+func (v2si a)
+{
+  v2di z = __builtin_convertvector (a, v2di);
+  return __builtin_convertvector (z, v2si);
+}
-- 
2.55.0
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.