#How to prevent useless save/restore of a callee save?

1 messages · Page 1 of 1 (latest)

flint ocean
#

See https://godbolt.org/z/1MxnqKsYs

export fn sampleTailCaller() noreturn {
    asm volatile("" : : : "rbx");
    const next: *const fn() callconv(.C) noreturn = @ptrFromInt(0xabcdef);
    @call(.always_tail, next, .{});
}
sampleTailCaller:
        push    rbx
        mov     eax, 11259375
        pop     rbx
        jmp     rax

Is it possible to avoid push rbx/pop rbx pair here without removing the asm statement?

#

This comes up when writing a VM in zig. As zig doesn't have computed gotos, you have to rely on tail calls. There are a few problems with callee-saves it seems though

nova galleon
#

iirc zig's "auto" calling convention is a derivative of sysv, which says that rbx must be callee-saved

#

if you don't want that, choose a calling convention that suits your purpose

flint ocean
#

well, what I am trying to do here is to make sure that function can use any registers without preserving their value first

#

this should be fine, as all these functions are noreturn, so they really shouldn't bother about preserving values from callee

nova galleon
#

do the functions have any arguments?

flint ocean
#

they would, yeah

nova galleon
#

on x86_64?

flint ocean
#

preferrably any arch

#

I want this code to be generic

nova galleon
#

unfortunately that certainly isn't possible, I looked around a bit and it seems like you're probably going to have to use naked functions and make your own "calling convention"

#

most calling conventions have callee saved registers

flint ocean
#

that's understandable, what I do not seem to understand is why does zig bother with saving those in the first place - it is not like its going to return back to the function

#

the type is noreturn

#

it's probably llvm's fault I imagine

#

I will just hope that I don't use many registers and llvm's regalloc will never pick callee saves

nova galleon
#

thats a fair point, it shouldn't need to save them in a noreturn; as for the last point: there are very few registers that are caller saved, so good luck

vapid tundra
#

The push/pop rbx is precisely because the asm indicates it as a clobber

#

rbx is caller saved, so if you clobber that then the compiler has to save/restore it. Something like rax OTOH is callee saved so if you clobber that no save/restore is needed as the compiler doesnt use rax before that asm

flint ocean
#

How to prevent useless save/restore of a caller save?

#

How to prevent useless save/restore of a callee save?

stoic ridge
nova galleon
# stoic ridge but your asm is 100% opaque to zig

Their argument is that callee saved registers shouldn't be saved in a noreturn function, because they're only saved because the caller may be using them: but in a noreturn function you never return to the caller