source: icGREP/icgrep-devel/icgrep/kernels/lzparabix/decoder/LZParabixAioKernel.cpp @ 6131

Last change on this file since 6131 was 6131, checked in by xwa163, 13 months ago

Minor bug fix for LZParabixAioKernel

File size: 28.8 KB
Line 
1//
2// Created by wxy325 on 2018/6/18.
3//
4
5#include "LZParabixAioKernel.h"
6
7#include <kernels/kernel_builder.h>
8#include <iostream>
9#include <string>
10#include <llvm/Support/raw_ostream.h>
11#include <kernels/streamset.h>
12#include <cstdint>
13
14
15using namespace llvm;
16using namespace kernel;
17using namespace std;
18
19
20namespace kernel{
21    LZParabixAioKernel::LZParabixAioKernel(const std::unique_ptr<kernel::KernelBuilder> &b, std::vector<unsigned> numsOfBitStreams)
22            :SegmentOrientedKernel("LZParabixAioKernel",
23            // Inputs
24                                   {
25                    Binding{b->getStreamSetTy(1, 8), "byteStream", BoundedRate(0, 1)},
26
27                    // block data
28                    Binding{b->getStreamSetTy(1, 64), "blockStart", BoundedRate(0, 1), AlwaysConsume()},
29                    Binding{b->getStreamSetTy(1, 64), "blockEnd", RateEqualTo("blockStart"), AlwaysConsume()}
30
31
32            },
33            //Outputs
34                                   {
35
36                                   },
37            //Arguments
38                                   {
39                                           Binding{b->getSizeTy(), "fileSize"}
40                                   },
41                                   {},
42            //Internal states:
43                                   {
44                                           Binding{b->getSizeTy(), "blockDataIndex"},
45                                           Binding{b->getInt64Ty(), "outputPos"},
46
47
48                                   }), mNumsOfBitStreams(numsOfBitStreams) {
49        this->setStride(4 * 1024 * 1024);
50        addAttribute(MustExplicitlyTerminate());
51
52        // TODO modify processing for input bitstream
53        mStreamSetInputs.push_back(Binding{b->getStreamSetTy(numsOfBitStreams[0], 1), "inputBitStream0", BoundedRate(0, 1), AlwaysConsume()});
54        mStreamSetOutputs.push_back(Binding{b->getStreamSetTy(numsOfBitStreams[0], 1), "outputStream0", BoundedRate(0, 1)});
55
56        for (unsigned i = 1; i < numsOfBitStreams.size(); i++) {
57            mStreamSetInputs.push_back(Binding{b->getStreamSetTy(numsOfBitStreams[i], 1), "inputBitStream" + std::to_string(i), RateEqualTo("inputBitStream0"), AlwaysConsume()});
58            mStreamSetOutputs.push_back(Binding{b->getStreamSetTy(numsOfBitStreams[i], 1), "outputStream" + std::to_string(i), RateEqualTo("outputStream0")});
59        }
60
61        this->initPendingOutputScalar(b);
62
63    }
64
65
66    void LZParabixAioKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> &b) {
67        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
68        BasicBlock* blockEndConBlock = b->CreateBasicBlock("blockEndConBlock");
69
70        Value * blockDataIndex = b->getScalarField("blockDataIndex");
71        Value * totalNumber = b->getAvailableItemCount("blockEnd");
72
73        Value * blockEnd = this->generateLoadInt64NumberInput(b, "blockEnd", blockDataIndex);
74
75        b->CreateCondBr(b->CreateICmpULT(blockDataIndex, totalNumber), blockEndConBlock, exitBlock);
76
77        b->SetInsertPoint(blockEndConBlock);
78
79        Value * blockStart = this->generateLoadInt64NumberInput(b, "blockStart", blockDataIndex);
80
81        Value* literalLengthPtr = b->getRawInputPointer("byteStream", blockStart);
82        literalLengthPtr = b->CreatePointerCast(literalLengthPtr, b->getInt32Ty()->getPointerTo());
83        Value* totalLiteralLength = b->CreateZExtOrBitCast(b->CreateLoad(literalLengthPtr), b->getSizeTy());
84        Value* literalStartPos = b->getProcessedItemCount("inputBitStream0");
85
86        Value* literalEndPos = b->CreateAdd(literalStartPos, totalLiteralLength);
87
88        Value* allItemAvailable = b->getInt1(true);
89
90        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
91            allItemAvailable = b->CreateAnd(allItemAvailable, b->CreateICmpULE(literalEndPos, b->getAvailableItemCount("inputBitStream" + std::to_string(i))));
92        }
93
94
95        BasicBlock * processBlock = b->CreateBasicBlock("processBlock");
96        b->CreateCondBr(allItemAvailable, processBlock, exitBlock);
97
98        b->SetInsertPoint(processBlock);
99
100        this->generateProcessCompressedBlock(b, blockStart, blockEnd);
101
102        Value * newBlockDataIndex = b->CreateAdd(blockDataIndex, b->getInt64(1));
103        b->setScalarField("blockDataIndex", newBlockDataIndex);
104        b->setProcessedItemCount("blockStart", newBlockDataIndex);
105        b->setProcessedItemCount("byteStream", blockEnd);
106        b->setProducedItemCount("outputStream0", b->getScalarField("outputPos"));
107        b->CreateBr(exitBlock);
108
109        b->SetInsertPoint(exitBlock);
110    }
111
112
113    llvm::Value *LZParabixAioKernel::generateLoadInt64NumberInput(const std::unique_ptr<KernelBuilder> &iBuilder,
114                                                                      std::string inputBufferName, llvm::Value *globalOffset) {
115
116        Value * capacity = iBuilder->getCapacity(inputBufferName);
117        Value * processed = iBuilder->getProcessedItemCount(inputBufferName);
118        processed = iBuilder->CreateAnd(processed, iBuilder->CreateNeg(capacity));
119        Value * offset = iBuilder->CreateSub(globalOffset, processed);
120        Value * valuePtr = iBuilder->getRawInputPointer(inputBufferName, offset);
121        return iBuilder->CreateLoad(valuePtr);
122    }
123
124    void LZParabixAioKernel::generateProcessCompressedBlock(const std::unique_ptr<KernelBuilder> &b,
125                                                            llvm::Value *lz4BlockStart, llvm::Value *lz4BlockEnd) {
126        Value* literalLengthPtr = b->getRawInputPointer("byteStream", lz4BlockStart);
127        literalLengthPtr = b->CreatePointerCast(literalLengthPtr, b->getInt32Ty()->getPointerTo());
128        Value* totalLiteralLength = b->CreateZExtOrBitCast(b->CreateLoad(literalLengthPtr), b->getSizeTy());
129        Value* literalStartPos = b->getProcessedItemCount("inputBitStream0");
130
131
132
133        Value* tokenStartPos = b->CreateAdd(b->CreateAdd(lz4BlockStart, b->getSize(4)), totalLiteralLength);
134
135
136
137        Value* isTerminal = b->CreateICmpEQ(lz4BlockEnd, b->getScalarField("fileSize"));
138        b->setTerminationSignal(isTerminal);
139
140        BasicBlock* exitBlock = b->CreateBasicBlock("processCompressedExitBlock");
141
142        BasicBlock* processCon = b->CreateBasicBlock("processCompressedConBlock");
143        BasicBlock* processBody = b->CreateBasicBlock("processCompressedBodyBlock");
144
145
146        BasicBlock* beforeProcessConBlock = b->GetInsertBlock();
147        b->CreateBr(processCon);
148        b->SetInsertPoint(processCon);
149
150        PHINode* phiLiteralCursorValue = b->CreatePHI(b->getInt64Ty(), 2);
151        phiLiteralCursorValue->addIncoming(literalStartPos, beforeProcessConBlock);
152
153        PHINode* phiTokenCursorValue = b->CreatePHI(b->getInt64Ty(), 2); // phiCursorValue should always be the position of next token except for the final sequence
154        phiTokenCursorValue->addIncoming(tokenStartPos, beforeProcessConBlock);
155
156        b->CreateCondBr(b->CreateICmpULT(phiTokenCursorValue, lz4BlockEnd), processBody, exitBlock);
157
158        b->SetInsertPoint(processBody);
159
160        auto ret = this->processSequence(b, phiLiteralCursorValue, phiTokenCursorValue, lz4BlockEnd);
161
162        Value* nextLiteralGlobalPos = ret.first;
163        Value* nextTokenGlobalPos = ret.second;
164
165        phiLiteralCursorValue->addIncoming(nextLiteralGlobalPos, b->GetInsertBlock());
166        phiTokenCursorValue->addIncoming(nextTokenGlobalPos, b->GetInsertBlock());
167        b->CreateBr(processCon);
168
169        b->SetInsertPoint(exitBlock);
170        this->storePendingOutput(b);
171        b->setProcessedItemCount("inputBitStream0", b->CreateAdd(literalStartPos, totalLiteralLength));
172    }
173
174
175    std::pair<llvm::Value *, llvm::Value *>
176    LZParabixAioKernel::processSequence(const std::unique_ptr<KernelBuilder> &b, llvm::Value *literalCursorPos,
177                                        llvm::Value *tokenCursorPos,
178                                        llvm::Value *lz4BlockEnd) {
179
180        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
181
182        Value* sequenceBasePtr = b->getRawInputPointer("byteStream", tokenCursorPos);
183        Value* sequenceToken = b->CreateLoad(sequenceBasePtr);
184
185        Value* highestTokenBit = b->CreateAnd(sequenceToken, b->getInt8((uint8_t)1 << 7));
186        Value* isLiteral = b->CreateICmpNE(highestTokenBit, b->getInt8(0));
187        Value* tokenNumValue = b->CreateZExt(b->CreateSub(sequenceToken, highestTokenBit), b->getSizeTy());
188
189
190        BasicBlock* literalProcessBlock = b->CreateBasicBlock("literalProcessBlock");
191        BasicBlock* matchProcessBlock = b->CreateBasicBlock("matchProcessBlock");
192        b->CreateCondBr(isLiteral, literalProcessBlock, matchProcessBlock);
193
194        // ---- literalProcessBlock
195        b->SetInsertPoint(literalProcessBlock);
196        this->processLiteral(b, literalCursorPos, tokenNumValue);
197        Value* newTokenCursorPosAfterLiteral = b->CreateAdd(tokenCursorPos, b->getSize(1));
198        Value* newLiteralCursorPosAfterLiteral = b->CreateAdd(literalCursorPos, tokenNumValue);
199
200
201        BasicBlock* literalProcessFinalBlock = b->GetInsertBlock();
202        b->CreateBr(exitBlock);
203
204        // ---- matchProcessBlock
205        b->SetInsertPoint(matchProcessBlock);
206        Value* tokenCursorNextPos = b->CreateAdd(tokenCursorPos, b->getSize(1));
207        Value* matchIndexBytes = this->processMatch(b, tokenCursorNextPos, tokenNumValue, sequenceBasePtr);
208        Value* newTokenCursorPosAfterMatch = b->CreateAdd(tokenCursorNextPos, matchIndexBytes);
209
210        BasicBlock* matchProcessFinalBlock = b->GetInsertBlock();
211        b->CreateBr(exitBlock);
212
213        // ---- exitBlock
214        b->SetInsertPoint(exitBlock);
215        PHINode* phiTokenCursorValue = b->CreatePHI(b->getSizeTy(), 2);
216        phiTokenCursorValue->addIncoming(newTokenCursorPosAfterLiteral, literalProcessFinalBlock);
217        phiTokenCursorValue->addIncoming(newTokenCursorPosAfterMatch, matchProcessFinalBlock);
218
219        PHINode* phiLiteralCursorValue = b->CreatePHI(b->getSizeTy(), 2);
220        phiLiteralCursorValue->addIncoming(newLiteralCursorPosAfterLiteral, literalProcessFinalBlock);
221        phiLiteralCursorValue->addIncoming(literalCursorPos, matchProcessFinalBlock);
222
223        return std::make_pair(phiLiteralCursorValue, phiTokenCursorValue);
224    }
225
226    void LZParabixAioKernel::processLiteral(const std::unique_ptr<KernelBuilder> &b, llvm::Value* cursorPos, llvm::Value* literalLength) {
227        // ---- EntryBlock
228        BasicBlock* entryBlock = b->GetInsertBlock();
229        Value* remCursorPos = b->CreateURem(cursorPos, b->getCapacity("inputBitStream0"));
230
231        BasicBlock* processLiteralConBlock = b->CreateBasicBlock("processLiteralConBlock");
232        BasicBlock* processLiteralBodyBlock = b->CreateBasicBlock("processLiteralBodyBlock");
233        BasicBlock* processLiteralExitBlock = b->CreateBasicBlock("processLiteralExitBlock");
234
235        b->CreateBr(processLiteralConBlock);
236
237        // ---- processLiteralConBlock
238        b->SetInsertPoint(processLiteralConBlock);
239        PHINode* phiRemCursorPos = b->CreatePHI(b->getSizeTy(), 2);
240        phiRemCursorPos->addIncoming(remCursorPos, entryBlock);
241        PHINode* phiRemainingLiteralLength = b->CreatePHI(b->getSizeTy(), 2);
242        phiRemainingLiteralLength->addIncoming(literalLength, entryBlock);
243
244        b->CreateCondBr(b->CreateICmpUGT(phiRemainingLiteralLength, b->getSize(0)), processLiteralBodyBlock, processLiteralExitBlock);
245
246        // ---- processLiteralBodyBlock
247        b->SetInsertPoint(processLiteralBodyBlock);
248
249        Value* targetLiteralLength = b->CreateSub(b->getSize(64), b->CreateURem(phiRemCursorPos, b->getSize(64)));
250        targetLiteralLength = b->CreateUMin(phiRemainingLiteralLength, targetLiteralLength);
251
252
253        Value* cursorBlockIndex = b->CreateUDiv(phiRemCursorPos, b->getSize(b->getBitBlockWidth()));
254        Value* cursorBlockRem = b->CreateURem(phiRemCursorPos, b->getSize(b->getBitBlockWidth()));
255        Value* cursorI64BlockIndex = b->CreateUDiv(cursorBlockRem, b->getSize(64));
256        Value* cursorI64BlockRem = b->CreateURem(cursorBlockRem, b->getSize(64));
257        Value* literalMask = b->CreateSub(
258                b->CreateSelect(b->CreateICmpEQ(targetLiteralLength, b->getInt64(0x40)), b->getInt64(0), b->CreateShl(b->getInt64(1), targetLiteralLength)),
259                b->getInt64(1)
260        );
261
262        std::vector<llvm::Value*> extractValues;
263
264        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
265            Value* bitStreamBasePtr = b->CreatePointerCast(b->getRawInputPointer("inputBitStream" + std::to_string(i), b->getSize(0)), b->getBitBlockType()->getPointerTo());
266            Value* targetBlockBasePtr = b->CreatePointerCast(b->CreateGEP(bitStreamBasePtr, b->CreateMul(cursorBlockIndex, b->getSize(mNumsOfBitStreams[i]))), b->getInt64Ty()->getPointerTo());
267
268            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
269                Value* ptr = b->CreateGEP(targetBlockBasePtr, b->CreateAdd(cursorI64BlockIndex, b->getSize(j * (b->getBitBlockWidth() / 64))));
270                Value* extractV = b->CreateLShr(b->CreateLoad(ptr), cursorI64BlockRem);
271                extractV = b->CreateAnd(extractV, literalMask);
272                extractValues.push_back(extractV);
273            }
274        }
275
276        this->appendBitStreamOutput(b, extractValues, targetLiteralLength);
277
278        phiRemCursorPos->addIncoming(b->CreateURem(b->CreateAdd(phiRemCursorPos, targetLiteralLength), b->getCapacity("inputBitStream0")), b->GetInsertBlock());
279        phiRemainingLiteralLength->addIncoming(b->CreateSub(phiRemainingLiteralLength, targetLiteralLength), b->GetInsertBlock());
280
281        b->CreateBr(processLiteralConBlock);
282
283        // ---- processLiteralExitBlock
284        b->SetInsertPoint(processLiteralExitBlock);
285    }
286
287
288    llvm::Value *LZParabixAioKernel::processMatch(const std::unique_ptr<KernelBuilder> &b, llvm::Value* cursorPos, llvm::Value* matchOffset, llvm::Value* sequenceBasePtr) {
289        Function* pdep = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_bmi_pdep_64);
290        Constant * PEXT_func = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_bmi_pext_64);
291
292        Value* pdepMask = b->getInt64(0x0101010101010101);
293
294        Value* oneBitIndex = b->CreateZExt(b->CreateLoad(b->CreateGEP(sequenceBasePtr, b->getSize(1))), b->getInt64Ty());
295        Value* zeroBitIndex = b->CreateZExt(b->CreateLoad(b->CreateGEP(sequenceBasePtr, b->getSize(2))), b->getInt64Ty());
296        Value* matchMaskPtr = b->CreatePointerCast(b->CreateGEP(sequenceBasePtr, b->getSize(3)), b->getInt64Ty()->getPointerTo());
297        Value* matchMask = b->CreateLoad(matchMaskPtr);
298
299        Value* fullOneBitIndex = b->CreateCall(pdep, {oneBitIndex, pdepMask});
300        Value* fullZeroBitIndex = b->CreateCall(pdep, {zeroBitIndex, pdepMask});
301
302
303        Value* remainingMask = b->CreateNot(b->CreateMul(b->CreateOr(fullOneBitIndex, fullZeroBitIndex), b->getInt64(0xff)));
304        Value* fullMatchMask = b->CreateOr(
305                b->CreateMul(fullOneBitIndex, b->getInt64(0xff)),
306                b->CreateCall(pdep, {matchMask, remainingMask})
307        );
308
309        Value* remCursorPos = b->CreateURem(cursorPos, b->getCapacity("outputStream0"));
310        Value* cursorPosI64BlockIndex = b->CreateUDiv(remCursorPos, b->getSize(64));
311
312        Value* remOutputPos = b->CreateURem(b->getScalarField("outputPos"), b->getCapacity("outputStream0"));
313        Value* outputPosI64BlockIndex = b->CreateUDiv(remOutputPos, b->getSize(64));
314
315        Value* matchCopyFromI64BlockIndex = b->CreateSub(outputPosI64BlockIndex, matchOffset);
316
317        Value* matchCopyFromBitBlockIndex = b->CreateUDiv(matchCopyFromI64BlockIndex, b->getSize(4));
318        matchCopyFromI64BlockIndex = b->CreateURem(matchCopyFromI64BlockIndex, b->getSize(4));
319
320        std::vector<llvm::Value*> extractValues;
321        unsigned iStreamIndex = 0;
322        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
323            Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream" + std::to_string(i), b->getSize(0)), b->getBitBlockType()->getPointerTo());
324            Value* outputBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(matchCopyFromBitBlockIndex, b->getSize(mNumsOfBitStreams[i])));
325            outputBlockBasePtr = b->CreatePointerCast(outputBlockBasePtr, b->getInt64Ty()->getPointerTo());
326
327            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
328                Value* ptr = b->CreateGEP(outputBlockBasePtr, b->CreateAdd(matchCopyFromI64BlockIndex, b->getSize(j * (b->getBitBlockWidth() / 64))));
329                Value* value = b->CreateLoad(ptr);
330                Value * extractV = b->CreateCall(PEXT_func, {value, fullMatchMask});
331                extractValues.push_back(extractV);
332                ++iStreamIndex;
333            }
334        }
335
336        this->appendBitStreamOutput(b, extractValues, b->CreatePopcount(fullMatchMask));
337
338        return b->CreateAdd(b->CreateSub(b->getSize(8), b->CreatePopcount(b->CreateOr(oneBitIndex, zeroBitIndex))), b->getSize(2));
339    }
340
341
342    // ---- Output
343    void LZParabixAioKernel::initPendingOutputScalar(const std::unique_ptr<KernelBuilder> &b) {
344        this->initPendingOutputScalar_BitStream(b);
345//        this->initPendingOutputScalar_Swizzled(b);
346    }
347
348    void LZParabixAioKernel::appendBitStreamOutput(const std::unique_ptr<KernelBuilder> &b, std::vector<llvm::Value*>& extractedValues, llvm::Value* valueLength) {
349        this->appendBitStreamOutput_BitStream(b, extractedValues, valueLength);
350//        this->appendBitStreamOutput_Swizzled(b, extractedValues, valueLength);
351    }
352
353    void LZParabixAioKernel::storePendingOutput(const std::unique_ptr<KernelBuilder> &b) {
354        BasicBlock* storePendingOutputBlock = b->CreateBasicBlock("storePendingOutputBlock");
355        BasicBlock* storePendingOutputExitBlock = b->CreateBasicBlock("storePendingOutputExitBlock");
356
357        Value* oldOutputPos = b->getScalarField("outputPos");
358        b->CreateCondBr(
359                b->CreateICmpNE(b->CreateURem(oldOutputPos, b->getSize(64)), b->getSize(0)),
360                storePendingOutputBlock,
361                storePendingOutputExitBlock
362        );
363
364        b->SetInsertPoint(storePendingOutputBlock);
365        this->storePendingOutput_BitStream(b);
366//        this->storePendingOutput_Swizzled(b);
367        b->CreateBr(storePendingOutputExitBlock);
368
369        b->SetInsertPoint(storePendingOutputExitBlock);
370    }
371
372
373    // ---- Output BitStream
374    void LZParabixAioKernel::initPendingOutputScalar_BitStream(const std::unique_ptr<KernelBuilder> &b) {
375        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
376            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
377                this->addScalar(b->getInt64Ty(), "pendingOutput" + std::to_string(i) + "_" + std::to_string(j));
378            }
379        }
380    }
381
382    void LZParabixAioKernel::appendBitStreamOutput_BitStream(const std::unique_ptr<KernelBuilder> &b, std::vector<llvm::Value*>& extractedValues, llvm::Value* valueLength) {
383        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
384
385        Value* oldOutputPos = b->getScalarField("outputPos");
386        Value* oldOutputPosRem64 = b->CreateURem(oldOutputPos, b->getSize(64));
387
388        std::vector<llvm::Value*> newOutputVec;
389
390        unsigned iStreamIndex = 0;
391        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
392            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
393                Value* newValue = b->CreateOr(b->getScalarField("pendingOutput" + std::to_string(i) + "_" + std::to_string(j)), b->CreateShl(extractedValues[iStreamIndex], oldOutputPosRem64));
394                newOutputVec.push_back(newValue);
395                ++iStreamIndex;
396            }
397        }
398
399        BasicBlock* noStoreOutputBlock = b->CreateBasicBlock("noStoreOutputBlock");
400        BasicBlock* storeOutputBlock =b->CreateBasicBlock("storeOutputBlock");
401
402        b->CreateCondBr(b->CreateICmpULT(b->CreateAdd(oldOutputPosRem64, valueLength), b->getSize(64)), noStoreOutputBlock, storeOutputBlock);
403
404        // ---- noStoreOutputBlock
405        b->SetInsertPoint(noStoreOutputBlock);
406
407        iStreamIndex = 0;
408        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
409            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
410                b->setScalarField("pendingOutput" + std::to_string(i) + "_" + std::to_string(j), newOutputVec[iStreamIndex]);
411                ++iStreamIndex;
412            }
413        }
414
415        b->CreateBr(exitBlock);
416
417        // ---- storeOutputBlock
418        b->SetInsertPoint(storeOutputBlock);
419
420        Value* oldOutputPosRem = b->CreateURem(oldOutputPos, b->getCapacity("outputStream0"));
421        Value* oldOutputPosBitBlockIndex = b->CreateUDiv(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
422        Value* oldOutputPosBitBlockRem = b->CreateURem(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
423
424        iStreamIndex = 0;
425        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
426            Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream" + std::to_string(i), b->getSize(0)), b->getBitBlockType()->getPointerTo());
427            Value* outputBitBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(oldOutputPosBitBlockIndex, b->getSize(mNumsOfBitStreams[i])));
428            outputBitBlockBasePtr = b->CreatePointerCast(outputBitBlockBasePtr, b->getInt64Ty()->getPointerTo());
429
430            Value* oldOutputPosI64Index = b->CreateUDiv(oldOutputPosBitBlockRem, b->getSize(64));
431
432            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
433                Value* targetPtr = b->CreateGEP(outputBitBlockBasePtr, b->CreateAdd(oldOutputPosI64Index, b->getSize(j * (b->getBitBlockWidth() / 64))));
434                b->CreateStore(newOutputVec[iStreamIndex], targetPtr);
435                ++iStreamIndex;
436            }
437        }
438
439        Value* shiftAmount = b->CreateSub(b->getSize(0x40), oldOutputPosRem64);
440        Value* fullyShift = b->CreateICmpEQ(shiftAmount, b->getSize(0x40));
441
442        iStreamIndex = 0;
443        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
444            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
445                b->setScalarField("pendingOutput" + std::to_string(i) + "_" + std::to_string(j), b->CreateSelect(fullyShift, b->getInt64(0), b->CreateLShr(extractedValues[iStreamIndex], shiftAmount)));
446                ++iStreamIndex;
447            }
448        }
449
450        b->CreateBr(exitBlock);
451
452        b->SetInsertPoint(exitBlock);
453        b->setScalarField("outputPos", b->CreateAdd(oldOutputPos, valueLength));
454    }
455
456    void LZParabixAioKernel::storePendingOutput_BitStream(const std::unique_ptr<KernelBuilder> &b) {
457        Value* oldOutputPos = b->getScalarField("outputPos");
458        Value* oldOutputPosRem = b->CreateURem(oldOutputPos, b->getCapacity("outputStream0"));
459        Value* oldOutputPosBitBlockIndex = b->CreateUDiv(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
460        Value* oldOutputPosBitBlockRem = b->CreateURem(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
461        Value* oldOutputPosI64Index = b->CreateUDiv(oldOutputPosBitBlockRem, b->getSize(64));
462
463        unsigned iStreamIndex = 0;
464        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
465            Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream" + std::to_string(i), b->getSize(0)), b->getBitBlockType()->getPointerTo());
466            Value* outputBitBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(oldOutputPosBitBlockIndex, b->getSize(mNumsOfBitStreams[i])));
467            outputBitBlockBasePtr = b->CreatePointerCast(outputBitBlockBasePtr, b->getInt64Ty()->getPointerTo());
468            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
469                Value* targetPtr = b->CreateGEP(outputBitBlockBasePtr, b->CreateAdd(oldOutputPosI64Index, b->getSize(j * (b->getBitBlockWidth() / 64))));
470                b->CreateStore(b->getScalarField("pendingOutput" + std::to_string(i) + "_" + std::to_string(j)), targetPtr);
471                ++iStreamIndex;
472            }
473        }
474    }
475
476    // ---- Output Swizzled
477    void LZParabixAioKernel::initPendingOutputScalar_Swizzled(const std::unique_ptr<KernelBuilder> &b) {
478        for (unsigned i = 0; i < (mNumsOfBitStreams[0] + 3) / 4; i++) {
479            this->addScalar(b->getBitBlockType(), "pendingOutput" + std::to_string(0) + "_" + std::to_string(i));
480        }
481    }
482    void LZParabixAioKernel::appendBitStreamOutput_Swizzled(const std::unique_ptr<KernelBuilder> &b, std::vector<llvm::Value*>& extractedValues, llvm::Value* valueLength) {
483
484        std::vector<llvm::Value*> extractedValuesVec;
485        for (unsigned i = 0; i < 2; i++) {
486            Value* vec = ConstantVector::getNullValue(b->getBitBlockType());
487            for (unsigned j = 0; j < 4; j++) {
488                vec = b->CreateInsertElement(vec, extractedValues[i * 4 + j], j);
489            }
490            extractedValuesVec.push_back(vec);
491        }
492
493        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
494
495        Value* oldOutputPos = b->getScalarField("outputPos");
496        Value* oldOutputPosRem64 = b->CreateURem(oldOutputPos, b->getSize(64));
497
498        std::vector<llvm::Value*> newOutputVec;
499        for (unsigned i = 0; i < 2; i++) {
500            Value* newValue = b->CreateOr(b->getScalarField("pendingOutput" + std::to_string(0) + "_" + std::to_string(i)), b->CreateShl(extractedValuesVec[i], b->simd_fill(64, oldOutputPosRem64)));
501            newOutputVec.push_back(newValue);
502        }
503
504
505        BasicBlock* noStoreOutputBlock = b->CreateBasicBlock("noStoreOutputBlock");
506        BasicBlock* storeOutputBlock =b->CreateBasicBlock("storeOutputBlock");
507
508        b->CreateCondBr(b->CreateICmpULT(b->CreateAdd(oldOutputPosRem64, valueLength), b->getSize(64)), noStoreOutputBlock, storeOutputBlock);
509
510        // ---- noStoreOutputBlock
511        b->SetInsertPoint(noStoreOutputBlock);
512        for (unsigned i = 0; i < 2; i++) {
513            b->setScalarField("pendingOutput" + std::to_string(0) + "_" + std::to_string(i), newOutputVec[i]);
514        }
515        b->CreateBr(exitBlock);
516
517        // ---- storeOutputBlock
518        b->SetInsertPoint(storeOutputBlock);
519
520        Value* oldOutputPosRem = b->CreateURem(oldOutputPos, b->getCapacity("outputStream0"));
521        Value* oldOutputPosBitBlockIndex = b->CreateUDiv(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
522        Value* oldOutputPosBitBlockRem = b->CreateURem(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
523
524        Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream0", b->getSize(0)), b->getBitBlockType()->getPointerTo());
525        Value* outputBitBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(oldOutputPosBitBlockIndex, b->getSize(8)));
526        outputBitBlockBasePtr = b->CreatePointerCast(outputBitBlockBasePtr, b->getInt64Ty()->getPointerTo());
527
528        Value* oldOutputPosI64Index = b->CreateUDiv(oldOutputPosBitBlockRem, b->getSize(64));
529
530        for (unsigned i = 0; i < 2; i++) {
531            for (unsigned j = 0; j < 4; j++) {
532                Value* targetPtr = b->CreateGEP(outputBitBlockBasePtr, b->CreateAdd(oldOutputPosI64Index, b->getSize((i * 4 + j) * 4)));
533                b->CreateStore(b->CreateExtractElement(newOutputVec[i], j), targetPtr);
534            }
535
536        }
537
538        Value* shiftAmount = b->CreateSub(b->getSize(0x40), oldOutputPosRem64);
539        Value* fullyShift = b->CreateICmpEQ(shiftAmount, b->getSize(0x40));
540
541        for (unsigned i = 0; i < 2; i++) {
542
543            b->setScalarField("pendingOutput" + std::to_string(0) + "_" + std::to_string(i), b->CreateSelect(fullyShift, ConstantVector::getNullValue(b->getBitBlockType()), b->CreateLShr(extractedValuesVec[i], b->simd_fill(64, shiftAmount))));
544        }
545
546        b->CreateBr(exitBlock);
547
548        b->SetInsertPoint(exitBlock);
549        b->setScalarField("outputPos", b->CreateAdd(oldOutputPos, valueLength));
550
551    }
552
553    void LZParabixAioKernel::storePendingOutput_Swizzled(const std::unique_ptr<KernelBuilder> &b) {
554        Value* oldOutputPos = b->getScalarField("outputPos");
555        Value* oldOutputPosRem = b->CreateURem(oldOutputPos, b->getCapacity("outputStream0"));
556        Value* oldOutputPosBitBlockIndex = b->CreateUDiv(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
557        Value* oldOutputPosBitBlockRem = b->CreateURem(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
558
559        Value* oldOutputPosI64Index = b->CreateUDiv(oldOutputPosBitBlockRem, b->getSize(64));
560
561        Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream0", b->getSize(0)), b->getBitBlockType()->getPointerTo());
562        Value* outputBitBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(oldOutputPosBitBlockIndex, b->getSize(8)));
563        outputBitBlockBasePtr = b->CreatePointerCast(outputBitBlockBasePtr, b->getInt64Ty()->getPointerTo());
564
565        vector<Value*> pendingOutputVec;
566        for (unsigned i = 0; i < 2; i++) {
567            pendingOutputVec.push_back(b->getScalarField("pendingOutput" + std::to_string(0) + "_" + std::to_string(i)));
568        }
569
570        for (unsigned i = 0; i < 2; i++) {
571            for (unsigned j = 0; j < 2; j++) {
572                Value* targetPtr = b->CreateGEP(outputBitBlockBasePtr, b->CreateAdd(oldOutputPosI64Index, b->getSize((i * 4 + j) * 4)));
573                b->CreateStore(b->CreateExtractElement(pendingOutputVec[i], j), targetPtr);
574            }
575        }
576    }
577}
Note: See TracBrowser for help on using the repository browser.