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

Last change on this file since 6117 was 6117, checked in by xwa163, 10 months ago

Fix bugs of LZParabixAioKernel

File size: 25.0 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        mStreamSetInputs.push_back(Binding{b->getStreamSetTy(numsOfBitStreams[0], 1), "inputBitStream0", RateEqualTo("byteStream")});
53        mStreamSetOutputs.push_back(Binding{b->getStreamSetTy(numsOfBitStreams[0], 1), "outputStream0", BoundedRate(0, 1)});
54
55        for (unsigned i = 1; i < numsOfBitStreams.size(); i++) {
56            mStreamSetInputs.push_back(Binding{b->getStreamSetTy(numsOfBitStreams[i], 1), "inputBitStream" + std::to_string(i), RateEqualTo("byteStream")});
57            mStreamSetOutputs.push_back(Binding{b->getStreamSetTy(numsOfBitStreams[i], 1), "outputStream" + std::to_string(i), RateEqualTo("outputStream0")});
58        }
59
60        this->initPendingOutputScalar(b);
61
62    }
63
64
65    void LZParabixAioKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> &b) {
66        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
67        BasicBlock* blockEndConBlock = b->CreateBasicBlock("blockEndConBlock");
68
69        Value * blockDataIndex = b->getScalarField("blockDataIndex");
70        Value * totalNumber = b->getAvailableItemCount("blockEnd");
71
72        Value * blockEnd = this->generateLoadInt64NumberInput(b, "blockEnd", blockDataIndex);
73
74        b->CreateCondBr(b->CreateICmpULT(blockDataIndex, totalNumber), blockEndConBlock, exitBlock);
75
76        b->SetInsertPoint(blockEndConBlock);
77        Value * blockStart = this->generateLoadInt64NumberInput(b, "blockStart", blockDataIndex);
78        BasicBlock * processBlock = b->CreateBasicBlock("processBlock");
79//        b->CreateCondBr(b->CreateICmpULE(blockEnd, totalExtender), processBlock, exitBlock);
80        b->CreateBr(processBlock);
81
82        b->SetInsertPoint(processBlock);
83
84        this->generateProcessCompressedBlock(b, blockStart, blockEnd);
85
86
87        Value * newBlockDataIndex = b->CreateAdd(blockDataIndex, b->getInt64(1));
88        b->setScalarField("blockDataIndex", newBlockDataIndex);
89        b->setProcessedItemCount("blockStart", newBlockDataIndex);
90        b->setProcessedItemCount("byteStream", blockEnd);
91        b->setProducedItemCount("outputStream0", b->getScalarField("outputPos"));
92        b->CreateBr(exitBlock);
93
94        b->SetInsertPoint(exitBlock);
95    }
96
97
98    llvm::Value *LZParabixAioKernel::generateLoadInt64NumberInput(const std::unique_ptr<KernelBuilder> &iBuilder,
99                                                                      std::string inputBufferName, llvm::Value *globalOffset) {
100
101        Value * capacity = iBuilder->getCapacity(inputBufferName);
102        Value * processed = iBuilder->getProcessedItemCount(inputBufferName);
103        processed = iBuilder->CreateAnd(processed, iBuilder->CreateNeg(capacity));
104        Value * offset = iBuilder->CreateSub(globalOffset, processed);
105        Value * valuePtr = iBuilder->getRawInputPointer(inputBufferName, offset);
106        return iBuilder->CreateLoad(valuePtr);
107    }
108
109    void LZParabixAioKernel::generateProcessCompressedBlock(const std::unique_ptr<KernelBuilder> &b,
110                                                            llvm::Value *lz4BlockStart, llvm::Value *lz4BlockEnd) {
111        Value* isTerminal = b->CreateICmpEQ(lz4BlockEnd, b->getScalarField("fileSize"));
112        b->setTerminationSignal(isTerminal);
113
114        BasicBlock* exitBlock = b->CreateBasicBlock("processCompressedExitBlock");
115
116        BasicBlock* processCon = b->CreateBasicBlock("processCompressedConBlock");
117        BasicBlock* processBody = b->CreateBasicBlock("processCompressedBodyBlock");
118
119
120        BasicBlock* beforeProcessConBlock = b->GetInsertBlock();
121        b->CreateBr(processCon);
122        b->SetInsertPoint(processCon);
123
124        PHINode* phiCursorValue = b->CreatePHI(b->getInt64Ty(), 2, "phiCursorValue"); // phiCursorValue should always be the position of next token except for the final sequence
125        phiCursorValue->addIncoming(lz4BlockStart, beforeProcessConBlock);
126
127        b->CreateCondBr(b->CreateICmpULT(phiCursorValue, lz4BlockEnd), processBody, exitBlock);
128
129        b->SetInsertPoint(processBody);
130
131        Value* nextTokenGlobalPos = this->processSequence(b, phiCursorValue, lz4BlockEnd);
132        phiCursorValue->addIncoming(nextTokenGlobalPos, b->GetInsertBlock());
133        b->CreateBr(processCon);
134
135        b->SetInsertPoint(exitBlock);
136        this->storePendingOutput(b);
137
138    }
139
140
141    llvm::Value *LZParabixAioKernel::processSequence(const std::unique_ptr<KernelBuilder> &b, llvm::Value *cursorPos,
142                                                              llvm::Value *lz4BlockEnd) {
143
144        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
145        Value* cursorNextPos = b->CreateAdd(cursorPos, b->getSize(1));
146
147        Value* sequenceBasePtr = b->getRawInputPointer("byteStream", cursorPos);
148        Value* sequenceToken = b->CreateLoad(sequenceBasePtr);
149
150        Value* highestTokenBit = b->CreateAnd(sequenceToken, b->getInt8((uint8_t)1 << 7));
151        Value* isLiteral = b->CreateICmpNE(highestTokenBit, b->getInt8(0));
152        Value* tokenNumValue = b->CreateZExt(b->CreateSub(sequenceToken, highestTokenBit), b->getSizeTy());
153
154
155        BasicBlock* literalProcessBlock = b->CreateBasicBlock("literalProcessBlock");
156        BasicBlock* matchProcessBlock = b->CreateBasicBlock("matchProcessBlock");
157        b->CreateCondBr(isLiteral, literalProcessBlock, matchProcessBlock);
158
159        // ---- literalProcessBlock
160        b->SetInsertPoint(literalProcessBlock);
161        this->processLiteral(b, cursorNextPos, tokenNumValue);
162        Value* newCursorPosAfterLiteral = b->CreateAdd(cursorNextPos, tokenNumValue);
163
164
165        BasicBlock* literalProcessFinalBlock = b->GetInsertBlock();
166        b->CreateBr(exitBlock);
167
168        // ---- matchProcessBlock
169        b->SetInsertPoint(matchProcessBlock);
170
171        Value* matchIndexBytes = this->processMatch(b, cursorNextPos, tokenNumValue, sequenceBasePtr);
172        Value* newCursorPosAfterMatch = b->CreateAdd(cursorNextPos, matchIndexBytes);
173
174        BasicBlock* matchProcessFinalBlock = b->GetInsertBlock();
175        b->CreateBr(exitBlock);
176
177        // ---- exitBlock
178        b->SetInsertPoint(exitBlock);
179        PHINode* phiCursorValue = b->CreatePHI(b->getSizeTy(), 2);
180        phiCursorValue->addIncoming(newCursorPosAfterLiteral, literalProcessFinalBlock);
181        phiCursorValue->addIncoming(newCursorPosAfterMatch, matchProcessFinalBlock);
182
183
184        return phiCursorValue;
185    }
186
187    llvm::Value *LZParabixAioKernel::processLiteral(const std::unique_ptr<KernelBuilder> &b, llvm::Value* cursorPos, llvm::Value* literalLength) {
188        Value* remCursorPos = b->CreateURem(cursorPos, b->getCapacity("inputBitStream0"));
189
190        Value* cursorBlockIndex = b->CreateUDiv(remCursorPos, b->getSize(b->getBitBlockWidth()));
191        Value* cursorBlockRem = b->CreateURem(remCursorPos, b->getSize(b->getBitBlockWidth()));
192        Value* cursorI64BlockIndex = b->CreateUDiv(cursorBlockRem, b->getSize(64));
193        Value* cursorI64BlockRem = b->CreateURem(cursorBlockRem, b->getSize(64));
194        Value* literalMask = b->CreateSub(
195                b->CreateSelect(b->CreateICmpEQ(literalLength, b->getInt64(0x40)), b->getInt64(0), b->CreateShl(b->getInt64(1), literalLength)),
196                b->getInt64(1)
197        );
198
199        std::vector<llvm::Value*> extractValues;
200
201        Value* oldOutputPos = b->getScalarField("outputPos");
202
203
204        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
205            Value* bitStreamBasePtr = b->CreatePointerCast(b->getRawInputPointer("inputBitStream" + std::to_string(i), b->getSize(0)), b->getBitBlockType()->getPointerTo());
206            Value* targetBlockBasePtr = b->CreatePointerCast(b->CreateGEP(bitStreamBasePtr, b->CreateMul(cursorBlockIndex, b->getSize(mNumsOfBitStreams[i]))), b->getInt64Ty()->getPointerTo());
207
208            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
209                Value* ptr = b->CreateGEP(targetBlockBasePtr, b->CreateAdd(cursorI64BlockIndex, b->getSize(j * (b->getBitBlockWidth() / 64))));
210                Value* extractV = b->CreateLShr(b->CreateLoad(ptr), cursorI64BlockRem);
211                extractV = b->CreateAnd(extractV, literalMask);
212                extractValues.push_back(extractV);
213            }
214        }
215
216        this->appendBitStreamOutput(b, extractValues, literalLength);
217    }
218
219
220    llvm::Value *LZParabixAioKernel::processMatch(const std::unique_ptr<KernelBuilder> &b, llvm::Value* cursorPos, llvm::Value* matchOffset, llvm::Value* sequenceBasePtr) {
221        Function* pdep = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_bmi_pdep_64);
222        Constant * PEXT_func = Intrinsic::getDeclaration(b->getModule(), Intrinsic::x86_bmi_pext_64);
223
224        Value* pdepMask = b->getInt64(0x0101010101010101);
225
226        Value* oneBitIndex = b->CreateZExt(b->CreateLoad(b->CreateGEP(sequenceBasePtr, b->getSize(1))), b->getInt64Ty());
227        Value* zeroBitIndex = b->CreateZExt(b->CreateLoad(b->CreateGEP(sequenceBasePtr, b->getSize(2))), b->getInt64Ty());
228        Value* matchMaskPtr = b->CreatePointerCast(b->CreateGEP(sequenceBasePtr, b->getSize(3)), b->getInt64Ty()->getPointerTo());
229        Value* matchMask = b->CreateLoad(matchMaskPtr);
230
231        Value* fullOneBitIndex = b->CreateCall(pdep, {oneBitIndex, pdepMask});
232        Value* fullZeroBitIndex = b->CreateCall(pdep, {zeroBitIndex, pdepMask});
233
234
235        Value* remainingMask = b->CreateNot(b->CreateMul(b->CreateOr(fullOneBitIndex, fullZeroBitIndex), b->getInt64(0xff)));
236        Value* fullMatchMask = b->CreateOr(
237                b->CreateMul(fullOneBitIndex, b->getInt64(0xff)),
238                b->CreateCall(pdep, {matchMask, remainingMask})
239        );
240
241        Value* remCursorPos = b->CreateURem(cursorPos, b->getCapacity("outputStream0"));
242        Value* cursorPosI64BlockIndex = b->CreateUDiv(remCursorPos, b->getSize(64));
243
244        Value* remOutputPos = b->CreateURem(b->getScalarField("outputPos"), b->getCapacity("outputStream0"));
245        Value* outputPosI64BlockIndex = b->CreateUDiv(remOutputPos, b->getSize(64));
246
247        Value* matchCopyFromI64BlockIndex = b->CreateSub(outputPosI64BlockIndex, matchOffset);
248
249        Value* matchCopyFromBitBlockIndex = b->CreateUDiv(matchCopyFromI64BlockIndex, b->getSize(4));
250        matchCopyFromI64BlockIndex = b->CreateURem(matchCopyFromI64BlockIndex, b->getSize(4));
251
252        std::vector<llvm::Value*> extractValues;
253        unsigned iStreamIndex = 0;
254        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
255            Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream" + std::to_string(i), b->getSize(0)), b->getBitBlockType()->getPointerTo());
256            Value* outputBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(matchCopyFromBitBlockIndex, b->getSize(mNumsOfBitStreams[i])));
257            outputBlockBasePtr = b->CreatePointerCast(outputBlockBasePtr, b->getInt64Ty()->getPointerTo());
258
259            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
260                Value* ptr = b->CreateGEP(outputBlockBasePtr, b->CreateAdd(matchCopyFromI64BlockIndex, b->getSize(j * (b->getBitBlockWidth() / 64))));
261                Value* value = b->CreateLoad(ptr);
262                Value * extractV = b->CreateCall(PEXT_func, {value, fullMatchMask});
263                extractValues.push_back(extractV);
264                ++iStreamIndex;
265            }
266        }
267
268        this->appendBitStreamOutput(b, extractValues, b->CreatePopcount(fullMatchMask));
269
270        return b->CreateAdd(b->CreateSub(b->getSize(8), b->CreatePopcount(b->CreateOr(oneBitIndex, zeroBitIndex))), b->getSize(2));
271    }
272
273
274    // ---- Output
275    void LZParabixAioKernel::initPendingOutputScalar(const std::unique_ptr<KernelBuilder> &b) {
276        this->initPendingOutputScalar_BitStream(b);
277//        this->initPendingOutputScalar_Swizzled(b);
278    }
279
280    void LZParabixAioKernel::appendBitStreamOutput(const std::unique_ptr<KernelBuilder> &b, std::vector<llvm::Value*>& extractedValues, llvm::Value* valueLength) {
281        this->appendBitStreamOutput_BitStream(b, extractedValues, valueLength);
282//        this->appendBitStreamOutput_Swizzled(b, extractedValues, valueLength);
283    }
284
285    void LZParabixAioKernel::storePendingOutput(const std::unique_ptr<KernelBuilder> &b) {
286        BasicBlock* storePendingOutputBlock = b->CreateBasicBlock("storePendingOutputBlock");
287        BasicBlock* storePendingOutputExitBlock = b->CreateBasicBlock("storePendingOutputExitBlock");
288
289        Value* oldOutputPos = b->getScalarField("outputPos");
290        b->CreateCondBr(
291                b->CreateICmpNE(b->CreateURem(oldOutputPos, b->getSize(64)), b->getSize(0)),
292                storePendingOutputBlock,
293                storePendingOutputExitBlock
294        );
295
296        b->SetInsertPoint(storePendingOutputBlock);
297        this->storePendingOutput_BitStream(b);
298//        this->storePendingOutput_Swizzled(b);
299        b->CreateBr(storePendingOutputExitBlock);
300
301        b->SetInsertPoint(storePendingOutputExitBlock);
302    }
303
304
305    // ---- Output BitStream
306    void LZParabixAioKernel::initPendingOutputScalar_BitStream(const std::unique_ptr<KernelBuilder> &b) {
307        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
308            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
309                this->addScalar(b->getInt64Ty(), "pendingOutput" + std::to_string(i) + "_" + std::to_string(j));
310            }
311        }
312    }
313
314    void LZParabixAioKernel::appendBitStreamOutput_BitStream(const std::unique_ptr<KernelBuilder> &b, std::vector<llvm::Value*>& extractedValues, llvm::Value* valueLength) {
315        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
316
317        Value* oldOutputPos = b->getScalarField("outputPos");
318        Value* oldOutputPosRem64 = b->CreateURem(oldOutputPos, b->getSize(64));
319
320        std::vector<llvm::Value*> newOutputVec;
321
322        unsigned iStreamIndex = 0;
323        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
324            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
325                Value* newValue = b->CreateOr(b->getScalarField("pendingOutput" + std::to_string(i) + "_" + std::to_string(j)), b->CreateShl(extractedValues[iStreamIndex], oldOutputPosRem64));
326                newOutputVec.push_back(newValue);
327                ++iStreamIndex;
328            }
329        }
330
331        BasicBlock* noStoreOutputBlock = b->CreateBasicBlock("noStoreOutputBlock");
332        BasicBlock* storeOutputBlock =b->CreateBasicBlock("storeOutputBlock");
333
334        b->CreateCondBr(b->CreateICmpULT(b->CreateAdd(oldOutputPosRem64, valueLength), b->getSize(64)), noStoreOutputBlock, storeOutputBlock);
335
336        // ---- noStoreOutputBlock
337        b->SetInsertPoint(noStoreOutputBlock);
338
339        iStreamIndex = 0;
340        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
341            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
342                b->setScalarField("pendingOutput" + std::to_string(i) + "_" + std::to_string(j), newOutputVec[iStreamIndex]);
343                ++iStreamIndex;
344            }
345        }
346
347        b->CreateBr(exitBlock);
348
349        // ---- storeOutputBlock
350        b->SetInsertPoint(storeOutputBlock);
351
352        Value* oldOutputPosRem = b->CreateURem(oldOutputPos, b->getCapacity("outputStream0"));
353        Value* oldOutputPosBitBlockIndex = b->CreateUDiv(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
354        Value* oldOutputPosBitBlockRem = b->CreateURem(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
355
356        iStreamIndex = 0;
357        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
358            Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream" + std::to_string(i), b->getSize(0)), b->getBitBlockType()->getPointerTo());
359            Value* outputBitBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(oldOutputPosBitBlockIndex, b->getSize(mNumsOfBitStreams[i])));
360            outputBitBlockBasePtr = b->CreatePointerCast(outputBitBlockBasePtr, b->getInt64Ty()->getPointerTo());
361
362            Value* oldOutputPosI64Index = b->CreateUDiv(oldOutputPosBitBlockRem, b->getSize(64));
363
364            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
365                Value* targetPtr = b->CreateGEP(outputBitBlockBasePtr, b->CreateAdd(oldOutputPosI64Index, b->getSize(j * (b->getBitBlockWidth() / 64))));
366                b->CreateStore(newOutputVec[iStreamIndex], targetPtr);
367                ++iStreamIndex;
368            }
369        }
370
371        Value* shiftAmount = b->CreateSub(b->getSize(0x40), oldOutputPosRem64);
372        Value* fullyShift = b->CreateICmpEQ(shiftAmount, b->getSize(0x40));
373
374        iStreamIndex = 0;
375        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
376            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
377                b->setScalarField("pendingOutput" + std::to_string(i) + "_" + std::to_string(j), b->CreateSelect(fullyShift, b->getInt64(0), b->CreateLShr(extractedValues[iStreamIndex], shiftAmount)));
378                ++iStreamIndex;
379            }
380        }
381
382        b->CreateBr(exitBlock);
383
384        b->SetInsertPoint(exitBlock);
385        b->setScalarField("outputPos", b->CreateAdd(oldOutputPos, valueLength));
386    }
387
388    void LZParabixAioKernel::storePendingOutput_BitStream(const std::unique_ptr<KernelBuilder> &b) {
389        Value* oldOutputPos = b->getScalarField("outputPos");
390        Value* oldOutputPosRem = b->CreateURem(oldOutputPos, b->getCapacity("outputStream0"));
391        Value* oldOutputPosBitBlockIndex = b->CreateUDiv(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
392        Value* oldOutputPosBitBlockRem = b->CreateURem(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
393        Value* oldOutputPosI64Index = b->CreateUDiv(oldOutputPosBitBlockRem, b->getSize(64));
394
395        unsigned iStreamIndex = 0;
396        for (unsigned i = 0; i < mNumsOfBitStreams.size(); i++) {
397            Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream" + std::to_string(i), b->getSize(0)), b->getBitBlockType()->getPointerTo());
398            Value* outputBitBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(oldOutputPosBitBlockIndex, b->getSize(mNumsOfBitStreams[i])));
399            outputBitBlockBasePtr = b->CreatePointerCast(outputBitBlockBasePtr, b->getInt64Ty()->getPointerTo());
400            for (unsigned j = 0; j < mNumsOfBitStreams[i]; j++) {
401                Value* targetPtr = b->CreateGEP(outputBitBlockBasePtr, b->CreateAdd(oldOutputPosI64Index, b->getSize(j * (b->getBitBlockWidth() / 64))));
402                b->CreateStore(b->getScalarField("pendingOutput" + std::to_string(i) + "_" + std::to_string(j)), targetPtr);
403                ++iStreamIndex;
404            }
405        }
406    }
407
408    // ---- Output Swizzled
409    void LZParabixAioKernel::initPendingOutputScalar_Swizzled(const std::unique_ptr<KernelBuilder> &b) {
410        for (unsigned i = 0; i < (mNumsOfBitStreams[0] + 3) / 4; i++) {
411            this->addScalar(b->getBitBlockType(), "pendingOutput" + std::to_string(0) + "_" + std::to_string(i));
412        }
413    }
414    void LZParabixAioKernel::appendBitStreamOutput_Swizzled(const std::unique_ptr<KernelBuilder> &b, std::vector<llvm::Value*>& extractedValues, llvm::Value* valueLength) {
415
416        std::vector<llvm::Value*> extractedValuesVec;
417        for (unsigned i = 0; i < 2; i++) {
418            Value* vec = ConstantVector::getNullValue(b->getBitBlockType());
419            for (unsigned j = 0; j < 4; j++) {
420                vec = b->CreateInsertElement(vec, extractedValues[i * 4 + j], j);
421            }
422            extractedValuesVec.push_back(vec);
423        }
424
425        BasicBlock* exitBlock = b->CreateBasicBlock("exitBlock");
426
427        Value* oldOutputPos = b->getScalarField("outputPos");
428        Value* oldOutputPosRem64 = b->CreateURem(oldOutputPos, b->getSize(64));
429
430        std::vector<llvm::Value*> newOutputVec;
431        for (unsigned i = 0; i < 2; i++) {
432            Value* newValue = b->CreateOr(b->getScalarField("pendingOutput" + std::to_string(0) + "_" + std::to_string(i)), b->CreateShl(extractedValuesVec[i], b->simd_fill(64, oldOutputPosRem64)));
433            newOutputVec.push_back(newValue);
434        }
435
436
437        BasicBlock* noStoreOutputBlock = b->CreateBasicBlock("noStoreOutputBlock");
438        BasicBlock* storeOutputBlock =b->CreateBasicBlock("storeOutputBlock");
439
440        b->CreateCondBr(b->CreateICmpULT(b->CreateAdd(oldOutputPosRem64, valueLength), b->getSize(64)), noStoreOutputBlock, storeOutputBlock);
441
442        // ---- noStoreOutputBlock
443        b->SetInsertPoint(noStoreOutputBlock);
444        for (unsigned i = 0; i < 2; i++) {
445            b->setScalarField("pendingOutput" + std::to_string(0) + "_" + std::to_string(i), newOutputVec[i]);
446        }
447        b->CreateBr(exitBlock);
448
449        // ---- storeOutputBlock
450        b->SetInsertPoint(storeOutputBlock);
451
452        Value* oldOutputPosRem = b->CreateURem(oldOutputPos, b->getCapacity("outputStream0"));
453        Value* oldOutputPosBitBlockIndex = b->CreateUDiv(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
454        Value* oldOutputPosBitBlockRem = b->CreateURem(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
455
456        Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream0", b->getSize(0)), b->getBitBlockType()->getPointerTo());
457        Value* outputBitBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(oldOutputPosBitBlockIndex, b->getSize(8)));
458        outputBitBlockBasePtr = b->CreatePointerCast(outputBitBlockBasePtr, b->getInt64Ty()->getPointerTo());
459
460        Value* oldOutputPosI64Index = b->CreateUDiv(oldOutputPosBitBlockRem, b->getSize(64));
461
462        for (unsigned i = 0; i < 2; i++) {
463            for (unsigned j = 0; j < 4; j++) {
464                Value* targetPtr = b->CreateGEP(outputBitBlockBasePtr, b->CreateAdd(oldOutputPosI64Index, b->getSize((i * 4 + j) * 4)));
465                b->CreateStore(b->CreateExtractElement(newOutputVec[i], j), targetPtr);
466            }
467
468        }
469
470        Value* shiftAmount = b->CreateSub(b->getSize(0x40), oldOutputPosRem64);
471        Value* fullyShift = b->CreateICmpEQ(shiftAmount, b->getSize(0x40));
472
473        for (unsigned i = 0; i < 2; i++) {
474
475            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))));
476        }
477
478        b->CreateBr(exitBlock);
479
480        b->SetInsertPoint(exitBlock);
481        b->setScalarField("outputPos", b->CreateAdd(oldOutputPos, valueLength));
482
483    }
484
485    void LZParabixAioKernel::storePendingOutput_Swizzled(const std::unique_ptr<KernelBuilder> &b) {
486        Value* oldOutputPos = b->getScalarField("outputPos");
487        Value* oldOutputPosRem = b->CreateURem(oldOutputPos, b->getCapacity("outputStream0"));
488        Value* oldOutputPosBitBlockIndex = b->CreateUDiv(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
489        Value* oldOutputPosBitBlockRem = b->CreateURem(oldOutputPosRem, b->getSize(b->getBitBlockWidth()));
490
491        Value* oldOutputPosI64Index = b->CreateUDiv(oldOutputPosBitBlockRem, b->getSize(64));
492
493        Value* outputBasePtr = b->CreatePointerCast(b->getRawOutputPointer("outputStream0", b->getSize(0)), b->getBitBlockType()->getPointerTo());
494        Value* outputBitBlockBasePtr = b->CreateGEP(outputBasePtr, b->CreateMul(oldOutputPosBitBlockIndex, b->getSize(8)));
495        outputBitBlockBasePtr = b->CreatePointerCast(outputBitBlockBasePtr, b->getInt64Ty()->getPointerTo());
496
497        vector<Value*> pendingOutputVec;
498        for (unsigned i = 0; i < 2; i++) {
499            pendingOutputVec.push_back(b->getScalarField("pendingOutput" + std::to_string(0) + "_" + std::to_string(i)));
500        }
501
502        for (unsigned i = 0; i < 2; i++) {
503            for (unsigned j = 0; j < 2; j++) {
504                Value* targetPtr = b->CreateGEP(outputBitBlockBasePtr, b->CreateAdd(oldOutputPosI64Index, b->getSize((i * 4 + j) * 4)));
505                b->CreateStore(b->CreateExtractElement(pendingOutputVec[i], j), targetPtr);
506            }
507        }
508    }
509}
Note: See TracBrowser for help on using the repository browser.