source: icGREP/icgrep-devel/icgrep/kernels/casefold_pipeline.cpp @ 5037

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

Refactor: move grep-specific code out of toolchain

File size: 6.8 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 <toolchain.h>
7#include <kernels/casefold_pipeline.h>
8#include <utf_encoding.h>
9
10#include <kernels/s2p_kernel.h>
11#include <kernels/p2s_kernel.h>
12#include <kernels/stdout_kernel.h>
13#include <kernels/instance.h>
14
15#include <pablo/function.h>
16#include <pablo/pablo_compiler.h>
17#include <pablo/pablo_toolchain.h>
18
19
20using namespace pablo;
21using namespace kernel;
22
23PipelineBuilder::PipelineBuilder(Module * m, IDISA::IDISA_Builder * b)
24: mMod(m)
25, iBuilder(b)
26, mBitBlockType(b->getBitBlockType())
27, mBlockSize(b->getBitBlockWidth()){
28
29}
30
31PipelineBuilder::~PipelineBuilder(){
32    delete mS2PKernel;
33    delete mCaseFoldKernel;
34    delete mP2SKernel;
35    delete mStdOutKernel;
36}
37
38void PipelineBuilder::CreateKernels(PabloFunction * function){
39    mS2PKernel = new KernelBuilder(iBuilder, "s2p", codegen::SegmentSize);
40    mP2SKernel = new KernelBuilder(iBuilder, "p2s", codegen::SegmentSize);
41    mCaseFoldKernel = new KernelBuilder(iBuilder, "casefold", codegen::SegmentSize);
42    mStdOutKernel = new KernelBuilder(iBuilder, "stddout", codegen::SegmentSize);
43
44    generateS2PKernel(mMod, iBuilder, mS2PKernel);
45    generateP2SKernel(mMod, iBuilder, mP2SKernel);
46    generateStdOutKernel(mMod, iBuilder, mStdOutKernel);
47
48    pablo_function_passes(function);
49
50    PabloCompiler pablo_compiler(mMod, iBuilder);
51    try {
52        pablo_compiler.setKernel(mCaseFoldKernel);
53        pablo_compiler.compile(function);
54        delete function;
55        releaseSlabAllocatorMemory();
56    } catch (std::runtime_error e) {
57        delete function;
58        releaseSlabAllocatorMemory();
59        std::cerr << "Runtime error: " << e.what() << std::endl;
60        exit(1);
61    }
62   
63}
64
65Function *  PipelineBuilder::ExecuteKernels() {
66    Type * const int64ty = iBuilder->getInt64Ty();
67    Type * const inputType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), std::vector<Type *>({ArrayType::get(mBitBlockType, 8)})), 1), 0);
68   
69    Function * const main = cast<Function>(mMod->getOrInsertFunction("Main", Type::getVoidTy(mMod->getContext()), inputType, int64ty, nullptr));
70    main->setCallingConv(CallingConv::C);
71    Function::arg_iterator args = main->arg_begin();
72   
73    Value * const inputStream = &*(args++);
74    inputStream->setName("input");
75    Value * const bufferSize = &*(args++);
76    bufferSize->setName("bufferSize");
77   
78    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", main,0));
79   
80    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
81
82    BasicBlock * segmentCondBlock = nullptr;
83    BasicBlock * segmentBodyBlock = nullptr;
84    const unsigned segmentSize = codegen::SegmentSize;
85    if (segmentSize > 1) {
86        segmentCondBlock = BasicBlock::Create(mMod->getContext(), "segmentCond", main, 0);
87        segmentBodyBlock = BasicBlock::Create(mMod->getContext(), "segmentBody", main, 0);
88    }
89    BasicBlock * fullCondBlock = BasicBlock::Create(mMod->getContext(), "fullCond", main, 0);
90    BasicBlock * fullBodyBlock = BasicBlock::Create(mMod->getContext(), "fullBody", main, 0);
91    BasicBlock * finalBlock = BasicBlock::Create(mMod->getContext(), "final", main, 0);
92    BasicBlock * finalPartialBlock = BasicBlock::Create(mMod->getContext(), "partial", main, 0);
93    BasicBlock * finalEmptyBlock = BasicBlock::Create(mMod->getContext(), "empty", main, 0);
94    BasicBlock * endBlock = BasicBlock::Create(mMod->getContext(), "end", main, 0);
95
96    Instance * s2pInstance = mS2PKernel->instantiate(inputStream);
97    Instance * caseFoldInstance = mCaseFoldKernel->instantiate(s2pInstance->getOutputStreamBuffer());
98    Instance * p2sInstance = mP2SKernel->instantiate(caseFoldInstance->getOutputStreamBuffer());
99    Instance * stdOutInstance = mStdOutKernel->instantiate(p2sInstance->getOutputStreamBuffer());
100
101    stdOutInstance->setInternalState("RemainingBytes", bufferSize);  // The total number of bytes to be sent to stdout.
102
103   
104    Value * initialBufferSize = nullptr;
105    BasicBlock * initialBlock = nullptr;
106   
107    if (segmentSize > 1) {
108        iBuilder->CreateBr(segmentCondBlock);
109        iBuilder->SetInsertPoint(segmentCondBlock);
110        PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
111        remainingBytes->addIncoming(bufferSize, entryBlock);
112        Constant * const step = ConstantInt::get(int64ty, mBlockSize * segmentSize);
113        Value * segmentCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
114        iBuilder->CreateCondBr(segmentCondTest, fullCondBlock, segmentBodyBlock);
115        iBuilder->SetInsertPoint(segmentBodyBlock);
116        for (unsigned i = 0; i < segmentSize; ++i) {
117            s2pInstance->CreateDoBlockCall();
118        }
119        for (unsigned i = 0; i < segmentSize; ++i) {
120            caseFoldInstance->CreateDoBlockCall();
121        }
122        for (unsigned i = 0; i < segmentSize; ++i) {
123            p2sInstance->CreateDoBlockCall();
124        }
125        for (unsigned i = 0; i < segmentSize; ++i) {
126            stdOutInstance->CreateDoBlockCall();
127        }
128        remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), segmentBodyBlock);
129        iBuilder->CreateBr(segmentCondBlock);
130        initialBufferSize = remainingBytes;
131        initialBlock = segmentCondBlock;
132    } else {
133        initialBufferSize = bufferSize;
134        initialBlock = entryBlock;
135        iBuilder->CreateBr(fullCondBlock);
136    }
137
138    iBuilder->SetInsertPoint(fullCondBlock);
139    PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
140    remainingBytes->addIncoming(initialBufferSize, initialBlock);
141
142    Constant * const step = ConstantInt::get(int64ty, mBlockSize);
143    Value * fullCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
144    iBuilder->CreateCondBr(fullCondTest, finalBlock, fullBodyBlock);
145   
146    iBuilder->SetInsertPoint(fullBodyBlock);
147
148    s2pInstance->CreateDoBlockCall();
149    caseFoldInstance->CreateDoBlockCall();
150    p2sInstance->CreateDoBlockCall();
151    stdOutInstance->CreateDoBlockCall();
152
153    Value * diff = iBuilder->CreateSub(remainingBytes, step);
154
155    remainingBytes->addIncoming(diff, fullBodyBlock);
156    iBuilder->CreateBr(fullCondBlock);
157   
158    iBuilder->SetInsertPoint(finalBlock);
159    Value * emptyBlockCond = iBuilder->CreateICmpEQ(remainingBytes, ConstantInt::get(int64ty, 0));
160    iBuilder->CreateCondBr(emptyBlockCond, finalEmptyBlock, finalPartialBlock);
161   
162   
163    iBuilder->SetInsertPoint(finalPartialBlock);
164    s2pInstance->CreateDoBlockCall();
165    iBuilder->CreateBr(endBlock);
166   
167    iBuilder->SetInsertPoint(finalEmptyBlock);
168    s2pInstance->clearOutputStreamSet();
169    iBuilder->CreateBr(endBlock);
170   
171    iBuilder->SetInsertPoint(endBlock);
172
173    caseFoldInstance->CreateDoBlockCall();
174    p2sInstance->CreateDoBlockCall();
175    stdOutInstance->CreateDoBlockCall();
176    iBuilder->CreateRetVoid();
177    return main;
178}
Note: See TracBrowser for help on using the repository browser.