给定常量函数参数的编译时间优化

时间:2018-06-29 04:47:33

标签: c++ compiler-optimization

我有两个功能void f(int x){...}void g(int x){f(x);}。我知道99%的时间g()收到3或5。在f()中,x从不改变,并监督许多循环和条件分支。以下内容会比我的原始代码快吗?

void g(int x)
{
  if(x == 3) f(3);
  else if(x == 5) f(5);
  else f(x);
}

编译器(g++ -Ofast)与f(3)分别编译f(5)f(x)类似于编译两个模板参数吗?我应该怎么做才能让编译器更轻松地认识到优化机会?声明void f(const int &x){...}有帮助还是必要?

2 个答案:

答案 0 :(得分:1)

此类问题的答案最终会引起误解,因为它们不仅取决于您使用的确切环境,还取决于您的项目将与之链接的其他代码(如果使用链接时间优化)。此外,编译器可以生成多个版本-更为“最优”,然后“最优性”取决于谁在呼叫g()。如果g()是constexpr-这样做,编译器可以使用该事实指导优化。

无论如何:您需要查看编译器的输出;与代码一起编译到您的项目中。只有这样你才能知道。作为序幕,您应该前往https://godbolt.org的Compiler Explorer,并在一个隔离的环境中亲眼看看。

答案 1 :(得分:1)

如果这是对性能至关重要的函数,并且99%的时间f(3)或f(5)被调用,并且您尝试进行优化,则应该测量此类调用的差值。如果f()是内联函数,则优化器也许可以更好地使用常量而不是变量,以便在编译时评估其某些功能(例如常量折叠,强度降低等)。 Godbolt.org查看程序集,看看是否有任何明显的改进。即使没有内联,LTO也可能会有所帮助,尽管不同的人对此表示不同程度的成功。

如果您没有看到太多改进,但认为可能事先了解x,则还可以考虑编写不同的专用版本的f(),例如针对这些情况进行了优化的f3()和f5()。 (尽管您最终可能还会遇到一条更大的指令,并遇到icache问题。这全都取决于您尝试进行的操作,看看收益(和损失)在哪里。最重要的是衡量。将代码复杂化对于没有收获(或更糟的是,以优化的名义减慢它的速度。)