Project

General

Profile

Bug #497

Compilation fails when building in Debug mode with CMake and gcc

Added by Rossen Apostolov over 9 years ago. Updated about 9 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Erik Lindahl
Category:
mdrun
Target version:
Affected version - extra info:
Affected version:
Difficulty:
uncategorized
Close

Description

Configuring the build as Debug fails to compile with:

Building C object src/gmxlib/CMakeFiles/gmx.dir/replace.c.o
/tmp/ccL3RWTh.s: Assembler messages:
/tmp/ccL3RWTh.s:2369: Error: local label `"2" (instance number 2 of a fb label)' is not defined
make2: *** [src/gmxlib/CMakeFiles/gmx.dir/replace.c.o] Error 1

With ./configure --enable-debug it succeeds because the configure script preserves all of the optimization flags (-O3 etc), and only adds "-g".

It is strange that replace.c would compile with "-O1" option, but will fail (with the same message as above) if "-O1" is substituted with the string of options that are implicitly turned on (according to "man gcc").

Also, is it OK to keep all the optimization flags when compiling in debug mode with autoconf?

History

#1 Updated by Erik Lindahl about 9 years ago

I've traced this down to thread_mpi headers at least. I'm continuing to look, but due to the low-level interaction and interdependence of those headers it's not entirely trivial to disable the one-by-one to find the problem.

I don't think it's anything obvious though, since it disappears when we enable optimization!

Sander - any ideas?

#2 Updated by Erik Lindahl about 9 years ago

Rats, gcc inline assembly - not my strongest side, but at least I can reproduce it with some simple code now. The bug is in include/thread_mpi/atomic/gcc_x86.h, in the routine tMPI_Spinlock_wait().

This code in an otherwise empty file reproduces it when compiled with gcc without any options:

----------------------------
void test(int x) {
asm volatile("1:\tcmpl $0, 0\n" /* check the lock /
"\tje 2f\n" /
try to lock if it is
free by jumping forward /
"\tpause\n" /
otherwise: small pause
as recommended by Intel /
"\tjmp 1b\n" /
and jump back /
: "=m"(x) /
input x%x
output var /
:
: "memory"/
we changed memory */
);
}
---------------------------

(sorry for the formatting)

#3 Updated by Erik Lindahl about 9 years ago

OK; after a quick gcc-asm-refreshment, I see that the problem is that we're trying to do a forward jump to a label "2" that isn't defined anywhere (second line of inline asm).

I think the solution here might be to insert an empty jump target label, e.g. "\t2: nop\n" as the last inline-asm line, but we will need Sander to confirm that is correct.

#4 Updated by Sander Pronk about 9 years ago

Erik: you're right; thanks for figuring this out. I added the extra label (unfortunately in front of a nop). commit 3643182cac1b28024876276136db8d0d0f9d689f now fixes compiles without optimization.

The reason that optimization made this issue go away is that this inline function is not used anywhere in the code (it's just there for completeness).

#5 Updated by Erik Lindahl about 9 years ago

unfortunately in front of a nop

Considering "nop" usually takes 0 cycles on x86 I think we can live with that ;-)

#6 Updated by Sander Pronk about 9 years ago

That's good to hear.
Interestingly, the 'pause' statement just before that (which is why I re-wrote the function in assembly in the first place) is translated by the assembler into a 'nop', but if a hyperthreaded cpu encounters one in a tight loop, it uses these as a signal to 'context switch' to the other thread - exactly what one would want in a waiting thread.

Also available in: Atom PDF