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: Stop sinking stores below commas in impStoreStruct #91586

Open
jakobbotsch opened this issue Sep 5, 2023 · 2 comments
Open

JIT: Stop sinking stores below commas in impStoreStruct #91586

jakobbotsch opened this issue Sep 5, 2023 · 2 comments
Assignees
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone

Comments

@jakobbotsch
Copy link
Member

jakobbotsch commented Sep 5, 2023

The following logic in the importer creates unnaturally/incorrectly typed COMMA nodes:

else if (src->OperIs(GT_COMMA))
{
if (pAfterStmt)
{
// Insert op1 after '*pAfterStmt'
Statement* newStmt = gtNewStmt(src->AsOp()->gtOp1, usedDI);
fgInsertStmtAfter(block, *pAfterStmt, newStmt);
*pAfterStmt = newStmt;
}
else if (impLastStmt != nullptr)
{
// Do the side-effect as a separate statement.
impAppendTree(src->AsOp()->gtOp1, curLevel, usedDI);
}
else
{
// In this case we have neither been given a statement to insert after, nor are we
// in the importer where we can append the side effect.
// Instead, we're going to sink the store below the COMMA.
store->Data() = src->AsOp()->gtOp2;
src->AsOp()->gtOp2 = impStoreStruct(store, curLevel, pAfterStmt, usedDI, block);
src->SetAllEffectsFlags(src->AsOp()->gtOp1, src->AsOp()->gtOp2);
gtUpdateNodeSideEffects(store);
return src;
}
// Evaluate the second thing using recursion.
store->Data() = src->AsOp()->gtOp2;
gtUpdateNodeSideEffects(store);
return impStoreStruct(store, curLevel, pAfterStmt, usedDI, block);
}

It changes for instance

               [000006] --CXG------                           COMMA     simd12
               [000005] H-CXG------                         ├──▌  CALL help int    CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
               [000003] ----------- arg0                      ├──▌  CNS_INT   int    0x8A2B390
               [000004] ----------- arg1                      └──▌  CNS_INT   int    1
               [000001] I---G------                         └──▌  IND       simd12
               [000000] H----------                            └──▌  CNS_INT(h) int    0x8601620 static Fseq[s]

to

               [000006] -ACXG------                           COMMA     simd12
               [000005] H-CXG------                         ├──▌  CALL help int    CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
               [000003] ----------- arg0                      ├──▌  CNS_INT   int    0x8A2B390
               [000004] ----------- arg1                      └──▌  CNS_INT   int    1
               [000087] DA--G------                         └──▌  STORE_LCL_VAR simd12<System.Numerics.Vector3> V02 tmp1         
               [000001] I---G------                            └──▌  IND       simd12
               [000000] H----------                               └──▌  CNS_INT(h) int    0x8601620 static Fseq[s]

We would usually expect [000006] to be TYP_VOID in the latter tree, as evidenced by gtExtractSideEffList. Morph also has code to compensate:

/* Special case: trees that don't produce a value */
if (op2->OperIsStore() || (op2->OperGet() == GT_COMMA && op2->TypeGet() == TYP_VOID) || fgIsThrow(op2))
{
typ = tree->gtType = TYP_VOID;
}

We should fix this; we can likely just avoid sinking these stores below the COMMAs -- this used to be necessary because block morphing did not handle the pattern, but it should be handled after #83590.

#91443 has an example bug because of this JIT IR oddity.

@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 5, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Sep 5, 2023
@jakobbotsch jakobbotsch added this to the 9.0.0 milestone Sep 5, 2023
@ghost
Copy link

ghost commented Sep 5, 2023

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

Issue Details

The following logic in the importer creates unnaturally/incorrectly typed COMMA nodes:

else if (src->OperIs(GT_COMMA))
{
if (pAfterStmt)
{
// Insert op1 after '*pAfterStmt'
Statement* newStmt = gtNewStmt(src->AsOp()->gtOp1, usedDI);
fgInsertStmtAfter(block, *pAfterStmt, newStmt);
*pAfterStmt = newStmt;
}
else if (impLastStmt != nullptr)
{
// Do the side-effect as a separate statement.
impAppendTree(src->AsOp()->gtOp1, curLevel, usedDI);
}
else
{
// In this case we have neither been given a statement to insert after, nor are we
// in the importer where we can append the side effect.
// Instead, we're going to sink the store below the COMMA.
store->Data() = src->AsOp()->gtOp2;
src->AsOp()->gtOp2 = impStoreStruct(store, curLevel, pAfterStmt, usedDI, block);
src->SetAllEffectsFlags(src->AsOp()->gtOp1, src->AsOp()->gtOp2);
gtUpdateNodeSideEffects(store);
return src;
}
// Evaluate the second thing using recursion.
store->Data() = src->AsOp()->gtOp2;
gtUpdateNodeSideEffects(store);
return impStoreStruct(store, curLevel, pAfterStmt, usedDI, block);
}

It changes for instance

               [000006] --CXG------                           COMMA     simd12
               [000005] H-CXG------                         ├──▌  CALL help int    CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
               [000003] ----------- arg0                      ├──▌  CNS_INT   int    0x8A2B390
               [000004] ----------- arg1                      └──▌  CNS_INT   int    1
               [000001] I---G------                         └──▌  IND       simd12
               [000000] H----------                            └──▌  CNS_INT(h) int    0x8601620 static Fseq[s]

to

               [000006] -ACXG------                           COMMA     simd12
               [000005] H-CXG------                         ├──▌  CALL help int    CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
               [000003] ----------- arg0                      ├──▌  CNS_INT   int    0x8A2B390
               [000004] ----------- arg1                      └──▌  CNS_INT   int    1
               [000087] DA--G------                         └──▌  STORE_LCL_VAR simd12<System.Numerics.Vector3> V02 tmp1         
               [000001] I---G------                            └──▌  IND       simd12
               [000000] H----------                               └──▌  CNS_INT(h) int    0x8601620 static Fseq[s]

We would usually expect [000006] to be TYP_VOID in the latter tree, as evidenced by gtExtractSideEffList. Morph also has code to compensate:

/* Special case: trees that don't produce a value */
if (op2->OperIsStore() || (op2->OperGet() == GT_COMMA && op2->TypeGet() == TYP_VOID) || fgIsThrow(op2))
{
typ = tree->gtType = TYP_VOID;
}

We should fix this; we can likely just avoid sinking these stores below the COMMAs anymore -- this used to be necessary because block morphing did not handle the pattern, but it should be handled after #83590.

Author: jakobbotsch
Assignees: -
Labels:

area-CodeGen-coreclr, untriaged

Milestone: -

@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Sep 5, 2023
jakobbotsch added a commit to jakobbotsch/runtime that referenced this issue Sep 5, 2023
Morph has post-order logic to compensate for mistyped commas produced by
impStoreStruct. However, block morphing can optimize unused stores into
INDs; this interacts with the mistyped commas to produce illegal IR
shapes (e.g. `COMMA<simd12>(..., IND<ubyte>(...))`).

The ideal solution is to fix impStoreStruct (dotnet#91586 tracks this), but
this change has a more surgical fix for the problem that can be
backported to .NET 8.

Fix dotnet#91443
@jakobbotsch jakobbotsch self-assigned this Sep 5, 2023
jakobbotsch added a commit that referenced this issue Sep 7, 2023
Morph has post-order logic to compensate for mistyped commas produced by
impStoreStruct. However, block morphing can optimize unused stores into
INDs; this interacts with the mistyped commas to produce illegal IR
shapes (e.g. `COMMA<simd12>(..., IND<ubyte>(...))`).

The ideal solution is to fix impStoreStruct (#91586 tracks this), but
this change has a more surgical fix for the problem that can be
backported to .NET 8.

Fix #91443
github-actions bot pushed a commit that referenced this issue Sep 7, 2023
Morph has post-order logic to compensate for mistyped commas produced by
impStoreStruct. However, block morphing can optimize unused stores into
INDs; this interacts with the mistyped commas to produce illegal IR
shapes (e.g. `COMMA<simd12>(..., IND<ubyte>(...))`).

The ideal solution is to fix impStoreStruct (#91586 tracks this), but
this change has a more surgical fix for the problem that can be
backported to .NET 8.

Fix #91443
jeffschwMSFT added a commit that referenced this issue Sep 11, 2023
…91718)

* JIT: Compensate for mistyped commas in morph pre-order too

Morph has post-order logic to compensate for mistyped commas produced by
impStoreStruct. However, block morphing can optimize unused stores into
INDs; this interacts with the mistyped commas to produce illegal IR
shapes (e.g. `COMMA<simd12>(..., IND<ubyte>(...))`).

The ideal solution is to fix impStoreStruct (#91586 tracks this), but
this change has a more surgical fix for the problem that can be
backported to .NET 8.

Fix #91443

* Fix build

---------

Co-authored-by: Jakob Botsch Nielsen <jakob.botsch.nielsen@gmail.com>
Co-authored-by: Jeff Schwartz <jeffschw@microsoft.com>
@jakobbotsch jakobbotsch modified the milestones: 9.0.0, 10.0.0 Jul 29, 2024
@jakobbotsch
Copy link
Member Author

#106380 is another example of a bug due to this issue.

We should fix this; we can likely just avoid sinking these stores below the COMMAs -- this used to be necessary because block morphing did not handle the pattern, but it should be handled after #83590.

Another thing is that, since LIR does not support TYP_STRUCT edges beyond some very restricted patterns, we should ensure that the handling for these struct operations properly handle interfering side effects.

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

No branches or pull requests

1 participant