[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 Andrew Pinski changed: What|Removed |Added Resolution|--- |DUPLICATE Status|NEW |RESOLVED --- Comment #13 from Andrew Pinski --- Dup. *** This bug has been marked as a duplicate of bug 94180 ***
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #12 from David Brown --- (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.
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #11 from Segher Boessenkool --- (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!)
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #10 from Segher Boessenkool --- > But the dump from combine does not make sense: What about this does not make sense to you? > Failed to match this instruction: and then still doing stuff? That is normal. I'll work on making that look better / make more sense, it always irked me as well.
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #9 from Segher Boessenkool --- (In reply to Alexander Monakov from comment #6) > From the context given in the gcc-help thread, the goal is to place an > optimization barrier in a sequence of floating-point calculation. "+r" is > inappropriate for floats, as it usually incurs a reload from a > floating-point register to a GPR and back, and there's no universal > constraint for FP regs (e.g. on amd64 it is "+x" for SSE registers, but "+t" > for long double (or x87 FPU on 32-bit x86)). Yup. "Some target-specific register constraint" :-)
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #8 from David Brown --- (In reply to Segher Boessenkool from comment #4) > Nothing has changed here. > > opt == 2 and opt == 3 should use "=X", not "+X", btw. > I realise (since you told me - thanks) that asm ("" : "+X" (x)) and asm ("" : "=X" (x) : "0" (x)) are the same. However, it seems that asm ("" : "+X" (x) : "0" (x)) is different. If I change "opt == 2" to use "=X", then it acts exactly like the "opt == 1" version (as expected), but having "+X" in "opt == 2" gives different results. I don't know /why/ this seems to be treated differently, since it is just repeating the input in the same target, but it is. 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.
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #7 from David Brown --- Yes, the goal is an optimisation barrier with the least possible impact on the code. For most uses, asm("" : "+g" (x)) has been ideal, as far as I have tested. Typically it ensures "x" is evaluated in a register before the assembly "executes", and uses that register for "x" afterwards. But "g" also matches memory, so if "x" happens to be in a stack slot, it gets left there - there is no extra movement in and out of a register. But "g" does not match floating point or SIMD registers. So if "x" is in one of these registers, extra moves are generated, and I'd like to avoid them. So the ideal constraint would be one that matches memory or any register that can contain data. That's not quite the same as "match anything" - it should not match immediate values, nor "special" registers such as PC, SP, or a flags register, or the extra registers many processors have for floating point settings, link registers, interrupt state registers, and so on. But it might include registers for other accelerators that some chips have.
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 Alexander Monakov changed: What|Removed |Added CC||amonakov at gcc dot gnu.org --- Comment #6 from Alexander Monakov --- >From the context given in the gcc-help thread, the goal is to place an optimization barrier in a sequence of floating-point calculation. "+r" is inappropriate for floats, as it usually incurs a reload from a floating-point register to a GPR and back, and there's no universal constraint for FP regs (e.g. on amd64 it is "+x" for SSE registers, but "+t" for long double (or x87 FPU on 32-bit x86)).
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #5 from Segher Boessenkool --- Oh, and if the goal of the code is to put and keep the datum in a register, the code should really use "+r" anyway!
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #4 from Segher Boessenkool --- Nothing has changed here. opt == 2 and opt == 3 should use "=X", not "+X", btw. combine is perfectly correct that "X" allows *any operand whatsoever*, also those that you cannot really use as an output. Maybe we should not allow "X" for output operands at all? The error happens during reloading btw. Which makes sense, I would be much more surprised if the compiler figured out a way to move data into an addition :-)
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 Richard Biener changed: What|Removed |Added CC||segher at gcc dot gnu.org Keywords||rejects-valid --- Comment #3 from Richard Biener --- I wonder if this ever worked - at least I don't remember any combiner changes for asms.
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 --- Comment #2 from Andrew Pinski --- (In reply to Andrew Pinski from comment #1) > So the problem seems like combine decides somehow to > combine: > ``` > (insn 7 4 9 2 (set (reg/v:SF 100 [ xD.4459 ]) > (plus:SF (reg/v:SF 102 [ aD.4455 ]) > (reg/v:SF 103 [ bD.4456 ]))) "/app/example.cpp":6:7 1043 {addsf3} > (expr_list:REG_DEAD (reg/v:SF 102 [ aD.4455 ]) > (nil))) > (insn 9 7 10 2 (set (reg:SF 104 [ xD.4459 ]) > (asm_operands:SF ("") ("=X") 0 [ > (reg/v:SF 100 [ xD.4459 ]) > ] > [ > (asm_input:SF ("0") /app/example.cpp:8) > ] > [] /app/example.cpp:8)) "/app/example.cpp":8:5 -1 > (expr_list:REG_DEAD (reg/v:SF 100 [ xD.4459 ]) > (nil))) > into: > ``` > (insn 9 7 10 2 (set (reg:SF 104 [ xD.4459 ]) > (asm_operands:SF ("") ("=X") 0 [ > (plus:SF (reg:SF 106) > (reg/v:SF 103 [ bD.4456 ])) > ] > [ > (asm_input:SF ("0") /app/example.cpp:8) > ] > [] /app/example.cpp:8)) "/app/example.cpp":8:5 -1 > (expr_list:REG_DEAD (reg:SF 106) > (nil))) > ``` > > But the dump from combine does not make sense: > ``` > Trying 7 -> 9: > 7: r100:SF=r106:SF+r103:SF > REG_DEAD r106:SF > 9: r104:SF=asm_operands > REG_DEAD r100:SF > Failed to match this instruction: > (set (reg:SF 104 [ xD.4459 ]) > (asm_operands:SF ("") ("=X") 0 [ > (plus:SF (reg:SF 106) > (reg/v:SF 103 [ bD.4456 ])) > ] > [ > (asm_input:SF ("0") /app/example.cpp:8) > ] > [] /app/example.cpp:8)) > allowing combination of insns 7 and 9 > original costs 8 + 4 = 12 > replacement cost 4 > deferring deletion of insn with uid = 7. > modifying insn i3 9: r104:SF=asm_operands > REG_DEAD r106:SF > deferring rescan insn with uid = 9. > ``` So basically check_asm_operands accepts the insn because the plus matches the operand but this is an output operand which does not work as it is not an lvalue ...
[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113280 Andrew Pinski changed: What|Removed |Added Keywords|ra | Ever confirmed|0 |1 Last reconfirmed||2024-01-08 Component|middle-end |rtl-optimization Status|UNCONFIRMED |NEW --- Comment #1 from Andrew Pinski --- So the problem seems like combine decides somehow to combine: ``` (insn 7 4 9 2 (set (reg/v:SF 100 [ xD.4459 ]) (plus:SF (reg/v:SF 102 [ aD.4455 ]) (reg/v:SF 103 [ bD.4456 ]))) "/app/example.cpp":6:7 1043 {addsf3} (expr_list:REG_DEAD (reg/v:SF 102 [ aD.4455 ]) (nil))) (insn 9 7 10 2 (set (reg:SF 104 [ xD.4459 ]) (asm_operands:SF ("") ("=X") 0 [ (reg/v:SF 100 [ xD.4459 ]) ] [ (asm_input:SF ("0") /app/example.cpp:8) ] [] /app/example.cpp:8)) "/app/example.cpp":8:5 -1 (expr_list:REG_DEAD (reg/v:SF 100 [ xD.4459 ]) (nil))) into: ``` (insn 9 7 10 2 (set (reg:SF 104 [ xD.4459 ]) (asm_operands:SF ("") ("=X") 0 [ (plus:SF (reg:SF 106) (reg/v:SF 103 [ bD.4456 ])) ] [ (asm_input:SF ("0") /app/example.cpp:8) ] [] /app/example.cpp:8)) "/app/example.cpp":8:5 -1 (expr_list:REG_DEAD (reg:SF 106) (nil))) ``` But the dump from combine does not make sense: ``` Trying 7 -> 9: 7: r100:SF=r106:SF+r103:SF REG_DEAD r106:SF 9: r104:SF=asm_operands REG_DEAD r100:SF Failed to match this instruction: (set (reg:SF 104 [ xD.4459 ]) (asm_operands:SF ("") ("=X") 0 [ (plus:SF (reg:SF 106) (reg/v:SF 103 [ bD.4456 ])) ] [ (asm_input:SF ("0") /app/example.cpp:8) ] [] /app/example.cpp:8)) allowing combination of insns 7 and 9 original costs 8 + 4 = 12 replacement cost 4 deferring deletion of insn with uid = 7. modifying insn i3 9: r104:SF=asm_operands REG_DEAD r106:SF deferring rescan insn with uid = 9. ```