C++ 循环中的常量条件:编译器优化
考虑以下代码:C++ 循环中的常量条件:编译器优化,c++,optimization,c++11,for-loop,conditional,C++,Optimization,C++11,For Loop,Conditional,考虑以下代码: // Preprocessor #include <iostream> #include <vector> // Internal branching void f1(std::vector<int>& v, const int x = 0) { for (unsigned int i = 1; i < v.size(); ++i) { v[i] = (x != 0) ? (v[i-1]*x) : (v[
// Preprocessor
#include <iostream>
#include <vector>
// Internal branching
void f1(std::vector<int>& v, const int x = 0)
{
for (unsigned int i = 1; i < v.size(); ++i) {
v[i] = (x != 0) ? (v[i-1]*x) : (v[i-1]+v[i-1]);
}
}
// External branching
void f2(std::vector<int>& v, const int x = 0)
{
if (x != 0) {
for (unsigned int i = 1; i < v.size(); ++i) {
v[i] = v[i-1]*x;
}
} else {
for (unsigned int i = 1; i < v.size(); ++i) {
v[i] = v[i-1]+v[i-1];
}
}
}
// Main
int main()
{
std::vector<int> v(10, 2);
f1(v);
f2(v);
return 0;
}
//预处理器
#包括
#包括
//内分枝
无效f1(标准::向量&v,常数int x=0)
{
for(无符号整数i=1;i
它说明了产生相同结果的两个函数的行为:
:在循环内部测试条件f1
:在循环外部测试条件f2
x
,声明为const
我的问题是:当所有优化级别都打开时,编译器是否足够智能,能够在
f2
中转换f1
?检查编译器是否将条件提升出循环的最佳方法是,在编译完程序集并进行充分优化后,真正检查程序集
使用以下内容构建示例后:
g++ -O3 -c example.cpp -o example.o
objdump -d -M intel example.o > example.S
以下是我为f1获得的:
00000020 <f1(std::vector<int, std::allocator<int> >&, int)>:
; ...
23: 8b 54 24 10 mov edx,DWORD PTR [esp+0x10]
27: 8b 7c 24 14 mov edi,DWORD PTR [esp+0x14]
2b: 8b 02 mov eax,DWORD PTR [edx]
2d: 8b 4a 04 mov ecx,DWORD PTR [edx+0x4]
30: 29 c1 sub ecx,eax
32: c1 f9 02 sar ecx,0x2
35: 83 f9 01 cmp ecx,0x1
38: 76 d jbe 57 <f1(std::vector<int, std::allocator<int> >&, int)+0x37>
3a: 31 db xor ebx,ebx
3c: 85 ff test edi,edi
3e: ba 01 00 00 00 mov edx,0x1
43: 75 b jne 60 <f1(std::vector<int, std::allocator<int> >&, int)+0x40>
45: 8b 34 18 mov esi,DWORD PTR [eax+ebx*1]
48: 83 c3 04 add ebx,0x4
4b: 01 f6 add esi,esi
4d: 89 34 90 mov DWORD PTR [eax+edx*4],esi
50: 83 c2 01 add edx,0x1
53: 39 d1 cmp ecx,edx
55: 75 ee jne 45 <f1(std::vector<int, std::allocator<int> >&, int)+0x25>
57: 5b pop ebx
58: 5e pop esi
59: 5f pop edi
5a: c3 ret
5b: 90 nop
5c: 8d 74 26 00 lea esi,[esi+eiz*1+0x0]
60: 8b 34 18 mov esi,DWORD PTR [eax+ebx*1]
63: 83 c3 04 add ebx,0x4
66: 0f af f7 imul esi,edi
69: 89 34 90 mov DWORD PTR [eax+edx*4],esi
6c: 83 c2 01 add edx,0x1
6f: 39 ca cmp edx,ecx
71: 75 ed jne 60 <f1(std::vector<int, std::allocator<int> >&, int)+0x40>
73: eb e2 jmp 57 <f1(std::vector<int, std::allocator<int> >&, int)+0x37>
从这一点开始,在检查之后,x
将不再进行测试,并且只对每个部分执行循环。从第45行到第55行的第一个循环在x==0
时完成。当x!=0
因此,是的,至少在这种情况下,gcc能够在启用完全优化的情况下将条件从循环中提升出来。告诉我以下几点:
#6
,#7
如果无法输入循环,则立即退出(size()
对于此代码,我希望编译器完全消除检查,只需为x==0
构建代码。您当然可以想出编译器无法执行此操作的场景,但在这种情况下,当然可以。[当然,如果你真的关心你的特殊情况,那么就用你的编译器和你的真实代码对它进行基准测试!]
; if(x != 0)
3c: 85 ff test edi,edi
43: 75 b jne 60 ; ...