首页 > 代码库 > 优化编译器的局限性
优化编译器的局限性
考察以下代码:
void Twiddle1(int *xp, int *yp){ *xp += *yp; *xp += *yp;}void Twiddle2(int *xp, *yp){ *xp += 2 * *yp;}
这两个过程等价吗? 事实上 Twiddle2 的效率更高, 因为它只要求 3 次存储器引用, 而 Twiddle1 需要 6 次, 但它们不能相互代替, 因为当 xp == yp 时,
*xp += *xp;*xp += *xp;
之后, xp 的值是原来的 4 倍, 但是类似 Twiddle2 的操作:
*xp += 2 * *xp;
的结果却是原来的 3 倍. 所以编译器不会产生 Twiddle2 的代码作为 Twiddle1 的优化代码.
考察以下代码:
x = 1000; y = 3000;*q = y;*p = x;t1 = *q // ?
t1 的值依赖于指针 p 和 q 的位置关系, 如果 p == q, 那么 t1 == 1000; 如果不相等, t1 == 3000. 这就是一种妨碍优化的因素, 它严重限制了编译器产生优化代码的机会和优化策略.
两个指针可能指向同一个储存器的位置的情况称为储存器别名使用(memory aliasing). 在直至项安全优化的代码中, 编译器需要假设储存器别名使用的情况.
第二个妨碍优化的因素是函数调用, 考察以下代码:
int F();int Func1(){ return F() + F() + F() + F();}int Func2(){ return 4 * F();}
看上去似乎是相同的结果, 但是 Func2() 只调用 F() 1 次, 而 Func1() 调用 4 次, 考虑以下代码:
int counter = 0;int F(){ return counter++;}
对于 Func1() 我们可以用内联函数进行优化即将函数调用替换为函数体:
//优化后的版本int Funct1Inline(){ int t = counter++; // +0 t = counter++; // +1 t = counter++; // +2 t = counter++; // +3 return t;}
这样的转换不仅可以减少了函数调用的开销, 也允许编译器对代码进行进一步优化:
//编译器进一步优化int Func1Opt(){ int t = 4 * counter + 6; counter = t + 4; return t;}
优化编译器的局限性
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。