我有一个性能关键的内联函数。它根据参数生成一些数据。我希望编译器优化所有调用的数据生成,其中参数在编译时是已知的。问题是我无法强制编译器将优化数据从堆栈中放入静态常量,因为标记数据static
会破坏参数不是编译时常量的情况。堆栈上的常量数据会影响性能。有没有办法推断(可能使用templates / boost :: enable_if),参数是编译时常量并选择适当的数据生成实现?
澄清
基本上我有以下内容:
struct Data {
int d_[16];
};
inline Data fun(int param)
{ //param can sometimes be a compile-time constant
... //generate the data
Data res = {gen0, gen2, gen3, ..., gen15}; //put the data into result
return res;
}
因此当param
不是编译时常量时,我们只生成所有数据并返回
当param
已知时,编译器可以优化数据生成。但是它无法优化以下行并生成大量代码,只需将res
成员设置为已知数据(数据嵌入到程序代码中)。我希望编译器创建一个静态常量,然后将其复制到返回对象(这比执行包含嵌入数据的代码更快)。由于这是一个内联函数,因此即使是副本也可能没有必要。
声明
此问题与How to use different overload of an inline function, depending on a compile time parameter?不同。这是更普遍的问题。
答案 0 :(得分:2)
我不相信有任何办法可以做到这一点;编译器有责任优化调用,而不是语言......所以没有可移植的方法来做到这一点。 :\
答案 1 :(得分:2)
您是否实际剖析了代码并证明将常量传递给您的(内联?)函数是瓶颈?
如果您确实进行了分析,那么您将不得不帮助编译器解决这个问题,因为没有办法自动完成。当您知道常量和正常版本时,您必须手动调用该函数的模板版本。
答案 2 :(得分:1)
所以听起来你有:
template <int N> myfunc_const_N() { /*...*/ }
inline myfunc_var_N(int N);
并且您希望能够键入myfunc(n);
并让编译器调用myfunc_const_N<n>();
(如果有效)或myfunc_var_N(n);
如果没有?
我的猜测是不可能的,但这很难证明。
但如果可以的话,它会给你带来多大的收获吗?在代码写入时,你不多久知道一个给定的表达式是否是编译时常量?如果你有常量,为什么不自己使用模板版本?如果你没有,那么为什么不自己使用函数参数版本?
答案 3 :(得分:1)
如果函数是内联的,那么编译器 将在适当时执行常量折叠优化,当它内联函数时,假设你有一个相当合理的编译器。
答案 4 :(得分:1)
这不可移植,但在GCC和可能的Clang上有一个__builtin_constant_p
编译器功能。这使您可以询问编译器是否在编译期间知道变量的值。您可以像这样使用它:
void f(int arg) {
if (__builtin_constant_p(arg) && arg == 0) {
// Handle case where arg is 0 AND known at compile time.
} else {
// Generic code.
}
}
这样,如果else
在编译时已知并且为0,编译器将不会在arg
分支中生成代码。
使这个更具可移植性的一个有用技巧可能是使用一些宏hackery。
#ifdef __GNUC__
# define CONSTANT_P(x) __builtin_constant_p(x)
#else
# define CONSTANT_P(x) 0
#endif
根据需要添加支持类似内容的其他编译器,现在您可以在不支持此功能的编译器上使用它而不会产生额外开销。那些编译器,如果它们有价值,将消除CONSTANT_P
分支,只留下通用代码。