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