-
Notifications
You must be signed in to change notification settings - Fork 5.2k
JIT: Add a primitive to split statements at a specified tree #83005
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
Changes from all commits
3ddd7c3
6290989
1a36677
2615537
b5038ba
5a9aa91
776b403
1166061
0c70dcb
2a8644f
7e6575e
57e875c
7940227
c1dcff1
c8402e5
07cb53a
ba9d351
7a7a683
f052a51
dc6e220
ca9de34
ef4943b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1776,6 +1776,7 @@ void Compiler::compInit(ArenaAllocator* pAlloc, | |
| // set this early so we can use it without relying on random memory values | ||
| verbose = compIsForInlining() ? impInlineInfo->InlinerCompiler->verbose : false; | ||
|
|
||
| compNumStatementLinksTraversed = 0; | ||
| compPoisoningAnyImplicitByrefs = false; | ||
| #endif | ||
|
|
||
|
|
@@ -4995,6 +4996,10 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl | |
| fgDomsComputed = false; | ||
| optLoopTableValid = false; | ||
|
|
||
| #ifdef DEBUG | ||
| DoPhase(this, PHASE_STRESS_SPLIT_TREE, &Compiler::StressSplitTree); | ||
| #endif | ||
|
|
||
| // Insert GC Polls | ||
| DoPhase(this, PHASE_INSERT_GC_POLLS, &Compiler::fgInsertGCPolls); | ||
|
|
||
|
|
@@ -5336,6 +5341,163 @@ PhaseStatus Compiler::placeLoopAlignInstructions() | |
| } | ||
| #endif | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // StressSplitTree: A phase that stresses the gtSplitTree function. | ||
| // | ||
| // Returns: | ||
| // Suitable phase status | ||
| // | ||
| // Notes: | ||
| // Stress is applied on a function-by-function basis | ||
| // | ||
| PhaseStatus Compiler::StressSplitTree() | ||
| { | ||
| if (compStressCompile(STRESS_SPLIT_TREES_RANDOMLY, 10)) | ||
| { | ||
| SplitTreesRandomly(); | ||
| return PhaseStatus::MODIFIED_EVERYTHING; | ||
| } | ||
|
|
||
| if (compStressCompile(STRESS_SPLIT_TREES_REMOVE_COMMAS, 10)) | ||
| { | ||
| SplitTreesRemoveCommas(); | ||
| return PhaseStatus::MODIFIED_EVERYTHING; | ||
| } | ||
|
|
||
| return PhaseStatus::MODIFIED_NOTHING; | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // SplitTreesRandomly: Split all statements at a random location. | ||
| // | ||
| void Compiler::SplitTreesRandomly() | ||
| { | ||
| #ifdef DEBUG | ||
| CLRRandom rng; | ||
| rng.Init(info.compMethodHash() ^ 0x077cc4d4); | ||
|
|
||
| for (BasicBlock* block : Blocks()) | ||
| { | ||
| for (Statement* stmt : block->NonPhiStatements()) | ||
| { | ||
| int numTrees = 0; | ||
| for (GenTree* tree : stmt->TreeList()) | ||
| { | ||
| if (tree->OperIs(GT_JTRUE)) // Due to relop invariant | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| numTrees++; | ||
| } | ||
|
|
||
| int splitTree = rng.Next(numTrees); | ||
| for (GenTree* tree : stmt->TreeList()) | ||
| { | ||
| if (tree->OperIs(GT_JTRUE)) | ||
| continue; | ||
|
|
||
| if (splitTree == 0) | ||
| { | ||
| JITDUMP("Splitting " FMT_STMT " at [%06u]\n", stmt->GetID(), dspTreeID(tree)); | ||
| Statement* newStmt; | ||
| GenTree** use; | ||
| if (gtSplitTree(block, stmt, tree, &newStmt, &use)) | ||
| { | ||
| while ((newStmt != nullptr) && (newStmt != stmt)) | ||
| { | ||
| fgMorphStmtBlockOps(block, newStmt); | ||
| newStmt = newStmt->GetNextStmt(); | ||
| } | ||
|
|
||
| fgMorphStmtBlockOps(block, stmt); | ||
| gtUpdateStmtSideEffects(stmt); | ||
| } | ||
|
Comment on lines
+5405
to
+5415
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
|
|
||
| break; | ||
| } | ||
|
|
||
| splitTree--; | ||
| } | ||
| } | ||
| } | ||
jakobbotsch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| #endif | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // SplitTreesRemoveCommas: Split trees to remove all commas. | ||
| // | ||
| void Compiler::SplitTreesRemoveCommas() | ||
| { | ||
| for (BasicBlock* block : Blocks()) | ||
| { | ||
| Statement* stmt = block->FirstNonPhiDef(); | ||
| while (stmt != nullptr) | ||
| { | ||
| Statement* nextStmt = stmt->GetNextStmt(); | ||
| for (GenTree* tree : stmt->TreeList()) | ||
| { | ||
| if (!tree->OperIs(GT_COMMA)) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| // Supporting this weird construct would require additional | ||
| // handling, we need to sort of move the comma into to the | ||
| // next node in execution order. We don't see this so just | ||
| // skip it. | ||
| assert(!tree->IsReverseOp()); | ||
|
|
||
| JITDUMP("Removing COMMA [%06u]\n", dspTreeID(tree)); | ||
| Statement* newStmt; | ||
| GenTree** use; | ||
| gtSplitTree(block, stmt, tree, &newStmt, &use); | ||
| GenTree* op1SideEffects = nullptr; | ||
| gtExtractSideEffList(tree->gtGetOp1(), &op1SideEffects); | ||
|
|
||
| if (op1SideEffects != nullptr) | ||
| { | ||
| Statement* op1Stmt = fgNewStmtFromTree(op1SideEffects); | ||
| fgInsertStmtBefore(block, stmt, op1Stmt); | ||
| if (newStmt == nullptr) | ||
| { | ||
| newStmt = op1Stmt; | ||
| } | ||
| } | ||
|
|
||
| *use = tree->gtGetOp2(); | ||
|
|
||
| for (Statement* cur = newStmt; (cur != nullptr) && (cur != stmt); cur = cur->GetNextStmt()) | ||
| { | ||
| fgMorphStmtBlockOps(block, cur); | ||
| } | ||
|
|
||
| fgMorphStmtBlockOps(block, stmt); | ||
| gtUpdateStmtSideEffects(stmt); | ||
|
|
||
| // Morphing block ops can introduce commas (and the original | ||
| // statement can also have more commas left). Proceed from the | ||
| // earliest newly introduced statement. | ||
| nextStmt = newStmt != nullptr ? newStmt : stmt; | ||
| break; | ||
| } | ||
|
|
||
| stmt = nextStmt; | ||
| } | ||
| } | ||
|
|
||
| for (BasicBlock* block : Blocks()) | ||
| { | ||
| for (Statement* stmt : block->NonPhiStatements()) | ||
| { | ||
| for (GenTree* tree : stmt->TreeList()) | ||
| { | ||
| assert(!tree->OperIs(GT_COMMA)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| //------------------------------------------------------------------------ | ||
| // generatePatchpointInfo: allocate and fill in patchpoint info data, | ||
| // and report it to the VM | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,7 @@ bool Compiler::fgBlockContainsStatementBounded(BasicBlock* block, | |
| Statement* stmt, | ||
| bool answerOnBoundExceeded /*= true*/) | ||
| { | ||
| const __int64 maxLinks = 1000000000; | ||
| const __int64 maxLinks = 100000000; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought this limit was a bit on the high side before. |
||
|
|
||
| __int64* numTraversed = &JitTls::GetCompiler()->compNumStatementLinksTraversed; | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.