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

Last change on this file since 5124 was 5117, checked in by cameron, 3 years ago

bitblock_advance

File size: 5.6 KB
Line 
1/*
2 *  Copyright (c) 2016 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 <string>
8#include <iostream>
9#include <fstream>
10#include <sstream>
11
12#include <toolchain.h>
13#include <llvm/IR/Function.h>
14#include <llvm/IR/Module.h>
15#include <llvm/ExecutionEngine/ExecutionEngine.h>
16#include <llvm/ExecutionEngine/MCJIT.h>
17#include "llvm/IR/LegacyPassManager.h"
18
19#include <llvm/IRReader/IRReader.h>
20#include <llvm/Support/CommandLine.h>
21#include <llvm/CodeGen/CommandFlags.h>
22#include <llvm/Support/SourceMgr.h>
23#include <llvm/Support/TargetSelect.h>
24#include <llvm/Support/Host.h>
25#include <llvm/Support/raw_ostream.h>
26
27#include <object_cache.h>
28
29using namespace llvm;
30
31namespace codegen {
32
33static cl::OptionCategory CodeGenOptions("Code Generation Options", "These options control code generation.");
34
35
36static cl::opt<bool> DumpGeneratedIR("dump-generated-IR", cl::init(false), cl::desc("Print LLVM IR generated by Pablo Compiler."), cl::cat(CodeGenOptions));
37static cl::opt<std::string> IROutputFilename("dump-generated-IR-output", cl::init(""), cl::desc("output IR filename"), cl::cat(CodeGenOptions));
38static cl::opt<bool> DumpASM("DumpASM", cl::init(false), cl::desc("Print Assembly Code."), cl::cat(CodeGenOptions));
39static cl::opt<bool> AsmVerbose("asm-verbose",
40                                cl::desc("Add comments to directives."),
41                                cl::init(true), cl::cat(CodeGenOptions));
42
43char OptLevel;
44static cl::opt<char, true> OptLevelOption("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] (default = '-O1')"), cl::location(OptLevel),
45                              cl::cat(CodeGenOptions), cl::Prefix, cl::ZeroOrMore, cl::init('1'));
46
47
48static cl::opt<bool> EnableObjectCache("enable-object-cache", cl::init(false), cl::desc("Enable object caching"), cl::cat(CodeGenOptions));
49
50static cl::opt<std::string> ObjectCacheDir("object-cache-dir", cl::init(""), cl::desc("Path to the object cache diretory"), cl::cat(CodeGenOptions));
51
52
53int BlockSize;
54int SegmentSize;
55
56static cl::opt<int, true> BlockSizeOption("BlockSize", cl::location(BlockSize), cl::init(0), cl::desc("specify a block size (defaults to widest SIMD register width in bits)."), cl::cat(CodeGenOptions));
57static cl::opt<int, true> SegmentSizeOption("segment-size", cl::location(SegmentSize), cl::desc("Segment Size"), cl::value_desc("positive integer"), cl::init(1));
58
59const cl::OptionCategory * codegen_flags() {return &CodeGenOptions;}
60
61}
62
63
64void setAllFeatures(EngineBuilder &builder) {
65    llvm::StringMap<bool> HostCPUFeatures;
66    if (llvm::sys::getHostCPUFeatures(HostCPUFeatures)) {
67        std::vector<std::string> attrs;
68        for (auto &flag : HostCPUFeatures) {
69            auto enabled = flag.second ? "+" : "-";
70            attrs.push_back(enabled + flag.first().str());
71        }
72        builder.setMAttrs(attrs);
73    }
74}
75
76bool AVX2_available() {
77    llvm::StringMap<bool> HostCPUFeatures;
78    if (llvm::sys::getHostCPUFeatures(HostCPUFeatures)) {
79        auto f = HostCPUFeatures.find("avx2");
80        return ((f != HostCPUFeatures.end()) && f->second);
81    }
82    return false;
83}
84
85
86void WriteAssembly (llvm::TargetMachine *TM, Module * m) {
87    llvm::legacy::PassManager PM;
88
89    llvm::SmallString<128> Str;
90    llvm::raw_svector_ostream dest(Str); 
91
92    if (TM->addPassesToEmitFile( PM , dest , llvm::TargetMachine::CGFT_AssemblyFile ) ) {
93      std::cout << "addPassesToEmitFile failed\n";
94      exit(1);
95    }
96    PM.run(*m);
97    std::cerr << std::string( Str.c_str() ) << "\n";
98}
99
100ExecutionEngine * JIT_to_ExecutionEngine (Module * m) {
101
102    InitializeNativeTarget();
103    InitializeNativeTargetAsmPrinter();
104    InitializeNativeTargetAsmParser();
105
106    PassRegistry * Registry = PassRegistry::getPassRegistry();
107    initializeCore(*Registry);
108    initializeCodeGen(*Registry);
109    initializeLowerIntrinsicsPass(*Registry);
110
111    std::string errMessage;
112    EngineBuilder builder{std::unique_ptr<Module>(m)};
113    builder.setErrorStr(&errMessage);
114    TargetOptions opts = InitTargetOptionsFromCodeGenFlags();
115    opts.MCOptions.AsmVerbose = codegen::AsmVerbose;
116
117    builder.setTargetOptions(opts);
118    builder.setVerifyModules(true);
119    CodeGenOpt::Level optLevel = CodeGenOpt::Level::None;
120    switch (codegen::OptLevel) {
121        case '0': optLevel = CodeGenOpt::None; break;
122        case '1': optLevel = CodeGenOpt::Less; break;
123        case '2': optLevel = CodeGenOpt::Default; break;
124        case '3': optLevel = CodeGenOpt::Aggressive; break;
125        default: errs() << codegen::OptLevel << " is an invalid optimization level.\n";
126    }
127    builder.setOptLevel(optLevel);
128
129    setAllFeatures(builder);
130
131    if (LLVM_UNLIKELY(codegen::DumpGeneratedIR)) {
132        if (codegen::IROutputFilename.empty()) {
133            m->dump();
134        } else {
135            std::error_code error;
136            llvm::raw_fd_ostream out(codegen::IROutputFilename, error, sys::fs::OpenFlags::F_None);
137            m->print(out, nullptr);
138        }
139    }
140
141    if (codegen::DumpASM) {
142      WriteAssembly(builder.selectTarget(), m);
143    }
144    ExecutionEngine * engine = builder.create();
145    if (engine == nullptr) {
146        throw std::runtime_error("Could not create ExecutionEngine: " + errMessage);
147    }   
148    return engine;
149}
150
151void ApplyObjectCache(ExecutionEngine * e) {
152    ICGrepObjectCache * cache = nullptr;
153    if (codegen::EnableObjectCache) {
154        if (codegen::ObjectCacheDir.empty())
155            // Default is $HOME/.cache/icgrep
156            cache = new ICGrepObjectCache();
157        else
158            cache = new ICGrepObjectCache(codegen::ObjectCacheDir);
159        e->setObjectCache(cache);
160    }   
161}
162
163
Note: See TracBrowser for help on using the repository browser.