source: icGREP/icgrep-devel/icgrep/editd/editd.cpp @ 5401

Last change on this file since 5401 was 5401, checked in by nmedfort, 2 years ago

Updated all projects to use ParabixDriver?. Deprecated original pipeline generation methods. Enabled LLVM optimizations, IR and ASM printing for Kernel modules. Enabled object cache by default. Begun work on moving consumed position information back to producing kernels.

  • Property svn:executable set to *
File size: 25.8 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 <toolchain.h>
11#include <pablo/pablo_toolchain.h>
12#include <llvm/IR/Function.h>
13#include <llvm/IR/Module.h>
14#include <llvm/ExecutionEngine/ExecutionEngine.h>
15#include "llvm/Linker/Linker.h"
16#include <llvm/Support/CommandLine.h>
17#include <cc/cc_compiler.h>
18#include <pablo/pablo_compiler.h>
19#include <pablo/pablo_kernel.h>
20#include <IR_Gen/idisa_builder.h>
21#include <IR_Gen/idisa_target.h>
22#include <kernels/streamset.h>
23#include <kernels/mmap_kernel.h>
24#include <kernels/s2p_kernel.h>
25#include <editd/editdscan_kernel.h>
26#include <kernels/pipeline.h>
27#include <editd/pattern_compiler.h>
28#include <boost/filesystem.hpp>
29#include <boost/iostreams/device/mapped_file.hpp>
30#include <mutex>
31#ifdef CUDA_ENABLED
32#include <editd/EditdCudaDriver.h>
33#include <editd/editd_gpu_kernel.h>
34#endif
35
36using namespace llvm;
37
38static cl::list<std::string> inputFiles(cl::Positional, cl::desc("<regex> <input file ...>"), cl::OneOrMore);
39
40static cl::list<std::string> pattVector("e", cl::desc("pattern"), cl::ZeroOrMore);
41static cl::opt<std::string> PatternFilename("f", cl::desc("Take patterns (one per line) from a file"), cl::value_desc("regex file"), cl::init(""));
42
43static cl::opt<bool> CaseInsensitive("i", cl::desc("Ignore case distinctions in the pattern and the file."));
44
45static cl::opt<int> editDistance("edit-dist", cl::desc("Edit Distance Value"), cl::init(2));
46static cl::opt<int> optPosition("opt-pos", cl::desc("Optimize position"), cl::init(8));
47static cl::opt<int> stepSize("step-size", cl::desc("Step Size"), cl::init(3));
48static cl::opt<int> prefixLen("prefix", cl::desc("Prefix length"), cl::init(4));
49static cl::opt<bool> ShowPositions("display", cl::desc("Display the match positions."), cl::init(false));
50
51static cl::opt<int> Threads("threads", cl::desc("Total number of threads."), cl::init(1));
52
53using namespace kernel;
54using namespace pablo;
55using namespace parabix;
56
57const static std::string IRFilename = "editd.ll";
58const static std::string PTXFilename = "editd.ptx";
59
60struct matchPosition
61{
62    size_t pos;
63    size_t dist;
64};
65
66std::vector<struct matchPosition> matchList;
67std::vector<std::vector<std::string>> pattGroups;
68
69void run_second_filter(int total_len, int pattern_segs, float errRate){
70   
71    if(matchList.empty()) return;
72
73    //remove the duplicates
74    bool cleared = true;
75    while(cleared){
76        cleared = false;
77        for (unsigned i=0; i<matchList.size()-1; i++){
78            if(matchList[i].pos == matchList[i+1].pos && matchList[i].dist == matchList[i+1].dist){
79                matchList.erase(matchList.begin() + i);
80                cleared = true;
81            }
82        }
83    }
84
85    //Sort match position
86    bool exchanged = true;
87    while(exchanged){
88        exchanged = false;
89        for (unsigned i=0; i<matchList.size()-1; i++){
90            if(matchList[i].pos > matchList[i+1].pos){
91                size_t tmp_pos = matchList[i].pos;
92                size_t tmp_dist = matchList[i].dist;
93                matchList[i].pos = matchList[i+1].pos;
94                matchList[i].dist = matchList[i+1].dist;
95                matchList[i+1].pos = tmp_pos;
96                matchList[i+1].dist = tmp_dist;
97                exchanged = true;
98            }
99        }
100    }
101
102    std::cout << "pattern_segs = " << pattern_segs << ", total_len = " << total_len << std::endl;
103
104    int v = pattern_segs * (editDistance+1) - total_len * errRate;
105
106    int startPos = matchList[0].pos;
107    int sum = matchList[0].dist;
108    int curIdx = 0;
109    unsigned i = 0;
110    int count = 0;
111    while (i < matchList.size()){
112        if(matchList[i].pos - startPos < total_len * (errRate+1)){
113            sum += matchList[i].dist;
114            i++;
115        }
116        else{
117            if(sum > v) count++;
118            sum -= matchList[curIdx].dist;
119            curIdx++;
120            startPos = matchList[curIdx].pos;
121        }
122    }
123
124    std::cout << "total candidate from the first filter is " << matchList.size() << std::endl;
125    std::cout << "total candidate from the second filter is " << count << std::endl;
126}
127
128extern "C" {
129std::mutex store_mutex;
130void wrapped_report_pos(size_t match_pos, int dist) {
131        struct matchPosition curMatch;
132        curMatch.pos = match_pos;
133        curMatch.dist = dist;
134
135        store_mutex.lock();
136        matchList.push_back(curMatch);
137        if(ShowPositions)
138            std::cout << "pos: " << match_pos << ", dist:" << dist << "\n";
139        store_mutex.unlock();
140    }
141
142}
143
144void icgrep_Linking(Module * m, ExecutionEngine * e) {
145    Module::FunctionListType & fns = m->getFunctionList();
146    for (Module::FunctionListType::iterator it = fns.begin(), it_end = fns.end(); it != it_end; ++it) {
147        std::string fnName = it->getName().str();
148        if (fnName == "wrapped_report_pos") {
149            e->addGlobalMapping(cast<GlobalValue>(it), (void *)&wrapped_report_pos);
150        }
151    }
152}
153
154void get_editd_pattern(int & pattern_segs, int & total_len) {
155 
156    if (PatternFilename != "") {
157        std::ifstream pattFile(PatternFilename.c_str());
158        std::string r;
159        if (pattFile.is_open()) {
160            while (std::getline(pattFile, r)) {
161                pattVector.push_back(r);
162                pattern_segs ++; 
163                total_len += r.size(); 
164            }
165            std::sort(pattVector.begin(), pattVector.end());
166            unsigned i = 0;
167            while(i < pattVector.size()){
168                std::vector<std::string> pattGroup;
169                std::string prefix = pattVector[i].substr(0, prefixLen);
170                while(i < pattVector.size() && pattVector[i].substr(0, prefixLen) == prefix){
171                    pattGroup.push_back(pattVector[i]);
172                    i++;
173                } 
174                pattGroups.push_back(pattGroup);
175            }
176            pattFile.close();
177        }
178    }
179   
180    // if there are no regexes specified through -e or -f, the first positional argument
181    // must be a regex, not an input file.
182   
183    if (pattVector.size() == 0) {
184        pattVector.push_back(inputFiles[0]);
185        inputFiles.erase(inputFiles.begin());
186    }
187}
188
189void buildPatternKernel(PabloKernel & kernel, IDISA::IDISA_Builder * iBuilder, const std::vector<std::string> & patterns) {
190    PabloBuilder entry(kernel.getEntryBlock());
191
192    Var * pat = kernel.getInputStreamVar("pat");
193
194    PabloAST * basisBits[4];
195
196    basisBits[0] = entry.createExtract(pat, 0, "A");
197    basisBits[1] = entry.createExtract(pat, 1, "C");
198    basisBits[2] = entry.createExtract(pat, 2, "T");
199    basisBits[3] = entry.createExtract(pat, 3, "G");
200
201    re::Pattern_Compiler pattern_compiler(kernel);
202    pattern_compiler.compile(patterns, entry, basisBits, editDistance, optPosition, stepSize);
203
204    pablo_function_passes(&kernel);
205}
206
207
208void editdPipeline(ParabixDriver & pxDriver, const std::vector<std::string> & patterns) {
209   
210    IDISA::IDISA_Builder * const iBuilder = pxDriver.getIDISA_Builder();
211    Module * const m = iBuilder->getModule();
212    Type * const sizeTy = iBuilder->getSizeTy();
213    Type * const voidTy = iBuilder->getVoidTy();
214    Type * const inputType = PointerType::get(ArrayType::get(ArrayType::get(iBuilder->getBitBlockType(), 8), 1), 0);
215   
216    Function * const main = cast<Function>(m->getOrInsertFunction("Main", voidTy, inputType, sizeTy, nullptr));
217    main->setCallingConv(CallingConv::C);
218    auto args = main->arg_begin();
219    Value * const inputStream = &*(args++);
220    inputStream->setName("input");
221    Value * const fileSize = &*(args++);
222    fileSize->setName("fileSize");
223    iBuilder->SetInsertPoint(BasicBlock::Create(m->getContext(), "entry", main,0));
224
225
226    ExternalFileBuffer ChStream(iBuilder, iBuilder->getStreamSetTy(4));
227    SingleBlockBuffer MatchResults(iBuilder, iBuilder->getStreamSetTy(editDistance + 1));
228
229    MMapSourceKernel mmapK(iBuilder);
230    mmapK.setInitialArguments({fileSize});
231    pxDriver.addKernelCall(mmapK, {}, {&ChStream});
232
233    PabloKernel editdk(iBuilder, "editd",
234                        {Binding{iBuilder->getStreamSetTy(4), "pat"}},
235                        {Binding{iBuilder->getStreamSetTy(editDistance + 1), "E"}});
236
237    ChStream.setStreamSetBuffer(inputStream);
238    MatchResults.allocateBuffer();
239
240    buildPatternKernel(editdk, iBuilder, patterns);
241    pxDriver.addKernelCall(editdk, {&ChStream}, {&MatchResults});
242
243    kernel::editdScanKernel editdScanK(iBuilder, editDistance);
244    pxDriver.addKernelCall(editdScanK, {&MatchResults}, {});
245       
246    pxDriver.generatePipelineIR();
247
248    iBuilder->CreateRetVoid();
249
250    pxDriver.linkAndFinalize();
251}
252
253void buildPreprocessKernel(PabloKernel & kernel, IDISA::IDISA_Builder * iBuilder) {
254    cc::CC_Compiler ccc(&kernel, kernel.getInputStreamVar("basis"));
255
256    PabloBuilder & pb = ccc.getBuilder();
257
258    PabloAST * A = ccc.compileCC(re::makeCC(re::makeCC(0x41), re::makeCC(0x61)), pb);
259    PabloAST * C = ccc.compileCC(re::makeCC(re::makeCC(0x43), re::makeCC(0x63)), pb);
260    PabloAST * T = ccc.compileCC(re::makeCC(re::makeCC(0x54), re::makeCC(0x74)), pb);
261    PabloAST * G = ccc.compileCC(re::makeCC(re::makeCC(0x47), re::makeCC(0x67)), pb);
262
263    Var * const pat = kernel.getOutputStreamVar("pat");
264
265    pb.createAssign(pb.createExtract(pat, 0), A);
266    pb.createAssign(pb.createExtract(pat, 1), C);
267    pb.createAssign(pb.createExtract(pat, 2), T);
268    pb.createAssign(pb.createExtract(pat, 3), G);
269
270    pablo_function_passes(&kernel);
271}
272
273void preprocessPipeline(ParabixDriver & pxDriver) {
274
275    IDISA::IDISA_Builder * iBuilder = pxDriver.getIDISA_Builder();
276    Module * m = iBuilder->getModule();
277    Type * mBitBlockType = iBuilder->getBitBlockType();
278   
279    Type * const size_ty = iBuilder->getSizeTy();
280    Type * const voidTy = iBuilder->getVoidTy();
281    Type * const inputType = PointerType::get(ArrayType::get(ArrayType::get(mBitBlockType, 8), 1), 0);
282    Type * const outputType = PointerType::get(ArrayType::get(mBitBlockType, 4), 0);
283   
284    Function * const main = cast<Function>(m->getOrInsertFunction("Main", voidTy, inputType, size_ty, outputType, nullptr));
285    main->setCallingConv(CallingConv::C);
286    Function::arg_iterator args = main->arg_begin();
287   
288    Value * const inputStream = &*(args++);
289    inputStream->setName("input");
290    Value * const fileSize = &*(args++);
291    fileSize->setName("fileSize");
292    Value * const outputStream = &*(args++);
293    outputStream->setName("output");
294    iBuilder->SetInsertPoint(BasicBlock::Create(m->getContext(), "entry", main));
295
296    ExternalFileBuffer ByteStream(iBuilder, iBuilder->getStreamSetTy(1, 8));
297    SingleBlockBuffer BasisBits(iBuilder, iBuilder->getStreamSetTy(8));
298    ExternalFileBuffer CCResults(iBuilder, iBuilder->getStreamSetTy(4));
299
300    MMapSourceKernel mmapK(iBuilder);
301    mmapK.setInitialArguments({fileSize});
302    pxDriver.addKernelCall(mmapK, {}, {&ByteStream});
303   
304    S2PKernel s2pk(iBuilder);
305    pxDriver.addKernelCall(s2pk, {&ByteStream}, {&BasisBits});
306
307    PabloKernel ccck(iBuilder, "ccc",
308                {{iBuilder->getStreamSetTy(8), "basis"}},
309                {{iBuilder->getStreamSetTy(4), "pat"}});
310
311    buildPreprocessKernel(ccck, iBuilder);
312    pxDriver.addKernelCall(ccck, {&BasisBits}, {&CCResults});
313         
314    ByteStream.setStreamSetBuffer(inputStream);
315
316    BasisBits.allocateBuffer();
317
318    CCResults.setStreamSetBuffer(outputStream);
319   
320    pxDriver.generatePipelineIR();
321
322    iBuilder->CreateRetVoid();
323
324    pxDriver.linkAndFinalize();
325}
326
327
328typedef void (*preprocessFunctionType)(char * byte_data, size_t filesize, char * output_data);
329
330preprocessFunctionType preprocessCodeGen() {                           
331    LLVMContext TheContext;
332    Module * M = new Module("preprocess", TheContext);
333    IDISA::IDISA_Builder * idb = IDISA::GetIDISA_Builder(M);
334    ParabixDriver pxDriver(idb);
335    preprocessPipeline(pxDriver);
336    auto f = reinterpret_cast<preprocessFunctionType>(pxDriver.getPointerToMain());
337    delete idb;
338    return f;
339}
340
341typedef void (*editdFunctionType)(char * byte_data, size_t filesize);
342
343editdFunctionType editdCodeGen(const std::vector<std::string> & patterns) {                           
344    LLVMContext TheContext;
345    Module * M = new Module("editd", TheContext);
346    IDISA::IDISA_Builder * const idb = IDISA::GetIDISA_Builder(M);
347    ParabixDriver pxDriver(idb);
348    editdPipeline(pxDriver, patterns);
349    auto f = reinterpret_cast<editdFunctionType>(pxDriver.getPointerToMain());
350    delete idb;
351    return f;
352}
353
354char * chStream;
355int size;
356
357char * preprocess(preprocessFunctionType fn_ptr) {
358    std::string fileName = inputFiles[0];
359    size_t fileSize;
360    char * fileBuffer;
361   
362    const boost::filesystem::path file(fileName);
363    if (exists(file)) {
364        if (is_directory(file)) {
365            exit(0);
366        }
367    } else {
368        std::cerr << "Error: cannot open " << fileName << " for processing. Skipped.\n";
369        exit(0);
370    }
371   
372    fileSize = file_size(file);
373    boost::iostreams::mapped_file_source mappedFile;
374    if (fileSize == 0) {
375        fileBuffer = nullptr;
376    }
377    else {
378        try {
379            mappedFile.open(fileName);
380        } catch (std::exception &e) {
381            std::cerr << "Error: Boost mmap of " << fileName << ": " << e.what() << std::endl;
382            exit(0);
383        }
384        fileBuffer = const_cast<char *>(mappedFile.data());
385    }
386
387    int ret = posix_memalign((void**)&chStream, 32, fileSize);
388    if (ret) {
389        std::cerr << "Cannot allocate memory for output.\n";
390        exit(-1);
391    }
392
393    fn_ptr(fileBuffer, fileSize, chStream);
394    size = fileSize;
395
396    mappedFile.close();
397
398    return chStream;   
399}
400
401void editd(editdFunctionType fn_ptr, char * inputStream, int size) {
402 
403    if (size == 0) {
404        inputStream = nullptr;
405    }
406
407    fn_ptr(inputStream, size);
408   
409}
410
411std::mutex count_mutex;
412size_t groupCount;
413void *DoEditd(void *threadid)
414{
415    size_t groupIdx;
416    count_mutex.lock();
417    groupIdx = groupCount;
418    groupCount++;
419    count_mutex.unlock();
420
421    while (groupIdx < pattGroups.size()){
422        editdFunctionType editd_ptr = editdCodeGen(pattGroups[groupIdx]);
423        editd(editd_ptr, chStream, size);
424
425        count_mutex.lock();
426        groupIdx = groupCount;
427        groupCount++;
428        count_mutex.unlock();
429    }
430
431    pthread_exit(NULL);
432}
433
434#ifdef CUDA_ENABLED
435
436#define GROUPTHREADS 64
437#define GROUPBLOCKS 64
438
439void editdGPUCodeGen(unsigned patternLen){ 
440    LLVMContext TheContext;
441    Module * M = new Module("editd-gpu", TheContext);
442    IDISA::IDISA_Builder * iBuilder = IDISA::GetIDISA_GPU_Builder(M);
443    M->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64");
444    M->setTargetTriple("nvptx64-nvidia-cuda");
445    unsigned addrSpace = 1;
446
447    Type * const mBitBlockType = iBuilder->getBitBlockType();
448    Type * const inputSizeTy = PointerType::get(iBuilder->getSizeTy(), 1);
449    Type * const int32ty = iBuilder->getInt32Ty();
450    Type * const voidTy = Type::getVoidTy(M->getContext());
451    Type * const inputTy = PointerType::get(ArrayType::get(mBitBlockType, 4), 1);
452    Type * const patternPtrTy = PointerType::get(iBuilder->getInt8Ty(), 1);
453    Type * const outputTy = PointerType::get(ArrayType::get(mBitBlockType, editDistance+1), 1);
454    Type * const stridesTy = PointerType::get(int32ty, 1);
455
456    ExternalFileBuffer CCStream(iBuilder, iBuilder->getStreamSetTy(4), addrSpace);
457    ExternalFileBuffer ResultStream(iBuilder, iBuilder->getStreamSetTy( editDistance+1, 1), addrSpace);
458
459    MMapSourceKernel mmapK(iBuilder);
460    mmapK.generateKernel({}, {&CCStream});
461
462    kernel::editdGPUKernel editdk(iBuilder, editDistance, patternLen); 
463    editdk.generateKernel({&CCStream}, {&ResultStream});
464
465    Function * const main = cast<Function>(M->getOrInsertFunction("GPU_Main", voidTy, inputTy, inputSizeTy, patternPtrTy, outputTy, stridesTy, nullptr));
466    main->setCallingConv(CallingConv::C);
467    Function::arg_iterator args = main->arg_begin();
468   
469    Value * const inputStream = &*(args++);
470    inputStream->setName("input");
471    Value * const inputSizePtr = &*(args++);
472    inputSizePtr->setName("inputSizePtr");
473    Value * const pattStream = &*(args++);
474    pattStream->setName("pattStream");
475    Value * const resultStream = &*(args++);
476    resultStream->setName("resultStream");
477    Value * const stridesPtr = &*(args++);
478    stridesPtr->setName("stridesPtr");
479   
480    iBuilder->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", main,0));
481
482    Function * tidFunc = M->getFunction("llvm.nvvm.read.ptx.sreg.tid.x");
483    Value * tid = iBuilder->CreateCall(tidFunc);
484    Value * inputThreadPtr = iBuilder->CreateGEP(inputStream, tid);
485
486    Function * bidFunc = cast<Function>(M->getOrInsertFunction("llvm.nvvm.read.ptx.sreg.ctaid.x", int32ty, nullptr));
487    Value * bid = iBuilder->CreateCall(bidFunc);
488    Value * strides = iBuilder->CreateLoad(stridesPtr);
489    Value * outputBlocks = iBuilder->CreateMul(strides, ConstantInt::get(int32ty, GROUPTHREADS));
490    Value * resultStreamPtr = iBuilder->CreateGEP(resultStream, iBuilder->CreateAdd(iBuilder->CreateMul(bid, outputBlocks), tid));
491
492    Value * inputSize = iBuilder->CreateLoad(inputSizePtr);
493    CCStream.setStreamSetBuffer(inputThreadPtr);
494    ResultStream.setStreamSetBuffer(resultStreamPtr);
495    mmapK.setInitialArguments({inputSize});
496
497    const unsigned numOfCarries = patternLen * (editDistance + 1) * 4;
498    Type * strideCarryTy = ArrayType::get(mBitBlockType, numOfCarries);
499    Value * strideCarry = iBuilder->CreateAlloca(strideCarryTy);
500    iBuilder->CreateStore(Constant::getNullValue(strideCarryTy), strideCarry);
501
502    editdk.setInitialArguments({pattStream, strideCarry});
503   
504    generatePipelineLoop(iBuilder, {&mmapK, &editdk});
505       
506    iBuilder->CreateRetVoid();
507   
508    MDNode * Node = MDNode::get(M->getContext(),
509                                {llvm::ValueAsMetadata::get(main),
510                                 MDString::get(M->getContext(), "kernel"), 
511                                 ConstantAsMetadata::get(ConstantInt::get(iBuilder->getInt32Ty(), 1))});
512    NamedMDNode *NMD = M->getOrInsertNamedMetadata("nvvm.annotations");
513    NMD->addOperand(Node);
514
515    Compile2PTX(M, IRFilename, PTXFilename);
516
517}
518
519void mergeGPUCodeGen(){
520        LLVMContext TheContext;
521    Module * M = new Module("editd-gpu", TheContext);
522    IDISA::IDISA_Builder * iBuilder = IDISA::GetIDISA_GPU_Builder(M);
523    M->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64");
524    M->setTargetTriple("nvptx64-nvidia-cuda");
525
526    Type * const mBitBlockType = iBuilder->getBitBlockType();
527    Type * const int32ty = iBuilder->getInt32Ty();
528    Type * const voidTy = Type::getVoidTy(M->getContext());
529    Type * const resultTy = PointerType::get(ArrayType::get(mBitBlockType, editDistance+1), 1);
530    Type * const stridesTy = PointerType::get(int32ty, 1);
531
532    Function * const main = cast<Function>(M->getOrInsertFunction("mergeResult", voidTy, resultTy, stridesTy, nullptr));
533    main->setCallingConv(CallingConv::C);
534    Function::arg_iterator args = main->arg_begin();
535   
536    Value * const resultStream = &*(args++);
537    resultStream->setName("resultStream");
538    Value * const stridesPtr = &*(args++);
539    stridesPtr->setName("stridesPtr");
540
541    BasicBlock * entryBlock = BasicBlock::Create(iBuilder->getContext(), "entryBlock", main, 0);
542    BasicBlock * strideLoopCond = BasicBlock::Create(iBuilder->getContext(), "strideLoopCond", main, 0);
543    BasicBlock * strideLoopBody = BasicBlock::Create(iBuilder->getContext(), "strideLoopBody", main, 0);
544    BasicBlock * stridesDone = BasicBlock::Create(iBuilder->getContext(), "stridesDone", main, 0);
545   
546    iBuilder->SetInsertPoint(entryBlock);
547
548    Function * tidFunc = M->getFunction("llvm.nvvm.read.ptx.sreg.tid.x");
549    Value * tid = iBuilder->CreateCall(tidFunc);
550
551    Function * bidFunc = cast<Function>(M->getOrInsertFunction("llvm.nvvm.read.ptx.sreg.ctaid.x", int32ty, nullptr));
552    Value * bid = iBuilder->CreateCall(bidFunc);
553    Value * strides = iBuilder->CreateLoad(stridesPtr);
554    Value * strideBlocks = ConstantInt::get(int32ty, iBuilder->getStride() / iBuilder->getBitBlockWidth());
555    Value * outputBlocks = iBuilder->CreateMul(strides, strideBlocks);
556    Value * resultStreamPtr = iBuilder->CreateGEP(resultStream, tid);
557
558    iBuilder->CreateBr(strideLoopCond);
559    iBuilder->SetInsertPoint(strideLoopCond);
560    PHINode * strideNo = iBuilder->CreatePHI(int32ty, 2, "strideNo");
561    strideNo->addIncoming(ConstantInt::get(int32ty, 0), entryBlock);
562    Value * notDone = iBuilder->CreateICmpULT(strideNo, strides);
563    iBuilder->CreateCondBr(notDone, strideLoopBody, stridesDone);
564 
565    iBuilder->SetInsertPoint(strideLoopBody);
566    Value * myResultStreamPtr = iBuilder->CreateGEP(resultStreamPtr, {iBuilder->CreateMul(strideBlocks, strideNo)});
567    Value * myResultStream = iBuilder->CreateLoad(iBuilder->CreateGEP(myResultStreamPtr, {iBuilder->getInt32(0), bid}));
568    for (unsigned i=1; i<GROUPBLOCKS; i++){
569        Value * nextStreamPtr = iBuilder->CreateGEP(myResultStreamPtr, {iBuilder->CreateMul(outputBlocks, iBuilder->getInt32(i)), bid});
570        myResultStream = iBuilder->CreateOr(myResultStream, iBuilder->CreateLoad(nextStreamPtr));
571    }   
572    iBuilder->CreateStore(myResultStream, iBuilder->CreateGEP(myResultStreamPtr, {iBuilder->getInt32(0), bid}));
573    strideNo->addIncoming(iBuilder->CreateAdd(strideNo, ConstantInt::get(int32ty, 1)), strideLoopBody);
574    iBuilder->CreateBr(strideLoopCond);
575   
576    iBuilder->SetInsertPoint(stridesDone);
577    iBuilder->CreateRetVoid();
578   
579    MDNode * Node = MDNode::get(M->getContext(),
580                                {llvm::ValueAsMetadata::get(main),
581                                 MDString::get(M->getContext(), "kernel"), 
582                                 ConstantAsMetadata::get(ConstantInt::get(iBuilder->getInt32Ty(), 1))});
583    NamedMDNode *NMD = M->getOrInsertNamedMetadata("nvvm.annotations");
584    NMD->addOperand(Node);
585
586    Compile2PTX(M, "merge.ll", "merge.ptx");
587
588}
589
590editdFunctionType editdScanCPUCodeGen() {
591                           
592    LLVMContext TheContext;
593    Module * M = new Module("editd", TheContext);
594    IDISA::IDISA_Builder * iBuilder = IDISA::GetIDISA_Builder(M);
595    ExecutionEngine * editdEngine = nullptr;
596
597    Type * mBitBlockType = iBuilder->getBitBlockType();
598    Type * const size_ty = iBuilder->getSizeTy();
599    Type * const voidTy = Type::getVoidTy(M->getContext());
600    Type * const inputType = PointerType::get(ArrayType::get(mBitBlockType, editDistance+1), 0);
601
602    ExternalFileBuffer MatchResults(iBuilder, iBuilder->getStreamSetTy( editDistance+1, 1));
603
604    MMapSourceKernel mmapK(iBuilder);
605    mmapK.generateKernel({}, {&MatchResults});
606
607    kernel::editdScanKernel editdScanK(iBuilder, editDistance);
608    editdScanK.generateKernel({&MatchResults}, {});               
609   
610    Function * const main = cast<Function>(M->getOrInsertFunction("CPU_Main", voidTy, inputType, size_ty, nullptr));
611    main->setCallingConv(CallingConv::C);
612    Function::arg_iterator args = main->arg_begin();
613   
614    Value * const inputStream = &*(args++);
615    inputStream->setName("input");
616    Value * const fileSize = &*(args++);
617    fileSize->setName("fileSize");
618   
619    iBuilder->SetInsertPoint(BasicBlock::Create(M->getContext(), "entry", main,0));
620
621    MatchResults.setStreamSetBuffer(inputStream);
622    mmapK.setInitialArguments({fileSize});
623   
624    generatePipelineLoop(iBuilder, {&mmapK, &editdScanK});
625       
626    iBuilder->CreateRetVoid();
627
628    editdEngine = JIT_to_ExecutionEngine(M);
629   
630    editdEngine->finalizeObject();
631
632    return reinterpret_cast<editdFunctionType>(editdEngine->getPointerToFunction(main));
633}
634
635#endif
636
637int main(int argc, char *argv[]) {
638
639    cl::ParseCommandLineOptions(argc, argv);
640
641    int pattern_segs = 0;
642    int total_len = 0;
643
644    get_editd_pattern(pattern_segs, total_len);
645
646#ifdef CUDA_ENABLED
647    codegen::BlockSize = 64;
648#endif
649
650    preprocessFunctionType preprocess_ptr = preprocessCodeGen();
651    preprocess(preprocess_ptr);
652
653#ifdef CUDA_ENABLED 
654    setNVPTXOption();   
655    if(codegen::NVPTX){
656
657        std::ifstream t(PatternFilename);
658        if (!t.is_open()) {
659            std::cerr << "Error: cannot open " << PatternFilename << " for processing. Skipped.\n";
660            exit(-1);
661        } 
662        std::string patterns((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
663
664        editdGPUCodeGen(patterns.length()/GROUPTHREADS - 1);
665
666        mergeGPUCodeGen();
667
668        ulong * rslt = RunPTX(PTXFilename, chStream, size, patterns.c_str(), patterns.length(), editDistance);
669
670        editdFunctionType editd_ptr = editdScanCPUCodeGen();
671
672        editd(editd_ptr, (char*)rslt, size);
673       
674        run_second_filter(pattern_segs, total_len, 0.15);
675
676        return 0;
677    }
678#endif
679   
680    if(pattVector.size() == 1){
681        editdFunctionType editd_ptr = editdCodeGen(pattVector);
682        editd(editd_ptr, chStream, size);
683    }
684    else{
685        if (Threads == 1) {
686            for(unsigned i=0; i<pattGroups.size(); i++){
687                editdFunctionType editd_ptr = editdCodeGen(pattGroups[i]);
688                editd(editd_ptr, chStream, size);
689            }
690        }
691        else{
692            const unsigned numOfThreads = Threads;
693            pthread_t threads[numOfThreads];
694            groupCount = 0;
695
696            for(unsigned long i = 0; i < numOfThreads; ++i){
697                const int rc = pthread_create(&threads[i], NULL, DoEditd, (void *)i);
698                if (rc) {
699                    llvm::report_fatal_error("Failed to create thread: code " + std::to_string(rc));
700                }
701            }
702
703            for(unsigned i = 0; i < numOfThreads; ++i) {
704                void * status = nullptr;
705                const int rc = pthread_join(threads[i], &status);
706                if (rc) {
707                    llvm::report_fatal_error("Failed to join thread: code " + std::to_string(rc));
708                }
709            }
710
711        }
712        run_second_filter(pattern_segs, total_len, 0.15);
713    }
714
715    return 0;
716}
Note: See TracBrowser for help on using the repository browser.