Skip to content

Enable eliding some bounds checks in the jit #36263

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

Merged
merged 6 commits into from
Jun 3, 2020

Conversation

nathan-moore
Copy link
Contributor

@nathan-moore nathan-moore commented May 12, 2020

  • For loop conditionals like i < bnd +- k, fix up assertion prop to generate Bound Oper Bnd assertions instead of Const Loop Bnd assertions.

  • When checking the range of a tree, handle comma nodes.

  • Add logging for when the jit bails due to encountering a negative constant.

This removes bound checks from the first two cases in #31638.
I also see it enabling removing a couple of other bounds check types, like the ones here with the index casted to a byte:

private int FastGetHashCode(string myString)
{
int myHashCode = myString.Length;
if (myHashCode != 0)
{
myHashCode ^= AsciiToLower[(byte)myString[0]] << 24 ^ AsciiToLower[(byte)myString[myHashCode - 1]] << 16;
}
return myHashCode;

The assembly diff is available here.

The two method regressions seem to be caused by register allocation. One of them is here if you wish to peruse through it.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 12, 2020
@dnfclas
Copy link

dnfclas commented May 12, 2020

CLA assistant check
All CLA requirements met.

@sandreenko
Copy link
Contributor

PTAL @dotnet/jit-contrib

@sandreenko
Copy link
Contributor

sandreenko commented Jun 2, 2020

Overall it looks good, thank you @nathan-moore.
I like the diffs:

x64, arm64:
Crossgen CodeSize Diffs for System.Private.CoreLib.dll, framework assemblies for  default jit
Summary of Code Size diffs:
(Lower is better)
Total bytes of diff: -2860 (-0.01% of base)
Crossgen CodeSize Diffs for System.Private.CoreLib.dll, framework assemblies for  linuxnonjit.dll
Summary of Code Size diffs:
(Lower is better)
Total bytes of diff: -9376 (-0.01% of base)
Crossgen CodeSize Diffs for System.Private.CoreLib.dll, framework assemblies for  protononjit.dll
Summary of Code Size diffs:
(Lower is better)
Total bytes of diff: -8744 (-0.01% of base)

but there are a few regressions, that happens when we create a new function instead of a better old variant.
For example:

N004 (  5,  5) [000127] ------------              *  JTRUE     void  
N003 (  3,  3) [000124] J------N----              \--*  LT        int    $1c3
N001 (  1,  1) [000126] ------------                 +--*  LCL_VAR   int    V07 loc1         u:2 $1c1
N002 (  1,  1) [000153] ------------                 \--*  CNS_INT   int    0 $40

where LCL_VAR is a result of ADD:

N006 (  5,  5) [000012] -A-XG---R---              *  ASG       int    $1c2
N005 (  1,  1) [000011] D------N----              +--*  LCL_VAR   int    V07 loc1         d:2 $1c1
N004 (  5,  5) [000010] ---XG-------              \--*  ADD       int    $1c2
N002 (  3,  3) [000077] ---XG-------                 +--*  ARR_LENGTH int    $1c0
N001 (  1,  1) [000076] ------------                 |  \--*  LCL_VAR   ref    V13 tmp1         u:1 $83
N003 (  1,  1) [000009] ------------                 \--*  CNS_INT   int    -1 $46

your new condition catches it when without your changes we were creating Const_Loop_Bnd and
optimized it better.
How did you choose a place for else if (vnStore->IsVNCompareCheckedBoundArith(relopVN)), would it be better to move it down after

    // Cases where op1 holds the condition bound check and op2 is 0.
    // Loop condition like: "i < 100 == 0"
    // Assertion: "i < 100 == false"
    else if (hasTestAgainstZero && vnStore->IsVNConstantBound(op1VN))

?

I attached the regressed method logs.
base.txt
diff.txt

Full diffs:
branchRemoval.All.txt

@sandreenko
Copy link
Contributor

How did you choose a place for else if (vnStore->IsVNCompareCheckedBoundArith(relopVN)), would it be better to move it down after

@briansull how would you choose where to put that check?

@nathan-moore
Copy link
Contributor Author

@sandreenko

your new condition catches it when without your changes we were creating Const_Loop_Bnd and
optimized it better.

As far as I can tell by grepping around the code, Const_Loop_Bnd and Bound_Oper_Bnd are only consumed by rangecheck. In the example you linked, (and in the regressions from the framework), we now remove the range check in those cases. Something just goes awry after that. I compared the lir after lowering in the case you linked, and the only difference I saw was the removal of the range check. That leads me to think it's a register allocation oddity caused by removing the check, which would explain the new spilling, but I could be missing something as that's a bit odd. If you have ideas, I can look into them more.

How did you choose a place for else if (vnStore->IsVNCompareCheckedBoundArith(relopVN)), would it be better to move it down after

I tried moving it to where you suggested and didn't see a difference (I also don't expect it to make a difference). I can move it if you think that location is better; I only put it where it is currently due to symmetry.

@sandreenko
Copy link
Contributor

That leads me to think it's a register allocation oddity caused by removing the check, which would explain the new spilling, but I could be missing something as that's a bit odd. If you have ideas, I can look into them more.

You are right, I have another example when with your changes we don't remove null check on a call anymore, but on the second look we were reaching assertion limit there and that is why we did not create a constant assertion there (Microsoft.CodeAnalysis.VisualBasic.Binder:ReportOverloadResolutionFailureForASingleCandidate, Windows x64), so just a side-effect that should not be fixed.

Copy link
Contributor

@sandreenko sandreenko left a comment

Choose a reason for hiding this comment

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

LGTM

@sandreenko sandreenko merged commit 3a2c768 into dotnet:master Jun 3, 2020
@sandreenko
Copy link
Contributor

Thanks @nathan-moore!

@nathan-moore nathan-moore deleted the BranchRemoval branch June 4, 2020 00:10
@ghost ghost locked as resolved and limited conversation to collaborators Dec 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
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