Registers in MIPS compilers — which to use?
-
26-10-2019 - |
Question
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?
Solution 2
Here's a better solution than chill's, which allocates registers in a finer granularity:
First we perform liveness analysis for each variable, and:
- For a variable the liveness interval of which spans a function call: we prefer callee-saved registers over caller-saved ones.
- For a variable the liveness interval of which doesn't span a function call: prefer caller-saved ones over callee-saved ones.
OTHER TIPS
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.