Index: include/clang/Driver/Compilation.h =================================================================== --- include/clang/Driver/Compilation.h +++ include/clang/Driver/Compilation.h @@ -15,6 +15,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 { @@ -77,6 +78,8 @@ /// Redirection for stdout, stderr, etc. const StringRef **Redirects; + llvm::ModuleDecisionTrees *moduleDecisionTrees; + /// Whether we're compiling for diagnostic purposes. bool ForDiagnostics; @@ -135,6 +138,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 @@ -19,7 +19,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/Path.h" // FIXME: Kill when CompilationInfo lands. - +#include "llvm/Analysis/IterativeCompilation.h" #include #include #include @@ -182,6 +182,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; @@ -234,6 +237,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 @@ -573,6 +573,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 @@ -44,6 +44,7 @@ #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" +#include "llvm/Analysis/Passes.h" #include using namespace clang; using namespace llvm; Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -58,7 +58,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) { // Provide a sane fallback if no VFS is specified. if (!this->VFS) @@ -532,6 +533,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(). @@ -4745,6 +4747,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,11 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include "llvm/Analysis/IterativeCompilation.h" +#include "llvm/Support/Program.h" +#include +#include +#include using namespace clang; using namespace clang::driver; using namespace llvm::opt; @@ -307,6 +312,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_); @@ -437,6 +516,34 @@ 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. + + std::string moduleName = llvm::getModuleName(argc_, argv_); + + llvm::ModuleDecisionTrees moduleDecisionTrees(ICNumberOfIterations, true, moduleName); + int CurrentIteration = 0; + int Res = 0; + + llvm::FnNameAndPhase::ICPhase CurrICPhase = llvm::FnNameAndPhase::ModulePhase; + + // start of iterative compilation loop + for (; CurrentIteration < ICNumberOfIterations; CurrentIteration++) { ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false); Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags); @@ -447,12 +554,34 @@ 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); + + moduleDecisionTrees.applyResults(MergerdResults); + int totalFitness = llvm::MdtResults::calculateTotalFitness(MergerdResults); + moduleDecisionTrees.setFunctionFitness(totalFitness); + moduleDecisionTrees.updateBestFunctionFitness(CurrentIteration); + moduleDecisionTrees.selectPath(false); + } + // Force a crash to test the diagnostics. if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) { Diags.Report(diag::err_drv_force_crash) << "FORCE_CLANG_DIAGNOSTICS_CRASH"; @@ -489,7 +618,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()); - + } llvm::llvm_shutdown(); #ifdef LLVM_ON_WIN32