When the user hits ctrl-c, bugpoint should attempt to stop reduction as

quickly as possible and output what it has so far.  If they hit it twice,
bugpoint is killed.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22579 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2005-08-02 02:16:17 +00:00
parent fa8c292ebd
commit f9aaae06cd
5 changed files with 59 additions and 30 deletions

View File

@ -35,6 +35,10 @@ class GCC;
extern bool DisableSimplifyCFG;
/// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
///
extern bool BugpointIsInterrupted;
class BugDriver {
const std::string ToolName; // Name of bugpoint
std::string ReferenceOutputFile; // Name of `good' output file

View File

@ -261,8 +261,6 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) {
/// on a program, try to destructively reduce the program while still keeping
/// the predicate true.
static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
bool AnyReduction = false;
// See if we can get away with nuking all of the global variable initializers
// in the program...
if (BD.getProgram()->global_begin() != BD.getProgram()->global_end()) {
@ -282,7 +280,6 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
std::cout << "\nChecking to see if we can delete global inits: ";
if (TestFn(BD, M)) { // Still crashes?
BD.setNewProgram(M);
AnyReduction = true;
std::cout << "\n*** Able to remove all global initializers!\n";
} else { // No longer crashes?
std::cout << " - Removing all global inits hides problem!\n";
@ -298,17 +295,15 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
if (!I->isExternal())
Functions.push_back(I);
if (Functions.size() > 1) {
if (Functions.size() > 1 && !BugpointIsInterrupted) {
std::cout << "\n*** Attempting to reduce the number of functions "
"in the testcase\n";
unsigned OldSize = Functions.size();
ReduceCrashingFunctions(BD, TestFn).reduceList(Functions);
if (Functions.size() < OldSize) {
if (Functions.size() < OldSize)
BD.EmitProgressBytecode("reduced-function");
AnyReduction = true;
}
}
// Attempt to delete entire basic blocks at a time to speed up
@ -316,7 +311,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
// to a return instruction then running simplifycfg, which can potentially
// shrinks the code dramatically quickly
//
if (!DisableSimplifyCFG) {
if (!DisableSimplifyCFG && !BugpointIsInterrupted) {
std::vector<const BasicBlock*> Blocks;
for (Module::const_iterator I = BD.getProgram()->begin(),
E = BD.getProgram()->end(); I != E; ++I)
@ -329,6 +324,7 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
// larger chunks of instructions at a time!
unsigned Simplification = 2;
do {
if (BugpointIsInterrupted) break;
--Simplification;
std::cout << "\n*** Attempting to reduce testcase by deleting instruc"
<< "tions: Simplification Level #" << Simplification << '\n';
@ -357,6 +353,8 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
if (InstructionsToSkipBeforeDeleting) {
--InstructionsToSkipBeforeDeleting;
} else {
if (BugpointIsInterrupted) goto ExitLoops;
std::cout << "Checking instruction '" << I->getName() << "': ";
Module *M = BD.deleteInstructionFromProgram(I, Simplification);
@ -365,7 +363,6 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
// Yup, it does, we delete the old module, and continue trying
// to reduce the testcase...
BD.setNewProgram(M);
AnyReduction = true;
InstructionsToSkipBeforeDeleting = CurInstructionNum;
goto TryAgain; // I wish I had a multi-level break here!
}
@ -381,22 +378,23 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) {
}
} while (Simplification);
ExitLoops:
// Try to clean up the testcase by running funcresolve and globaldce...
std::cout << "\n*** Attempting to perform final cleanups: ";
Module *M = CloneModule(BD.getProgram());
M = BD.performFinalCleanups(M, true);
if (!BugpointIsInterrupted) {
std::cout << "\n*** Attempting to perform final cleanups: ";
Module *M = CloneModule(BD.getProgram());
M = BD.performFinalCleanups(M, true);
// Find out if the pass still crashes on the cleaned up program...
if (TestFn(BD, M)) {
BD.setNewProgram(M); // Yup, it does, keep the reduced version...
AnyReduction = true;
} else {
delete M;
// Find out if the pass still crashes on the cleaned up program...
if (TestFn(BD, M)) {
BD.setNewProgram(M); // Yup, it does, keep the reduced version...
} else {
delete M;
}
}
if (AnyReduction)
BD.EmitProgressBytecode("reduced-simplified");
BD.EmitProgressBytecode("reduced-simplified");
return false;
}
@ -414,7 +412,8 @@ bool BugDriver::debugOptimizerCrash() {
// Reduce the list of passes which causes the optimizer to crash...
unsigned OldSize = PassesToRun.size();
ReducePassList(*this).reduceList(PassesToRun);
if (!BugpointIsInterrupted)
ReducePassList(*this).reduceList(PassesToRun);
std::cout << "\n*** Found crashing pass"
<< (PassesToRun.size() == 1 ? ": " : "es: ")

View File

@ -19,6 +19,8 @@
#include <iostream>
namespace llvm {
extern bool BugpointIsInterrupted;
template<typename ElTy>
struct ListReducer {
@ -62,6 +64,12 @@ struct ListReducer {
unsigned MidTop = TheList.size();
while (MidTop > 1) {
// Halt if the user presses ctrl-c.
if (BugpointIsInterrupted) {
std::cerr << "\n\n*** Reduction Interrupted, cleaning up...\n\n";
return true;
}
unsigned Mid = MidTop / 2;
std::vector<ElTy> Prefix(TheList.begin(), TheList.begin()+Mid);
std::vector<ElTy> Suffix(TheList.begin()+Mid, TheList.end());
@ -97,6 +105,11 @@ struct ListReducer {
Changed = false;
std::vector<ElTy> TrimmedList;
for (unsigned i = 1; i < TheList.size()-1; ++i) { // Check interior elts
if (BugpointIsInterrupted) {
std::cerr << "\n\n*** Reduction Interrupted, cleaning up...\n\n";
return true;
}
std::vector<ElTy> TestList(TheList);
TestList.erase(TestList.begin()+i);

View File

@ -407,6 +407,8 @@ bool ReduceMiscompiledBlocks::TestFuncs(const std::vector<BasicBlock*> &BBs) {
static bool ExtractBlocks(BugDriver &BD,
bool (*TestFn)(BugDriver &, Module *, Module *),
std::vector<Function*> &MiscompiledFunctions) {
if (BugpointIsInterrupted) return false;
std::vector<BasicBlock*> Blocks;
for (unsigned i = 0, e = MiscompiledFunctions.size(); i != e; ++i)
for (Function::iterator I = MiscompiledFunctions[i]->begin(),
@ -493,7 +495,8 @@ DebugAMiscompilation(BugDriver &BD,
MiscompiledFunctions.push_back(I);
// Do the reduction...
ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
if (!BugpointIsInterrupted)
ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
std::cout << "\n*** The following function"
<< (MiscompiledFunctions.size() == 1 ? " is" : "s are")
@ -513,7 +516,8 @@ DebugAMiscompilation(BugDriver &BD,
DisambiguateGlobalSymbols(BD.getProgram());
// Do the reduction...
ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
if (!BugpointIsInterrupted)
ReduceMiscompilingFunctions(BD, TestFn).reduceList(MiscompiledFunctions);
std::cout << "\n*** The following function"
<< (MiscompiledFunctions.size() == 1 ? " is" : "s are")
@ -570,11 +574,12 @@ static bool TestOptimizer(BugDriver &BD, Module *Test, Module *Safe) {
///
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;
}
if (!BugpointIsInterrupted)
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") << ": "
@ -663,7 +668,7 @@ static void CleanupAndPrepareModules(BugDriver &BD, Module *&Test,
for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
if (F->isExternal() && !F->use_empty() && &*F != resolverFunc &&
F->getIntrinsicID() == 0 /* ignore intrinsics */) {
Function *TestFn = Test->getFunction(F->getName(), F->getFunctionType());
Function *TestFn = Test->getNamedFunction(F->getName());
// Don't forward functions which are external in the test module too.
if (TestFn && !TestFn->isExternal()) {

View File

@ -32,13 +32,21 @@ InputFilenames(cl::Positional, cl::OneOrMore,
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Passes available:"), cl::ZeroOrMore);
/// BugpointIsInterrupted - Set to true when the user presses ctrl-c.
bool llvm::BugpointIsInterrupted = false;
static void BugpointInterruptFunction() {
BugpointIsInterrupted = true;
}
int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv,
" LLVM automatic testcase reducer. See\nhttp://"
"llvm.cs.uiuc.edu/docs/CommandGuide/bugpoint.html"
" for more information.\n");
sys::PrintStackTraceOnErrorSignal();
sys::SetInterruptFunction(BugpointInterruptFunction);
BugDriver D(argv[0]);
if (D.addSources(InputFilenames)) return 1;
D.addPasses(PassList.begin(), PassList.end());