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];
124 std::string_view commandLineArgument)
127 if (commandLineArgument ==
"ThetaGammaInversion")
132 if (map.HasValue(commandLineArgument))
133 return map.LookupValue(commandLineArgument);
143 if (map.HasKey(optimizationId))
144 return map.LookupKey(optimizationId);
146 throw util::Error(
"Unknown optimization identifier");
151 std::string_view commandLineArgument)
172 throw util::Error(
"Unknown statistics identifier");
179 static std::unordered_map<InputFormat, std::string_view> map(
182 if (map.find(inputFormat) != map.end())
183 return map[inputFormat];
192 return mapping.at(outputFormat);
235 const std::unordered_map<JlmOptCommandLineOptions::OutputFormat, std::string_view> &
238 static std::unordered_map<OutputFormat, std::string_view> mapping = {
247 JLM_ASSERT(mapping.size() == lastIndex - firstIndex - 1);
268 static ::llvm::cl::OptionEnumValue
277 static ::llvm::cl::OptionEnumValue
280 std::string_view description)
290 CommandLineParser::Exception::~Exception() noexcept = default;
292 JlcCommandLineParser::~JlcCommandLineParser() noexcept = default;
294 const JlcCommandLineOptions &
297 auto checkAndConvertJlmOptOptimizations =
298 [](const ::llvm::cl::list<std::string> & optimizations,
335 std::vector<JlmOptCommandLineOptions::OptimizationId> optimizationIds;
336 for (
auto & optimization : optimizations)
349 optimizationIds.emplace_back(optimizationId);
352 return optimizationIds;
355 CommandLineOptions_.Reset();
357 using namespace ::
llvm;
366 cl::TopLevelSubCommand->reset();
368 cl::opt<bool> onlyPrintCommands(
371 cl::desc(
"Print (but do not run) the commands for this compilation."));
373 cl::list<std::string> inputFiles(cl::Positional, cl::desc(
"<inputs>"));
375 cl::list<std::string> includePaths(
378 cl::desc(
"Add directory <dir> to include search paths."),
379 cl::value_desc(
"dir"));
381 cl::list<std::string> libraryPaths(
384 cl::desc(
"Add directory <dir> to library search paths."),
385 cl::value_desc(
"dir"));
387 cl::list<std::string> libraries(
390 cl::desc(
"Search the library <lib> when linking."),
391 cl::value_desc(
"lib"));
393 cl::opt<std::string> outputFile(
"o", cl::desc(
"Write output to <file>."), cl::value_desc(
"file"));
395 cl::opt<bool> generateDebugInformation(
398 cl::desc(
"Generate source-level debug information."));
400 cl::opt<bool> noLinking(
403 cl::desc(
"Only run preprocess, compile, and assemble steps."));
405 cl::opt<std::string> optimizationLevel(
409 cl::desc(
"Optimization level. [O0, O1, O2, O3]"),
410 cl::value_desc(
"#"));
412 cl::list<std::string> macroDefinitions(
415 cl::desc(
"Add <macro> to preprocessor macros."),
416 cl::value_desc(
"macro"));
418 cl::list<std::string> warnings(
421 cl::desc(
"Enable specified warning."),
422 cl::value_desc(
"warning"));
424 cl::opt<std::string> languageStandard(
426 cl::desc(
"Language standard."),
427 cl::value_desc(
"standard"));
429 cl::list<std::string> flags(
"f", cl::Prefix, cl::desc(
"Specify flags."), cl::value_desc(
"flag"));
431 cl::list<std::string> jlmOptimizations(
434 cl::desc(
"jlm-opt optimization. Run 'jlm-opt -help' for viable options."),
435 cl::value_desc(
"jlmopt"));
437 cl::opt<bool> verbose(
440 cl::desc(
"Show commands to run and use verbose output. (Affects only clang for now)"));
442 cl::opt<bool> rDynamic(
445 cl::desc(
"rDynamic option passed to clang"));
447 cl::opt<bool> suppress(
"w", cl::ValueDisallowed, cl::desc(
"Suppress all warnings"));
449 cl::opt<bool> usePthreads(
452 cl::desc(
"Support POSIX threads in generated code"));
457 cl::desc(
"Write a depfile containing user and system headers"));
459 cl::opt<std::string> mF(
461 cl::desc(
"Write depfile output from -mD to <file>."),
462 cl::value_desc(
"file"));
464 cl::opt<std::string> mT(
466 cl::desc(
"Specify name of main file output in depfile."),
467 cl::value_desc(
"value"));
469 cl::list<util::Statistics::Id> jlmOptPassStatistics(
470 "JlmOptPassStatistics",
474 "Collect control flow graph aggregation pass statistics."),
477 "Collect agnostic mod/ref summarizer pass statistics."),
480 "Collect Andersen alias analysis pass statistics."),
483 "Collect aggregation tree annotation pass statistics."),
486 "Collect memory state encoding pass statistics."),
489 "Collect common node elimination pass statistics."),
492 "Collect control flow recovery pass statistics."),
495 "Collect data node to delta node conversion pass statistics."),
498 "Collect dead node elimination pass statistics."),
501 "Collect function inlining pass statistics."),
504 "Collect invariant value redirection pass statistics."),
507 "Collect Jlm to RVSDG conversion pass statistics."),
510 "Collect loop strength reduction pass statistics."),
513 "Collect loop unrolling pass statistics."),
516 "Collect loop unswitching pass statistics."),
519 "Collect node pull pass statistics."),
522 "Collect node push pass statistics."),
525 "Collect node reduction pass statistics."),
528 "Collect region-aware mod/ref summarizer pass statistics."),
531 "Collect RVSDG construction pass statistics."),
534 "Collect RVSDG destruction pass statistics."),
537 "Collect RVSDG optimization pass statistics."),
540 "Collect RVSDG tree printer pass statistics."),
543 "Collect scalar evolution analysis pass statistics.")),
544 cl::desc(
"Collect jlm-opt pass statistics"));
546 cl::ParseCommandLineOptions(argc, argv);
550 static std::unordered_map<std::string, JlcCommandLineOptions::OptimizationLevel>
556 static std::unordered_map<std::string, JlcCommandLineOptions::LanguageStandard>
568 if (!optimizationLevel.empty())
570 auto iterator = optimizationLevelMap.find(optimizationLevel);
571 if (iterator == optimizationLevelMap.end())
573 std::cerr <<
"Unknown optimization level.\n";
576 CommandLineOptions_.OptimizationLevel_ = iterator->second;
579 if (!languageStandard.empty())
581 auto iterator = languageStandardMap.find(languageStandard);
582 if (iterator == languageStandardMap.end())
584 std::cerr <<
"Unknown language standard.\n";
587 CommandLineOptions_.LanguageStandard_ = iterator->second;
590 if (inputFiles.empty())
592 std::cerr <<
"jlc: no input files.\n";
596 if (inputFiles.size() > 1 && noLinking && !outputFile.empty())
598 std::cerr <<
"jlc: cannot specify -o when generating multiple output files.\n";
602 auto jlmOptOptimizations =
603 checkAndConvertJlmOptOptimizations(jlmOptimizations, CommandLineOptions_.OptimizationLevel_);
605 CommandLineOptions_.Libraries_ = libraries;
606 CommandLineOptions_.MacroDefinitions_ = macroDefinitions;
607 CommandLineOptions_.LibraryPaths_ = libraryPaths;
608 CommandLineOptions_.Warnings_ = warnings;
609 CommandLineOptions_.IncludePaths_ = includePaths;
610 CommandLineOptions_.OnlyPrintCommands_ = onlyPrintCommands;
611 CommandLineOptions_.GenerateDebugInformation_ = generateDebugInformation;
612 CommandLineOptions_.Flags_ = flags;
613 CommandLineOptions_.JlmOptOptimizations_ = jlmOptOptimizations;
615 { jlmOptPassStatistics.begin(), jlmOptPassStatistics.end() });
616 CommandLineOptions_.Verbose_ = verbose;
617 CommandLineOptions_.Rdynamic_ = rDynamic;
618 CommandLineOptions_.Suppress_ = suppress;
619 CommandLineOptions_.UsePthreads_ = usePthreads;
620 CommandLineOptions_.Md_ = mD;
622 for (
auto & inputFile : inputFiles)
625 if (IsObjectFile(inputFilePath))
628 CommandLineOptions_.Compilations_.push_back(
629 { inputFilePath,
util::FilePath(
""), inputFilePath,
"",
false,
false,
false,
true });
634 CommandLineOptions_.Compilations_.push_back(
636 mF.empty() ? ToDependencyFile(inputFilePath) :
util::FilePath(mF),
637 ToObjectFile(inputFilePath),
638 mT.empty() ? ToObjectFile(inputFilePath).
name() : mT,
645 if (!outputFile.empty())
650 JLM_ASSERT(CommandLineOptions_.Compilations_.size() == 1);
651 CommandLineOptions_.Compilations_[0].SetOutputFile(outputFilePath);
655 CommandLineOptions_.OutputFile_ = outputFilePath;
659 return CommandLineOptions_;
667 using namespace ::
llvm;
676 cl::TopLevelSubCommand->reset();
678 cl::opt<std::string> inputFile(cl::Positional, cl::desc(
"<input>"));
680 cl::opt<std::string> outputFile(
683 cl::desc(
"Write output to <file>"),
684 cl::value_desc(
"file"));
687 const auto statisticDirectoryDescription =
688 "Write statistics and debug output to files in <dir>. Default is "
689 + statisticsDirectoryDefault.
to_str() +
".";
690 cl::opt<std::string> statisticDirectory(
692 cl::init(statisticsDirectoryDefault.to_str()),
693 cl::desc(statisticDirectoryDescription),
694 cl::value_desc(
"dir"));
696 cl::opt<bool> dumpRvsdgGraphs(
699 cl::desc(
"Dump RVSDG as json graphs after each transformation in debug folder."));
701 cl::list<util::Statistics::Id> printStatistics(
705 "Write aggregate alloca splitting statistics to file."),
708 "Write aggregation statistics to file."),
711 "Collect agnostic mod/ref summarization pass statistics."),
714 "Evaluate alias analysis precision and store to file"),
717 "Collect Andersen alias analysis pass statistics."),
720 "Write annotation statistics to file."),
723 "Write encoding statistics of basic encoder to file."),
726 "Write common node elimination statistics to file."),
729 "Write control flow recovery statistics to file."),
732 "Write data node to delta node conversion statistics to file."),
735 "Write dead node elimination statistics to file."),
738 "Write function inlining statistics to file."),
741 "Collect if-conversion transformation statistics"),
744 "Write invariant value redirection statistics to file."),
747 "Write Jlm to RVSDG conversion statistics to file."),
750 "Write loop strength reduction statistics to file."),
753 "Write loop unrolling statistics to file."),
756 "Collect loop unswitching pass statistics."),
759 "Write node pull statistics to file."),
762 "Write node push statistics to file."),
765 "Write node reduction statistics to file."),
768 "Collect region-aware mod/ref summarization statistics."),
771 "Write RVSDG construction statistics to file."),
774 "Write RVSDG destruction statistics to file."),
777 "Write RVSDG optimization statistics to file."),
780 "Write RVSDG tree printer pass statistics."),
783 "Write scalar evolution statistics to file."),
786 "Write store value forwarding statistics to file.")),
787 cl::desc(
"Write statistics"));
793 cl::opt<JlmOptCommandLineOptions::InputFormat> inputFormat(
795 cl::desc(
"Select input format:"),
800 "Input LLVM IR [default]"),
805 cl::init(llvmInputFormat));
810 cl::opt<JlmOptCommandLineOptions::OutputFormat> outputFormat(
812 cl::desc(
"Select output format:"),
821 "Output Rvsdg tree as JSON"),
824 "Output LLVM IR [default]"),
830 "Output Rvsdg Tree")),
835 auto aggregateAllocaSplitting =
841 auto invariantValueRedirection =
855 cl::list<JlmOptCommandLineOptions::OptimizationId> optimizationIds(
860 "Andersen alias analysis with agnostic memory state encoding"),
862 aAAndersenRegionAware,
864 "Andersen alias analysis with region-aware memory state encoding"),
866 aggregateAllocaSplitting,
868 "Split aggregate type alloca nodes"),
870 commonNodeElimination,
872 "Common Node Elimination"),
876 "Dead Node Elimination"),
880 "Function Inlining"),
884 "Convert pass-through values of gamma nodes to select operations"),
886 invariantValueRedirection,
888 "Invariant Value Redirection"),
892 "Separate chains of load operations"),
894 loopStrengthReduction,
896 "Loop strength reduction"),
904 "Move conditionals outside loops"),
918 predicateCorrelation,
920 "Correlate predicates between theta and gamma nodes"),
924 "Rvsdg Tree Printer"),
930 storeValueForwarding,
932 "Store Value Forwarding"),
935 "ThetaGammaInversion",
936 "[DEPRECATED] Use --LoopUnswitching instead.")),
937 cl::desc(
"Perform optimization"));
939 cl::list<llvm::RvsdgTreePrinter::Configuration::Annotation> rvsdgTreePrinterAnnotations(
941 cl::values(::clEnumValN(
944 "Annotate region and node IDs")),
945 cl::values(::clEnumValN(
947 "NumAggregateAllocaNodes",
948 "Annotate number of AllocaOperation nodes with aggregate types.")),
949 cl::values(::clEnumValN(
952 "Annotate number of AllocaOperation nodes")),
953 cl::values(::clEnumValN(
956 "Annotate number of LoadOperation nodes")),
957 cl::values(::clEnumValN(
959 "NumMemoryStateInputsOutputs",
960 "Annotate number of inputs/outputs with memory state type")),
961 cl::values(::clEnumValN(
964 "Annotate number of RVSDG nodes")),
965 cl::values(::clEnumValN(
968 "Annotate number of StoreOperation nodes")),
970 cl::desc(
"Comma separated list of RVSDG tree printer annotations"));
972 cl::ParseCommandLineOptions(argc, argv);
978 { printStatistics.begin(), printStatistics.end() });
981 std::move(demandedStatistics),
982 statisticsDirectoryFilePath,
983 inputFilePath.
base());
986 { rvsdgTreePrinterAnnotations.begin(), rvsdgTreePrinterAnnotations.end() });
991 std::move(inputFilePath),
995 std::move(statisticsCollectorSettings),
996 std::move(treePrinterConfiguration),
997 std::move(optimizationIds),
1000 return *CommandLineOptions_;
1015 CommandLineOptions_.
Reset();
1017 using namespace ::
llvm;
1026 cl::TopLevelSubCommand->reset();
1028 cl::opt<std::string> inputFile(cl::Positional, cl::desc(
"<input>"));
1030 cl::opt<std::string> outputFolder(
1032 cl::desc(
"Write output to <folder>"),
1033 cl::value_desc(
"folder"));
1035 cl::opt<std::string> hlsFunction(
1038 cl::desc(
"Function that should be accelerated"),
1039 cl::value_desc(
"hls-function"));
1041 cl::opt<int> latency(
1044 cl::init(CommandLineOptions_.MemoryLatency_),
1045 cl::desc(
"Memory latency"),
1046 cl::value_desc(
"latency"));
1048 cl::opt<bool> extractHlsFunction(
1051 cl::desc(
"Extracts function specified by hls-function"));
1053 cl::opt<bool> dumpRvsdgGraphs(
1056 cl::desc(
"Dump RVSDG as json graphs after each transformation in debug folder."));
1058 cl::opt<JlmHlsCommandLineOptions::OutputFormat> format(
1063 "Output FIRRTL [default]"),
1065 cl::desc(
"Select output format"));
1067 cl::ParseCommandLineOptions(argc, argv);
1069 if (outputFolder.empty())
1070 throw util::Error(
"jlm-hls no output directory provided, i.e, -o.\n");
1072 if (extractHlsFunction && hlsFunction.empty())
1074 "jlm-hls: --hls-function is not specified.\n which is required for --extract\n");
1077 CommandLineOptions_.HlsFunction_ = std::move(hlsFunction);
1079 CommandLineOptions_.ExtractHlsFunction_ = extractHlsFunction;
1080 CommandLineOptions_.OutputFormat_ = format;
1081 CommandLineOptions_.dumpRvsdgGraphs_ = dumpRvsdgGraphs;
1085 throw util::Error(
"The --latency must be set to a number larger than zero.");
1087 CommandLineOptions_.MemoryLatency_ = latency;
1089 return CommandLineOptions_;
1104 CommandLineOptions_.
Reset();
1106 using namespace ::
llvm;
1115 cl::TopLevelSubCommand->reset();
1117 cl::opt<bool> onlyPrintCommands(
1119 cl::ValueDisallowed,
1120 cl::desc(
"Print (but do not run) the commands for this compilation."));
1122 cl::list<std::string> inputFiles(cl::Positional, cl::desc(
"<inputs>"));
1124 cl::list<std::string> includePaths(
1127 cl::desc(
"Add directory <dir> to include search paths."),
1128 cl::value_desc(
"dir"));
1130 cl::list<std::string> libraryPaths(
1133 cl::desc(
"Add directory <dir> to library search paths."),
1134 cl::value_desc(
"dir"));
1136 cl::list<std::string> libraries(
1139 cl::desc(
"Search the library <lib> when linking."),
1140 cl::value_desc(
"lib"));
1142 cl::opt<std::string> outputFile(
"o", cl::desc(
"Write output to <file>."), cl::value_desc(
"file"));
1144 cl::opt<bool> generateDebugInformation(
1146 cl::ValueDisallowed,
1147 cl::desc(
"Generate source-level debug information."));
1149 cl::opt<bool> noLinking(
1151 cl::ValueDisallowed,
1152 cl::desc(
"Only run preprocess, compile, and assemble steps."));
1154 cl::opt<std::string> optimizationLevel(
1158 cl::desc(
"Optimization level. [O0, O1, O2, O3]"),
1159 cl::value_desc(
"#"));
1161 cl::list<std::string> macroDefinitions(
1164 cl::desc(
"Add <macro> to preprocessor macros."),
1165 cl::value_desc(
"macro"));
1167 cl::list<std::string> warnings(
1170 cl::desc(
"Enable specified warning."),
1171 cl::value_desc(
"warning"));
1173 cl::opt<std::string> languageStandard(
1175 cl::desc(
"Language standard."),
1176 cl::value_desc(
"standard"));
1178 cl::list<std::string> flags(
"f", cl::Prefix, cl::desc(
"Specify flags."), cl::value_desc(
"flag"));
1180 cl::list<std::string> jlmHlsOptimizations(
1183 cl::desc(
"jlm-hls optimization. Run 'jlm-hls -help' for viable options."),
1184 cl::value_desc(
"jlmhls"));
1186 cl::opt<bool> verbose(
1188 cl::ValueDisallowed,
1189 cl::desc(
"Show commands to run and use verbose output. (Affects only clang for now)"));
1191 cl::opt<bool> rdynamic(
1193 cl::ValueDisallowed,
1194 cl::desc(
"rdynamic option passed to clang"));
1196 cl::opt<bool> suppress(
"w", cl::ValueDisallowed, cl::desc(
"Suppress all warnings"));
1198 cl::opt<bool> usePthreads(
1200 cl::ValueDisallowed,
1201 cl::desc(
"Support POSIX threads in generated code"));
1205 cl::ValueDisallowed,
1206 cl::desc(
"Write a depfile containing user and system headers"));
1208 cl::opt<std::string> mF(
1210 cl::desc(
"Write depfile output from -MD to <file>."),
1211 cl::value_desc(
"file"));
1213 cl::opt<std::string> mT(
1215 cl::desc(
"Specify name of main file output in depfile."),
1216 cl::value_desc(
"value"));
1218 cl::list<std::string> hlsFunction(
1221 cl::desc(
"function that should be accelerated"),
1222 cl::value_desc(
"regex"));
1224 cl::opt<bool> generateFirrtl(
"firrtl", cl::ValueDisallowed, cl::desc(
"Generate firrtl"));
1226 cl::opt<bool> useCirct(
1229 cl::desc(
"DEPRACATED - CIRCT is always used to generate FIRRTL"));
1231 cl::ParseCommandLineOptions(argc, argv);
1235 static std::unordered_map<std::string, JhlsCommandLineOptions::OptimizationLevel> Olvlmap(
1241 static std::unordered_map<std::string, JhlsCommandLineOptions::LanguageStandard> stdmap(
1252 if (!optimizationLevel.empty())
1254 auto it = Olvlmap.find(optimizationLevel);
1255 if (it == Olvlmap.end())
1257 std::cerr <<
"Unknown optimization level.\n";
1260 CommandLineOptions_.OptimizationLevel_ = it->second;
1263 if (!languageStandard.empty())
1265 auto it = stdmap.find(languageStandard);
1266 if (it == stdmap.end())
1268 std::cerr <<
"Unknown language standard.\n";
1271 CommandLineOptions_.LanguageStandard_ = it->second;
1274 if (inputFiles.empty())
1276 std::cerr <<
"jlc: no input files.\n";
1280 if (inputFiles.size() > 1 && noLinking && !outputFile.empty())
1282 std::cerr <<
"jlc: cannot specify -o when generating multiple output files.\n";
1286 if (!hlsFunction.empty())
1288 CommandLineOptions_.Hls_ =
true;
1289 CommandLineOptions_.HlsFunctionRegex_ = hlsFunction.front();
1292 if (hlsFunction.size() > 1)
1294 std::cerr <<
"jlc-hls: more than one function regex specified\n";
1298 CommandLineOptions_.Libraries_ = libraries;
1299 CommandLineOptions_.MacroDefinitions_ = macroDefinitions;
1300 CommandLineOptions_.LibraryPaths_ = libraryPaths;
1301 CommandLineOptions_.Warnings_ = warnings;
1302 CommandLineOptions_.IncludePaths_ = includePaths;
1303 CommandLineOptions_.OnlyPrintCommands_ = onlyPrintCommands;
1304 CommandLineOptions_.GenerateDebugInformation_ = generateDebugInformation;
1305 CommandLineOptions_.Flags_ = flags;
1306 CommandLineOptions_.JlmHls_ = jlmHlsOptimizations;
1307 CommandLineOptions_.Verbose_ = verbose;
1308 CommandLineOptions_.Rdynamic_ = rdynamic;
1309 CommandLineOptions_.Suppress_ = suppress;
1310 CommandLineOptions_.UsePthreads_ = usePthreads;
1311 CommandLineOptions_.Md_ = mD;
1312 CommandLineOptions_.GenerateFirrtl_ = generateFirrtl;
1314 for (
auto & inputFile : inputFiles)
1317 if (IsObjectFile(inputFilePath))
1320 CommandLineOptions_.Compilations_.push_back(
1321 { inputFilePath,
util::FilePath(
""), inputFilePath,
"",
false,
false,
false,
true });
1326 CommandLineOptions_.Compilations_.push_back(
1328 mF.empty() ? CreateDependencyFileFromFile(inputFilePath) :
util::FilePath(mF),
1329 CreateObjectFileFromFile(inputFilePath),
1330 mT.empty() ? CreateObjectFileFromFile(inputFilePath).
name() : mT,
1337 if (!outputFile.empty())
1342 JLM_ASSERT(CommandLineOptions_.Compilations_.size() == 1);
1343 CommandLineOptions_.Compilations_[0].SetOutputFile(outputFilePath);
1347 CommandLineOptions_.OutputFile_ = outputFilePath;
1351 return CommandLineOptions_;
1357 return file.
suffix() ==
"o";
static const jlm::tooling::JlcCommandLineOptions & ParseCommandLineArguments(const std::vector< std::string > &commandLineArguments)
@ NumAggregateAllocaNodes
@ 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
@ AggregateAllocaSplitting
@ AliasAnalysisPrecisionEvaluation
@ AgnosticModRefSummarizer
@ RegionAwareModRefSummarizer
static std::string strfmt(Args... args)