@@ -1885,41 +1885,79 @@ void ReplaceVisitor::InsertPreStatementReadBacks()
1885
1885
// 3. Creating embedded stores in ReplaceLocal disables local copy prop for
1886
1886
// that local (see ReplaceLocal).
1887
1887
1888
- for (GenTreeLclVarCommon* lcl : m_currentStmt->LocalsTreeList ())
1888
+ // Normally, we read back only for the uses we will see. However, with
1889
+ // implicit EH flow we may also read back all replacements mid-tree (see
1890
+ // InsertMidTreeReadBacks). So for that case we read back everything. This
1891
+ // is a correctness requirement for QMARKs, but we do it indiscriminately
1892
+ // for the same reasons as mentioned above.
1893
+ if (((m_currentStmt->GetRootNode ()->gtFlags & (GTF_EXCEPT | GTF_CALL)) != 0 ) &&
1894
+ m_compiler->ehBlockHasExnFlowDsc (m_currentBlock))
1889
1895
{
1890
- if (lcl->TypeIs (TYP_STRUCT))
1891
- {
1892
- continue ;
1893
- }
1896
+ JITDUMP (
1897
+ " Reading back pending replacements before statement with possible exception side effect inside block in try region\n " );
1894
1898
1895
- AggregateInfo* agg = m_aggregates.Lookup (lcl->GetLclNum ());
1896
- if (agg == nullptr )
1899
+ for (AggregateInfo* agg : m_aggregates)
1897
1900
{
1898
- continue ;
1901
+ for (Replacement& rep : agg->Replacements )
1902
+ {
1903
+ InsertPreStatementReadBackIfNecessary (agg->LclNum , rep);
1904
+ }
1899
1905
}
1900
-
1901
- size_t index = Promotion::BinarySearch<Replacement, &Replacement::Offset>(agg->Replacements , lcl->GetLclOffs ());
1902
- if ((ssize_t )index < 0 )
1906
+ }
1907
+ else
1908
+ {
1909
+ // Otherwise just read back the locals we see uses of.
1910
+ for (GenTreeLclVarCommon* lcl : m_currentStmt->LocalsTreeList ())
1903
1911
{
1904
- continue ;
1905
- }
1912
+ if (lcl->TypeIs (TYP_STRUCT))
1913
+ {
1914
+ continue ;
1915
+ }
1906
1916
1907
- Replacement& rep = agg->Replacements [index];
1908
- if (rep.NeedsReadBack )
1909
- {
1910
- JITDUMP (" Reading back replacement V%02u.[%03u..%03u) -> V%02u before [%06u]:\n " , agg->LclNum , rep.Offset ,
1911
- rep.Offset + genTypeSize (rep.AccessType ), rep.LclNum ,
1912
- Compiler::dspTreeID (m_currentStmt->GetRootNode ()));
1917
+ AggregateInfo* agg = m_aggregates.Lookup (lcl->GetLclNum ());
1918
+ if (agg == nullptr )
1919
+ {
1920
+ continue ;
1921
+ }
1913
1922
1914
- GenTree* readBack = Promotion::CreateReadBack (m_compiler, agg->LclNum , rep);
1915
- Statement* stmt = m_compiler->fgNewStmtFromTree (readBack);
1916
- DISPSTMT (stmt);
1917
- m_compiler->fgInsertStmtBefore (m_currentBlock, m_currentStmt, stmt);
1918
- ClearNeedsReadBack (rep);
1923
+ size_t index =
1924
+ Promotion::BinarySearch<Replacement, &Replacement::Offset>(agg->Replacements , lcl->GetLclOffs ());
1925
+ if ((ssize_t )index < 0 )
1926
+ {
1927
+ continue ;
1928
+ }
1929
+
1930
+ InsertPreStatementReadBackIfNecessary (agg->LclNum , agg->Replacements [index]);
1919
1931
}
1920
1932
}
1921
1933
}
1922
1934
1935
+ // ------------------------------------------------------------------------
1936
+ // InsertPreStatementReadBackIfNecessary:
1937
+ // Insert a read back of the specified replacement before the current
1938
+ // statement, if the replacement needs it.
1939
+ //
1940
+ // Parameters:
1941
+ // aggLclNum - Struct local
1942
+ // rep - The replacement
1943
+ //
1944
+ void ReplaceVisitor::InsertPreStatementReadBackIfNecessary (unsigned aggLclNum, Replacement& rep)
1945
+ {
1946
+ if (!rep.NeedsReadBack )
1947
+ {
1948
+ return ;
1949
+ }
1950
+
1951
+ JITDUMP (" Reading back replacement V%02u.[%03u..%03u) -> V%02u before [%06u]:\n " , aggLclNum, rep.Offset ,
1952
+ rep.Offset + genTypeSize (rep.AccessType ), rep.LclNum , Compiler::dspTreeID (m_currentStmt->GetRootNode ()));
1953
+
1954
+ GenTree* readBack = Promotion::CreateReadBack (m_compiler, aggLclNum, rep);
1955
+ Statement* stmt = m_compiler->fgNewStmtFromTree (readBack);
1956
+ DISPSTMT (stmt);
1957
+ m_compiler->fgInsertStmtBefore (m_currentBlock, m_currentStmt, stmt);
1958
+ ClearNeedsReadBack (rep);
1959
+ }
1960
+
1923
1961
// ------------------------------------------------------------------------
1924
1962
// VisitOverlappingReplacements:
1925
1963
// Call a function for every replacement that overlaps a specified segment.
0 commit comments