source: icGREP/icgrep-devel/icgrep/kernels/pipeline.cpp @ 5074

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

Kernel infrastructure: move common logic into KernelBuilder? base class; demo linking in wc

File size: 6.2 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 */
5
6
7#include <toolchain.h>
8#include "pipeline.h"
9#include "utf_encoding.h"
10
11#include <kernels/scanmatchgen.h>
12#include <kernels/s2p_kernel.h>
13
14#include <pablo/function.h>
15#include <pablo/pablo_kernel.h>
16#include <pablo/pablo_toolchain.h>
17
18#include <llvm/IR/Intrinsics.h>
19#include "llvm/Support/SourceMgr.h"
20#include "llvm/IRReader/IRReader.h"
21#include "llvm/Linker/Linker.h"
22
23
24
25using namespace pablo;
26using namespace kernel;
27
28PipelineBuilder::PipelineBuilder(Module * m, IDISA::IDISA_Builder * b)
29: mMod(m)
30, iBuilder(b)
31, mBitBlockType(b->getBitBlockType())
32, mBlockSize(b->getBitBlockWidth()) {
33
34}
35
36PipelineBuilder::~PipelineBuilder() {
37}
38
39inline Value * generatePopcount(IDISA::IDISA_Builder * iBuilder, Value * bits) {
40    Value * ctpopFunc = Intrinsic::getDeclaration(iBuilder->getModule(), Intrinsic::ctpop, bits->getType());
41    return iBuilder->CreateCall(ctpopFunc, {bits});
42}
43
44inline Value * Cal_Count(Value * match_ptr, IDISA::IDISA_Builder * iBuilder) {
45    Value * matches = iBuilder->CreateLoad(match_ptr, false, "match");
46    return generatePopcount(iBuilder, matches);
47}
48
49Function * PipelineBuilder::ExecuteKernels(PabloFunction * function, bool isNameExpression, bool CountOnly, bool UTF_16) {
50   
51    s2pKernel  s2pk(iBuilder);
52    scanMatchKernel scanMatchK(iBuilder, 64, false);
53
54    s2pk.generateKernel();
55    scanMatchK.generateKernel();
56   
57    //std::unique_ptr<Module> s2pM = s2pk.createKernelModule();
58    //std::unique_ptr<Module> scanMatchM = scanMatchK.createKernelModule();
59   
60    //s2pk.addKernelDeclarations(mMod);
61    //scanMatchK.addKernelDeclarations(mMod);
62
63    pablo_function_passes(function);
64    PabloKernel  icgrepK(iBuilder, "icgrep", function, {"matchedLineCount"});
65    icgrepK.generateKernel();
66
67    //std::unique_ptr<Module> icgrepM = icgrepK.createKernelModule();
68    //icgrepK.addKernelDeclarations(mMod);
69   
70    Type * const int64ty = iBuilder->getInt64Ty();
71    Type * const int8PtrTy = iBuilder->getInt8PtrTy();
72    Type * const inputType = PointerType::get(ArrayType::get(ArrayType::get(mBitBlockType, (UTF_16 ? 16 : 8)), 1), 0);
73    Type * const resultTy = CountOnly ? int64ty : iBuilder->getVoidTy();
74    Function * const main = cast<Function>(mMod->getOrInsertFunction("Main", resultTy, inputType, int64ty, int64ty, nullptr));
75    main->setCallingConv(CallingConv::C);
76    Function::arg_iterator args = main->arg_begin();
77
78    Value * const inputStream = &*(args++);
79    inputStream->setName("input");
80    Value * const bufferSize = &*(args++);
81    bufferSize->setName("bufferSize");
82    Value * const fileIdx = &*(args++);
83    fileIdx->setName("fileIdx");
84
85    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", main,0));
86    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
87    BasicBlock * fullCondBlock = BasicBlock::Create(mMod->getContext(), "fullCond", main, 0);
88    BasicBlock * fullBodyBlock = BasicBlock::Create(mMod->getContext(), "fullBody", main, 0);
89    BasicBlock * finalBlock = BasicBlock::Create(mMod->getContext(), "final", main, 0);
90
91   
92    const unsigned segmentSize = 1;// or codegen::SegmentSize
93   
94    StreamSetBuffer ByteStream(iBuilder, StreamSetType(1, (UTF_16 ? 16 : 8)), 0);
95    StreamSetBuffer BasisBits(iBuilder, StreamSetType((UTF_16 ? 16 : 8), 1), segmentSize);
96    StreamSetBuffer MatchResults(iBuilder, StreamSetType(2, 1), segmentSize);
97   
98    ByteStream.setStreamSetBuffer(inputStream);
99    BasisBits.allocateBuffer();
100    MatchResults.allocateBuffer();
101
102    Value * initialBufferSize = bufferSize;
103    Value * initialBlockNo = iBuilder->getInt64(0);
104    BasicBlock * initialBlock = entryBlock;
105   
106    Value * s2pInstance = s2pk.createInstance({});
107    Value * icgrepInstance = icgrepK.createInstance({});
108    Value * scanMatchInstance = nullptr;
109    if (!CountOnly) {
110        scanMatchInstance = scanMatchK.createInstance({iBuilder->CreateBitCast(inputStream, int8PtrTy), bufferSize, fileIdx});
111    }
112    iBuilder->CreateBr(fullCondBlock);
113   
114    iBuilder->SetInsertPoint(fullCondBlock);
115    PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
116    remainingBytes->addIncoming(initialBufferSize, initialBlock);
117    PHINode * blockNo = iBuilder->CreatePHI(int64ty, 2, "blockNo");
118    blockNo->addIncoming(initialBlockNo, initialBlock);
119   
120    Constant * const step = ConstantInt::get(int64ty, mBlockSize * (UTF_16 ? 2 : 1));
121    Value * fullCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
122    iBuilder->CreateCondBr(fullCondTest, finalBlock, fullBodyBlock);
123
124    // Full Block Pipeline loop
125    iBuilder->SetInsertPoint(fullBodyBlock);
126   
127    Value * byteStreamPtr = ByteStream.getBlockPointer(blockNo);
128    Value * basisBitsPtr = BasisBits.getBlockPointer(blockNo);
129    Value * matchResultsPtr = MatchResults.getBlockPointer(blockNo);
130    s2pk.createDoBlockCall(s2pInstance, {byteStreamPtr, basisBitsPtr});
131    icgrepK.createDoBlockCall(icgrepInstance, {basisBitsPtr, matchResultsPtr});
132    if (!CountOnly) {
133
134        scanMatchK.createDoBlockCall(scanMatchInstance, {matchResultsPtr});
135    }
136    remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), fullBodyBlock);
137    blockNo->addIncoming(iBuilder->CreateAdd(blockNo, iBuilder->getInt64(1)), fullBodyBlock);
138    iBuilder->CreateBr(fullCondBlock);
139
140    iBuilder->SetInsertPoint(finalBlock);
141    byteStreamPtr = ByteStream.getBlockPointer(blockNo);
142    basisBitsPtr = BasisBits.getBlockPointer(blockNo);
143    matchResultsPtr = MatchResults.getBlockPointer(blockNo);
144    s2pk.createFinalBlockCall(s2pInstance, remainingBytes, {byteStreamPtr, basisBitsPtr});
145    icgrepK.createFinalBlockCall(icgrepInstance, remainingBytes, {basisBitsPtr, matchResultsPtr});
146    if (CountOnly) {
147        Value * matchCount = icgrepK.createGetAccumulatorCall(icgrepInstance, "matchedLineCount");
148        iBuilder->CreateRet(matchCount);
149    }
150    else {
151        scanMatchK.createFinalBlockCall(scanMatchInstance, remainingBytes, {matchResultsPtr});
152        iBuilder->CreateRetVoid();
153    }
154   
155    //Linker L(*mMod);
156    //L.linkInModule(std::move(s2pM));
157    //L.linkInModule(std::move(scanMatchM));
158    //L.linkInModule(std::move(icgrepM));
159
160
161    return main;
162}
Note: See TracBrowser for help on using the repository browser.