[Bug target/126619] New: [17 Regression] Slowdown of s116 from TSVC on x86_64 since r17-2876-gf0bd50e8317926

"pheeck at gcc dot gnu.org via Gcc-bugs" <[email protected]> Mon, 03 Aug 2026 16:10:59 +0000
Newsgroups gmane.comp.gcc.bugs
Message-ID <[email protected]/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D126619

            Bug ID: 126619
           Summary: [17 Regression] Slowdown of s116 from TSVC on x86_64
                    since r17-2876-gf0bd50e8317926
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: missed-optimization
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: pheeck at gcc dot gnu.org
                CC: sayle at gcc dot gnu.org
  Target Milestone: ---
              Host: x86_64-pc-linux-gnu
            Target: x86_64-pc-linux-gnu

I observe slowdowns of the s116 benchmark from the TSVC benchmark suite.

AMD zen2:

-O2 generic march
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D176.815.0

-Ofast -march=3Dnative
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D171.815.0


Intel Ice Lake (3rd generation Xeon):

-O2 generic march
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D466.815.0

-Ofast -march=3Dnative
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D463.815.0


AMD zen3:

-O2 generic march
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D286.815.0

-Ofast -march=3Dnative
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D283.815.0


AMD zen4:

-O2 generic march
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D556.815.0


AMD zen5:

-O2 generic march
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D994.815.0

-Ofast -march=3Dnative
https://lnt.opensuse.org/db_default/v4/CPP/graph?plot.0=3D987.815.0


I extracted the benchmark from the benchmark suite:

--- mytestcase.c ---
#include <time.h>=20=20=20=20
#include <stdio.h>=20=20=20=20
#include <stdlib.h>=20=20=20=20
#include <string.h>=20=20=20=20
#include <math.h>=20=20=20=20
#include <sys/time.h>=20=20=20=20

#define ARRAY_ALIGNMENT 64=20=20=20=20
#define LEN_1D 32000=20=20=20=20
#define iterations 100000=20=20=20=20
extern __attribute__((aligned(ARRAY_ALIGNMENT))) float a[LEN_1D];=20=20=20=
=20
int dummy(float[LEN_1D]);=20=20=20=20
void initialise_a();=20=20=20=20

__attribute__((aligned(ARRAY_ALIGNMENT))) float a[LEN_1D];=20=20=20=20

int main()=20=20=20=20
{=20=20=20=20

//    linear dependence testing=20=20=20=20

    initialise_a();=20=20=20=20

    for (int nl =3D 0; nl < iterations*10; nl++) {=20=20=20=20
        for (int i =3D 0; i < LEN_1D - 5; i +=3D 5) {=20=20=20=20
            a[i] =3D a[i + 1] * a[i];=20=20=20=20
            a[i + 1] =3D a[i + 2] * a[i + 1];=20=20=20=20
            a[i + 2] =3D a[i + 3] * a[i + 2];=20=20=20=20
            a[i + 3] =3D a[i + 4] * a[i + 3];=20=20=20=20
            a[i + 4] =3D a[i + 5] * a[i + 4];=20=20=20=20
        }=20=20=20=20
        dummy(a);=20=20=20=20
    }=20=20=20=20

    return 0;=20=20=20=20
}
--- ---

--- mytestcase2.c ---
#include <stdio.h>=20=20=20
#include <stdlib.h>=20=20=20
#include <malloc.h>=20=20=20=20
#include <string.h>=20=20=20=20
#include <math.h>=20=20=20=20

#define ARRAY_ALIGNMENT 64
#define LEN_1D 32000=20=20=20=20=20=20=20=20=20=20
extern __attribute__((aligned(ARRAY_ALIGNMENT))) float a[LEN_1D];

void initialise_a()=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20
{=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20
    for (int i =3D 0; i < LEN_1D; i++) {
        a[i] =3D 1.;
    }=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20=20=20=20=20=20=20=20
}=20=20=20=20

int dummy(float a[LEN_1D])
{=20=20=20=20
    return 0;=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=
=20=20
}
--- ---

If I build GCC from r17-2876, compile the testcase and run it, I get longer
runtime than with r17-2875 GCC.

gcc-r17-2876 -O2 mytestcase{,2}.c -o tsvc
time ./tsvc
real    0m6.224s
user    0m6.223s
sys     0m0.000s

gcc-r17-2875 -O2 mytestcase{,2}.c -o tsvc
time ./tsvc
real    0m4.665s
user    0m4.665s
sys     0m0.000s

(I did this experiment on an AMD Zen5 machine)

Thus, I believe this slowdown is caused by r17-2876-gf0bd50e8317926

commit f0bd50e831792692ffcedf288b312167a9339260
Author:     Roger Sayle <[email protected]>
AuthorDate: Sat Aug 1 17:51:02 2026 +0100
Commit:     Roger Sayle <[email protected]>
CommitDate: Sat Aug 1 17:53:52 2026 +0100

    x86 SSE: Improved vector initialization/construction.


Here's a diff of the disassembly of the main function. The - lines are
r17-2875, the + lines are r17-2876.

diff -u --color=3Dauto tsvc-before-suspect.s tsvc-suspect.s
--- tsvc-before-suspect.s       2026-08-03 17:50:27.178228585 +0200
+++ tsvc-suspect.s      2026-08-03 17:50:26.253068980 +0200
@@ -1,5 +1,5 @@

-tsvc-before-suspect:     file format elf64-x86-64
+tsvc-suspect:     file format elf64-x86-64


 Disassembly of section .init:
@@ -16,42 +16,38 @@

 Disassembly of section .text:

-0000000000401040 <main>:
+0000000000401020 <main>:
 53                     push   %rbx
 bb 40 42 0f 00         mov    $0xf4240,%ebx
-e8 95 01 00 00         call   4011e0 <initialise_a>
-f3 0f 10 05 2d 30 00   movss  0x302d(%rip),%xmm0        # 404080 <a>
+e8 75 01 00 00         call   4011a0 <initialise_a>
+f3 0f 10 05 4d 30 00   movss  0x304d(%rip),%xmm0        # 404080 <a>
 00=20
 b8 80 40 40 00         mov    $0x404080,%eax
-0f 1f 80 00 00 00 00   nopl   0x0(%rax)
-66 66 2e 0f 1f 84 00   data16 cs nopw 0x0(%rax,%rax,1)
-00 00 00 00=20
-66 66 2e 0f 1f 84 00   data16 cs nopw 0x0(%rax,%rax,1)
-00 00 00 00=20
-66 66 2e 0f 1f 84 00   data16 cs nopw 0x0(%rax,%rax,1)
-00 00 00 00=20
-f3 0f 10 48 10         movss  0x10(%rax),%xmm1
-f3 0f 10 58 0c         movss  0xc(%rax),%xmm3
+0f 1f 84 00 00 00 00   nopl   0x0(%rax,%rax,1)
+00=20
+66 0f 7e c2            movd   %xmm0,%edx
+0f 10 48 04            movups 0x4(%rax),%xmm1
+f3 0f 10 50 08         movss  0x8(%rax),%xmm2
+f3 0f 10 58 10         movss  0x10(%rax),%xmm3
+66 0f 6e c2            movd   %edx,%xmm0
 48 83 c0 14            add    $0x14,%rax
-f3 0f 10 60 f4         movss  -0xc(%rax),%xmm4
-0f 10 50 f0            movups -0x10(%rax),%xmm2
-0f 14 d9               unpcklps %xmm1,%xmm3
-0f 14 c4               unpcklps %xmm4,%xmm0
-0f c6 d2 90            shufps $0x90,%xmm2,%xmm2
-0f 16 c3               movlhps %xmm3,%xmm0
-0f 59 c2               mulps  %xmm2,%xmm0
+0f 14 c2               unpcklps %xmm2,%xmm0
+f3 0f 10 50 f8         movss  -0x8(%rax),%xmm2
+0f 14 d3               unpcklps %xmm3,%xmm2
+0f c6 c9 90            shufps $0x90,%xmm1,%xmm1
+0f 16 c2               movlhps %xmm2,%xmm0
+0f 59 c1               mulps  %xmm1,%xmm0
+f3 0f 10 48 fc         movss  -0x4(%rax),%xmm1
 0f 11 40 ec            movups %xmm0,-0x14(%rax)
 f3 0f 10 00            movss  (%rax),%xmm0
 f3 0f 59 c8            mulss  %xmm0,%xmm1
 f3 0f 11 48 fc         movss  %xmm1,-0x4(%rax)
 48 3d 6c 34 42 00      cmp    $0x42346c,%rax
-75 c0                  jne    401080 <main+0x40>
+75 b3                  jne    401040 <main+0x20>
 bf 80 40 40 00         mov    $0x404080,%edi
-e8 56 01 00 00         call   401220 <dummy>
+e8 49 01 00 00         call   4011e0 <dummy>
 83 eb 01               sub    $0x1,%ebx
-0f 85 78 ff ff ff      jne    40104b <main+0xb>
+75 8f                  jne    40102b <main+0xb>
 31 c0                  xor    %eax,%eax
 5b                     pop    %rbx
 c3                     ret
-66 0f 1f 84 00 00 00   nopw   0x0(%rax,%rax,1)
-00 00


Different vector instructions are used, but I didn't dive deep enough into =
this
to understand why the ones chosen by r17-2875 perform better.  Roger, can y=
ou
make sense of this?  Can something reasonable be done to make GCC emit the
faster instructions in this testcase?=