From: Nick Lewycky Date: Wed, 14 Nov 2007 06:47:06 +0000 (+0000) Subject: Allow the block extractor take to take a list of basic blocks to not extract X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6fa98b13206583e6eb90b8304758b35548914944;p=oota-llvm.git Allow the block extractor take to take a list of basic blocks to not extract from a file containing Function/BasicBlock pairings. This is not safe against anonymous or abnormally-named Funcs or BBs. Make bugpoint use this interface to pass the BBs list to the child bugpoint. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44101 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/IPO/LoopExtractor.cpp b/lib/Transforms/IPO/LoopExtractor.cpp index a6787fea11d..80ce1fdd751 100644 --- a/lib/Transforms/IPO/LoopExtractor.cpp +++ b/lib/Transforms/IPO/LoopExtractor.cpp @@ -21,10 +21,13 @@ #include "llvm/Pass.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/FunctionUtils.h" #include "llvm/ADT/Statistic.h" +#include +#include using namespace llvm; STATISTIC(NumExtracted, "Number of loops extracted"); @@ -144,15 +147,28 @@ FunctionPass *llvm::createSingleLoopExtractorPass() { namespace { + // BlockFile - A file which contains a list of blocks that should not be + // extracted. + cl::opt + BlockFile("extract-blocks-file", cl::value_desc("filename"), + cl::desc("A file containing list of basic blocks to not extract"), + cl::Hidden); + /// BlockExtractorPass - This pass is used by bugpoint to extract all blocks /// from the module into their own functions except for those specified by the /// BlocksToNotExtract list. class BlockExtractorPass : public ModulePass { + void LoadFile(const char *Filename); + std::vector BlocksToNotExtract; + std::vector > BlocksToNotExtractByName; public: static char ID; // Pass identification, replacement for typeid explicit BlockExtractorPass(const std::vector &B) - : ModulePass((intptr_t)&ID), BlocksToNotExtract(B) {} + : ModulePass((intptr_t)&ID), BlocksToNotExtract(B) { + if (!BlockFile.empty()) + LoadFile(BlockFile.c_str()); + } BlockExtractorPass() : ModulePass((intptr_t)&ID) {} bool runOnModule(Module &M); @@ -171,6 +187,24 @@ ModulePass *llvm::createBlockExtractorPass(const std::vector &BTNE) return new BlockExtractorPass(BTNE); } +void BlockExtractorPass::LoadFile(const char *Filename) { + // Load the BlockFile... + std::ifstream In(Filename); + if (!In.good()) { + cerr << "WARNING: BlockExtractor couldn't load file '" << Filename + << "'!\n"; + return; + } + while (In) { + std::string FunctionName, BlockName; + In >> FunctionName; + In >> BlockName; + if (!BlockName.empty()) + BlocksToNotExtractByName.push_back( + std::make_pair(FunctionName, BlockName)); + } +} + bool BlockExtractorPass::runOnModule(Module &M) { std::set TranslatedBlocksToNotExtract; for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) { @@ -187,6 +221,29 @@ bool BlockExtractorPass::runOnModule(Module &M) { TranslatedBlocksToNotExtract.insert(BBI); } + while (!BlocksToNotExtractByName.empty()) { + // There's no way to find BBs by name without looking at every BB inside + // every Function. Fortunately, this is always empty except when used by + // bugpoint in which case correctness is more important than performance. + + std::string &FuncName = BlocksToNotExtractByName.back().first; + std::string &BlockName = BlocksToNotExtractByName.back().second; + + for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) { + Function &F = *FI; + if (F.getName() != FuncName) continue; + + for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) { + BasicBlock &BB = *BI; + if (BB.getName() != BlockName) continue; + + TranslatedBlocksToNotExtract.insert(BI); + } + } + + BlocksToNotExtractByName.pop_back(); + } + // Now that we know which blocks to not extract, figure out which ones we WANT // to extract. std::vector BlocksToExtract; diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index 4652e37ba2f..fa3264f9dcf 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -234,7 +234,8 @@ public: /// automatically attempt to track down a crashing pass if one exists, and /// this method will never return null. Module *runPassesOn(Module *M, const std::vector &Passes, - bool AutoDebugCrashes = false); + bool AutoDebugCrashes = false, unsigned NumExtraArgs = 0, + const char * const *ExtraArgs = NULL); /// runPasses - Run the specified passes on Program, outputting a bitcode /// file and writting the filename into OutputFile if successful. If the @@ -242,11 +243,13 @@ public: /// otherwise return false. If DeleteOutput is set to true, the bitcode is /// deleted on success, and the filename string is undefined. This prints to /// cout a single line message indicating whether compilation was successful - /// or failed, unless Quiet is set. + /// or failed, unless Quiet is set. ExtraArgs specifies additional arguments + /// to pass to the child bugpoint instance. /// bool runPasses(const std::vector &PassesToRun, std::string &OutputFilename, bool DeleteOutput = false, - bool Quiet = false) const; + bool Quiet = false, unsigned NumExtraArgs = 0, + const char * const *ExtraArgs = NULL) const; /// runManyPasses - Take the specified pass list and create different /// combinations of passes to compile the program with. Compile the program with diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 7c7e214cbe8..75aba5990d4 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -27,7 +27,10 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileUtilities.h" +#include "llvm/System/Path.h" +#include "llvm/System/Signals.h" #include +#include #include using namespace llvm; @@ -305,10 +308,51 @@ Module *llvm::SplitFunctionsOutOfModule(Module *M, Module *BugDriver::ExtractMappedBlocksFromModule(const std::vector &BBs, Module *M) { + char *ExtraArg = NULL; + + sys::Path uniqueFilename("bugpoint-extractblocks"); + std::string ErrMsg; + if (uniqueFilename.createTemporaryFileOnDisk(true, &ErrMsg)) { + std::cout << "*** Basic Block extraction failed!\n"; + std::cerr << "Error creating temporary file: " << ErrMsg << "\n"; + M = swapProgramIn(M); + EmitProgressBitcode("basicblockextractfail", true); + swapProgramIn(M); + return 0; + } + sys::RemoveFileOnSignal(uniqueFilename); + + std::ofstream BlocksToNotExtractFile(uniqueFilename.c_str()); + if (!BlocksToNotExtractFile) { + std::cout << "*** Basic Block extraction failed!\n"; + std::cerr << "Error writing list of blocks to not extract: " << ErrMsg + << "\n"; + M = swapProgramIn(M); + EmitProgressBitcode("basicblockextractfail", true); + swapProgramIn(M); + return 0; + } + for (std::vector::const_iterator I = BBs.begin(), E = BBs.end(); + I != E; ++I) { + BasicBlock *BB = *I; + BlocksToNotExtractFile << BB->getParent()->getName() << " " + << BB->getName() << "\n"; + } + BlocksToNotExtractFile.close(); + + const char *uniqueFN = uniqueFilename.c_str(); + ExtraArg = (char*)malloc(23 + strlen(uniqueFN)); + strcat(strcpy(ExtraArg, "--extract-blocks-file="), uniqueFN); + std::vector PI; - // FIXME: BBs is actually ignored. See http://llvm.org/PR1775 - PI.push_back(getPI(createBlockExtractorPass(BBs))); - Module *Ret = runPassesOn(M, PI); + std::vector EmptyBBs; // This parameter is ignored. + PI.push_back(getPI(createBlockExtractorPass(EmptyBBs))); + Module *Ret = runPassesOn(M, PI, false, 1, &ExtraArg); + + if (uniqueFilename.exists()) + uniqueFilename.eraseFromDisk(); // Free disk space + free(ExtraArg); + if (Ret == 0) { std::cout << "*** Basic Block extraction failed, please report a bug!\n"; M = swapProgramIn(M); diff --git a/tools/bugpoint/Miscompilation.cpp b/tools/bugpoint/Miscompilation.cpp index be820c8b284..c9780e22103 100644 --- a/tools/bugpoint/Miscompilation.cpp +++ b/tools/bugpoint/Miscompilation.cpp @@ -223,7 +223,7 @@ bool ReduceMiscompilingFunctions::TestFuncs(const std::vector&Funcs){ Module *ToNotOptimize = CloneModule(BD.getProgram()); Module *ToOptimize = SplitFunctionsOutOfModule(ToNotOptimize, Funcs); - // Run the predicate, not that the predicate will delete both input modules. + // Run the predicate, note that the predicate will delete both input modules. return TestFn(BD, ToOptimize, ToNotOptimize); } diff --git a/tools/bugpoint/OptimizerDriver.cpp b/tools/bugpoint/OptimizerDriver.cpp index a3ce42ec71c..9a0725a3ac9 100644 --- a/tools/bugpoint/OptimizerDriver.cpp +++ b/tools/bugpoint/OptimizerDriver.cpp @@ -124,7 +124,8 @@ int BugDriver::runPassesAsChild(const std::vector &Passes) { /// bool BugDriver::runPasses(const std::vector &Passes, std::string &OutputFilename, bool DeleteOutput, - bool Quiet) const { + bool Quiet, unsigned NumExtraArgs, + const char * const *ExtraArgs) const { // setup the output file name cout << std::flush; sys::Path uniqueFilename("bugpoint-output.bc"); @@ -156,7 +157,7 @@ bool BugDriver::runPasses(const std::vector &Passes, // setup the child process' arguments const char** args = (const char**) alloca(sizeof(const char*) * - (Passes.size()+13+2*PluginLoader::getNumPlugins())); + (Passes.size()+13+2*PluginLoader::getNumPlugins()+NumExtraArgs)); int n = 0; sys::Path tool = sys::Program::FindProgramByName(ToolName); if (UseValgrind) { @@ -182,6 +183,8 @@ bool BugDriver::runPasses(const std::vector &Passes, E = pass_args.end(); I != E; ++I ) args[n++] = I->c_str(); args[n++] = inputFilename.c_str(); + for (unsigned i = 0; i < NumExtraArgs; ++i) + args[n++] = *ExtraArgs; args[n++] = 0; sys::Path prog; @@ -225,10 +228,12 @@ bool BugDriver::runPasses(const std::vector &Passes, /// failure. Module *BugDriver::runPassesOn(Module *M, const std::vector &Passes, - bool AutoDebugCrashes) { + bool AutoDebugCrashes, unsigned NumExtraArgs, + const char * const *ExtraArgs) { Module *OldProgram = swapProgramIn(M); std::string BitcodeResult; - if (runPasses(Passes, BitcodeResult, false/*delete*/, true/*quiet*/)) { + if (runPasses(Passes, BitcodeResult, false/*delete*/, true/*quiet*/, + NumExtraArgs, ExtraArgs)) { if (AutoDebugCrashes) { cerr << " Error running this sequence of passes" << " on the input program!\n";