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

Last change on this file since 6047 was 6047, checked in by nmedfort, 13 months ago

Major refactoring of buffer types. Static buffers replace Circular and CircularCopyback?. External buffers unify Source/External?.

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