source: icGREP/icgrep-devel/icgrep/kernels/lz4/lz4_bitstream_match_copy_kernel.cpp @ 6055

Last change on this file since 6055 was 6055, checked in by cameron, 11 months ago

Various small fixes

File size: 21.8 KB
Line 
1
2#include "lz4_bitstream_match_copy_kernel.h"
3
4#include <kernels/kernel_builder.h>
5#include <kernels/streamset.h>
6#include <toolchain/toolchain.h>
7#include <vector>
8#include <llvm/Support/raw_ostream.h>
9#include <llvm/IR/Intrinsics.h>
10
11
12using namespace llvm;
13using namespace std;
14namespace kernel {
15
16    std::vector<llvm::Value *>
17    LZ4BitStreamMatchCopyKernel::loadAllI64BitStreamValues(const std::unique_ptr<KernelBuilder> &b,
18                                                                 llvm::Value *basePtr,
19                                                                 llvm::Value *i64PackIndex) {
20        // TODO use gather to improve performance
21        std::vector<llvm::Value *, allocator<llvm::Value*>> v;
22
23        // For now, assume bit block type is always <4 * i64>
24        Value* bitBlockIndex = b->CreateUDiv(i64PackIndex, b->getSize(4));
25        Value* extractIndex = b->CreateURem(i64PackIndex, b->getSize(4));
26
27        for (unsigned i = 0; i < mNumberOfStreams; i++) {
28            Value* bitBlockPtr =  b->CreateGEP(basePtr, b->CreateAdd(b->CreateMul(bitBlockIndex, b->getSize(mNumberOfStreams)), b->getSize(i)));
29            bitBlockPtr = b->CreatePointerCast(bitBlockPtr, b->getInt64Ty()->getPointerTo());
30            v.push_back(b->CreateLoad(b->CreateGEP(bitBlockPtr, extractIndex)));
31        }
32        return v;
33    }
34
35    Value *LZ4BitStreamMatchCopyKernel::advanceUntilNextBit(const std::unique_ptr<KernelBuilder> &iBuilder, string inputName, Value *startPos, bool isNextOne) {
36        BasicBlock* entryBlock = iBuilder->GetInsertBlock();
37
38        Constant* SIZE_0 = iBuilder->getSize(0);
39        Constant* SIZE_1 = iBuilder->getSize(1);
40        Value* SIZE_64 = iBuilder->getSize(64); // maybe need to handle 32 bit machine
41        Value* SIZE_INPUT_64_COUNT = iBuilder->CreateUDiv(iBuilder->getCapacity(inputName), iBuilder->getSize(64));
42
43        Value* initCurrentPos = startPos;
44
45        Value* offsetMarkerRawPtr = iBuilder->CreatePointerCast(iBuilder->getRawInputPointer(inputName, SIZE_0), iBuilder->getInt64Ty()->getPointerTo());
46
47        BasicBlock* findNextMatchOffsetConBlock = iBuilder->CreateBasicBlock("findNextMatchOffsetConBlock");
48        BasicBlock* findNextMatchOffsetBodyBlock = iBuilder->CreateBasicBlock("findNextMatchOffsetBodyBlock");
49
50        iBuilder->CreateBr(findNextMatchOffsetConBlock);
51        iBuilder->SetInsertPoint(findNextMatchOffsetConBlock);
52        // Find position marker bit of next 1 bit
53
54        PHINode* phiCurrentPos = iBuilder->CreatePHI(iBuilder->getSizeTy(), 2);
55        phiCurrentPos->addIncoming(initCurrentPos, entryBlock);
56
57        Value* currentPosGlobalBlockIndex = iBuilder->CreateUDiv(phiCurrentPos, SIZE_64);
58        Value* currentPosLocalBlockIndex = iBuilder->CreateURem(currentPosGlobalBlockIndex, SIZE_INPUT_64_COUNT);
59        Value* currentPosBlockOffset = iBuilder->CreateURem(phiCurrentPos, SIZE_64);
60        Value* currentValue = iBuilder->CreateLoad(iBuilder->CreateGEP(offsetMarkerRawPtr, currentPosLocalBlockIndex));
61
62        Value* countValue = iBuilder->CreateLShr(currentValue, currentPosBlockOffset);
63        if (!isNextOne) {
64            countValue = iBuilder->CreateNot(countValue);
65        }
66        Value* forwardZero = iBuilder->CreateCountForwardZeroes(countValue);
67        Value* realForwardZero = iBuilder->CreateAdd(currentPosBlockOffset, forwardZero);
68
69        // If targetMarker == 0, move to next block, otherwise count forward zero
70        phiCurrentPos->addIncoming(iBuilder->CreateMul(SIZE_64, iBuilder->CreateAdd(currentPosGlobalBlockIndex, SIZE_1)), iBuilder->GetInsertBlock());
71        iBuilder->CreateCondBr(iBuilder->CreateICmpUGE(realForwardZero, SIZE_64), findNextMatchOffsetConBlock, findNextMatchOffsetBodyBlock);
72
73        iBuilder->SetInsertPoint(findNextMatchOffsetBodyBlock);
74
75        Value* newPosition = iBuilder->CreateAdd(iBuilder->CreateMul(currentPosGlobalBlockIndex, SIZE_64), realForwardZero);
76
77        return newPosition;
78    }
79
80    pair<Value*, Value*> LZ4BitStreamMatchCopyKernel::loadNextMatchOffset(const unique_ptr<KernelBuilder> &iBuilder) {
81        Value* initCurrentPos = iBuilder->CreateAdd(iBuilder->getScalarField("currentOffsetMarkerPos"), iBuilder->getSize(1));
82        Value* newPosition = this->advanceUntilNextBit(iBuilder, "MatchOffsetMarker", initCurrentPos, true);
83
84        // Load Match Offset from newPosition
85        Value* matchOffsetPtr = iBuilder->getRawInputPointer("byteStream", newPosition);
86        // For now, it is safe to cast matchOffset pointer into i16 since the input byte stream is always linear available
87        matchOffsetPtr = iBuilder->CreatePointerCast(matchOffsetPtr, iBuilder->getInt16Ty()->getPointerTo());
88        Value* matchOffset = iBuilder->CreateZExt(iBuilder->CreateLoad(matchOffsetPtr), iBuilder->getSizeTy());
89
90        return std::make_pair(matchOffset, newPosition);
91    }
92
93
94    void LZ4BitStreamMatchCopyKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & b) {
95        // ---- Contant
96        ConstantInt * const SIZE_4_MEGS = b->getSize(4 * 1024 * 1024);
97        ConstantInt * const SIZE_0 = b->getSize(0);
98        ConstantInt * const SIZE_1 = b->getSize(1);
99        ConstantInt * const SIZE_64 = b->getSize(64);
100        ConstantInt * const INT64_0 = b->getInt64(0);
101        ConstantInt * const INT64_1 = b->getInt64(1);
102
103        Value * BITBLOCK_0 = b->CreateBitCast(ConstantInt::get(b->getIntNTy(b->getBitBlockWidth()), 0), b->getBitBlockType());
104
105        // ---- Type
106        Type* BITBLOCK_TYPE = b->getBitBlockType();
107        Type* BITBLOCK_PTR_TYPE = BITBLOCK_TYPE->getPointerTo();
108        Type* I64_TY = b->getInt64Ty();
109        Type* I64_PTR_TY = I64_TY->getPointerTo();
110
111        Value * PDEP_func = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_bmi_pdep_64); //TODO for now only consider 64 bits
112
113        // ---- EntryBlock
114        BasicBlock * const entryBlock = b->GetInsertBlock();
115        BasicBlock * const exitBlock = b->CreateBasicBlock("exitBlock");
116
117        Value * const available = b->getAvailableItemCount("inputBitStream");
118        Value * const processed = b->getProcessedItemCount("inputBitStream");
119
120        Value * const itemsToDo = b->CreateUMin(b->CreateSub(available, processed), SIZE_4_MEGS);
121        b->setTerminationSignal(b->CreateICmpULT(itemsToDo, SIZE_4_MEGS));
122
123
124        Value* m0MarkerBasePtr = b->CreatePointerCast(b->getInputStreamBlockPtr("M0Marker", SIZE_0), I64_PTR_TY); // i64*
125        Value* sourceStreamPtr = b->CreatePointerCast(b->getInputStreamBlockPtr("inputBitStream", SIZE_0), BITBLOCK_PTR_TYPE);
126        Value* outputStreamPtr = b->CreatePointerCast(b->getOutputStreamBlockPtr("outputBitStream", SIZE_0), BITBLOCK_PTR_TYPE);
127
128        BasicBlock * const processLoopCon = b->CreateBasicBlock("processLoopCon");
129        BasicBlock * const processLoopBody = b->CreateBasicBlock("processLoopBody");
130        BasicBlock * const processLoopExit = b->CreateBasicBlock("processLoopExit");
131
132        b->CreateBr(processLoopCon);
133
134        // ---- ProcessLoopCon
135        // ProcessLoop will process one block of data each time (64bit m0, <4 * i64> input and output data)
136        b->SetInsertPoint(processLoopCon);
137
138        // carryBit === 0x1 only when the most significant bit of the target M0 block is one, which means the first position of next block need to be deposited (match copy)
139
140        PHINode* phiCarryBit = b->CreatePHI(b->getInt64Ty(), 2);
141        PHINode* phiCurrentPosition = b->CreatePHI(b->getInt64Ty(), 2); // 0~4mb, and all M0 related
142        PHINode* phiCarryMatchOffset = b->CreatePHI(b->getSizeTy(), 2);
143
144        phiCarryBit->addIncoming(INT64_0, entryBlock);
145        phiCurrentPosition->addIncoming(INT64_0, entryBlock);
146        phiCarryMatchOffset->addIncoming(SIZE_0, entryBlock);
147
148        b->CreateLikelyCondBr(b->CreateICmpULT(phiCurrentPosition, itemsToDo), processLoopBody, processLoopExit);
149
150        // ---- ProcessLoopBody
151        b->SetInsertPoint(processLoopBody);
152
153        Value* dataBlockIndex = b->CreateUDiv(phiCurrentPosition, SIZE_64);
154        Value* currentInitM0 = b->CreateLoad(b->CreateGEP(m0MarkerBasePtr, dataBlockIndex));
155        vector<Value*> initSourceData = this->loadAllI64BitStreamValues(b, sourceStreamPtr, dataBlockIndex);
156
157        Value* bitBlockIndex = b->CreateUDiv(dataBlockIndex, b->getSize(4));
158        Value* extractIndex = b->CreateURem(dataBlockIndex, b->getSize(4));
159
160        BasicBlock* carryBitProcessBlock = b->CreateBasicBlock("CarryBitProcessBlock");
161
162        BasicBlock* matchCopyLoopCon = b->CreateBasicBlock("MatchCopyLoopCon");
163        BasicBlock* matchCopyLoopBody = b->CreateBasicBlock("MatchCopyLoopBody");
164        BasicBlock* matchCopyLoopExit = b->CreateBasicBlock("MatchCopyLoopExit");
165
166        //
167        // The carry bit will need to be processed specially only when
168        // the most significant bit of previous block is 1 (the carry bit is 0x1) and the
169        // least significant bit of current block is 0
170        // e.g.
171        //   Assume the most significant bit is on the right side
172        //
173        //                    i64_1       i64_2
174        //   M0         ... 0000 0011 | 0111 0000 ...  - Carry bit need to be handle specially
175        //   M0         ... 0000 0011 | 1011 0000 ...  - Carry bit will be handle in the loop of i64_2
176        //   Carry Bit                  1000 0000 ...  - 0x1
177
178        Value* needProcessCarryBit = b->CreateAnd(phiCarryBit, b->CreateNot(b->CreateAnd(currentInitM0, b->getInt64(1))));
179        needProcessCarryBit = b->CreateICmpNE(needProcessCarryBit, INT64_0);
180
181        b->CreateUnlikelyCondBr(needProcessCarryBit, carryBitProcessBlock, matchCopyLoopCon);
182
183        // ---- CarryBitProcessBlock
184        b->SetInsertPoint(carryBitProcessBlock);
185        Value* carryCopyFromPos = b->CreateSub(phiCurrentPosition, phiCarryMatchOffset);
186        Value* carryCopyFromBlockIndex = b->CreateUDiv(carryCopyFromPos, SIZE_64);
187        Value* carryCopyFromOffset = b->CreateURem(carryCopyFromPos, SIZE_64);
188
189        vector<Value*> initSourceDataWithCarry = this->loadAllI64BitStreamValues(b, outputStreamPtr,
190                                                                                 carryCopyFromBlockIndex);
191
192        for (unsigned i = 0; i < mNumberOfStreams; i++) {
193            Value* v = initSourceDataWithCarry[i];
194            v = b->CreateLShr(v, carryCopyFromOffset);
195            v = b->CreateAnd(v, INT64_1);
196            initSourceDataWithCarry[i] = b->CreateOr(v, initSourceData[i]);
197        }
198        b->CreateBr(matchCopyLoopCon);
199
200        // ---- MatchCopyLoopCon
201        // MatchCopy Loop will handle one continuous data deposit each time
202        b->SetInsertPoint(matchCopyLoopCon);
203
204        PHINode* phiLatestMatchOffset = b->CreatePHI(b->getInt64Ty(), 3);
205        phiLatestMatchOffset->addIncoming(phiCarryMatchOffset, processLoopBody);
206        phiLatestMatchOffset->addIncoming(phiCarryMatchOffset, carryBitProcessBlock);
207
208        PHINode* phiRemainingM0Marker = b->CreatePHI(b->getInt64Ty(), 3);
209        phiRemainingM0Marker->addIncoming(currentInitM0, processLoopBody);
210        phiRemainingM0Marker->addIncoming(currentInitM0, carryBitProcessBlock);
211
212        std::vector<PHINode*> outputData;
213        for (unsigned i = 0; i < mNumberOfStreams; i++) {
214            PHINode* outputValue = b->CreatePHI(b->getInt64Ty(), 3);
215            outputValue->addIncoming(initSourceData[i], processLoopBody);
216            outputValue->addIncoming(initSourceDataWithCarry[i], carryBitProcessBlock);
217            outputData.push_back(outputValue);
218        }
219
220        b->CreateLikelyCondBr(b->CreateICmpNE(phiRemainingM0Marker, INT64_0), matchCopyLoopBody, matchCopyLoopExit);
221
222        // ---- MatchCopyLoopBody
223        b->SetInsertPoint(matchCopyLoopBody);
224
225        // Match Offset
226        // M0      0111 1000  - load new match offset
227        // M0      1100 0011  - use carryMatchOffset
228        Value* remainM0ForwardZero = b->CreateCountForwardZeroes(phiRemainingM0Marker);
229
230        BasicBlock* loadNextMatchOffsetBlock = b->CreateBasicBlock("loadNextMatchOffsetBlock");
231        BasicBlock* doMatchCopyBlock = b->CreateBasicBlock("DoMatchCopyBlock");
232
233        b->CreateLikelyCondBr(
234                b->CreateOr(b->CreateICmpEQ(phiLatestMatchOffset, INT64_0),
235                                   b->CreateICmpNE(remainM0ForwardZero, INT64_0)
236                ),
237                loadNextMatchOffsetBlock, doMatchCopyBlock
238        );
239
240        // ---- loadNextMatchOffsetBlock
241        b->SetInsertPoint(loadNextMatchOffsetBlock);
242        auto matchOffsetRet = this->loadNextMatchOffset(b);
243        BasicBlock* loadNextMatchOffsetExitBlock = b->GetInsertBlock();
244        Value* newMatchOffset = matchOffsetRet.first;
245        Value* newMatchOffsetPos = matchOffsetRet.second;
246        b->setScalarField("currentOffsetMarkerPos", newMatchOffsetPos);
247        b->setProcessedItemCount("MatchOffsetMarker", newMatchOffsetPos);
248        b->CreateBr(doMatchCopyBlock);
249
250        // ---- doMatchCopyBlock
251        b->SetInsertPoint(doMatchCopyBlock);
252
253        PHINode* phiTargetMatchOffset = b->CreatePHI(b->getSizeTy(), 2);
254        phiTargetMatchOffset->addIncoming(phiLatestMatchOffset, matchCopyLoopBody);
255        phiTargetMatchOffset->addIncoming(newMatchOffset, loadNextMatchOffsetExitBlock);
256
257        //
258        // M0            0011 0010
259        // boundary      0000 1000
260        // nextMask      0000 0111
261        // deposit       0011 1000
262        // newM0         0000 0010
263
264        Value* remainStart = b->CreateShl(INT64_1, remainM0ForwardZero);
265
266        Value* boundaryMarker = b->CreateAnd(b->CreateAdd(phiRemainingM0Marker, remainStart), b->CreateNot(phiRemainingM0Marker));
267
268        Value* nextMask = b->CreateSub(INT64_0, b->CreateShl(boundaryMarker, INT64_1));
269        Value* depositMarker = b->CreateAnd(
270                b->CreateOr(phiRemainingM0Marker, boundaryMarker),
271                b->CreateNot(nextMask)
272        );
273        Value* newM0Marker = b->CreateAnd(phiRemainingM0Marker, nextMask);
274        Value* depositMarkerPopcount = b->CreatePopcount(depositMarker);
275
276        Value* matchCopyFromStart = b->CreateSub(b->CreateAdd(phiCurrentPosition, remainM0ForwardZero), phiTargetMatchOffset);
277        Value* matchCopyFromBlockIndex = b->CreateUDiv(matchCopyFromStart, SIZE_64);
278
279        Value* matchCopyFromOffset = b->CreateURem(matchCopyFromStart, SIZE_64);
280        Value* matchCopyFromRemaining = b->CreateSub(SIZE_64, matchCopyFromOffset);
281        Value* matchCopyFromNextBlockIndex = b->CreateAdd(matchCopyFromBlockIndex, b->CreateSelect(b->CreateICmpULE(depositMarkerPopcount, matchCopyFromRemaining), SIZE_0, SIZE_1));
282
283
284        vector<Value*> fromBlockValues = this->loadAllI64BitStreamValues(b, outputStreamPtr, matchCopyFromBlockIndex);
285        vector<Value*> fromNextBlockValues = this->loadAllI64BitStreamValues(b, outputStreamPtr, matchCopyFromNextBlockIndex);
286
287        vector<Value*> pdepSourceData;
288        for (unsigned i = 0; i < mNumberOfStreams; i++) {
289            Value* fromBlockValue = fromBlockValues[i];
290            // when dataBlockIndex == matchCopyFromBlockIndex, we need to use current output value as input
291            fromBlockValue = b->CreateSelect(b->CreateICmpEQ(dataBlockIndex, matchCopyFromBlockIndex), outputData[i], fromBlockValue);
292            Value* fromNextBlockValue = fromNextBlockValues[i];
293            fromNextBlockValue = b->CreateSelect(b->CreateICmpEQ(dataBlockIndex, matchCopyFromNextBlockIndex), outputData[i], fromNextBlockValue);
294
295
296            Value * allFromValue = b->CreateOr(
297                    b->CreateLShr(fromBlockValue, matchCopyFromOffset),
298                    b->CreateShl(fromNextBlockValue, matchCopyFromRemaining)
299            );
300            pdepSourceData.push_back(allFromValue);
301        }
302
303
304        BasicBlock* doubleSourceDataCon = b->CreateBasicBlock("doubleSourceDataCon");
305        BasicBlock* doubleSourceDataBody = b->CreateBasicBlock("doubleSourceDataBody");
306        BasicBlock* doubleSourceDataExit = b->CreateBasicBlock("doubleSourceDataExit");
307
308        b->CreateBr(doubleSourceDataCon);
309
310        //
311        // When matchOffset < depositMarkerPopcount, we need to use log2 approach to double the source data
312        // e.g.
313        // Assume that match copy start position is 1, matchOffset is 1, match length is 5
314        //     outputBuffer              a000 0000 0000 0000
315        //     sourceDataBeforeDouble    a000 0000 0000 0000
316        // At this point, only 1 bit of source data is accessable, so it will double the source data 3 times until we have
317        // 1 * 2 ^ 3 = 8 bits accessable
318        //     sourceDataAfterDouble     aaaa aaaa 0000 0000
319        //     outputBuffer(after copy)  aaaa aa00 0000 0000
320        //
321
322        // ---- doubleSourceDataCon
323        b->SetInsertPoint(doubleSourceDataCon);
324        PHINode* phiSourceDataAccessable = b->CreatePHI(b->getSizeTy(), 2);
325        phiSourceDataAccessable->addIncoming(phiTargetMatchOffset, doMatchCopyBlock);
326        vector<PHINode*> phiPdepSourceData;
327        for (int i = 0; i < mNumberOfStreams; i++) {
328            PHINode* v = b->CreatePHI(b->getInt64Ty(), 2);
329            v->addIncoming(pdepSourceData[i], doMatchCopyBlock);
330            phiPdepSourceData.push_back(v);
331        }
332        b->CreateUnlikelyCondBr(b->CreateICmpULT(phiSourceDataAccessable, depositMarkerPopcount), doubleSourceDataBody, doubleSourceDataExit);
333
334        // ---- doubleSourceDataBody
335        b->SetInsertPoint(doubleSourceDataBody);
336        for (int i = 0; i < mNumberOfStreams; i++) {
337            PHINode* v = phiPdepSourceData[i];
338            Value* newValue = b->CreateOr(v, b->CreateShl(v, phiSourceDataAccessable));
339            v->addIncoming(newValue, doubleSourceDataBody);
340        }
341        phiSourceDataAccessable->addIncoming(b->CreateShl(phiSourceDataAccessable, SIZE_1), doubleSourceDataBody);
342
343        b->CreateBr(doubleSourceDataCon);
344
345        // ---- doubleSourceDataExit
346        b->SetInsertPoint(doubleSourceDataExit);
347        // At this point, we can guarantee we have enough data for pdep
348        for (unsigned i = 0; i < mNumberOfStreams; i++) {
349            // Do Match Copy by PDEP
350            Value* source_field = phiPdepSourceData[i];
351            Value * newValue = b->CreateCall(PDEP_func, {source_field, depositMarker});
352            PHINode* outputValue = outputData[i];
353            Value* newOutputValue = b->CreateOr(outputValue, newValue);
354            outputValue->addIncoming(newOutputValue, b->GetInsertBlock());
355        }
356        phiRemainingM0Marker->addIncoming(newM0Marker, b->GetInsertBlock());
357        phiLatestMatchOffset->addIncoming(phiTargetMatchOffset, b->GetInsertBlock());
358
359        b->CreateBr(matchCopyLoopCon);
360
361        // ---- MatchCopyLoopExit
362        b->SetInsertPoint(matchCopyLoopExit);
363        this->storeAllI64BitStreamValues(b, outputStreamPtr, dataBlockIndex, outputData);
364
365        Value* hasNewCarryBit = b->CreateAnd(currentInitM0, b->CreateShl(INT64_1, b->getInt64(63)));
366        hasNewCarryBit = b->CreateICmpNE(hasNewCarryBit, INT64_0);
367        Value* newCarryBit = b->CreateSelect(hasNewCarryBit, INT64_1, INT64_0);
368        phiCarryBit->addIncoming(newCarryBit, b->GetInsertBlock());
369
370        phiCarryMatchOffset->addIncoming(b->CreateSelect(hasNewCarryBit, phiLatestMatchOffset, b->getSize(0)), b->GetInsertBlock());
371
372        phiCurrentPosition->addIncoming(b->CreateAdd(phiCurrentPosition, SIZE_64), b->GetInsertBlock());
373
374        b->CreateBr(processLoopCon);
375
376        // ---- ProcessLoopExit
377        b->SetInsertPoint(processLoopExit);
378        Value * const toProcessItemCount = b->CreateAdd(processed, itemsToDo);
379        b->setProcessedItemCount("M0Marker", toProcessItemCount);
380        b->CreateBr(exitBlock);
381
382        // ---- ExitBlock
383        b->SetInsertPoint(exitBlock);
384    }
385
386    void LZ4BitStreamMatchCopyKernel::storeAllI64BitStreamValues(const std::unique_ptr<KernelBuilder> &b,
387                                                                       llvm::Value *basePtr, llvm::Value *i64PackIndex,
388                                                                       const std::vector<llvm::PHINode *> &values) {
389        // TODO PHINode here is a workaround
390        // For now, assume bit block type is always <4 * i64>
391        Value* bitBlockIndex = b->CreateUDiv(i64PackIndex, b->getSize(4));
392        Value* extractIndex = b->CreateURem(i64PackIndex, b->getSize(4));
393
394        for (unsigned i = 0; i < mNumberOfStreams; i++) {
395            Value* bitBlockPtr =  b->CreateGEP(basePtr, b->CreateAdd(b->CreateMul(bitBlockIndex, b->getSize(mNumberOfStreams)), b->getSize(i)));
396            bitBlockPtr = b->CreatePointerCast(bitBlockPtr, b->getInt64Ty()->getPointerTo());
397            b->CreateStore(values[i], b->CreateGEP(bitBlockPtr, extractIndex));
398        }
399
400    }
401
402    LZ4BitStreamMatchCopyKernel::LZ4BitStreamMatchCopyKernel(const std::unique_ptr<kernel::KernelBuilder> & iBuilder, unsigned numberOfStreams, std::string name)
403            : SegmentOrientedKernel(std::move(name),
404// Inputs
405                                    {
406                                            Binding{iBuilder->getStreamSetTy(1, 1), "MatchOffsetMarker", BoundedRate(0, 1)},
407                                            Binding{iBuilder->getStreamSetTy(1, 1), "M0Marker", BoundedRate(0, 1)},
408                                            Binding{iBuilder->getStreamSetTy(1, 8), "byteStream", RateEqualTo("MatchOffsetMarker")},
409                                            Binding{iBuilder->getStreamSetTy(numberOfStreams, 1), "inputBitStream",
410                                                    RateEqualTo("M0Marker")},
411                                    },
412// Outputs
413                                    {
414                                            Binding{iBuilder->getStreamSetTy(numberOfStreams, 1), "outputBitStream",
415                                                    RateEqualTo("M0Marker")}
416                                    },
417// Arguments
418                                    {
419                                    },
420                                    {},
421                                    {
422                    Binding(iBuilder->getSizeTy(), "currentOffsetMarkerPos"),
423            })
424            , mNumberOfStreams(numberOfStreams) {
425
426        setStride(4 * 1024 * 1024);
427        addAttribute(MustExplicitlyTerminate());
428    }
429
430}
Note: See TracBrowser for help on using the repository browser.