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: fix incorrect scale in genCreateAddrMode + no-opt #75433

Merged
merged 11 commits into from
Sep 13, 2022

Conversation

EgorBo
Copy link
Member

@EgorBo EgorBo commented Sep 12, 2022

Fixes #75312

The problem is basically an incorrect behavior of genCreateAddrMode for the following tree:

N009 ( 11,  9) [000008] -------N---                         *  ADD       int
N007 ( 10,  8) [000006] -------N---                         +--*  ADD       int
N001 (  3,  2) [000000] -c---------                         |  +--*  LCL_VAR   int    V00 arg0
N006 (  7,  6) [000005] -------N---                         |  \--*  LSH       int
N004 (  6,  5) [000003] -----------                         |     +--*  MUL       int
N002 (  1,  1) [000001] -----------                         |     |  +--*  CNS_INT   int    3
N003 (  1,  1) [000002] -c---------                         |     |  \--*  CNS_INT   int    0
N005 (  1,  1) [000004] -c---------                         |     \--*  CNS_INT   int    2
N008 (  1,  1) [000007] -c---------                         \--*  CNS_INT   int    1

for which, genCreateAddrMode returns:

base = arg0
idx = nullptr
scale = 0
offset = 4

while offset should be 1

@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 Sep 12, 2022
@ghost ghost assigned EgorBo Sep 12, 2022
@ghost
Copy link

ghost commented Sep 12, 2022

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

Issue Details

Fixes #75312

The problem is basically in a tree:

N009 ( 11,  9) [000008] -------N---                         *  ADD       int
N007 ( 10,  8) [000006] -------N---                         +--*  ADD       int
N001 (  3,  2) [000000] -c---------                         |  +--*  LCL_VAR   int    V00 arg0
N006 (  7,  6) [000005] -------N---                         |  \--*  LSH       int
N004 (  6,  5) [000003] -----------                         |     +--*  MUL       int
N002 (  1,  1) [000001] -----------                         |     |  +--*  CNS_INT   int    3
N003 (  1,  1) [000002] -c---------                         |     |  \--*  CNS_INT   int    0
N005 (  1,  1) [000004] -c---------                         |     \--*  CNS_INT   int    2
N008 (  1,  1) [000007] -c---------                         \--*  CNS_INT   int    1

that is an address for IND, for which, genCreateAddrMode returns:

base = arg0
idx = nullptr
scale = 0
offset = 4

while offset should be 1

Author: EgorBo
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

@EgorBo
Copy link
Member Author

EgorBo commented Sep 12, 2022

/azp run runtime-coreclr outerloop, runtime-coreclr jitstress, runtime-coreclr jitstressregs, runtime-coreclr gcstress0x3-gcstress0xc, Fuzzlyn

@azure-pipelines
Copy link

Azure Pipelines successfully started running 5 pipeline(s).

@EgorBo EgorBo marked this pull request as ready for review September 12, 2022 12:55
@JulieLeeMSFT JulieLeeMSFT added this to the 7.0.0 milestone Sep 12, 2022
@JulieLeeMSFT
Copy link
Member

@kunalspathak Please prioritize to review this PR before RC2 snap.
cc @dotnet/jit-contrib.

@kunalspathak
Copy link
Member

/azp run runtime-coreclr outerloop, runtime-coreclr jitstress, runtime-coreclr jitstressregs, runtime-coreclr gcstress0x3-gcstress0xc, Fuzzlyn

Have you analyzed any of these failures and are there anything related?

@JulieLeeMSFT
Copy link
Member

cc @jeffschwMSFT. Once we complete this PR, we will backport this to 7.0 and 6.0.

@AndyAyersMS
Copy link
Member

Jit stress failures look like known issues:

@AndyAyersMS
Copy link
Member

So the bug was an uninitialized local? How could we have not caught this before now?

@kunalspathak
Copy link
Member

So the bug was an uninitialized local? How could we have not caught this before now?

That's exactly I was wondering. Why it needed complex C++ / CLI only to reproduce?

@EgorBo
Copy link
Member Author

EgorBo commented Sep 12, 2022

So the bug was an uninitialized local? How could we have not caught this before now?

Ah, no, that change is unrelated, let me remove the redundant initialization actually,
the problem is in zero scale, it's not respected.

@EgorBo
Copy link
Member Author

EgorBo commented Sep 12, 2022

Why it needed complex C++ / CLI only to reproduce?

It's not C++ specific, it's just that x * 0 rarely makes it to genAddrMode phase - when optimizations are enabled it's folded long before it reaches the phase. In debug mode it's hard to get it anyhow since e.g. Roslyn folds x * 0 to 0 even in Debug mode with <Optimize>false</Optimize> - that's why I wrote the test in IL.

This bug is a good example on why we need unit tests for jit phases

@kunalspathak
Copy link
Member

the problem is in zero scale, it's not respected.

Make sense.

Copy link
Member

@kunalspathak kunalspathak left a comment

Choose a reason for hiding this comment

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

LGTM

{
/* Get hold of the index value */
ssize_t ixv = index->AsIntConCommon()->IconValue();

/* Scale the index if necessary */
ixv *= tmpMul;
if (tmpMul)
Copy link
Member

Choose a reason for hiding this comment

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

So its ok to have tmpMul == 0 here from the else on line 1417 and not scale?

Copy link
Member Author

@EgorBo EgorBo Sep 12, 2022

Choose a reason for hiding this comment

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

Looks like it can be but only if we also disable jit optimizations and write IL for array[1 + 2] because Roslyn will fold cns + cns too again (even in Debug mode).

Copy link
Member Author

@EgorBo EgorBo Sep 12, 2022

Choose a reason for hiding this comment

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

Actually, let me run a few more tests, probably some parts of this logic can be just removed

Copy link
Member Author

Choose a reason for hiding this comment

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

@kunalspathak so I've slightly changed the logic - the whole block can be removed in theory but it produced several Tier0 regressions so I decided to keep it + special handled zero index or zero scale, so if optGetArrayRefScaleAndIndex returns either 0 or non-zero but index represents 0 then we drop the whole index part.

Copy link
Member

Choose a reason for hiding this comment

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

What happens for !(rv2->OperIs(GT_MUL, GT_LSH) && (rv2->gtGetOp2()->IsCnsIntOrI())) where we set index = rv2?

else
{
    /* May be a simple array. rv2 will points to the actual index */

    index  = rv2;
    tmpMul = mul;
}

Copy link
Member Author

Choose a reason for hiding this comment

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

@kunalspathak good point, it explains a single regression in the jit-diffs, but overall the code as is correct, it's just that the block you highlighted handles constant index that is converted to constant offset (this path is never hit in optimized code from what I see)

Copy link
Member Author

Choose a reason for hiding this comment

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

Let me push a quick change

Copy link
Member Author

Choose a reason for hiding this comment

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

@kunalspathak should be correct now and zero diff

Copy link
Member

@kunalspathak kunalspathak 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 double check if there are zero diffs for all archs before merging.

@EgorBo
Copy link
Member Author

EgorBo commented Sep 13, 2022

Yeah, the diff is empty but there is a conflict

@EgorBo
Copy link
Member Author

EgorBo commented Sep 13, 2022

/backport to release/7.0

@github-actions
Copy link
Contributor

Started backporting to release/7.0: https://github.com/dotnet/runtime/actions/runs/3048213131

@EgorBo
Copy link
Member Author

EgorBo commented Sep 13, 2022

@kunalspathak could you also approve the backport - #75560

@EgorBo EgorBo merged commit 53815bd into dotnet:main Sep 13, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Oct 14, 2022
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.

Calling GetControllingUnknown () generates an assert
4 participants