-
Notifications
You must be signed in to change notification settings - Fork 5k
Expand "return condition" into "return condition ? true : false" #107499
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
Conversation
Will first address various size regressions in separate PRs before moving forward with this. |
458fe11
to
76cdec5
Compare
PTAL @amanasifkhalid @AndyAyersMS cc @dotnet/jit-contrib
Seems to be nice PerfScore improvements: diffs (size diffs aren't too big, but PerfScore are). Many size regressions are PerfScore improvements, some are missing opportunities for ifConversion phase. |
if (!node->TypeIs(TYP_VOID)) | ||
{ | ||
printf("The tree is expected to be TYP_VOID:\n"); | ||
m_compiler->gtDispTree(node); |
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.
Should there be an assert 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.
Ah, oops, indeed
src/coreclr/jit/optimizebools.cpp
Outdated
cond->gtFlags &= ~GTF_RELOP_JMP_USED; | ||
|
||
// It's difficult to restore the original weight of the block, profile repair will handle it. | ||
fgPgoConsistent = false; |
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.
retTrueBb
and retFalseBb
don't have any successors, right? To maintain the profile, I think you only need to decrease the weight of each return block by the weight of the edge you just removed. We have some helpers to do this:
if (block->hasProfileWeight())
{
retTrueBb->decreaseBBProfileWeight(trueEdge->getLikelyWeight());
retFalseBb->decreaseBBProfileWeight(falseEdge->getLikelyWeight());
}
If you know which epilogue is becoming unreachable, then you can skip this computation. Also, if you use fgRemoveAllRefPreds
above instead of fgRemoveRefPred
, it will return the removed edge, so you don't need to do this computation before changing block
into a BBJ_RETURN
.
Regardless of how you do it, I think we should be able to maintain the profile throughout this transformation.
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.
retTrueBb and retFalseBb don't have any successors, right?
@amanasifkhalid one of them is allowed to have multiple predecessors, hence, can't be removed. But yeah, I agree that we should be able to set the weight, let me see
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.
@amanasifkhalid have I addressed your feedback? in the recent commits
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.
Yes, just one more thing below
Co-authored-by: Aman Khalid <amankhalid@microsoft.com>
src/coreclr/jit/optimizebools.cpp
Outdated
|
||
// Decrease the weight of the return blocks since we no longer have edges to them. | ||
// Although, they still might be reachable from other blocks (at least one of them). | ||
retTrueBb->decreaseBBProfileWeight(block->GetTrueEdge()->getLikelyWeight()); |
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.
nit: These BB weight helpers will set the BBF_PROF_WEIGHT
flag, so if we always update the profile weights here, we will have a mix of profile-derived and heuristic-derived block weights in non-PGO scenarios. We've been trying to avoid this so far by wrapping these updates in if (block->hasProfileWeight())
checks. Some day, I hope to turn on profile synthesis for non-PGO scenarios too so we can get rid of these checks and always maintain the profile, but that will require us to start benchmarking NativeAOT regularly before I feel good about making that change.
In the meantime, could you please wrap this with a hasProfileWeight
check? Thanks!
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, I see - added checks
src/coreclr/jit/optimizebools.cpp
Outdated
#endif | ||
|
||
// Early out if the current method is not returning a boolean. | ||
if ((info.compRetType != TYP_UBYTE) || (genReturnBB != nullptr)) |
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.
Seems like we could proceed and then bail out later, if one of the successors is genReturnBB
.
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
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.
Although, I misunderstood how it works. If am not mistaken, when we run out of some arbitrary limit of RETURNs in the merge-return phase, we merge the rest using this genReturnBb
so you're right, we should not give up 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.
Addressed via ce10e5c
Co-authored-by: Aman Khalid <amankhalid@microsoft.com>
/ba-g "azurelinux.3 timeous" |
Closes #8363
Closes #65370
Various control-flow related optimizations do not kick in for
return <condition>
patterns properly, because JIT mostly works withBBJ_COND
types of blocks.optOptimizeBool
is one of few phases which does supportBBJ_RETURN
but that support takes extra (a lot of) code to support.Instead, let's just expand all
return condition
intoreturn condition ? true : false
and then convert back toreturn condition
where profitable.Example:
Here, "recognize bit-test" optimization (
fgRecognizeSwitch
) does not kick in due toBBJ_RETURN
:This PR:
@stephentoub hit this problem when he was trying to showcase various jit optimizations on simple methods and had to rewrite them into
if-else
.As a follow-up I might clean up various phases relying on
BBJ_RETURN