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

"H.J. Lu" <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CAMe9rOqmw+DnzCRCUu2ZKdfTh+q1cvUKncozisXrf_PHSs6B9Q@mail.gmail.com>
On Thu, Aug 13, 2026 at 5:29 PM H.J. Lu <[email protected]> wrote:
>
> On Thu, Aug 13, 2026 at 3:11 PM Richard Biener
> <[email protected]> wrote:
> >
> > On Wed, Aug 12, 2026 at 4:16 PM H.J. Lu <[email protected]> wrote:
> > >
> > > 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.
> >
> > @@ -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)))
> >
> > as you are touching this - since the inter_float also includes vector types this
> > shows the patterns lack vector validation completely.  Instead (note
> > inside_vec == inter_vec == final_vec in all cases) this should be
> >
> >        && (!inter_vec || <... vector support check ...>)
> >
> > I'll note that target_suppoorts_op_p is not the correct check here as conversion
> > support of course depends on both the source and the destination type.  The
> > appropriate function to use should be
> >
> >    supportable_convert_operation (ocvt, type, TREE_TYPE (@0), &vcode)
> >
> > the last argument is redundant, I'll remove it.  Let me handle the conversion
> > pattern adjustments, the minmax part of the patch is OK.
>
> I will wait for your adjustments.   My minmax change triggered these
> issues.   You can use my minmax change + tests to validate the
> adjustments.
>

Here is the v3 patch only with the minmax change.   I am going to check it in.

-- 
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.  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++.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.
v3-0001-match.pd-Change-the-MIN-MAX-narrowing-to-MIN-MAX-.patch (text/x-patch, 12.1 KB)
From ded12acff16364f7e93c2aef0bba4013fc60b857 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <[email protected]>
Date: Tue, 11 Aug 2026 12:39:54 +0800
Subject: [PATCH v3] 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++.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.

Signed-off-by: H.J. Lu <[email protected]>
---
 gcc/match.pd                                  | 19 ++++++-------
 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 +++++++++++++++++
 11 files changed, 200 insertions(+), 12 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

diff --git a/gcc/match.pd b/gcc/match.pd
index 02684d8a302..8841464fa1a 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4714,7 +4714,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
@@ -4724,18 +4724,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++.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..d93762f95dd
--- /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 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..660e98c76f3
--- /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 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;
+}
-- 
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.