mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
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. llvm-svn: 22579
This commit is contained in:
parent
2ba2324c96
commit
c7ffb0c713
@ -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
|
||||
|
@ -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: ")
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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()) {
|
||||
|
@ -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());
|
||||
|
Loading…
Reference in New Issue
Block a user