Skip to content

JIT: fix incorrect scale in genCreateAddrMode + no-opt - #75433

Merged
EgorBo merged 11 commits into
dotnet:mainfrom
EgorBo:fix-addr-mode-debug
Sep 13, 2022
Merged

JIT: fix incorrect scale in genCreateAddrMode + no-opt#75433
EgorBo merged 11 commits into
dotnet:mainfrom
EgorBo:fix-addr-mode-debug

Conversation

@EgorBo

@EgorBoEgorBo commented Sep 12, 2022

Copy link
Copy Markdown
Member

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

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Sep 12, 2022
@ghostghost assigned EgorBoSep 12, 2022
@ghost

Copy link
Copy Markdown

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
Copy Markdown
MemberAuthor

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

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 5 pipeline(s).

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

Copy link
Copy Markdown
Member

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

@kunalspathak

Copy link
Copy Markdown
Contributor

/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
Copy Markdown
Member

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

@AndyAyersMS

Copy link
Copy Markdown
Member

Jit stress failures look like known issues:

@AndyAyersMS

Copy link
Copy Markdown
Member

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

@kunalspathak

Copy link
Copy Markdown
Contributor

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
Copy Markdown
MemberAuthor

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

EgorBo commented Sep 12, 2022

Copy link
Copy Markdown
MemberAuthor

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

It's not C++ specific, it's just that x * 0rarely 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
Copy Markdown
Contributor

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

Make sense.

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Comment threadsrc/coreclr/jit/codegencommon.cpp Outdated

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

Copy link
Copy Markdown
Contributor

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?

@EgorBoEgorBoSep 12, 2022

Copy link
Copy Markdown
MemberAuthor

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).

@EgorBoEgorBoSep 12, 2022

Copy link
Copy Markdown
MemberAuthor

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
Copy Markdown
MemberAuthor

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
Copy Markdown
Contributor

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
Copy Markdown
MemberAuthor

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
Copy Markdown
MemberAuthor

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
Copy Markdown
MemberAuthor

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

@kunalspathakkunalspathak left a comment

Copy link
Copy Markdown
Contributor

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
Copy Markdown
MemberAuthor

Yeah, the diff is empty but there is a conflict

@EgorBo

Copy link
Copy Markdown
MemberAuthor

/backport to release/7.0

@github-actions

Copy link
Copy Markdown
Contributor

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

@EgorBo

Copy link
Copy Markdown
MemberAuthor

@kunalspathak could you also approve the backport - #75560

@EgorBo
EgorBo merged commit 53815bd into dotnet:mainSep 13, 2022
@ghostghost locked as resolved and limited conversation to collaborators Oct 14, 2022
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR 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

@EgorBo@JulieLeeMSFT@kunalspathak@AndyAyersMS