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
diff --git a/Driver/Backend.cpp b/Driver/Backend.cpp
index a59c82c..dd372b1 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 <fstream> // FIXME: Remove
 
 using namespace clang;
@@ -38,6 +43,7 @@
 namespace {
   class VISIBILITY_HIDDEN BackendConsumer  : public ASTConsumer {
     BackendAction Action;
+    CompileOptions CompileOpts;
     const std::string &InputFile;
     std::string OutputFile;
     llvm::OwningPtr<CodeGenerator> Gen;
@@ -70,10 +76,11 @@
     
   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 @@
 }
 
 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 @@
 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);  
 }