]> git.ipfire.org Git - thirdparty/gcc.git/commit
x86: Don't save callee-saved registers in noreturn functions
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 23 Jan 2024 14:59:51 +0000 (06:59 -0800)
committerH.J. Lu <(no_default)>
Sat, 27 Jan 2024 12:10:49 +0000 (04:10 -0800)
commit7cc9adc62cee0aa91ce834b3dd6296ce38f1d79d
tree136ccdd572744e357c4ecd852084ad8cbe51ceb0
parenta96549dce7636edfc693bf758ef27fcd8adc6161
x86: Don't save callee-saved registers in noreturn functions

There is no need to save callee-saved registers in noreturn functions
if they don't throw nor support exceptions.  We can treat them the same
as functions with no_callee_saved_registers attribute.

Adjust stack-check-17.c for noreturn function which no longer saves any
registers.

With this change, __libc_start_main in glibc 2.39, which is a noreturn
function, is changed from

__libc_start_main:
endbr64
push   %r15
push   %r14
mov    %rcx,%r14
push   %r13
push   %r12
push   %rbp
mov    %esi,%ebp
push   %rbx
mov    %rdx,%rbx
sub    $0x28,%rsp
mov    %rdi,(%rsp)
mov    %fs:0x28,%rax
mov    %rax,0x18(%rsp)
xor    %eax,%eax
test   %r9,%r9

to

__libc_start_main:
endbr64
        sub    $0x28,%rsp
        mov    %esi,%ebp
        mov    %rdx,%rbx
        mov    %rcx,%r14
        mov    %rdi,(%rsp)
        mov    %fs:0x28,%rax
        mov    %rax,0x18(%rsp)
        xor    %eax,%eax
        test   %r9,%r9

In Linux kernel 6.7.0 on x86-64, do_exit is changed from

do_exit:
        endbr64
        call   <do_exit+0x9>
        push   %r15
        push   %r14
        push   %r13
        push   %r12
        mov    %rdi,%r12
        push   %rbp
        push   %rbx
        mov    %gs:0x0,%rbx
        sub    $0x28,%rsp
        mov    %gs:0x28,%rax
        mov    %rax,0x20(%rsp)
        xor    %eax,%eax
        call   *0x0(%rip)        # <do_exit+0x39>
        test   $0x2,%ah
        je     <do_exit+0x8d3>

to

do_exit:
        endbr64
        call   <do_exit+0x9>
        sub    $0x28,%rsp
        mov    %rdi,%r12
        mov    %gs:0x28,%rax
        mov    %rax,0x20(%rsp)
        xor    %eax,%eax
        mov    %gs:0x0,%rbx
        call   *0x0(%rip)        # <do_exit+0x2f>
        test   $0x2,%ah
        je     <do_exit+0x8c9>

I compared GCC master branch bootstrap and test times on a slow machine
with 6.6 Linux kernels compiled with the original GCC 13 and the GCC 13
with the backported patch.  The performance data isn't precise since the
measurements were done on different days with different GCC sources under
different 6.6 kernel versions.

GCC master branch build time in seconds:

before                after                  improvement
30043.75user          30013.16user           0%
1274.85system         1243.72system          2.4%

GCC master branch test time in seconds (new tests added):

before                after                  improvement
216035.90user         216547.51user          0
27365.51system        26658.54system         2.6%

gcc/

PR target/38534
* config/i386/i386-options.cc (ix86_set_func_type): Don't
save and restore callee saved registers for a noreturn function
with nothrow or compiled with -fno-exceptions.

gcc/testsuite/

PR target/38534
* gcc.target/i386/pr38534-1.c: New file.
* gcc.target/i386/pr38534-2.c: Likewise.
* gcc.target/i386/pr38534-3.c: Likewise.
* gcc.target/i386/pr38534-4.c: Likewise.
* gcc.target/i386/stack-check-17.c: Updated.
gcc/config/i386/i386-options.cc
gcc/testsuite/gcc.target/i386/pr38534-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr38534-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr38534-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr38534-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/stack-check-17.c