Index: lib/Analysis/MemorySSAUpdater.cpp =================================================================== --- lib/Analysis/MemorySSAUpdater.cpp +++ lib/Analysis/MemorySSAUpdater.cpp @@ -858,7 +858,6 @@ for (auto *BB : NewBlocks) PredMap.erase(BB); - SmallVector BlocksToProcess; SmallVector BlocksWithDefsToReplace; SmallVector InsertedPhis; @@ -934,10 +933,6 @@ for (auto *Pred : PrevBlockSet) for (int I = 0, E = EdgeCountMap[{Pred, BB}]; I < E; ++I) NewPhi->addIncoming(DefP1, Pred); - - // Insert BB in the set of blocks that now have definition. We'll use this - // to compute IDF and add Phis there next. - BlocksToProcess.push_back(BB); } // Get all blocks that used to dominate BB and no longer do after adding @@ -952,6 +947,14 @@ GetNoLongerDomBlocks(PrevIDom, NewIDom, BlocksWithDefsToReplace); } + tryRemoveTrivialPhis(InsertedPhis); + // Create the set of blocks that now have a definition. We'll use this to + // compute IDF and add Phis there next. + SmallVector BlocksToProcess; + for (auto &VH : InsertedPhis) + if (auto *MPhi = cast_or_null(VH)) + BlocksToProcess.push_back(MPhi->getBlock()); + // Compute IDF and add Phis in all IDF blocks that do not have one. SmallVector IDFBlocks; if (!BlocksToProcess.empty()) { Index: test/Analysis/MemorySSA/simple_loop_unswitch_nontrivial.ll =================================================================== --- /dev/null +++ test/Analysis/MemorySSA/simple_loop_unswitch_nontrivial.ll @@ -0,0 +1,113 @@ +; RUN: opt -simple-loop-unswitch -enable-nontrivial-unswitch -verify-memoryssa -S %s | FileCheck %s +; REQUIRES: asserts + +target triple = "x86_64-unknown-linux-gnu" + +declare void @foo() + +; In Test1, there are no definitions. MemorySSA updates insert trivial phis and remove them. +; Verify all are removed, considering the SLU pass leaves unreachable blocks hanging when the MSSA updates are done. +; CHECK-LABEL: @Test1 +define void @Test1(i32) { +header: + br label %outer + +outer.loopexit.split: ; preds = %continue + br label %outer.loopexit + +outer.loopexit: ; preds = %outer.loopexit.split.us, %outer.loopexit.split + br label %outer + +outer: ; preds = %outer.loopexit, %header + br i1 false, label %outer.split.us, label %outer.split + +outer.split.us: ; preds = %outer + br label %inner.us + +inner.us: ; preds = %continue.us, %outer.split.us + br label %overflow.us + +overflow.us: ; preds = %inner.us + br label %continue.us + +continue.us: ; preds = %overflow.us + br i1 true, label %outer.loopexit.split.us, label %inner.us + +outer.loopexit.split.us: ; preds = %continue.us + br label %outer.loopexit + +outer.split: ; preds = %outer + br label %inner + +inner: ; preds = %continue, %outer.split + br label %switchme + +switchme: ; preds = %inner + switch i32 %0, label %continue [ + i32 88, label %go_out + i32 99, label %case2 + ] + +case2: ; preds = %switchme + br label %continue + +continue: ; preds = %case2, %switchme + br i1 true, label %outer.loopexit.split, label %inner + +go_out: ; preds = %switchme + unreachable +} + +; In Test2 there is a single def (call to foo). There are already Phis in place that are cloned when unswitching. +; Ensure MemorySSA remains correct. Due to SLU's pruned cloning, continue.us2 becomes unreachable, with an empty Phi that is later cleaned. +; CHECK-LABEL: @Test2 +define void @Test2(i32) { +header: + br label %outer + +outer.loopexit.split: ; preds = %continue + br label %outer.loopexit + +outer.loopexit: ; preds = %outer.loopexit.split.us, %outer.loopexit.split + br label %outer + +outer: ; preds = %outer.loopexit, %header + br i1 false, label %outer.split.us, label %outer.split + +outer.split.us: ; preds = %outer + br label %inner.us + +inner.us: ; preds = %continue.us, %outer.split.us + br label %overflow.us + +overflow.us: ; preds = %inner.us + br label %continue.us + +continue.us: ; preds = %overflow.us + br i1 true, label %outer.loopexit.split.us, label %inner.us + +outer.loopexit.split.us: ; preds = %continue.us + br label %outer.loopexit + +outer.split: ; preds = %outer + br label %inner + +inner: ; preds = %continue, %outer.split + br label %switchme + +switchme: ; preds = %inner + switch i32 %0, label %continue [ + i32 88, label %go_out + i32 99, label %case2 + ] + +case2: ; preds = %switchme + call void @foo() + br label %continue + +continue: ; preds = %case2, %switchme + br i1 true, label %outer.loopexit.split, label %inner + +go_out: ; preds = %switchme + unreachable +}