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/IterativeCompilation.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/IterativeCompilation.h" #include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo #include // lands. @@ -157,6 +158,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; @@ -209,6 +213,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 @@ -528,6 +528,8 @@ def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group; 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 fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -40,6 +40,7 @@ #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" +#include "llvm/Analysis/Passes.h" #include using namespace clang; using namespace llvm; @@ -224,6 +225,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,7 +55,8 @@ CCPrintHeadersFilename(nullptr), CCLogDiagnosticsFilename(nullptr), CCCPrintBindings(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), - CCCUsePCH(true), SuppressMissingInputWarning(false) { + CCCUsePCH(true), SuppressMissingInputWarning(false), + moduleDecisionTrees(0) { Name = llvm::sys::path::filename(ClangExecutable); Dir = llvm::sys::path::parent_path(ClangExecutable); @@ -454,6 +455,8 @@ // The compilation takes ownership of Args. Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs); + C->setModuleDecisionTrees(moduleDecisionTrees); + if (!HandleImmediateArgs(*C)) return C; Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -42,6 +42,8 @@ #include "llvm/Support/Program.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/TargetParser.h" +#include "llvm/Analysis/ICUtils.h" +#include #ifdef LLVM_ON_UNIX #include // For getuid(). @@ -4043,6 +4045,34 @@ 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"); + llvm::ModuleDecisionTrees *ModDecisionTrees = + C.getModuleDecisionTrees(); + CmdArgs.push_back("-mllvm"); + std::string &OptIF = ModDecisionTrees->getICInputFileOpt(); + OptIF = "-fic-input-file=" + ModDecisionTrees->getICInputFile().getFilename(); + CmdArgs.push_back(OptIF.c_str()); + CmdArgs.push_back("-mllvm"); + std::string &OptIF2 = ModDecisionTrees->getICInputFile2Opt(); + OptIF2 = "-fic-input2-file=" + ModDecisionTrees->getICInputFile2().getFilename(); + CmdArgs.push_back(OptIF2.c_str()); + CmdArgs.push_back("-mllvm"); + std::string &OptRF = ModDecisionTrees->getICResultsFileOpt(); + OptRF = "-fic-results-file=" + ModDecisionTrees->getICResultsFile().getFilename(); + CmdArgs.push_back(OptRF.c_str()); + CmdArgs.push_back("-mllvm"); + std::string &OptRF2 = ModDecisionTrees->getICResultsFile2Opt(); + OptRF2 = "-fic-results2-file=" + ModDecisionTrees->getICResultsFile2().getFilename(); + 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 @@ -50,6 +50,10 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include "llvm/Analysis/IterativeCompilation.h" +#include "llvm/Support/Program.h" +#include +#include using namespace clang; using namespace clang::driver; using namespace llvm::opt; @@ -386,6 +390,80 @@ return 1; } +void initControlFiles(llvm::ModuleDecisionTrees &MDT, int CurrentIteration) +{ + std::string ICResultsFile; + std::string ICResultsFile2; + + // assign control files + llvm::ICResultsFile results1("ic-results", CurrentIteration); + llvm::ICResultsFile results2("ic-results2", CurrentIteration); + MDT.getICResultsFile() = results1; + MDT.getICResultsFile2() = results2; + + llvm::ICInputFile input1("ic-input", CurrentIteration); + llvm::ICInputFile input2("ic-input2", CurrentIteration); + MDT.getICInputFile() = input1; + MDT.getICInputFile2() = input2; +} + +void writeInputFiles(llvm::ModuleDecisionTrees &MDT) +{ + // inits and declarations + llvm::ICPathsMap paths; + llvm::ICPathsMap pathBeforeCodegen; + llvm::ICPathsMap pathAfterCodegen; + + // split paths + MDT.getPaths(paths); + MDT.splitPaths(paths, pathBeforeCodegen, pathAfterCodegen); + + // convert paths to strings and write them to files + llvm::ICInputFile input1 = MDT.getICInputFile(); + llvm::ICInputFile input2 = MDT.getICInputFile2(); + + input1.setPaths(pathBeforeCodegen); + input2.setPaths(pathAfterCodegen); + + input1.write(); + input2.write(); +} + +void removeControlFiles(llvm::ModuleDecisionTrees &MDT) { + MDT.getICResultsFile().remove(); + MDT.getICResultsFile2().remove(); +} + +int loadResultFiles(llvm::ModuleDecisionTrees &MDT, + std::vector &merged) { + llvm::ICResultsFile results1 = MDT.getICResultsFile(); + llvm::ICResultsFile results2 = MDT.getICResultsFile2(); + + int r1 = results1.read(); + int r2 = results2.read(); + + if(r1 || r2) + return 1; + + llvm::MdtResults::mergeMdtResults(merged, + results1.getResults(), results2.getResults()); + + return 0; +} + +llvm::MdtResults* getModuleResults(std::vector &merged, + std::string name) +{ + llvm::MdtResults *moduleResults = NULL; + + for(auto res : merged) { + if (res.FunctionNameAndPhase.getName() == name) + moduleResults = new llvm::MdtResults(res); + } + + return moduleResults; +} + int main(int argc_, const char **argv_) { llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc_, argv_); @@ -506,6 +584,31 @@ Diags.takeClient(), std::move(SerializedConsumer))); } + // Get number of iterations for iterative compilation. + // declare files and number of iterations + int ICNumberOfIterations = 0; + + // extract number of iterations from cli args + std::unique_ptr CCopts(createDriverOptTable()); + unsigned MissingArgIndex, MissingArgCount; + ArrayRef argv_ref(argv); + InputArgList Args = CCopts->ParseArgs(argv_ref.slice(1), + 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; + + llvm::FnNameAndPhase::ICPhase CurrICPhase = llvm::FnNameAndPhase::ModulePhase; + + for (; CurrentIteration < ICNumberOfIterations; CurrentIteration++) { ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false); Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); @@ -516,12 +619,51 @@ SetBackdoorDriverOutputsFromEnvVars(TheDriver); + if (ICNumberOfIterations > 1) { + TheDriver.setModuleDecisionTrees(&moduleDecisionTrees); + + initControlFiles(moduleDecisionTrees, CurrentIteration); + writeInputFiles(moduleDecisionTrees); + + moduleDecisionTrees.startNewIteration(); + } + std::unique_ptr C(TheDriver.BuildCompilation(argv)); int Res = 0; SmallVector, 4> FailingCommands; if (C.get()) Res = TheDriver.ExecuteCompilation(*C, FailingCommands); + if (ICNumberOfIterations > 1) { + std::vector MergerdResults; + if(loadResultFiles(moduleDecisionTrees, MergerdResults)) + return 1; + removeControlFiles(moduleDecisionTrees); + + if (CurrICPhase == llvm::FnNameAndPhase::ModulePhase) { + std::string ModuleNameId = "module-id"; + llvm::FnNameAndPhase nameAndPhase(ModuleNameId, llvm::FnNameAndPhase::ModulePhase); + llvm::DecisionTree &dt = moduleDecisionTrees.getDecisionTree(nameAndPhase); + + llvm::MdtResults *ModuleResults; + ModuleResults = getModuleResults(MergerdResults, ModuleNameId); + + if (ModuleResults) + dt.applyResults(*ModuleResults); + + int TotalFittness = llvm::MdtResults::calculateTotalFitness(MergerdResults); + dt.setFunctionFitness(TotalFittness); + dt.updateBestFunctionFitness(CurrentIteration); + + bool FinalIteration = CurrentIteration >= ICNumberOfIterations - 2; + bool finished = dt.selectPath(FinalIteration); + + // early finish - tree is completely explored + if (finished && CurrentIteration < (ICNumberOfIterations - 2)) + CurrentIteration = ICNumberOfIterations - 2; + } + } + // Force a crash to test the diagnostics. if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) { Diags.Report(diag::err_drv_force_crash) << "FORCE_CLANG_DIAGNOSTICS_CRASH"; @@ -558,7 +700,7 @@ // 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()); - + } // iterative compiler llvm::llvm_shutdown(); #ifdef LLVM_ON_WIN32