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
/// 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()) {
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";
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
// 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)
// 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';
if (InstructionsToSkipBeforeDeleting) {
--InstructionsToSkipBeforeDeleting;
} else {
+ if (BugpointIsInterrupted) goto ExitLoops;
+
std::cout << "Checking instruction '" << I->getName() << "': ";
Module *M = BD.deleteInstructionFromProgram(I, Simplification);
// 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!
}
}
} 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;
}
// 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: ")
#include <iostream>
namespace llvm {
+
+ extern bool BugpointIsInterrupted;
template<typename ElTy>
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());
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);
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(),
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")
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")
///
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") << ": "
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()) {
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());