Skip to content

Commit b001c60

Browse files
committed
Fix a bad assumption
1 parent 28c9ec7 commit b001c60

File tree

1 file changed

+34
-15
lines changed

1 file changed

+34
-15
lines changed

src/coreclr/jit/promotion.cpp

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,21 +1249,40 @@ void ReplaceVisitor::EndBlock()
12491249
assert(!rep.NeedsReadBack || !rep.NeedsWriteBack);
12501250
if (rep.NeedsReadBack)
12511251
{
1252-
// We only mark fields as requiring read-back if they are live
1253-
// at the point where the stack local was written. If the
1254-
// replacement still needs to be read back then we saw no use
1255-
// between that point and the end of the BB, so we expect the
1256-
// use to be in a successor.
1257-
assert(m_liveness->IsReplacementLiveOut(m_currentBlock, agg->LclNum, (unsigned)i));
1258-
1259-
JITDUMP("Reading back replacement V%02u.[%03u..%03u) -> V%02u near the end of " FMT_BB ":\n",
1260-
agg->LclNum, rep.Offset, rep.Offset + genTypeSize(rep.AccessType), rep.LclNum,
1261-
m_currentBlock->bbNum);
1262-
1263-
GenTree* readBack = Promotion::CreateReadBack(m_compiler, agg->LclNum, rep);
1264-
Statement* stmt = m_compiler->fgNewStmtFromTree(readBack);
1265-
DISPSTMT(stmt);
1266-
m_compiler->fgInsertStmtNearEnd(m_currentBlock, stmt);
1252+
if (m_liveness->IsReplacementLiveOut(m_currentBlock, agg->LclNum, (unsigned)i))
1253+
{
1254+
JITDUMP("Reading back replacement V%02u.[%03u..%03u) -> V%02u near the end of " FMT_BB ":\n",
1255+
agg->LclNum, rep.Offset, rep.Offset + genTypeSize(rep.AccessType), rep.LclNum,
1256+
m_currentBlock->bbNum);
1257+
1258+
GenTree* readBack = Promotion::CreateReadBack(m_compiler, agg->LclNum, rep);
1259+
Statement* stmt = m_compiler->fgNewStmtFromTree(readBack);
1260+
DISPSTMT(stmt);
1261+
m_compiler->fgInsertStmtNearEnd(m_currentBlock, stmt);
1262+
}
1263+
else
1264+
{
1265+
// We only mark fields as requiring read-back if they are
1266+
// live at the point where the stack local was written, so
1267+
// at first glance we would not expect this case to ever
1268+
// happen. However, it is possible that the field is live
1269+
// because it has a future struct use, in which case we may
1270+
// not need to insert any readbacks anywhere. For example,
1271+
// consider:
1272+
//
1273+
// V03 = CALL() // V03 is a struct with promoted V03.[000..008)
1274+
// CALL(struct V03) // V03.[000.008) marked as live here
1275+
//
1276+
// While V03.[000.008) gets marked for readback at the
1277+
// assignment, no readback is necessary at the location of
1278+
// the call argument, and it may die after that.
1279+
1280+
JITDUMP("Skipping reading back dead replacement V%02u.[%03u..%03u) -> V%02u near the end of " FMT_BB
1281+
"\n",
1282+
agg->LclNum, rep.Offset, rep.Offset + genTypeSize(rep.AccessType), rep.LclNum,
1283+
m_currentBlock->bbNum);
1284+
}
1285+
12671286
rep.NeedsReadBack = false;
12681287
}
12691288

0 commit comments

Comments
 (0)