Hi,
I found the following bug in gcc 3.3 and 3.4 with TLS on x86-32. It seems to be
OK with gcc 4.0-4.4. This problem affects the Userspace RCU library
(http://lttng.org/urcu). I am providing a small test case to show the problem.
comp...@compumobile:~/test$ gcc-3.4 -v -save-temps -c -o gccbug-tls.o
gccbug-tls.c
Reading specs from /usr/lib/gcc/i486-linux-gnu/3.4.6/specs
Configured with: ../src/configure -v --enable-languages=c,f77 --prefix=/usr
--libexecdir=/usr/lib --with-gxx-include-dir=/usr/include/c++/3.4
--enable-shared --with-system-zlib --enable-nls --without-included-gettext
--program-suffix=-3.4 --enable-__cxa_atexit --with-tune=i686 i486-linux-gnu
Thread model: posix
gcc version 3.4.6 (Debian 3.4.6-9)
/usr/lib/gcc/i486-linux-gnu/3.4.6/cc1 -E -quiet -v gccbug-tls.c -mtune=i686 -o
gccbug-tls.i
ignoring nonexistent directory "/usr/local/include/i486-linux-gnu"
ignoring nonexistent directory "/usr/include/i486-linux-gnu"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/gcc/i486-linux-gnu/3.4.6/include
/usr/include
End of search list.
/usr/lib/gcc/i486-linux-gnu/3.4.6/cc1 -fpreprocessed gccbug-tls.i -quiet
-dumpbase gccbug-tls.c -mtune=i686 -auxbase-strip gccbug-tls.o -version -o
gccbug-tls.s
GNU C version 3.4.6 (Debian 3.4.6-9) (i486-linux-gnu)
compiled by GNU C version 3.4.6 (Debian 3.4.6-9).
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
gccbug-tls.c: In function `main':
gccbug-tls.c:26: error: unrecognizable insn:
(insn 21 3 22 0 (set (reg/f:SI 70)
(const:SI (plus:SI (symbol_ref:SI ("data") [flags 0x22] <var_decl
0xb7390c3c data>)
(const_int 4 [0x4])))) -1 (nil)
(nil))
gccbug-tls.c:26: internal compiler error: in extract_insn, at recog.c:2083
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
For Debian GNU/Linux specific bug reporting instructions,
see <URL:file:///usr/share/doc/gcc-3.4/README.Bugs>.
Here is the a sample program that generates this error.
<<<begin>>>
extern struct tls_data __thread data;
struct tls_data {
int val;
char count;
};
struct tls_data __thread data;
/*
* Instruct the compiler to perform only a single access to a variable
* (prohibits merging and refetching). The compiler is also forbidden to reorder
* successive instances of ACCESS_ONCE(), but only when the compiler is aware of
* particular ordering. Compiler ordering can be ensured, for example, by
* putting two ACCESS_ONCE() in separate C statements.
*
* This macro does absolutely -nothing- to prevent the CPU from reordering,
* merging, or refetching absolutely anything at any time. Its main intended
* use is to mediate communication between process-level code and irq/NMI
* handlers, all running on the same CPU.
*/
#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x))
int main(int argc, char **argv)
{
ACCESS_ONCE(data.count);
return 0;
}
<<<end>>>
If we remove the "val" field from the structure (hence putting "count" at the
beginning of the structure with a 0 offset), it works fine.
Thanks,
Mathieu
--
Mathieu Desnoyers
Operating System Efficiency Consultant
EfficiOS Inc.
http://www.efficios.com