如何解决为GCC复制clang的__builtin_assume
最近,我发现了void __builtin_assume(bool)
for clang,它可以向编译器提供有关程序状态的其他信息。这可以产生很大的变化,例如for example:
#include <cstddef>
// compiles to about 80 instructions at -O3
unsigned sum(unsigned data[],size_t count) {
unsigned sum = 0;
for (size_t i = 0; i < count; ++i) {
sum += data[i];
}
return sum;
}
// compiles to about 10 instructions at -O3
unsigned sum_small(unsigned data[],size_t count) {
__builtin_assume(count <= 4);
unsigned sum = 0;
for (size_t i = 0; i < count; ++i) {
sum += data[i];
}
return sum;
}
我目前被迫使用GCC,我很好奇是否存在等效的内置函数。不幸的是,我在the GCC documentation中找不到__builtin_assume
。也许存在一个内置函数,但是它只是一个不同的名字?
如果不存在等效的内置函数,是否有可能在没有__builtin_assume
的情况下产生相同的结果,例如在条件不成立时有意调用未定义的行为吗?
理想情况下,我想要一个始终可以安全调用的宏,例如:
#if ... // detect clang
#define MY_ASSUME(condition) __builtin_assume(condition)
#elif ... // detect GCC
#define MY_ASSUME(condition) __gcc_builtin_assume_equivalent(condition)
#else
#define MY_ASSUME(condition)
#endif
无论采用哪种解决方案,它都应在constexpr
函数中起作用。
解决方法
我使用了__builtin_unreachable()
,它表示控制流到达此处是“未定义行为”。您可以将其包装在if
中以实质上编写断言。条件可以是false
的任何不变式,因此在您的情况下,您可以放置相反的条件。
示例:
// Basically `assert(count <= 4);`
if ( !(count <= 4) ) {
__builtin_unreachable();
}
编辑:响应评论,您可以将其转换为断言宏,如下所示:
// Line break for readability
#define my_assert( condition ) \
{ if(!(condition)) __builtin_unreachable(); }
根据问题中的代码,您将像这样使用它:
unsigned sum_small(unsigned data[],size_t count) {
my_assert(count <= 4); // <--- Changed here
unsigned sum = 0;
for (size_t i = 0; i < count; ++i) {
sum += data[i];
}
return sum;
}
,
我觉得完全不需要通过未定义的行为。非常简单的if
校验和abort
的定义是明确的,并为优化程序提供了足够的思考空间:
#include <cstddef>
#include <cstdlib>
// compiles to about 10 instructions at -O3
unsigned sum_small(unsigned data[],size_t count) {
if (count > 4)
std::abort();
unsigned sum = 0;
for (size_t i = 0; i < count; ++i) {
sum += data[i];
}
return sum;
}
不需要时,不需要召唤鼻恶魔。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。