-
Notifications
You must be signed in to change notification settings - Fork 0
Fixing for Discarded GOs which are emitted during the second build. #109
Conversation
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 really don't fully understand what this proposed change does and why. Please help me understand!
} | ||
|
||
// Reurn true if the GO is in the new module fragments. | ||
auto It = ModuleFragments.find(Digest); |
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.
Is ModuleFragments the collection of fragments that will appear in this compilation? Does it include the pruned entries?
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.
Is ModuleFragments the collection of fragments that will appear in this compilation?
Yes, you are right.
Does it include the pruned entries?
No, it doesn't.
// If function 'A' is dependent on function 'B' and 'B' is dependent on | ||
// function 'C', both RepoDefinition of 'B' and 'C' need to be added | ||
// into in the 'repo.definitions' during the pruning. | ||
addDependentFragments(M, DependentFragments, Fragments, Repository, | ||
CM->digest); | ||
XFixupNames, CM->digest); |
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.
The comment immediately above this line of code is interesting. Why is this the case?
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.
The comment tries to explain why we need recursive calling addDependentFragments
function. It gives an example to demo the case. By the way, it is not added by this PR. The test mentioned in the comment has been added into LLVM test when I fixed the dependent error.
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.
The comment tries to explain why we need recursive calling addDependentFragments function. It gives an example to demo the case. By the way, it is not added by this PR.
Indeed but it does appear to very relevant indeed to the proposed change. In my plea above for help to understand what this does, this seemed particularly pertinent. For the definition of “dependent” in this code you appear to rely on the external fixups rather than the dependents section that I might expect.
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.
Sorry to misunderstand your question. Before discussing the dependent
, I want to clarify the following things:
- Current Status: The discardable functions/variables are always pruned if they are present in the repository.
- The proposed change: The discardable functions/variables are only pruned if they are present in the repository and referenced by other GOs which are in the repository.
- To check whether it is referenced by other pruned GOs. I use the external fixups.
Now, back to your question why I need to change addDependentFragments
function to collect the external fixups of the fragments in the dependent section?
I want to use an example to explain the reason.
The initial build:
Assuming,
- there is a global function
A
and an internal functionB
during the RepoMetadataGeneration pass. - a new function is created by other optimisation pass ( which is after the RepoMetadataGeneration pass) and added into the
A
’s dependent section. - The output compilation contains three members:
A
,B
andD
.B
is only referenced byD
(not byA
). - After the initial build, the
A
,B
andD
are saved in the repository.A
does not have any external fixups.
Build the same file again.
- During the pruning stage, there are only
A
andB
(D
does not exist). A
is pruned and its external fixups are empty.D
needs to be added into the RepoDefinition metadata and its external fixup needs to be collected. This is the change I added in the function ofaddDependentFragments
: collect the external fixups of fragments in the dependent section.B
is a discardable GO but it is referenced byD
, therefore, it can be pruned.
Hope it makes sense. If not, maybe we can arrange a Team Meeting to discuss this in details. 😊
There are two commits in this pull request.
As mentioned before, two kinds of pruning are in the RepoPruning pass:
@Var1 = global i32 42
@Var2 = internal global i32 42
@Var3 = weak global i32 42 The @Var1 = global i32 42, !repo_definition !0
@Var2 = external global i32, !repo_definition !1
@Var3 = external global i32, !repo_definition !2 We can see that 1) the The issue #55 is mainly caused by the repository level pruning. If GO is a discarded GO and isn't referenced by the pruned repository level pruned GO, it would be pruned. Hope this helpful. Please let me know if you need more information. |
The first of these commits sounds like much more than a code refactoring if it introduces new concepts! Perhaps we need to discuss this change in a PR of its own…
This is what we’ve previously considered the role of the pruning pass to be.
Is this a newly introduced feature? What is the motivation behind it? Does this only happen if there is no existing repository (or simply when objects in the compilation are not found in the repo)? |
It didn't introduce any new concepts. These two kinds of pruning always exist in the current master branch. However, they are handled in one single function. The first commit is just a code factoring to make two kinds of pruning more obvious and noticeable.
No, it exists in the current master branch.
I think the motivation is the same as the repository level pruning.
I am not sure I fully understand your question. It does not matter whether there is an existing repository or not. However, the repository level pruning has a high priority. Firstly, the pruning pass will try to find whether there is existing fragment in the repository. If yes, pruning it. Otherwise, the pruning pass will try to find whether there is an existing object in the module. |
Hmm, okay. These are, however, terms that are new to me. Have I simply forgotten from them from earlier discussions (which would be distressing)? Nonetheless, I think that it would be wise to separate these two changes so that the code relating to the functional change can be easily seen. I‘ve spent many hours now trying to work out exactly what this change does and why… We seem to be recursively chasing external fixup names and turning them into records in the dependents section. However, I’m not yet completely convinced that this will be correct in all cases.
The “repository-level pruning” (to use your term) removes code and data that are unchanged since a previous compile. Perhaps “module-level” pruning is just an early optimization to reduce the amount of stuff going through the back-end?
This seems to contradict what you said in the text that I quoted (from this comment):
Did you mean to say something like “if the objects are not already present in the repository“? |
Sorry, we did discuss this when we implement the
Fully agree. I will create a separate PR for code refactoring.
Yes, thanks for clarifying the difference between these two kinds of pruning.
Yes, thanks for correcting this. |
I have created #113 for code review, thanks. |
The discardable functions/variables are only pruned if they are referenced by the pruned GOs.
Fix for #55