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

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

Init check in for new compression format (lzparabix) related kernels and pipelines, including compressor, decoder and grep

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