Jlm
Loading...
Searching...
No Matches
CommandLine.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2022 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
11
12#include <llvm/Support/CommandLine.h>
13
14#include <unordered_map>
15
16namespace jlm::tooling
17{
18
20
21std::string_view
23{
24 static std::unordered_map<OptimizationLevel, std::string_view> map({
25 { OptimizationLevel::O0, "O0" },
26 { OptimizationLevel::O1, "O1" },
27 { OptimizationLevel::O2, "O2" },
28 { OptimizationLevel::O3, "O3" },
29 });
30
31 JLM_ASSERT(map.find(optimizationLevel) != map.end());
32 return map[optimizationLevel];
33}
34
35std::string_view
37{
38 static std::unordered_map<LanguageStandard, std::string_view> map(
39 { { LanguageStandard::None, "" },
40 { LanguageStandard::Gnu89, "gnu89" },
41 { LanguageStandard::Gnu99, "gnu99" },
42 { LanguageStandard::C89, "c89" },
43 { LanguageStandard::C99, "c99" },
44 { LanguageStandard::C11, "c11" },
45 { LanguageStandard::Cpp98, "c++98" },
46 { LanguageStandard::Cpp03, "c++03" },
47 { LanguageStandard::Cpp11, "c++11" },
48 { LanguageStandard::Cpp14, "c++14" } });
49
50 JLM_ASSERT(map.find(languageStandard) != map.end());
51 return map[languageStandard];
52}
53
54void
56{
57 OnlyPrintCommands_ = false;
59 Verbose_ = false;
60 Rdynamic_ = false;
61 Suppress_ = false;
62 UsePthreads_ = false;
63
64 Md_ = false;
65
68
69 OutputFile_ = util::FilePath("a.out");
70 Libraries_.clear();
71 MacroDefinitions_.clear();
72 LibraryPaths_.clear();
73 Warnings_.clear();
74 IncludePaths_.clear();
75 Flags_.clear();
77
78 Compilations_.clear();
79}
80
81void
90
93{
95 { OptimizationId::AAAndersenAgnostic, "AAAndersenAgnostic" },
96 { OptimizationId::AAAndersenRegionAware, "AAAndersenRegionAware" },
97 { OptimizationId::AggregateAllocaSplitting, "AggregateAllocaSplitting" },
98 { OptimizationId::CommonNodeElimination, "CommonNodeElimination" },
99 { OptimizationId::DeadNodeElimination, "DeadNodeElimination" },
100 { OptimizationId::FunctionInlining, "FunctionInlining" },
101 { OptimizationId::IfConversion, "IfConversion" },
102 { OptimizationId::InvariantValueRedirection, "InvariantValueRedirection" },
103 { OptimizationId::IOBarrierElimination, "IOBarrierElimination" },
104 { OptimizationId::LoadChainSeparation, "LoadChainSeparation" },
105 { OptimizationId::LoopStrengthReduction, "LoopStrengthReduction" },
106 { OptimizationId::LoopUnrolling, "LoopUnrolling" },
107 { OptimizationId::LoopUnswitching, "LoopUnswitching" },
108 { OptimizationId::NodePullIn, "NodePullIn" },
109 { OptimizationId::NodePushOut, "NodePushOut" },
110 { OptimizationId::NodeReduction, "NodeReduction" },
111 { OptimizationId::PredicateCorrelation, "PredicateCorrelation" },
112 { OptimizationId::RvsdgTreePrinter, "RvsdgTreePrinter" },
113 { OptimizationId::ScalarEvolution, "ScalarEvolution" },
114 { OptimizationId::StoreValueForwarding, "StoreValueForwarding" }
115 };
116
117 auto firstIndex = static_cast<size_t>(OptimizationId::FirstEnumValue);
118 auto lastIndex = static_cast<size_t>(OptimizationId::LastEnumValue);
119 JLM_ASSERT(map.Size() == lastIndex - firstIndex - 1);
120 return map;
121}
122
125 std::string_view commandLineArgument)
126{
127 // TODO: Deprecated, to be removed
128 if (commandLineArgument == "ThetaGammaInversion")
130
131 const auto & map = GetOptimizationIdCommandLineMap();
132
133 if (map.HasValue(commandLineArgument))
134 return map.LookupValue(commandLineArgument);
135
136 throw util::Error(util::strfmt("Unknown command line argument: ", commandLineArgument));
137}
138
139std::string_view
141{
142 const auto & map = GetOptimizationIdCommandLineMap();
143
144 if (map.HasKey(optimizationId))
145 return map.LookupKey(optimizationId);
146
147 throw util::Error("Unknown optimization identifier");
148}
149
152 std::string_view commandLineArgument)
153{
154 try
155 {
156 return GetStatisticsIdCommandLineArguments().LookupValue(commandLineArgument);
157 }
158 catch (...)
159 {
160 throw util::Error(util::strfmt("Unknown command line argument: ", commandLineArgument));
161 }
162}
163
164std::string_view
166{
167 try
168 {
169 return GetStatisticsIdCommandLineArguments().LookupKey(statisticsId);
170 }
171 catch (...)
172 {
173 throw util::Error("Unknown statistics identifier");
174 }
175}
176
177std::string_view
179{
180 static std::unordered_map<InputFormat, std::string_view> map(
181 { { InputFormat::Llvm, "llvm" }, { InputFormat::Mlir, "mlir" } });
182
183 if (map.find(inputFormat) != map.end())
184 return map[inputFormat];
185
186 throw util::Error("Unknown input format");
187}
188
189std::string_view
191{
192 auto & mapping = GetOutputFormatCommandLineArguments();
193 return mapping.at(outputFormat);
194}
195
198{
200 { util::Statistics::Id::AggregateAllocaSplitting, "print-aggregate-alloca-splitting" },
201 { util::Statistics::Id::Aggregation, "print-aggregation-time" },
202 { util::Statistics::Id::AgnosticModRefSummarizer, "print-agnostic-mod-ref-summarization" },
203 { util::Statistics::Id::AliasAnalysisPrecisionEvaluation, "print-aa-precision-evaluation" },
204 { util::Statistics::Id::AndersenAnalysis, "print-andersen-analysis" },
205 { util::Statistics::Id::Annotation, "print-annotation-time" },
207 { util::Statistics::Id::ControlFlowRecovery, "print-cfr-time" },
208 { util::Statistics::Id::DataNodeToDelta, "printDataNodeToDelta" },
209 { util::Statistics::Id::DeadNodeElimination, "print-dne-stat" },
210 { util::Statistics::Id::FunctionInlining, "print-iln-stat" },
211 { util::Statistics::Id::IfConversion, "print-if-conversion" },
212 { util::Statistics::Id::InvariantValueRedirection, "printInvariantValueRedirection" },
213 { util::Statistics::Id::IOBarrierElimination, "print-io-barrier-elimination" },
214 { util::Statistics::Id::JlmToRvsdgConversion, "print-jlm-rvsdg-conversion" },
215 { util::Statistics::Id::LoopStrengthReduction, "print-loop-strength-reduction" },
216 { util::Statistics::Id::LoopUnrolling, "print-unroll-stat" },
217 { util::Statistics::Id::LoopUnswitching, "print-ivt-stat" },
218 { util::Statistics::Id::MemoryStateEncoder, "print-basicencoder-encoding" },
219 { util::Statistics::Id::PullNodes, "print-pull-stat" },
220 { util::Statistics::Id::PushNodes, "print-push-stat" },
221 { util::Statistics::Id::ReduceNodes, "print-reduction-stat" },
222 { util::Statistics::Id::RegionAwareModRefSummarizer, "print-mod-ref-summarization" },
223 { util::Statistics::Id::RvsdgConstruction, "print-rvsdg-construction" },
224 { util::Statistics::Id::RvsdgDestruction, "print-rvsdg-destruction" },
225 { util::Statistics::Id::RvsdgOptimization, "print-rvsdg-optimization" },
226 { util::Statistics::Id::RvsdgTreePrinter, "print-rvsdg-tree" },
227 { util::Statistics::Id::ScalarEvolution, "print-scalar-evolution" },
228 { util::Statistics::Id::StoreValueForwarding, "print-store-value-forwarding" },
229 };
230
231 auto firstIndex = static_cast<size_t>(util::Statistics::Id::FirstEnumValue);
232 auto lastIndex = static_cast<size_t>(util::Statistics::Id::LastEnumValue);
233 JLM_ASSERT(mapping.Size() == lastIndex - firstIndex - 1);
234 return mapping;
235}
236
237const std::unordered_map<JlmOptCommandLineOptions::OutputFormat, std::string_view> &
239{
240 static std::unordered_map<OutputFormat, std::string_view> mapping = {
241 { OutputFormat::Ascii, "ascii" }, { OutputFormat::Dot, "dot" },
242 { OutputFormat::Json, "json" }, { OutputFormat::JsonTree, "jsonTree" },
243 { OutputFormat::Llvm, "llvm" }, { OutputFormat::Mlir, "mlir" },
244 { OutputFormat::Tree, "tree" },
245 };
246
247 auto firstIndex = static_cast<size_t>(OutputFormat::FirstEnumValue);
248 auto lastIndex = static_cast<size_t>(OutputFormat::LastEnumValue);
249 JLM_ASSERT(mapping.size() == lastIndex - firstIndex - 1);
250 return mapping;
251}
252
253void
263
264void
266{
267 *this = JhlsCommandLineOptions();
268}
269
270static ::llvm::cl::OptionEnumValue
271CreateStatisticsOption(util::Statistics::Id statisticsId, std::string_view description)
272{
273 return ::clEnumValN(
274 statisticsId,
276 description);
277}
278
279static ::llvm::cl::OptionEnumValue
282 std::string_view description)
283{
284 return ::clEnumValN(
285 outputFormat,
287 description);
288}
289
290CommandLineParser::~CommandLineParser() noexcept = default;
291
292CommandLineParser::Exception::~Exception() noexcept = default;
293
294JlcCommandLineParser::~JlcCommandLineParser() noexcept = default;
295
296const JlcCommandLineOptions &
297JlcCommandLineParser::ParseCommandLineArguments(int argc, const char * const * argv)
298{
299 auto checkAndConvertJlmOptOptimizations =
300 [](const ::llvm::cl::list<std::string> & optimizations,
302 {
303 if (optimizations.empty() && optimizationLevel == JlcCommandLineOptions::OptimizationLevel::O3)
304 {
305 return std::vector({
333 });
334 }
335
336 std::vector<JlmOptCommandLineOptions::OptimizationId> optimizationIds;
337 for (auto & optimization : optimizations)
338 {
340 try
341 {
342 optimizationId =
344 }
345 catch (util::Error &)
346 {
347 throw CommandLineParser::Exception("Unknown jlm-opt optimization: " + optimization);
348 }
349
350 optimizationIds.emplace_back(optimizationId);
351 }
352
353 return optimizationIds;
354 };
355
356 CommandLineOptions_.Reset();
357
358 using namespace ::llvm;
359
360 /*
361 FIXME: The command line parser setup is currently redone
362 for every invocation of parse_cmdline. We should be able
363 to do it only once and then reset the parser on every
364 invocation of parse_cmdline.
365 */
366
367 cl::TopLevelSubCommand->reset();
368
369 cl::opt<bool> onlyPrintCommands(
370 "###",
371 cl::ValueDisallowed,
372 cl::desc("Print (but do not run) the commands for this compilation."));
373
374 cl::list<std::string> inputFiles(cl::Positional, cl::desc("<inputs>"));
375
376 cl::list<std::string> includePaths(
377 "I",
378 cl::Prefix,
379 cl::desc("Add directory <dir> to include search paths."),
380 cl::value_desc("dir"));
381
382 cl::list<std::string> libraryPaths(
383 "L",
384 cl::Prefix,
385 cl::desc("Add directory <dir> to library search paths."),
386 cl::value_desc("dir"));
387
388 cl::list<std::string> libraries(
389 "l",
390 cl::Prefix,
391 cl::desc("Search the library <lib> when linking."),
392 cl::value_desc("lib"));
393
394 cl::opt<std::string> outputFile("o", cl::desc("Write output to <file>."), cl::value_desc("file"));
395
396 cl::opt<bool> generateDebugInformation(
397 "g",
398 cl::ValueDisallowed,
399 cl::desc("Generate source-level debug information."));
400
401 cl::opt<bool> noLinking(
402 "c",
403 cl::ValueDisallowed,
404 cl::desc("Only run preprocess, compile, and assemble steps."));
405
406 cl::opt<std::string> optimizationLevel(
407 "O",
408 cl::Prefix,
409 cl::ValueOptional,
410 cl::desc("Optimization level. [O0, O1, O2, O3]"),
411 cl::value_desc("#"));
412
413 cl::list<std::string> macroDefinitions(
414 "D",
415 cl::Prefix,
416 cl::desc("Add <macro> to preprocessor macros."),
417 cl::value_desc("macro"));
418
419 cl::list<std::string> warnings(
420 "W",
421 cl::Prefix,
422 cl::desc("Enable specified warning."),
423 cl::value_desc("warning"));
424
425 cl::opt<std::string> languageStandard(
426 "std",
427 cl::desc("Language standard."),
428 cl::value_desc("standard"));
429
430 cl::list<std::string> flags("f", cl::Prefix, cl::desc("Specify flags."), cl::value_desc("flag"));
431
432 cl::list<std::string> jlmOptimizations(
433 "J",
434 cl::Prefix,
435 cl::desc("jlm-opt optimization. Run 'jlm-opt -help' for viable options."),
436 cl::value_desc("jlmopt"));
437
438 cl::opt<bool> verbose(
439 "v",
440 cl::ValueDisallowed,
441 cl::desc("Show commands to run and use verbose output. (Affects only clang for now)"));
442
443 cl::opt<bool> rDynamic(
444 "rdynamic",
445 cl::ValueDisallowed,
446 cl::desc("rDynamic option passed to clang"));
447
448 cl::opt<bool> suppress("w", cl::ValueDisallowed, cl::desc("Suppress all warnings"));
449
450 cl::opt<bool> usePthreads(
451 "pthread",
452 cl::ValueDisallowed,
453 cl::desc("Support POSIX threads in generated code"));
454
455 cl::opt<bool> mD(
456 "MD",
457 cl::ValueDisallowed,
458 cl::desc("Write a depfile containing user and system headers"));
459
460 cl::opt<std::string> mF(
461 "MF",
462 cl::desc("Write depfile output from -mD to <file>."),
463 cl::value_desc("file"));
464
465 cl::opt<std::string> mT(
466 "MT",
467 cl::desc("Specify name of main file output in depfile."),
468 cl::value_desc("value"));
469
470 cl::list<util::Statistics::Id> jlmOptPassStatistics(
471 "JlmOptPassStatistics",
472 cl::values(
475 "Collect control flow graph aggregation pass statistics."),
478 "Collect agnostic mod/ref summarizer pass statistics."),
481 "Collect Andersen alias analysis pass statistics."),
484 "Collect aggregation tree annotation pass statistics."),
487 "Collect memory state encoding pass statistics."),
490 "Collect common node elimination pass statistics."),
493 "Collect control flow recovery pass statistics."),
496 "Collect data node to delta node conversion pass statistics."),
499 "Collect dead node elimination pass statistics."),
502 "Collect function inlining pass statistics."),
505 "Collect invariant value redirection pass statistics."),
508 "Collect Jlm to RVSDG conversion pass statistics."),
511 "Collect loop strength reduction pass statistics."),
514 "Collect loop unrolling pass statistics."),
517 "Collect loop unswitching pass statistics."),
520 "Collect node pull pass statistics."),
523 "Collect node push pass statistics."),
526 "Collect node reduction pass statistics."),
529 "Collect region-aware mod/ref summarizer pass statistics."),
532 "Collect RVSDG construction pass statistics."),
535 "Collect RVSDG destruction pass statistics."),
538 "Collect RVSDG optimization pass statistics."),
541 "Collect RVSDG tree printer pass statistics."),
544 "Collect scalar evolution analysis pass statistics.")),
545 cl::desc("Collect jlm-opt pass statistics"));
546
547 cl::ParseCommandLineOptions(argc, argv);
548
549 /* Process parsed options */
550
551 static std::unordered_map<std::string, JlcCommandLineOptions::OptimizationLevel>
552 optimizationLevelMap({ { "0", JlcCommandLineOptions::OptimizationLevel::O0 },
556
557 static std::unordered_map<std::string, JlcCommandLineOptions::LanguageStandard>
558 languageStandardMap({ { "gnu89", JlcCommandLineOptions::LanguageStandard::Gnu89 },
568
569 if (!optimizationLevel.empty())
570 {
571 auto iterator = optimizationLevelMap.find(optimizationLevel);
572 if (iterator == optimizationLevelMap.end())
573 {
574 std::cerr << "Unknown optimization level.\n";
575 exit(EXIT_FAILURE);
576 }
577 CommandLineOptions_.OptimizationLevel_ = iterator->second;
578 }
579
580 if (!languageStandard.empty())
581 {
582 auto iterator = languageStandardMap.find(languageStandard);
583 if (iterator == languageStandardMap.end())
584 {
585 std::cerr << "Unknown language standard.\n";
586 exit(EXIT_FAILURE);
587 }
588 CommandLineOptions_.LanguageStandard_ = iterator->second;
589 }
590
591 if (inputFiles.empty())
592 {
593 std::cerr << "jlc: no input files.\n";
594 exit(EXIT_FAILURE);
595 }
596
597 if (inputFiles.size() > 1 && noLinking && !outputFile.empty())
598 {
599 std::cerr << "jlc: cannot specify -o when generating multiple output files.\n";
600 exit(EXIT_FAILURE);
601 }
602
603 auto jlmOptOptimizations =
604 checkAndConvertJlmOptOptimizations(jlmOptimizations, CommandLineOptions_.OptimizationLevel_);
605
606 CommandLineOptions_.Libraries_ = libraries;
607 CommandLineOptions_.MacroDefinitions_ = macroDefinitions;
608 CommandLineOptions_.LibraryPaths_ = libraryPaths;
609 CommandLineOptions_.Warnings_ = warnings;
610 CommandLineOptions_.IncludePaths_ = includePaths;
611 CommandLineOptions_.OnlyPrintCommands_ = onlyPrintCommands;
612 CommandLineOptions_.GenerateDebugInformation_ = generateDebugInformation;
613 CommandLineOptions_.Flags_ = flags;
614 CommandLineOptions_.JlmOptOptimizations_ = jlmOptOptimizations;
615 CommandLineOptions_.JlmOptPassStatistics_ = util::HashSet<util::Statistics::Id>(
616 { jlmOptPassStatistics.begin(), jlmOptPassStatistics.end() });
617 CommandLineOptions_.Verbose_ = verbose;
618 CommandLineOptions_.Rdynamic_ = rDynamic;
619 CommandLineOptions_.Suppress_ = suppress;
620 CommandLineOptions_.UsePthreads_ = usePthreads;
621 CommandLineOptions_.Md_ = mD;
622
623 for (auto & inputFile : inputFiles)
624 {
625 util::FilePath inputFilePath(inputFile);
626 if (IsObjectFile(inputFilePath))
627 {
628 /* FIXME: print a warning like clang if noLinking is true */
629 CommandLineOptions_.Compilations_.push_back(
630 { inputFilePath, util::FilePath(""), inputFilePath, "", false, false, false, true });
631
632 continue;
633 }
634
635 CommandLineOptions_.Compilations_.push_back(
636 { inputFilePath,
637 mF.empty() ? ToDependencyFile(inputFilePath) : util::FilePath(mF),
638 ToObjectFile(inputFilePath),
639 mT.empty() ? ToObjectFile(inputFilePath).name() : mT,
640 true,
641 true,
642 true,
643 !noLinking });
644 }
645
646 if (!outputFile.empty())
647 {
648 util::FilePath outputFilePath(outputFile);
649 if (noLinking)
650 {
651 JLM_ASSERT(CommandLineOptions_.Compilations_.size() == 1);
652 CommandLineOptions_.Compilations_[0].SetOutputFile(outputFilePath);
653 }
654 else
655 {
656 CommandLineOptions_.OutputFile_ = outputFilePath;
657 }
658 }
659
660 return CommandLineOptions_;
661}
662
664
666JlmOptCommandLineParser::ParseCommandLineArguments(int argc, const char * const * argv)
667{
668 using namespace ::llvm;
669
670 /*
671 FIXME: The command line parser setup is currently redone
672 for every invocation of parse_cmdline. We should be able
673 to do it only once and then reset the parser on every
674 invocation of parse_cmdline.
675 */
676
677 cl::TopLevelSubCommand->reset();
678
679 cl::opt<std::string> inputFile(cl::Positional, cl::desc("<input>"));
680
681 cl::opt<std::string> outputFile(
682 "o",
683 cl::init(""),
684 cl::desc("Write output to <file>"),
685 cl::value_desc("file"));
686
687 const auto statisticsDirectoryDefault = util::FilePath::TempDirectoryPath().Join("jlm");
688 const auto statisticDirectoryDescription =
689 "Write statistics and debug output to files in <dir>. Default is "
690 + statisticsDirectoryDefault.to_str() + ".";
691 cl::opt<std::string> statisticDirectory(
692 "s",
693 cl::init(statisticsDirectoryDefault.to_str()),
694 cl::desc(statisticDirectoryDescription),
695 cl::value_desc("dir"));
696
697 cl::opt<bool> dumpRvsdgGraphs(
698 "dumpRvsdgGraphs",
699 cl::init(false),
700 cl::desc("Dump RVSDG as json graphs after each transformation in debug folder."));
701
702 cl::list<util::Statistics::Id> printStatistics(
703 cl::values(
706 "Write aggregate alloca splitting statistics to file."),
709 "Write aggregation statistics to file."),
712 "Collect agnostic mod/ref summarization pass statistics."),
715 "Evaluate alias analysis precision and store to file"),
718 "Collect Andersen alias analysis pass statistics."),
721 "Write annotation statistics to file."),
724 "Write encoding statistics of basic encoder to file."),
727 "Write common node elimination statistics to file."),
730 "Write control flow recovery statistics to file."),
733 "Write data node to delta node conversion statistics to file."),
736 "Write dead node elimination statistics to file."),
739 "Write function inlining statistics to file."),
742 "Collect if-conversion transformation statistics"),
745 "Write invariant value redirection statistics to file."),
748 "Write Jlm to RVSDG conversion statistics to file."),
751 "Write loop strength reduction statistics to file."),
754 "Write loop unrolling statistics to file."),
757 "Collect loop unswitching pass statistics."),
760 "Write node pull statistics to file."),
763 "Write node push statistics to file."),
766 "Write node reduction statistics to file."),
769 "Collect region-aware mod/ref summarization statistics."),
772 "Write RVSDG construction statistics to file."),
775 "Write RVSDG destruction statistics to file."),
778 "Write RVSDG optimization statistics to file."),
781 "Write RVSDG tree printer pass statistics."),
784 "Write scalar evolution statistics to file."),
787 "Write store value forwarding statistics to file.")),
788 cl::desc("Write statistics"));
789
790#ifdef ENABLE_MLIR
791 auto llvmInputFormat = JlmOptCommandLineOptions::InputFormat::Llvm;
792 auto mlirInputFormat = JlmOptCommandLineOptions::InputFormat::Mlir;
793
794 cl::opt<JlmOptCommandLineOptions::InputFormat> inputFormat(
795 "input-format",
796 cl::desc("Select input format:"),
797 cl::values(
798 ::clEnumValN(
799 llvmInputFormat,
801 "Input LLVM IR [default]"),
802 ::clEnumValN(
803 mlirInputFormat,
805 "Input MLIR")),
806 cl::init(llvmInputFormat));
807#else
809#endif
810
811 cl::opt<JlmOptCommandLineOptions::OutputFormat> outputFormat(
812 "output-format",
813 cl::desc("Select output format:"),
814 cl::values(
819 "Output json dump"),
822 "Output Rvsdg tree as JSON"),
825 "Output LLVM IR [default]"),
826#ifdef ENABLE_MLIR
828#endif
831 "Output Rvsdg Tree")),
833
836 auto aggregateAllocaSplitting =
842 auto invariantValueRedirection =
856
857 cl::list<JlmOptCommandLineOptions::OptimizationId> optimizationIds(
858 cl::values(
859 ::clEnumValN(
860 aAAndersenAgnostic,
862 "Andersen alias analysis with agnostic memory state encoding"),
863 ::clEnumValN(
864 aAAndersenRegionAware,
866 "Andersen alias analysis with region-aware memory state encoding"),
867 ::clEnumValN(
868 aggregateAllocaSplitting,
869 JlmOptCommandLineOptions::ToCommandLineArgument(aggregateAllocaSplitting),
870 "Split aggregate type alloca nodes"),
871 ::clEnumValN(
872 commonNodeElimination,
874 "Common Node Elimination"),
875 ::clEnumValN(
876 deadNodeElimination,
878 "Dead Node Elimination"),
879 ::clEnumValN(
880 functionInlining,
882 "Function Inlining"),
883 ::clEnumValN(
884 ifConversion,
886 "Convert pass-through values of gamma nodes to select operations"),
887 ::clEnumValN(
888 invariantValueRedirection,
889 JlmOptCommandLineOptions::ToCommandLineArgument(invariantValueRedirection),
890 "Invariant Value Redirection"),
891 ::clEnumValN(
892 ioBarrierElimination,
894 "Eliminate IOBarrier nodes"),
895 ::clEnumValN(
896 loadChainSeparation,
898 "Separate chains of load operations"),
899 ::clEnumValN(
900 loopStrengthReduction,
902 "Loop strength reduction"),
903 ::clEnumValN(
904 loopUnrolling,
906 "Loop Unrolling"),
907 ::clEnumValN(
908 loopUnswitching,
910 "Move conditionals outside loops"),
911 ::clEnumValN(
912 nodePushOut,
914 "Node Push Out"),
915 ::clEnumValN(
916 nodePullIn,
918 "Node Pull In"),
919 ::clEnumValN(
920 nodeReduction,
922 "Node Reduction"),
923 ::clEnumValN(
924 predicateCorrelation,
926 "Correlate predicates between theta and gamma nodes"),
927 ::clEnumValN(
928 rvsdgTreePrinter,
930 "Rvsdg Tree Printer"),
931 ::clEnumValN(
932 scalarEvolution,
934 "Scalar evolution"),
935 ::clEnumValN(
936 storeValueForwarding,
938 "Store Value Forwarding"),
939 ::clEnumValN(
940 loopUnswitching,
941 "ThetaGammaInversion",
942 "[DEPRECATED] Use --LoopUnswitching instead.")),
943 cl::desc("Perform optimization"));
944
945 cl::list<llvm::RvsdgTreePrinter::Configuration::Annotation> rvsdgTreePrinterAnnotations(
946 "annotations",
947 cl::values(::clEnumValN(
949 "DebugIds",
950 "Annotate region and node IDs")),
951 cl::values(::clEnumValN(
953 "NumAggregateAllocaNodes",
954 "Annotate number of AllocaOperation nodes with aggregate types.")),
955 cl::values(::clEnumValN(
957 "NumAllocaNodes",
958 "Annotate number of AllocaOperation nodes")),
959 cl::values(::clEnumValN(
961 "NumLoadNodes",
962 "Annotate number of LoadOperation nodes")),
963 cl::values(::clEnumValN(
965 "NumMemoryStateInputsOutputs",
966 "Annotate number of inputs/outputs with memory state type")),
967 cl::values(::clEnumValN(
969 "NumRvsdgNodes",
970 "Annotate number of RVSDG nodes")),
971 cl::values(::clEnumValN(
973 "NumStoreNodes",
974 "Annotate number of StoreOperation nodes")),
975 cl::CommaSeparated,
976 cl::desc("Comma separated list of RVSDG tree printer annotations"));
977
978 cl::ParseCommandLineOptions(argc, argv);
979
980 jlm::util::FilePath statisticsDirectoryFilePath(statisticDirectory);
981 jlm::util::FilePath inputFilePath(inputFile);
982
983 util::HashSet<util::Statistics::Id> demandedStatistics(
984 { printStatistics.begin(), printStatistics.end() });
985
986 util::StatisticsCollectorSettings statisticsCollectorSettings(
987 std::move(demandedStatistics),
988 statisticsDirectoryFilePath,
989 inputFilePath.base());
990
992 { rvsdgTreePrinterAnnotations.begin(), rvsdgTreePrinterAnnotations.end() });
993
994 llvm::RvsdgTreePrinter::Configuration treePrinterConfiguration(std::move(demandedAnnotations));
995
996 CommandLineOptions_ = JlmOptCommandLineOptions::Create(
997 std::move(inputFilePath),
998 inputFormat,
999 util::FilePath(outputFile),
1000 outputFormat,
1001 std::move(statisticsCollectorSettings),
1002 std::move(treePrinterConfiguration),
1003 std::move(optimizationIds),
1004 dumpRvsdgGraphs);
1005
1006 return *CommandLineOptions_;
1007}
1008
1010JlmOptCommandLineParser::Parse(int argc, const char * const * argv)
1011{
1012 static JlmOptCommandLineParser parser;
1013 return parser.ParseCommandLineArguments(argc, argv);
1014}
1015
1017
1019JlmHlsCommandLineParser::ParseCommandLineArguments(int argc, const char * const * argv)
1020{
1021 CommandLineOptions_.Reset();
1022
1023 using namespace ::llvm;
1024
1025 /*
1026 FIXME: The command line parser setup is currently redone
1027 for every invocation of parse_cmdline. We should be able
1028 to do it only once and then reset the parser on every
1029 invocation of parse_cmdline.
1030 */
1031
1032 cl::TopLevelSubCommand->reset();
1033
1034 cl::opt<std::string> inputFile(cl::Positional, cl::desc("<input>"));
1035
1036 cl::opt<std::string> outputFolder(
1037 "o",
1038 cl::desc("Write output to <folder>"),
1039 cl::value_desc("folder"));
1040
1041 cl::opt<std::string> hlsFunction(
1042 "hls-function",
1043 cl::Prefix,
1044 cl::desc("Function that should be accelerated"),
1045 cl::value_desc("hls-function"));
1046
1047 cl::opt<int> latency(
1048 "latency",
1049 cl::Prefix,
1050 cl::init(CommandLineOptions_.MemoryLatency_),
1051 cl::desc("Memory latency"),
1052 cl::value_desc("latency"));
1053
1054 cl::opt<bool> extractHlsFunction(
1055 "extract",
1056 cl::Prefix,
1057 cl::desc("Extracts function specified by hls-function"));
1058
1059 cl::opt<bool> dumpRvsdgGraphs(
1060 "dumpRvsdgGraphs",
1061 cl::init(false),
1062 cl::desc("Dump RVSDG as json graphs after each transformation in debug folder."));
1063
1064 cl::opt<JlmHlsCommandLineOptions::OutputFormat> format(
1065 cl::values(
1066 ::clEnumValN(
1068 "fir",
1069 "Output FIRRTL [default]"),
1070 ::clEnumValN(JlmHlsCommandLineOptions::OutputFormat::Dot, "dot", "Output DOT graph")),
1071 cl::desc("Select output format"));
1072
1073 cl::ParseCommandLineOptions(argc, argv);
1074
1075 if (outputFolder.empty())
1076 throw util::Error("jlm-hls no output directory provided, i.e, -o.\n");
1077
1078 if (extractHlsFunction && hlsFunction.empty())
1079 throw util::Error(
1080 "jlm-hls: --hls-function is not specified.\n which is required for --extract\n");
1081
1082 CommandLineOptions_.InputFile_ = util::FilePath(inputFile);
1083 CommandLineOptions_.HlsFunction_ = std::move(hlsFunction);
1084 CommandLineOptions_.OutputFiles_ = util::FilePath(outputFolder);
1085 CommandLineOptions_.ExtractHlsFunction_ = extractHlsFunction;
1086 CommandLineOptions_.OutputFormat_ = format;
1087 CommandLineOptions_.dumpRvsdgGraphs_ = dumpRvsdgGraphs;
1088
1089 if (latency < 1)
1090 {
1091 throw util::Error("The --latency must be set to a number larger than zero.");
1092 }
1093 CommandLineOptions_.MemoryLatency_ = latency;
1094
1095 return CommandLineOptions_;
1096}
1097
1099JlmHlsCommandLineParser::Parse(int argc, const char * const * argv)
1100{
1101 static JlmHlsCommandLineParser parser;
1102 return parser.ParseCommandLineArguments(argc, argv);
1103}
1104
1106
1108JhlsCommandLineParser::ParseCommandLineArguments(int argc, const char * const * argv)
1109{
1110 CommandLineOptions_.Reset();
1111
1112 using namespace ::llvm;
1113
1114 /*
1115 FIXME: The command line parser setup is currently redone
1116 for every invocation of parse_cmdline. We should be able
1117 to do it only once and then reset the parser on every
1118 invocation of parse_cmdline.
1119 */
1120
1121 cl::TopLevelSubCommand->reset();
1122
1123 cl::opt<bool> onlyPrintCommands(
1124 "###",
1125 cl::ValueDisallowed,
1126 cl::desc("Print (but do not run) the commands for this compilation."));
1127
1128 cl::list<std::string> inputFiles(cl::Positional, cl::desc("<inputs>"));
1129
1130 cl::list<std::string> includePaths(
1131 "I",
1132 cl::Prefix,
1133 cl::desc("Add directory <dir> to include search paths."),
1134 cl::value_desc("dir"));
1135
1136 cl::list<std::string> libraryPaths(
1137 "L",
1138 cl::Prefix,
1139 cl::desc("Add directory <dir> to library search paths."),
1140 cl::value_desc("dir"));
1141
1142 cl::list<std::string> libraries(
1143 "l",
1144 cl::Prefix,
1145 cl::desc("Search the library <lib> when linking."),
1146 cl::value_desc("lib"));
1147
1148 cl::opt<std::string> outputFile("o", cl::desc("Write output to <file>."), cl::value_desc("file"));
1149
1150 cl::opt<bool> generateDebugInformation(
1151 "g",
1152 cl::ValueDisallowed,
1153 cl::desc("Generate source-level debug information."));
1154
1155 cl::opt<bool> noLinking(
1156 "c",
1157 cl::ValueDisallowed,
1158 cl::desc("Only run preprocess, compile, and assemble steps."));
1159
1160 cl::opt<std::string> optimizationLevel(
1161 "O",
1162 cl::Prefix,
1163 cl::ValueOptional,
1164 cl::desc("Optimization level. [O0, O1, O2, O3]"),
1165 cl::value_desc("#"));
1166
1167 cl::list<std::string> macroDefinitions(
1168 "D",
1169 cl::Prefix,
1170 cl::desc("Add <macro> to preprocessor macros."),
1171 cl::value_desc("macro"));
1172
1173 cl::list<std::string> warnings(
1174 "W",
1175 cl::Prefix,
1176 cl::desc("Enable specified warning."),
1177 cl::value_desc("warning"));
1178
1179 cl::opt<std::string> languageStandard(
1180 "std",
1181 cl::desc("Language standard."),
1182 cl::value_desc("standard"));
1183
1184 cl::list<std::string> flags("f", cl::Prefix, cl::desc("Specify flags."), cl::value_desc("flag"));
1185
1186 cl::list<std::string> jlmHlsOptimizations(
1187 "J",
1188 cl::Prefix,
1189 cl::desc("jlm-hls optimization. Run 'jlm-hls -help' for viable options."),
1190 cl::value_desc("jlmhls"));
1191
1192 cl::opt<bool> verbose(
1193 "v",
1194 cl::ValueDisallowed,
1195 cl::desc("Show commands to run and use verbose output. (Affects only clang for now)"));
1196
1197 cl::opt<bool> rdynamic(
1198 "rdynamic",
1199 cl::ValueDisallowed,
1200 cl::desc("rdynamic option passed to clang"));
1201
1202 cl::opt<bool> suppress("w", cl::ValueDisallowed, cl::desc("Suppress all warnings"));
1203
1204 cl::opt<bool> usePthreads(
1205 "pthread",
1206 cl::ValueDisallowed,
1207 cl::desc("Support POSIX threads in generated code"));
1208
1209 cl::opt<bool> mD(
1210 "MD",
1211 cl::ValueDisallowed,
1212 cl::desc("Write a depfile containing user and system headers"));
1213
1214 cl::opt<std::string> mF(
1215 "MF",
1216 cl::desc("Write depfile output from -MD to <file>."),
1217 cl::value_desc("file"));
1218
1219 cl::opt<std::string> mT(
1220 "MT",
1221 cl::desc("Specify name of main file output in depfile."),
1222 cl::value_desc("value"));
1223
1224 cl::list<std::string> hlsFunction(
1225 "hls-function",
1226 cl::Prefix,
1227 cl::desc("function that should be accelerated"),
1228 cl::value_desc("regex"));
1229
1230 cl::opt<bool> generateFirrtl("firrtl", cl::ValueDisallowed, cl::desc("Generate firrtl"));
1231
1232 cl::opt<bool> useCirct(
1233 "circt",
1234 cl::Prefix,
1235 cl::desc("DEPRACATED - CIRCT is always used to generate FIRRTL"));
1236
1237 cl::ParseCommandLineOptions(argc, argv);
1238
1239 /* Process parsed options */
1240
1241 static std::unordered_map<std::string, JhlsCommandLineOptions::OptimizationLevel> Olvlmap(
1246
1247 static std::unordered_map<std::string, JhlsCommandLineOptions::LanguageStandard> stdmap(
1257
1258 if (!optimizationLevel.empty())
1259 {
1260 auto it = Olvlmap.find(optimizationLevel);
1261 if (it == Olvlmap.end())
1262 {
1263 std::cerr << "Unknown optimization level.\n";
1264 exit(EXIT_FAILURE);
1265 }
1266 CommandLineOptions_.OptimizationLevel_ = it->second;
1267 }
1268
1269 if (!languageStandard.empty())
1270 {
1271 auto it = stdmap.find(languageStandard);
1272 if (it == stdmap.end())
1273 {
1274 std::cerr << "Unknown language standard.\n";
1275 exit(EXIT_FAILURE);
1276 }
1277 CommandLineOptions_.LanguageStandard_ = it->second;
1278 }
1279
1280 if (inputFiles.empty())
1281 {
1282 std::cerr << "jlc: no input files.\n";
1283 exit(EXIT_FAILURE);
1284 }
1285
1286 if (inputFiles.size() > 1 && noLinking && !outputFile.empty())
1287 {
1288 std::cerr << "jlc: cannot specify -o when generating multiple output files.\n";
1289 exit(EXIT_FAILURE);
1290 }
1291
1292 if (!hlsFunction.empty())
1293 {
1294 CommandLineOptions_.Hls_ = true;
1295 CommandLineOptions_.HlsFunctionRegex_ = hlsFunction.front();
1296 }
1297
1298 if (hlsFunction.size() > 1)
1299 {
1300 std::cerr << "jlc-hls: more than one function regex specified\n";
1301 exit(EXIT_FAILURE);
1302 }
1303
1304 CommandLineOptions_.Libraries_ = libraries;
1305 CommandLineOptions_.MacroDefinitions_ = macroDefinitions;
1306 CommandLineOptions_.LibraryPaths_ = libraryPaths;
1307 CommandLineOptions_.Warnings_ = warnings;
1308 CommandLineOptions_.IncludePaths_ = includePaths;
1309 CommandLineOptions_.OnlyPrintCommands_ = onlyPrintCommands;
1310 CommandLineOptions_.GenerateDebugInformation_ = generateDebugInformation;
1311 CommandLineOptions_.Flags_ = flags;
1312 CommandLineOptions_.JlmHls_ = jlmHlsOptimizations;
1313 CommandLineOptions_.Verbose_ = verbose;
1314 CommandLineOptions_.Rdynamic_ = rdynamic;
1315 CommandLineOptions_.Suppress_ = suppress;
1316 CommandLineOptions_.UsePthreads_ = usePthreads;
1317 CommandLineOptions_.Md_ = mD;
1318 CommandLineOptions_.GenerateFirrtl_ = generateFirrtl;
1319
1320 for (auto & inputFile : inputFiles)
1321 {
1322 util::FilePath inputFilePath(inputFile);
1323 if (IsObjectFile(inputFilePath))
1324 {
1325 /* FIXME: print a warning like clang if noLinking is true */
1326 CommandLineOptions_.Compilations_.push_back(
1327 { inputFilePath, util::FilePath(""), inputFilePath, "", false, false, false, true });
1328
1329 continue;
1330 }
1331
1332 CommandLineOptions_.Compilations_.push_back(
1333 { inputFilePath,
1334 mF.empty() ? CreateDependencyFileFromFile(inputFilePath) : util::FilePath(mF),
1335 CreateObjectFileFromFile(inputFilePath),
1336 mT.empty() ? CreateObjectFileFromFile(inputFilePath).name() : mT,
1337 true,
1338 true,
1339 true,
1340 !noLinking });
1341 }
1342
1343 if (!outputFile.empty())
1344 {
1345 util::FilePath outputFilePath(outputFile);
1346 if (noLinking)
1347 {
1348 JLM_ASSERT(CommandLineOptions_.Compilations_.size() == 1);
1349 CommandLineOptions_.Compilations_[0].SetOutputFile(outputFilePath);
1350 }
1351 else
1352 {
1353 CommandLineOptions_.OutputFile_ = outputFilePath;
1354 }
1355 }
1356
1357 return CommandLineOptions_;
1358}
1359
1360bool
1362{
1363 return file.suffix() == "o";
1364}
1365
1368{
1369 return f.Dirname().Join(f.base() + ".o");
1370}
1371
1374{
1375 return f.Dirname().Join(f.base() + ".d");
1376}
1377
1379JhlsCommandLineParser::Parse(int argc, const char * const * argv)
1380{
1381 static JhlsCommandLineParser parser;
1382 return parser.ParseCommandLineArguments(argc, argv);
1383}
1384
1385}
static const jlm::tooling::JlcCommandLineOptions & ParseCommandLineArguments(const std::vector< std::string > &commandLineArguments)
virtual ~CommandLineParser() noexcept
const JhlsCommandLineOptions & ParseCommandLineArguments(int argc, const char *const *argv) override
static util::FilePath CreateDependencyFileFromFile(const util::FilePath &f)
static const JhlsCommandLineOptions & Parse(int argc, const char *const *arv)
static util::FilePath CreateObjectFileFromFile(const util::FilePath &f)
static bool IsObjectFile(const util::FilePath &file)
~JhlsCommandLineParser() noexcept override
std::vector< Compilation > Compilations_
void Reset() noexcept override
static std::string_view ToString(const OptimizationLevel &optimizationLevel)
std::vector< std::string > Warnings_
std::vector< JlmOptCommandLineOptions::OptimizationId > JlmOptOptimizations_
std::vector< std::string > LibraryPaths_
std::vector< std::string > Libraries_
std::vector< std::string > MacroDefinitions_
std::vector< std::string > Flags_
std::vector< std::string > IncludePaths_
static const JlmHlsCommandLineOptions & Parse(int argc, const char *const *argv)
const JlmHlsCommandLineOptions & ParseCommandLineArguments(int argc, const char *const *argv) override
~JlmHlsCommandLineParser() noexcept override
static const util::BijectiveMap< util::Statistics::Id, std::string_view > & GetStatisticsIdCommandLineArguments()
static OptimizationId FromCommandLineArgumentToOptimizationId(std::string_view commandLineArgument)
static std::string_view ToCommandLineArgument(OptimizationId optimizationId)
static util::Statistics::Id FromCommandLineArgumentToStatisticsId(std::string_view commandLineArgument)
static const std::unordered_map< OutputFormat, std::string_view > & GetOutputFormatCommandLineArguments()
static std::unique_ptr< JlmOptCommandLineOptions > Create(util::FilePath inputFile, InputFormat inputFormat, util::FilePath outputFile, OutputFormat outputFormat, util::StatisticsCollectorSettings statisticsCollectorSettings, llvm::RvsdgTreePrinter::Configuration rvsdgTreePrinterConfiguration, std::vector< OptimizationId > optimizations, bool dumpRvsdgGraphs)
static const util::BijectiveMap< OptimizationId, std::string_view > & GetOptimizationIdCommandLineMap()
std::vector< OptimizationId > OptimizationIds_
util::StatisticsCollectorSettings StatisticsCollectorSettings_
static const JlmOptCommandLineOptions & Parse(int argc, const char *const *argv)
const JlmOptCommandLineOptions & ParseCommandLineArguments(int argc, const char *const *argv) override
~JlmOptCommandLineParser() noexcept override
std::size_t Size() const noexcept
std::string name() const noexcept
Returns the name of the file, excluding the path.
Definition file.hpp:81
static FilePath TempDirectoryPath()
Definition file.hpp:317
FilePath Join(const std::string &other) const
Definition file.hpp:193
std::string base() const noexcept
Returns the base name of the file without the path.
Definition file.hpp:61
const std::string & to_str() const noexcept
Definition file.hpp:275
FilePath Dirname() const noexcept
Returns the path to the file or directory's parent directory. Emulates the behavior of the GNU coreut...
Definition file.hpp:148
std::string suffix() const noexcept
Returns the suffix (extension) of the file.
Definition file.hpp:116
#define JLM_ASSERT(x)
Definition common.hpp:16
::llvm::cl::OptionEnumValue CreateOutputFormatOption(JlmOptCommandLineOptions::OutputFormat outputFormat, std::string_view description)
::llvm::cl::OptionEnumValue CreateStatisticsOption(util::Statistics::Id statisticsId, std::string_view description)
static std::string strfmt(Args... args)
Definition strfmt.hpp:35