Wrong code generated for big-endian and -O1

Bug #1332079 reported by Petr Cvachouček on 2014-06-19
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
GNU Arm Embedded Toolchain
High
Thomas Preud'homme

Bug Description

Version: 4.8-2014q2
Host: All
Target: Cortex-R4 big-endian (TMS570)

To reproduce, build this simple test program with -O0, -O1 and -O2:

test.c:
---------
#include <stdio.h>

unsigned short v = 0x5678;
int i;
int j = 0;
int *ptr = &j;

int func()
{
    for (i = 0; i < 1; ++i)
    {
        *ptr = -1;
        v = 0x1234;
    }
    return v;
}

int main (void)
{
    int x = func();
    printf("x = 0x%x, j = %d, v = 0x%x\n", x, j, v);
    return 0;
}

This program outputs (depending on optimization level):
-O0: x = 0x1234, j = -1, v = 0x1234
-O1: x = 0x0, j = -1, v = 0x0
-O2: x = 0x1234, j = -1, v = 0x1234

build commands:
arm-none-eabi-gcc -c test.c -o test0be.o -O0 -march=armv7-r -mbig-endian
arm-none-eabi-gcc -c test.c -o test1be.o -O1 -march=armv7-r -mbig-endian
arm-none-eabi-gcc -c test.c -o test2be.o -O2 -march=armv7-r -mbig-endian
arm-none-eabi-objdump -d test0be.o >test.dump
arm-none-eabi-objdump -d test1be.o >>test.dump
arm-none-eabi-objdump -d test2be.o >>test.dump

The function func() sets the global variable "unsigned short v" to value 0x1234. We get correct output of the program for -O0 and -O2. Optimization -O1 causes program miscompilation.

object dump (-O1 case only):
00000000 <func>:
   0: e3003000 movw r3, #0
   4: e3403000 movt r3, #0
   8: e3a02000 mov r2, #0
   c: e5832000 str r2, [r3]
  10: e3001000 movw r1, #0
  14: e3401000 movt r1, #0
  18: e3e0c000 mvn ip, #0
  1c: e1df03b0 ldrh r0, [pc, #48] ; 54 <func+0x54> <== here we load half-word from offset 0x54 where should be 0x1234
  20: e1a02003 mov r2, r3
  24: e5913000 ldr r3, [r1]
  28: e583c000 str ip, [r3]
  2c: e1c100b4 strh r0, [r1, #4] <== here we write to global variable v
  30: e5923000 ldr r3, [r2]
  34: e2833001 add r3, r3, #1
  38: e5823000 str r3, [r2]
  3c: e3530000 cmp r3, #0
  40: dafffff7 ble 24 <func+0x24>
  44: e3003000 movw r3, #0
  48: e3403000 movt r3, #0
  4c: e1d300b4 ldrh r0, [r3, #4]
  50: e12fff1e bx lr
  54: 00001234 .word 0x00001234 <== loading half-word from this offset results in reading 0x0000 (we're on big-endian)

Petr Cvachouček (cvachoucek) wrote :
Changed in gcc-arm-embedded:
status: New → Confirmed
importance: Undecided → High
assignee: nobody → Thomas Preud'homme (thomas-preudhomme)

This affects latest release toolchain but seems to have been solved in trunk. Or maybe not but the code generated doesn't use a litteral anymore but an immediate instead. Maybe the bug is still latent though.

In fact the bug is also present on trunk but the given testcase as compiled by trunk gcc will use immediate instead of a constant pool. Thanks for your bug report Petr!

Changed in gcc-arm-embedded:
status: Confirmed → In Progress
Changed in gcc-arm-embedded:
status: In Progress → Fix Committed
Changed in gcc-arm-embedded:
status: Fix Committed → 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  Edit
Everyone can see this information.

Other bug subscribers

Bug attachments