diff --git a/tools/bugpoint/CodeGeneratorBug.cpp b/tools/bugpoint/CodeGeneratorBug.cpp index 597d580432e..abd940b34bf 100644 --- a/tools/bugpoint/CodeGeneratorBug.cpp +++ b/tools/bugpoint/CodeGeneratorBug.cpp @@ -20,11 +20,14 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Linker.h" +#include "Support/CommandLine.h" #include "Support/Statistic.h" #include "Support/StringExtras.h" #include #include +extern cl::list InputArgv; + class ReduceMisCodegenFunctions : public ListReducer { BugDriver &BD; public: @@ -47,10 +50,9 @@ public: bool ReduceMisCodegenFunctions::TestFuncs(const std::vector &Funcs, bool KeepFiles) { - DEBUG(std::cerr << "Test functions are:\n"); - for (std::vector::const_iterator I = Funcs.begin(),E = Funcs.end(); - I != E; ++I) - DEBUG(std::cerr << "\t" << (*I)->getName() << "\n"); + std::cout << "Testing functions: "; + BD.PrintFunctionList(Funcs); + std::cout << "\t"; // Clone the module for the two halves of the program we want. Module *SafeModule = CloneModule(BD.Program); @@ -150,7 +152,7 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector &Funcs, // cast the result from the resolver to correctly-typed function CastInst *castResolver = new CastInst(resolve, PointerType::get(F->getFunctionType()), - "", Inst); + "resolverCast", Inst); // actually use the resolved function Inst->replaceUsesOfWith(F, castResolver); } else { @@ -227,8 +229,12 @@ bool ReduceMisCodegenFunctions::TestFuncs(const std::vector &Funcs, if (KeepFiles) { std::cout << "You can reproduce the problem with the command line: \n" << (BD.isExecutingJIT() ? "lli" : "llc") - << " -load " << SharedObject << " " << TestModuleBC - << "\n"; + << " -load " << SharedObject << " " << TestModuleBC; + for (unsigned i=0, e = InputArgv.size(); i != e; ++i) + std::cout << " " << InputArgv[i]; + std::cout << "\n"; + std::cout << "The shared object " << SharedObject << " was created from " + << SafeModuleBC << ", using `dis -c'.\n"; } else { removeFile(TestModuleBC); removeFile(SafeModuleBC); @@ -346,7 +352,11 @@ bool BugDriver::debugCodeGenerator() { DisambiguateGlobalSymbols(Program); // Do the reduction... - ReduceMisCodegenFunctions(*this).reduceList(MisCodegenFunctions); + if (!ReduceMisCodegenFunctions(*this).reduceList(MisCodegenFunctions)) { + std::cerr << "*** Execution matches reference output! No problem " + << "detected...\nbugpoint can't help you with your problem!\n"; + return false; + } std::cout << "\n*** The following functions are being miscompiled: "; PrintFunctionList(MisCodegenFunctions); diff --git a/tools/bugpoint/ListReducer.h b/tools/bugpoint/ListReducer.h index a4dee5bc587..cee68926c9c 100644 --- a/tools/bugpoint/ListReducer.h +++ b/tools/bugpoint/ListReducer.h @@ -30,7 +30,24 @@ struct ListReducer { // list while still maintaining the "test" property. This is the core of the // "work" that bugpoint does. // - void reduceList(std::vector &TheList) { + bool reduceList(std::vector &TheList) { + std::vector empty; + switch (doTest(TheList, empty)) { + case KeepPrefix: + if (TheList.size() == 1) // we are done, it's the base case and it fails + return true; + else + break; // there's definitely an error, but we need to narrow it down + + case KeepSuffix: + // cannot be reached! + std::cerr << "bugpoint ListReducer internal error: selected empty set.\n"; + abort(); + + case NoFailure: + return false; // there is no failure with the full set of passes/funcs! + } + unsigned MidTop = TheList.size(); while (MidTop > 1) { unsigned Mid = MidTop / 2; @@ -80,6 +97,8 @@ struct ListReducer { } } } + + return true; // there are some failure and we've narrowed them down } }; diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index 833dd437b63..b65b4a6a678 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -268,12 +268,8 @@ bool BugDriver::debugMiscompilation() { return false; // Problem found } - // Figure out which transformations miscompile the input program. - unsigned OldSize = PassesToRun.size(); - ReduceMiscompilingPasses(*this).reduceList(PassesToRun); - // Make sure something was miscompiled... - if (PassesToRun.size() == OldSize) { + 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;