constexpr 的函数参数等效项是什么?

jww*_*jww 2 clang constexpr c++11

我们正在尝试加速 Clang 和 Visual C++ 下的一些代码(GCC 和 ICC 也可以)。我们认为可以用来constexpr告诉 Clang 一个值是编译时常量,但它会导致编译错误:

$ clang++ -g2 -O3 -std=c++11 test.cxx -o test.exe
test.cxx:11:46: error: function parameter cannot be constexpr
unsigned int RightRotate(unsigned int value, constexpr unsigned int rotate)
                                             ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

这是简化的情况:

$ cat test.cxx
#include <iostream>

unsigned int RightRotate(unsigned int value, constexpr unsigned int rotate);

int main(int argc, char* argv[])
{
  std::cout << "Rotated: " << RightRotate(argc, 2) << std::endl;
  return 0;
}

unsigned int RightRotate(unsigned int value, constexpr unsigned int rotate)
{
  // x = value; y = rotate
  __asm__ ("rorl %1, %0" : "+mq" (value) : "I" ((unsigned char)rotate));
  return value;
}
Run Code Online (Sandbox Code Playgroud)

海合会和国际商会会做正确的事。2他们认识到表达式中的值RightRotate(argc, 2)在我们所知的物理宇宙定律下不能改变,并且它将被视为2编译时间常数并将其传播到汇编代码中。

如果我们删除constexpr,那么 Clang 和 VC++ 会将函数组装成 a rotate REGISTER,这比 a 慢 3 倍rotate IMMEDIATE

我们如何告诉 Clang 函数参数rotate是一个编译时常量,并且它应该被组装成 arotate IMMEDIATE而不是 a rotate REGISTER

tem*_*def 5

您可以为此使用非类型模板参数:

template <unsigned int rotate> RightRotate(unsigned int value) {
     ...
}
Run Code Online (Sandbox Code Playgroud)

然后你可以将其调用为

RightRotate<137>(argument); // rotate is 137 here
Run Code Online (Sandbox Code Playgroud)