Hi folks,

I'm looking for a bit of a historic context for a fun GCC behavior we
stumbled across. For... reasons we build some of our binaries using an
older version of GCC (8.3.1, yes, we'll be upgrading soon, and no, this
message is not about helping with an ancient version :-) )

We noticed that this version of GCC compiling on aarch64 will happily use
FP registers to temporarily store/load pointers, so there'd be "fmov d9,
x1" to store a pointer, and then later when it's used as a parameter to a
function call we'll see "fmov x1, d9" etc. We noticed this while
investigating some crashes that seemed to always occur in functions called
with parameters loaded through this mechanism, on certain specific models
of aarch64 CPUs. On the face of it, this doesn't seem a _too_ terrible idea
– one'd think that a FP register should preserve the bit pattern so as long
as the only operations are stores and loads, what's the harm, right? Hey,
more free registers! Except, on some silicon, it's unfortunately strongly
correlated with crashes further down the callee chain.

Further proving the theory is that after we did some judicious application
of __attribute__((target("general-regs-only"))) to offending functions to
discourage the compiler from the practice, the crashes were gone.
Unfortunately, it sometimes required contorting the code to move any
implied uses of FP out of the way (heck, an inlined std::map constructor
requires FP operations 'cause of its load factor!)

I also noticed that a more modern version of GCC (e.g. 12.x) does not seem
to emit such code anymore (thus also eliminating the problem.) Curiously, I
couldn't wrangle a good enough Google search term to find anything about
what brought about the change – a discussion, a blog post, anything. I
wanted to know if the practice of stashing pointers in FP registers indeed
proved to be dangerous and was thus deliberately abandoned, or is it maybe
just a byproduct of some other change.

If someone knows more about this, I'd be very curious to hear about it.
It'd be great to know that this was an explicitly eliminated behavior so we
can rest assured that by using a newer version of GCC we will not get
bitten by it again.

Thanks,
  Attila.

Reply via email to