source: icGREP/icgrep-devel/icgrep/casefold.cpp @ 5026

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

Updates for LLVM 3.8; hide unrelated command line options

File size: 6.5 KB
Line 
1/*
2 *  Copyright (c) 2015 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 <llvm/IR/Function.h>
13#include <llvm/IR/Module.h>
14#include <llvm/ExecutionEngine/ExecutionEngine.h>
15#include <llvm/ExecutionEngine/MCJIT.h>
16#include <llvm/IRReader/IRReader.h>
17#include <llvm/Support/CommandLine.h>
18#include <llvm/CodeGen/CommandFlags.h>
19#include <llvm/Support/SourceMgr.h>
20#include <llvm/Support/TargetSelect.h>
21#include <llvm/Support/Host.h>
22#include <llvm/Support/raw_ostream.h>
23
24#include <re/re_cc.h>
25#include <cc/cc_compiler.h>
26#include <pablo/function.h>
27#include <IDISA/idisa_builder.h>
28#include <IDISA/idisa_target.h>
29#include <kernels/casefold_pipeline.h>
30
31// Dynamic processor detection
32#define ISPC_LLVM_VERSION ISPC_LLVM_3_6
33#include <util/ispc.cpp>
34
35#include <utf_encoding.h>
36
37// mmap system
38#include <boost/filesystem.hpp>
39#include <boost/iostreams/device/mapped_file.hpp>
40using namespace boost::iostreams;
41using namespace boost::filesystem;
42
43#include <fcntl.h>
44
45static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<input file ...>"), cl::OneOrMore);
46
47
48static cl::OptionCategory cMachineCodeOptimization("Machine Code Optimizations", "These options control back-end compilier optimization levels.");
49
50static cl::opt<char> OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] (default = '-O0')"),
51                              cl::cat(cMachineCodeOptimization), cl::Prefix, cl::ZeroOrMore, cl::init('0'));
52
53
54//
55//  Functions taken from toolchain.cpp and modified for casefold
56//  JIT_t_ExecutionEngine : remove object cache
57//  icgrep_Linking:   unneeded?
58//  all others: definitely unneeded
59//
60
61ExecutionEngine * JIT_to_ExecutionEngine (Module * m) {
62
63    InitializeNativeTarget();
64    InitializeNativeTargetAsmPrinter();
65    InitializeNativeTargetAsmParser();
66
67    PassRegistry * Registry = PassRegistry::getPassRegistry();
68    initializeCore(*Registry);
69    initializeCodeGen(*Registry);
70    initializeLowerIntrinsicsPass(*Registry);
71
72    std::string errMessage;
73    EngineBuilder builder(std::move(std::unique_ptr<Module>(m)));
74    builder.setErrorStr(&errMessage);
75    builder.setMCPU(sys::getHostCPUName());
76    CodeGenOpt::Level optLevel = CodeGenOpt::Level::None;
77    switch (OptLevel) {
78        case '0': optLevel = CodeGenOpt::None; break;
79        case '1': optLevel = CodeGenOpt::Less; break;
80        case '2': optLevel = CodeGenOpt::Default; break;
81        case '3': optLevel = CodeGenOpt::Aggressive; break;
82        default: errs() << OptLevel << " is an invalid optimization level.\n";
83    }
84    builder.setOptLevel(optLevel);
85
86    if ((strncmp(lGetSystemISA(), "avx2", 4) == 0)) {
87            std::vector<std::string> attrs;
88            attrs.push_back("avx2");
89            builder.setMAttrs(attrs);
90    }
91
92    // builder.selectTarget();
93
94    //builder.setOptLevel(mMaxWhileDepth ? CodeGenOpt::Level::Less : CodeGenOpt::Level::None);
95    ExecutionEngine * engine = builder.create();
96    if (engine == nullptr) {
97        throw std::runtime_error("Could not create ExecutionEngine: " + errMessage);
98    }
99    return engine;
100}
101
102
103//
104//  Generate Pablo code for case folding.
105//
106
107pablo::PabloFunction * casefold2pablo(const Encoding encoding) {
108    pablo::PabloFunction * function = pablo::PabloFunction::Create("casefold_block", 8, 8);
109    cc::CC_Compiler cc_compiler(*function, encoding);
110    pablo::PabloBuilder pBuilder(cc_compiler.getBuilder().getPabloBlock(), cc_compiler.getBuilder());
111    const std::vector<pablo::Var *> basis_bits = cc_compiler.getBasisBits();
112   
113    pablo::PabloAST * alpha = cc_compiler.compileCC(re::makeCC(0x41, 0x5A));  // ASCII A-Z
114   
115    function->setResult(0, pBuilder.createAssign("b0", basis_bits[0]));
116    function->setResult(1, pBuilder.createAssign("b1", basis_bits[1]));
117    function->setResult(2, pBuilder.createAssign("b2", pBuilder.createXor(basis_bits[2], alpha)));
118    function->setResult(3, pBuilder.createAssign("b3", basis_bits[3]));
119    function->setResult(4, pBuilder.createAssign("b4", basis_bits[4]));
120    function->setResult(5, pBuilder.createAssign("b5", basis_bits[5]));
121    function->setResult(6, pBuilder.createAssign("b6", basis_bits[6]));
122    function->setResult(7, pBuilder.createAssign("b7", basis_bits[7]));
123    return function;
124}
125
126
127
128typedef void (*casefoldFunctionType)(char * byte_data, size_t filesize);
129
130casefoldFunctionType caseFoldCodeGen(void) {
131                           
132    Module * M = new Module("casefold", getGlobalContext());
133   
134    IDISA::IDISA_Builder * idb = GetIDISA_Builder(M);
135
136    kernel::PipelineBuilder pipelineBuilder(M, idb);
137
138    Encoding encoding(Encoding::Type::UTF_8, 8);
139   
140    pablo::PabloFunction * function = casefold2pablo(encoding);
141   
142
143    pipelineBuilder.CreateKernels(function);
144
145    pipelineBuilder.ExecuteKernels();
146
147    //std::cerr << "ExecuteKernels(); done\n";
148    llvm::Function * main_IR = M->getFunction("Main");
149    ExecutionEngine * mEngine = JIT_to_ExecutionEngine(M);
150   
151    mEngine->finalizeObject();
152    //std::cerr << "finalizeObject(); done\n";
153
154    delete idb;
155
156    return reinterpret_cast<casefoldFunctionType>(mEngine->getPointerToFunction(main_IR));
157}
158
159void doCaseFold(casefoldFunctionType fn_ptr, const std::string & fileName) {
160    std::string mFileName = fileName;
161    size_t mFileSize;
162    char * mFileBuffer;
163   
164    const path file(mFileName);
165    if (exists(file)) {
166        if (is_directory(file)) {
167            return;
168        }
169    } else {
170        std::cerr << "Error: cannot open " << mFileName << " for processing. Skipped.\n";
171        return;
172    }
173   
174    mFileSize = file_size(file);
175    mapped_file mFile;
176    if (mFileSize == 0) {
177        mFileBuffer = nullptr;
178    }
179    else {
180        try {
181            mFile.open(mFileName, mapped_file::priv, mFileSize, 0);
182        } catch (std::ios_base::failure e) {
183            std::cerr << "Error: Boost mmap of " << mFileName << ": " << e.what() << std::endl;
184            return;
185        }
186        mFileBuffer = mFile.data();
187    }
188    //std::cerr << "mFileSize =" << mFileSize << "\n";
189    //std::cerr << "fn_ptr =" << std::hex << reinterpret_cast<intptr_t>(fn_ptr) << "\n";
190
191    fn_ptr(mFileBuffer, mFileSize);
192
193    mFile.close();
194   
195}
196
197
198int main(int argc, char *argv[]) {
199    cl::ParseCommandLineOptions(argc, argv);
200
201    casefoldFunctionType fn_ptr = caseFoldCodeGen();
202
203    for (unsigned i = 0; i != inputFiles.size(); ++i) {
204        doCaseFold(fn_ptr, inputFiles[i]);
205    }
206
207    return 0;
208}
209
210                       
Note: See TracBrowser for help on using the repository browser.