【发布时间】:2020-05-23 09:16:07
【问题描述】:
square 的以下实现会产生一系列 cmp/je 语句,就像我期望的链式 if 语句一样:
int square(int num) {
if (num == 0){
return 0;
} else if (num == 1){
return 1;
} else if (num == 2){
return 4;
} else if (num == 3){
return 9;
} else if (num == 4){
return 16;
} else if (num == 5){
return 25;
} else if (num == 6){
return 36;
} else if (num == 7){
return 49;
} else {
return num * num;
}
}
下面会生成一个数据表供返回:
int square_2(int num) {
switch (num){
case 0: return 0;
case 1: return 1;
case 2: return 4;
case 3: return 9;
case 4: return 16;
case 5: return 25;
case 6: return 36;
case 7: return 49;
default: return num * num;
}
}
为什么gcc无法将top的优化成bottom的?
拆机参考:https://godbolt.org/z/UP_igi
编辑:有趣的是,MSVC 为 switch case 生成了一个跳转表而不是一个数据表。令人惊讶的是,clang 将它们优化为相同的结果。
【问题讨论】:
-
“未定义的行为”是什么意思?只要可观察的行为相同,编译器就可以生成它想要的任何汇编/机器代码
-
@user207421 忽略
returns;案例没有breaks,因此开关也有特定的执行顺序。 if/else 链在每个分支中都有返回,这种情况下的语义是等价的。优化不是impossible。作为反例icc 没有优化任何功能。 -
也许是最简单的答案...... gcc 只是无法看到这个结构并优化它(还)。
-
我同意@user1810087。您只是找到了编译器细化过程的当前边界。当前未被识别为可优化的子子案例(某些编译器)。事实上,并非所有 else-if 链都可以这样优化,只有 SAME 变量针对常量值进行测试的子集。
-
if-else 执行顺序不同,从上到下。尽管如此,用 if 语句替换代码并没有改进机器代码。另一方面,switch 没有预定义的执行顺序,本质上只是一个美化的 goto 跳转表。话虽如此,编译器可以对此处的可观察行为进行推理,因此 if-else 版本的糟糕优化令人非常失望。
标签: c++ c gcc optimization compiler-optimization