编译器优化开关的方式与if-then-else长链不同吗? [英] Do compilers optimize switches differently than long if-then-else chains?

查看:46
本文介绍了编译器优化开关的方式与if-then-else长链不同吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  const int x = foo();开关(x){情况V_1:{/*用于V_1的命令,不更改x */};情况V_2:{/* V_1的命令不更改x */}中断;/* ... */大小写V_N:{/* V_1的命令,不更改x */};} 

  const int x = foo();if(x == V_1){/* V_1的命令,它不会更改x */}否则,如果(x == V_2){/* V_2的命令不更改x */}别的 ...否则,如果(x == V_N){/* V_N的命令不变x */} 

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

注意:

  • 对于现代C ++编译器,我的意思主要是GCC,clang和MSVC的最新版本.ICC也可能是相关的.
  • 请回答有关最大优化级别(clang和GCC的 -O3 )
  • ...但是,如果 switch es和 if-then-else -链的处理方式在某些优化级别上相同,而在其他优化级别上不同,则也很有趣.
  • 我猜答案可能取决于 N 的值-如果可能,请提供阈值.
具有讽刺意味的是,这正是我几天前对最新编译器所做的测试.碰巧,对于最新的编译器, clang switch if 生成相同的程序集-在少数情况下(低于5)一堆直接条件跳转,而在5个或更多情况下,它会执行间接表跳转.

另一方面, gcc 则以不同的方式对待它们:它将 switch 转换为间接表跳转,而一系列的 if 语句仍然保留一连串的条件直接跳跃.

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

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

Suppose I have N different integral values known at compile time, V_1 through V_N. Consider the following structures:

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;
}

versus

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 */ }

Do modern C++ compilers treat these differently? That is, do they apply different potential optimization to these code structures? Or do they "canonicalize" them to the same for, then decide on optimizations (such as whether to form a jump table or not)?

Notes:

  • By modern C++ compilers I mean mostly recent versions of GCC, clang and MSVC. ICC could also be relevant.
  • Please answer regarding the maximum optimization level (-O3 for clang and GCC)
  • ... but then, if the treatment of switches and if-then-else-chains is the same in some optimization levels and different in others, that's also interesting.
  • I'm guessing the answer might depend on the value of N - give thresholds if possible.

解决方案

Ironically, that is exactly the test I did just a couple of days back for most recent compilers. As it happened, with latest compilers, clang produces the same assembly for switch and if - for small number of cases (below 5) it produces a bunch of direct conditional jumps, while for 5 or more cases it does an indirect table jump.

On the other hand, gcc treats those differently: it converts switch to indirect table jump, while a series of if statements remain a series of conditional direct jumps.

It is also worth noting, that if switch case has "holes" in it (i.e. possible values for control variable which are not covered by case label), it can be still converted into series of conditional direct jumps or indirect table jump, but I wasn't able to figure out the exact formula.

Here is some play code: https://gcc.godbolt.org/z/Lll1Kd

这篇关于编译器优化开关的方式与if-then-else长链不同吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆