https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126214

            Bug ID: 126214
           Summary: Optimization regression when returning struct by-value
                    (x86_64)
           Product: gcc
           Version: 16.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gcc at lombera dot dev
  Target Milestone: ---

Reproducer: https://godbolt.org/z/jMEb9Ecfs

(An apology if this is a duplicate, I tried to look for duplicates by
don't the proper compiler/GCC-internal terminology to search for)

I found an optimization regression reproducible with following test
case:

typedef struct {
        int a, b, c, d;
} S4_32;

S4_32 init4_32(int x) {
        S4_32 s = {x+1, x+2, x+3, x+4};

        return s;
}

When compiled with GCC 16.1 (as shipped by Debian) at -O2/3 it produces
following assembly:

init4_32:
        leal    1(%rdi), %eax
        leal    2(%rdi), %esi
        xorl    %edx, %edx
        movabsq $-4294967296, %r8
        salq    $32, %rsi
        movl    %eax, %ecx
        orq     %rsi, %rcx
        leal    3(%rdi), %esi
        movq    %rcx, %rax
        movq    %rdx, %rcx
        andq    %r8, %rcx
        orq     %rsi, %rcx
        leal    4(%rdi), %esi
        salq    $32, %rsi
        movl    %ecx, %ecx
        orq     %rsi, %rcx
        movq    %rcx, %rdx
        ret

There is a lot of unnecessary instructions there.  After further
investigation, I found it's a regression first introduced in GCC 14.1
(which produces even more instructions).  In comparison, this is what
GCC 13.4 produces:

init4_32:
        leal    2(%rdi), %edx
        leal    1(%rdi), %eax
        salq    $32, %rdx
        leal    4(%rdi), %ecx
        orq     %rdx, %rax
        salq    $32, %rcx
        leal    3(%rdi), %edx
        orq     %rcx, %rdx
        ret

The "verbose" assembly is only generated when the whole rax/rdx
registers are being used to return the result, e.g. it doesn't happen
when the struct in the example only have 2/3 fields (see the linked
Godbolt reproducer).

The regression is observable since GCC 14.1 and still present in trunk.

According to git-bisect, the regression was first introduced by this
commit:

commit bdf2737cda53a83332db1a1a021653447b05a7e7
Author: Roger Sayle <[email protected]>
Date:   Fri Jul 7 20:39:58 2023 +0100

    i386: Improve __int128 argument passing (in ix86_expand_move).

Reply via email to