New user self-registration is disabled due to spam. Please email eigen-core-team @ if you need an account.
Bug 566 - EIGEN_CPUID: inconsistent operand constraints in an 'asm' for x64 with -fPIC
Summary: EIGEN_CPUID: inconsistent operand constraints in an 'asm' for x64 with -fPIC
Alias: None
Product: Eigen
Classification: Unclassified
Component: Core - general (show other bugs)
Version: 3.1
Hardware: x86 - 64-bit Linux
: Normal Unknown
Assignee: Nobody
Depends on:
Blocks: 3.2
  Show dependency treegraph
Reported: 2013-03-17 12:26 UTC by Michael Schmidt
Modified: 2013-03-19 14:15 UTC (History)
2 users (show)

Patch for Memory.h (808 bytes, patch)
2013-03-19 12:59 UTC, Michael Schmidt
no flags Details | Diff

Description Michael Schmidt 2013-03-17 12:26:37 UTC
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'

System Details:
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.
Comment 1 Michael Schmidt 2013-03-17 12:39:51 UTC
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:
Comment 2 Gael Guennebaud 2013-03-19 00:39:44 UTC
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:
Comment 3 Michael Schmidt 2013-03-19 11:13:08 UTC
I did some more googling and found the following information:

Post 75:
"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...
Comment 4 Gael Guennebaud 2013-03-19 11:28:31 UTC
At least it does not harm. Hopefully that'll work for you.
Comment 5 Michael Schmidt 2013-03-19 12:58:27 UTC
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 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....
Comment 6 Michael Schmidt 2013-03-19 12:59:51 UTC
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...
Comment 7 Gael Guennebaud 2013-03-19 14:15:35 UTC
I don't see what could go wrong, so:
changeset:   79d013cace93
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:
changeset:   201cfa810067
user:        ggael
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.

Note You need to log in before you can comment on or make changes to this bug.