12 #include <llvm/Support/CommandLine.h>
14 #include <unordered_map>
24 static std::unordered_map<OptimizationLevel, std::string_view> map({
31 JLM_ASSERT(map.find(optimizationLevel) != map.end());
32 return map[optimizationLevel];
38 static std::unordered_map<LanguageStandard, std::string_view> map(
50 JLM_ASSERT(map.find(languageStandard) != map.end());
51 return map[languageStandard];
121 std::string_view commandLineArgument)
124 if (commandLineArgument ==
"ThetaGammaInversion")
129 if (map.HasValue(commandLineArgument))
130 return map.LookupValue(commandLineArgument);
140 if (map.HasKey(optimizationId))
141 return map.LookupKey(optimizationId);
143 throw util::Error(
"Unknown optimization identifier");
148 std::string_view commandLineArgument)
169 throw util::Error(
"Unknown statistics identifier");
176 static std::unordered_map<InputFormat, std::string_view> map(
179 if (map.find(inputFormat) != map.end())
180 return map[inputFormat];
189 return mapping.at(outputFormat);
229 const std::unordered_map<JlmOptCommandLineOptions::OutputFormat, std::string_view> &
232 static std::unordered_map<OutputFormat, std::string_view> mapping = {
240 JLM_ASSERT(mapping.size() == lastIndex - firstIndex - 1);
261 static ::llvm::cl::OptionEnumValue
270 static ::llvm::cl::OptionEnumValue
273 std::string_view description)
283 CommandLineParser::Exception::~Exception() noexcept = default;
285 JlcCommandLineParser::~JlcCommandLineParser() noexcept = default;
287 const JlcCommandLineOptions &
290 auto checkAndConvertJlmOptOptimizations =
291 [](const ::llvm::cl::list<std::string> & optimizations,
324 std::vector<JlmOptCommandLineOptions::OptimizationId> optimizationIds;
325 for (
auto & optimization : optimizations)
338 optimizationIds.emplace_back(optimizationId);
341 return optimizationIds;
344 CommandLineOptions_.Reset();
346 using namespace ::
llvm;
355 cl::TopLevelSubCommand->reset();
357 cl::opt<bool> onlyPrintCommands(
360 cl::desc(
"Print (but do not run) the commands for this compilation."));
362 cl::list<std::string> inputFiles(cl::Positional, cl::desc(
"<inputs>"));
364 cl::list<std::string> includePaths(
367 cl::desc(
"Add directory <dir> to include search paths."),
368 cl::value_desc(
"dir"));
370 cl::list<std::string> libraryPaths(
373 cl::desc(
"Add directory <dir> to library search paths."),
374 cl::value_desc(
"dir"));
376 cl::list<std::string> libraries(
379 cl::desc(
"Search the library <lib> when linking."),
380 cl::value_desc(
"lib"));
382 cl::opt<std::string> outputFile(
"o", cl::desc(
"Write output to <file>."), cl::value_desc(
"file"));
384 cl::opt<bool> generateDebugInformation(
387 cl::desc(
"Generate source-level debug information."));
389 cl::opt<bool> noLinking(
392 cl::desc(
"Only run preprocess, compile, and assemble steps."));
394 cl::opt<std::string> optimizationLevel(
398 cl::desc(
"Optimization level. [O0, O1, O2, O3]"),
399 cl::value_desc(
"#"));
401 cl::list<std::string> macroDefinitions(
404 cl::desc(
"Add <macro> to preprocessor macros."),
405 cl::value_desc(
"macro"));
407 cl::list<std::string> warnings(
410 cl::desc(
"Enable specified warning."),
411 cl::value_desc(
"warning"));
413 cl::opt<std::string> languageStandard(
415 cl::desc(
"Language standard."),
416 cl::value_desc(
"standard"));
418 cl::list<std::string> flags(
"f", cl::Prefix, cl::desc(
"Specify flags."), cl::value_desc(
"flag"));
420 cl::list<std::string> jlmOptimizations(
423 cl::desc(
"jlm-opt optimization. Run 'jlm-opt -help' for viable options."),
424 cl::value_desc(
"jlmopt"));
426 cl::opt<bool> verbose(
429 cl::desc(
"Show commands to run and use verbose output. (Affects only clang for now)"));
431 cl::opt<bool> rDynamic(
434 cl::desc(
"rDynamic option passed to clang"));
436 cl::opt<bool> suppress(
"w", cl::ValueDisallowed, cl::desc(
"Suppress all warnings"));
438 cl::opt<bool> usePthreads(
441 cl::desc(
"Support POSIX threads in generated code"));
446 cl::desc(
"Write a depfile containing user and system headers"));
448 cl::opt<std::string> mF(
450 cl::desc(
"Write depfile output from -mD to <file>."),
451 cl::value_desc(
"file"));
453 cl::opt<std::string> mT(
455 cl::desc(
"Specify name of main file output in depfile."),
456 cl::value_desc(
"value"));
458 cl::list<util::Statistics::Id> jlmOptPassStatistics(
459 "JlmOptPassStatistics",
463 "Collect control flow graph aggregation pass statistics."),
466 "Collect agnostic mod/ref summarizer pass statistics."),
469 "Collect Andersen alias analysis pass statistics."),
472 "Collect aggregation tree annotation pass statistics."),
475 "Collect memory state encoding pass statistics."),
478 "Collect common node elimination pass statistics."),
481 "Collect control flow recovery pass statistics."),
484 "Collect data node to delta node conversion pass statistics."),
487 "Collect dead node elimination pass statistics."),
490 "Collect function inlining pass statistics."),
493 "Collect invariant value redirection pass statistics."),
496 "Collect Jlm to RVSDG conversion pass statistics."),
499 "Collect loop unrolling pass statistics."),
502 "Collect loop unswitching pass statistics."),
505 "Collect node pull pass statistics."),
508 "Collect node push pass statistics."),
511 "Collect node reduction pass statistics."),
514 "Collect region-aware mod/ref summarizer pass statistics."),
517 "Collect RVSDG construction pass statistics."),
520 "Collect RVSDG destruction pass statistics."),
523 "Collect RVSDG optimization pass statistics."),
526 "Collect RVSDG tree printer pass statistics."),
529 "Collect scalar evolution analysis pass statistics.")),
530 cl::desc(
"Collect jlm-opt pass statistics"));
532 cl::ParseCommandLineOptions(argc, argv);
536 static std::unordered_map<std::string, JlcCommandLineOptions::OptimizationLevel>
542 static std::unordered_map<std::string, JlcCommandLineOptions::LanguageStandard>
554 if (!optimizationLevel.empty())
556 auto iterator = optimizationLevelMap.find(optimizationLevel);
557 if (iterator == optimizationLevelMap.end())
559 std::cerr <<
"Unknown optimization level.\n";
562 CommandLineOptions_.OptimizationLevel_ = iterator->second;
565 if (!languageStandard.empty())
567 auto iterator = languageStandardMap.find(languageStandard);
568 if (iterator == languageStandardMap.end())
570 std::cerr <<
"Unknown language standard.\n";
573 CommandLineOptions_.LanguageStandard_ = iterator->second;
576 if (inputFiles.empty())
578 std::cerr <<
"jlc: no input files.\n";
582 if (inputFiles.size() > 1 && noLinking && !outputFile.empty())
584 std::cerr <<
"jlc: cannot specify -o when generating multiple output files.\n";
588 auto jlmOptOptimizations =
589 checkAndConvertJlmOptOptimizations(jlmOptimizations, CommandLineOptions_.OptimizationLevel_);
591 CommandLineOptions_.Libraries_ = libraries;
592 CommandLineOptions_.MacroDefinitions_ = macroDefinitions;
593 CommandLineOptions_.LibraryPaths_ = libraryPaths;
594 CommandLineOptions_.Warnings_ = warnings;
595 CommandLineOptions_.IncludePaths_ = includePaths;
596 CommandLineOptions_.OnlyPrintCommands_ = onlyPrintCommands;
597 CommandLineOptions_.GenerateDebugInformation_ = generateDebugInformation;
598 CommandLineOptions_.Flags_ = flags;
599 CommandLineOptions_.JlmOptOptimizations_ = jlmOptOptimizations;
601 { jlmOptPassStatistics.begin(), jlmOptPassStatistics.end() });
602 CommandLineOptions_.Verbose_ = verbose;
603 CommandLineOptions_.Rdynamic_ = rDynamic;
604 CommandLineOptions_.Suppress_ = suppress;
605 CommandLineOptions_.UsePthreads_ = usePthreads;
606 CommandLineOptions_.Md_ = mD;
608 for (
auto & inputFile : inputFiles)
611 if (IsObjectFile(inputFilePath))
614 CommandLineOptions_.Compilations_.push_back(
615 { inputFilePath,
util::FilePath(
""), inputFilePath,
"",
false,
false,
false,
true });
620 CommandLineOptions_.Compilations_.push_back(
622 mF.empty() ? ToDependencyFile(inputFilePath) :
util::FilePath(mF),
623 ToObjectFile(inputFilePath),
624 mT.empty() ? ToObjectFile(inputFilePath).
name() : mT,
631 if (!outputFile.empty())
636 JLM_ASSERT(CommandLineOptions_.Compilations_.size() == 1);
637 CommandLineOptions_.Compilations_[0].SetOutputFile(outputFilePath);
641 CommandLineOptions_.OutputFile_ = outputFilePath;
645 return CommandLineOptions_;
653 using namespace ::
llvm;
662 cl::TopLevelSubCommand->reset();
664 cl::opt<std::string> inputFile(cl::Positional, cl::desc(
"<input>"));
666 cl::opt<std::string> outputFile(
669 cl::desc(
"Write output to <file>"),
670 cl::value_desc(
"file"));
673 const auto statisticDirectoryDescription =
674 "Write statistics and debug output to files in <dir>. Default is "
675 + statisticsDirectoryDefault.
to_str() +
".";
676 cl::opt<std::string> statisticDirectory(
678 cl::init(statisticsDirectoryDefault.to_str()),
679 cl::desc(statisticDirectoryDescription),
680 cl::value_desc(
"dir"));
682 cl::opt<bool> dumpRvsdgDotGraphs(
683 "dumpRvsdgDotGraphs",
685 cl::desc(
"Dump RVSDG as dot graphs after each transformation in debug folder."));
687 cl::list<util::Statistics::Id> printStatistics(
691 "Write aggregation statistics to file."),
694 "Collect agnostic mod/ref summarization pass statistics."),
697 "Evaluate alias analysis precision and store to file"),
700 "Collect Andersen alias analysis pass statistics."),
703 "Write annotation statistics to file."),
706 "Write encoding statistics of basic encoder to file."),
709 "Write common node elimination statistics to file."),
712 "Write control flow recovery statistics to file."),
715 "Write data node to delta node conversion statistics to file."),
718 "Write dead node elimination statistics to file."),
721 "Write function inlining statistics to file."),
724 "Collect if-conversion transformation statistics"),
727 "Write invariant value redirection statistics to file."),
730 "Write Jlm to RVSDG conversion statistics to file."),
733 "Write loop unrolling statistics to file."),
736 "Collect loop unswitching pass statistics."),
739 "Write node pull statistics to file."),
742 "Write node push statistics to file."),
745 "Write node reduction statistics to file."),
748 "Collect region-aware mod/ref summarization statistics."),
751 "Write RVSDG construction statistics to file."),
754 "Write RVSDG destruction statistics to file."),
757 "Write RVSDG optimization statistics to file."),
760 "Write RVSDG tree printer pass statistics."),
763 "Write scalar evolution statistics to file.")),
764 cl::desc(
"Write statistics"));
770 cl::opt<JlmOptCommandLineOptions::InputFormat> inputFormat(
772 cl::desc(
"Select input format:"),
777 "Input LLVM IR [default]"),
782 cl::init(llvmInputFormat));
787 cl::opt<JlmOptCommandLineOptions::OutputFormat> outputFormat(
789 cl::desc(
"Select output format:"),
795 "Output LLVM IR [default]"),
801 "Output Rvsdg Tree"),
811 auto invariantValueRedirection =
823 cl::list<JlmOptCommandLineOptions::OptimizationId> optimizationIds(
828 "Andersen alias analysis with agnostic memory state encoding"),
830 aAAndersenRegionAware,
832 "Andersen alias analysis with region-aware memory state encoding"),
834 commonNodeElimination,
836 "Common Node Elimination"),
840 "Dead Node Elimination"),
844 "Function Inlining"),
848 "Convert pass-through values of gamma nodes to select operations"),
850 invariantValueRedirection,
852 "Invariant Value Redirection"),
856 "Separate chains of load operations"),
864 "Move conditionals outside loops"),
878 predicateCorrelation,
880 "Correlate predicates between theta and gamma nodes"),
884 "Rvsdg Tree Printer"),
891 "ThetaGammaInversion",
892 "[DEPRECATED] Use --LoopUnswitching instead.")),
893 cl::desc(
"Perform optimization"));
895 cl::list<llvm::RvsdgTreePrinter::Configuration::Annotation> rvsdgTreePrinterAnnotations(
897 cl::values(::clEnumValN(
900 "Annotate number of AllocaOperation nodes")),
901 cl::values(::clEnumValN(
904 "Annotate number of LoadOperation nodes")),
905 cl::values(::clEnumValN(
907 "NumMemoryStateInputsOutputs",
908 "Annotate number of inputs/outputs with memory state type")),
909 cl::values(::clEnumValN(
912 "Annotate number of RVSDG nodes")),
913 cl::values(::clEnumValN(
916 "Annotate number of StoreOperation nodes")),
918 cl::desc(
"Comma separated list of RVSDG tree printer annotations"));
920 cl::ParseCommandLineOptions(argc, argv);
926 { printStatistics.begin(), printStatistics.end() });
929 std::move(demandedStatistics),
930 statisticsDirectoryFilePath,
931 inputFilePath.
base());
934 { rvsdgTreePrinterAnnotations.begin(), rvsdgTreePrinterAnnotations.end() });
939 std::move(inputFilePath),
943 std::move(statisticsCollectorSettings),
944 std::move(treePrinterConfiguration),
945 std::move(optimizationIds),
948 return *CommandLineOptions_;
963 CommandLineOptions_.Reset();
965 using namespace ::
llvm;
974 cl::TopLevelSubCommand->reset();
976 cl::opt<std::string> inputFile(cl::Positional, cl::desc(
"<input>"));
978 cl::opt<std::string> outputFolder(
980 cl::desc(
"Write output to <folder>"),
981 cl::value_desc(
"folder"));
983 cl::opt<std::string> hlsFunction(
986 cl::desc(
"Function that should be accelerated"),
987 cl::value_desc(
"hls-function"));
989 cl::opt<int> latency(
992 cl::init(CommandLineOptions_.MemoryLatency_),
993 cl::desc(
"Memory latency"),
994 cl::value_desc(
"latency"));
996 cl::opt<bool> extractHlsFunction(
999 cl::desc(
"Extracts function specified by hls-function"));
1001 cl::opt<bool> dumpRvsdgDotGraphs(
1002 "dumpRvsdgDotGraphs",
1004 cl::desc(
"Dump RVSDG as dot graphs after each transformation in debug folder."));
1006 cl::opt<JlmHlsCommandLineOptions::OutputFormat> format(
1011 "Output FIRRTL [default]"),
1013 cl::desc(
"Select output format"));
1015 cl::ParseCommandLineOptions(argc, argv);
1017 if (outputFolder.empty())
1018 throw util::Error(
"jlm-hls no output directory provided, i.e, -o.\n");
1020 if (extractHlsFunction && hlsFunction.empty())
1022 "jlm-hls: --hls-function is not specified.\n which is required for --extract\n");
1025 CommandLineOptions_.HlsFunction_ = std::move(hlsFunction);
1027 CommandLineOptions_.ExtractHlsFunction_ = extractHlsFunction;
1028 CommandLineOptions_.OutputFormat_ = format;
1029 CommandLineOptions_.dumpRvsdgDotGraphs_ = dumpRvsdgDotGraphs;
1033 throw util::Error(
"The --latency must be set to a number larger than zero.");
1035 CommandLineOptions_.MemoryLatency_ = latency;
1037 return CommandLineOptions_;
1052 CommandLineOptions_.Reset();
1054 using namespace ::
llvm;
1063 cl::TopLevelSubCommand->reset();
1065 cl::opt<bool> onlyPrintCommands(
1067 cl::ValueDisallowed,
1068 cl::desc(
"Print (but do not run) the commands for this compilation."));
1070 cl::list<std::string> inputFiles(cl::Positional, cl::desc(
"<inputs>"));
1072 cl::list<std::string> includePaths(
1075 cl::desc(
"Add directory <dir> to include search paths."),
1076 cl::value_desc(
"dir"));
1078 cl::list<std::string> libraryPaths(
1081 cl::desc(
"Add directory <dir> to library search paths."),
1082 cl::value_desc(
"dir"));
1084 cl::list<std::string> libraries(
1087 cl::desc(
"Search the library <lib> when linking."),
1088 cl::value_desc(
"lib"));
1090 cl::opt<std::string> outputFile(
"o", cl::desc(
"Write output to <file>."), cl::value_desc(
"file"));
1092 cl::opt<bool> generateDebugInformation(
1094 cl::ValueDisallowed,
1095 cl::desc(
"Generate source-level debug information."));
1097 cl::opt<bool> noLinking(
1099 cl::ValueDisallowed,
1100 cl::desc(
"Only run preprocess, compile, and assemble steps."));
1102 cl::opt<std::string> optimizationLevel(
1106 cl::desc(
"Optimization level. [O0, O1, O2, O3]"),
1107 cl::value_desc(
"#"));
1109 cl::list<std::string> macroDefinitions(
1112 cl::desc(
"Add <macro> to preprocessor macros."),
1113 cl::value_desc(
"macro"));
1115 cl::list<std::string> warnings(
1118 cl::desc(
"Enable specified warning."),
1119 cl::value_desc(
"warning"));
1121 cl::opt<std::string> languageStandard(
1123 cl::desc(
"Language standard."),
1124 cl::value_desc(
"standard"));
1126 cl::list<std::string> flags(
"f", cl::Prefix, cl::desc(
"Specify flags."), cl::value_desc(
"flag"));
1128 cl::list<std::string> jlmHlsOptimizations(
1131 cl::desc(
"jlm-hls optimization. Run 'jlm-hls -help' for viable options."),
1132 cl::value_desc(
"jlmhls"));
1134 cl::opt<bool> verbose(
1136 cl::ValueDisallowed,
1137 cl::desc(
"Show commands to run and use verbose output. (Affects only clang for now)"));
1139 cl::opt<bool> rdynamic(
1141 cl::ValueDisallowed,
1142 cl::desc(
"rdynamic option passed to clang"));
1144 cl::opt<bool> suppress(
"w", cl::ValueDisallowed, cl::desc(
"Suppress all warnings"));
1146 cl::opt<bool> usePthreads(
1148 cl::ValueDisallowed,
1149 cl::desc(
"Support POSIX threads in generated code"));
1153 cl::ValueDisallowed,
1154 cl::desc(
"Write a depfile containing user and system headers"));
1156 cl::opt<std::string> mF(
1158 cl::desc(
"Write depfile output from -MD to <file>."),
1159 cl::value_desc(
"file"));
1161 cl::opt<std::string> mT(
1163 cl::desc(
"Specify name of main file output in depfile."),
1164 cl::value_desc(
"value"));
1166 cl::list<std::string> hlsFunction(
1169 cl::desc(
"function that should be accelerated"),
1170 cl::value_desc(
"regex"));
1172 cl::opt<bool> generateFirrtl(
"firrtl", cl::ValueDisallowed, cl::desc(
"Generate firrtl"));
1174 cl::opt<bool> useCirct(
1177 cl::desc(
"DEPRACATED - CIRCT is always used to generate FIRRTL"));
1179 cl::ParseCommandLineOptions(argc, argv);
1183 static std::unordered_map<std::string, JhlsCommandLineOptions::OptimizationLevel> Olvlmap(
1189 static std::unordered_map<std::string, JhlsCommandLineOptions::LanguageStandard> stdmap(
1200 if (!optimizationLevel.empty())
1202 auto it = Olvlmap.find(optimizationLevel);
1203 if (it == Olvlmap.end())
1205 std::cerr <<
"Unknown optimization level.\n";
1208 CommandLineOptions_.OptimizationLevel_ = it->second;
1211 if (!languageStandard.empty())
1213 auto it = stdmap.find(languageStandard);
1214 if (it == stdmap.end())
1216 std::cerr <<
"Unknown language standard.\n";
1219 CommandLineOptions_.LanguageStandard_ = it->second;
1222 if (inputFiles.empty())
1224 std::cerr <<
"jlc: no input files.\n";
1228 if (inputFiles.size() > 1 && noLinking && !outputFile.empty())
1230 std::cerr <<
"jlc: cannot specify -o when generating multiple output files.\n";
1234 if (!hlsFunction.empty())
1236 CommandLineOptions_.Hls_ =
true;
1237 CommandLineOptions_.HlsFunctionRegex_ = hlsFunction.front();
1240 if (hlsFunction.size() > 1)
1242 std::cerr <<
"jlc-hls: more than one function regex specified\n";
1246 CommandLineOptions_.Libraries_ = libraries;
1247 CommandLineOptions_.MacroDefinitions_ = macroDefinitions;
1248 CommandLineOptions_.LibraryPaths_ = libraryPaths;
1249 CommandLineOptions_.Warnings_ = warnings;
1250 CommandLineOptions_.IncludePaths_ = includePaths;
1251 CommandLineOptions_.OnlyPrintCommands_ = onlyPrintCommands;
1252 CommandLineOptions_.GenerateDebugInformation_ = generateDebugInformation;
1253 CommandLineOptions_.Flags_ = flags;
1254 CommandLineOptions_.JlmHls_ = jlmHlsOptimizations;
1255 CommandLineOptions_.Verbose_ = verbose;
1256 CommandLineOptions_.Rdynamic_ = rdynamic;
1257 CommandLineOptions_.Suppress_ = suppress;
1258 CommandLineOptions_.UsePthreads_ = usePthreads;
1259 CommandLineOptions_.Md_ = mD;
1260 CommandLineOptions_.GenerateFirrtl_ = generateFirrtl;
1262 for (
auto & inputFile : inputFiles)
1265 if (IsObjectFile(inputFilePath))
1268 CommandLineOptions_.Compilations_.push_back(
1269 { inputFilePath,
util::FilePath(
""), inputFilePath,
"",
false,
false,
false,
true });
1274 CommandLineOptions_.Compilations_.push_back(
1276 mF.empty() ? CreateDependencyFileFromFile(inputFilePath) :
util::FilePath(mF),
1277 CreateObjectFileFromFile(inputFilePath),
1278 mT.empty() ? CreateObjectFileFromFile(inputFilePath).
name() : mT,
1285 if (!outputFile.empty())
1290 JLM_ASSERT(CommandLineOptions_.Compilations_.size() == 1);
1291 CommandLineOptions_.Compilations_[0].SetOutputFile(outputFilePath);
1295 CommandLineOptions_.OutputFile_ = outputFilePath;
1299 return CommandLineOptions_;
1305 return file.
suffix() ==
"o";
@ NumMemoryStateInputsOutputs
std::size_t Size() const noexcept
std::string name() const noexcept
Returns the name of the file, excluding the path.
static FilePath TempDirectoryPath()
const std::string & to_str() const noexcept
FilePath Join(const std::string &other) const
std::string base() const noexcept
Returns the base name of the file without the path.
FilePath Dirname() const noexcept
Returns the path to the file or directory's parent directory. Emulates the behavior of the GNU coreut...
std::string suffix() const noexcept
Returns the suffix (extension) of the file.
@ InvariantValueRedirection
@ AliasAnalysisPrecisionEvaluation
@ AgnosticModRefSummarizer
@ RegionAwareModRefSummarizer
static std::string strfmt(Args... args)