Skip to content

Conversation

@sandreenko
Copy link
Contributor

@sandreenko sandreenko commented Nov 21, 2019

There was an issue with range calculations in a rare loop form that was exposed by complus_JitStressBBProf=1 in https://github.com/dotnet/coreclr/issues/27805.

I have added a test that exposes the issue without any stress mode but it relies on the assertion prop optimization that I have added in #160. New test failures.

In the new test case, fgOptimizeBranch is blocked by different try regions and we can't copy loop condition as we usually do.
So we keep our original order:

while(i < 100)
{
    arr[i] = i;
    ++i;
}

Note: usually we tranform it into:

if (i < 100)
{
do
{
  arr[i] = i;
  i++;
}
while (i < 100);
}

so with the original order when we try to optimize bounds check for arr[i] we have two phi nodes, one is i0=(0, 0) that is the pre loop value and another is i1=(dependent, dependent) that is loop variable:

i0 = 0;
LOOP:
i1 = phi(i0, i2);
if (i1 < 100)
{
    
    arr[i1] = i1;
    i2 = i1 + 1;
    goto LOOP;
}

so i1 asks for a range of i1 and i2. When it asks for i2 it tries to use assertion propagation info, but there is no info about i2 there. So we end up with i0=(0, 0), i2=(dependent, dependent) and the old code was merging it into i1=(0,0) that allowed the compiler to incorrectly remove the bounds check.

In the case where we don't have different try regions and create a loop with postcondition assertion propagation has information about i2 and uses it to modify i2 range as (dependent, 100) so i1 = (0, 100).

complus_JitStressBBProf=1 was blocking that cloning and exposed the issue on many test cases in that file.

The fix is to use increasingMonotoning flag only to set the lower bound.

Note: We can add the same optimization for decreasing iterators later, but they are probably very rare.

Fixes https://github.com/dotnet/coreclr/issues/27805.

Commits:
1860741: add a new test case to osr015.

4239890: Improve JitDump output for range checks.

9ef0ca3: Rename monotonic to monIncreasing.

396198f: Fix the bug.

monIncreasing can be used only to liberally assume the lower bound.

@sandreenko sandreenko added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 21, 2019
@sandreenko sandreenko marked this pull request as ready for review November 22, 2019 01:56
@sandreenko
Copy link
Contributor Author

PTAL @dotnet/jit-contrib

Sergey Andreenko added 2 commits November 21, 2019 18:33
`monIncreasing` can be used only to liberally assume the lower bound.
//
// **Step 5. If monotonic is true, then perform a widening step, where we assume, the
// SSA variables that are "dependent" get their values from the definitions in the
// **Step 5. If monotonic increasing is true, then perform a widening step, where we assume, the
Copy link
Member

Choose a reason for hiding this comment

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

Nit from pre-existing comment: I think this really should be called a "narrowing step" as (dep,dep) abstractly describes a wider set of values than (0,dep).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In classic compiler books that step is called "widening" (or widening operator) because it also sets the upper limit to +INF.
I do not see any immediate benefits if we start replacing (dep) with (inf) right now. However, I think it is better to keep the preexisting name so people can find the articles that the algorithm was based on.

Copy link
Member

Choose a reason for hiding this comment

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

so people can find the articles that the algorithm was based on.

Perhaps we could mention those articles in a comment? I am curious to learn if range check is actually based on any sort of analysis formalism.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is hard for me to find the first article that describes that part of the interval analysis. A good example that is available in preview is in "Compiler Design: Analysis and Transformation, Helmut Seidl, Reinhard Wilhelm, Sebastian Hack" . There are earlier articles that have more mathematical formalism but they are far from our implementation.

Sergey Andreenko added 2 commits November 22, 2019 10:37
I have used a wrong exception type when copied the test.
I have checked that it fails without the fix on x86 and passes with it.
@sandreenko
Copy link
Contributor Author

@erozenfeld @AndyAyersMS could you please take another look?

I would like to merge it, so I could delete the fork that it uses and start to publish new PRs.

Copy link
Member

@erozenfeld erozenfeld 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 3571bdb into dotnet:master Nov 27, 2019
@sandreenko sandreenko deleted the fixRangeCheck branch November 27, 2019 10:03
@karelz karelz added this to the 5.0.0 milestone Aug 18, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 11, 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