X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fgccas%2Fgccas.cpp;h=dd8b8e0698498db4613ad007bd2a0ee311d0227f;hb=227b6d00dd1faee07c921c7e2256e0fca737d2e5;hp=235dadf4fa05cf184e06d8609547e71e7dfec026;hpb=0732c70ffb55d663fa2d1f5406c5c25bcd27a8b0;p=oota-llvm.git diff --git a/tools/gccas/gccas.cpp b/tools/gccas/gccas.cpp index 235dadf4fa0..dd8b8e06984 100644 --- a/tools/gccas/gccas.cpp +++ b/tools/gccas/gccas.cpp @@ -1,66 +1,170 @@ +//===-- gccas.cpp - The "optimizing assembler" used by the GCC frontend ---===// +// +// 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 'GCCAS' UTILITY // -// This utility is designed to be used by the GCC frontend for creating -// bytecode files from it's intermediate llvm assembly. The requirements for -// this utility are thus slightly different than that of the standard as util. +// This utility is designed to be used by the GCC frontend for creating bytecode +// files from its intermediate LLVM assembly. The requirements for this utility +// are thus slightly different than that of the standard `as' util. // //===----------------------------------------------------------------------===// #include "llvm/Module.h" #include "llvm/PassManager.h" +#include "llvm/Analysis/LoadValueNumbering.h" +#include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/Parser.h" -#include "llvm/Transforms/CleanupGCCOutput.h" -#include "llvm/Transforms/LevelChange.h" -#include "llvm/Transforms/ConstantMerge.h" -#include "llvm/Transforms/ChangeAllocations.h" -#include "llvm/Transforms/Scalar/DCE.h" -#include "llvm/Transforms/Scalar/IndVarSimplify.h" -#include "llvm/Transforms/Scalar/InstructionCombining.h" -#include "llvm/Transforms/Scalar/PromoteMemoryToRegister.h" #include "llvm/Bytecode/WriteBytecodePass.h" -#include "Support/CommandLine.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/System/Signals.h" #include #include -#include -cl::String InputFilename ("", "Parse file, compile to bytecode", - cl::Required, ""); -cl::String OutputFilename("o", "Override output filename", cl::NoFlags, ""); -cl::Flag StopAtLevelRaise("stopraise", "Stop optimization before level raise", - cl::Hidden); +using namespace llvm; + +namespace { + cl::opt + InputFilename(cl::Positional,cl::desc(""),cl::init("-")); + + cl::opt + OutputFilename("o", cl::desc("Override output filename"), + cl::value_desc("filename")); + + cl::opt + Verify("verify", cl::desc("Verify each pass result")); + + cl::opt + DisableInline("disable-inlining", cl::desc("Do not run the inliner pass")); + + cl::opt + DisableOptimizations("disable-opt", + cl::desc("Do not run any optimization passes")); + + cl::opt + DisableDSE("disable-dse", cl::desc("Do not run dead store elimination")); + cl::opt + NoCompress("disable-compression", cl::init(false), + cl::desc("Don't ompress the generated bytecode")); +} + + +static inline void addPass(PassManager &PM, Pass *P) { + // Add the pass to the pass manager... + PM.add(P); + + // If we are verifying all of the intermediate steps, add the verifier... + if (Verify) PM.add(createVerifierPass()); +} + + +void AddConfiguredTransformationPasses(PassManager &PM) { + PM.add(createVerifierPass()); // Verify that input is correct + addPass(PM, createLowerSetJmpPass()); // Lower llvm.setjmp/.longjmp + addPass(PM, createFunctionResolvingPass()); // Resolve (...) functions + + if (DisableOptimizations) return; + + addPass(PM, createRaiseAllocationsPass()); // call %malloc -> malloc inst + addPass(PM, createCFGSimplificationPass()); // Clean up disgusting code + addPass(PM, createPromoteMemoryToRegister()); // Kill useless allocas + addPass(PM, createGlobalOptimizerPass()); // Optimize out global vars + addPass(PM, createGlobalDCEPass()); // Remove unused fns and globs + addPass(PM, createIPConstantPropagationPass());// IP Constant Propagation + addPass(PM, createDeadArgEliminationPass()); // Dead argument elimination + addPass(PM, createInstructionCombiningPass()); // Clean up after IPCP & DAE + addPass(PM, createCFGSimplificationPass()); // Clean up after IPCP & DAE + + addPass(PM, createPruneEHPass()); // Remove dead EH info + + if (!DisableInline) + addPass(PM, createFunctionInliningPass()); // Inline small functions + addPass(PM, createArgumentPromotionPass()); // Scalarize uninlined fn args + + addPass(PM, createRaisePointerReferencesPass());// Recover type information + addPass(PM, createTailDuplicationPass()); // Simplify cfg by copying code + addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs + addPass(PM, createScalarReplAggregatesPass()); // Break up aggregate allocas + addPass(PM, createInstructionCombiningPass()); // Combine silly seq's + + addPass(PM, createReassociatePass()); // Reassociate expressions + addPass(PM, createInstructionCombiningPass()); // Combine silly seq's + addPass(PM, createTailCallEliminationPass()); // Eliminate tail calls + addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs + addPass(PM, createLICMPass()); // Hoist loop invariants + addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller + addPass(PM, createIndVarSimplifyPass()); // Canonicalize indvars + addPass(PM, createLoopUnrollPass()); // Unroll small loops + addPass(PM, createInstructionCombiningPass()); // Clean up after the unroller + addPass(PM, createLoadValueNumberingPass()); // GVN for load instructions + addPass(PM, createGCSEPass()); // Remove common subexprs + addPass(PM, createSCCPPass()); // Constant prop with SCCP + + // Run instcombine after redundancy elimination to exploit opportunities + // opened up by them. + addPass(PM, createInstructionCombiningPass()); + if (!DisableDSE) + addPass(PM, createDeadStoreEliminationPass()); // Delete dead stores + addPass(PM, createAggressiveDCEPass()); // SSA based 'Aggressive DCE' + addPass(PM, createCFGSimplificationPass()); // Merge & remove BBs + addPass(PM, createDeadTypeEliminationPass()); // Eliminate dead types + addPass(PM, createConstantMergePass()); // Merge dup global constants +} + int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n"); + sys::PrintStackTraceOnErrorSignal(); std::auto_ptr M; try { // Parse the file now... M.reset(ParseAssemblyFile(InputFilename)); } catch (const ParseException &E) { - cerr << E.getMessage() << endl; + std::cerr << argv[0] << ": " << E.getMessage() << "\n"; return 1; } if (M.get() == 0) { - cerr << "assembly didn't read correctly.\n"; + std::cerr << argv[0] << ": assembly didn't read correctly.\n"; return 1; } - + + std::ostream *Out = 0; if (OutputFilename == "") { // Didn't specify an output filename? - std::string IFN = InputFilename; - int Len = IFN.length(); - if (IFN[Len-2] == '.' && IFN[Len-1] == 's') { // Source ends in .s? - OutputFilename = std::string(IFN.begin(), IFN.end()-2); + if (InputFilename == "-") { + OutputFilename = "-"; } else { - OutputFilename = IFN; // Append a .o to it + std::string IFN = InputFilename; + int Len = IFN.length(); + if (IFN[Len-2] == '.' && IFN[Len-1] == 's') { // Source ends in .s? + OutputFilename = std::string(IFN.begin(), IFN.end()-2); + } else { + OutputFilename = IFN; // Append a .o to it + } + OutputFilename += ".o"; } - OutputFilename += ".o"; } - std::ofstream Out(OutputFilename.c_str(), ios::out); - if (!Out.good()) { - cerr << "Error opening " << OutputFilename << "!\n"; + if (OutputFilename == "-") + Out = &std::cout; + else { + Out = new std::ofstream(OutputFilename.c_str(), std::ios::out); + + // Make sure that the Out file gets unlinked from the disk if we get a + // signal + sys::RemoveFileOnSignal(sys::Path(OutputFilename)); + } + + + if (!Out->good()) { + std::cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; return 1; } @@ -68,21 +172,24 @@ int main(int argc, char **argv) { // a little bit. Do this now. // PassManager Passes; - Passes.add(createDeadInstEliminationPass()); // Remove Dead code/vars - Passes.add(createRaiseAllocationsPass()); // call %malloc -> malloc inst - Passes.add(createPromoteMemoryToRegister()); // memory->register promotion - Passes.add(createCleanupGCCOutputPass()); // Fix gccisms - Passes.add(createIndVarSimplifyPass()); // Simplify indvars - if (!StopAtLevelRaise) { - Passes.add(createRaisePointerReferencesPass()); // Eliminate casts - Passes.add(createConstantMergePass()); // Merge dup global consts - Passes.add(createInstructionCombiningPass()); // Combine silly seq's - Passes.add(createDeadCodeEliminationPass()); // Remove Dead code/vars - } - Passes.add(new WriteBytecodePass(&Out)); // Write bytecode to file... + + // Add an appropriate TargetData instance for this module... + Passes.add(new TargetData("gccas", M.get())); + + // Add all of the transformation passes to the pass manager to do the cleanup + // and optimization of the GCC output. + // + AddConfiguredTransformationPasses(Passes); + + // Make sure everything is still good. + Passes.add(createVerifierPass()); + + // Write bytecode to file... + Passes.add(new WriteBytecodePass(Out,false,!NoCompress)); // Run our queue of passes all at once now, efficiently. - Passes.run(M.get()); + Passes.run(*M.get()); + + if (Out != &std::cout) delete Out; return 0; } -