-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GT: Implement live-range covering (lengthened covered by shortened), plus relaxations #65
GT: Implement live-range covering (lengthened covered by shortened), plus relaxations #65
Conversation
9fafd82
to
9be050c
Compare
Perhaps this last commit should be its own PR |
Yes that would make it easier to review. They would definitely ask for that on reviews.llvm.org |
int16_t NumUses() { return useCnt_; } | ||
|
||
llvm::ArrayRef<Register *> GetDefs() { | ||
return {defs_, static_cast<size_t>(defCnt_)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has the same issue as before right? It just extends it to other parts of the code. I thought we could make the underlying datastrcuture (defs_,uses_) a vector. Is this a lot of work to implement? I know it's in list from #47.
Otherwise I can just review the graphtrans portion of the change without this latest commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am planning to pull this commit out into its own PR; I just haven't gotten around to that yet.
What do you mean by "same issue as before"? This doesn't copy the underlying datastructure at all. It's just a pointer + size. This also allows the underlying datastructure to be converted into a vector<Register *>
without any change for users. I did not want to implement conversion to a vector yet because it's tricky to ensure the change doesn't break anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay this makes sense to me.
442b86d
to
9c1f567
Compare
I pulled that commit into its own branch (https://github.com/Quincunx271/OptSched/tree/refactor-getusedef-arrayref). I'll PR that once this PR gets merged |
Sorry, I'll review this as I get a chance. |
Register **uses; | ||
const int useCount = node->GetUses(uses); | ||
assert(useCount >= 0); | ||
return {uses, static_cast<size_t>(useCount)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering, does makeArrayRef work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed it would. It has an overload which calls the same constructor that I'm calling here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
I wonder about live out values. I believe the exit node will be counted as a user of live-out vregs. If B is the last user in the region of a live-out value should it matter from reg-alloc POV?
@kerbowa I want to make sure I understand what you're saying. If we have a live-out vreg
I don't see how that can affect things for this graph transformation. We'll always find |
That's what I mean. I was wondering if live-out values might need special consideration, and should "affect things". For example what if the live range is split and we are spilling the second half of the interval. Could it be better to schedule B first in that situation? This most likely falls out of the realm of what the scheduler should be expected to know when calculating register pressure. Whether live-out values should have special consideration is something that has wider implications. I have no issues with this PR. |
Allow a live range to be lengthened, if a corresponding range is shortened. Some refactoring: - Pull out logic to find possible last uses of a node into its own function. - Wrap GetUses and GetDefs to return an llvm::SmallVector - Use algorithms where possible
For the hypothetical schedule considering nodes A and B, where B appears before A, given a register R used by B but not by A, there must be a node C such that: The old condition was: C in RcrsvScsr(B) (and hence C in RcrsvScsr(A) because of an earlier RcrsvScsr(B) is a subset of RcrsvScsr(A)). We can relax this requirement: C in RcrsvScsr(A). The goal is to show that such a C must exist after A, given the hypothetical: [..., B, ..., A, ...]. If C in RcsrvScsr(A) and C is not A, then the hypothetical must actually be [..., B, ..., A, ..., C, ...], meaning that we're good and can proceed.
We can cover lengthened live ranges based on defines, not just uses. The easiest way to account for this is to change the way of thinking about it: (# lengthened) - (# shortened) <= 0 meets our optimality condition.
We don't need to copy the uses/defs. Instead, we use an llvm::ArrayRef.
9c1f567
to
fb7ed87
Compare
This PR implements live-range covering for the static superiority graph transformations, and it also relaxes the rules to apply graph transformations.
The relaxations:
This is valid because the point is to prove that R is used after the "critical" region, and A is at the end of said region.
This has been tested on the fp part of CPU2006. Without history domination and with PERP, there are no mismatches.