[Bug c/70566] Bad ARM code generated for evaluating unsigned int bitfield value

2016-04-06 Thread dan at reactivated dot net
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70566

--- Comment #2 from Daniel Drake  ---
Created attachment 38206
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38206=edit
main.i preprocessed output

[Bug c/70566] Bad ARM code generated for evaluating unsigned int bitfield value

2016-04-06 Thread dan at reactivated dot net
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70566

--- Comment #1 from Daniel Drake  ---
Created attachment 38205
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38205=edit
other.c test case source

[Bug c/70566] New: Bad ARM code generated for evaluating unsigned int bitfield value

2016-04-06 Thread dan at reactivated dot net
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70566

Bug ID: 70566
   Summary: Bad ARM code generated for evaluating unsigned int
bitfield value
   Product: gcc
   Version: 5.3.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: dan at reactivated dot net
  Target Milestone: ---

Created attachment 38204
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=38204=edit
main.c test case source

I have reproduced on gcc-4.9.2, gcc-4.9.3, and gcc-5.3.1 in Debian.

System type: ODROID-U2 (Exynos4412) ARMv7

COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/5/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Debian 5.3.1-13'
--with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs
--enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-5 --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
--enable-libstdcxx-debug --enable-libstdcxx-time=yes
--with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm
--disable-libquadmath --enable-plugin --with-system-zlib
--disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-armhf/jre --enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-armhf
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-armhf
--with-arch-directory=arm --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--enable-objc-gc --enable-multiarch --disable-sjlj-exceptions
--with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb
--enable-checking=release --build=arm-linux-gnueabihf
--host=arm-linux-gnueabihf --target=arm-linux-gnueabihf
Thread model: posix
gcc version 5.3.1 20160323 (Debian 5.3.1-13) 



With a struct set up with bitfield values like this:

struct mystruct {
unsigned int uid_set : 1;
unsigned int is_loaded : 1;
unsigned int nonexistent : 1;
};

The following C code is compiled to bad ARMv7 assembly under certain
circumstances at -O2:

if (!user->is_loaded) 
set_is_loaded (user, 1);

The resultant bad assembly is:

  14:   7803ldrbr3, [r0, #0]
  16:   079blslsr3, r3, #30
  18:   d400bmi.n   1c <on_get_all_finished+0x8>
  1a:   d000beq.n   1e <on_get_all_finished+0xa>
  1c:   4770bx  lr
  1e:   e7efb.n 0 

In the bitfield, uid_set is bit 0 and is_loaded is bit 1.

The assembly loads the bitfield value and shifts left to have the value of
is_loaded at bit 31. So the "bmi" instruction makes perfect sense: if is_loaded
is set, jump to some code that is not going to call set_is_loaded.

The following "beq" instruction is bad. Here we have is_loaded at bit 31, but
we also have uid_set at bit 30. So the value of uid_set is clearly going to
influence the code behaviour here: if uid_set is 1, we will not call
set_is_loaded.

This issue originates from freedesktop's accountsservice where I noticed the
incorrect runtime behaviour.

I am attaching a minimal test case which you can compile with:
gcc -O2 -g -c main.c -o out.o
gcc -c other.c -o other.o
gcc other.o out.o -o prog

Run with:

./prog 0
./prog 1

The argument controls the value of uid_set. It should have no effect on the
runtime behaviour, but you'll notice that myfunc is only called when the arg is
0.

Unfortunately I couldn't figure out how to slim down the test case into a
single file, as that resulted in different (working) asm being generated.

I'm also attaching the preprocessed version of main.c.