Track zero and sign extension throughout the code generator. #1584
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Previously we manually, and eagerly, sign and zero extended registers as we needed them. This was easy to get wrong, because the absence of sign/zero extension did not mean that it wasn't needed.
This commit forces register allocation to always consider sign / zero extension. What before was, for example:
now becomes:
in_ext
specifies "what extension must be the input value satisfy?" andout_ext
specifies "what extension will the output value have?"The major parts of this commit are thus:
This turned up various potentially dodgy things, including some parts where we had more complexity than I wanted to deal with. I have not hesitated to simplify (which mostly mean deoptimise!) some parts of code generation where it makes reasoning about the changes in this commit easier. In particular, I've less often special-cased the 32-bit cases. We can always make this more complex again later.
This showed up a number of ways we could go wrong: I ended up having to fundamentally rewrite the core part of register allocation because of this. I have also simplified this and we thus generate less optimal code in several ways (notably we spill more due to this commit), though note that we do a lot less sign / zero extension. I have also made more parts of the register allocator amenable in the future to being broken up into testable units, though this commit does not test those bits in isolation.
Note this commit only updates general purpose register allocation. Floating point register allocation is left untouched for now, because (1) this commit is already sufficiently unwieldy (2) sign/zero extension in FP isn't something we need to worry about.
I have tried to strengthen tests when possible, but some have had to be weakened slightly because of our (currently) poorer code generation.
I am sure this commit introduces some new bugs, but I suspect it fixes more bugs than it introduces. I have somewhat more confidence in it than I did before, and I think it provides a more solid base for future changes which will strengthen our confidence further.