如何在编译时检查内联函数的参数是否已知?

时间:2011-02-16 20:50:36

标签: c++ static constants inline

我有一个性能关键的内联函数。它根据参数生成一些数据。我希望编译器优化所有调用的数据生成,其中参数在编译时是已知的。问题是我无法强制编译器将优化数据从堆栈中放入静态常量,因为标记数据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?不同。这是更普遍的问题。

5 个答案:

答案 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分支,只留下通用代码。