Hi hfinkel, atrick, chandlerc,

This patch adds command line option for iterative compilation, as well
as the code that invokes clang iteratively.
Communication between multiple runs is done over temporary files.

http://reviews.llvm.org/D4724

Files:
  include/clang/Driver/Compilation.h
  include/clang/Driver/Driver.h
  include/clang/Driver/Options.td
  lib/CodeGen/BackendUtil.cpp
  lib/Driver/Driver.cpp
  lib/Driver/Tools.cpp
  tools/driver/driver.cpp
Index: include/clang/Driver/Compilation.h
===================================================================
--- include/clang/Driver/Compilation.h
+++ include/clang/Driver/Compilation.h
@@ -14,6 +14,7 @@
 #include "clang/Driver/Util.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Analysis/DecisionTree.h"
 
 namespace llvm {
 namespace opt {
@@ -69,6 +70,8 @@
   /// Redirection for stdout, stderr, etc.
   const StringRef **Redirects;
 
+  llvm::ModuleDecisionTrees *moduleDecisionTrees;
+
   /// Whether we're compiling for diagnostic purposes.
   bool ForDiagnostics;
 
@@ -107,6 +110,10 @@
   /// Returns the sysroot path.
   StringRef getSysRoot() const;
 
+  llvm::ModuleDecisionTrees *getModuleDecisionTrees() const { return moduleDecisionTrees; }
+
+  void setModuleDecisionTrees(llvm::ModuleDecisionTrees *x) { moduleDecisionTrees = x; }
+
   /// getArgsForToolChain - Return the derived argument list for the
   /// tool chain \p TC (or the default tool chain, if TC is not specified).
   ///
Index: include/clang/Driver/Driver.h
===================================================================
--- include/clang/Driver/Driver.h
+++ include/clang/Driver/Driver.h
@@ -18,6 +18,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/DecisionTree.h"
 #include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo
 #include <memory>
                               // lands.
@@ -153,6 +154,9 @@
   /// Whether the driver is generating diagnostics for debugging purposes.
   unsigned CCGenDiagnostics : 1;
 
+  /// Module decision trees for iterative compilation.
+  llvm::ModuleDecisionTrees *moduleDecisionTrees;
+
 private:
   /// Name to use when invoking gcc/g++.
   std::string CCCGenericGCCName;
@@ -199,6 +203,9 @@
   /// @name Accessors
   /// @{
 
+  llvm::ModuleDecisionTrees *getModuleDecisionTrees() const { return moduleDecisionTrees; }
+  void setModuleDecisionTrees(llvm::ModuleDecisionTrees *x) { moduleDecisionTrees = x; }
+
   /// Name to use when invoking gcc/g++.
   const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; }
 
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -473,6 +473,8 @@
   HelpText<"Emit all declarations, even if unused">;
 def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>;
 def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>, Flags<[CoreOption]>;
+def fiterative_comp_EQ : Joined<["-"], "fiterative-comp=">, Group<f_Group>,
+  HelpText<"Number of iterations for iterative compilation">;
 def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Enable support for exception handling">;
 def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -38,6 +38,7 @@
 #include "llvm/Transforms/Instrumentation.h"
 #include "llvm/Transforms/ObjCARC.h"
 #include "llvm/Transforms/Scalar.h"
+#include "llvm/Analysis/Passes.h"
 #include <memory>
 using namespace clang;
 using namespace llvm;
@@ -197,6 +198,7 @@
   if (Builder.OptLevel > 0) {
     PM.add(createEarlyCSEPass());
     PM.add(createReassociatePass());
+    PM.add(createICSetCurrentFuncPass());
     PM.add(createLICMPass());
     PM.add(createGVNPass());
     PM.add(createInstructionCombiningPass());
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -55,8 +55,8 @@
     CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
     CCLogDiagnosticsFilename(nullptr),
     CCCPrintBindings(false),
-    CCPrintHeaders(false), CCLogDiagnostics(false),
-    CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
+    CCGenDiagnostics(false), moduleDecisionTrees(0),
+    CCCGenericGCCName(""), CheckInputsExist(true),
     CCCUsePCH(true), SuppressMissingInputWarning(false) {
 
   Name = llvm::sys::path::stem(ClangExecutable);
@@ -370,6 +370,8 @@
   // The compilation takes ownership of Args.
   Compilation *C = new Compilation(*this, TC, Args, TranslatedArgs);
 
+  C->setModuleDecisionTrees(moduleDecisionTrees);
+
   if (!HandleImmediateArgs(*C))
     return C;
 
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -38,6 +38,8 @@
 #include "llvm/Support/Process.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Analysis/DecisionTree.h"
+#include <sstream>
 
 using namespace clang::driver;
 using namespace clang::driver::tools;
@@ -3455,6 +3457,30 @@
     CmdArgs.push_back(A->getValue());
   else
     CmdArgs.push_back("19");
+  if (Arg *A = Args.getLastArg(options::OPT_fiterative_comp_EQ)) {
+    std::string Val = A->getValue();
+    int IterNo;
+    std::stringstream Convert(Val);
+    Convert >> IterNo;
+    if (IterNo > 1) {
+      CmdArgs.push_back("-mllvm");
+      CmdArgs.push_back("-fiterative-comp");
+      CmdArgs.push_back("-mllvm");
+      llvm::ModuleDecisionTrees *ModDecisionTrees =
+        C.getModuleDecisionTrees();
+      std::string &OptIF = ModDecisionTrees->getICInputFileOpt();
+      OptIF = "-fic-input-file=" + ModDecisionTrees->getICInputFile();
+      CmdArgs.push_back(OptIF.c_str());
+      CmdArgs.push_back("-mllvm");
+      std::string &OptRF = ModDecisionTrees->getICResultsFileOpt();
+      OptRF = "-fic-results-file=" + ModDecisionTrees->getICResultsFile();
+      CmdArgs.push_back(OptRF.c_str());
+      CmdArgs.push_back("-mllvm");
+      std::string &OptRF2 = ModDecisionTrees->getICResultsFile2Opt();
+      OptRF2 = "-fic-results2-file=" + ModDecisionTrees->getICResultsFile2();
+      CmdArgs.push_back(OptRF2.c_str());
+    }
+  }
 
   if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) {
     CmdArgs.push_back("-fmacro-backtrace-limit");
Index: tools/driver/driver.cpp
===================================================================
--- tools/driver/driver.cpp
+++ tools/driver/driver.cpp
@@ -47,6 +47,10 @@
 #include "llvm/Support/raw_ostream.h"
 #include <memory>
 #include <system_error>
+#include "llvm/Analysis/DecisionTree.h"
+#include "llvm/Support/Program.h"
+#include <string>
+#include <sstream>
 using namespace clang;
 using namespace clang::driver;
 using namespace llvm::opt;
@@ -371,84 +375,182 @@
   DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
   ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
 
-  Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
+  // Get number of iterations for iterative compilation.
+  int ICNumberOfIterations = 0;
+  std::string ICInputFile;
+  std::string ICResultsFile;
+  std::string ICResultsFile2;
+
+  std::unique_ptr<OptTable> CCopts(createDriverOptTable());
+  unsigned MissingArgIndex, MissingArgCount;
+  std::unique_ptr<InputArgList> Args(CCopts->ParseArgs(argv.begin()+1, argv.end(),
+                                            MissingArgIndex, MissingArgCount));
+  if (Args->getLastArg(options::OPT_fiterative_comp_EQ)) {
+    std::string Val = Args->getLastArgValue(options::OPT_fiterative_comp_EQ, "1");
+    std::stringstream Convert(Val);
+    Convert >> ICNumberOfIterations;
+   }
+  if (!ICNumberOfIterations)
+    ICNumberOfIterations = 1; // Default value is 1.
+
+  llvm::ModuleDecisionTrees moduleDecisionTrees;
+
+  int CurrentIteration = 0;
+  int Res = 0;
 
-  // Attempt to find the original path used to invoke the driver, to determine
-  // the installed path. We do this manually, because we want to support that
-  // path being a symlink.
-  {
-    SmallString<128> InstalledPath(argv[0]);
-
-    // Do a PATH lookup, if there are no directory components.
-    if (llvm::sys::path::filename(InstalledPath) == InstalledPath) {
-      std::string Tmp = llvm::sys::FindProgramByName(
-        llvm::sys::path::filename(InstalledPath.str()));
-      if (!Tmp.empty())
-        InstalledPath = Tmp;
+  llvm::ModuleDecisionTrees::IterativeCompilationPhase ICPhase =
+    llvm::ModuleDecisionTrees::ModulePhase;
+
+  for (; CurrentIteration < ICNumberOfIterations; CurrentIteration++) {
+    Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple()
+                     , Diags);
+    // Attempt to find the original path used to invoke the driver, to determine
+    // the installed path. We do this manually, because we want to support that
+    // path being a symlink.
+    {
+      SmallString<128> InstalledPath(argv[0]);
+
+      // Do a PATH lookup, if there are no directory components.
+      if (llvm::sys::path::filename(InstalledPath) == InstalledPath) {
+        std::string Tmp = llvm::sys::FindProgramByName(
+          llvm::sys::path::filename(InstalledPath.str()));
+        if (!Tmp.empty())
+          InstalledPath = Tmp;
+      }
+      llvm::sys::fs::make_absolute(InstalledPath);
+      InstalledPath = llvm::sys::path::parent_path(InstalledPath);
+      bool exists;
+      if (!llvm::sys::fs::exists(InstalledPath.str(), exists) && exists)
+        TheDriver.setInstalledDir(InstalledPath);
     }
-    llvm::sys::fs::make_absolute(InstalledPath);
-    InstalledPath = llvm::sys::path::parent_path(InstalledPath);
-    bool exists;
-    if (!llvm::sys::fs::exists(InstalledPath.str(), exists) && exists)
-      TheDriver.setInstalledDir(InstalledPath);
-  }
+    llvm::InitializeAllTargets();
+    ParseProgName(argv, SavedStrings, TheDriver);
+
+    // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
+    TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
+    if (TheDriver.CCPrintOptions)
+      TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE");
+
+    // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE.
+    TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS");
+    if (TheDriver.CCPrintHeaders)
+      TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE");
+
+    // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE.
+    TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
+    if (TheDriver.CCLogDiagnostics)
+      TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
+
+    if (ICNumberOfIterations > 1) {
+      std::string ErrMsg;
+      SmallString<128> PathVec;
+      if (llvm::sys::fs::createTemporaryFile("ic-input","", PathVec)) {
+        llvm::errs() << "Error creating temporary file: " << ErrMsg << "\n";
+        ICNumberOfIterations = 1;
+      }
 
-  llvm::InitializeAllTargets();
-  ParseProgName(argv, SavedStrings, TheDriver);
+      ICInputFile = PathVec.c_str();
 
-  // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
-  TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");
-  if (TheDriver.CCPrintOptions)
-    TheDriver.CCPrintOptionsFilename = ::getenv("CC_PRINT_OPTIONS_FILE");
+      SmallString<128> ResPath;
+      if (llvm::sys::fs::createTemporaryFile("ic-results","", ResPath)) {
+        llvm::errs() << "Error creating temporary file: " << ErrMsg << "\n";
+        ICNumberOfIterations = 1;
+      }
+      ICResultsFile = ResPath.c_str();
 
-  // Handle CC_PRINT_HEADERS and CC_PRINT_HEADERS_FILE.
-  TheDriver.CCPrintHeaders = !!::getenv("CC_PRINT_HEADERS");
-  if (TheDriver.CCPrintHeaders)
-    TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE");
+      SmallString<128> ResPath1;
+      if (llvm::sys::fs::createTemporaryFile("ic-results2","", ResPath1)) {
+        llvm::errs() << "Error creating temporary file: " << ErrMsg << "\n";
+        ICNumberOfIterations = 1;
+      }
+      ICResultsFile2 = ResPath1.c_str();
+
+      moduleDecisionTrees.getICInputFile() = ICInputFile;
+      moduleDecisionTrees.getICResultsFile() = ICResultsFile;
+      moduleDecisionTrees.getICResultsFile2() = ICResultsFile2;
+      TheDriver.setModuleDecisionTrees(&moduleDecisionTrees);
+
+      std::map<std::string, std::vector<bool> > paths;
+      moduleDecisionTrees.getPaths(paths);
+      std::string pathsStr =
+        llvm::ModuleDecisionTrees::generateMdtPathsString(paths);
+      llvm::DecisionTree::writeToFile(ICInputFile, pathsStr);
+    }
 
-  // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE.
-  TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS");
-  if (TheDriver.CCLogDiagnostics)
-    TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE");
+    std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv));
+    SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
+    if (C.get())
+      Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
+
+    if (ICNumberOfIterations > 1) {
+      // Load the results file.
+      std::string ResultsStr = llvm::DecisionTree::readFromFile(ICResultsFile);
+      std::map<std::string, std::vector<int> > Results;
+      llvm::ModuleDecisionTrees::parseMdtResults(Results, ResultsStr);
+
+      std::string ResultsStr2 = llvm::DecisionTree::readFromFile(ICResultsFile2);
+      std::map<std::string, std::vector<int> > Results2;
+      llvm::ModuleDecisionTrees::parseMdtResults(Results2, ResultsStr2);
+
+      llvm::sys::fs::remove(ICInputFile);
+      llvm::sys::fs::remove(ICResultsFile);
+      llvm::sys::fs::remove(ICResultsFile2);
+
+      Results.insert(Results2.begin(),Results2.end());
+
+      // Calculate the new decision three paths.
+      if (ICPhase == llvm::ModuleDecisionTrees::ModulePhase) {
+        int TotalFittness =
+          llvm::ModuleDecisionTrees::calculateTotalFitness(Results2);
+        std::string ModuleNameId = "module-id";
+        llvm::DecisionTree &dt =
+          moduleDecisionTrees.getDecisionTree(ModuleNameId);
+        std::vector<int> ModuleResults = Results[ModuleNameId];
+        dt.applayResults(ModuleResults);
+        dt.setFunctionFitness(TotalFittness);
+        dt.updateBestFunctionFitness(CurrentIteration);
+        dt.updatePriorities();
+        bool FinalIteration = false;
+        if (CurrentIteration >= ICNumberOfIterations - 2)
+          FinalIteration = true;
+        bool finished = dt.selectPath(FinalIteration);
+        if (finished && CurrentIteration < (ICNumberOfIterations - 2))
+          CurrentIteration = ICNumberOfIterations - 2;
+      }
+    }
 
-  std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(argv));
-  int Res = 0;
-  SmallVector<std::pair<int, const Command *>, 4> FailingCommands;
-  if (C.get())
-    Res = TheDriver.ExecuteCompilation(*C, FailingCommands);
-
-  // Force a crash to test the diagnostics.
-  if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) {
-    Diags.Report(diag::err_drv_force_crash) << "FORCE_CLANG_DIAGNOSTICS_CRASH";
-    const Command *FailingCommand = nullptr;
-    FailingCommands.push_back(std::make_pair(-1, FailingCommand));
-  }
+    // Force a crash to test the diagnostics.
+    if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) {
+      Diags.Report(diag::err_drv_force_crash) << "FORCE_CLANG_DIAGNOSTICS_CRASH";
+      const Command *FailingCommand = nullptr;
+      FailingCommands.push_back(std::make_pair(-1, FailingCommand));
+    }
 
-  for (SmallVectorImpl< std::pair<int, const Command *> >::iterator it =
-         FailingCommands.begin(), ie = FailingCommands.end(); it != ie; ++it) {
-    int CommandRes = it->first;
-    const Command *FailingCommand = it->second;
-    if (!Res)
-      Res = CommandRes;
-
-    // If result status is < 0, then the driver command signalled an error.
-    // If result status is 70, then the driver command reported a fatal error.
-    // On Windows, abort will return an exit code of 3.  In these cases,
-    // generate additional diagnostic information if possible.
-    bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70;
+    for (SmallVectorImpl< std::pair<int, const Command *> >::iterator it =
+           FailingCommands.begin(), ie = FailingCommands.end(); it != ie; ++it) {
+      int CommandRes = it->first;
+      const Command *FailingCommand = it->second;
+      if (!Res)
+        Res = CommandRes;
+
+      // If result status is < 0, then the driver command signalled an error.
+      // If result status is 70, then the driver command reported a fatal error.
+      // On Windows, abort will return an exit code of 3.  In these cases,
+      // generate additional diagnostic information if possible.
+      bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70;
 #ifdef LLVM_ON_WIN32
-    DiagnoseCrash |= CommandRes == 3;
+      DiagnoseCrash |= CommandRes == 3;
 #endif
-    if (DiagnoseCrash) {
-      TheDriver.generateCompilationDiagnostics(*C, FailingCommand);
-      break;
+      if (DiagnoseCrash) {
+        TheDriver.generateCompilationDiagnostics(*C, FailingCommand);
+        break;
+      }
     }
-  }
 
-  // If any timers were active but haven't been destroyed yet, print their
-  // results now.  This happens in -disable-free mode.
-  llvm::TimerGroup::printAll(llvm::errs());
-  
+    // If any timers were active but haven't been destroyed yet, print their
+    // results now.  This happens in -disable-free mode.
+    llvm::TimerGroup::printAll(llvm::errs());
+  }
   llvm::llvm_shutdown();
 
 #ifdef LLVM_ON_WIN32
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to