Index: lib/Transforms/Utils/LibCallsShrinkWrap.cpp =================================================================== --- lib/Transforms/Utils/LibCallsShrinkWrap.cpp +++ lib/Transforms/Utils/LibCallsShrinkWrap.cpp @@ -33,6 +33,7 @@ #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstVisitor.h" @@ -75,6 +76,7 @@ INITIALIZE_PASS_BEGIN(LibCallsShrinkWrapLegacyPass, "libcalls-shrinkwrap", "Conditionally eliminate dead library calls", false, false) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) INITIALIZE_PASS_END(LibCallsShrinkWrapLegacyPass, "libcalls-shrinkwrap", "Conditionally eliminate dead library calls", false, false) @@ -82,7 +84,8 @@ namespace { class LibCallsShrinkWrap : public InstVisitor { public: - LibCallsShrinkWrap(const TargetLibraryInfo &TLI) : TLI(TLI), Changed(false){}; + LibCallsShrinkWrap(const TargetLibraryInfo &TLI, DominatorTree &DT) + : TLI(TLI), DT(DT), Changed(false){}; bool isChanged() const { return Changed; } void visitCallInst(CallInst &CI) { checkCandidate(CI); } void perform() { @@ -134,6 +137,7 @@ } const TargetLibraryInfo &TLI; + DominatorTree &DT; SmallVector WorkList; bool Changed; }; @@ -502,11 +506,31 @@ assert(Cond != nullptr && "hrinkWrapCI is not expecting an empty call inst"); MDNode *BranchWeights = MDBuilder(CI->getContext()).createBranchWeights(1, 2000); + + // Remember the BB containing the call pre-split so that we can use it + // to update the dominator locally. + BasicBlock *OrigBB = CI->getParent(); + TerminatorInst *NewInst = SplitBlockAndInsertIfThen(Cond, CI, false, BranchWeights); BasicBlock *CallBB = NewInst->getParent(); CallBB->setName("cdce.call"); - CallBB->getSingleSuccessor()->setName("cdce.end"); + BasicBlock *SuccBB = CallBB->getSingleSuccessor(); + assert(SuccBB && "The split block should have a single successor"); + SuccBB->setName("cdce.end"); + + // The split block operation transforms the block A into + // + // A + // /| + // B | + // \| + // C + // So we create two new BasicBlocks which obviously have as immediate + // dominator the original block. Update accordingly. + DT.addNewBlock(CallBB, OrigBB); + DT.addNewBlock(SuccBB, OrigBB); + CI->removeFromParent(); CallBB->getInstList().insert(CallBB->getFirstInsertionPt(), CI); DEBUG(dbgs() << "== Basic Block After =="); @@ -532,22 +556,31 @@ } void LibCallsShrinkWrapLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addPreserved(); AU.addPreserved(); + AU.addRequired(); AU.addRequired(); } -static bool runImpl(Function &F, const TargetLibraryInfo &TLI) { +static bool runImpl(Function &F, const TargetLibraryInfo &TLI, + DominatorTree &DT) { if (F.hasFnAttribute(Attribute::OptimizeForSize)) return false; - LibCallsShrinkWrap CCDCE(TLI); + LibCallsShrinkWrap CCDCE(TLI, DT); CCDCE.visit(F); CCDCE.perform(); + +// Verify the dominator after we've updated it locally. +#ifndef NDEBUG + DT.verifyDomTree(); +#endif return CCDCE.isChanged(); } bool LibCallsShrinkWrapLegacyPass::runOnFunction(Function &F) { auto &TLI = getAnalysis().getTLI(); - return runImpl(F, TLI); + auto &DT = getAnalysis().getDomTree(); + return runImpl(F, TLI, DT); } namespace llvm { @@ -561,11 +594,13 @@ PreservedAnalyses LibCallsShrinkWrapPass::run(Function &F, FunctionAnalysisManager &FAM) { auto &TLI = FAM.getResult(F); - bool Changed = runImpl(F, TLI); + auto &DT = FAM.getResult(F); + bool Changed = runImpl(F, TLI, DT); if (!Changed) return PreservedAnalyses::all(); auto PA = PreservedAnalyses(); PA.preserve(); + PA.preserve(); return PA; } }