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

Handle overlapped groups of bounds checks #112660

Merged
merged 4 commits into from
Feb 20, 2025
Merged

Conversation

EgorBo
Copy link
Member

@EgorBo EgorBo commented Feb 18, 2025

A follow up to #112595

@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 Feb 18, 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 Feb 19, 2025

PTAL @jakobbotsch @dotnet/jit-contrib a small addition, mainly to handle

dst[i + 0] = src[i + 0];
dst[i + 1] = src[i + 1];
dst[i + 2] = src[i + 2];
dst[i + 3] = src[i + 3];

here we have 2 groups and if we cut the statements too precisely for e.g. dst array, the next pass won't be able to find 4 checks in the new block for src because one of them will be left out in a different block.

I do want eventually to handle this via 1 joint condition (and 1 joint fallback) - but that will require a bit of work to handle side effects properly

Diffs - no PerfScore/TP regressions

@EgorBo EgorBo marked this pull request as ready for review February 19, 2025 10:24
@Copilot Copilot bot review requested due to automatic review settings February 19, 2025 10:25

Choose a reason for hiding this comment

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

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

@EgorBo EgorBo requested a review from jakobbotsch February 20, 2025 09:24
Comment on lines 117 to 120
if ((arrObj != nullptr) && ((arrObj->gtFlags & GTF_ALL_EFFECT) == 0))
{
bndsChk->GetArrayLength()->gtFlags &= ~GTF_EXCEPT;
}
Copy link
Member

Choose a reason for hiding this comment

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

This isn't really correct. The only thing we know here is that the conservative normal VN is the same as the first bounds check's conservative normal VN, but the array length here could still be something like 0 * (1 / 0) + arr.Length (obviously a constructed example) where this code would get rid of the DivisionByZeroException.

Maybe something like

if (bndsChk->GetArrayLength()->OperIs(GT_ARR_LENGTH) &&
    firstBndsChk->GetArrayLength()->OperIs(GT_ARR_LENGTH) &&
    (bndsChk->GetArrayLength()->GetIndirOrArrMetaDataAddr()->gtVNPair.GetConservative() == firstBndsChk->GetArrayLength()->GetIndirOrArrMetaDataAddr()->gtVNPair.GetConservative())
{
  bndsChk->GetArrayLength()->gtFlags |= GTF_IND_NONFAULTING;
  gtUpdateStmtSideEffects(stmt);
}

would get the cases?

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, even previous code didn't catch anything, so let me just remove this part

Co-authored-by: Jakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
JITDUMP("Cloning bounds checks in " FMT_BB " from " FMT_STMT " to " FMT_STMT "\n", block->bbNum,
firstGroup->Bottom().stmt->GetID(), lastStmt->GetID());

block = optRangeCheckCloning_DoClone(this, block, firstGroup, lastStmt);
Copy link
Member

@jakobbotsch jakobbotsch Feb 20, 2025

Choose a reason for hiding this comment

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

Is block here guaranteed to be nonnull in the case where we cloned and it returned fastPathBb->Prev()?

Might be a bit clearer to have optRangeCheckCloning_DoClone return the next block to visit

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed

Comment on lines +627 to +631
BasicBlock* nextBbToVisit = optRangeCheckCloning_DoClone(this, block, firstGroup, lastStmt);
assert(nextBbToVisit != nullptr);
// optRangeCheckCloning_DoClone wants us to visit nextBbToVisit next
block = nextBbToVisit->Prev();
assert(block != nullptr);
Copy link
Member

Choose a reason for hiding this comment

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

Another way you could do this without requiring the asserts would be:

BasicBlock* next;
for (BasicBlock* block = fgFirstBB; block != nullptr; block = next)
{
  next = block->Next();
  ...
  next = optRangeCheckCloning_DoClone(...);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, makes sense, I was thinking about goto 😄 I'll change in a follow up to avoid spinning CI

@EgorBo EgorBo merged commit 03324cd into dotnet:main Feb 20, 2025
109 of 112 checks passed
@EgorBo EgorBo deleted the overlapped-groups branch February 20, 2025 14:47
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.

2 participants