views:

67

answers:

2

For a function with signature:

struct Pair { void *v1, *v2 };
void f(Pair p);

compiled on x64, I would like Pair's fields to be passed via register, as if the function was:

void f(void *v1, void *v2);

Compiling a test with gcc 4.2.1 for x86_64 on OSX 10.6, I can see this is exactly what happens by examining the disassembly. However, compiling with MSVC 2008 for x64 on Windows, the disassembly shows that Pair is passed on the stack. I understand that platform ABIs can prevent this optimization; does anyone know any MSVC-specific annotations, calling conventions, flags, or other hacks that can get this to work?

Thank you!

A: 

what if you do this ?

   void f( void *ps ){
       struct Pair *p = (struct Pair *)ps;
   }

or

void f( unsigned long addr ){
    struct Pair *p = (struct Pair *)addr;
}

struct Pair pp;

f( reinterpret_cast<unsigned long>(&pp) );
Simone Margaritelli
Still paying the stores/loads, see the third comment on the question.
Luke
Saw it, even with the second solution ? (i'm just guessing, never coded such things on 64bit)
Simone Margaritelli
I think sizeof(unsigned long) is 4; the sizeof(Pair) (containing two pointers) is 16. That might work, though, if were a portable builtin which is 16 bytes on both gcc and MSVC and is passed by register. (Is there?) It would also require the ABI allowing scalar values to be split across registers.
Luke
Actually, it would be something more like (assuming a mystical long long long):void f(long long long bits) { Pair }Pair p;f(reinterpret_cast<long long long *>(
Luke
+1  A: 

My VS2008 x64 compiler doesn't do the same thing yours does. The struct fits in an XMM register, it passes a pointer to the copy of the pair object in a register:

    Pair p;
    f(p);
000000013F2B1189  movaps      xmm6,xmmword ptr [p] 
000000013F2B118E  lea         rcx,[p] 
000000013F2B1193  movdqa      xmmword ptr [p],xmm6 
000000013F2B1199  call        f (13F2B1000h) 

Nothing is passed on the stack here.

Hans Passant
Thanks for answering! What does the disassembly for the callee look like if it accesses a field of the struct? Any loads?
Luke
@Luke, have a look at it yourself. Start the debugger, right-click the text editor and choose "Go To Disassembly". Beware that only looking at the Release build code is meaningful.
Hans Passant
@nobugz, that's what I did before asking the question. The reason I ask you is because your assembly looks different. It also is not clear that the callee won't be doing loads to access the parameter values.
Luke