public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug ipa/113293] New: Incorrect code after inlining function containing extended asm
@ 2024-01-09 16:51 dories.spirits_0p at icloud dot com
  2024-01-09 17:05 ` [Bug ipa/113293] " pinskia at gcc dot gnu.org
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: dories.spirits_0p at icloud dot com @ 2024-01-09 16:51 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 113293
           Summary: Incorrect code after inlining function containing
                    extended asm
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ipa
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dories.spirits_0p at icloud dot com
                CC: marxin at gcc dot gnu.org
  Target Milestone: ---

GCC compiles the following code (with -O3 -std=gnu2x):

#include <stdint.h>

#define SYSCALL_GETCHAR 1
#define SYSCALL_THREAD_CREATE 2

typedef void (*thread_func)(void *);

static inline char getc() {
    register char r0 asm("r0");
    asm volatile ("svc %[syscall]" 
                   : "=r" (r0)
                   : [syscall] "i" (SYSCALL_GETCHAR)
                   : "r1", "r2", "r3");
    return r0;
}

static inline void thread_create(thread_func func, const void * args, uint32_t
args_size) {
    register uint32_t r0 asm("r0") = (uint32_t) func;
    register uint32_t r1 asm("r1") = (uint32_t) args;
    register uint32_t r2 asm("r2") = args_size;
    asm volatile ("svc %[syscall]" 
                   : "+r" (r0), "+r" (r1), "+r" (r2)
                   : [syscall] "i" (SYSCALL_THREAD_CREATE), "r" (r0), "r" (r1),
"r" (r2)
                   : "r3");
}

void worker([[maybe_unused]] void *x) {}

void main() {
        while (true) {
                char arg = getc();
                thread_create(worker, &arg, sizeof(arg));
        }
}

into something like

main:
        movw    ip, #:lower16:worker
        sub     sp, sp, #8
        movt    ip, #:upper16:worker
.L4:
        svc #1             //char getc()
        mov     r2, #1
        mov     r0, ip     //return value of 'getc' svc call overwritten
        add     r1, sp, #7 //nothing in the stack here!
        svc #2             
        b       .L4

The return value of 'getc' is overwritten/not stored on the stack with -O1 and
higher (-Og and -O0 are not affected). I've tested on a local copy of
arm-none-eabi-gcc 10.2.0 as well as arm gcc trunk (arm-unknown-linux-gnueabihf
14.0.0 20240108) on compiler explorer.

I've also tested clang 17 targeting arm-none-eabi, which correctly stores the
result of the 'getc' svc call on the stack in all optimization levels:

.LBB1_1:
        svc     #1
        strb    r0, [sp, #3]
        [...]

ARM GCC trunk and Clang trunk:
https://godbolt.org/z/ercEYfacM

If 'getc' is marked noinline, r0 is correctly saved to the stack:

.L5:
        bl      getc
        strb    r0, [sp, #7] //saved to stack
        add     r1, sp, #7
        [...]
        svc #2
        b       .L5

With [[gnu::noinline]]
https://godbolt.org/z/ETManW1hY

This is my first bug, so please let me know if there's anything else I need to
provide.

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

* [Bug ipa/113293] Incorrect code after inlining function containing extended asm
  2024-01-09 16:51 [Bug ipa/113293] New: Incorrect code after inlining function containing extended asm dories.spirits_0p at icloud dot com
@ 2024-01-09 17:05 ` pinskia at gcc dot gnu.org
  2024-01-09 17:14 ` dories.spirits_0p at icloud dot com
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-01-09 17:05 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
           Keywords|                            |inline-asm
         Resolution|---                         |INVALID

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
The inline-asm is not marking as clobbering memory.

In this case since you just pass the address of the variable, gcc does not know
the inline-asm will read memory at all, it deletes the store. Anyways adding
"memory" as a clobber to the inline-asm, fixes the issue.

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

* [Bug ipa/113293] Incorrect code after inlining function containing extended asm
  2024-01-09 16:51 [Bug ipa/113293] New: Incorrect code after inlining function containing extended asm dories.spirits_0p at icloud dot com
  2024-01-09 17:05 ` [Bug ipa/113293] " pinskia at gcc dot gnu.org
@ 2024-01-09 17:14 ` dories.spirits_0p at icloud dot com
  2024-01-09 18:27 ` amonakov at gcc dot gnu.org
  2024-01-09 19:41 ` dories.spirits_0p at icloud dot com
  3 siblings, 0 replies; 5+ messages in thread
From: dories.spirits_0p at icloud dot com @ 2024-01-09 17:14 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from KBDeveloper <dories.spirits_0p at icloud dot com> ---
(In reply to Andrew Pinski from comment #1)
> The inline-asm is not marking as clobbering memory.
> 
> In this case since you just pass the address of the variable, gcc does not
> know the inline-asm will read memory at all, it deletes the store. Anyways
> adding "memory" as a clobber to the inline-asm, fixes the issue.

Ah, that makes sense. I had assumed that taking the address of arg would force
gcc to store it in memory somewhere. 
Is there a reason why gcc then allocates 8 bytes on the stack and fills r1 with
sp - #7? Or is what I had just UB and gcc can do whatever?

At any rate, thanks for the quick response.

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

* [Bug ipa/113293] Incorrect code after inlining function containing extended asm
  2024-01-09 16:51 [Bug ipa/113293] New: Incorrect code after inlining function containing extended asm dories.spirits_0p at icloud dot com
  2024-01-09 17:05 ` [Bug ipa/113293] " pinskia at gcc dot gnu.org
  2024-01-09 17:14 ` dories.spirits_0p at icloud dot com
@ 2024-01-09 18:27 ` amonakov at gcc dot gnu.org
  2024-01-09 19:41 ` dories.spirits_0p at icloud dot com
  3 siblings, 0 replies; 5+ messages in thread
From: amonakov at gcc dot gnu.org @ 2024-01-09 18:27 UTC (permalink / raw)
  To: gcc-bugs

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

Alexander Monakov <amonakov at gcc dot gnu.org> changed:

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

--- Comment #3 from Alexander Monakov <amonakov at gcc dot gnu.org> ---
(In reply to KBDeveloper from comment #2)
> 
> Ah, that makes sense. I had assumed that taking the address of arg would
> force gcc to store it in memory somewhere. 
> Is there a reason why gcc then allocates 8 bytes on the stack and fills r1
> with sp - #7? Or is what I had just UB and gcc can do whatever?

The compiler allocates stack memory for 'arg' and passes the address of 'arg'
to the asm; it is necessary in case the asm does something with it without
reading 'arg' itself. One example would be installing a hardware watchpoint on
that memory location.

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

* [Bug ipa/113293] Incorrect code after inlining function containing extended asm
  2024-01-09 16:51 [Bug ipa/113293] New: Incorrect code after inlining function containing extended asm dories.spirits_0p at icloud dot com
                   ` (2 preceding siblings ...)
  2024-01-09 18:27 ` amonakov at gcc dot gnu.org
@ 2024-01-09 19:41 ` dories.spirits_0p at icloud dot com
  3 siblings, 0 replies; 5+ messages in thread
From: dories.spirits_0p at icloud dot com @ 2024-01-09 19:41 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from KBDeveloper <dories.spirits_0p at icloud dot com> ---
(In reply to Alexander Monakov from comment #3)
> (In reply to KBDeveloper from comment #2)
> > 
> > Ah, that makes sense. I had assumed that taking the address of arg would
> > force gcc to store it in memory somewhere. 
> > Is there a reason why gcc then allocates 8 bytes on the stack and fills r1
> > with sp - #7? Or is what I had just UB and gcc can do whatever?
> 
> The compiler allocates stack memory for 'arg' and passes the address of
> 'arg' to the asm; it is necessary in case the asm does something with it
> without reading 'arg' itself. One example would be installing a hardware
> watchpoint on that memory location.

That makes sense. Thanks for the explanation (and your time!)

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

end of thread, other threads:[~2024-01-09 19:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-09 16:51 [Bug ipa/113293] New: Incorrect code after inlining function containing extended asm dories.spirits_0p at icloud dot com
2024-01-09 17:05 ` [Bug ipa/113293] " pinskia at gcc dot gnu.org
2024-01-09 17:14 ` dories.spirits_0p at icloud dot com
2024-01-09 18:27 ` amonakov at gcc dot gnu.org
2024-01-09 19:41 ` dories.spirits_0p at icloud dot com

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).