【发布时间】:2019-07-16 15:52:06
【问题描述】:
我有一堆代码如下:
int sign(MyEnum e)
{
switch(e)
{
case A:
case B:
return 1;
case C:
case D:
return -1;
default:
throw std::runtime_error("Invalid enum value");
}
}
int f(int a, int b, int c, MyEnum e)
{
const int sign = sign(e);
const int x = a * b - sign * c;
const int y = a + sign * c;
return x / y;
}
这里的算术只是一个例子。实际的代码更复杂,但重点是 sign 是 -1 或 1,具体取决于枚举值,我们进行了一系列计算,其中各种事物乘以 sign。 (编辑:枚举值在编译时未知。)
我希望优化这段代码,就好像我写了如下内容一样:
int f(int a, int b, int c, MyEnum e)
{
switch(e)
{
case A:
case B:
{
const int x = a * b - c;
const int y = a + c;
return x / y;
}
case C:
case D:
{
const int x = a * b + c;
const int y = a - c;
return x / y;
}
default:
throw new std::runtime_error("Invalid enum value");
}
}
当然,我实际上并不想编写所有这样的代码,因为这是测试和维护的噩梦。
使用编译器资源管理器,看起来sign 中的异常可能是这里的问题;如果我有“默认”案例返回,比如-1,那么我得到了我想要的。但我希望这里一些安全。
问题:
- 是否存在引发异常会阻止(或阻止编译器使用)这种优化的根本原因?
- 看起来在
-O3编译这个方法会复制两个方法,其中一个可以满足我的要求,尽管我不知道哪个会真正运行。我可以为此提供提示吗? - 我不知道我是否想在
-O3编译所有内容。我可以只对特定代码块启用优化,还是鼓励编译器进行优化? - 是否有一些花哨的模板元编程技巧或可以用来编写看起来像第一个块但生成的代码看起来像第二个块的代码的东西?
- 对于我正在尝试做的事情还有其他建议吗?
编辑:因为我(显然)不了解手头的所有问题,所以我可能没有给这个标题起个好名字。如果您知道自己在做什么,请随时编辑。
【问题讨论】:
-
如果您不介意 GCC 特定的解决方案,那么您可以考虑
__attribute__((always_inline)),也许.. -
int sign(MyEnum)函数是否被其他翻译单元使用?如果是,则它需要可用于链接。如果不是,它可能位于匿名命名空间中或标记为static。 -
你知道
e在编译时的值是多少吗? -
关于第3点:有GCC-specifc
__attribute__((hot)). -
在此上下文中,
static表示该函数是翻译单元的本地函数,并且不会链接到该翻译单元之外。这允许优化器执行更多优化并可能完全消除该功能(假设启用了优化)。