[Bug rtl-optimization/113280] Strange error for empty inline assembly with +X constraint

2024-03-22 Thread pinskia at gcc dot gnu.org via Gcc-bugs
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

2024-01-09 Thread david at westcontrol dot com via Gcc-bugs
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

2024-01-09 Thread segher at gcc dot gnu.org via Gcc-bugs
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

2024-01-09 Thread segher at gcc dot gnu.org via Gcc-bugs
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

2024-01-09 Thread segher at gcc dot gnu.org via Gcc-bugs
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

2024-01-09 Thread david at westcontrol dot com via Gcc-bugs
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

2024-01-09 Thread david at westcontrol dot com via Gcc-bugs
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

2024-01-09 Thread amonakov at gcc dot gnu.org via Gcc-bugs
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

2024-01-09 Thread segher at gcc dot gnu.org via Gcc-bugs
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

2024-01-09 Thread segher at gcc dot gnu.org via Gcc-bugs
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

2024-01-09 Thread rguenth at gcc dot gnu.org via Gcc-bugs
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

2024-01-08 Thread pinskia at gcc dot gnu.org via Gcc-bugs
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

2024-01-08 Thread pinskia at gcc dot gnu.org via Gcc-bugs
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.
```