Skip to content
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

JIT: Fold more nullchecks #111985

Merged
merged 12 commits into from
Jan 31, 2025
Merged

JIT: Fold more nullchecks #111985

merged 12 commits into from
Jan 31, 2025

Conversation

EgorBo
Copy link
Member

@EgorBo EgorBo commented Jan 29, 2025

Handles redundant checks in Example 1 in #111980

Some nice diffs

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jan 29, 2025
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@EgorBo
Copy link
Member Author

EgorBo commented Jan 30, 2025

@AndyAyersMS @jakobbotsch @dotnet/jit-contrib PTAL, diffs show no TP regression.

I also tried to extend the algorithm to handle nested PHIs, but it didn't find additionally anything. Ideally, like Jakob suggested, we should use VisitReachingVN function, but it's tricky to extract BBs out of it.
After this PR I want to make a small clean up in various opt...IsNonNull functions

@@ -5810,6 +5833,35 @@ ASSERT_VALRET_TP Compiler::optGetVnMappedAssertions(ValueNum vn)
return BitVecOps::UninitVal();
}

//------------------------------------------------------------------------
// optGetEdgeAssertions: Given a block and its predecessor, get the assertions
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've extracted this function from rangecheck.cpp to re-use in my function

{
AssertionIndex assertionIndex = GetAssertionIndex(index);
if (assertionIndex > optAssertionCount)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant condition, I guess it wasn't deleted when we moved all "walk asserts" pieces to BitVecOps::Iter.

return blockPred->bbAssertionOut;
}

if ((blockPred->KindIs(BBJ_ALWAYS) && blockPred->TargetIs(block)) ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought for BBJ_ALWAYS the right set was bbAssertionOut?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually for all other BBJ_KINDs you can use bbAssertionOut. Just BBJ_COND is special.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AndyAyersMS are you sure? e.g. what about BBJ_SWITCH or some EH related blocks? I copied this function from rangecheck

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've partially addressed your feedback as I was not confident I can just unconditionally return bbAssertionOut for something other than BBJ_ALWAYS/BBJ_COND(false edge).
However, it looks like we don't typically work with anything but these two anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bbAssertionOut should be set for all blocks -- for most block kinds it is the only thing we have. Only BBJ_COND also has bbJtrueAssertionOut.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AndyAyersMS I see, ok changed

return bbJtrueAssertionOut[blockPred->bbNum];
}
}
return BitVecOps::UninitVal();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this should return an empty BV on failure, though I also think (once the above is restructured to handle all pred block kinds) you should never get here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returned empty BV

@EgorBo
Copy link
Member Author

EgorBo commented Jan 30, 2025

@AndyAyersMS @jakobbotsch anything else? I've addressed your feedback. Diffs slightly improved (due to better way to look for PhiDefs via VN).

I plan to use optVisitReachingAssertions for a few more things with nice diffs (if not wrong) 🙂

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just one thing I'm puzzled about.

{
if ((blockPred->KindIs(BBJ_COND) && blockPred->TrueTargetIs(block)))
{
if (bbJtrueAssertionOut != nullptr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious if you ever see this being null.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assumed it could in rangecheck if assertprop didn't run, but not sure such combination is possible. From a quick SPMI run it's not null. I'll convert it into an assert in my next PR to avoid spinning CI for it

@EgorBo
Copy link
Member Author

EgorBo commented Jan 31, 2025

/ba-g "Linux-arm64 is blocked by dotnet/dnceng#4892, Build-analysis didn't recognize some failures as known build issue "

@EgorBo EgorBo merged commit 62528e7 into dotnet:main Jan 31, 2025
108 of 113 checks passed
@EgorBo EgorBo deleted the improve-nonnull-assertions branch January 31, 2025 00:16
grendello added a commit to grendello/runtime that referenced this pull request Jan 31, 2025
* main:
  JIT: fix case where implied subrange assertions can get lost in morph (dotnet#112020)
  Propose new async API (dotnet#110420)
  Move the diagnostic print for stack overflow test failure (dotnet#112001)
  JIT: Fold more nullchecks (dotnet#111985)
  Baseline more pri1 tests (dotnet#111068)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants