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

Last change on this file since 4986 was 4986, checked in by nmedfort, 3 years ago

First attempt at dynamic segment size intergration.

File size: 8.1 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
19static cl::opt<unsigned> SegmentSize("segment-size", cl::desc("Segment Size"), cl::value_desc("positive integer"), cl::init(1));
20
21using namespace pablo;
22using namespace kernel;
23
24PipelineBuilder::PipelineBuilder(Module * m, IDISA::IDISA_Builder * b)
25: mMod(m)
26, iBuilder(b)
27, mBitBlockType(b->getBitBlockType())
28, mBlockSize(b->getBitBlockWidth()) {
29
30}
31
32PipelineBuilder::~PipelineBuilder() {
33    delete mS2PKernel;
34    delete mICgrepKernel;
35    delete mScanMatchKernel;
36}
37
38void PipelineBuilder::CreateKernels(PabloFunction * function, bool isNameExpression){
39    mS2PKernel = new KernelBuilder("s2p", mMod, iBuilder, SegmentSize);
40    mICgrepKernel = new KernelBuilder("icgrep", mMod, iBuilder, SegmentSize);
41    mScanMatchKernel = new KernelBuilder("scanMatch", mMod, iBuilder, SegmentSize);
42    generateS2PKernel(mMod, iBuilder, mS2PKernel);
43    generateScanMatch(mMod, iBuilder, 64, mScanMatchKernel, isNameExpression);
44    pablo_function_passes(function);
45    PabloCompiler pablo_compiler(mMod, iBuilder);
46    try {
47        pablo_compiler.setKernel(mICgrepKernel);
48        pablo_compiler.compile(function);
49        delete function;
50        releaseSlabAllocatorMemory();
51    } catch (std::runtime_error e) {
52        delete function;
53        releaseSlabAllocatorMemory();
54        std::cerr << "Runtime error: " << e.what() << std::endl;
55        exit(1);
56    }
57}
58
59Function * PipelineBuilder::ExecuteKernels() {
60    Type * const int64ty = iBuilder->getInt64Ty();
61    Type * const int8PtrTy = iBuilder->getInt8PtrTy();
62    Type * const inputType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), std::vector<Type *>({ArrayType::get(mBitBlockType, 8)})), 1), 0);
63
64    Function * const main = cast<Function>(mMod->getOrInsertFunction("Main", Type::getVoidTy(mMod->getContext()), inputType, int64ty, int8PtrTy, int64ty, nullptr));
65    main->setCallingConv(CallingConv::C);
66    Function::arg_iterator args = main->arg_begin();
67
68    Value * const inputStream = args++;
69    inputStream->setName("input");
70    Value * const bufferSize = args++;
71    bufferSize->setName("bufferSize");
72    Value * const fileName = args++;
73    fileName->setName("fileName");
74    Value * const finalLineUnterminated = args++;
75    finalLineUnterminated->setName("finalLineUnterminated");
76
77    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", main,0));
78
79    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
80    BasicBlock * segmentCondBlock = nullptr;
81    BasicBlock * segmentBodyBlock = nullptr;
82    const unsigned segmentSize = SegmentSize;
83    if (segmentSize > 1) {
84        segmentCondBlock = BasicBlock::Create(mMod->getContext(), "segmentCond", main, 0);
85        segmentBodyBlock = BasicBlock::Create(mMod->getContext(), "segmentBody", main, 0);
86    }
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    BasicBlock * finalPartialBlock = BasicBlock::Create(mMod->getContext(), "partial", main, 0);
91    BasicBlock * finalEmptyBlock = BasicBlock::Create(mMod->getContext(), "empty", main, 0);
92    BasicBlock * endBlock = BasicBlock::Create(mMod->getContext(), "end", main, 0);
93    BasicBlock * unterminatedBlock = BasicBlock::Create(mMod->getContext(), "unterminated", main, 0);
94    BasicBlock * exitBlock = BasicBlock::Create(mMod->getContext(), "exit", main, 0);
95
96    Instance * s2pInstance = mS2PKernel->instantiate(inputStream);
97    Instance * icGrepInstance = mICgrepKernel->instantiate(s2pInstance->getOutputStreamSet());
98    Instance * scanMatchInstance = mScanMatchKernel->instantiate(icGrepInstance->getOutputStreamSet());
99
100    Value * ptr = iBuilder->CreateBitCast(inputStream, int8PtrTy);
101
102    scanMatchInstance->setInternalState("FileBuf", ptr);
103    scanMatchInstance->setInternalState("FileSize", bufferSize);
104    scanMatchInstance->setInternalState("FileName", fileName);
105
106    // iBuilder->CallPrintInt("source", iBuilder->CreatePtrToInt(ptr, iBuilder->getInt64Ty()));
107
108    Value * initialBufferSize = nullptr;
109    BasicBlock * initialBlock = nullptr;
110
111    if (segmentSize > 1) {
112        iBuilder->CreateBr(segmentCondBlock);
113        iBuilder->SetInsertPoint(segmentCondBlock);
114        PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
115        remainingBytes->addIncoming(bufferSize, entryBlock);
116        Constant * const step = ConstantInt::get(int64ty, mBlockSize * segmentSize);
117        Value * segmentCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
118        iBuilder->CreateCondBr(segmentCondTest, fullCondBlock, segmentBodyBlock);
119        iBuilder->SetInsertPoint(segmentBodyBlock);
120        for (unsigned i = 0; i < segmentSize; ++i) {
121            s2pInstance->CreateDoBlockCall();
122        }
123        for (unsigned i = 0; i < segmentSize; ++i) {
124            icGrepInstance->CreateDoBlockCall();
125        }
126        for (unsigned i = 0; i < segmentSize; ++i) {
127            scanMatchInstance->CreateDoBlockCall();
128        }
129        remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), segmentBodyBlock);
130        iBuilder->CreateBr(segmentCondBlock);
131        initialBufferSize = remainingBytes;
132        initialBlock = segmentCondBlock;
133    } else {
134        initialBufferSize = bufferSize;
135        initialBlock = entryBlock;
136        iBuilder->CreateBr(fullCondBlock);
137    }
138
139    iBuilder->SetInsertPoint(fullCondBlock);
140    PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
141    remainingBytes->addIncoming(initialBufferSize, initialBlock);
142
143    Constant * const step = ConstantInt::get(int64ty, mBlockSize);
144    Value * fullCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
145    iBuilder->CreateCondBr(fullCondTest, finalBlock, fullBodyBlock);
146
147    iBuilder->SetInsertPoint(fullBodyBlock);
148    s2pInstance->CreateDoBlockCall();
149    icGrepInstance->CreateDoBlockCall();
150    scanMatchInstance->CreateDoBlockCall();
151
152    remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), fullBodyBlock);
153    iBuilder->CreateBr(fullCondBlock);
154
155    iBuilder->SetInsertPoint(finalBlock);
156    Value * const b4 = s2pInstance->getOutputStream(4);
157    Value * const b6 = s2pInstance->getOutputStream(6);
158    Value * emptyBlockCond = iBuilder->CreateICmpEQ(remainingBytes, ConstantInt::get(int64ty, 0));
159    iBuilder->CreateCondBr(emptyBlockCond, finalEmptyBlock, finalPartialBlock);
160
161
162    iBuilder->SetInsertPoint(finalPartialBlock);
163    s2pInstance->CreateDoBlockCall();
164    iBuilder->CreateBr(endBlock);
165
166    iBuilder->SetInsertPoint(finalEmptyBlock);
167    s2pInstance->clearOutputStream();
168    iBuilder->CreateBr(endBlock);
169
170    iBuilder->SetInsertPoint(endBlock);
171    Value * isFinalLineUnterminated = iBuilder->CreateICmpEQ(finalLineUnterminated, ConstantInt::get(int64ty, 0));
172    iBuilder->CreateCondBr(isFinalLineUnterminated, exitBlock, unterminatedBlock);
173   
174    iBuilder->SetInsertPoint(unterminatedBlock);
175
176    Value * remaining = iBuilder->CreateZExt(remainingBytes, iBuilder->getIntNTy(mBlockSize));
177    Value * EOF_pos = iBuilder->CreateShl(ConstantInt::get(iBuilder->getIntNTy(mBlockSize), 1), remaining);
178    EOF_pos = iBuilder->CreateBitCast(EOF_pos, mBitBlockType);
179
180
181    Value * b4val = iBuilder->CreateBlockAlignedLoad(b4);
182    b4val = iBuilder->CreateOr(b4val, EOF_pos);
183    iBuilder->CreateBlockAlignedStore(b4val, b4);
184
185    Value * b6val = iBuilder->CreateBlockAlignedLoad(b6);
186    b6val = iBuilder->CreateOr(b6val, EOF_pos);
187    iBuilder->CreateBlockAlignedStore(b6val, b6);
188
189    iBuilder->CreateBr(exitBlock);
190
191    iBuilder->SetInsertPoint(exitBlock);
192
193    icGrepInstance->CreateDoBlockCall();
194    scanMatchInstance->CreateDoBlockCall();
195    iBuilder->CreateRetVoid();
196
197    return main;
198}
Note: See TracBrowser for help on using the repository browser.