-
Notifications
You must be signed in to change notification settings - Fork 3
Fix trim UnusedYield #453
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
Fix trim UnusedYield #453
Conversation
Sometimes when there are equal args being yielded and equal args in the initializer with equal names, deleting the first variable may end up changing the semantics. This commmit corrects that behaviour.
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
☂️ Python Coverage
Overall Coverage
New FilesNo new covered files... Modified Files
|
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 test cases look good but I'm not familiar enough with kirin internals to understand the fix. Can @weinbe58 look this over as well?
There appears to be a bug in trim because of a bug in lowering a for loop + some potential issues in the implementation of the rewrite pass as well. The convention for the return values, initializers, and block arguments are not consistent. inside the loop body if there are repeated variable names those are added to a yield list. after traversing the body of the loop that yield list and the yield results are put into the parent frame to handle the scoping. The problem is that the mapping from names to SSA values is done via a dictionary so depending on how you iterate over the yielded values will change which variable is map to which ssa. The issue here was that when putting the results into the parent frame, the order was switched so that the yielded values that appear later in the body of the loop are added last which means those values will be be used in subsequent statements, but this is not the convention, the convention is that the first values should be used. This lead to some weird code that needed to be added in #453 requiring a double loop over loop variables and checking names which effectively does a remapping of indices to get the order correct. Here the fix is simply to reverse the iterators when putting the result values into the parent frame when lowering so that the earlier arguments are put in last which means they will be used in subsequent statements. Then the rewrite itself had some issues where the block arguments container was being mutated while looping it. At the same time there is a check that compares the loop index of the mutating container to the indices of the original sized container which is not good. I fixed this implementation so that you only mutate the container after doing all the rewrites. closes #452
There appears to be a bug in trim because of a bug in lowering a for loop + some potential issues in the implementation of the rewrite pass as well. The convention for the return values, initializers, and block arguments are not consistent. inside the loop body if there are repeated variable names those are added to a yield list. after traversing the body of the loop that yield list and the yield results are put into the parent frame to handle the scoping. The problem is that the mapping from names to SSA values is done via a dictionary so depending on how you iterate over the yielded values will change which variable is map to which ssa. The issue here was that when putting the results into the parent frame, the order was switched so that the yielded values that appear later in the body of the loop are added last which means those values will be be used in subsequent statements, but this is not the convention, the convention is that the first values should be used. This lead to some weird code that needed to be added in #453 requiring a double loop over loop variables and checking names which effectively does a remapping of indices to get the order correct. Here the fix is simply to reverse the iterators when putting the result values into the parent frame when lowering so that the earlier arguments are put in last which means they will be used in subsequent statements. Then the rewrite itself had some issues where the block arguments container was being mutated while looping it. At the same time there is a check that compares the loop index of the mutating container to the indices of the original sized container which is not good. I fixed this implementation so that you only mutate the container after doing all the rewrites. closes #452
Fix the problem with unused yield removing the wrong arguments.
Fixes Issue #452.
The reason root cause is the following.
For example, consider the example in the Issue.
which becomes the following IR
In this case, each iteration of the for loop yields the the same value twice.
The old behaviour of
scf.trim.UnusedYield
rewrites the for loop to this:It seems to be deleting the first argument it sees everywhere, without regard for whether or not it is used later on when there are other equal values which should be deleted.
This is incorrect, since the
iter_arg
value%x_2
is clearly not used in the arguments of theadd
statement for%x_3
which is what is returned. Instead%x
is used, which would be equivalent to returning0 + n-1
, not using anything from the previous iterations.Instead this should be the correct behaviour:
In the above the
%x_2
argument is actually used in theadd
statement.This PR corrects this incorrect behaviour to correctly delete the right argument when they are both the same.