From 89a14af688cc6be08df3cec6c69d4f62915aa7fe Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Tue, 6 Dec 2016 15:37:08 -0800 Subject: [PATCH] Fix use edge iterator for DYN_BLK nodes. Dynamic block nodes (i.e. DYN_BLK and STORE_DYN_BLK) are not standard nodes. As such, the use order of their operands may be reordered in ways that are not visible via the usual mechanisms. The use edge iterator was not taking these mechanisms into account, which caused mismatches between the use order observed by LSRA and the order observed by code generation. This in turn caused SBCG under circumstances in which one operand needed to be copied from e.g. esi to edi before another operand was unspilled into esi. Fixes VSO 297113. Commit migrated from https://github.com/dotnet/coreclr/commit/bdcf7fbde9aa473799b02c1ae4d61a463e67f7b8 --- src/coreclr/src/jit/gentree.cpp | 49 ++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/coreclr/src/jit/gentree.cpp b/src/coreclr/src/jit/gentree.cpp index a749cb5..4a6cc74 100644 --- a/src/coreclr/src/jit/gentree.cpp +++ b/src/coreclr/src/jit/gentree.cpp @@ -9244,30 +9244,53 @@ GenTree** GenTreeUseEdgeIterator::GetNextUseEdge() const } case GT_DYN_BLK: + { + GenTreeDynBlk* const dynBlock = m_node->AsDynBlk(); switch (m_state) { case 0: - return &(m_node->AsDynBlk()->gtOp1); + return dynBlock->gtEvalSizeFirst ? &dynBlock->gtDynamicSize : &dynBlock->gtOp1; case 1: - return &(m_node->AsDynBlk()->gtDynamicSize); + return dynBlock->gtEvalSizeFirst ? &dynBlock->gtOp1 : &dynBlock->gtDynamicSize; default: return nullptr; } - break; + } + break; case GT_STORE_DYN_BLK: - switch (m_state) + { + GenTreeDynBlk* const dynBlock = m_node->AsDynBlk(); + if (dynBlock->gtEvalSizeFirst) { - case 0: - return &(m_node->AsDynBlk()->gtOp1); - case 1: - return &(m_node->AsDynBlk()->gtOp2); - case 2: - return &(m_node->AsDynBlk()->gtDynamicSize); - default: - return nullptr; + switch (m_state) + { + case 0: + return &dynBlock->gtDynamicSize; + case 1: + return dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1; + case 2: + return dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2; + default: + return nullptr; + } } - break; + else + { + switch (m_state) + { + case 0: + return dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1; + case 1: + return dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2; + case 2: + return &dynBlock->gtDynamicSize; + default: + return nullptr; + } + } + } + break; case GT_LEA: { -- 2.7.4