Local variables in specified registers don't work correctly with inline asm operands

Bug #1411655 reported by Tim Pambor
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
GNU Arm Embedded Toolchain
Fix Released
Undecided
Unassigned

Bug Description

Version: 4.1.2 - 4.9.3 (4.9-2014-q4-major)
Host: all

register int r0 asm("r0") = 5;
asm volatile("mov %[r0], %[r0]" :: [r0]"r"(r0));

Expected behaviour accotding to the documentation would be that gcc generate:

...
mov r0, r0
...

Instead gcc uses under certain conditions different registers if optimization is turned on.

Related documentation is https://gcc.gnu.org/onlinedocs/gcc/Local-Reg-Vars.html#Local-Reg-Vars which states:
"You may not code an explicit reference to this register in the assembler instruction template part of an asm statement and assume it always refers to this variable. However, using the variable as an asm operand guarantees that the specified register is used for the operand."

I attached a testcase for reproducing this bug. There is a little more code included to increase the register pressure.
With 4.9-2014-q4-major toolchain bug has been reproduced with:
arm-none-eabi-gcc -mthumb -mcpu=cortex-m3 -O1 -fverbose-asm -S -o testcase-46164.s testcase-46164.c

Expected assembler code would have been:
...
  mov r0, r0 @ r0
  mov r1, r1 @ r1
  mov r2, r2 @ r2
...

Actually generated assembler code:
...
  mov r0, r0 @ r0
  mov r4, r4 @ r1
  mov r2, r2 @ r2
...

This bug was already reported upstream 5 years ago but did not see much attention.
Upstream bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=46164

Revision history for this message
Tim Pambor (tp-8) wrote :
Revision history for this message
Hale Wang (hale-wang) wrote :

You are right. This problem is related to the -O1 option. If you use -O0, -O2 or -O3 options, it is OK.

I will follow up with this issue. Thank you.

Revision history for this message
Hale Wang (hale-wang) wrote :

The combine pass combined the volatile register which caused this bug.

The expected assembler code should be:

  mov r4, .L_temp
  mov r1, r4
  ...
  mov r0, r0 @ r0
  mov r1, r1 @ r1
  mov r2, r2 @ r2

But GCC combined the insns, and the code is generated as:

  mov r4, .L_temp
  ...
  mov r0, r0 @ r0
  mov r4, r4 @ r1
  mov r2, r2 @ r2

The register 'r1' is defined as volatile in this case. It should not be combined.

Revision history for this message
Hale Wang (hale-wang) wrote :

I have submitted a patch to GCC community for further discussion.

Refer to: https://gcc.gnu.org/ml/gcc-patches/2015-01/msg02238.html.

Revision history for this message
Hale Wang (hale-wang) wrote :

Hi Tim,

Your testcase is caused by the combine. It's not the same with Siarhei's test case. So I think we should divide your test case to another bug.

And my patch is only used to fix the bug with your test case. So I will submit a new bug in the bugzilla to record your comments.

Thanks,
Hale

Revision history for this message
Hale Wang (hale-wang) wrote :

I have resubmitted a new bug in bugzilla: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64818.

Changed in gcc-arm-embedded:
status: New → In Progress
Changed in gcc-arm-embedded:
status: In Progress → Fix Committed
Changed in gcc-arm-embedded:
status: Fix Committed → Fix Released
milestone: none → 4.9-2015-q2-update
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.