diff options
author | Chris Lattner <sabre@nondot.org> | 2004-04-05 21:37:38 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-04-05 21:37:38 +0000 |
commit | b15825b0a29e527b361b63a6e41aff5fdb8fdd5a (patch) | |
tree | 8b88b79f3530f3e5da98de397d5185e8b2e27477 /tools/bugpoint | |
parent | 8505c867b1ff74cded2cf8ec211584b965683388 (diff) | |
download | llvm-b15825b0a29e527b361b63a6e41aff5fdb8fdd5a.tar.gz llvm-b15825b0a29e527b361b63a6e41aff5fdb8fdd5a.tar.bz2 llvm-b15825b0a29e527b361b63a6e41aff5fdb8fdd5a.tar.xz |
Refactor and genericize code
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@12675 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/bugpoint')
-rw-r--r-- | tools/bugpoint/Miscompilation.cpp | 126 |
1 files changed, 71 insertions, 55 deletions
diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 0913caeb36..9b9a020c3f 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -124,8 +124,11 @@ ReduceMiscompilingPasses::doTest(std::vector<const PassInfo*> &Prefix, namespace { class ReduceMiscompilingFunctions : public ListReducer<Function*> { BugDriver &BD; + bool (*TestFn)(BugDriver &, Module *, Module *); public: - ReduceMiscompilingFunctions(BugDriver &bd) : BD(bd) {} + ReduceMiscompilingFunctions(BugDriver &bd, + bool (*F)(BugDriver &, Module *, Module *)) + : BD(bd), TestFn(F) {} virtual TestResult doTest(std::vector<Function*> &Prefix, std::vector<Function*> &Suffix) { @@ -183,25 +186,15 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector<Function*>&Funcs){ Module *ToNotOptimize = CloneModule(BD.getProgram()); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, Funcs); - // Run the optimization passes on ToOptimize, producing a transformed version - // of the functions being tested. - std::cout << " Optimizing functions being tested: "; - Module *Optimized = BD.runPassesOn(ToOptimize, BD.getPassesToRun(), - /*AutoDebugCrashes*/true); - std::cout << "done.\n"; - delete ToOptimize; - - - std::cout << " Checking to see if the merged program executes correctly: "; - bool Broken = TestMergedProgram(BD, Optimized, ToNotOptimize, true); - std::cout << (Broken ? " nope.\n" : " yup.\n"); - return Broken; + // Run the predicate, not that the predicate will delete both input modules. + return TestFn(BD, ToOptimize, ToNotOptimize); } /// ExtractLoops - Given a reduced list of functions that still exposed the bug, /// check to see if we can extract the loops in the region without obscuring the /// bug. If so, it reduces the amount of code identified. -static bool ExtractLoops(BugDriver &BD, +static bool ExtractLoops(BugDriver &BD, + bool (*TestFn)(BugDriver &, Module *, Module *), std::vector<Function*> &MiscompiledFunctions) { bool MadeChange = false; while (1) { @@ -235,27 +228,22 @@ static bool ExtractLoops(BugDriver &BD, return MadeChange; } - // Okay, the loop extractor didn't break the program. Run the series of - // optimizations on the loop extracted portion and see if THEY still break - // the program. If so, it was safe to extract these loops! - std::cout << " Running optimizations on loop extracted portion: "; - Module *Optimized = BD.runPassesOn(ToOptimizeLoopExtracted, - BD.getPassesToRun(), - /*AutoDebugCrashes*/true); - std::cout << "done.\n"; - - std::cout << " Checking to see if the merged program executes correctly: "; - bool Broken = TestMergedProgram(BD, Optimized, ToNotOptimize, false); - delete Optimized; - if (!Broken) { - std::cout << "yup: loop extraction masked the problem. Undoing.\n"; + std::cout << " Testing after loop extraction:\n"; + // Clone modules, the tester function will free them. + Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted); + Module *TNOBackup = CloneModule(ToNotOptimize); + if (!TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize)) { + std::cout << "*** Loop extraction masked the problem. Undoing.\n"; // If the program is not still broken, then loop extraction did something // that masked the error. Stop loop extraction now. - delete ToNotOptimize; - delete ToOptimizeLoopExtracted; + delete TOLEBackup; + delete TNOBackup; return MadeChange; } - std::cout << "nope: loop extraction successful!\n"; + ToOptimizeLoopExtracted = TOLEBackup; + ToNotOptimize = TNOBackup; + + std::cout << "*** Loop extraction successful!\n"; // Okay, great! Now we know that we extracted a loop and that loop // extraction both didn't break the program, and didn't mask the problem. @@ -288,34 +276,23 @@ static bool ExtractLoops(BugDriver &BD, } } -/// debugMiscompilation - This method is used when the passes selected are not -/// crashing, but the generated output is semantically different from the -/// input. -/// -bool BugDriver::debugMiscompilation() { - // Make sure something was miscompiled... - if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) { - std::cerr << "*** Optimized program matches reference output! No problem " - << "detected...\nbugpoint can't help you with your problem!\n"; - return false; - } - - std::cout << "\n*** Found miscompiling pass" - << (getPassesToRun().size() == 1 ? "" : "es") << ": " - << getPassesString(getPassesToRun()) << "\n"; - EmitProgressBytecode("passinput"); - +/// DebugAMiscompilation - This is a generic driver to narrow down +/// miscompilations, either in an optimization or a code generator. +static std::vector<Function*> +DebugAMiscompilation(BugDriver &BD, + bool (*TestFn)(BugDriver &, Module *, Module *)) { // Okay, now that we have reduced the list of passes which are causing the // failure, see if we can pin down which functions are being // miscompiled... first build a list of all of the non-external functions in // the program. std::vector<Function*> MiscompiledFunctions; - for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I) + Module *Prog = BD.getProgram(); + for (Module::iterator I = Prog->begin(), E = Prog->end(); I != E; ++I) if (!I->isExternal()) MiscompiledFunctions.push_back(I); // Do the reduction... - ReduceMiscompilingFunctions(*this).reduceList(MiscompiledFunctions); + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); std::cout << "\n*** The following function" << (MiscompiledFunctions.size() == 1 ? " is" : "s are") @@ -325,12 +302,12 @@ bool BugDriver::debugMiscompilation() { // See if we can rip any loops out of the miscompiled functions and still // trigger the problem. - if (ExtractLoops(*this, MiscompiledFunctions)) { + if (ExtractLoops(BD, TestFn, MiscompiledFunctions)) { // Okay, we extracted some loops and the problem still appears. See if we // can eliminate some of the created functions from being candidates. // Do the reduction... - ReduceMiscompilingFunctions(*this).reduceList(MiscompiledFunctions); + ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions); std::cout << "\n*** The following function" << (MiscompiledFunctions.size() == 1 ? " is" : "s are") @@ -339,6 +316,45 @@ bool BugDriver::debugMiscompilation() { std::cout << "\n"; } + return MiscompiledFunctions; +} + +static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe) { + // Run the optimization passes on ToOptimize, producing a transformed version + // of the functions being tested. + std::cout << " Optimizing functions being tested: "; + Module *Optimized = BD.runPassesOn(Test, BD.getPassesToRun(), + /*AutoDebugCrashes*/true); + std::cout << "done.\n"; + delete Test; + + std::cout << " Checking to see if the merged program executes correctly: "; + bool Broken = TestMergedProgram(BD, Test, Safe, true); + std::cout << (Broken ? " nope.\n" : " yup.\n"); + return Broken; +} + + +/// debugMiscompilation - This method is used when the passes selected are not +/// crashing, but the generated output is semantically different from the +/// input. +/// +bool BugDriver::debugMiscompilation() { + // Make sure something was miscompiled... + if (!ReduceMiscompilingPasses(*this).reduceList(PassesToRun)) { + std::cerr << "*** Optimized program matches reference output! No problem " + << "detected...\nbugpoint can't help you with your problem!\n"; + return false; + } + + std::cout << "\n*** Found miscompiling pass" + << (getPassesToRun().size() == 1 ? "" : "es") << ": " + << getPassesString(getPassesToRun()) << "\n"; + EmitProgressBytecode("passinput"); + + std::vector<Function*> MiscompiledFunctions = + DebugAMiscompilation(*this, TestOptimizer); + // Output a bunch of bytecode files for the user... std::cout << "Outputting reduced bytecode files which expose the problem:\n"; Module *ToNotOptimize = CloneModule(getProgram()); @@ -346,12 +362,12 @@ bool BugDriver::debugMiscompilation() { MiscompiledFunctions); std::cout << " Non-optimized portion: "; - std::swap(Program, ToNotOptimize); + ToNotOptimize = swapProgramIn(ToNotOptimize); EmitProgressBytecode("tonotoptimize", true); setNewProgram(ToNotOptimize); // Delete hacked module. std::cout << " Portion that is input to optimizer: "; - std::swap(Program, ToOptimize); + ToOptimize = swapProgramIn(ToOptimize); EmitProgressBytecode("tooptimize"); setNewProgram(ToOptimize); // Delete hacked module. |