Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell GCC that a pointer argument is always double-word-aligned?

Tags:

c

alignment

gcc

c99

In my program I have a function that does a simple vector addition c[0:15] = a[0:15] + b[0:15]. The function prototype is:

void vecadd(float * restrict a, float * restrict b, float * restrict c); 

On our 32-bit embedded architecture there is a load/store option of loading/storing double words, like:

r16 = 0x4000  ; strd r0,[r16] ; stores r0 in [0x4000] and r1 in [0x4004] 

The GCC optimizer recognizes the vector nature of the loop and generates two branches of the code - one for the case where the 3 arrays are double word aligned (so it uses the double load/store instructions) and the other for the case that the arrays are word-aligned (where it uses the single load/store option).

The problem is that the address alignment check is costly relative to the addition part and I want to eliminate it by hinting the compiler that a, b and c are always 8-aligned. Is there a modifier to add to the pointer declaration to tell this to the compiler?

The arrays that are used for calling this function have the aligned(8) attribute, but it is not reflected in the function code itself. is it possible to add this attribute to the function parameters?

like image 323
ysap Avatar asked Mar 07 '12 19:03

ysap


1 Answers

If the attributes don't work, or aren't an option ....

I'm not sure, but try this:

void vecadd (float * restrict a, float * restrict b, float * restrict c) {    a = __builtin_assume_aligned (a, 8);    b = __builtin_assume_aligned (b, 8);    c = __builtin_assume_aligned (c, 8);     for .... 

That should tell GCC that the pointers are aligned. From that whether it does what you want depends on whether the compiler can use that information effectively; it might not be smart enough: these optimizations aren't easy.

Another option might be to wrap the float inside a union that must be 8-byte aligned:

typedef union {   float f;   long long dummy; } aligned_float;  void vedadd (aligned_float * a, ...... 

I think that should enforce 8-byte alignment, but again, I don't know if the compiler is smart enough to use it.

like image 176
ams Avatar answered Oct 06 '22 13:10

ams