@@ -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