我有一些使用频繁的代码,我希望GCC能够积极优化。但我还想编写干净,可重用的代码,其中包含从几个地方调用的(无限)函数。在内联函数中,有些情况下我知道可以删除代码,因为条件永远不会发生。
让我们看一个具体的例子:
#include <assert.h>
static inline int foo(int c)
{
if (c < 4)
return c;
else
return 4;
}
int bar(int c)
{
assert(c < 2);
return foo(c);
}
使用-DNDEBUG -O3
,GCC仍会生成(c <4)比较,即使我知道不需要它,因为bar
函数的前提是c
是0或1.如果没有-DNDEBUG
,GCC 会删除比较,因为它是断言所隐含的 - 但当然你有断言的开销(这是更多)。
有没有办法将变量范围传达给GCC,以便可以用于优化?
如果CLang能做得更好,我也可以考虑转换编译器。
答案 0 :(得分:2)
您可以在测试中使用__builtin_unreachable
(阅读other builtins)来告诉编译器,例如
if (x<2 || x>100) __builtin_unreachable();
// here the compiler knows that x is between 3 and 99 inclusive
在您的情况下,在bar
开头添加(可能包含在一些漂亮的宏中):
if (c >= 2) __builtin_unreachable();
如果强烈优化(例如至少-O2
),编译器知道 x介于3和99之间(并且最近的GCC包含进行此类分析的代码 - 至少处理简单的常数区间约束,如上所述 - 并在以后的优化过程中利用它们。)
但是,我不太确定你应该使用它! (至少不要经常使用它并将其包装在某些assert
- 就像宏),因为它可能不值得麻烦,因为编译器实际上只能处理和传播简单的约束(其详细信息是特定于编译器版本的)。
AFAIK最近的Clang和GCC都接受了内置。
同时查看__builtin_trap
(也会发出运行时代码)。