Index: lib/Analysis/MemorySSAUpdater.cpp =================================================================== --- lib/Analysis/MemorySSAUpdater.cpp +++ lib/Analysis/MemorySSAUpdater.cpp @@ -1184,6 +1184,14 @@ Instruction *Start) { assert(From->getSinglePredecessor() == To && "From block is expected to have a single predecessor (To)."); + if (MemoryPhi *MP = MSSA->getMemoryAccess(From)) { + // `From` might have a trivial PHI with a single input. Optimize it + // now before `From` is removed. + assert(MP.getNumIncomingValues() == 1 && "From can only have one pred"); + auto *ReplacedWith = tryRemoveTrivialPhi(MP); + assert(ReplacedWith != MP && + "If there is a Phi it must be trivially removable"); + } moveAllAccesses(From, To, Start); for (BasicBlock *Succ : successors(From)) if (MemoryPhi *MPhi = MSSA->getMemoryAccess(Succ)) Index: lib/Transforms/Utils/BasicBlockUtils.cpp =================================================================== --- lib/Transforms/Utils/BasicBlockUtils.cpp +++ lib/Transforms/Utils/BasicBlockUtils.cpp @@ -227,18 +227,24 @@ Updates.push_back({DominatorTree::Delete, PredBB, BB}); } - if (MSSAU) - MSSAU->moveAllAfterMergeBlocks(BB, PredBB, &*(BB->begin())); - - // Delete the unconditional branch from the predecessor... - PredBB->getInstList().pop_back(); + // We need to update MemorySSA if MSSAU is provided. MemorySSAUpdater expects + // a specifc state when notified: `PredBB` still branches to `BB`, but all + // instructions were moved from `BB` to `PredBB` and `BB` is now an empty + // block. Splice the instructions, but keep the terminators intact. + Instruction *PredBBTerm = PredBB->getTerminator(); + Instruction *BBTerm = BB->getTerminator(); + Instruction *FirstBBInst = &*(BB->begin()); + PredBB->getInstList().splice(PredBBTerm->getIterator(), BB->getInstList(), + BB->begin(), BBTerm->getIterator()); - // Make all PHI nodes that referred to BB now refer to Pred as their - // source... - BB->replaceAllUsesWith(PredBB); + if (MSSAU) + MSSAU->moveAllAfterMergeBlocks(BB, PredBB, FirstBBInst); - // Move all definitions in the successor to the predecessor... - PredBB->getInstList().splice(PredBB->end(), BB->getInstList()); + // Finish updating the CFG after MSSAU is notified. + BB->replaceSuccessorsPhiUsesWith(PredBB); + BBTerm->removeFromParent(); + BBTerm->insertBefore(PredBBTerm); + PredBBTerm->eraseFromParent(); new UnreachableInst(BB->getContext(), BB); // Eliminate duplicate dbg.values describing the entry PHI node post-splice. Index: test/Transforms/LoopSimplifyCFG/unswitch_simplify_mssa_update.ll =================================================================== --- /dev/null +++ test/Transforms/LoopSimplifyCFG/unswitch_simplify_mssa_update.ll @@ -0,0 +1,32 @@ +; RUN: opt -passes='loop-mssa(unswitch,simplify-cfg),verify' -S < %s | FileCheck %s + +declare void @a() +declare void @b() +declare void @x() + +; CHECK: test_unswitch_simplify +define void @test_unswitch_simplify(i1* %ptr, i1 %cond, i1 %f, i32 %n) { +entry: + br i1 %f, label %loop_begin, label %loop_exit + +loop_begin: + %iv = phi i32 [0, %entry], [%iv.next, %loop_latch] + call void @x() + br i1 %cond, label %loop_a, label %loop_b + +loop_a: + call void @a() + br label %loop_latch + +loop_b: + call void @b() + br label %loop_latch + +loop_latch: + %iv.next = add i32 %iv, 1 + %v = icmp eq i32 %iv.next, %n + br i1 %v, label %loop_begin, label %loop_exit + +loop_exit: + ret void +} \ No newline at end of file