[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#800321: gcc-5: [mips64el] miscompilation caused by -fexpensive-optimizations



Package: gcc-5
Version: 5.2.1-17
Severity: important
Control: affects -1 ffmpeg
X-Debbugs-Cc: debian-mips@lists.debian.org


Dear Maintainer,

ffmpeg 7:2.8-1 failed to build on mips64el due to a test failure.

I investigated the problem and it turns out to be caused by a compiler bug
that can be avoided by using '-fno-expensive-optimizations'.

Attached is a reduced test case:
$ ls
Makefile  main.c  test.c
$ make
cc -fPIC -O2 -fno-expensive-optimizations -c -o working.o test.c
cc -shared -o libworking.so working.o
cc -o working main.c -L. -lworking
cc -fPIC -O2 -c -o broken.o test.c
cc -shared -o libbroken.so broken.o
cc -o broken main.c -L. -lbroken
LD_LIBRARY_PATH=. ./working || true
A f00000100 101
B f00000100 101
working
LD_LIBRARY_PATH=. ./broken || true
A f00000100 101
broken

In the broken version the '& 0xFFFFFFFF' in following line gets ignored:
    if (*last == ((state | buf) & 0xFFFFFFFF)) 

This also fails with gcc-4.9 and gcc-4.8, so it is a longstanding problem.

Best regards,
Andreas


-- System Information:
Debian Release: stretch/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: mips64el (mips64)

Kernel: Linux 4.2.0-trunk-amd64 (SMP w/4 CPU cores)
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) (ignored: LC_ALL set to C)
Shell: /bin/sh linked to /bin/dash
Init: unable to detect

Versions of packages gcc-5 depends on:
ii  binutils      2.25.1-3
ii  cpp-5         5.2.1-17
ii  gcc-5-base    5.2.1-17
ii  libc6         2.19-22
ii  libcc1-0      5.2.1-17
ii  libgcc-5-dev  5.2.1-17
ii  libgcc1       1:5.2.1-17
ii  libgmp10      2:6.0.0+dfsg-7+b1
ii  libisl13      0.14-2+b1
ii  libmpc3       1.0.3-1+b1
ii  libmpfr4      3.1.3-1+b1
ii  libstdc++6    5.2.1-17
ii  zlib1g        1:1.2.8.dfsg-2+b1

Versions of packages gcc-5 recommends:
ii  libc6-dev  2.19-22

Versions of packages gcc-5 suggests:
pn  gcc-5-doc        <none>
pn  gcc-5-locales    <none>
pn  gcc-5-multilib   <none>
pn  libasan2-dbg     <none>
pn  libatomic1-dbg   <none>
pn  libcilkrts5-dbg  <none>
pn  libgcc1-dbg      <none>
pn  libgomp1-dbg     <none>
pn  libitm1-dbg      <none>
pn  liblsan0-dbg     <none>
pn  libmpx0-dbg      <none>
pn  libquadmath-dbg  <none>
pn  libtsan0-dbg     <none>
pn  libubsan0-dbg    <none>

-- no debconf information
#include <inttypes.h>
#include <stdio.h>

int compare(uint64_t state, uint32_t *last, uint8_t buf);

int main(int argc, char **argv)
{
    uint64_t state = 0xF00000100U;
    uint32_t last  = 0x101U;
    int ret        = compare(state, &last, 0x01);
    if (ret == 0)
        printf("working\n");
    else
        printf("broken\n");
    return ret;
}
CFLAGS += -fPIC -O2
LDFLAGS += -shared

all: working broken
	LD_LIBRARY_PATH=. ./working || true
	LD_LIBRARY_PATH=. ./broken || true

working.o:
	$(CC) $(CFLAGS) -fno-expensive-optimizations -c -o working.o test.c

broken.o:
	$(CC) $(CFLAGS) -c -o broken.o test.c

libworking.so: working.o
	$(CC) $(LDFLAGS) -o libworking.so working.o

libbroken.so: broken.o
	$(CC) $(LDFLAGS) -o libbroken.so broken.o

working: libworking.so
	$(CC) -o working main.c -L. -lworking

broken: libbroken.so
	$(CC) -o broken main.c -L. -lbroken

clean:
	rm -f working.o libworking.so working broken.o libbroken.so broken
#include <inttypes.h>
#include <stdio.h>

int compare(uint64_t state, uint32_t *last, uint8_t buf)
{
    printf("A %"PRIx64" %"PRIx32"\n", state, *last);
    if (*last == ((state | buf) & 0xFFFFFFFF)) {
        printf("B %"PRIx64" %"PRIx32"\n", state, *last);
        return 0;
    }
    return 1;
}

Reply to: