python-greenlet/greenlet — pull request #65 by basak (2014-10-14 16:57:40+00:00)
Title: arm32: force return value from asm

In my case, instead of a simple "mov r0, #0", the optimizer had done
this:

Between calls to slp_save_state and slp_restore_state, it saved the
value now guaranteed to be 0 using "str r0, [r7]".

Now, at the end, it restores that value into r0 using "ldr r3, [r7]"
and then "mov r0, r3".

It isn't clear to me that intermediate values managed by the compiler,
like this one at [r7], would be preserved in the stack this way,
especially as at this point we're in a "different" stack (unknown to the
optimizer).

Instead, prevent the optimizer from re-using a previous result like this
by forcing it to rely on the inline assembly to produce the result.

This fixes test failures on Ubuntu Utopic using gcc 4.9.1 (-5ubuntu1).

I think even this is still a hack though, and not guaranteed to work.
Ultimately, gcc can even re-order the "__asm__ volatile" functions at
will around the entire function, or just wrap each REGS_TO_SAVE
clobbering call with a simple push/pop, thus not preserving the
registers between stack switches.

The only way I can see of doing this without relying on undefined
compiler behaviour is to write the entire slp_switch function in
assembly for each architecture, instead of inlining it into a C function
for code reuse.

* Example compiler output before this change (but with `-fno-omit-frame-pointer` from pull #64): https://gist.github.com/basak/85b88e6df4f7da8215c1
* Example compiler output after this change: https://gist.github.com/basak/63d87b8494f5ad7708ba