When I try to compile some code for x64 CPU architecture with the -fPIC compiler flag set, I run into the following compile error:
Eigen/src/Core/util/Memory.h: In function 'void Eigen::internal::queryCacheSizes_intel(int&, int&, int&, int)':
Eigen/src/Core/util/Memory.h:771:128: error: inconsistent operand constraints in an 'asm'
Eigen/src/Core/util/Memory.h:800:126: error: inconsistent operand constraints in an 'asm'
Ubuntu Linux 12.04
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
Eigen 3.1.2 release
I had a look at the various definitions of the EIGEN_CPUID macro and the version that is defined for x86 with -fPIC compiles. However, since I have absolutely no knowledge of asm code, I don't know whether this will also create correct code. Could someone more knowledgeable have a look at this? Since the default branch has the same code, it is likely to also be a problem for the upcoming 3.2 release.
For what it's worth, here is a discussion of the same problem in some other code:
As discussed there, the problem has also been posted to the GCC bug tracker, unfortunately without reaction so far: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55744
Hm, what you're saying is that for you we should go through the PIC path for both i386 and x64. That would be opposite of what we had to do there:
I did some more googling and found the following information:
"Regarding your CPUID substitute, the problem I see is that you have a "=a" in the output list and an "a" in the input list. While the syntax does let you reuse a specific register, I didn't think mentioing it by name twice was allowed. Msieve does something similar: ..."
If we substitute "a" and "c" in the input list by "0" and "2", we get the same code as that which is defined for __cpuid_count in <cpuid.h> of my GCC compiler, except for some different formatting (as far as I can tell, hoping that I don't miss an important syntax feature of inline assembler code):
#define __cpuid_count(level, count, a, b, c, d) \
__asm__ ("cpuid\n\t" \
: "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
: "0" (level), "2" (count))
I'll give this a try later to see whether it works for me...
At least it does not harm. Hopefully that'll work for you.
No, this didn't solve the problem. I think the bug report that I linked to in the original post was actually referring to this implementation... However, I can't reach any of the gcc.gnu.org websites currently :(
However, the following discussion on the gcc - patches mailinglist is dealing with the topic:
There it is stated that the rbx register is in fact used in x64 mode if memory model "medium" or "large" is used but not with the default "small" model. This explains why I encounter the problem, since we configure the large memory model in our Makefiles. There is a patch discussed in there which I incorporated into the EIGEN_CPUID macro as shown in the attached patch. The code compiles fine now, but it would be good if someone could check that it actually does the right thing....
Created attachment 319 [details]
Patch for Memory.h
This patch adds a x64 PIC variant for EIGEN_CPUID. I created it with TortoiseSVN since I dont have hg installed here, but it's a trivial change anyway so hopefully it's easy to apply anyway...
I don't see what could go wrong, so:
user: Michael Schmidt \
date: 2013-03-19 14:00:42
summary: Fix bug 566: rbx register has to be saved when calling cpuid on x84_64 with -fPIC and medium or large code models.
and I also fixed the 32bits version:
date: 2013-03-19 14:11:59
summary: Make cpuid not use %%esi -> dangerous if someone is using it.
However, I don't feel confidant enough to backport it to 3.1 right now.