source: icGREP/icgrep-devel/icgrep/toolchain/toolchain.cpp @ 5745

Last change on this file since 5745 was 5745, checked in by cameron, 15 months ago

ShowIR, ShowASM, ShowUnoptimizedIR options can set filename: -ShowIR=myIRfile

File size: 8.1 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include <toolchain/toolchain.h>
8#include <UCD/UCD_Config.h>
9#include <llvm/CodeGen/CommandFlags.h>
10#include <llvm/Support/raw_ostream.h>
11
12using namespace llvm;
13
14#ifndef NDEBUG
15#define IN_DEBUG_MODE true
16#else
17#define IN_DEBUG_MODE false
18#endif
19
20namespace codegen {
21
22static cl::OptionCategory CodeGenOptions("Code Generation Options", "These options control code generation.");
23
24static cl::bits<DebugFlags>
25DebugOptions(cl::values(clEnumVal(VerifyIR, "Run the IR verification pass."),
26                        clEnumVal(SerializeThreads, "Force segment threads to run sequentially."),
27                        clEnumVal(TraceCounts, "Show kernel processed and produced item counts."),
28                        clEnumVal(TraceDynamicBuffers, "Show dynamic buffer allocations and deallocations."),
29                        clEnumVal(EnableAsserts, "Enable built-in Parabix framework asserts in generated IR."),
30                        clEnumVal(EnableCycleCounter, "Count and report CPU cycles per kernel.")
31                        CL_ENUM_VAL_SENTINEL), cl::cat(CodeGenOptions));
32
33std::string ShowIROption = OmittedOption;
34static cl::opt<std::string, true> IROutputOption("ShowIR", cl::location(ShowIROption), cl::ValueOptional,
35                                                         cl::desc("Print optimized LLVM IR to stderr (by omitting =<filename>) or a file"), cl::value_desc("filename"), cl::cat(CodeGenOptions));
36
37std::string ShowUnoptimizedIROption = OmittedOption;
38static cl::opt<std::string, true> UnoptimizedIROutputOption("ShowUnoptimizedIR", cl::location(ShowUnoptimizedIROption), cl::ValueOptional,
39                                                         cl::desc("Print generated LLVM IR to stderr (by omitting =<filename> or a file"), cl::value_desc("filename"), cl::cat(CodeGenOptions));
40
41#if LLVM_VERSION_INTEGER >= LLVM_3_7_0
42std::string ShowASMOption = OmittedOption;
43static cl::opt<std::string, true> ASMOutputFilenameOption("ShowASM", cl::location(ShowASMOption), cl::ValueOptional,
44                                                         cl::desc("Print generated assembly code to stderr (by omitting =<filename> or a file"), cl::value_desc("filename"), cl::cat(CodeGenOptions));
45#endif
46
47static cl::opt<char> OptLevelOption("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] (default = '-O1')"),
48                                    cl::cat(CodeGenOptions), cl::Prefix, cl::ZeroOrMore, cl::init('1'));
49
50
51static cl::opt<bool, true> EnableObjectCacheOption("enable-object-cache", cl::location(EnableObjectCache), cl::init(true),
52                                                   cl::desc("Enable object caching"), cl::cat(CodeGenOptions));
53
54static cl::opt<std::string> ObjectCacheDirOption("object-cache-dir", cl::init(""),
55                                                 cl::desc("Path to the object cache diretory"), cl::cat(CodeGenOptions));
56
57
58static cl::opt<int, true> BlockSizeOption("BlockSize", cl::location(BlockSize), cl::init(0),
59                                          cl::desc("specify a block size (defaults to widest SIMD register width in bits)."), cl::cat(CodeGenOptions));
60
61
62static cl::opt<int, true> SegmentSizeOption("segment-size", cl::location(SegmentSize), cl::init(8),
63                                            cl::desc("Segment Size"), cl::value_desc("positive integer"));
64
65static cl::opt<int, true> BufferSegmentsOption("buffer-segments", cl::location(BufferSegments), cl::init(1),
66                                               cl::desc("Buffer Segments"), cl::value_desc("positive integer"));
67
68
69static cl::opt<int, true> ThreadNumOption("thread-num", cl::location(ThreadNum), cl::init(2),
70                                          cl::desc("Number of threads used for segment pipeline parallel"), cl::value_desc("positive integer"));
71
72
73static cl::opt<bool, true> pipelineParallelOption("enable-pipeline-parallel", cl::location(PipelineParallel), cl::init(false),
74                                                  cl::desc("Enable multithreading with pipeline parallelism."), cl::cat(CodeGenOptions));
75   
76static cl::opt<bool, true> segmentPipelineParallelOption("enable-segment-pipeline-parallel", cl::location(SegmentPipelineParallel),
77                                                         cl::desc("Enable multithreading with segment pipeline parallelism."), cl::cat(CodeGenOptions));
78
79static cl::opt<bool, true> NVPTXOption("NVPTX", cl::location(NVPTX), cl::init(false),
80                                 cl::desc("Run on GPU only."), cl::cat(CodeGenOptions));
81
82static cl::opt<int, true> GroupNumOption("group-num", cl::location(GroupNum), cl::init(256),
83                                         cl::desc("NUmber of groups declared on GPU"), cl::value_desc("positive integer"), cl::cat(CodeGenOptions));
84
85CodeGenOpt::Level OptLevel;
86
87bool PipelineParallel;
88
89bool SegmentPipelineParallel;
90
91const char * ObjectCacheDir;
92
93int BlockSize;
94
95int SegmentSize;
96
97int BufferSegments;
98
99int ThreadNum;
100
101bool EnableObjectCache;
102
103bool NVPTX = [](const bool nvptx) {
104    #ifndef CUDA_ENABLED
105    if (nvptx) {
106        report_fatal_error("CUDA compiler is not supported.");
107    }
108    #endif
109    return nvptx;
110}(NVPTXOption);
111
112int GroupNum;
113
114const llvm::Reloc::Model RelocModel = ::RelocModel;
115
116const llvm::CodeModel::Model CMModel = ::CMModel;
117
118const std::string MArch = ::MArch;
119
120const llvm::TargetMachine::CodeGenFileType FileType = ::FileType;
121
122TargetOptions Options;
123
124const cl::OptionCategory * codegen_flags() {
125    return &CodeGenOptions;
126}
127
128bool DebugOptionIsSet(const DebugFlags flag) {
129    if (IN_DEBUG_MODE && (flag == EnableAsserts)) return true;
130    return DebugOptions.isSet(flag);
131}
132
133std::string getCPUStr() {
134    return ::getCPUStr();
135}
136
137std::string getFeaturesStr() {
138    return ::getFeaturesStr();
139}
140
141void setFunctionAttributes(llvm::StringRef CPU, llvm::StringRef Features, llvm::Module &M) {
142    return ::setFunctionAttributes(CPU, Features, M);
143}
144
145std::string ProgramName;
146
147void ParseCommandLineOptions(int argc, const char * const *argv, std::initializer_list<const cl::OptionCategory *> hiding) {
148    AddParabixVersionPrinter();
149    codegen::ProgramName = argv[0];
150#if LLVM_VERSION_INTEGER >= LLVM_3_7_0
151    if (hiding.size() != 0) {
152        cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *>(hiding));
153    }
154#endif
155    cl::ParseCommandLineOptions(argc, argv);
156    if (DebugOptions.getBits() || (ShowIROption != OmittedOption) || (ShowUnoptimizedIROption != OmittedOption) || (ShowASMOption != OmittedOption)) {
157        EnableObjectCache = false;
158    }
159    ObjectCacheDir = ObjectCacheDirOption.empty() ? nullptr : ObjectCacheDirOption.data();
160    Options = InitTargetOptionsFromCodeGenFlags();
161#if LLVM_VERSION_INTEGER >= LLVM_3_7_0
162    Options.MCOptions.AsmVerbose = true;
163#endif
164    switch (OptLevelOption) {
165        case '0': OptLevel = CodeGenOpt::None; break;
166        case '1': OptLevel = CodeGenOpt::Less; break;
167        case '2': OptLevel = CodeGenOpt::Default; break;
168        case '3': OptLevel = CodeGenOpt::Aggressive; break;
169        default: report_fatal_error(std::string(1, OptLevelOption) + " is an invalid optimization level.");
170    }
171#ifndef CUDA_ENABLED
172    if (NVPTX) {
173        report_fatal_error("CUDA compiler is not supported.");
174    }
175#endif
176}
177
178}
179#if LLVM_VERSION_INTEGER < LLVM_6_0_0
180void printParabixVersion () {
181    outs() << "Unicode version " << UCD::UnicodeVersion << "\n";
182    outs() << "Parabix (http://parabix.costar.sfu.ca/):\n  " << "Parabix revision " << PARABIX_VERSION << "\n";
183}
184#else
185void printParabixVersion (raw_ostream & outs) {
186    outs << "Unicode version " << UCD::UnicodeVersion << "\n";
187    outs << "Parabix (http://parabix.costar.sfu.ca/):\n  " << "Parabix revision " << PARABIX_VERSION << "\n";
188}
189#endif
190
191void AddParabixVersionPrinter() {
192    cl::AddExtraVersionPrinter(&printParabixVersion);
193}
194
195bool AVX2_available() {
196    StringMap<bool> HostCPUFeatures;
197    if (sys::getHostCPUFeatures(HostCPUFeatures)) {
198        auto f = HostCPUFeatures.find("avx2");
199        return ((f != HostCPUFeatures.end()) && f->second);
200    }
201    return false;
202}
Note: See TracBrowser for help on using the repository browser.