Re: [PATCH 4/5] x86/cpuid: Standardize on u32 in <asm/cpuid/api.h>

From: H. Peter Anvin
Date: Tue Mar 18 2025 - 15:10:49 EST


On 3/18/25 11:48, H. Peter Anvin wrote:

One more thing is that we ought to be able to make cpuid a const
function, allowing the compiler to elide multiple calls. (Slight warning
for feature-enabling MSRs changing CPUID), but that would require
changing the API to returning a structure, since a pure or const
structure can't return values by reference.


So I experimented (test included) and found that gcc 14.2 does not seem to merge the cpuid calls in this code, whereas clang 19.1 does.

-hpa
#include <inttypes.h>
#include <stdio.h>

typedef uint32_t u32;

struct cpuid {
u32 ebx;
u32 edx;
u32 ecx;
u32 eax;
};

static inline __attribute__((const)) struct cpuid
cpuid(u32 leaf, u32 subleaf)
{
struct cpuid rv;
asm("cpuid"
: "=a" (rv.eax), "=c" (rv.ecx), "=d" (rv.edx), "=b" (rv.ebx)
: "a" (leaf), "c" (subleaf));
return rv;
}

static inline __attribute__((const)) u32
cpuid_eax(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.eax;
}
static inline __attribute__((const)) u32
cpuid_ecx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.ecx;
}
static inline __attribute__((const)) u32
cpuid_edx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.edx;
}
static inline __attribute__((const)) u32
cpuid_ebx(u32 leaf, u32 subleaf)
{
struct cpuid rv = cpuid(leaf, subleaf);
return rv.ebx;
}

u32 eax(u32 leaf, u32 subleaf)
{
return cpuid_eax(leaf, subleaf);
}

struct cpuid _cpuid(u32 leaf, u32 subleaf)
{
return cpuid(leaf, subleaf);
}

int test_cpuid(void)
{
int found = 0;

found += !!(cpuid_edx(1, 0) & (1 << 26)); /* SSE2 */
found += !!(cpuid_ecx(1, 0) & (1 << 0)); /* SSE3 */
found += !!(cpuid(1, 0).ecx & (1 << 9)); /* SSSE3 */

return found;
}