Search code examples
gccintrinsicsbmi

How can I check if BMI2 instructions are available in my ifunc resolver?


I want to use the _bzhi_u32 intrinsic, but I want to revert to a regular C implementation if the processor where the executable runs doesn't support the BMI2 instruction set.

I'm using GCC 4.8.3 and I have the following

static inline uint32_t myfunc_bmi(uint32_t in) {
     return _bzhi_u32(in, 3); /* as an example */ 
}
static void * resolve_myfunc(void) {
  __builtin_cpu_init();.
  if (__builtin_cpu_is("corei7") return myfunc_bmi2;
  return myfunc_default;
}
static inline uint32_t myfunc(uint32_t in) __attribute__ ((ifunc "resolve_myfunc")));

I originally wanted to use __builtin_cpu_support() to check explicitly for BMI2 but seems that you can't check for that with __builtin_cpu_support(). My current check of corei7 doesn't seem perfect either because as I understand some mobile versions of i7 Haswell doesn't have BMI2 (I tried on a VirtualBox Linux guest running on Windows 7 on [email protected] and it raises a SIGILL Illegal Instruction).

So is there a fail-safe way to check for BMI2?


Solution

  • The __builtin_cpu_supports is working for me (GCC 5.1).. GCC 4.9 and lower versions does not support BMI2 detection.

    Try this ->

    __builtin_cpu_init ();
    if (__builtin_cpu_supports("bmi2")) {
        printf("BMI2 supported \n");
    }
    

    To resolve your issue you should update your GCC version.

    Alternatively use CPUID and extract the BMI2 bit if you don't want to update your GCC.

    /A