From 70f92436f5828c11ef108463da4473d44e114c28 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 23 Oct 2008 05:50:47 +0000 Subject: [PATCH] Add -O[0-3s] support (following llvm-gcc). - Passes match llvm-gcc but many of the switches aren't wired. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58034 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/ASTConsumers.h | 4 +- Driver/Backend.cpp | 97 +++++++++++++++++++++++++-- Driver/clang.cpp | 51 ++++++++++++-- include/clang/Driver/CompileOptions.h | 45 +++++++++++++ 4 files changed, 186 insertions(+), 11 deletions(-) create mode 100644 include/clang/Driver/CompileOptions.h diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h index 9c8af64bed..bc76df5f53 100644 --- a/Driver/ASTConsumers.h +++ b/Driver/ASTConsumers.h @@ -27,9 +27,10 @@ namespace clang { class ASTConsumer; class Diagnostic; class FileManager; -struct LangOptions; class Preprocessor; class PreprocessorFactory; +struct CompileOptions; +struct LangOptions; ASTConsumer *CreateASTPrinter(llvm::raw_ostream* OS = NULL); @@ -50,6 +51,7 @@ enum BackendAction { ASTConsumer *CreateBackendConsumer(BackendAction Action, Diagnostic &Diags, const LangOptions &Features, + const CompileOptions &CompileOpts, const std::string& InFile, const std::string& OutFile, bool GenerateDebugInfo); diff --git a/Driver/Backend.cpp b/Driver/Backend.cpp index a59c82cd76..dd372b195d 100644 --- a/Driver/Backend.cpp +++ b/Driver/Backend.cpp @@ -14,11 +14,14 @@ #include "clang/AST/TranslationUnit.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Driver/CompileOptions.h" #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/PassManager.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Assembly/PrintModulePass.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" @@ -30,6 +33,8 @@ #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachineRegistry.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/IPO.h" #include // FIXME: Remove using namespace clang; @@ -38,6 +43,7 @@ using namespace llvm; namespace { class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer { BackendAction Action; + CompileOptions CompileOpts; const std::string &InputFile; std::string OutputFile; llvm::OwningPtr Gen; @@ -70,10 +76,11 @@ namespace { public: BackendConsumer(BackendAction action, Diagnostic &Diags, - const LangOptions &Features, + const LangOptions &Features, const CompileOptions &compopts, const std::string& infile, const std::string& outfile, bool GenerateDebugInfo) : Action(action), + CompileOpts(compopts), InputFile(infile), OutputFile(outfile), Gen(CreateLLVMCodeGen(Diags, Features, InputFile, GenerateDebugInfo)), @@ -218,7 +225,88 @@ bool BackendConsumer::AddEmitPasses(bool Fast, std::string &Error) { } void BackendConsumer::CreatePasses() { - + // In -O0 if checking is disabled, we don't even have per-function passes. + if (CompileOpts.VerifyModule) + getPerFunctionPasses()->add(createVerifierPass()); + + if (CompileOpts.OptimizationLevel > 0) { + FunctionPassManager *PM = getPerFunctionPasses(); + PM->add(createCFGSimplificationPass()); + if (CompileOpts.OptimizationLevel == 1) + PM->add(createPromoteMemoryToRegisterPass()); + else + PM->add(createScalarReplAggregatesPass()); + PM->add(createInstructionCombiningPass()); + } + + // For now we always create per module passes. + PassManager *PM = getPerModulePasses(); + if (CompileOpts.OptimizationLevel > 0) { + if (CompileOpts.UnitAtATime) + PM->add(createRaiseAllocationsPass()); // call %malloc -> malloc inst + PM->add(createCFGSimplificationPass()); // Clean up disgusting code + PM->add(createPromoteMemoryToRegisterPass()); // Kill useless allocas + if (CompileOpts.UnitAtATime) { + PM->add(createGlobalOptimizerPass()); // Optimize out global vars + PM->add(createGlobalDCEPass()); // Remove unused fns and globs + PM->add(createIPConstantPropagationPass()); // IP Constant Propagation + PM->add(createDeadArgEliminationPass()); // Dead argument elimination + } + PM->add(createInstructionCombiningPass()); // Clean up after IPCP & DAE + PM->add(createCFGSimplificationPass()); // Clean up after IPCP & DAE + if (CompileOpts.UnitAtATime) { + PM->add(createPruneEHPass()); // Remove dead EH info + PM->add(createAddReadAttrsPass()); // Set readonly/readnone attrs + } + if (CompileOpts.InlineFunctions) + PM->add(createFunctionInliningPass()); // Inline small functions + else + PM->add(createAlwaysInlinerPass()); // Respect always_inline + if (CompileOpts.OptimizationLevel > 2) + PM->add(createArgumentPromotionPass()); // Scalarize uninlined fn args + if (CompileOpts.SimplifyLibCalls) + PM->add(createSimplifyLibCallsPass()); // Library Call Optimizations + PM->add(createInstructionCombiningPass()); // Cleanup for scalarrepl. + PM->add(createJumpThreadingPass()); // Thread jumps. + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createScalarReplAggregatesPass()); // Break up aggregate allocas + PM->add(createInstructionCombiningPass()); // Combine silly seq's + PM->add(createCondPropagationPass()); // Propagate conditionals + PM->add(createTailCallEliminationPass()); // Eliminate tail calls + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + PM->add(createReassociatePass()); // Reassociate expressions + PM->add(createLoopRotatePass()); // Rotate Loop + PM->add(createLICMPass()); // Hoist loop invariants + PM->add(createLoopUnswitchPass(CompileOpts.OptimizeSize ? true : false)); + PM->add(createLoopIndexSplitPass()); // Split loop index + PM->add(createInstructionCombiningPass()); + PM->add(createIndVarSimplifyPass()); // Canonicalize indvars + PM->add(createLoopDeletionPass()); // Delete dead loops + if (CompileOpts.UnrollLoops) + PM->add(createLoopUnrollPass()); // Unroll small loops + PM->add(createInstructionCombiningPass()); // Clean up after the unroller + PM->add(createGVNPass()); // Remove redundancies + PM->add(createMemCpyOptPass()); // Remove memcpy / form memset + PM->add(createSCCPPass()); // Constant prop with SCCP + + // Run instcombine after redundancy elimination to exploit opportunities + // opened up by them. + PM->add(createInstructionCombiningPass()); + PM->add(createCondPropagationPass()); // Propagate conditionals + PM->add(createDeadStoreEliminationPass()); // Delete dead stores + PM->add(createAggressiveDCEPass()); // Delete dead instructions + PM->add(createCFGSimplificationPass()); // Merge & remove BBs + + if (CompileOpts.UnitAtATime) { + PM->add(createStripDeadPrototypesPass()); // Get rid of dead prototypes + PM->add(createDeadTypeEliminationPass()); // Eliminate dead types + } + + if (CompileOpts.OptimizationLevel > 1 && CompileOpts.UnitAtATime) + PM->add(createConstantMergePass()); // Merge dup global constants + } else { + PerModulePasses->add(createAlwaysInlinerPass()); + } } /// EmitAssembly - Handle interaction with LLVM backend to generate @@ -275,9 +363,10 @@ void BackendConsumer::EmitAssembly() { ASTConsumer *clang::CreateBackendConsumer(BackendAction Action, Diagnostic &Diags, const LangOptions &Features, + const CompileOptions &CompileOpts, const std::string& InFile, const std::string& OutFile, bool GenerateDebugInfo) { - return new BackendConsumer(Action, Diags, Features, InFile, OutFile, - GenerateDebugInfo); + return new BackendConsumer(Action, Diags, Features, CompileOpts, + InFile, OutFile, GenerateDebugInfo); } diff --git a/Driver/clang.cpp b/Driver/clang.cpp index 9a106c70b8..6d3f0b3843 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -24,6 +24,7 @@ #include "clang.h" #include "ASTConsumers.h" +#include "clang/Driver/CompileOptions.h" #include "clang/Driver/HTMLDiagnostics.h" #include "clang/Driver/InitHeaderSearch.h" #include "clang/Driver/TextDiagnosticBuffer.h" @@ -1083,6 +1084,37 @@ static void ParseFile(Preprocessor &PP, MinimalAction *PA) { delete PA; } +//===----------------------------------------------------------------------===// +// Code generation options +//===----------------------------------------------------------------------===// + +static llvm::cl::opt +OptSize("Os", + llvm::cl::desc("Optimize for size")); + +// It might be nice to add bounds to the CommandLine library directly. +struct OptLevelParser : public llvm::cl::parser { + bool parse(llvm::cl::Option &O, const char *ArgName, + const std::string &Arg, unsigned &Val) { + if (llvm::cl::parser::parse(O, ArgName, Arg, Val)) + return true; + // FIXME: Support -O4. + if (Val > 3) + return O.error(": '" + Arg + "' invalid optimization level!"); + return false; + } +}; +static llvm::cl::opt +OptLevel("O", llvm::cl::Prefix, + llvm::cl::desc("Optimization level"), + llvm::cl::init(0)); + +static void InitializeCompileOptions(CompileOptions &Opts) { + Opts.OptimizationLevel = OptLevel; + Opts.OptimizeSize = OptSize; + // FIXME: Wire other options. +} + //===----------------------------------------------------------------------===// // Main driver //===----------------------------------------------------------------------===// @@ -1115,14 +1147,21 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile, return CreateSerializationTest(Diag, FileMgr); case EmitAssembly: - return CreateBackendConsumer(Backend_EmitAssembly, Diag, LangOpts, - InFile, OutputFile, GenerateDebugInfo); case EmitLLVM: - return CreateBackendConsumer(Backend_EmitLL, Diag, LangOpts, - InFile, OutputFile, GenerateDebugInfo); - case EmitBC: - return CreateBackendConsumer(Backend_EmitBC, Diag, LangOpts, + case EmitBC: { + BackendAction Act; + if (ProgAction == EmitAssembly) { + Act = Backend_EmitAssembly; + } else if (ProgAction == EmitLLVM) { + Act = Backend_EmitLL; + } else { + Act = Backend_EmitBC; + } + CompileOptions Opts; + InitializeCompileOptions(Opts); + return CreateBackendConsumer(Act, Diag, LangOpts, Opts, InFile, OutputFile, GenerateDebugInfo); + } case SerializeAST: // FIXME: Allow user to tailor where the file is written. diff --git a/include/clang/Driver/CompileOptions.h b/include/clang/Driver/CompileOptions.h new file mode 100644 index 0000000000..560944566a --- /dev/null +++ b/include/clang/Driver/CompileOptions.h @@ -0,0 +1,45 @@ +//===--- CompileOptions.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the CompileOptions interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_COMPILEOPTIONS_H +#define LLVM_CLANG_COMPILEOPTIONS_H + +namespace clang { + +/// CompileOptions - Track various options which control how the code +/// is optimized and passed to the backend. +struct CompileOptions { + unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. + unsigned OptimizeSize : 1; /// If -Os is specified. + unsigned UnitAtATime : 1; /// Unused. For mirroring GCC + /// optimization selection. + unsigned InlineFunctions : 1; /// Should functions be inlined? + unsigned SimplifyLibCalls : 1; /// Should standard library calls be + /// treated specially. + unsigned UnrollLoops : 1; /// Control whether loops are unrolled. + unsigned VerifyModule : 1; /// Control whether the module + /// should be run through the LLVM Verifier. + +public: + CompileOptions() { + OptimizationLevel = 0; + OptimizeSize = 0; + UnitAtATime = InlineFunctions = SimplifyLibCalls = 1; + UnrollLoops = 1; + VerifyModule = 1; + } +}; + +} // end namespace clang + +#endif -- 2.40.0