/// ExtractLoops - Given a reduced list of functions that still exposed the bug, /// check to see if we can extract the loops in the region without obscuring the /// bug. If so, it reduces the amount of code identified. /// static bool ExtractLoops(BugDriver &BD, bool (*TestFn)(BugDriver &, Module *, Module *, std::string &), std::vector<Function*> &MiscompiledFunctions, std::string &Error) { bool MadeChange = false; while (1) { if (BugpointIsInterrupted) return MadeChange; DenseMap<const Value*, Value*> ValueMap; Module *ToNotOptimize = CloneModule(BD.getProgram(), ValueMap); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, MiscompiledFunctions, ValueMap); Module *ToOptimizeLoopExtracted = BD.ExtractLoop(ToOptimize); if (!ToOptimizeLoopExtracted) { // If the loop extractor crashed or if there were no extractible loops, // then this chapter of our odyssey is over with. delete ToNotOptimize; delete ToOptimize; return MadeChange; } errs() << "Extracted a loop from the breaking portion of the program.\n"; // Bugpoint is intentionally not very trusting of LLVM transformations. In // particular, we're not going to assume that the loop extractor works, so // we're going to test the newly loop extracted program to make sure nothing // has broken. If something broke, then we'll inform the user and stop // extraction. AbstractInterpreter *AI = BD.switchToSafeInterpreter(); bool Failure = TestMergedProgram(BD, ToOptimizeLoopExtracted, ToNotOptimize, false, Error); if (!Error.empty()) return false; if (Failure) { BD.switchToInterpreter(AI); // Merged program doesn't work anymore! errs() << " *** ERROR: Loop extraction broke the program. :(" << " Please report a bug!\n"; errs() << " Continuing on with un-loop-extracted version.\n"; BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-tno.bc", ToNotOptimize); BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to.bc", ToOptimize); BD.writeProgramToFile(OutputPrefix + "-loop-extract-fail-to-le.bc", ToOptimizeLoopExtracted); errs() << "Please submit the " << OutputPrefix << "-loop-extract-fail-*.bc files.\n"; delete ToOptimize; delete ToNotOptimize; delete ToOptimizeLoopExtracted; return MadeChange; } delete ToOptimize; BD.switchToInterpreter(AI); outs() << " Testing after loop extraction:\n"; // Clone modules, the tester function will free them. Module *TOLEBackup = CloneModule(ToOptimizeLoopExtracted); Module *TNOBackup = CloneModule(ToNotOptimize); Failure = TestFn(BD, ToOptimizeLoopExtracted, ToNotOptimize, Error); if (!Error.empty()) return false; if (!Failure) { outs() << "*** Loop extraction masked the problem. Undoing.\n"; // If the program is not still broken, then loop extraction did something // that masked the error. Stop loop extraction now. delete TOLEBackup; delete TNOBackup; return MadeChange; } ToOptimizeLoopExtracted = TOLEBackup; ToNotOptimize = TNOBackup; outs() << "*** Loop extraction successful!\n"; std::vector<std::pair<std::string, const FunctionType*> > MisCompFunctions; for (Module::iterator I = ToOptimizeLoopExtracted->begin(), E = ToOptimizeLoopExtracted->end(); I != E; ++I) if (!I->isDeclaration()) MisCompFunctions.push_back(std::make_pair(I->getName(), I->getFunctionType())); // Okay, great! Now we know that we extracted a loop and that loop // extraction both didn't break the program, and didn't mask the problem. // Replace the current program with the loop extracted version, and try to // extract another loop. std::string ErrorMsg; if (Linker::LinkModules(ToNotOptimize, ToOptimizeLoopExtracted, &ErrorMsg)){ errs() << BD.getToolName() << ": Error linking modules together:" << ErrorMsg << '\n'; exit(1); } delete ToOptimizeLoopExtracted; // All of the Function*'s in the MiscompiledFunctions list are in the old // module. Update this list to include all of the functions in the // optimized and loop extracted module. MiscompiledFunctions.clear(); for (unsigned i = 0, e = MisCompFunctions.size(); i != e; ++i) { Function *NewF = ToNotOptimize->getFunction(MisCompFunctions[i].first); assert(NewF && "Function not found??"); assert(NewF->getFunctionType() == MisCompFunctions[i].second && "found wrong function type?"); MiscompiledFunctions.push_back(NewF); } BD.setNewProgram(ToNotOptimize); MadeChange = true; } }