https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280
--- Comment #12 from David Brown <david at westcontrol dot com> --- (In reply to Segher Boessenkool from comment #11) > (In reply to David Brown from comment #8) > > As for using "=X" in the "opt == 3" case, I worry that that could lead to > > errors as the two assembly lines are independent. The first says "put X > > anywhere", and the second - if it had "=X" - says "take X from anywhere". > > These don't have to be the same "anywhere" unless the input and output are > > in the same statement - and if the compiler picked different anywheres, the > > code would not work. > > This cannot lead to errors. The compiler knows where "x" is (it put it there > itself!) If I write : int regtest(int a, int x) { (void) a; // Ignore first parameter return x; } I get the assembly (x86-64) : movl %esi, %eax ret or (arm 32-bit) mov r0, r1 bx lr That's all fine, and as expected. But with this : int regtest(int a, int x) { (void) a; // Ignore first parameter asm("" :: "X" (x); asm("" : "=X" (x); return x; } the result is just a "ret" or a "bx lr" instruction. The register move is missing, because for the first assembly the "anywhere" is picked as esi/r1, and for the second assembly the "anywhere" is picked as eax/r0. This is a perfectly valid choice of registers for the compiler, but it is not what we want in this use-case. It is only if I use "+X" (or add a "0" (x) input), rather than "=X", that the compiler picks the same register for input and output, because it is within the one assembly instruction. (The same applies to "=g" / "+g".) I don't understand why having a "asm("" :: "X" (x))" seems to be necessary sometimes for "asm("" : "+X" (x))" to work the way I expect, without a compiler error, but I /do/ understand why "asm("" :: "X" (x))" followed by "asm("" : "=X" (x))" will sometimes not give the results I am looking for.