uni*_*n83 20 c++ optimization goto compiler-optimization
使用goto
现代C++编译器有哪些性能优势或惩罚?
我正在编写一个C++代码生成器,使用goto
它会使编写更容易.没有人会触及生成的C++文件,所以不要让我全部"goto is bad".作为一个好处,他们可以节省临时变量的使用.
从纯粹的编译器优化角度来看,我想知道goto对编译器优化器的结果是什么?与使用临时/标志相比,它是否使代码更快,更慢或通常没有性能变化.
Jer*_*fin 22
受影响的编译器部分使用流程图.用于创建特定流图的语法通常是无关紧要的 - 如果while
使用goto
而不是实际while
语句创建类似循环的东西,它根本不会影响优化器(到那时,产生的语法)流程图将早已消失).
但是,有可能生成一个流程图,其中goto
s不能由任何正常的流程控制语句(循环,开关等)产生.在这种情况下,您可能会生成不可缩减的流程图,以及何时/如果你这样做,往往会限制编译器优化代码的能力.
换句话说,如果(举例来说)你把代码与正常写for
,while
,switch
等,并转换为使用goto
在任何情况下,但保留了相同的结构,几乎任何合理的现代编译器可能会产生基本相同的代码,通过办法.但是,如果你使用goto
s来生成像几十年前我必须看到的FORTRAN的大部分意大利面,那么编译器可能无法用它做很多事情.
从纯粹的编译器优化预测中,我想知道goto对编译器优化器的结果是什么?与使用临时/标志相比,它是否使代码更快,更慢或通常没有性能变化.
你为什么在乎?您主要关注的是让代码生成器创建正确的代码.效率远不如正确性重要.你的问题应该是"我使用gotos会使我生成的代码更可能或更不可能正确吗?"
查看lex/yacc或flex/bison生成的代码.那段代码充满了getos.这是有充分理由的.lex和yacc实现有限状态机.由于机器在状态转换时进入另一个状态,因此goto可以说是这种转换的最自然的工具.
通过while
在switch
语句周围使用循环,有一种简单的方法可以在许多情况下消除这些.这是结构化代码.Per Douglas Jones(Jones DW,How(not)编码有限状态机,SIGPLAN Not.23,8(1988年8月),19-22.),这是编码FSM的最差方法.他认为基于goto的方案更好.
他还认为,有一种更好的方法,即使用图论技术将FSM转换为控制流程图.这并不容易.这是NP难题.这就是为什么你仍然会看到很多FSM,特别是自动生成的FSM,实现为围绕交换机的循环或通过gotos实现的状态转换.
您如何认为在装配级别表示循环?
使用跳转指令标签 ......
许多编译器实际上甚至会在他们的中级表示中使用跳转:
int loop(int* i) {
int result = 0;
while(*i) {
result += *i;
}
return result;
}
int jump(int* i) {
int result = 0;
while (true) {
if (not *i) { goto end; }
result += *i;
}
end:
return result;
}
Run Code Online (Sandbox Code Playgroud)
LLVM中的收益率:
define i32 @_Z4loopPi(i32* nocapture %i) nounwind uwtable readonly {
%1 = load i32* %i, align 4, !tbaa !0
%2 = icmp eq i32 %1, 0
br i1 %2, label %3, label %.lr.ph..lr.ph.split_crit_edge
.lr.ph..lr.ph.split_crit_edge: ; preds = %.lr.ph..lr.ph.split_crit_edge, %0
br label %.lr.ph..lr.ph.split_crit_edge
; <label>:3 ; preds = %0
ret i32 0
}
define i32 @_Z4jumpPi(i32* nocapture %i) nounwind uwtable readonly {
%1 = load i32* %i, align 4, !tbaa !0
%2 = icmp eq i32 %1, 0
br i1 %2, label %3, label %.lr.ph..lr.ph.split_crit_edge
.lr.ph..lr.ph.split_crit_edge: ; preds = %.lr.ph..lr.ph.split_crit_edge, %0
br label %.lr.ph..lr.ph.split_crit_edge
; <label>:3 ; preds = %0
ret i32 0
}
Run Code Online (Sandbox Code Playgroud)
哪里br
是分支指令(条件跳转).
所有优化都在此结构上执行.那么,goto
是优化者的面包和黄油.
归档时间: |
|
查看次数: |
3492 次 |
最近记录: |