diff options
author | Nick Lewycky <nicholas@mxc.ca> | 2009-05-25 05:30:00 +0000 |
---|---|---|
committer | Nick Lewycky <nicholas@mxc.ca> | 2009-05-25 05:30:00 +0000 |
commit | 40ebc873ea3f20e0be818462bbb4a4f4f10e7dfe (patch) | |
tree | 632d0cbdc37d9be2abd00d14461e1f822c3cdb31 | |
parent | c8a292737a7de0489a5f7937aed12f89f7c122cf (diff) | |
download | external_llvm-40ebc873ea3f20e0be818462bbb4a4f4f10e7dfe.zip external_llvm-40ebc873ea3f20e0be818462bbb4a4f4f10e7dfe.tar.gz external_llvm-40ebc873ea3f20e0be818462bbb4a4f4f10e7dfe.tar.bz2 |
Add a bisection step on the list of instructions before doing the linear
simplification. It's not clear to me whether this can replace the first of the
linear instruction simplification stages or not, so I left it in.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72377 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | tools/bugpoint/CrashDebugger.cpp | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index f46fed7..f369d4e 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -342,6 +342,82 @@ bool ReduceCrashingBlocks::TestBlocks(std::vector<const BasicBlock*> &BBs) { return false; } +namespace { + /// ReduceCrashingInstructions reducer - This works by removing the specified + /// non-terminator instructions and replacing them with undef. + /// + class ReduceCrashingInstructions : public ListReducer<const Instruction*> { + BugDriver &BD; + bool (*TestFn)(BugDriver &, Module *); + public: + ReduceCrashingInstructions(BugDriver &bd, bool (*testFn)(BugDriver &, + Module *)) + : BD(bd), TestFn(testFn) {} + + virtual TestResult doTest(std::vector<const Instruction*> &Prefix, + std::vector<const Instruction*> &Kept) { + if (!Kept.empty() && TestInsts(Kept)) + return KeepSuffix; + if (!Prefix.empty() && TestInsts(Prefix)) + return KeepPrefix; + return NoFailure; + } + + bool TestInsts(std::vector<const Instruction*> &Prefix); + }; +} + +bool ReduceCrashingInstructions::TestInsts(std::vector<const Instruction*> + &Insts) { + // Clone the program to try hacking it apart... + DenseMap<const Value*, Value*> ValueMap; + Module *M = CloneModule(BD.getProgram(), ValueMap); + + // Convert list to set for fast lookup... + SmallPtrSet<Instruction*, 64> Instructions; + for (unsigned i = 0, e = Insts.size(); i != e; ++i) { + assert(!isa<TerminatorInst>(Insts[i])); + Instructions.insert(cast<Instruction>(ValueMap[Insts[i]])); + } + + std::cout << "Checking for crash with only " << Instructions.size(); + if (Instructions.size() == 1) + std::cout << " instruction: "; + else + std::cout << " instructions: "; + + for (Module::iterator MI = M->begin(), ME = M->end(); MI != ME; ++MI) + for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE; ++FI) + for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E;) { + Instruction *Inst = I++; + if (!Instructions.count(Inst) && !isa<TerminatorInst>(Inst)) { + if (Inst->getType() != Type::VoidTy) + Inst->replaceAllUsesWith(UndefValue::get(Inst->getType())); + Inst->eraseFromParent(); + } + } + + // Verify that this is still valid. + PassManager Passes; + Passes.add(createVerifierPass()); + Passes.run(*M); + + // Try running on the hacked up program... + if (TestFn(BD, M)) { + BD.setNewProgram(M); // It crashed, keep the trimmed version... + + // Make sure to use instruction pointers that point into the now-current + // module, and that they don't include any deleted blocks. + Insts.clear(); + for (SmallPtrSet<Instruction*, 64>::const_iterator I = Instructions.begin(), + E = Instructions.end(); I != E; ++I) + Insts.push_back(*I); + return true; + } + delete M; // It didn't crash, try something else. + return false; +} + /// DebugACrash - Given a predicate that determines whether a component crashes /// on a program, try to destructively reduce the program while still keeping /// the predicate true. @@ -432,6 +508,22 @@ static bool DebugACrash(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *)) { BD.EmitProgressBitcode("reduced-blocks"); } + // Attempt to delete instructions using bisection. This should help out nasty + // cases with large basic blocks where the problem is at one end. + if (!BugpointIsInterrupted) { + std::vector<const Instruction*> Insts; + for (Module::const_iterator MI = BD.getProgram()->begin(), + ME = BD.getProgram()->end(); MI != ME; ++MI) + for (Function::const_iterator FI = MI->begin(), FE = MI->end(); FI != FE; + ++FI) + for (BasicBlock::const_iterator I = FI->begin(), E = FI->end(); + I != E; ++I) + if (!isa<TerminatorInst>(I)) + Insts.push_back(I); + + ReduceCrashingInstructions(BD, TestFn).reduceList(Insts); + } + // FIXME: This should use the list reducer to converge faster by deleting // larger chunks of instructions at a time! unsigned Simplification = 2; |