MIPS 编译器中的寄存器使用哪个?
我目前正在写一个玩具编译器作为作业,针对MIPS架构。
从高级语言转换时通常有 18 个可用寄存器:s0
到 s7
(由被调用者保存),以及 t0
到 < code>t9 是调用者保存的。
有了这 18 个可用寄存器,一个问题就出现了:在执行函数转换时我应该选择哪个寄存器。
每组都有其优点和缺点:
- 被调用者保存的寄存器必须分别在函数开始和结束时保存到堆栈中并从堆栈中恢复。
- 调用者保存的寄存器必须分别在调用子例程之前和之后保存到堆栈并从堆栈中恢复。
我很清楚,如果我采用静态策略来使用这些寄存器——无论策略是什么,比如更喜欢被调用者保存的寄存器而不是调用者保存的寄存器——我将不会获得最佳性能,因为很可能会出现不必要的寄存器加载/商店。
那么,使用这两组寄存器有什么好的做法吗?
I'm currently writing a toy compiler as a homework, targeted at the MIPS architecture.
There are 18 registers that are generally available when translating from higher-level languages: s0
to s7
which are callee-saved, and t0
to t9
which are caller-saved.
With these 18 registers available, a question emerges: which register should I prefer when performing the translation of a function.
Each set has its pros and cons:
- Callee-saved registers must be saved to and restored from the stack at the beginning and the end of a function, respectively.
- Caller-saved registers must be saved to and restored from the stack before and after invoking a subroutine, respectively.
It's clear to me that if I adopt a static strategy on using these registers — whatever the strategy is, like preferring callee-saved registers over caller-saved ones — I will not get the optimal performance since most probably there will be unnecessary register load/stores.
So, is there any good practices of using these two sets of registers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在非叶函数中更喜欢被调用者保存的寄存器,在叶函数中更喜欢调用者保存的寄存器。
在调用树的叶子和上一层,如果运气好的话,您将不会有任何保存。
Prefer callee-saved registers in non-leaf functions, prefer caller-saved registers in leaf functions.
At the leaves and one level up the call tree, with only a little luck, you won't have any saves whatsoever.
这是一个比 chill 更好的解决方案,它以更细的粒度分配寄存器:
首先,我们对每个变量执行活跃度分析,并且:
Here's a better solution than chill's, which allocates registers in a finer granularity:
First we perform liveness analysis for each variable, and: