-
Notifications
You must be signed in to change notification settings - Fork 5.4k
[Wasm RyuJIT]: Fix LIR Semantics in Stackifier Output #127412
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
base: main
Are you sure you want to change the base?
Changes from all commits
7ac9a35
3a9fb5b
2096c11
244f535
2fbab95
3227554
b01beb4
bb29310
a0dc9dc
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 |
|---|---|---|
|
|
@@ -552,6 +552,9 @@ void Lowering::AfterLowerBlocks() | |
| { | ||
| assert(IsDataFlowRoot(node)); | ||
| node = StackifyTree(node); | ||
| // We don't track liveness of temporaries more precisely since introducing eairler uses | ||
| // may interfere with later (by that point already inserted and stackified) stores. | ||
| ReleaseTemporaries(); | ||
| } | ||
|
Comment on lines
554
to
558
|
||
| m_lower->m_block = nullptr; | ||
|
|
||
|
|
@@ -567,7 +570,6 @@ void Lowering::AfterLowerBlocks() | |
| // Simple greedy algorithm working backwards. The invariant is that the stack top must be placed right next | ||
| // to (in normal linear order - before) the node we last stackified. | ||
| m_stack.Push(&root); | ||
| ReleaseTemporariesDefinedBy(root); | ||
|
|
||
| GenTree* lastStackified = root->gtNext; | ||
| while (m_stack.Height() != initialDepth) | ||
|
|
@@ -668,8 +670,6 @@ void Lowering::AfterLowerBlocks() | |
| *use = lclNode; | ||
|
|
||
| JITDUMP("Replaced [%06u] with a temporary:\n", Compiler::dspTreeID(node)); | ||
| DISPNODE(node); | ||
| DISPNODE(lclNode); | ||
|
Contributor
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. Why remove the dumps?
Contributor
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. Ah, accidental, will revert. |
||
|
|
||
| if ((node->gtLIRFlags & LIR::Flags::MultiplyUsed) == LIR::Flags::MultiplyUsed) | ||
| { | ||
|
|
@@ -704,33 +704,37 @@ void Lowering::AfterLowerBlocks() | |
| return lclNum; | ||
| } | ||
|
|
||
| void ReleaseTemporariesDefinedBy(GenTree* node) | ||
| void ReleaseTemporaries() | ||
| { | ||
| // We rely in this function on the lifetime of temporaries beginning (recall this is backwards traversal) | ||
| // at exactly "node"'s position, and not shrinking or extending after this call. This is currently true | ||
| // because we never move dataflow roots, and we only begin processing them after all subsequent nodes | ||
| // have already been stackified and thus won't move either. | ||
| assert(IsDataFlowRoot(node)); | ||
| if (!node->OperIs(GT_STORE_LCL_VAR)) | ||
| if (m_minimumTempLclNum == m_compiler->lvaCount) | ||
| { | ||
| // No temporaries were created | ||
| return; | ||
| } | ||
| assert(m_minimumTempLclNum < m_compiler->lvaCount); | ||
|
|
||
| unsigned lclNum = node->AsLclVar()->GetLclNum(); | ||
| if (lclNum < m_minimumTempLclNum) | ||
| // Recycle all available temporaries as unused nodes | ||
| for (int i = 0; i < TYP_COUNT; i++) | ||
| { | ||
| return; | ||
| while (m_availableTemps[i] != nullptr) | ||
| { | ||
| Temporary* temp = Remove(&m_availableTemps[i]); | ||
| Append(&m_unusedTempNodes, temp); | ||
|
Contributor
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 understanding you're working with the model from the previous algorithm where we had piece-wise node addition and removal, but at this point it would make more sense to use the more traditional "available/in-use" free lists, i. e. make |
||
| } | ||
| } | ||
|
|
||
| Temporary* local = Remove(&m_unusedTempNodes); // See if we have any free nodes in the pool. | ||
| if (local == nullptr) | ||
| for (unsigned lclNum = m_minimumTempLclNum; lclNum < m_compiler->lvaCount; lclNum++) | ||
| { | ||
| local = new (m_compiler, CMK_Lower) Temporary(); | ||
| } | ||
| local->LclNum = lclNum; | ||
| Temporary* local = Remove(&m_unusedTempNodes); // See if we have any free nodes in the pool. | ||
| if (local == nullptr) | ||
| { | ||
| local = new (m_compiler, CMK_Lower) Temporary(); | ||
| } | ||
| local->LclNum = lclNum; | ||
|
|
||
| JITDUMP("Temporary V%02u is now free and can be re-used\n", lclNum); | ||
| Append(&m_availableTemps[genActualType(node->TypeGet())], local); | ||
| JITDUMP("Temporary V%02u is now free and can be re-used\n", lclNum); | ||
| Append(&m_availableTemps[genActualType(m_compiler->lvaGetDesc(lclNum)->TypeGet())], local); | ||
| } | ||
| } | ||
|
Comment on lines
+707
to
738
|
||
|
|
||
| Temporary* Remove(Temporary** pTemps) | ||
|
|
||
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.
Typo in the new comment: "eairler" should be "earlier" (and consider tweaking wording for clarity since this comment explains the rationale for the new lifetime behavior).