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

Last change on this file since 5025 was 5025, checked in by xuedongx, 3 years ago

If '-c', ignore the scanmatch kernel.

File size: 9.9 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#include "pipeline.h"
7#include "utf_encoding.h"
8
9#include <kernels/scanmatchgen.h>
10#include <kernels/s2p_kernel.h>
11#include <kernels/instance.h>
12
13#include <pablo/function.h>
14#include <pablo/pablo_compiler.h>
15#include <pablo/pablo_toolchain.h>
16
17#include <llvm/Support/CommandLine.h>
18#include <llvm/IR/Intrinsics.h>
19
20static cl::opt<unsigned> SegmentSize("segment-size", cl::desc("Segment Size"), cl::value_desc("positive integer"), cl::init(1));
21
22using namespace pablo;
23using namespace kernel;
24
25PipelineBuilder::PipelineBuilder(Module * m, IDISA::IDISA_Builder * b)
26: mMod(m)
27, iBuilder(b)
28, mBitBlockType(b->getBitBlockType())
29, mBlockSize(b->getBitBlockWidth()) {
30
31}
32
33PipelineBuilder::~PipelineBuilder() {
34    delete mS2PKernel;
35    delete mICgrepKernel;
36    delete mScanMatchKernel;
37}
38
39void PipelineBuilder::CreateKernels(PabloFunction * function, bool isNameExpression){
40    mS2PKernel = new KernelBuilder(iBuilder, "s2p", SegmentSize);
41    mICgrepKernel = new KernelBuilder(iBuilder, "icgrep", SegmentSize);
42    mScanMatchKernel = new KernelBuilder(iBuilder, "scanMatch", SegmentSize);
43    generateS2PKernel(mMod, iBuilder, mS2PKernel);
44    generateScanMatch(mMod, iBuilder, 64, mScanMatchKernel, isNameExpression);
45    pablo_function_passes(function);
46    PabloCompiler pablo_compiler(mMod, iBuilder);
47    try {
48        pablo_compiler.setKernel(mICgrepKernel);
49        pablo_compiler.compile(function);
50        delete function;
51        releaseSlabAllocatorMemory();
52    } catch (std::runtime_error e) {
53        delete function;
54        releaseSlabAllocatorMemory();
55        std::cerr << "Runtime error: " << e.what() << std::endl;
56        exit(1);
57    }
58}
59
60Value * generatePopcount(IDISA::IDISA_Builder * iBuilder, Value * bits) {
61    Value * ctpopFunc = Intrinsic::getDeclaration(iBuilder->getModule(), Intrinsic::ctpop, bits->getType());
62    return iBuilder->CreateCall(ctpopFunc, std::vector<Value *>({bits}));
63}
64
65Value * Cal_Count(Instance * icGrepInstance, IDISA::IDISA_Builder * iBuilder, int mBlockSize) {
66    const unsigned index = 0;
67    const unsigned streamOffset = 0;
68    Value * match = (icGrepInstance->getOutputStream(index, streamOffset));
69    Value * temp = iBuilder->CreateLoad(match);
70    Value * matches = iBuilder->CreateBitCast(temp, iBuilder->getIntNTy(mBlockSize));
71    Value * popcount = generatePopcount(iBuilder, matches);
72    return popcount;
73}
74
75Function * PipelineBuilder::ExecuteKernels(bool CountOnly) {
76    Type * const int64ty = iBuilder->getInt64Ty();
77    Type * const int8PtrTy = iBuilder->getInt8PtrTy();
78    Type * const inputType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), std::vector<Type *>({ArrayType::get(mBitBlockType, 8)})), 1), 0);
79
80    Function * const main = cast<Function>(mMod->getOrInsertFunction("Main", Type::getVoidTy(mMod->getContext()), inputType, int64ty, int64ty, iBuilder->getInt1Ty(), nullptr));
81    main->setCallingConv(CallingConv::C);
82    Function::arg_iterator args = main->arg_begin();
83
84    Value * const inputStream = &*(args++);
85    inputStream->setName("input");
86    Value * const bufferSize = &*(args++);
87    bufferSize->setName("bufferSize");
88    Value * const fileIdx = &*(args++);
89    fileIdx->setName("fileIdx");
90    Value * const finalLineUnterminated = &*(args++);
91    finalLineUnterminated->setName("finalLineUnterminated");
92
93    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", main,0));
94
95
96    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
97    BasicBlock * segmentCondBlock = nullptr;
98    BasicBlock * segmentBodyBlock = nullptr;
99    const unsigned segmentSize = SegmentSize;
100    if (segmentSize > 1) {
101        segmentCondBlock = BasicBlock::Create(mMod->getContext(), "segmentCond", main, 0);
102        segmentBodyBlock = BasicBlock::Create(mMod->getContext(), "segmentBody", main, 0);
103    }
104    BasicBlock * fullCondBlock = BasicBlock::Create(mMod->getContext(), "fullCond", main, 0);
105    BasicBlock * fullBodyBlock = BasicBlock::Create(mMod->getContext(), "fullBody", main, 0);
106    BasicBlock * finalBlock = BasicBlock::Create(mMod->getContext(), "final", main, 0);
107    BasicBlock * finalPartialBlock = BasicBlock::Create(mMod->getContext(), "partial", main, 0);
108    BasicBlock * finalEmptyBlock = BasicBlock::Create(mMod->getContext(), "empty", main, 0);
109    BasicBlock * endBlock = BasicBlock::Create(mMod->getContext(), "end", main, 0);
110    BasicBlock * unterminatedBlock = BasicBlock::Create(mMod->getContext(), "unterminated", main, 0);
111    BasicBlock * exitBlock = BasicBlock::Create(mMod->getContext(), "exit", main, 0);
112
113    Value * count = iBuilder->CreateAlloca (Type::getIntNTy(mMod->getContext(), mBlockSize), nullptr, "count");
114    Value * num = ConstantInt::get(iBuilder->getIntNTy(mBlockSize), 0);
115    iBuilder->CreateStore(num, count, false);
116
117    Instance * s2pInstance = mS2PKernel->instantiate(inputStream);
118    Instance * icGrepInstance = mICgrepKernel->instantiate(s2pInstance->getOutputStreamBuffer());
119    Instance * scanMatchInstance = mScanMatchKernel->instantiate(icGrepInstance->getOutputStreamBuffer());
120   
121    if(!CountOnly) {
122        scanMatchInstance->setInternalState("FileBuf", iBuilder->CreateBitCast(inputStream, int8PtrTy));
123        scanMatchInstance->setInternalState("FileSize", bufferSize);
124        scanMatchInstance->setInternalState("FileIdx", fileIdx);
125    }
126    Value * initialBufferSize = nullptr;
127    BasicBlock * initialBlock = nullptr;
128
129    if (segmentSize > 1) {
130        iBuilder->CreateBr(segmentCondBlock);
131        iBuilder->SetInsertPoint(segmentCondBlock);
132        PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
133        remainingBytes->addIncoming(bufferSize, entryBlock);
134        Constant * const step = ConstantInt::get(int64ty, mBlockSize * segmentSize);
135        Value * segmentCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
136        iBuilder->CreateCondBr(segmentCondTest, fullCondBlock, segmentBodyBlock);
137        iBuilder->SetInsertPoint(segmentBodyBlock);
138        for (unsigned i = 0; i < segmentSize; ++i) {
139            s2pInstance->CreateDoBlockCall();
140        }
141        for (unsigned i = 0; i < segmentSize; ++i) {
142            icGrepInstance->CreateDoBlockCall();
143            if(CountOnly){
144                Value * popcount_for = Cal_Count(icGrepInstance, iBuilder, mBlockSize);
145                Value * temp_countfor = iBuilder->CreateLoad(count);
146                Value * add_for = iBuilder->CreateAdd(temp_countfor, popcount_for);
147                iBuilder->CreateStore(add_for, count);
148            }
149        }
150        if(!CountOnly) {
151            for (unsigned i = 0; i < segmentSize; ++i) {
152                scanMatchInstance->CreateDoBlockCall();
153            }
154        }
155        remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), segmentBodyBlock);
156        iBuilder->CreateBr(segmentCondBlock);
157        initialBufferSize = remainingBytes;
158        initialBlock = segmentCondBlock;
159    } else {
160        initialBufferSize = bufferSize;
161        initialBlock = entryBlock;
162        iBuilder->CreateBr(fullCondBlock);
163    }
164
165    iBuilder->SetInsertPoint(fullCondBlock);
166    PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
167    remainingBytes->addIncoming(initialBufferSize, initialBlock);
168
169    Constant * const step = ConstantInt::get(int64ty, mBlockSize);
170    Value * fullCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
171    iBuilder->CreateCondBr(fullCondTest, finalBlock, fullBodyBlock);
172
173    iBuilder->SetInsertPoint(fullBodyBlock);
174    s2pInstance->CreateDoBlockCall();
175    icGrepInstance->CreateDoBlockCall();
176    if(CountOnly){
177        Value * popcount = Cal_Count(icGrepInstance, iBuilder, mBlockSize);   
178        Value * temp_count = iBuilder->CreateLoad(count);
179        Value * add = iBuilder->CreateAdd(temp_count, popcount);
180        iBuilder->CreateStore(add, count);
181    }
182
183    if(!CountOnly) {
184        scanMatchInstance->CreateDoBlockCall();
185    }
186
187    remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), fullBodyBlock);
188    iBuilder->CreateBr(fullCondBlock);
189
190    iBuilder->SetInsertPoint(finalBlock);
191    Value * const b4 = s2pInstance->getOutputStream(4);
192    Value * const b6 = s2pInstance->getOutputStream(6);
193    Value * emptyBlockCond = iBuilder->CreateICmpEQ(remainingBytes, ConstantInt::get(int64ty, 0));
194    iBuilder->CreateCondBr(emptyBlockCond, finalEmptyBlock, finalPartialBlock);
195
196
197    iBuilder->SetInsertPoint(finalPartialBlock);
198    s2pInstance->CreateDoBlockCall();
199    iBuilder->CreateBr(endBlock);
200
201    iBuilder->SetInsertPoint(finalEmptyBlock);
202    s2pInstance->clearOutputStreamSet();
203    iBuilder->CreateBr(endBlock);
204
205    iBuilder->SetInsertPoint(endBlock);
206    Value * isFinalLineUnterminated = iBuilder->CreateICmpEQ(finalLineUnterminated, ConstantInt::getNullValue(finalLineUnterminated->getType()));
207    iBuilder->CreateCondBr(isFinalLineUnterminated, exitBlock, unterminatedBlock);
208   
209    iBuilder->SetInsertPoint(unterminatedBlock);
210
211    Value * remaining = iBuilder->CreateZExt(remainingBytes, iBuilder->getIntNTy(mBlockSize));
212    Value * EOF_pos = iBuilder->CreateShl(ConstantInt::get(iBuilder->getIntNTy(mBlockSize), 1), remaining);
213    EOF_pos = iBuilder->CreateBitCast(EOF_pos, mBitBlockType);
214
215
216    Value * b4val = iBuilder->CreateBlockAlignedLoad(b4);
217    b4val = iBuilder->CreateOr(b4val, EOF_pos);
218    iBuilder->CreateBlockAlignedStore(b4val, b4);
219
220    Value * b6val = iBuilder->CreateBlockAlignedLoad(b6);
221    b6val = iBuilder->CreateOr(b6val, EOF_pos);
222    iBuilder->CreateBlockAlignedStore(b6val, b6);
223
224    iBuilder->CreateBr(exitBlock);
225
226    iBuilder->SetInsertPoint(exitBlock);
227
228    icGrepInstance->CreateDoBlockCall();
229    if(CountOnly){
230        Value * popcount1 = Cal_Count(icGrepInstance, iBuilder, mBlockSize);   
231        Value * temp_count1 = iBuilder->CreateLoad(count);
232        Value * add1 = iBuilder->CreateAdd(temp_count1, popcount1);
233        iBuilder->CreateStore(add1, count);
234    }
235    if(!CountOnly) {
236        scanMatchInstance->CreateDoBlockCall();
237    }
238    if(CountOnly){
239        Value * Ret = iBuilder->CreateLoad(count);
240        iBuilder->CreateRet(Ret);
241    }
242    else{
243        iBuilder->CreateRetVoid();
244    }
245
246
247    return main;
248}
Note: See TracBrowser for help on using the repository browser.