Index: include/llvm/Pass.h =================================================================== --- include/llvm/Pass.h +++ include/llvm/Pass.h @@ -350,8 +350,9 @@ /// runOnBasicBlock - Virtual method overriden by subclasses to do the /// per-basicblock processing of the pass. + /// IsAlive can be used to determine if the basicblock is dead or alive. /// - virtual bool runOnBasicBlock(BasicBlock &BB) = 0; + virtual bool runOnBasicBlock(BasicBlock &BB, bool IsAlive) = 0; /// doFinalization - Virtual method overriden by BasicBlockPass subclasses to /// do any post processing needed after all passes have run. Index: lib/IR/IRPrintingPasses.cpp =================================================================== --- lib/IR/IRPrintingPasses.cpp +++ lib/IR/IRPrintingPasses.cpp @@ -107,7 +107,7 @@ PrintBasicBlockPass(raw_ostream &Out, const std::string &Banner) : BasicBlockPass(ID), Out(Out), Banner(Banner) {} - bool runOnBasicBlock(BasicBlock &BB) override { + bool runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) override { Out << Banner << BB; return false; } Index: lib/IR/LegacyPassManager.cpp =================================================================== --- lib/IR/LegacyPassManager.cpp +++ lib/IR/LegacyPassManager.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/LegacyPassManager.h" +#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/IR/CFG.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManagers.h" @@ -1278,6 +1280,11 @@ bool Changed = doInitialization(F); + // Mark all the forward reachable blocks, once for all blocks + df_iterator_default_set Reachable; + for (BasicBlock *BB : depth_first_ext(&F, Reachable)) + (void)BB; + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { BasicBlockPass *BP = getContainedPass(Index); @@ -1293,7 +1300,8 @@ PassManagerPrettyStackEntry X(BP, *I); TimeRegion PassTimer(getPassTimer(BP)); - LocalChanged |= BP->runOnBasicBlock(*I); + // Run the pass and inform if the block is forward reachable + LocalChanged |= BP->runOnBasicBlock(*I, Reachable.count(&*I)); } Changed |= LocalChanged; Index: lib/Target/NVPTX/NVPTXLowerAlloca.cpp =================================================================== --- lib/Target/NVPTX/NVPTXLowerAlloca.cpp +++ lib/Target/NVPTX/NVPTXLowerAlloca.cpp @@ -42,7 +42,7 @@ namespace { class NVPTXLowerAlloca : public BasicBlockPass { - bool runOnBasicBlock(BasicBlock &BB) override; + bool runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) override; public: static char ID; // Pass identification, replacement for typeid @@ -61,7 +61,7 @@ // ============================================================================= // Main function for this pass. // ============================================================================= -bool NVPTXLowerAlloca::runOnBasicBlock(BasicBlock &BB) { +bool NVPTXLowerAlloca::runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) { if (skipBasicBlock(BB)) return false; Index: lib/Transforms/Scalar/DCE.cpp =================================================================== --- lib/Transforms/Scalar/DCE.cpp +++ lib/Transforms/Scalar/DCE.cpp @@ -41,7 +41,7 @@ DeadInstElimination() : BasicBlockPass(ID) { initializeDeadInstEliminationPass(*PassRegistry::getPassRegistry()); } - bool runOnBasicBlock(BasicBlock &BB) override { + bool runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) override { if (skipBasicBlock(BB)) return false; auto *TLIP = getAnalysisIfAvailable(); Index: lib/Transforms/Scalar/LoadCombine.cpp =================================================================== --- lib/Transforms/Scalar/LoadCombine.cpp +++ lib/Transforms/Scalar/LoadCombine.cpp @@ -61,7 +61,7 @@ using llvm::Pass::doInitialization; bool doInitialization(Function &) override; - bool runOnBasicBlock(BasicBlock &BB) override; + bool runOnBasicBlock(BasicBlock &BB, bool IsAlive) override; void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); AU.addRequired(); @@ -229,8 +229,8 @@ return true; } -bool LoadCombine::runOnBasicBlock(BasicBlock &BB) { - if (skipBasicBlock(BB)) +bool LoadCombine::runOnBasicBlock(BasicBlock &BB, bool IsAlive) { + if (!IsAlive || skipBasicBlock(BB)) return false; AA = &getAnalysis().getAAResults(); Index: lib/Transforms/Vectorize/BBVectorize.cpp =================================================================== --- lib/Transforms/Vectorize/BBVectorize.cpp +++ lib/Transforms/Vectorize/BBVectorize.cpp @@ -439,7 +439,7 @@ return changed; } - bool runOnBasicBlock(BasicBlock &BB) override { + bool runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) override { // OptimizeNone check deferred to vectorizeBB(). AA = &getAnalysis().getAAResults(); Index: test/Transforms/LoadCombine/deadcode.ll =================================================================== --- /dev/null +++ test/Transforms/LoadCombine/deadcode.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -load-combine -disable-output + +; It has been detected that dead loops like the one in this test case can be +; created by -jump-threading (it was detected by a csmith generated program). +; +; According to -verify this is valid input (even if it could be discussed if +; the dead loop really satisfies SSA form). +; +; The problem found was that the -load-combine pass ends up in an infinite loop +; when analysing the 'bb1' basic block. +define void @test1() { + ret void + +bb1: + %_tmp4 = load i16, i16* %_tmp10, align 1 + %_tmp10 = getelementptr i16, i16* %_tmp10, i16 1 + br label %bb1 +} Index: tools/bugpoint-passes/TestPasses.cpp =================================================================== --- tools/bugpoint-passes/TestPasses.cpp +++ tools/bugpoint-passes/TestPasses.cpp @@ -33,7 +33,7 @@ AU.setPreservesAll(); } - bool runOnBasicBlock(BasicBlock &BB) override { + bool runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) override { for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) if (isa(*I)) abort(); @@ -56,7 +56,7 @@ static char ID; // Pass ID, replacement for typeid DeleteCalls() : BasicBlockPass(ID) {} private: - bool runOnBasicBlock(BasicBlock &BB) override { + bool runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) override { for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) if (CallInst *CI = dyn_cast(I)) { if (!CI->use_empty()) Index: tools/opt/PassPrinters.cpp =================================================================== --- tools/opt/PassPrinters.cpp +++ tools/opt/PassPrinters.cpp @@ -206,7 +206,7 @@ PassName = "BasicBlockPass Printer: " + PassToPrintName; } - bool runOnBasicBlock(BasicBlock &BB) override { + bool runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) override { if (!QuietPass) Out << "Printing Analysis info for BasicBlock '" << BB.getName() << "': Pass " << PassToPrint->getPassName() << ":\n"; Index: unittests/IR/LegacyPassManagerTest.cpp =================================================================== --- unittests/IR/LegacyPassManagerTest.cpp +++ unittests/IR/LegacyPassManagerTest.cpp @@ -246,7 +246,7 @@ inited++; return false; } - bool runOnBasicBlock(BasicBlock &BB) override { + bool runOnBasicBlock(BasicBlock &BB, bool /* IsAlive */) override { run(); return false; }