small structures passing

Started by
5 comments, last by SeanMiddleditch 9 years, 9 months ago

I wonder if such small structures that size is up to given architecture procesor word size like

struct Color {unsigned char a,r,g,b;}

struct Int32Pair {Int32 x,y;} // on 64 bit architecture

are guaranteed to be passed and returned in quick one registry way?

same with returning sse work types like _m128 (i mean in intermodular calls

not inline)

or are thay wasted by doing ram copies in calls?

Advertisement

Have a look on the ABI (application binary interface) of the compiler and/or operating system.

Because many libraries come with the operating system the operating system defines some standard for passing parameters to functions and how they can be stored in registers instead moving them accross the stack.

This is what the ABI is for. If some special passing mechanism is used it must be made sure that you do not link diffent calling conventions (ABIs) together. If I remember right there has been in the history of MS compilers a calling convention "fast call" that used nearly all registers to pass parameters. To make sure that the caller is aware of it the linker symbols for such functions has prepended an @. This way they make sure not to call a fastcall function from some code that is not aware of this.

Have a look on the ABI (application binary interface) of the compiler and/or operating system.

Because many libraries come with the operating system the operating system defines some standard for passing parameters to functions and how they can be stored in registers instead moving them accross the stack.

This is what the ABI is for. If some special passing mechanism is used it must be made sure that you do not link diffent calling conventions (ABIs) together. If I remember right there has been in the history of MS compilers a calling convention "fast call" that used nearly all registers to pass parameters. To make sure that the caller is aware of it the linker symbols for such functions has prepended an @. This way they make sure not to call a fastcall function from some code that is not aware of this.

those abi topics are confusing, but isnt there some common standards

that when i compile code with gcc to .o there is some specyfic convention - and if so how such passing of Color and Int32Pair physically look like?

maybe this is not so much important, though on the other side if at present machines every call of the functions equals to physical memcopy of the args record when optymizing this should be really avoided

yet one related thing

is this true that when optymizing i should revrite code such way to

minimalize local variables? each variable is storing and loading the

bytes, for example if i got 20 int variables versus 10 int variables (where those 10 are reused) is it more efficient?

im not sure if compiler is physically obliged to use all those 20 ram

variables when used in code or some of them after optymization are becoming virtual - and he is for example using only say 7 and the rest of mechanics is doing in the registers...

not sure as to this but some thinking suggest me that i should avoid populating local variables and reusing the small set of them - im not sure as to this

ABIs ARE the standard.

Be it the C defined one or compiler/OS specific ones.

This is the subject you need to understand to answer your question.

those abi topics are confusing, but isnt there some common standards


No. There is no common standard for how data is passed to or from functions. GCC and VC++ can choose to do it entirely differently. GCC can do it differently for Intel chips than it does for ARM chips.

If you don't want to read ABIs and just want to know if this is possible or how it's done or if it's done, _look at the compiler's output_.

Sample code:
struct Color {unsigned char a,r,g,b;};

Color make_color() { Color c; c.r = 1; c.g = 2; c.b = 3; c.a = 4; return c; }
x86-64 via GCC 4.9.0 at -03:
make_color():
	mov	eax, 50462980
	ret
ARM via GCC 4.6 at -03:
make_color():
	movs	r3, #4
	movs	r0, #0
	bfi	r0, r3, #0, #8
	movs	r3, #1
	bfi	r0, r3, #8, #8
	movs	r3, #2
	bfi	r0, r3, #16, #8
	movs	r3, #3
	sub	sp, sp, #8
	bfi	r0, r3, #24, #8
	add	sp, sp, #8
	bx	lr
x86 via Visual C++ 2013 Nov13_CTP in Release:
00FE4790  push        ebp  
00FE4791  mov         ebp,esp  
00FE4793  push        ecx  
00FE4794  mov         word ptr [ebp-3],201h  
00FE479A  mov         byte ptr [ebp-1],3  
00FE479E  mov         byte ptr [c],4  
00FE47A2  mov         eax,dword ptr [c]  
00FE47A5  mov         esp,ebp  
00FE47A7  pop         ebp  
00FE47A8  ret  
At least with ARM and x86_64 via GCC and x86 via VC++ small structs are indeed returned in single registers at least on these specific architectures with these specific compilers on these specifics platforms.

If you want more guarantees, you'll need to read the relevant ABI documents.

Sean Middleditch – Game Systems Engineer – Join my team!



alright, thats cool,

do you maybe know if it would work the same way with 64 bit

i mean something like


 
struct X {unsigned char a,b,c,d, e,f,g,h; }
 
X makeX()
{
  X x;
 
  x.a = 1;
  x.b = 2;

  x.c = 3;

  x.d = 4;

  x.e = 5;

  x.f  = 6;

  x.g = 7;

  x.h = 8;
 
  return X;






}
 
will it be
 
makeX:
    mov    rax, 23486347850462980 //somethin
    ret
got 32-bit xp and not sure if i could compile and disasemble 64-bit
exe probably not
and yet

__m128 makeM128i()
{
   unsigned char y[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16};
 
   __m128i m = _mm_loadu_si128(y) ;
    return m;
}
or if there is not a intrinsic to load m128 not from memory but immediate constant (unclear for me yet) - though maybe this will be optymized to constant
(ps, forum bugs spoils some texts, nearly always it cut a text after the closing code tag)


do you maybe know if it would work the same way with 64 bit

gcc.godbolt.org. Try it out and see. Those all compile on AMD64 unless they say otherwise (like the ARM cross compilers).

Sean Middleditch – Game Systems Engineer – Join my team!

This topic is closed to new replies.

Advertisement