public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output
@ 2023-04-12  9:49 570070308 at qq dot com
  2023-04-12 10:51 ` [Bug middle-end/109484] " rguenth at gcc dot gnu.org
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: 570070308 at qq dot com @ 2023-04-12  9:49 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

            Bug ID: 109484
           Summary: [Wrong Code][inline-asm] output operands overlap with
                    output
           Product: gcc
           Version: 13.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: 570070308 at qq dot com
  Target Milestone: ---

For code:
```c
void kkk(void **const pp)
{
    void *temp;
    __asm__ volatile (
            "movq   %1, %0\n\t"
            "movq   $0, %1"
            :"=r"(temp), "+m"(*pp)
            :
            :);
    __asm__ volatile(""::"D"(temp):);
}
```

After compile with -O3:
```assemble
kkk:
        movq   (%rdi), %rdi
        movq   $0, (%rdi)   # %rdi overlap, abort if %rdi == NULL
        ret
```



I think there's nothing wrong with this c code according to gcc inline asm doc:
``` From GCC DOC
GCC may allocate the output operand in the same register as an unrelated input
operand, on the assumption that the assembler code consumes its inputs before
producing outputs. 
```
The C code do read *pp first, then write the output.




I think according to gcc's doc, an output operand(without'&') will only overlap
to input operands.
``` From GCC DOC
Operands using the ‘+’ constraint modifier count as two operands (that is, both
as input and output) towards the total maximum of 30 operands per asm
statement.

Use the ‘&’ constraint modifier (see Modifiers) on all output operands that
must not overlap an input. Otherwise, GCC may allocate the output operand in
the same register as an unrelated input operand, on the assumption that the
assembler code consumes its inputs before producing outputs. This assumption
may be false if the assembler code actually consists of more than one
instruction.

The same problem can occur if one output parameter (a) allows a register
constraint and another output parameter (b) allows a memory constraint. The
code generated by GCC to access the memory address in b can contain registers
which might be shared by a, and GCC considers those registers to be inputs to
the asm. As above, GCC assumes that such input registers are consumed before
any outputs are written. This assumption may result in incorrect behavior if
the asm statement writes to a before using b. Combining the ‘&’ modifier with
the register constraint on a ensures that modifying a does not affect the
address referenced by b. Otherwise, the location of b is undefined if a is
modified before using b.
```

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
@ 2023-04-12 10:51 ` rguenth at gcc dot gnu.org
  2023-04-12 11:03 ` 570070308 at qq dot com
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-04-12 10:51 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
but you clobber 'temp' early and fail to indicate that so GCC allocates the
same register as part of the "+m" output.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
  2023-04-12 10:51 ` [Bug middle-end/109484] " rguenth at gcc dot gnu.org
@ 2023-04-12 11:03 ` 570070308 at qq dot com
  2023-04-12 11:07 ` rguenth at gcc dot gnu.org
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: 570070308 at qq dot com @ 2023-04-12 11:03 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

--- Comment #2 from 。 <570070308 at qq dot com> ---
(In reply to Richard Biener from comment #1)
> but you clobber 'temp' early and fail to indicate that so GCC allocates the
> same register as part of the "+m" output.

The requirements you describe are not reflected in the documentation. The
document only says that `GCC assumpts that the assembler code consumes its
inputs before producing outputs`, and this code fits the assumption. First, it
reads the input from %1, then write the output to %0, then write the output to
%1. No outputs happend before inputs.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
  2023-04-12 10:51 ` [Bug middle-end/109484] " rguenth at gcc dot gnu.org
  2023-04-12 11:03 ` 570070308 at qq dot com
@ 2023-04-12 11:07 ` rguenth at gcc dot gnu.org
  2023-04-12 11:09 ` rguenth at gcc dot gnu.org
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-04-12 11:07 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to 。 from comment #2)
> (In reply to Richard Biener from comment #1)
> > but you clobber 'temp' early and fail to indicate that so GCC allocates the
> > same register as part of the "+m" output.
> 
> The requirements you describe are not reflected in the documentation. The
> document only says that `GCC assumpts that the assembler code consumes its
> inputs before producing outputs`, and this code fits the assumption. First,
> it reads the input from %1, then write the output to %0, then write the
> output to %1. No outputs happend before inputs.

You first write to 'temp' and then read from it.  The wording applies to the
assigned register / address, _not_ to the C variables mapped.

Note I'm not an expert here and I wonder if an output operand is the
appropriate
way to create a scratch register for arbitrary use.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
                   ` (2 preceding siblings ...)
  2023-04-12 11:07 ` rguenth at gcc dot gnu.org
@ 2023-04-12 11:09 ` rguenth at gcc dot gnu.org
  2023-04-12 11:13 ` 570070308 at qq dot com
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-04-12 11:09 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
So, use "=&r" (temp) (an early-clobber), that should fix it.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
                   ` (3 preceding siblings ...)
  2023-04-12 11:09 ` rguenth at gcc dot gnu.org
@ 2023-04-12 11:13 ` 570070308 at qq dot com
  2023-04-12 12:48 ` 570070308 at qq dot com
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: 570070308 at qq dot com @ 2023-04-12 11:13 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

--- Comment #5 from 。 <570070308 at qq dot com> ---
(In reply to Richard Biener from comment #3)
> (In reply to 。 from comment #2)
> > (In reply to Richard Biener from comment #1)
> > > but you clobber 'temp' early and fail to indicate that so GCC allocates the
> > > same register as part of the "+m" output.
> > 
> > The requirements you describe are not reflected in the documentation. The
> > document only says that `GCC assumpts that the assembler code consumes its
> > inputs before producing outputs`, and this code fits the assumption. First,
> > it reads the input from %1, then write the output to %0, then write the
> > output to %1. No outputs happend before inputs.
> 
> You first write to 'temp' and then read from it.  The wording applies to the
> assigned register / address, _not_ to the C variables mapped.
> 
> Note I'm not an expert here and I wonder if an output operand is the
> appropriate
> way to create a scratch register for arbitrary use.

The second instruction is $0, not %0.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
                   ` (4 preceding siblings ...)
  2023-04-12 11:13 ` 570070308 at qq dot com
@ 2023-04-12 12:48 ` 570070308 at qq dot com
  2023-04-12 13:03 ` jakub at gcc dot gnu.org
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: 570070308 at qq dot com @ 2023-04-12 12:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

--- Comment #6 from 。 <570070308 at qq dot com> ---
A better testcase:
```c
void kkk(void **const pp)
{
    void *temp;
    __asm__ volatile (
            "movq   $0xff, %0\n\t"
            "movq   $0xff, %1"
            :"=r"(temp), "=m"(*pp)
            :
            :);
    __asm__ volatile(""::"D"(temp):);
}
```

After compile:
```assemble
kkk:
        movq   $0xff, %rdi
        movq   $0xff, (%rdi)    # abort
        ret
```

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
                   ` (5 preceding siblings ...)
  2023-04-12 12:48 ` 570070308 at qq dot com
@ 2023-04-12 13:03 ` jakub at gcc dot gnu.org
  2023-04-13 11:51 ` xry111 at gcc dot gnu.org
  2023-04-13 11:55 ` jakub at gcc dot gnu.org
  8 siblings, 0 replies; 10+ messages in thread
From: jakub at gcc dot gnu.org @ 2023-04-12 13:03 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Similar bug.  The basic GCC expectations for inline-asm is that the whole
assembly template after substitutions (which is for GCC mostly intentionally a
black box) works as a single instruction which reads all its inputs (and that
obviously doesn't mean just  the input themselves, but also any other
register/memory used in the input) and then stores all its outputs.
Early clobbers are the way to tell the compiler that it is not the case and
some output is written before all the inputs are used.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
                   ` (6 preceding siblings ...)
  2023-04-12 13:03 ` jakub at gcc dot gnu.org
@ 2023-04-13 11:51 ` xry111 at gcc dot gnu.org
  2023-04-13 11:55 ` jakub at gcc dot gnu.org
  8 siblings, 0 replies; 10+ messages in thread
From: xry111 at gcc dot gnu.org @ 2023-04-13 11:51 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

Xi Ruoyao <xry111 at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |xry111 at gcc dot gnu.org

--- Comment #8 from Xi Ruoyao <xry111 at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #7)
> Similar bug.  The basic GCC expectations for inline-asm is that the whole
> assembly template after substitutions (which is for GCC mostly intentionally
> a black box) works as a single instruction which reads all its inputs (and
> that obviously doesn't mean just  the input themselves, but also any other
> register/memory used in the input) and then stores all its outputs.
> Early clobbers are the way to tell the compiler that it is not the case and
> some output is written before all the inputs are used.

Should we add this info into the doc?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Bug middle-end/109484] [Wrong Code][inline-asm] output operands overlap with output
  2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
                   ` (7 preceding siblings ...)
  2023-04-13 11:51 ` xry111 at gcc dot gnu.org
@ 2023-04-13 11:55 ` jakub at gcc dot gnu.org
  8 siblings, 0 replies; 10+ messages in thread
From: jakub at gcc dot gnu.org @ 2023-04-13 11:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109484

--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The documentation already says that.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-04-13 11:55 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-12  9:49 [Bug middle-end/109484] New: [Wrong Code][inline-asm] output operands overlap with output 570070308 at qq dot com
2023-04-12 10:51 ` [Bug middle-end/109484] " rguenth at gcc dot gnu.org
2023-04-12 11:03 ` 570070308 at qq dot com
2023-04-12 11:07 ` rguenth at gcc dot gnu.org
2023-04-12 11:09 ` rguenth at gcc dot gnu.org
2023-04-12 11:13 ` 570070308 at qq dot com
2023-04-12 12:48 ` 570070308 at qq dot com
2023-04-12 13:03 ` jakub at gcc dot gnu.org
2023-04-13 11:51 ` xry111 at gcc dot gnu.org
2023-04-13 11:55 ` jakub at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).