Index: test/DebugInfo/debugify.ll =================================================================== --- test/DebugInfo/debugify.ll +++ test/DebugInfo/debugify.ll @@ -7,11 +7,11 @@ ; RUN: FileCheck %s -check-prefix=CHECK-REPEAT ; RUN: opt -debugify -check-debugify -S -o - < %s | \ -; RUN: FileCheck %s -implicit-check-not="CheckDebugify: FAIL" +; RUN: FileCheck %s -implicit-check-not="CheckModuleDebugify: FAIL" ; RUN: opt -passes=debugify,check-debugify -S -o - < %s | \ -; RUN: FileCheck %s -implicit-check-not="CheckDebugify: FAIL" +; RUN: FileCheck %s -implicit-check-not="CheckModuleDebugify: FAIL" ; RUN: opt -enable-debugify -passes=verify -S -o - < %s | \ -; RUN: FileCheck %s -implicit-check-not="CheckDebugify: FAIL" +; RUN: FileCheck %s -implicit-check-not="CheckModuleDebugify: FAIL" ; RUN: opt -debugify -strip -check-debugify -S -o - < %s | \ ; RUN: FileCheck %s -check-prefix=CHECK-FAIL @@ -21,6 +21,15 @@ ; RUN: opt -enable-debugify -S -o - < %s | FileCheck %s -check-prefix=PASS +; RUN: opt -debugify-each -debugify -S -o - < %s 2>&1 | \ +; RUN: FileCheck %s -check-prefix=CHECK-EACH-REPEAT + +; RUN: opt -debugify-each -check-debugify -S -o - < %s 2>&1 | \ +; RUN: FileCheck %s -check-prefix=CHECK-EACH-REPEAT-CHECK + +; RUN: opt -debugify-each -strip -S -o - < %s | \ +; RUN: FileCheck %s -check-prefix=CHECK-EACH-FAIL + ; CHECK-LABEL: define void @foo define void @foo() { ; CHECK: ret void, !dbg ![[RET1:.*]] @@ -68,7 +77,7 @@ ; CHECK-DAG: ![[NUM_VARS]] = !{i32 1} ; --- Repeat case -; CHECK-REPEAT: Debugify: Skipping module with debug info +; CHECK-REPEAT: ModuleDebugify: Skipping module with debug info ; --- Failure case ; CHECK-FAIL: ERROR: Instruction with empty DebugLoc -- ret void @@ -80,6 +89,35 @@ ; CHECK-FAIL: WARNING: Missing line 3 ; CHECK-FAIL: WARNING: Missing line 4 ; CHECK-FAIL: ERROR: Missing variable 1 -; CHECK-FAIL: CheckDebugify: FAIL +; CHECK-FAIL: CheckModuleDebugify: FAIL + +; PASS: CheckModuleDebugify: PASS -; PASS: CheckDebugify: PASS +; --- Debugify-each repeat case +; CHECK-EACH-REPEAT: ModuleDebugify: Skipping module with debug info +; CHECK-EACH-REPEAT: CheckModuleDebugify: PASS +; CHECK-EACH-REPEAT: CheckFunctionDebugify: PASS +; CHECK-EACH-REPEAT: CheckFunctionDebugify: PASS +; CHECK-EACH-REPEAT: CheckFunctionDebugify: PASS + +; --- Debugify-each repeat check case +; CHECK-EACH-REPEAT-CHECK: CheckModuleDebugify: PASS +; CHECK-EACH-REPEAT-CHECK: CheckModuleDebugify: PASS +; CHECK-EACH-REPEAT-CHECK: CheckFunctionDebugify: PASS +; CHECK-EACH-REPEAT-CHECK: CheckFunctionDebugify: PASS +; CHECK-EACH-REPEAT-CHECK: CheckFunctionDebugify: PASS + +; --- Debugify-each failure case +; CHECK-EACH-FAIL: ERROR: Instruction with empty DebugLoc -- ret void +; CHECK-EACH-FAIL: ERROR: Instruction with empty DebugLoc -- call void @foo() +; CHECK-EACH-FAIL: ERROR: Instruction with empty DebugLoc -- {{.*}} add i32 0, 1 +; CHECK-EACH-FAIL: ERROR: Instruction with empty DebugLoc -- ret i32 0 +; CHECK-EACH-FAIL: WARNING: Missing line 1 +; CHECK-EACH-FAIL: WARNING: Missing line 2 +; CHECK-EACH-FAIL: WARNING: Missing line 3 +; CHECK-EACH-FAIL: WARNING: Missing line 4 +; CHECK-EACH-FAIL: ERROR: Missing variable 1 +; CHECK-EACH-FAIL: CheckModuleDebugify: FAIL +; CHECK-EACH-FAIL: CheckFunctionDebugify: PASS +; CHECK-EACH-FAIL: CheckFunctionDebugify: PASS +; CHECK-EACH-FAIL: CheckFunctionDebugify: PASS Index: test/Transforms/Mem2Reg/PromoteMemToRegister.ll =================================================================== --- test/Transforms/Mem2Reg/PromoteMemToRegister.ll +++ test/Transforms/Mem2Reg/PromoteMemToRegister.ll @@ -2,7 +2,7 @@ ; RUN: opt < %s -debugify -mem2reg -check-debugify -S | FileCheck %s ; CHECK-NOT: alloca -; CHECK: CheckDebugify: PASS +; CHECK: CheckModuleDebugify: PASS define double @testfunc(i32 %i, double %j) { %I = alloca i32 ; [#uses=4] Index: tools/opt/Debugify.cpp =================================================================== --- tools/opt/Debugify.cpp +++ tools/opt/Debugify.cpp @@ -39,201 +39,376 @@ return F.isDeclaration() || !F.hasExactDefinition(); } -bool applyDebugifyMetadata(Module &M) { +DIType *getCachedDIType(uint64_t Size, + DIBuilder &DIB, + DenseMap &Cache) { + DIType *&DTy = Cache[Size]; + if (!DTy) { + std::string Name = "ty" + utostr(Size); + DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned); + } + return DTy; +} + +/// Track the number of distinct lines and variables. +void insertLineAndVarCounters(unsigned NextLine, + unsigned NextVar, + Module &M) { + LLVMContext &Ctx = M.getContext(); + NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify"); + auto *IntTy = Type::getInt32Ty(Ctx); + auto addDebugifyOperand = [&](unsigned N) { + NMD->addOperand(MDNode::get( + Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N)))); + }; + addDebugifyOperand(NextLine - 1); // Original number of lines. + addDebugifyOperand(NextVar - 1); // Original number of variables. +} + +bool applyFunctionDebugifyMetadata(Function &F, + DIBuilder &DIB, + DICompileUnit *CU, + unsigned &NextLine, + unsigned &NextVar, + DenseMap &Cache) { + if (isFunctionSkipped(F)) + return false; + + Module *M = F.getParent(); + LLVMContext &Ctx = M->getContext(); + DIFile* File = CU->getFile(); + + // Visit each instruction. + auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); + bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage(); + auto SP = + DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType, + IsLocalToUnit, /*isDefinition=*/true, NextLine, + DINode::FlagZero, /*isOptimized=*/true); + F.setSubprogram(SP); + for (BasicBlock &BB : F) { + // Attach debug locations. + for (Instruction &I : BB) + I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP)); + + // Attach debug values. + for (Instruction &I : BB) { + // Skip void-valued instructions. + if (I.getType()->isVoidTy()) + continue; + + // Skip the terminator instruction and any just-inserted intrinsics. + if (isa(&I) || isa(&I)) + break; + + std::string Name = utostr(NextVar++); + const DILocation *Loc = I.getDebugLoc().get(); + Type *Ty = I.getType(); + uint64_t Size = Ty->isSized() ? M->getDataLayout().getTypeAllocSizeInBits(Ty) : 0; + auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(), + getCachedDIType(Size, DIB, Cache), + /*AlwaysPreserve=*/true); + DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc, + BB.getTerminator()); + } + } + DIB.finalizeSubprogram(SP); + return true; +} + +bool applyModuleDebugifyMetadata(Module &M) { // Skip modules with debug info. if (M.getNamedMetadata("llvm.dbg.cu")) { - errs() << "Debugify: Skipping module with debug info\n"; + errs() << "ModuleDebugify: Skipping module with debug info\n"; return false; } DIBuilder DIB(M); - LLVMContext &Ctx = M.getContext(); // Get a DIType which corresponds to Ty. DenseMap TypeCache; - auto getCachedDIType = [&](Type *Ty) -> DIType * { - uint64_t Size = - Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0; - DIType *&DTy = TypeCache[Size]; - if (!DTy) { - std::string Name = "ty" + utostr(Size); - DTy = DIB.createBasicType(Name, Size, dwarf::DW_ATE_unsigned); - } - return DTy; - }; unsigned NextLine = 1; unsigned NextVar = 1; - auto File = DIB.createFile(M.getName(), "/"); auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C, DIB.createFile(M.getName(), "/"), "debugify", /*isOptimized=*/true, "", 0); // Visit each instruction. - for (Function &F : M) { - if (isFunctionSkipped(F)) - continue; + for (Function &F : M) + applyFunctionDebugifyMetadata(F, DIB, CU, NextLine, NextVar, TypeCache); - auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None)); - bool IsLocalToUnit = F.hasPrivateLinkage() || F.hasInternalLinkage(); - auto SP = - DIB.createFunction(CU, F.getName(), F.getName(), File, NextLine, SPType, - IsLocalToUnit, /*isDefinition=*/true, NextLine, - DINode::FlagZero, /*isOptimized=*/true); - F.setSubprogram(SP); - for (BasicBlock &BB : F) { - // Attach debug locations. - for (Instruction &I : BB) - I.setDebugLoc(DILocation::get(Ctx, NextLine++, 1, SP)); - - // Attach debug values. - for (Instruction &I : BB) { - // Skip void-valued instructions. - if (I.getType()->isVoidTy()) - continue; - - // Skip the terminator instruction and any just-inserted intrinsics. - if (isa(&I) || isa(&I)) - break; - - std::string Name = utostr(NextVar++); - const DILocation *Loc = I.getDebugLoc().get(); - auto LocalVar = DIB.createAutoVariable(SP, Name, File, Loc->getLine(), - getCachedDIType(I.getType()), - /*AlwaysPreserve=*/true); - DIB.insertDbgValueIntrinsic(&I, LocalVar, DIB.createExpression(), Loc, - BB.getTerminator()); - } - } - DIB.finalizeSubprogram(SP); - } DIB.finalize(); - // Track the number of distinct lines and variables. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.debugify"); - auto *IntTy = Type::getInt32Ty(Ctx); - auto addDebugifyOperand = [&](unsigned N) { - NMD->addOperand(MDNode::get( - Ctx, ValueAsMetadata::getConstant(ConstantInt::get(IntTy, N)))); - }; - addDebugifyOperand(NextLine - 1); // Original number of lines. - addDebugifyOperand(NextVar - 1); // Original number of variables. + insertLineAndVarCounters(NextLine, NextVar, M); return true; } -void checkDebugifyMetadata(Module &M) { - // Skip modules without debugify metadata. - NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify"); - if (!NMD) - return; +bool checkFunctionDebugifyMetadata(Function &F, + BitVector &MissingLines, + BitVector &MissingVars) { + if (isFunctionSkipped(F)) + return false; - auto getDebugifyOperand = [&](unsigned Idx) -> unsigned { - return mdconst::extract(NMD->getOperand(Idx)->getOperand(0)) - ->getZExtValue(); - }; - unsigned OriginalNumLines = getDebugifyOperand(0); - unsigned OriginalNumVars = getDebugifyOperand(1); bool HasErrors = false; // Find missing lines. - BitVector MissingLines{OriginalNumLines, true}; - for (Function &F : M) { - if (isFunctionSkipped(F)) + for (Instruction &I : instructions(F)) { + if (isa(&I)) continue; - for (Instruction &I : instructions(F)) { - if (isa(&I)) - continue; - - auto DL = I.getDebugLoc(); - if (DL) { - MissingLines.reset(DL.getLine() - 1); - continue; - } + auto DL = I.getDebugLoc(); + if (DL && MissingLines.size() > (DL.getLine() - 1)) { + MissingLines.reset(DL.getLine() - 1); + continue; + } + if (DL) + outs() << "ERROR: Instruction with invalid DebugLoc -- "; + else outs() << "ERROR: Instruction with empty DebugLoc -- "; - I.print(outs()); - outs() << "\n"; - HasErrors = true; - } + I.print(outs()); + outs() << "\n"; + HasErrors = true; } - for (unsigned Idx : MissingLines.set_bits()) - outs() << "WARNING: Missing line " << Idx + 1 << "\n"; // Find missing variables. - BitVector MissingVars{OriginalNumVars, true}; - for (Function &F : M) { - if (isFunctionSkipped(F)) + for (Instruction &I : instructions(F)) { + auto *DVI = dyn_cast(&I); + if (!DVI) continue; - for (Instruction &I : instructions(F)) { - auto *DVI = dyn_cast(&I); - if (!DVI) - continue; - - unsigned Var = ~0U; - (void)to_integer(DVI->getVariable()->getName(), Var, 10); - assert(Var <= OriginalNumVars && "Unexpected name for DILocalVariable"); - MissingVars.reset(Var - 1); - } + unsigned Var = ~0U; + (void)to_integer(DVI->getVariable()->getName(), Var, 10); + assert(Var <= MissingVars.size() && "Unexpected name for DILocalVariable"); + MissingVars.reset(Var - 1); } + + return HasErrors; +} + +void printCheckDebugifyResults(std::string Conclusion, + BitVector MissingLines, + BitVector MissingVars) { + for (unsigned Idx : MissingLines.set_bits()) + outs() << "WARNING: Missing line " << Idx + 1 << "\n"; + for (unsigned Idx : MissingVars.set_bits()) outs() << "ERROR: Missing variable " << Idx + 1 << "\n"; + + outs() << Conclusion << '\n'; +} + +void stripDebugifyMetadata(Module &M) { + NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify"); + StripDebugInfo(M); + M.eraseNamedMetadata(NMD); + if (Function *F = M.getFunction("llvm.dbg.value")) { + F->replaceAllUsesWith(UndefValue::get((Type*)F->getType())); + F->eraseFromParent(); + } +} + +unsigned getDebugifyOperand(NamedMDNode *NMD, unsigned Idx) { + return mdconst::extract(NMD->getOperand(Idx)->getOperand(0)) + ->getZExtValue(); +} + +void checkModuleDebugifyMetadata(Module &M) { + // Skip modules without debugify metadata. + NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify"); + if (!NMD) { + errs() << "CheckModuleDebugify: " + << "Skipping module without debugify metadata\n"; + return; + } + + unsigned OriginalNumLines = getDebugifyOperand(NMD, 0); + unsigned OriginalNumVars = getDebugifyOperand(NMD, 1); + bool HasErrors = false; + + BitVector MissingLines{OriginalNumLines, true}; + BitVector MissingVars{OriginalNumVars, true}; + for (Function &F : M) + HasErrors |= checkFunctionDebugifyMetadata(F, MissingLines, MissingVars); + HasErrors |= MissingVars.count() > 0; - outs() << "CheckDebugify: " << (HasErrors ? "FAIL" : "PASS") << "\n"; + std::string Conclusion = + "CheckModuleDebugify: " + (HasErrors ? std::string("FAIL") + : std::string("PASS")); + printCheckDebugifyResults(Conclusion, MissingLines, MissingVars); } -/// Attach synthetic debug info to everything. -struct DebugifyPass : public ModulePass { - bool runOnModule(Module &M) override { return applyDebugifyMetadata(M); } +/// ModulePass for attaching synthetic debug info to everything, used with the +/// legacy module pass manager. +struct DebugifyModulePass : public ModulePass { + bool runOnModule(Module &M) override { return applyModuleDebugifyMetadata(M); } + + DebugifyModulePass() : ModulePass(ID) {} + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesAll(); + } + + static char ID; // Pass identification. +}; + +/// FunctionPass for attaching synthetic debug info to everything, used with the +/// legacy module pass manager. +struct DebugifyFunctionPass : public FunctionPass { + bool runOnFunction(Function &F) override { + if (!ShouldApply) + return false; + + Module *M = F.getParent(); + unsigned NextLine = 1; + unsigned NextVar = 1; + DIBuilder DIB(*M); + DICompileUnit *CU = DIB.createCompileUnit(dwarf::DW_LANG_C, + DIB.createFile(M->getName(), "/"), + "debugify", /*isOptimized=*/true, "", 0); + + bool Changed = applyFunctionDebugifyMetadata(F, DIB, CU, NextLine, NextVar, TypeCache); + + insertLineAndVarCounters(NextLine, NextVar, *M); + return Changed; + } + + bool doInitialization(Module &M) override { + ShouldApply = (M.getNamedMetadata("llvm.dbg.cu") == nullptr); + if (!ShouldApply) + errs() << "FunctionDebugify: Skipping module with debug info\n"; + return false; + } - DebugifyPass() : ModulePass(ID) {} + DebugifyFunctionPass() : FunctionPass(ID) {} void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } static char ID; // Pass identification. + +private: + bool ShouldApply; + DenseMap TypeCache; }; -/// Check debug info inserted by -debugify for completeness. -struct CheckDebugifyPass : public ModulePass { +/// ModulePass for checking debug info inserted by -debugify, used with the +/// legacy module pass manager. +struct CheckDebugifyModulePass : public ModulePass { bool runOnModule(Module &M) override { - checkDebugifyMetadata(M); + checkModuleDebugifyMetadata(M); + if (Strip) { + stripDebugifyMetadata(M); + return true; + } + return false; } - CheckDebugifyPass() : ModulePass(ID) {} + CheckDebugifyModulePass(bool Strip = false) : ModulePass(ID) { + this->Strip = Strip; + } + + static char ID; // Pass identification. + +private: + bool Strip; +}; + +/// FunctionPass for checking debug info inserted by -debugify-function, used +/// with the legacy module pass manager. +struct CheckDebugifyFunctionPass : public FunctionPass { + bool runOnFunction(Function &F) override { + Module *M = F.getParent(); + NamedMDNode *NMD = M->getNamedMetadata("llvm.debugify"); + if (!NMD) { + errs() << "CheckFunctionDebugify: " + << "Skipping module without debugify metadata\n"; + return false; + } + + unsigned OriginalNumLines = getDebugifyOperand(NMD, 0); + unsigned OriginalNumVars = getDebugifyOperand(NMD, 1); + + BitVector MissingLines{OriginalNumLines, true}; + BitVector MissingVars{OriginalNumVars, true}; + + bool HasErrors = checkFunctionDebugifyMetadata(F, + MissingLines, + MissingVars); + HasErrors |= MissingVars.count() > 0; + + std::string Conclusion = + "CheckFunctionDebugify: " + (HasErrors ? std::string("FAIL") + : std::string("PASS")); + printCheckDebugifyResults(Conclusion, MissingLines, MissingVars); + + if (Strip) { + stripDebugifyMetadata(*M); + return true; + } + + return false; + } + + CheckDebugifyFunctionPass(bool Strip = false) : FunctionPass(ID) { + this->Strip = Strip; + } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } static char ID; // Pass identification. + +private: + bool Strip; }; } // end anonymous namespace -ModulePass *createDebugifyPass() { return new DebugifyPass(); } +ModulePass *createDebugifyModulePass() { + return new DebugifyModulePass(); +} + +FunctionPass *createDebugifyFunctionPass() { + return new DebugifyFunctionPass(); +} PreservedAnalyses NewPMDebugifyPass::run(Module &M, ModuleAnalysisManager &) { - applyDebugifyMetadata(M); + applyModuleDebugifyMetadata(M); return PreservedAnalyses::all(); } -ModulePass *createCheckDebugifyPass() { return new CheckDebugifyPass(); } +ModulePass *createCheckDebugifyModulePass(bool Strip) { + return new CheckDebugifyModulePass(Strip); +} + +FunctionPass *createCheckDebugifyFunctionPass(bool Strip) { + return new CheckDebugifyFunctionPass(Strip); +} PreservedAnalyses NewPMCheckDebugifyPass::run(Module &M, ModuleAnalysisManager &) { - checkDebugifyMetadata(M); + checkModuleDebugifyMetadata(M); return PreservedAnalyses::all(); } -char DebugifyPass::ID = 0; -static RegisterPass X("debugify", +char DebugifyModulePass::ID = 0; +static RegisterPass DM("debugify", "Attach debug info to everything"); -char CheckDebugifyPass::ID = 0; -static RegisterPass Y("check-debugify", +char CheckDebugifyModulePass::ID = 0; +static RegisterPass CDM("check-debugify", "Check debug info from -debugify"); + +char DebugifyFunctionPass::ID = 0; +static RegisterPass DF("debugify-function", + "Attach debug info to a function"); + +char CheckDebugifyFunctionPass::ID = 0; +static RegisterPass CDF("check-debugify-function", + "Check debug info from -debugify-function"); Index: tools/opt/PassPrinters.h =================================================================== --- tools/opt/PassPrinters.h +++ tools/opt/PassPrinters.h @@ -49,17 +49,21 @@ } // end namespace llvm -llvm::ModulePass *createDebugifyPass(); +llvm::ModulePass *createDebugifyModulePass(); +llvm::FunctionPass *createDebugifyFunctionPass(); struct NewPMDebugifyPass : public llvm::PassInfoMixin { llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM); }; -llvm::ModulePass *createCheckDebugifyPass(); +llvm::ModulePass *createCheckDebugifyModulePass(bool Strip = false); +llvm::FunctionPass *createCheckDebugifyFunctionPass(bool Strip = false); struct NewPMCheckDebugifyPass : public llvm::PassInfoMixin { llvm::PreservedAnalyses run(llvm::Module &M, llvm::ModuleAnalysisManager &AM); }; +llvm::ModulePass *createStripDbgInfoPass(); + #endif // LLVM_TOOLS_OPT_PASSPRINTERS_H Index: tools/opt/opt.cpp =================================================================== --- tools/opt/opt.cpp +++ tools/opt/opt.cpp @@ -207,6 +207,11 @@ cl::desc( "Start the pipeline with debugify and end it with check-debugify")); +static cl::opt DebugifyEach( + "debugify-each", + cl::desc( + "Start each pass with debugify and end it with check-debugify")); + static cl::opt PrintBreakpoints("print-breakpoints-for-testing", cl::desc("Print select breakpoints location for testing")); @@ -256,6 +261,65 @@ cl::desc("YAML output filename for pass remarks"), cl::value_desc("filename")); +class DebugifyEachPassManager : public legacy::PassManager { + bool DebugifyEach; + +public: + DebugifyEachPassManager(bool DebugifyEach) : legacy::PassManager(), + DebugifyEach(DebugifyEach) {} + + void add(Pass *P) override { + if (!DebugifyEach) { + PassManager::add(P); + return; + } + + // Do not debugify ImmutablePass + if (P->getAsImmutablePass()) { + PassManager::add(P); + } + // Do not debugify PrinterPass + else if (P->getPassName() == "Print Module IR") { + PassManager::add(P); + } else { + PassKind Kind = P->getPassKind(); + switch (Kind) { + case PT_BasicBlock: + PassManager::add(P); + break; + case PT_Region: + PassManager::add(P); + break; + case PT_Loop: + PassManager::add(P); + break; + case PT_Function: + PassManager::add(createDebugifyFunctionPass()); + PassManager::add(P); + PassManager::add(createCheckDebugifyFunctionPass(true)); + break; + case PT_CallGraphSCC: + PassManager::add(P); + break; + case PT_Module: + PassManager::add(createDebugifyModulePass()); + PassManager::add(P); + PassManager::add(createCheckDebugifyModulePass(true)); + break; + case PT_PassManager: + PassManager::add(P); + break; + default: + break; + } + } + } + + bool run(Module &M) { + return PassManager::run(M); + } +}; + static inline void addPass(legacy::PassManagerBase &PM, Pass *P) { // Add the pass to the pass manager... PM.add(P); @@ -556,8 +620,7 @@ // Create a PassManager to hold and optimize the collection of passes we are // about to build. - // - legacy::PassManager Passes; + DebugifyEachPassManager Passes(DebugifyEach); // Add an appropriate TargetLibraryInfo pass for the module's triple. TargetLibraryInfoImpl TLII(ModuleTriple); @@ -571,8 +634,8 @@ Passes.add(createTargetTransformInfoWrapperPass(TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())); - if (EnableDebugify) - Passes.add(createDebugifyPass()); + if (EnableDebugify && !DebugifyEach) + Passes.add(createDebugifyModulePass()); std::unique_ptr FPasses; if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || @@ -719,8 +782,8 @@ if (!NoVerify && !VerifyEach) Passes.add(createVerifierPass()); - if (EnableDebugify) - Passes.add(createCheckDebugifyPass()); + if (EnableDebugify && !DebugifyEach) + Passes.add(createCheckDebugifyModulePass(false)); // In run twice mode, we want to make sure the output is bit-by-bit // equivalent if we run the pass manager again, so setup two buffers and