diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index 3dbb84dab65..f88d29ffb77 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -125,6 +125,12 @@ private: /// Module *deleteInstructionFromProgram(Instruction *I, unsigned Simp) const; + /// performFinalCleanups - This method clones the current Program and performs + /// a series of cleanups intended to get rid of extra cruft on the module + /// before handing it to the user... + /// + Module *performFinalCleanups() const; + /// initializeExecutionEnvironment - This method is used to set up the /// environment for executing LLVM programs. /// diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index daf3915a5eb..315e1823ce0 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -84,6 +84,7 @@ static unsigned CountFunctions(Module *M) { /// bool BugDriver::debugPassCrash(const PassInfo *Pass) { EmitProgressBytecode(Pass, "passinput"); + bool Reduced = false, AnyReduction = false; if (CountFunctions(Program) > 1) { // Attempt to reduce the input program down to a single function that still @@ -106,7 +107,7 @@ bool BugDriver::debugPassCrash(const PassInfo *Pass) { // reduce the testcase... delete M; - EmitProgressBytecode(Pass, "reduced-"+I->getName()); + Reduced = AnyReduction = true; break; } @@ -122,6 +123,11 @@ bool BugDriver::debugPassCrash(const PassInfo *Pass) { } } + if (Reduced) { + EmitProgressBytecode(Pass, "reduced-function"); + Reduced = false; + } + // FIXME: This should attempt to delete entire basic blocks at a time to speed // up convergence... @@ -159,8 +165,8 @@ bool BugDriver::debugPassCrash(const PassInfo *Pass) { if (runPass(Pass)) { // Yup, it does, we delete the old module, and continue trying to // reduce the testcase... - EmitProgressBytecode(Pass, "reduced-" + I->getName()); delete M; + Reduced = AnyReduction = true; goto TryAgain; // I wish I had a multi-level break here! } @@ -171,6 +177,28 @@ bool BugDriver::debugPassCrash(const PassInfo *Pass) { } } } while (Simplification); - + + // Try to clean up the testcase by running funcresolve and globaldce... + if (AnyReduction) { + std::cout << "\n*** Attempting to perform final cleanups: "; + Module *M = performFinalCleanups(); + std::swap(Program, M); + + // Find out if the pass still crashes on the cleaned up program... + if (runPass(Pass)) { + // Yup, it does, keep the reduced version... + delete M; + Reduced = AnyReduction = true; + } else { + delete Program; // Otherwise, restore the original module... + Program = M; + } + } + + if (Reduced) { + EmitProgressBytecode(Pass, "reduced-simplified"); + Reduced = false; + } + return false; } diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 9b5440c0d4e..c99c8f32b5f 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -81,3 +81,16 @@ Module *BugDriver::deleteInstructionFromProgram(Instruction *I, Passes.run(*Result); return Result; } + +/// performFinalCleanups - This method clones the current Program and performs +/// a series of cleanups intended to get rid of extra cruft on the module +/// before handing it to the user... +/// +Module *BugDriver::performFinalCleanups() const { + PassManager CleanupPasses; + CleanupPasses.add(createFunctionResolvingPass()); + CleanupPasses.add(createGlobalDCEPass()); + Module *M = CloneModule(Program); + CleanupPasses.run(*M); + return M; +}