我正在编写一门课程的编译器。我遇到了一些优化问题,我不确定如何处理最佳。假设输入语言有一个while循环,它使用必须保存在寄存器中的N个局部变量(或者应该为了快速计算)。假设N> K,寄存器的数量。在while循环结束时有可能改变条件寄存器。编译代码生成 - 条件块内部的寄存器分配
例如,假设x的寄存器(比方说,在i386%EAX)确定之前发表声明如下:
while (x) { x = x - 1 ; /* more statements */ }
在多个语句代码,它有可能被溢出的X回到栈上。当代码跳回到while循环的开始以重新计算x时,它将尝试使用%eax - 但这可能甚至不会保存x的值。所以我们可以有像我使用的是强制代码while语句(所以寄存器被视为空从代码生成的角度来看)之前,溢出所有修改寄存器
movl -8(%ebp), %eax # eax <- x
.... # do stuff but let x stay in %eax
_LOOP1: cmpl $0, %eax
....
movl -12(%ebp), %eax #eax now holds something else
....
jmp _LOOP1
一种解决方案。在while循环的标签之后,代码必须根据需要将所有内容加载到寄存器中。
我的解决办法是这样的:
movl -8(%ebp), %eax # eax <- x
.... # do stuff but let x stay in %eax
movl %eax, -8(%ebp) # spilling and clearing all registers
_LOOP1: movl -8(%ebp), %eax # get a register for x again
cmpl $0, %eax
....
movl -12(%ebp), %eax # eax now holds something else
....
movl %eax, -8(%ebp) # spill to prevent overwrite
jmp _LOOP1
好像我的解决办法是有点多余的或不必要的。有没有我在这里忘记的一些一般优化技巧?
编辑:我还想指出类似的情况发生的条件,如if和if else。发生这种情况是因为一个寄存器可能被分配给条件块内的一个变量,但代码生成器假定它被移动到那里以后的其他所有内容中。我处理这个案件的方法几乎相同。
我还没有太多时间来研究这个问题,但似乎以增加复杂性为代价的性能增益非常微小? – Kizaru 2010-09-27 13:30:17
取决于正在编译的代码(与所有编译器优化一样),获得的增益差别很大。很少有优化影响代码速度总体上超过百分之几。 – 2010-09-27 17:43:12
谢谢。我授予赏金。当我发布我的第一条评论时,我打算这么做。在一些测试用例之后,优化确实很小(对于i386)。我期望它能在像MIPS这样的架构上有用。 – Kizaru 2010-09-29 15:57:57