https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60925
Jeffrey A. Law <law at redhat dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2015-01-21 CC| |law at redhat dot com Ever confirmed|0 |1 --- Comment #11 from Jeffrey A. Law <law at redhat dot com> --- Carlos, In general, you want to avoid using a register that is in a singleton class in an asm explicitly in an asm. While it works a hell of a lot better now than it has in the past, there's still cases where you can put the compiler into a situation where it can't figure out what to do. Typically that happens when you explicit clobber every register that GCC could potentially use to resolve a reload. And that's much more likely if you happen to clobber a register that is a singleton in a class. For the PA, %r1 is not fixed, but it is in a singleton class because it is the only register that can be set by addil. And ldil;add is not equivalent to addil because of some *insanely* gross stuff done by the HP linker where it will change addil <whatever>,r27 into addil <whatever>,r0, depending on what subsection <whatever> is in. THe linker isn't smart enough to do the same transformation on an ldil/add sequence which should otherwise be equivalent. Thus GCC has to put %r1 into its own class as a singleton. %r1 will often be needed as a reload scratch register as well as an intermediate for secondary reloads, most of the time to handle references to data in static storage, but also to handle constants that may be shoved into static storage. Registers with this kind of need are handled specially by reload and their "lifetime" essentially is the entire insn that triggered the reload. In this particular case, the lifetime is essentially the entire asm statement. So in this case, you have &lock being passed to lll_mutex_lock. That's a reference to static storage and thus *may* %r1 as a reload scratch register. That use as a reload scratch is seen as interfering with the %r1 in the clobber list. >From looking at the ASM you're trying to clobber all the call-clobbered registers, presumably due to the hidden "call" in the asm (the branch-and-link-external). Note that you should probably be including %r2 in that list. My asm and PA-fu are a bit rusty, so it's not immediately clear how to do what you want. You could try changing r1 so that you're clobbering a register that has to go into class "a". At least in that case you might be able to use a simple clobber ("=a") rather than an earlyclobber ("=&a") for the constraint. That gives GCC a bit more leeway in building the conflicts, but may still not be enough. Or get lock out of static memory or otherwise hide the fact that its in static memory so that GCC won't try to create a direct reference to it in the asm. I think that's what David's workaround was in effect suggesting. If by a level of indirection you can prevent GCC from discovering that futex is in static memory, then this problem should go away (its address will just be sitting in a register and can be used directly). These are just potential workarounds for a reload issue that is highly unlikely to ever get fixed. If your asm clobber the entire set of call-clobbered registers, you really don't leave reload enough leeway to handle reloads. Similarly if it clobbers everything in a particular class, then you run into the same problem if there's an operand that requires a reload register of that class. This is probably a WONTFIX.