'__has_builtin' and '-mcpu'

For our chip we have implemented many builtins, but some of these builtins are only available with particular versions of the chip that we select using ‘-mcpu’.

If the programmer attempts to use a builtin that is not supported by the selected CPU, the compiler correctly diagnoses that it is not available, so all is well.

But I was thinking that it might be useful for the programmer to test for the existence of the builtin using ‘__has_builtin’, but while this returns true when give the name of any of our builtins, it does so regardless of which CPU variant was selected.

Is there someplace I need to supplement the builtin descriptions so that ‘__has_builtin’ will return false if the builtin exists but is not available for the selected CPU, or is it not possible to express this? If it is possible, how should I express this?

Thanks,

MartinO

Hi Martin,

A similar problem was reported by Android:

https://llvm.org/bugs/show_bug.cgi?id=28629

and it seems my interpretation of "has_builtin" was wrong, and yours
is right (so was Stephen's).

I'll update that bug to reflect this, but this opens a larger Clang
question as to what does it mean to "have a builtin".

In that example, __has_builtin returns true, but it's implemented as a
library call and only implemented in Compiler-RT, which is an odd
combination. That is why I assumed that it meant that Clang "knew
about it and how to lower" instead of "knew how to custom lower
without library calls".

Given that this is a CPU specific (at least TargetFeature-specific)
feature, getting the target's description is sine qua non to get this
working, which means call backs into LLVM. But once you got the
Subtarget object, "has<FeatureX>" is a simple call. :slight_smile:

cheers,
--renato

Gosh, not the response I was expecting, I just assumed I had missed implementing something.

Thanks for your reply and the useful bug ticket. For me it's not a big problem, because I can use:

  #if __has_builtin(__builtin_shave_foobar) && defined(__cpuname__)

but had thought it would be neater to just do:

  #if __has_builtin(__builtin_shave_foobar)

Most of my builtins are bindings to discrete exotic instructions that the compiler cannot easily discover, but each chip variant adds or removes new instructions, which is what prompted my question. The definitions for these which I added into 'tools/clang/lib/CodeGen/CGBuiltin.cpp' does detect that the requested builtin is not available and I return 'nullptr', so the compiler gracefully diagnoses it and it never gets as far as LLVM and lowering.

Thanks again,

  MartinO

I may be completely wrong on the implementation side, of course. But
this is what GCC folks told me about the "intention" of the
has_builtin check.

I'm not sure how much we can do in terms of individual CPUs anyway. I
may have to live with those weird edge cases for a long time... :slight_smile:

cheers,
--renato