-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[VPlan] Generalize collectUsersInExitBlocks for multiple exit bbs. #115066
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
Changes from all commits
852ad20
9aa9eca
19efb90
dda14f7
7c70e37
db4e3a0
2bbae30
5569ded
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3839,6 +3839,12 @@ class VPlan { | |
return cast<VPBasicBlock>(getVectorLoopRegion()->getSingleSuccessor()); | ||
} | ||
|
||
/// Return an iterator range over the VPIRBasicBlock wrapping the exit blocks | ||
/// of the VPlan, that is leaf nodes except the scalar header. Defined in | ||
/// VPlanHCFG, as the definition of the type needs access to the definitions | ||
/// of VPBlockShallowTraversalWrapper. | ||
auto getExitBlocks(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If possible, it would be nice if this returned a concrete type or had a comment describing it. It's just a bit awkward for the reader having to look in a different header file to see what it returns. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is a bit unfortunate but I couldn't find a way to do that, as it needs accesses to the definition of There may be another way to spell out the type I am not aware of (it is a few nests of various iterator range adopters). For now I extended the comment to provide more information |
||
|
||
/// The trip count of the original loop. | ||
VPValue *getTripCount() const { | ||
assert(TripCount && "trip count needs to be set before accessing it"); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -306,6 +306,15 @@ template <> struct GraphTraits<VPlan *> { | |
} | ||
}; | ||
|
||
inline auto VPlan::getExitBlocks() { | ||
VPBlockBase *ScalarHeader = getScalarHeader(); | ||
return make_filter_range( | ||
VPBlockUtils::blocksOnly<VPIRBasicBlock>( | ||
vp_depth_first_shallow(getVectorLoopRegion()->getSingleSuccessor())), | ||
[ScalarHeader](VPIRBasicBlock *VPIRBB) { | ||
return VPIRBB != ScalarHeader && VPIRBB->getNumSuccessors() == 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment as in the other PR - I think this can return different blocks depending upon whether you call this before or during VPlan::execute. Is this something we should worry about? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should always return the exit blocks currently in the VPlan, so if some transformation replaces/removes some of the exit blocks, the result would be different. But at the moment, the exit blocks should be fixed, we know them at time of construction and can wrap them in VPIRBasicBlocks and those shouldn't change (and if they change the transform would be responsible to make sure the exit phis are updated accordingly). Is there anything particular in VPlan::execute you are thinking of? (We replace VPBasicBlocks with VPIRBasicBlocks in some cases if they are only created during skeleton creation, but that shouldn't be the case for the exit blocks) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently isn't the middle block the single successor of the loop region? Perhaps I've misunderstood what There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I think the reason why this works is because of the extra There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The middle-block may or may not be included by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, thanks for explaining! I realised that around the same time that you replied. It just took me a while to figure it out. :) |
||
}); | ||
} | ||
} // namespace llvm | ||
|
||
#endif // LLVM_TRANSFORMS_VECTORIZE_VPLANCFG_H |
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.
Not sure how this works when all exiting blocks jump to the same exit block? LoopVectorizationLegality has a list of exiting and exit blocks that could perhaps be useful here? Otherwise you could compile a list of all exiting blocks for that exit block and walk over them.
This algorithm is definitely more powerful than what I originally planned in #88385, which isn't a bad thing. However, I guess it is more difficult to implement for the general case. If it's easier you could just limit this to the single early exit case that LoopVectorizationLegality current supports? That class already has the single early exiting block and early exit block.
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.
To handle multiple exiting blocks, this can be replaced by iterating over all exiting blocks when processing each exit phi I think, as in https://github.com/llvm/llvm-project/pull/112138/files#diff-da321d454a7246f8ae276bf1db2782bf26b5210b8133cb59e4d7fd45d0905decR8857
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.
Oh I see so this patch is only generalising for multiple exit blocks on the assumption that there is only a single predecessor per exit block. It looks like in PR #112138 you've generalised this further by removing that restriction. I guess this is ok and reduces the diff for PR #112138. In that case is it worth adding a temporary assert until PR #112138 lands?
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 current version of the patch has an assert in
addUsersInExitBlocks
to make sure we only updated the exit phis, if the incoming value is from the middle block. Do you think that's sufficient or should I add another one here as suggested?I'll update #112138 once this lands, and the assert in
addUsersInExitBlocks
would be turned into a bail-out as it means we encountered a exit value we cannot handle yet, and only will be able to with #88385,?Uh oh!
There was an error while loading. Please reload this page.
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.
Ah yes I see, that makes sense. In that case you're right what you have now is fine and happy for you to merge this patch!