resolved conflicts for merge of 7c75d915 to master

Change-Id: I25c1dc90af679e2463abffd33ee8838b4727396f
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index cee5daa..4199fb2 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -47,6 +47,7 @@
 #include "llvm/CodeGen/RegAllocRegistry.h"
 #include "llvm/CodeGen/SchedulerRegistry.h"
 
+#include "llvm/MC/MCContext.h"
 #include "llvm/MC/SubtargetFeature.h"
 
 #include "llvm/Transforms/IPO.h"
@@ -59,14 +60,16 @@
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
 
-#include "llvm/Type.h"
+#include "llvm/Constants.h"
 #include "llvm/GlobalValue.h"
 #include "llvm/Linker.h"
 #include "llvm/LLVMContext.h"
 #include "llvm/Metadata.h"
 #include "llvm/Module.h"
 #include "llvm/PassManager.h"
+#include "llvm/Type.h"
 #include "llvm/Value.h"
 
 #include <errno.h>
@@ -82,6 +85,8 @@
 #include <string>
 #include <vector>
 
+extern char* gDebugDumpDirectory;
+
 namespace bcc {
 
 //////////////////////////////////////////////////////////////////////////////
@@ -140,6 +145,12 @@
 // synced with slang_rs_metadata.h)
 const llvm::StringRef Compiler::ObjectSlotMetadataName = "#rs_object_slots";
 
+// Name of metadata node where RS optimization level resides (should be
+// synced with slang_rs_metadata.h)
+const llvm::StringRef OptimizationLevelMetadataName = "#optimization_level";
+
+
+
 //////////////////////////////////////////////////////////////////////////////
 // Compiler
 //////////////////////////////////////////////////////////////////////////////
@@ -226,23 +237,9 @@
   InitializeDisassembler();
 #endif
 
-  // -O0: llvm::CodeGenOpt::None
-  // -O1: llvm::CodeGenOpt::Less
-  // -O2: llvm::CodeGenOpt::Default
-  // -O3: llvm::CodeGenOpt::Aggressive
-  CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
-
   // Register the scheduler
   llvm::RegisterScheduler::setDefault(llvm::createDefaultScheduler);
 
-  // Register allocation policy:
-  //  createFastRegisterAllocator: fast but bad quality
-  //  createLinearScanRegisterAllocator: not so fast but good quality
-  llvm::RegisterRegAlloc::setDefault
-    ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
-     llvm::createFastRegisterAllocator :
-     llvm::createGreedyRegisterAllocator);
-
 #if USE_CACHE
   // Read in SHA1 checksum of libbcc and libRS.
   readSHA1(sha1LibBCC_SHA1, sizeof(sha1LibBCC_SHA1), pathLibBCC_SHA1);
@@ -313,6 +310,9 @@
 
   std::string FeaturesStr;
 
+  if (mModule == NULL)  // No module was loaded
+    return 0;
+
   llvm::NamedMDNode const *PragmaMetadata;
   llvm::NamedMDNode const *ExportVarMetadata;
   llvm::NamedMDNode const *ExportFuncMetadata;
@@ -324,8 +324,37 @@
   std::vector<std::string> ForEachExpandList;
   std::vector<uint32_t> forEachSigList;
 
-  if (mModule == NULL)  // No module was loaded
-    return 0;
+  llvm::NamedMDNode const *OptimizationLevelMetadata =
+    mModule->getNamedMetadata(OptimizationLevelMetadataName);
+
+  // Default to maximum optimization in the absence of named metadata node
+  int OptimizationLevel = 3;
+  if (OptimizationLevelMetadata) {
+    llvm::ConstantInt* OL = llvm::dyn_cast<llvm::ConstantInt>(
+      OptimizationLevelMetadata->getOperand(0)->getOperand(0));
+    OptimizationLevel = OL->getZExtValue();
+  }
+
+  if (OptimizationLevel == 0) {
+    CodeGenOptLevel = llvm::CodeGenOpt::None;
+  } else if (OptimizationLevel == 1) {
+    CodeGenOptLevel = llvm::CodeGenOpt::Less;
+  } else if (OptimizationLevel == 2) {
+    CodeGenOptLevel = llvm::CodeGenOpt::Default;
+  } else if (OptimizationLevel == 3) {
+    CodeGenOptLevel = llvm::CodeGenOpt::Aggressive;
+  }
+
+  // not the best place for this, but we need to set the register allocation
+  // policy after we read the optimization_level metadata from the bitcode
+
+  // Register allocation policy:
+  //  createFastRegisterAllocator: fast but bad quality
+  //  createLinearScanRegisterAllocator: not so fast but good quality
+  llvm::RegisterRegAlloc::setDefault
+    ((CodeGenOptLevel == llvm::CodeGenOpt::None) ?
+     llvm::createFastRegisterAllocator :
+     llvm::createGreedyRegisterAllocator);
 
   // Find LLVM Target
   Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
@@ -410,7 +439,7 @@
   // Perform link-time optimization if we have multiple modules
   if (mHasLinked) {
     runLTO(new llvm::TargetData(*TD), ExportVarMetadata, ExportFuncMetadata,
-           ForEachExpandList);
+           ForEachExpandList, CodeGenOptLevel);
   }
 
   // Perform code generation
@@ -440,6 +469,9 @@
     goto on_bcc_compile_error;
   }
 
+  rsloaderUpdateSectionHeaders(mRSExecutable,
+    (unsigned char*) mEmittedELFExecutable.begin());
+
   if (ExportVarMetadata) {
     ScriptCompiled::ExportVarList &varList = mpResult->mExportVars;
     std::vector<std::string> &varNameList = mpResult->mExportVarsName;
@@ -754,7 +786,7 @@
   MCCodeGenPasses.add(TD);
 
   // Add MC code generation passes to pass manager
-  llvm::MCContext *Ctx;
+  llvm::MCContext *Ctx = NULL;
   if (TM->addPassesToEmitMC(MCCodeGenPasses, Ctx, OutSVOS, false)) {
     setError("Fail to add passes to emit file");
     return 1;
@@ -781,12 +813,8 @@
 int Compiler::runLTO(llvm::TargetData *TD,
                      llvm::NamedMDNode const *ExportVarMetadata,
                      llvm::NamedMDNode const *ExportFuncMetadata,
-                     std::vector<std::string>& ForEachExpandList) {
-  llvm::PassManager LTOPasses;
-
-  // Add TargetData to LTO passes
-  LTOPasses.add(TD);
-
+                     std::vector<std::string>& ForEachExpandList,
+                     llvm::CodeGenOpt::Level OptimizationLevel) {
   // Collect All Exported Symbols
   std::vector<const char*> ExportSymbols;
 
@@ -840,85 +868,111 @@
             UserDefinedExternalSymbols.end(),
             std::back_inserter(ExportSymbols));
 
+  llvm::PassManager LTOPasses;
+
+  // Add TargetData to LTO passes
+  LTOPasses.add(TD);
+
   // We now create passes list performing LTO. These are copied from
   // (including comments) llvm::createStandardLTOPasses().
+  // Only a subset of these LTO passes are enabled in optimization level 0
+  // as they interfere with interactive debugging.
+  // FIXME: figure out which passes (if any) makes sense for levels 1 and 2
 
-  // Internalize all other symbols not listed in ExportSymbols
-  LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
+  if (OptimizationLevel != llvm::CodeGenOpt::None) {
+    // Internalize all other symbols not listed in ExportSymbols
+    LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
 
-  // Propagate constants at call sites into the functions they call. This
-  // opens opportunities for globalopt (and inlining) by substituting
-  // function pointers passed as arguments to direct uses of functions.
-  LTOPasses.add(llvm::createIPSCCPPass());
+    // Propagate constants at call sites into the functions they call. This
+    // opens opportunities for globalopt (and inlining) by substituting
+    // function pointers passed as arguments to direct uses of functions.
+    LTOPasses.add(llvm::createIPSCCPPass());
 
-  // Now that we internalized some globals, see if we can hack on them!
-  LTOPasses.add(llvm::createGlobalOptimizerPass());
+    // Now that we internalized some globals, see if we can hack on them!
+    LTOPasses.add(llvm::createGlobalOptimizerPass());
 
-  // Linking modules together can lead to duplicated global constants, only
-  // keep one copy of each constant...
-  LTOPasses.add(llvm::createConstantMergePass());
+    // Linking modules together can lead to duplicated global constants, only
+    // keep one copy of each constant...
+    LTOPasses.add(llvm::createConstantMergePass());
 
-  // Remove unused arguments from functions...
-  LTOPasses.add(llvm::createDeadArgEliminationPass());
+    // Remove unused arguments from functions...
+    LTOPasses.add(llvm::createDeadArgEliminationPass());
 
-  // Reduce the code after globalopt and ipsccp. Both can open up
-  // significant simplification opportunities, and both can propagate
-  // functions through function pointers. When this happens, we often have
-  // to resolve varargs calls, etc, so let instcombine do this.
-  LTOPasses.add(llvm::createInstructionCombiningPass());
+    // Reduce the code after globalopt and ipsccp. Both can open up
+    // significant simplification opportunities, and both can propagate
+    // functions through function pointers. When this happens, we often have
+    // to resolve varargs calls, etc, so let instcombine do this.
+    LTOPasses.add(llvm::createInstructionCombiningPass());
 
-  // Inline small functions
-  LTOPasses.add(llvm::createFunctionInliningPass());
+    // Inline small functions
+    LTOPasses.add(llvm::createFunctionInliningPass());
 
-  // Remove dead EH info.
-  LTOPasses.add(llvm::createPruneEHPass());
+    // Remove dead EH info.
+    LTOPasses.add(llvm::createPruneEHPass());
 
-  // Internalize the globals again after inlining
-  LTOPasses.add(llvm::createGlobalOptimizerPass());
+    // Internalize the globals again after inlining
+    LTOPasses.add(llvm::createGlobalOptimizerPass());
 
-  // Remove dead functions.
-  LTOPasses.add(llvm::createGlobalDCEPass());
+    // Remove dead functions.
+    LTOPasses.add(llvm::createGlobalDCEPass());
 
-  // If we didn't decide to inline a function, check to see if we can
-  // transform it to pass arguments by value instead of by reference.
-  LTOPasses.add(llvm::createArgumentPromotionPass());
+    // If we didn't decide to inline a function, check to see if we can
+    // transform it to pass arguments by value instead of by reference.
+    LTOPasses.add(llvm::createArgumentPromotionPass());
 
-  // The IPO passes may leave cruft around.  Clean up after them.
-  LTOPasses.add(llvm::createInstructionCombiningPass());
-  LTOPasses.add(llvm::createJumpThreadingPass());
+    // The IPO passes may leave cruft around.  Clean up after them.
+    LTOPasses.add(llvm::createInstructionCombiningPass());
+    LTOPasses.add(llvm::createJumpThreadingPass());
 
-  // Break up allocas
-  LTOPasses.add(llvm::createScalarReplAggregatesPass());
+    // Break up allocas
+    LTOPasses.add(llvm::createScalarReplAggregatesPass());
 
-  // Run a few AA driven optimizations here and now, to cleanup the code.
-  LTOPasses.add(llvm::createFunctionAttrsPass());  // Add nocapture.
-  LTOPasses.add(llvm::createGlobalsModRefPass());  // IP alias analysis.
+    // Run a few AA driven optimizations here and now, to cleanup the code.
+    LTOPasses.add(llvm::createFunctionAttrsPass());  // Add nocapture.
+    LTOPasses.add(llvm::createGlobalsModRefPass());  // IP alias analysis.
 
-  // Hoist loop invariants.
-  LTOPasses.add(llvm::createLICMPass());
+    // Hoist loop invariants.
+    LTOPasses.add(llvm::createLICMPass());
 
-  // Remove redundancies.
-  LTOPasses.add(llvm::createGVNPass());
+    // Remove redundancies.
+    LTOPasses.add(llvm::createGVNPass());
 
-  // Remove dead memcpys.
-  LTOPasses.add(llvm::createMemCpyOptPass());
+    // Remove dead memcpys.
+    LTOPasses.add(llvm::createMemCpyOptPass());
 
-  // Nuke dead stores.
-  LTOPasses.add(llvm::createDeadStoreEliminationPass());
+    // Nuke dead stores.
+    LTOPasses.add(llvm::createDeadStoreEliminationPass());
 
-  // Cleanup and simplify the code after the scalar optimizations.
-  LTOPasses.add(llvm::createInstructionCombiningPass());
+    // Cleanup and simplify the code after the scalar optimizations.
+    LTOPasses.add(llvm::createInstructionCombiningPass());
 
-  LTOPasses.add(llvm::createJumpThreadingPass());
+    LTOPasses.add(llvm::createJumpThreadingPass());
 
-  // Delete basic blocks, which optimization passes may have killed.
-  LTOPasses.add(llvm::createCFGSimplificationPass());
+    // Delete basic blocks, which optimization passes may have killed.
+    LTOPasses.add(llvm::createCFGSimplificationPass());
 
-  // Now that we have optimized the program, discard unreachable functions.
-  LTOPasses.add(llvm::createGlobalDCEPass());
+    // Now that we have optimized the program, discard unreachable functions.
+    LTOPasses.add(llvm::createGlobalDCEPass());
+
+  } else {
+    LTOPasses.add(llvm::createInternalizePass(ExportSymbols));
+    LTOPasses.add(llvm::createGlobalOptimizerPass());
+    LTOPasses.add(llvm::createConstantMergePass());
+  }
 
   LTOPasses.run(*mModule);
 
+#if ANDROID_ENGINEERING_BUILD
+  if (0 != gDebugDumpDirectory) {
+    std::string errs;
+    std::string Filename(gDebugDumpDirectory);
+    Filename += "/post-lto-module.ll";
+    llvm::raw_fd_ostream FS(Filename.c_str(), errs);
+    mModule->print(FS, 0);
+    FS.close();
+  }
+#endif
+
   return 0;
 }