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

Use rangecheck in assertprop #112766

Merged
merged 5 commits into from
Feb 22, 2025
Merged

Conversation

EgorBo
Copy link
Member

@EgorBo EgorBo commented Feb 20, 2025

Contributes to #112765 (the sign-extension cast).

The PR borrows @jakobbotsch's idea to re-use rangecheck outside of its phase (#110352)

@EgorBo
Copy link
Member Author

EgorBo commented Feb 21, 2025

PTAL @jakobbotsch @AndyAyersMS @dotnet/jit-contrib Diffs

Had to fix a bug inside MergeEdgeAssertions around unsigned comparisons

@EgorBo EgorBo marked this pull request as ready for review February 21, 2025 21:49
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.

Changes LGTM.

Up at the top of the method seems like we could hoist the // First, check simple properties without assertions code up above the initial set of bail-out checks?

Comment on lines 4146 to 4147
rng.LowerLimit().AddConstant(cns);
rng.UpperLimit().AddConstant(cns);
Copy link
Member

Choose a reason for hiding this comment

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

Return value needs to be checked?

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, didn't realize AddConstant doesn't do anything if cns limit overflows. Added!

Comment on lines +4153 to +4156
if ((rng.LowerLimit().GetConstant() == 0))
{
*isKnownNonNegative = true;
}
Copy link
Member

Choose a reason for hiding this comment

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

Does this check not need to account for overflow?

Copy link
Member Author

Choose a reason for hiding this comment

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

but how can X - CNS + CNS overflow?

Copy link
Member Author

Choose a reason for hiding this comment

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

(AddConstant checks for overflow before it)

Copy link
Member

Choose a reason for hiding this comment

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

I was worried that for a range like "[8..unknown]", that "unknown" could mean "some computation that overflowed" and hence that the lower limit was actually smaller than 8. But it's probably ok since the range here comes from assertions only.

Comment on lines +4168 to +4184
else
{
Range rng = Range(Limit(Limit::keDependent));
RangeCheck::MergeEdgeAssertions(this, treeVN, ValueNumStore::NoVN, assertions, &rng, false);
Limit lowerBound = rng.LowerLimit();
if (lowerBound.IsConstant())
{
if (lowerBound.GetConstant() >= 0)
{
*isKnownNonNegative = true;
}
if (lowerBound.GetConstant() > 0)
{
*isKnownNonZero = true;
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Does this part catch cases? Naively I would expect assertion prop to know to check for the "straightforward" assertions that range check is checking here already.

Copy link
Member Author

@EgorBo EgorBo Feb 22, 2025

Choose a reason for hiding this comment

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

Yep, good chunk of diffs are caught by this

Copy link
Member

@jakobbotsch jakobbotsch Feb 22, 2025

Choose a reason for hiding this comment

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

I wonder if we could get rid of some of the checks above then, I would expect there to be a good amount of duplication between range check's assertion handling and that assertion handling above.

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 agree, I'll check what is missing in the above

*isKnownNonZero = true;
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

IIRC, you had a version where you tried to use range check directly on the IR node. It seems like it would catch more cases, because the logic here for additions should already be conceptually the same logic that range check has to handle additions.

Copy link
Member Author

Choose a reason for hiding this comment

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

That version had terrible TP impact and needed more touches (perhaps, its cache can be shared with rangecheck?), I might investigate it again in the future

Copy link
Member Author

@EgorBo EgorBo Feb 22, 2025

Choose a reason for hiding this comment

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

Actually, I'll do it after this PR - diffs look nice (if TP regressions are mitigated)

Comment on lines +4148 to +4152
if ((rng.LowerLimit().IsConstant() && !rng.LowerLimit().AddConstant(cns)) ||
(rng.UpperLimit().IsConstant() && !rng.UpperLimit().AddConstant(cns)))
{
// Add cns to both bounds if they are constants. Make sure the addition doesn't overflow.
return;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if ((rng.LowerLimit().IsConstant() && !rng.LowerLimit().AddConstant(cns)) ||
(rng.UpperLimit().IsConstant() && !rng.UpperLimit().AddConstant(cns)))
{
// Add cns to both bounds if they are constants. Make sure the addition doesn't overflow.
return;
if (!rng.LowerLimit().AddConstant(cns) || !rng.UpperLimit().AddConstant(cns))
{
// Add cns to both bounds. Make sure the addition doesn't overflow.
return;

Should be ok since there's the check for IsConstant below already?

Copy link
Member Author

Choose a reason for hiding this comment

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

Nope. This is too conservative - we're fine with some bounds to be Dependent (non-constant) when we e.g. only check Lower one. AddConstant returns false for them making the improvement super conservative

Copy link
Member

@jakobbotsch jakobbotsch left a comment

Choose a reason for hiding this comment

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

LGTM. Would be nice to find some way to unify what assertion prop and range check are trying to do since they are starting to converge to trying to do the same thing it seems.

@EgorBo EgorBo merged commit 6022adf into dotnet:main Feb 22, 2025
109 of 112 checks passed
@EgorBo EgorBo deleted the use-rangecheck-assertprop branch February 22, 2025 17:52
AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this pull request Feb 24, 2025
AndyAyersMS added a commit that referenced this pull request Feb 24, 2025
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.

4 participants