编译器优化开关是否与长 if-then-else 链不同?

ein*_*ica 5 c++ g++ switch-statement 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;
}
Run Code Online (Sandbox Code Playgroud)

相对

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 */ }
Run Code Online (Sandbox Code Playgroud)

现代 C++ 编译器是否区别对待这些?也就是说,他们是否对这些代码结构应用了不同的潜在优化?或者他们是否将它们“规范化”为相同的,然后决定优化(例如是否形成跳转表)?

笔记:

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

Ser*_*eyA 4

讽刺的是,这正是我几天前对最新编译器所做的测试。事实上,最新的编译器为和clang生成相同的程序集- 对于少量情况(低于 5 个),它会生成一堆直接条件跳转,而对于 5 个或更多情况,它会执行间接表跳转。switchif

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

还值得注意的是,如果 switch case 有“洞”(即控制变量的可能值没有被 case 标签覆盖),它仍然可以转换为一系列条件直接跳转或间接表跳转,但我无法找出确切的公式。

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