0
votes

Does gcc compiler use push/pop for register backup if I dont write anything in clobber list? What happens for input and output list registers?

I will make a short asm inline that saves some general purpose registers to XMM/YMM registers then plays on general purpose registers. In the end, original values are returned from XMM/YMM registers to general purpose ones. Would compiler put push/pops to save them anyway?

How can I tell GCC compiler: "dont push/pop enything for me, I am using XMM/YMM for that purpose . Maybe I will do push/pops myself"

Something like:

__asm__ __volatile__ (
        ".intel_syntax noprefix \n\t"
        "movd xmm0,eax \n\t"//storing in xmm registers instead of   pushing
        "movd xmm1,ebx \n\t"
        "movd xmm2,ecx \n\t"
        "movd xmm3,edx \n\t"
        "movd xmm4,edi \n\t" // end of  backups
        //.
        //... doing work
        //.
        "movd edi,xmm4 \n\t"
        "movd edx,xmm3 \n\t"
        "movd ecx,xmm2 \n\t"
        "movd ebx,xmm1 \n\t"
        "movd eax,xmm0 \n\t" // end of pops

        ://outputs
        "=g"(x[0]),  //%0
        "=g"(x[1])   //%1
        ://inputs
        "g"(x[0]),  //%2
        "g"(x[1])   //%3
        ://no clobber list
    );

or something like this(I know this swapping is extremely slow, just wanted to have push pops working):

__asm__ __volatile__ (
        ".intel_syntax noprefix \n\t"
        "push rax \n\t"
        "push rbx \n\t"
        "push rcx \n\t"
        "push rdx \n\t"

        "mov eax,%2 \n\t"
        "mov ecx,%3 \n\t"
        "mov edx,eax \n\t"
        "mov eax,ecx \n\t"
        "mov ecx,edx \n\t"
        "mov %0,eax \n\t"
        "mov %1,ecx \n\t"

        "pop rdx \n\t"
        "pop rcx \n\t"
        "pop rbx \n\t"
        "pop rax \n\t"

        ://outputs
        "=g"(x[0]),  //%0
        "=g"(x[1])   //%1
        ://inputs
        "g"(x[0]),  //%2
        "g"(x[1])   //%3
        ://no clobber list
    );
1
The compiler wants to "own" the XMM regs just like the regular general-purpose ones. You cannot simply use them from inline assembly unless you tell the compiler either: your inline assembly is expecting values in XMM regs as input/output operands, or: by explicitly listing the regs you wish to modify in the clobber list_. If you do this, then there's no need whatsoever to push/pop yourself. The compiler will automatically insert such code before/after your inline asm statement if (and only if) it chose to put any variable into one of the registers you've stated you'd modify. - FrankH.
Okay, do I show them as "YMM0","YMM16" ? Is it possible for the overhead of saving/restoring registers being less than overhead of JNI call? - huseyin tugrul buyukisik
Yes, theoretically you can list all vector regs in the clobber list. But that's wasteful and likely unnecessary ... it depends on your exact usecase whether inline assembler or a completely separate function all-written-in-assembler is better. Constructed artifical testcases can be found for either ... need to know more about the real problem you're trying to solve here. - FrankH.
I sense a misunderstanding ... GCC inline assembly is very different from MSVC. In the latter (no 64bit) the compiler did "nothing" for you regarding preservation/restoration of "C program state" before/after inline assembly blocks. with MSVC _asm: you had to use push/pop for regs you were planning to use. That's not the case for gcc inline asm; if your asm is fine using no more regs than you have inputs / outputs, you need no clobber list at all. You can use 'temp' vars as inputs to "get a reg". Only if you must use a register explicitly by its name, you must list it as clobbered. - FrankH.
Also note that at least on UNX, you'll break the ABI if you push from within inline assembly blocks. That's because leaf functions on 64bit x86 UNX are allowed to use -128(%rsp) ... (%rsp) without having to explicitly adjust the stackpointer (the so-called red zone), and if you'd push from within a leaf function you may clobber local variables of the func your asm() is in. You can likewise not call from within inline assembly blocks. - FrankH.

1 Answers

1
votes

This question is kind of tricky. As far as I know, the way you compile will have impact on the result. I am not sure if this is what you need but if you don't use inline assembly, you can control it.

You write your code in a separate .s file, and compile with optimization like -O3, gcc will not push and protect nonvolatile registers. I don't use inline assembly myself so I am not clear with that part. You can test it yourself :D

BTW: I think if you write .asm file and use nasm to compile it and link the object with gcc, same thing would happen. With optimization, I don't think gcc will do the push/pop automatically. Let me know if there are something wrong in my reply. Thanks.

Good luck

xiangpisaiMM