<div dir="ltr"><div>_has_builtin is a function-like macro that evaluates to 1 if the builtin function name that's passed to it is supported by the current version of clang or the architecture that is being targeted.</div><div><br></div><div><a href="http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros" target="_blank">http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros</a><br></div><div><br></div><div>Some people have expressed interest in enhancing the functionality of this macro and making it aware of target features.</div><div><br></div><div>For example, let's say I had the following program and wanted to emit avx2  builtin __builtin_ia32_paddsw256 if the target architecture supported it and emit a plain addition if it was unsupported (I don't know whether the users will specify -mavx2 on the command line):</div><div><br></div><div>$ cat add1.c</div><div><br></div><div>typedef unsigned short v16hi __attribute__((__vector_size__(32)));</div><div><br></div><div>v16hi func1(v16hi a, v16hi b) {</div><div>#if __has_builtin(__builtin_ia32_paddsw256)</div><div>  return __builtin_ia32_paddsw256(a, b);</div><div>#else</div><div>  return a + b;</div><div>#endif</div><div>}</div><div><br></div><div>Currently, clang fails to compile this program unless -mavx2 is explicitly specified on the command line or the target supports avx2: </div><div><br></div><div>$ clang add1.c -S -o - -v -emit-llvm</div>







<div>







<p><span><b>add1.c:5:10: </b></span><span><b>error: </b></span><span><b>'__builtin_ia32_paddsw256' needs target feature avx2</b></span></p><p><b>  </b>return __builtin_ia32_paddsw256(a, b);</p><p>This happens because _has_builtin always evaluates to 1 if the current version of clang supports the builtin for the target architecture (x86 in the case above) regardless of which target features (e.g., avx2) are set. So in this case, we want _has_builtin to know which features are set and evaluate to 0 if feature avx2 is not set.</p><p>However, making _has_builitin smarter breaks the following use case:</p><p>$ cat add1.c<br></p><div>v16hi __attribute__((target("avx2"))) func1(v16hi a, v16hi b) {</div><div>#if __has_builtin(__builtin_ia32_paddsw256)</div><div>  return __builtin_ia32_paddsw256(a, b);</div><div>#else</div><div>  return a + b;</div><div>#endif</div><div>}</div><div><br></div><div>$ clang add1.c -S -o - -v -emit-llvm<br></div><div><br></div><div>If a user compiles the program with clang today, __has_builtin returns 1 because the builtin is supported. In this case, this is what the user wants: the user doesn't need to know if avx2 instructions are available (the target attribute says avx2 is available) but just wants to use _has_builitin to find out whether the current version of clang supports the builtin. However, if we make _has_builtin aware of the target feature, __has_builtin will evaluate to 0, which results in clang emitting the plain addition instead of the builtin (note that the preprocessor is not aware of what target attributes are on the function).</div><div><br></div><div>I can see how making _has_builtin aware of target features can improve programmers' experience. But I've also heard opinions from people who are concerned about the use cases this change will break, so I'm sending out this email to a wider audience.</div></div></div>