Skip to content

JIT: Add a primitive to split statements at a specified tree - #83005

Merged
jakobbotsch merged 22 commits into
dotnet:mainfrom
jakobbotsch:stress-split-tree
Mar 11, 2023
Merged

JIT: Add a primitive to split statements at a specified tree#83005
jakobbotsch merged 22 commits into
dotnet:mainfrom
jakobbotsch:stress-split-tree

Conversation

@jakobbotsch

@jakobbotschjakobbotsch commented Mar 5, 2023

Copy link
Copy Markdown
Member

Add a gtSplitTree that can split a statement at an arbitrary tree: this creates new statements before the statement such that the original statement now executes the input tree as the very first non-invariant node.

This can be used for example to introduce control flow at an arbitrary point within a tree.

@ghostghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 5, 2023
@ghostghost assigned jakobbotschMar 5, 2023
@ghost

ghost commented Mar 5, 2023

Copy link
Copy Markdown

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

Issue Details

null

Author:jakobbotsch
Assignees:jakobbotsch
Labels:

area-CodeGen-coreclr

Milestone:-

@BruceForstall

Copy link
Copy Markdown
Contributor

It seems totally reasonable to add this as one of the JIT stress modes if it is incorporated into the JIT.

Could we use gtSplitTree to remove all GT_COMMA by hoisting the op1 to its own statement? There are probably lots of optimizations that are doing tree-based pattern matching including commas that would generate worse code (or fail) as a result, but maybe as a stress mode?

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

It seems totally reasonable to add this as one of the JIT stress modes if it is incorporated into the JIT.

Could we use gtSplitTree to remove all GT_COMMA by hoisting the op1 to its own statement? There are probably lots of optimizations that are doing tree-based pattern matching including commas that would generate worse code (or fail) as a result, but maybe as a stress mode?

Yes, I think I will end up PR'ing this primitive separately from #81635, and it seems like a good idea to have these stress modes. Indeed it can be used to remove all COMMA nodes, that would also be an interesting stress mode, I'll add it once this is in a more workable state.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run Fuzzlyn

@azure-pipelines

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

Also fix LIR links traversed initialization
Comment threadsrc/coreclr/jit/compiler.cpp
Comment threadsrc/coreclr/jit/compiler.cpp
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotschjakobbotsch changed the title Stress testing gtSplitTreeJIT: Add a primitive to split statements at a specified treeMar 10, 2023
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress

@azure-pipelines

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

@jakobbotsch

jakobbotsch commented Mar 11, 2023

Copy link
Copy Markdown
MemberAuthor

There are probably lots of optimizations that are doing tree-based pattern matching including commas that would generate worse code (or fail) as a result, but maybe as a stress mode?

In case you are curious, here are the diffs if we remove all commas before the optimization phases:
https://gist.github.com/jakobbotsch/e210230f6d154c7547ae0823ed32b230

The interference checking done by gtSplitTree in this PR is very rudimentary, we would need something closer to IsInvariantInRange in lowering if we actually wanted to try this for real (to avoid being conservative).

@BruceForstall

Copy link
Copy Markdown
Contributor

In case you are curious, here are the diffs

As expected... bad :-) If optimizations used SSA instead of tree-based pattern matching, maybe it wouldn't be so bad.

@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

Previous stress runs were clean except for #83298. I had to merge this to pick up #83224 that this was based on, but that shouldn't require a rerun of those pipelines.

cc @dotnet/jit-contrib PTAL @EgorBo

Comment on lines +5403 to +5413
if (gtSplitTree(block, stmt, tree, &newStmt, &use))
{
while ((newStmt != nullptr) && (newStmt != stmt))
{
fgMorphStmtBlockOps(block, newStmt);
newStmt = newStmt->GetNextStmt();
}

fgMorphStmtBlockOps(block, stmt);
gtUpdateStmtSideEffects(stmt);
}

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.

@EgorBo Your PR will need to do something similar like this, but note that calling fgMorphStmtBlockOps can invalidate the use, so it should be done only after you've replaced it with the new local.

bool answerOnBoundExceeded /*= true*/)
{
const __int64 maxLinks = 1000000000;
const __int64 maxLinks = 100000000;

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.

I thought this limit was a bit on the high side before.

@EgorBoEgorBo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks! I've been following changes in this PR so LGTM

@jakobbotsch
jakobbotsch merged commit 5265218 into dotnet:mainMar 11, 2023
@jakobbotsch
jakobbotsch deleted the stress-split-tree branch March 11, 2023 21:11
@ghostghost locked as resolved and limited conversation to collaborators Apr 11, 2023
@jakobbotsch

Copy link
Copy Markdown
MemberAuthor

As expected... bad :-) If optimizations used SSA instead of tree-based pattern matching, maybe it wouldn't be so bad.

I realized while working on #89560 that the comma removal is more conservative than necessary -- it introduces a local for the comma's op2, which is unnecessary.

With that fixed the diffs look like https://gist.github.com/jakobbotsch/dd2ea6d7b94d9dbf80283191d98e2dd0, so it goes from "very bad" to "still very bad, but only half as very bad".

@EgorBo

Copy link
Copy Markdown
Member

Wonder what happens in this small guy: System.Numerics.Vector2:get_Item(int):float:this (FullOpts)
image

@jakobbotsch

jakobbotsch commented Jul 27, 2023

Copy link
Copy Markdown
MemberAuthor

Wonder what happens in this small guy: System.Numerics.Vector2:get_Item(int):float:this (FullOpts)

Removal of commas changes

N009 ( 12, 14) [000008] ---XG------RETURN float $205N008 ( 11, 13) [000007] ---XG------└──▌HWINTRINSIC float float GetElement <l:$2c3, c:$2c2>
N002 ( 3, 2) [000001] ---XG------├──▌IND simd8 <l:$240, c:$241>
N001 ( 1, 1) [000000] -----------└──▌LCL_VAR byref V00this u:1 (last use) $80N007 ( 7, 10) [000006] ---X-------└──▌COMMA int $280N005 ( 6, 9) [000005] ---X-------├──▌BOUNDS_CHECK_ArgRng void $203N003 ( 1, 1) [000004] -----------├──▌LCL_VAR int V01 arg1 u:1 $c0
N004 ( 1, 1) [000003] -----------└──▌CNS_INT int 2 $44N006 ( 1, 1) [000002] -----------└──▌LCL_VAR int V01 arg1 u:1 (last use) $c0

into

------------BB01 [000..00D) (return), preds={} succs={}
*****BB01STMT00001 ( 0x000[E-] ... ??? )
N003 ( 7, 5) [000009] DA-XG------STORE_LCL_VAR simd8 V03 rat0 N002 ( 3, 2) [000001] ---XG------└──▌IND simd8 <l:$240, c:$241>
N001 ( 1, 1) [000000] -----------└──▌LCL_VAR byref V00this u:1 (last use) $80*****BB01STMT00002 ( ??? ... ??? )
N003 ( 6, 9) [000005] ---X-------BOUNDS_CHECK_ArgRng void $203N001 ( 1, 1) [000004] -----------├──▌LCL_VAR int V01 arg1 u:1 $c0
N002 ( 1, 1) [000003] -----------└──▌CNS_INT int 2 $44*****BB01STMT00000 ( 0x000[E-] ... 0x00C )
N004 ( 6, 5) [000008] ----G------RETURN float $205N003 ( 5, 4) [000007] ----G------└──▌HWINTRINSIC float float GetElement <l:$2c3, c:$2c2>
N001 ( 3, 2) [000010] -----------├──▌LCL_VAR simd8 V03 rat0 N002 ( 1, 1) [000002] -----------└──▌LCL_VAR int V01 arg1 u:1 (last use) $c0

It actually looks like LowerHWIntrinsicGetElement is doing something illegal here in the baseline. It ends up reordering [000001] and [000005], which reorders a ArgumentOutOfRangeException and NullReferenceException.
Although in this case presumably [000001] is non-faulting, even though it's not marked as such.

Edit: opened #89565 for this.

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.

3 participants

@jakobbotsch@BruceForstall@EgorBo