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 // 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; def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group, Flags<[CoreOption]>; +def fiterative_comp_EQ : Joined<["-"], "fiterative-comp=">, Group, + HelpText<"Number of iterations for iterative compilation">; def fexceptions : Flag<["-"], "fexceptions">, Group, Flags<[CC1Option]>, HelpText<"Enable support for exception handling">; def : Flag<["-"], "fexpensive-optimizations">, 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 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 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 #include +#include "llvm/Analysis/DecisionTree.h" +#include "llvm/Support/Program.h" +#include +#include 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 CCopts(createDriverOptTable()); + unsigned MissingArgIndex, MissingArgCount; + std::unique_ptr 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 > 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 C(TheDriver.BuildCompilation(argv)); + SmallVector, 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 > Results; + llvm::ModuleDecisionTrees::parseMdtResults(Results, ResultsStr); + + std::string ResultsStr2 = llvm::DecisionTree::readFromFile(ICResultsFile2); + std::map > 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 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 C(TheDriver.BuildCompilation(argv)); - int Res = 0; - SmallVector, 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 >::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 >::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