[llvm-commits] [llvm-gcc-4.2] r63344 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp

Evan Cheng evan.cheng at apple.com
Thu Jan 29 15:39:04 PST 2009


Author: evancheng
Date: Thu Jan 29 17:39:04 2009
New Revision: 63344

URL: http://llvm.org/viewvc/llvm-project?rev=63344&view=rev
Log:
- Split createOptimizationPasses() into two. Now we initialize the per module pass manager after all the functions are processed. This allows it to scan the list and find out whether always-inline pass is actually needed.

Modified:
    llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp

Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=63344&r1=63343&r2=63344&view=diff

==============================================================================
--- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original)
+++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Thu Jan 29 17:39:04 2009
@@ -104,8 +104,8 @@
 static PassManager *PerModulePasses = 0;
 static FunctionPassManager *CodeGenPasses = 0;
 
-static void createOptimizationPasses();
-bool OptimizationPassesCreated = false;
+static void createPerFunctionOptimizationPasses();
+static void createPerModuleOptimizationPasses();
 static void destroyOptimizationPasses();
 
 // Forward decl visibility style to global.
@@ -298,7 +298,7 @@
     exit(1);
   }
 
-  if (OptimizationPassesCreated) {
+  if (PerFunctionPasses || PerModulePasses) {
     destroyOptimizationPasses();
 
     // Don't run codegen, when we should output PCH
@@ -321,8 +321,6 @@
   AsmOutRawStream = new raw_os_ostream(*AsmOutStream);
   AsmOutFile = new OStream(*AsmOutStream);
 
-  assert(!OptimizationPassesCreated);
-  OptimizationPassesCreated = true;
   PerModulePasses = new PassManager();
   PerModulePasses->add(new TargetData(*TheTarget->getTargetData()));
 
@@ -344,9 +342,6 @@
 }
 
 static void destroyOptimizationPasses() {
-  assert(OptimizationPassesCreated ||
-         (!PerFunctionPasses && !PerModulePasses && !CodeGenPasses));
-
   delete PerFunctionPasses;
   delete PerModulePasses;
   delete CodeGenPasses;
@@ -354,16 +349,11 @@
   PerFunctionPasses = 0;
   PerModulePasses   = 0;
   CodeGenPasses     = 0;
-  OptimizationPassesCreated = false;
 }
 
-static void createOptimizationPasses() {
-  assert(OptimizationPassesCreated ||
-         (!PerFunctionPasses && !PerModulePasses && !CodeGenPasses));
-
-  if (OptimizationPassesCreated)
+static void createPerFunctionOptimizationPasses() {
+  if (PerFunctionPasses) 
     return;
-  OptimizationPassesCreated = true;
 
   // Create and set up the per-function pass manager.
   // FIXME: Move the code generator to be function-at-a-time.
@@ -388,19 +378,73 @@
     PerFunctionPasses->add(createInstructionCombiningPass());
   }
 
+  // If there are no module-level passes that have to be run, we codegen as
+  // each function is parsed.
+  // FIXME: We can't figure this out until we know there are no always-inline
+  // functions.
+  // FIXME: This is disabled right now until bugs can be worked out.  Reenable
+  // this for fast -O0 compiles!
+  if (!emit_llvm_bc && !emit_llvm && 0) {
+    FunctionPassManager *PM = PerFunctionPasses;    
+    HasPerFunctionPasses = true;
+
+    // Normal mode, emit a .s file by running the code generator.
+    // Note, this also adds codegenerator level optimization passes.
+    switch (TheTarget->addPassesToEmitFile(*PM, *AsmOutRawStream,
+                                           TargetMachine::AssemblyFile,
+                                           /*FAST*/optimize == 0)) {
+    default:
+    case FileModel::Error:
+      cerr << "Error interfacing to target machine!\n";
+      exit(1);
+    case FileModel::AsmFile:
+      break;
+    }
+
+    if (TheTarget->addPassesToEmitFileFinish(*PM, 0, /*Fast*/optimize == 0)) {
+      cerr << "Error interfacing to target machine!\n";
+      exit(1);
+    }
+  }
+  
+  if (HasPerFunctionPasses) {
+    PerFunctionPasses->doInitialization();
+  } else {
+    delete PerFunctionPasses;
+    PerFunctionPasses = 0;
+  }
+}
+
+static void createPerModuleOptimizationPasses() {
+  if (PerModulePasses)
+    // llvm_pch_write_init has already created the per module passes.
+    return;
+
   // FIXME: AT -O0/O1, we should stream out functions at a time.
   PerModulePasses = new PassManager();
   PerModulePasses->add(new TargetData(*TheTarget->getTargetData()));
   bool HasPerModulePasses = false;
+  bool NeedAlwaysInliner = false;
+  if (flag_inline_trees <= 1) {
+    // If full inliner is not run, check if always-inline is needed to handle
+    // functions that are  marked as always_inline.
+    for (Module::iterator I = TheModule->begin(), E = TheModule->end();
+         I != E; ++I)
+      if (I->hasFnAttr(Attribute::AlwaysInline)) {
+        NeedAlwaysInliner = true;
+        break;
+      }
+  }
 
   if (!DisableLLVMOptimizations) {
     HasPerModulePasses = true;
-    if (optimize == 0)
-      // Unless all LLVM optimizations are disabled, always run
-      // always-inline pass.
-      PerModulePasses->add(createAlwaysInlinerPass());
-    else {
-      PassManager *PM = PerModulePasses;
+    PassManager *PM = PerModulePasses;
+    if (optimize == 0) {
+      if (flag_inline_trees > 1)                // respect -fno-inline-functions
+        PM->add(createFunctionInliningPass());    // Inline small functions
+      else if (NeedAlwaysInliner)
+        PM->add(createAlwaysInlinerPass());       // Inline always_inline funcs
+    } else {
       if (flag_unit_at_a_time)
         PM->add(createRaiseAllocationsPass());    // call %malloc -> malloc inst
       PM->add(createCFGSimplificationPass());     // Clean up disgusting code
@@ -420,7 +464,7 @@
       }
       if (flag_inline_trees > 1)                // respect -fno-inline-functions
         PM->add(createFunctionInliningPass());    // Inline small functions
-      else
+      else if (NeedAlwaysInliner)
         PM->add(createAlwaysInlinerPass());       // Inline always_inline funcs
       if (optimize > 2)
         PM->add(createArgumentPromotionPass());   // Scalarize uninlined fn args
@@ -479,55 +523,43 @@
     PerModulePasses->add(createPrintModulePass(AsmOutRawStream));
     HasPerModulePasses = true;
   } else {
-    FunctionPassManager *PM;
-    
     // If there are passes we have to run on the entire module, we do codegen
     // as a separate "pass" after that happens.
+    // However if there are no module-level passes that have to be run, we
+    // codegen as each function is parsed.
     // FIXME: This is disabled right now until bugs can be worked out.  Reenable
     // this for fast -O0 compiles!
-    if (HasPerModulePasses || 1) {
-      CodeGenPasses = PM =
+    if (PerModulePasses || 1) {
+      FunctionPassManager *PM = CodeGenPasses =
         new FunctionPassManager(new ExistingModuleProvider(TheModule));
       PM->add(new TargetData(*TheTarget->getTargetData()));
-    } else {
-      // If there are no module-level passes that have to be run, we codegen as
-      // each function is parsed.
-      PM = PerFunctionPasses;
-      HasPerFunctionPasses = true;
-    }
 
-    // Normal mode, emit a .s file by running the code generator.
-    // Note, this also adds codegenerator level optimization passes.
-    switch (TheTarget->addPassesToEmitFile(*PM, *AsmOutRawStream,
-                                           TargetMachine::AssemblyFile,
-                                           /*FAST*/optimize == 0)) {
-    default:
-    case FileModel::Error:
-      cerr << "Error interfacing to target machine!\n";
-      exit(1);
-    case FileModel::AsmFile:
-      break;
-    }
+      // Normal mode, emit a .s file by running the code generator.
+      // Note, this also adds codegenerator level optimization passes.
+      switch (TheTarget->addPassesToEmitFile(*PM, *AsmOutRawStream,
+                                             TargetMachine::AssemblyFile,
+                                             /*FAST*/optimize == 0)) {
+      default:
+      case FileModel::Error:
+        cerr << "Error interfacing to target machine!\n";
+        exit(1);
+      case FileModel::AsmFile:
+        break;
+      }
 
-    if (TheTarget->addPassesToEmitFileFinish(*PM, 0, /*Fast*/optimize == 0)) {
-      cerr << "Error interfacing to target machine!\n";
-      exit(1);
+      if (TheTarget->addPassesToEmitFileFinish(*PM, 0, /*Fast*/optimize == 0)) {
+        cerr << "Error interfacing to target machine!\n";
+        exit(1);
+      }
     }
   }
-  
-  if (HasPerFunctionPasses) {
-    PerFunctionPasses->doInitialization();
-  } else {
-    delete PerFunctionPasses;
-    PerFunctionPasses = 0;
-  }
+
   if (!HasPerModulePasses) {
     delete PerModulePasses;
     PerModulePasses = 0;
   }
 }
 
-
 // llvm_asm_file_start - Start the .s file.
 void llvm_asm_file_start(void) {
   timevar_push(TV_LLVM_INIT);
@@ -583,7 +615,7 @@
   timevar_push(TV_LLVM_PERFILE);
 
   performLateBackendInitialization();
-  createOptimizationPasses();
+  createPerFunctionOptimizationPasses();
 
   if (flag_pch_file) {
     writeLLVMTypesStringTable();
@@ -677,7 +709,9 @@
     delete AsmIntermediateOutFile;
     AsmIntermediateOutFile = 0;
   }
+
   // Run module-level optimizers, if any are present.
+  createPerModuleOptimizationPasses();
   if (PerModulePasses)
     PerModulePasses->run(*TheModule);
   
@@ -743,7 +777,7 @@
 #endif
 
   performLateBackendInitialization();
-  createOptimizationPasses();
+  createPerFunctionOptimizationPasses();
 
   if (PerFunctionPasses)
     PerFunctionPasses->run(*Fn);





More information about the llvm-commits mailing list