4

Hello I am currently working on a program where I need to process a data blob that contains a series of floats which could be unaligned (and also are sometimes). I am compiling with gcc 4.6.2 for an ARM cortex-a8. I have a question to the generated assembly code:

As example I wrote a minimal example: For the following test code

float aligned[2];
float *unaligned = (float*)(((char*)aligned)+2);

int main(int argc, char **argv) 
{
    float f = unaligned[0];  
    return (int)f;
}

the compiler (gcc 4.6.2 - with optimization -O3) produces

00008634 <main>:
    8634: e30038ec            movw         r3, #2284      ; 0x8ec
    8638: e3403001            movt         r3, #1
    863c: e5933000            ldr          r3, [r3]
    8640: edd37a00            vldr         s15, [r3]
    8644: eefd7ae7            vcvt.s32.f32 s15, s15
    8648: ee170a90            vmov         r0, s15
    864c: e12fff1e            bx           lr

The compiler here cannot know if the data is aligned but never the less it uses VLDR which needs aligned data or the program will crash with a bus error.

Now here is my actual question: Is this correct from the compiler and I need to take care of alignment in my C++ code or is this a bug in the compiler?

I also might add my current workaround which works and brings gcc to make a copy before accessing the value. The trick is to define a struct which only contains a float with the gcc packed attribute and access the data via a struct pointer. Code snippet:

struct FloatWrapper { float f; } __attribute__((packed));
const FloatWrapper *x = reinterpret_cast<const FloatWrapper *>(rawX.data());
const FloatWrapper *y = reinterpret_cast<const FloatWrapper *>(rawY.data());

for (size_t i = 0; i < vertexCount; ++i) {
    vertices[i].x = x[i].f;
    vertices[i].y = y[i].f;
}
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Jahn
  • 103
  • 1
  • 8
  • 7
    The C99 standard contains this footnote: “Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer, an address inappropriately aligned for the type of object pointed to, …”. I have no doubt the C++ standard contains a similar warning. So your program is technically undefined and the compiler is free to generate any sequence of instruction it likes without it being a bug. – Pascal Cuoq Jun 19 '13 at 09:58
  • A `float*` is always assumed to have at least `alignof(float)` alignment. If you're violating that, you need to use `memcpy` or something other than simple dereference to avoid Undefined Behaviour. (Even when compiling for x86, for example.) [Why does unaligned access to mmap'ed memory sometimes segfault on AMD64?](https://stackoverflow.com/q/47510783) / https://trust-in-soft.com/blog/2020/04/06/gcc-always-assumes-aligned-pointers/ – Peter Cordes Jan 15 '21 at 11:30

1 Answers1

3

As you have pointed ARM ARM A3.2.1 states regardless of SCTLR.A value, VLDR generates Alignment fault.

I've tested your example on an Cortex-A9 and I got

# float_align                                                   
[1] + Stopped (signal)     float_align 

However, I'm confused also by the ARM Cortex-A8 TRM 4.2.1, it states

If an alignment qualifier is not specified, and A=1, the alignment fault is taken if it is not aligned to element size.

If an alignment qualifier is not specified, and A=0, it is treated as unaligned access.

This is probably a half baked explanation, since ARM ARM is giving more information with a detailed table on instructions.

So I think answer is, you need to take care of alignment yourself since compiler can't find out which addresses you are loading in all scenarios, like address might be available after linking etc.

auselen
  • 27,577
  • 7
  • 73
  • 114
  • Hi auselen, thank you for your reply. As I gathered from the ARM Architecture Reference Manual for ARMv7-A and ARMv7-R Chapter A3.2 Alignment Support/ A3.2.1 there are some instructions (VLDR and other instructions) that don't support unaligned access. [Link to Reference Manual](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0406c/index.html) – Jahn Jun 19 '13 at 09:32
  • Thanks auselen for looking into it, I will also look further into the comment Pascal about the C(++) standard and post the results here. – Jahn Jun 19 '13 at 13:18
  • I also came to the conclusion that we have to take care about the alignment ourself. Very interesting fact especially in the case when you get data in a specified format you have no influence on or if your function gets called with a pointer to data created somewhere else. – Jahn Jun 21 '13 at 07:30