编译器优化开关的方式与if-then-else长链不同吗?

时间:2018-11-07 21:43:16

标签: c++ switch-statement g++ compiler-optimization clang++

假设我在编译时有N个不同的整数值,即V_1至V_N。考虑以下结构:

const int x = foo();
switch(x) {
case V_1: { /* commands for V_1 which don't change x */ } break;
case V_2: { /* commands for V_1 which don't change x */ } break;
/* ... */
case V_N: { /* commands for V_1 which don't change x */ } break;
}

const int x = foo();
if      (x == V_1) { /* commands for V_1 which don't change x */ }
else if (x == V_2) { /* commands for V_2 which don't change x */ }
else ...
else if (x == V_N) { /* commands for V_N which don't change x */ }

现代C ++编译器对这些处理方式是否有所不同?也就是说,它们是否对这些代码结构应用了不同的潜在优化方法?还是将它们“规范化”为相同的名称,然后决定进行优化(例如是否形成跳转表)?

注意:

  • 对于现代C ++编译器,我的意思主要是GCC,clang和MSVC的最新版本。 ICC也可能是相关的。
  • 请回答有关最大优化级别(对于clang和GCC,-O3
  • ...但是,如果switchif-then-else链的处理在某些优化级别上是相同的而在其他优化级别上是不同的,那也很有趣。
  • 我猜答案可能取决于N的值-尽可能给出阈值。

1 个答案:

答案 0 :(得分:3)

具有讽刺意味的是,这正是我几天前对最新编译器所做的测试。碰巧,对于最新的编译器,clang会为switchif生成相同的程序集-在少数情况下(低于5),它会生成一堆直接的条件跳转,而对于5种或更多情况下,它会进行间接表跳转。

另一方面,gcc对待它们的方式有所不同:它将switch转换为间接表跳转,而一系列if语句仍然是一系列条件直接跳转。

还值得注意的是,如果开关外壳中有“孔”(即,外壳变量未覆盖的控制变量的可能值),它仍可以转换为一系列条件直接跳转或间接表跳转,但我无法找出确切的公式。

以下是一些播放代码: https://gcc.godbolt.org/z/Lll1Kd