diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 43dd651a686b..66d29cb5d65e 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -78,10 +78,10 @@ private: bool prepareExplicitEH(Function &F); void colorFunclets(Function &F); - void demotePHIsOnFunclets(Function &F, bool DemoteCatchSwitchPHIOnly); - void cloneCommonBlocks(Function &F); - void removeImplausibleInstructions(Function &F); - void cleanupPreparedFunclets(Function &F); + bool demotePHIsOnFunclets(Function &F, bool DemoteCatchSwitchPHIOnly); + bool cloneCommonBlocks(Function &F); + bool removeImplausibleInstructions(Function &F); + bool cleanupPreparedFunclets(Function &F); void verifyPreparedFunclets(Function &F); bool DemoteCatchSwitchPHIOnly; @@ -861,8 +861,10 @@ void WinEHPrepareImpl::colorFunclets(Function &F) { } } -void WinEHPrepareImpl::demotePHIsOnFunclets(Function &F, +bool WinEHPrepareImpl::demotePHIsOnFunclets(Function &F, bool DemoteCatchSwitchPHIOnly) { + bool Changed = false; + // Strip PHI nodes off of EH pads. SmallVector PHINodes; for (BasicBlock &BB : make_early_inc_range(F)) { @@ -892,6 +894,8 @@ void WinEHPrepareImpl::demotePHIsOnFunclets(Function &F, break; } + Changed = true; + AllocaInst *SpillSlot = insertPHILoads(PN, F); if (SpillSlot) insertPHIStores(PN, SpillSlot); @@ -905,9 +909,13 @@ void WinEHPrepareImpl::demotePHIsOnFunclets(Function &F, PN->replaceAllUsesWith(PoisonValue::get(PN->getType())); PN->eraseFromParent(); } + + return Changed; } -void WinEHPrepareImpl::cloneCommonBlocks(Function &F) { +bool WinEHPrepareImpl::cloneCommonBlocks(Function &F) { + bool Changed = false; + // We need to clone all blocks which belong to multiple funclets. Values are // remapped throughout the funclet to propagate both the new instructions // *and* the new basic blocks themselves. @@ -952,6 +960,8 @@ void WinEHPrepareImpl::cloneCommonBlocks(Function &F) { if (Orig2Clone.empty()) continue; + Changed = true; + // Update our color mappings to reflect that one block has lost a color and // another has gained a color. for (auto &BBMapping : Orig2Clone) { @@ -1107,9 +1117,13 @@ void WinEHPrepareImpl::cloneCommonBlocks(Function &F) { SSAUpdate.RewriteUseAfterInsertions(*UsesToRename.pop_back_val()); } } + + return Changed; } -void WinEHPrepareImpl::removeImplausibleInstructions(Function &F) { +bool WinEHPrepareImpl::removeImplausibleInstructions(Function &F) { + bool Changed = false; + // Remove implausible terminators and replace them with UnreachableInst. for (auto &Funclet : FuncletBlocks) { BasicBlock *FuncletPadBB = Funclet.first; @@ -1139,6 +1153,8 @@ void WinEHPrepareImpl::removeImplausibleInstructions(Function &F) { (CalledFn && CalledFn->isIntrinsic() && CB->doesNotThrow())) continue; + Changed = true; + // This call site was not part of this funclet, remove it. if (isa(CB)) { // Remove the unwind edge if it was an invoke. @@ -1170,9 +1186,11 @@ void WinEHPrepareImpl::removeImplausibleInstructions(Function &F) { IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad; if (IsUnreachableRet || IsUnreachableCatchret || IsUnreachableCleanupret) { + Changed = true; changeToUnreachable(TI); } else if (isa(TI)) { if (Personality == EHPersonality::MSVC_CXX && CleanupPad) { + Changed = true; // Invokes within a cleanuppad for the MSVC++ personality never // transfer control to their unwind edge: the personality will // terminate the program. @@ -1181,20 +1199,26 @@ void WinEHPrepareImpl::removeImplausibleInstructions(Function &F) { } } } + + return Changed; } -void WinEHPrepareImpl::cleanupPreparedFunclets(Function &F) { +bool WinEHPrepareImpl::cleanupPreparedFunclets(Function &F) { + bool Changed = false; + // Clean-up some of the mess we made by removing useles PHI nodes, trivial // branches, etc. for (BasicBlock &BB : llvm::make_early_inc_range(F)) { - SimplifyInstructionsInBlock(&BB); - ConstantFoldTerminator(&BB, /*DeleteDeadConditions=*/true); - MergeBlockIntoPredecessor(&BB); + Changed |= SimplifyInstructionsInBlock(&BB); + Changed |= ConstantFoldTerminator(&BB, /*DeleteDeadConditions=*/true); + Changed |= MergeBlockIntoPredecessor(&BB); } // We might have some unreachable blocks after cleaning up some impossible // control flow. - removeUnreachableBlocks(F); + Changed |= removeUnreachableBlocks(F); + + return Changed; } #ifndef NDEBUG @@ -1216,23 +1240,23 @@ bool WinEHPrepareImpl::prepareExplicitEH(Function &F) { // Remove unreachable blocks. It is not valuable to assign them a color and // their existence can trick us into thinking values are alive when they are // not. - removeUnreachableBlocks(F); + bool Changed = removeUnreachableBlocks(F); // Determine which blocks are reachable from which funclet entries. colorFunclets(F); - cloneCommonBlocks(F); + Changed |= cloneCommonBlocks(F); if (!DisableDemotion) - demotePHIsOnFunclets(F, DemoteCatchSwitchPHIOnly || - DemoteCatchSwitchPHIOnlyOpt); + Changed |= demotePHIsOnFunclets(F, DemoteCatchSwitchPHIOnly || + DemoteCatchSwitchPHIOnlyOpt); if (!DisableCleanups) { assert(!verifyFunction(F, &dbgs())); - removeImplausibleInstructions(F); + Changed |= removeImplausibleInstructions(F); assert(!verifyFunction(F, &dbgs())); - cleanupPreparedFunclets(F); + Changed |= cleanupPreparedFunclets(F); } LLVM_DEBUG(verifyPreparedFunclets(F)); @@ -1240,7 +1264,7 @@ bool WinEHPrepareImpl::prepareExplicitEH(Function &F) { LLVM_DEBUG(colorFunclets(F)); LLVM_DEBUG(verifyPreparedFunclets(F)); - return true; + return Changed; } // TODO: Share loads when one use dominates another, or when a catchpad exit