X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fopt%2Fopt.cpp;h=43e807472557a109ced39dd7e647f70d602d0b37;hb=b04cb7daf5a9d7b57450b0612e699df49fcb7cbe;hp=c183dec9e08a0b712eaa4e37a400c3992e3cb303;hpb=e04a967e7e9eb1add857fdc307a3db66caa1a639;p=oota-llvm.git diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index c183dec9e08..43e80747255 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -1,5 +1,11 @@ +//===- opt.cpp - The LLVM Modular Optimizer -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// //===----------------------------------------------------------------------===// -// LLVM 'OPT' UTILITY // // Optimizations may be specified an arbitrary number of times on the command // line, they are run in the order specified. @@ -7,131 +13,159 @@ //===----------------------------------------------------------------------===// #include "llvm/Module.h" +#include "llvm/PassManager.h" #include "llvm/Bytecode/Reader.h" -#include "llvm/Bytecode/Writer.h" -#include "llvm/Optimizations/AllOpts.h" -#include "llvm/Transforms/Instrumentation/TraceValues.h" +#include "llvm/Bytecode/WriteBytecodePass.h" #include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Transforms/ConstantMerge.h" -#include "llvm/Transforms/CleanupGCCOutput.h" -#include "llvm/Transforms/LevelChange.h" -#include "llvm/Transforms/SwapStructContents.h" -#include "llvm/Transforms/IPO/GlobalDCE.h" -#include "llvm/Transforms/Scalar/IndVarSimplify.h" -#include "Support/CommandLine.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetMachineImpls.h" +#include "llvm/Support/PassNameParser.h" +#include "llvm/System/Signals.h" +#include "Support/SystemUtils.h" #include #include +#include -enum Opts { - // Basic optimizations - dce, constprop, inlining, mergecons, strip, mstrip, - - // Miscellaneous Transformations - trace, tracem, print, cleangcc, - - // More powerful optimizations - indvars, sccp, adce, raise, - - // Interprocedural optimizations... - globaldce, swapstructs, -}; - -struct { - enum Opts OptID; - Pass *ThePass; -} OptTable[] = { - { swapstructs, 0 }, - { dce , new opt::DeadCodeElimination() }, - { constprop, new opt::ConstantPropogation() }, - { inlining , new opt::MethodInlining() }, - { mergecons, new ConstantMerge() }, - { strip , new opt::SymbolStripping() }, - { mstrip , new opt::FullSymbolStripping() }, - { indvars , new InductionVariableSimplify() }, - { sccp , new opt::SCCPPass() }, - { adce , new opt::AgressiveDCE() }, - { raise , new RaisePointerReferences() }, - { trace , new InsertTraceCode(true, true) }, - { tracem , new InsertTraceCode(false, true) }, - { print , new PrintModulePass("Current Method: \n",&cerr) }, - { cleangcc , new CleanupGCCOutput() }, -}; - -cl::String InputFilename ("", "Load file to optimize", cl::NoFlags, "-"); -cl::String OutputFilename("o", "Override output filename", cl::NoFlags, ""); -cl::Flag Force ("f", "Overwrite output files", cl::NoFlags, false); -cl::Flag Quiet ("q", "Don't print modifying pass names", 0, false); -cl::Alias QuietA ("quiet", "Alias for -q", cl::NoFlags, Quiet); -cl::EnumList OptimizationList(cl::NoFlags, - clEnumVal(dce , "Dead Code Elimination"), - clEnumVal(constprop, "Simple Constant Propogation"), - clEnumValN(inlining , "inline", "Method Integration"), - clEnumVal(mergecons, "Merge identical global constants"), - clEnumVal(strip , "Strip Symbols"), - clEnumVal(mstrip , "Strip Module Symbols"), - clEnumVal(indvars , "Simplify Induction Variables"), - clEnumVal(sccp , "Sparse Conditional Constant Propogation"), - clEnumVal(adce , "Agressive DCE"), - - clEnumVal(globaldce, "Remove unreachable globals"), - clEnumVal(swapstructs, "Swap structure types around"), - - clEnumVal(cleangcc , "Cleanup GCC Output"), - clEnumVal(raise , "Raise to Higher Level"), - clEnumVal(trace , "Insert BB & Method trace code"), - clEnumVal(tracem , "Insert Method trace code only"), - clEnumVal(print , "Print working method to stderr"), -0); - -static void RunOptimization(Module *M, enum Opts Opt) { - for (unsigned j = 0; j < sizeof(OptTable)/sizeof(OptTable[0]); ++j) - if (Opt == OptTable[j].OptID) { - if (OptTable[j].ThePass->run(M) && !Quiet) - cerr << OptimizationList.getArgName(Opt) - << " pass made modifications!\n"; - return; - } - - // Special cases that haven't been fit into a consistent framework yet... - switch (Opt) { - case globaldce: { - GlobalDCE GDCE; GDCE.run(M); return; - } - case swapstructs: { - PrebuiltStructMutation SM(M, PrebuiltStructMutation::SortElements); - SM.run(M); return; - } - default: - cerr << "Optimization tables inconsistent!!\n"; - } -} +using namespace llvm; + +// The OptimizationList is automatically populated with registered Passes by the +// PassNameParser. +// +static cl::list > +OptimizationList(cl::desc("Optimizations available:")); + + +// Other command line options... +// +static cl::opt +InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + +static cl::opt +OutputFilename("o", cl::desc("Override output filename"), + cl::value_desc("filename"), cl::init("-")); + +static cl::opt +Force("f", cl::desc("Overwrite output files")); + +static cl::opt +PrintEachXForm("p", cl::desc("Print module after each transformation")); + +static cl::opt +NoOutput("disable-output", + cl::desc("Do not write result bytecode file"), cl::Hidden); + +static cl::opt +NoVerify("disable-verify", cl::desc("Do not verify result module"), cl::Hidden); + +static cl::opt +Quiet("q", cl::desc("Don't print 'program modified' message")); + +static cl::alias +QuietA("quiet", cl::desc("Alias for -q"), cl::aliasopt(Quiet)); + +//===----------------------------------------------------------------------===// +// main for opt +// int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, " llvm .bc -> .bc modular optimizer\n"); - std::auto_ptr M(ParseBytecodeFile(InputFilename)); + PrintStackTraceOnErrorSignal(); + + // Allocate a full target machine description only if necessary... + // FIXME: The choice of target should be controllable on the command line. + std::auto_ptr target; + + TargetMachine* TM = NULL; + std::string ErrorMessage; + + // Load the input module... + std::auto_ptr M(ParseBytecodeFile(InputFilename, &ErrorMessage)); if (M.get() == 0) { - cerr << "bytecode didn't read correctly.\n"; + std::cerr << argv[0] << ": "; + if (ErrorMessage.size()) + std::cerr << ErrorMessage << "\n"; + else + std::cerr << "bytecode didn't read correctly.\n"; return 1; } - // Run all of the optimizations specified on the command line - for (unsigned i = 0; i < OptimizationList.size(); ++i) - RunOptimization(M.get(), OptimizationList[i]); + // Figure out what stream we are supposed to write to... + std::ostream *Out = &std::cout; // Default to printing to stdout... + if (OutputFilename != "-") { + if (!Force && std::ifstream(OutputFilename.c_str())) { + // If force is not specified, make sure not to overwrite a file! + std::cerr << argv[0] << ": error opening '" << OutputFilename + << "': file exists!\n" + << "Use -f command line argument to force output\n"; + return 1; + } + Out = new std::ofstream(OutputFilename.c_str()); - ostream *Out = &cout; // Default to printing to stdout... - if (OutputFilename != "") { - Out = new ofstream(OutputFilename.c_str(), - (Force ? 0 : ios::noreplace)|ios::out); if (!Out->good()) { - cerr << "Error opening " << OutputFilename << "!\n"; + std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; return 1; } + + // Make sure that the Output file gets unlinked from the disk if we get a + // SIGINT + RemoveFileOnSignal(OutputFilename); } - // Okay, we're done now... write out result... - WriteBytecodeToFile(M.get(), *Out); + // If the output is set to be emitted to standard out, and standard out is a + // console, print out a warning message and refuse to do it. We don't impress + // anyone by spewing tons of binary goo to a terminal. + if (Out == &std::cout && isStandardOutAConsole() && !Force && !NoOutput) { + std::cerr << "WARNING: It looks like you're attempting to print out a " + << "bytecode file. I'm\ngoing to pretend you didn't ask me to do" + << " this (for your own good). If you\nREALLY want to taste LLVM" + << " bytecode first hand, you can force output with the\n'-f'" + << " option.\n\n"; + NoOutput = true; + } + + // Create a PassManager to hold and optimize the collection of passes we are + // about to build... + // + PassManager Passes; + + // Add an appropriate TargetData instance for this module... + Passes.add(new TargetData("opt", M.get())); + + // Create a new optimization pass for each one specified on the command line + for (unsigned i = 0; i < OptimizationList.size(); ++i) { + const PassInfo *Opt = OptimizationList[i]; + + if (Opt->getNormalCtor()) + Passes.add(Opt->getNormalCtor()()); + else if (Opt->getTargetCtor()) { +#if 0 + if (target.get() == NULL) + target.reset(allocateSparcTargetMachine()); // FIXME: target option +#endif + assert(target.get() && "Could not allocate target machine!"); + Passes.add(Opt->getTargetCtor()(*target.get())); + } else + std::cerr << argv[0] << ": cannot create pass: " << Opt->getPassName() + << "\n"; + + if (PrintEachXForm) + Passes.add(new PrintModulePass(&std::cerr)); + } + + // Check that the module is well formed on completion of optimization + if (!NoVerify) + Passes.add(createVerifierPass()); + + // Write bytecode out to disk or cout as the last step... + if (!NoOutput) + Passes.add(new WriteBytecodePass(Out, Out != &std::cout)); + + // Now that we have all of the passes ready, run them. + if (Passes.run(*M.get()) && !Quiet) + std::cerr << "Program modified.\n"; - if (Out != &cout) delete Out; return 0; }