[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