-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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: Add a primitive to split statements at a specified tree #83005
Conversation
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch, @kunalspathak Issue Detailsnull
|
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. |
/azp run Fuzzlyn |
Azure Pipelines successfully started running 1 pipeline(s). |
Also fix LIR links traversed initialization
/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress |
Azure Pipelines successfully started running 2 pipeline(s). |
/azp run runtime-coreclr jitstress, runtime-coreclr libraries-jitstress |
Azure Pipelines successfully started running 2 pipeline(s). |
In case you are curious, here are the diffs if we remove all commas before the optimization phases: The interference checking done by |
As expected... bad :-) If optimizations used SSA instead of tree-based pattern matching, maybe it wouldn't be so bad. |
if (gtSplitTree(block, stmt, tree, &newStmt, &use)) | ||
{ | ||
while ((newStmt != nullptr) && (newStmt != stmt)) | ||
{ | ||
fgMorphStmtBlockOps(block, newStmt); | ||
newStmt = newStmt->GetNextStmt(); | ||
} | ||
|
||
fgMorphStmtBlockOps(block, stmt); | ||
gtUpdateStmtSideEffects(stmt); | ||
} |
There was a problem hiding this comment.
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.
@@ -18,7 +18,7 @@ bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, | |||
Statement* stmt, | |||
bool answerOnBoundExceeded /*= true*/) | |||
{ | |||
const __int64 maxLinks = 1000000000; | |||
const __int64 maxLinks = 100000000; |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
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". |
Removal of commas changes N009 ( 12, 14) [000008] ---XG------ ▌ RETURN float $205
N008 ( 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 V00 this u:1 (last use) $80
N007 ( 7, 10) [000006] ---X------- └──▌ COMMA int $280
N005 ( 6, 9) [000005] ---X------- ├──▌ BOUNDS_CHECK_ArgRng void $203
N003 ( 1, 1) [000004] ----------- │ ├──▌ LCL_VAR int V01 arg1 u:1 $c0
N004 ( 1, 1) [000003] ----------- │ └──▌ CNS_INT int 2 $44
N006 ( 1, 1) [000002] ----------- └──▌ LCL_VAR int V01 arg1 u:1 (last use) $c0 into ------------ BB01 [000..00D) (return), preds={} succs={}
***** BB01
STMT00001 ( 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 V00 this u:1 (last use) $80
***** BB01
STMT00002 ( ??? ... ??? )
N003 ( 6, 9) [000005] ---X------- ▌ BOUNDS_CHECK_ArgRng void $203
N001 ( 1, 1) [000004] ----------- ├──▌ LCL_VAR int V01 arg1 u:1 $c0
N002 ( 1, 1) [000003] ----------- └──▌ CNS_INT int 2 $44
***** BB01
STMT00000 ( 0x000[E-] ... 0x00C )
N004 ( 6, 5) [000008] ----G------ ▌ RETURN float $205
N003 ( 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 Edit: opened #89565 for this. |
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.