Skip to content

Commit e7afbea

Browse files
author
Whitney Tsang
committed
[MemorySSA] Clear VisitedBlocks per query
The problem can be shown from the newly added test case. There are two invocations to MemorySSAUpdater::moveToPlace, and the internal data structure VisitedBlocks is changed in the first invocation, and reused in the second invocation. In between the two invocations, there is a change to the CFG, and MemorySSAUpdater is notified about the change. Reviewed By: asbirlea Differential Revision: https://reviews.llvm.org/D119898
1 parent 93e2b59 commit e7afbea

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

llvm/lib/Analysis/MemorySSAUpdater.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ MemoryAccess *MemorySSAUpdater::tryRemoveTrivialPhi(MemoryPhi *Phi,
243243
}
244244

245245
void MemorySSAUpdater::insertUse(MemoryUse *MU, bool RenameUses) {
246+
VisitedBlocks.clear();
246247
InsertedPHIs.clear();
247248
MU->setDefiningAccess(getPreviousDef(MU));
248249

@@ -311,6 +312,7 @@ static void setMemoryPhiValueForBlock(MemoryPhi *MP, const BasicBlock *BB,
311312
// point to the correct new defs, to ensure we only have one variable, and no
312313
// disconnected stores.
313314
void MemorySSAUpdater::insertDef(MemoryDef *MD, bool RenameUses) {
315+
VisitedBlocks.clear();
314316
InsertedPHIs.clear();
315317

316318
// See if we had a local def, and if not, go hunting.

llvm/unittests/Analysis/MemorySSATest.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,3 +1772,95 @@ TEST_F(MemorySSATest, TestInvariantGroup) {
17721772
EXPECT_EQ(CallAccess, LClobber);
17731773
}
17741774
}
1775+
1776+
static BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
1777+
for (BasicBlock &BB : F)
1778+
if (BB.getName() == Name)
1779+
return &BB;
1780+
llvm_unreachable("Expected to find basic block!");
1781+
}
1782+
1783+
static Instruction *getInstructionByName(Function &F, StringRef Name) {
1784+
for (BasicBlock &BB : F)
1785+
for (Instruction &I : BB)
1786+
if (I.getName() == Name)
1787+
return &I;
1788+
llvm_unreachable("Expected to find instruction!");
1789+
}
1790+
1791+
TEST_F(MemorySSATest, TestVisitedBlocks) {
1792+
SMDiagnostic E;
1793+
auto M = parseAssemblyString(
1794+
"define void @test(i64* noalias %P, i64 %N) {\n"
1795+
"preheader.n:\n"
1796+
" br label %header.n\n"
1797+
"header.n:\n"
1798+
" %n = phi i64 [ 0, %preheader.n ], [ %inc.n, %latch.n ]\n"
1799+
" %guard.cond.i = icmp slt i64 0, %N\n"
1800+
" br i1 %guard.cond.i, label %header.i.check, label %other.i\n"
1801+
"header.i.check:\n"
1802+
" br label %preheader.i\n"
1803+
"preheader.i:\n"
1804+
" br label %header.i\n"
1805+
"header.i:\n"
1806+
" %i = phi i64 [ 0, %preheader.i ], [ %inc.i, %header.i ]\n"
1807+
" %v1 = load i64, i64* %P, align 8\n"
1808+
" %v2 = load i64, i64* %P, align 8\n"
1809+
" %inc.i = add nsw i64 %i, 1\n"
1810+
" %cmp.i = icmp slt i64 %inc.i, %N\n"
1811+
" br i1 %cmp.i, label %header.i, label %exit.i\n"
1812+
"exit.i:\n"
1813+
" br label %commonexit\n"
1814+
"other.i:\n"
1815+
" br label %commonexit\n"
1816+
"commonexit:\n"
1817+
" br label %latch.n\n"
1818+
"latch.n:\n"
1819+
" %inc.n = add nsw i64 %n, 1\n"
1820+
" %cmp.n = icmp slt i64 %inc.n, %N\n"
1821+
" br i1 %cmp.n, label %header.n, label %exit.n\n"
1822+
"exit.n:\n"
1823+
" ret void\n"
1824+
"}\n",
1825+
E, C);
1826+
ASSERT_TRUE(M);
1827+
F = M->getFunction("test");
1828+
ASSERT_TRUE(F);
1829+
setupAnalyses();
1830+
MemorySSA &MSSA = *Analyses->MSSA;
1831+
MemorySSAUpdater Updater(&MSSA);
1832+
1833+
{
1834+
// Move %v1 before the terminator of %header.i.check
1835+
BasicBlock *BB = getBasicBlockByName(*F, "header.i.check");
1836+
Instruction *LI = getInstructionByName(*F, "v1");
1837+
LI->moveBefore(BB->getTerminator());
1838+
if (MemoryUseOrDef *MUD = MSSA.getMemoryAccess(LI))
1839+
Updater.moveToPlace(MUD, BB, MemorySSA::BeforeTerminator);
1840+
1841+
// Change the termiantor of %header.i.check to `br label true, label
1842+
// %preheader.i, label %other.i`
1843+
BB->getTerminator()->eraseFromParent();
1844+
ConstantInt *BoolTrue = ConstantInt::getTrue(F->getContext());
1845+
BranchInst::Create(getBasicBlockByName(*F, "preheader.i"),
1846+
getBasicBlockByName(*F, "other.i"), BoolTrue, BB);
1847+
SmallVector<DominatorTree::UpdateType, 4> DTUpdates;
1848+
DTUpdates.push_back(DominatorTree::UpdateType(
1849+
DominatorTree::Insert, BB, getBasicBlockByName(*F, "other.i")));
1850+
Updater.applyUpdates(DTUpdates, Analyses->DT, true);
1851+
}
1852+
1853+
// After the first moveToPlace(), %other.i is in VisitedBlocks, even after
1854+
// there is a new edge to %other.i, which makes the second moveToPlace()
1855+
// traverse incorrectly.
1856+
{
1857+
// Move %v2 before the terminator of %preheader.i
1858+
BasicBlock *BB = getBasicBlockByName(*F, "preheader.i");
1859+
Instruction *LI = getInstructionByName(*F, "v2");
1860+
LI->moveBefore(BB->getTerminator());
1861+
// Check that there is no assertion of "Incomplete phi during partial
1862+
// rename"
1863+
if (MemoryUseOrDef *MUD = MSSA.getMemoryAccess(LI))
1864+
Updater.moveToPlace(MUD, BB, MemorySSA::BeforeTerminator);
1865+
}
1866+
}

0 commit comments

Comments
 (0)