For ARMv7M (including the Cortex-M3 in your atsam3x) the stack alignment in interrupt handlers is controlled by hardware.
Firstly, it is impossible to ever have the stack pointer aligned any worse than 4 bytes. This is because the bottom two bits of the stack pointer are always zero and no instruction can ever change them. The compiler knows this and so if you create char[3]
it rounds it up to 4 bytes.
If the STKALIGN bit of the CCR control register is 0 then this is all that happens. The stack pointer is aligned to a multiple of 4 bytes on entry to an interrupt handler function.
If the STKALIGN bit is 1 then the hardware automatically aligns the stack to an 8-byte boundary on entry to an interrupt.
On Cortex-M3 the reset value of the CCR.STKALIGN is 1, and ARM strongly recommend that you do not change it.
In the ARM ABI it is the responsibility of the caller to align the stack. This is because there is a 50:50 chance that it knows it is already aligned without doing anything, so this is much more efficient.
If your compiler is configured to generate code for the ARM ABI then it will assume that the stack is correctly aligned to an 8-byte boundary on entry to any externally linked function and not generate any code to align it again in the called function.
On ARMv7M (and v6M) it is normal and correct to use a bare function as an interrupt handler. There is no ISR prolog/epilog as mentioned in some of the comments.
All of this combined means that as long as your compiler is configured to use the ARM ABI, and as long as you haven't changed the default value of CCR.STKALIGN then your stack will always be correctly aligned.