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

            Bug ID: 70184
           Summary: Exlpicit register variables overwritten by conversion
                    libcall
           Product: gcc
           Version: 6.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: inline-asm
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org
  Target Milestone: ---
            Target: arm

Consider the testcase:
void foo(unsigned a, float b)
{
  unsigned c = (unsigned) b;
  register unsigned r0 __asm__("r0") = a;
  register unsigned r1 __asm__("r1") = c;
    __asm__ volatile( "str %[r1], [%[r0]]\n"
                      :
                      : [r0] "r" (r0),
                        [r1] "r" (r1));
}

Compile for an arm target with (for example) -Os -mfloat-abi=soft
-march=armv7-a -marm.
This generates:
foo:
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        push    {r4, lr}
        mov     r0, r1
        bl      __aeabi_f2uiz
        mov     r1, r0
        .syntax divided
@ 7 "foo.c" 1
        str r1, [r0]

@ 0 "" 2
        .syntax unified
        pop     {r4, pc}

The register r0 holding 'a' gets overwritten as part of the setup for the
rounding libcall so when it gets tied to the variable 'r0' expecting it to hold
'a' it gets garbage instead.

This testcase is warned about in:
https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables

but the code above explicitly follows the workaround suggested on that page so
I'd expect it to work.
Is this indeed a supported usecase of local register variables? and if so, is
there a workaround for this bug?

Reply via email to