source: icGREP/icgrep-devel/icgrep/kernels/lz4/lz4_block_decoder.cpp @ 6026

Last change on this file since 6026 was 6026, checked in by xwa163, 13 months ago
  1. Implement SwizzledMultiplePDEPkernel with the same logic as new PDEPkernel, remove LZ4MultiplePDEPkernel, improve the performance
  2. Remove some unnecessary include
  3. Add prefix for some kernels
  4. Remove a legacy kernel
File size: 7.6 KB
Line 
1
2
3#include "lz4_block_decoder.h"
4
5#include <kernels/kernel_builder.h>
6#include <iostream>
7#include <string>
8#include <llvm/Support/raw_ostream.h>
9#include <kernels/streamset.h>
10
11using namespace llvm;
12using namespace kernel;
13using namespace std;
14
15namespace kernel{
16
17LZ4BlockDecoderNewKernel::LZ4BlockDecoderNewKernel(const std::unique_ptr<kernel::KernelBuilder> &iBuilder, std::string&& kernelName)
18: SegmentOrientedKernel(std::string(kernelName),
19// Inputs
20{
21    Binding{iBuilder->getStreamSetTy(1, 8), "byteStream"},
22},
23//Outputs
24{
25    Binding{iBuilder->getStreamSetTy(1, 8), "isCompressed", BoundedRate(0, 1)},
26    Binding{iBuilder->getStreamSetTy(1, 64), "blockStart", RateEqualTo("isCompressed")},
27    Binding{iBuilder->getStreamSetTy(1, 64), "blockEnd", RateEqualTo("isCompressed")}},
28//Arguments
29{
30    Binding{iBuilder->getInt1Ty(), "hasBlockChecksum"},
31    Binding{iBuilder->getSizeTy(), "headerSize"},
32    Binding{iBuilder->getSizeTy(), "fileSize"}
33},
34{},
35//Internal states:
36{
37Binding{iBuilder->getInt1Ty(), "hasSkipHeader"},
38Binding{iBuilder->getSizeTy(), "previousOffset"},
39Binding{iBuilder->getInt1Ty(), "reachFinalBlock"},
40
41Binding{iBuilder->getInt1Ty(), "pendingIsCompressed"},
42Binding{iBuilder->getInt64Ty(), "pendingBlockStart"},
43Binding{iBuilder->getInt64Ty(), "pendingBlockEnd"},
44}) {
45
46}
47
48void LZ4BlockDecoderNewKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & iBuilder) {
49
50    Constant* INT64_0 = iBuilder->getInt64(0);
51
52    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
53
54    // Skip Header
55    Value* hasSkipHeader = iBuilder->getScalarField("hasSkipHeader");
56    iBuilder->setScalarField("hasSkipHeader", iBuilder->getTrue());
57    Value* skipLength = iBuilder->CreateSelect(hasSkipHeader, iBuilder->getSize(0), iBuilder->getScalarField("headerSize"));
58    Value* previousOffset = iBuilder->getScalarField("previousOffset");
59    previousOffset = iBuilder->CreateAdd(skipLength, previousOffset);
60    Value* initBlockStart = iBuilder->getScalarField("pendingBlockStart");
61    Value* initBlockEnd = iBuilder->getScalarField("pendingBlockEnd");
62    Value* initIsCompressed = iBuilder->getScalarField("pendingIsCompressed");
63    Value * availableItemCount = iBuilder->getAvailableItemCount("byteStream");
64    BasicBlock * processCon = iBuilder->CreateBasicBlock("process_con");
65    iBuilder->CreateBr(processCon);
66
67    iBuilder->SetInsertPoint(processCon);
68
69    PHINode* phiIsCompressed = iBuilder->CreatePHI(initIsCompressed->getType(), 3);
70    PHINode* phiBlockStart = iBuilder->CreatePHI(initBlockStart->getType(), 3);
71    PHINode* phiBlockEnd = iBuilder->CreatePHI(initBlockEnd->getType(), 3);
72    PHINode* sOffset = iBuilder->CreatePHI(previousOffset->getType(), 3);
73
74    phiIsCompressed->addIncoming(initIsCompressed, entryBlock);
75    phiBlockStart->addIncoming(initBlockStart, entryBlock);
76    phiBlockEnd->addIncoming(initBlockEnd, entryBlock);
77    sOffset->addIncoming(previousOffset, entryBlock);
78
79    // Store Output
80    BasicBlock* storeOutputBlock = iBuilder->CreateBasicBlock("storeOutputBlock");
81    BasicBlock * block_decoder_con = iBuilder->CreateBasicBlock("block_decoder_con_block");
82
83    iBuilder->CreateUnlikelyCondBr(
84            iBuilder->CreateAnd(
85                    iBuilder->CreateICmpULE(phiBlockEnd, availableItemCount),
86                    iBuilder->CreateNot(iBuilder->CreateICmpEQ(phiBlockEnd, INT64_0))
87            ),
88            storeOutputBlock,
89            block_decoder_con
90    );
91
92    iBuilder->SetInsertPoint(storeOutputBlock);
93
94    appendOutput(iBuilder, phiIsCompressed, phiBlockStart, phiBlockEnd);
95
96    phiIsCompressed->addIncoming(iBuilder->getFalse(), storeOutputBlock);
97    phiBlockStart->addIncoming(INT64_0, storeOutputBlock);
98    phiBlockEnd->addIncoming(INT64_0, storeOutputBlock);
99    sOffset->addIncoming(sOffset, storeOutputBlock);
100
101    iBuilder->CreateBr(processCon);
102
103
104    // block decoder entry
105    iBuilder->SetInsertPoint(block_decoder_con);
106
107    BasicBlock * block_decoder_body = iBuilder->CreateBasicBlock("block_decoder_body_block");
108    BasicBlock * block_decoder_exit = iBuilder->CreateBasicBlock("block_decoder_exit_block");
109
110    Value * reachFinalBlock = iBuilder->getScalarField("reachFinalBlock");
111    iBuilder->CreateCondBr(
112        iBuilder->CreateAnd(
113            iBuilder->CreateICmpULT(sOffset, availableItemCount),
114            iBuilder->CreateNot(reachFinalBlock)
115        ),
116        block_decoder_body,
117        block_decoder_exit);
118
119    //block_decoder_body
120    iBuilder->SetInsertPoint(block_decoder_body);
121    Value* currentBlockSize = iBuilder->getSize(0);
122    for (size_t i = 0; i < 4; i++) {
123        Value * offset = iBuilder->CreateAdd(sOffset, iBuilder->getSize(i));
124        Value * rawOffset = iBuilder->CreateZExt(generateLoadInput(iBuilder, offset), iBuilder->getSizeTy());
125        currentBlockSize = iBuilder->CreateOr(currentBlockSize, iBuilder->CreateShl(rawOffset, iBuilder->getSize(8 * i)));
126    }
127
128    Value * realBlockSize = iBuilder->CreateAnd(currentBlockSize, 0x7fffffff);
129
130    Value * isCompressed = iBuilder->CreateNot(currentBlockSize);
131    isCompressed = iBuilder->CreateLShr(isCompressed, 31);
132    isCompressed = iBuilder->CreateTrunc(isCompressed, iBuilder->getInt1Ty());
133
134    Value * isFinalBlock = iBuilder->CreateICmpEQ(realBlockSize, iBuilder->getSize(0));
135    iBuilder->setScalarField("reachFinalBlock", isFinalBlock);
136
137    Value * blockStart = iBuilder->CreateAdd(sOffset, iBuilder->getSize(4));
138    Value * blockEnd = iBuilder->CreateAdd(blockStart, realBlockSize);
139
140    Value * newOffset = sOffset;
141    newOffset = iBuilder->CreateAdd(newOffset, iBuilder->getSize(4)); // Block Size
142    newOffset = iBuilder->CreateAdd(newOffset, realBlockSize); // Block Content
143    Value * const blockChecksumOffset = iBuilder->CreateSelect(iBuilder->getScalarField("hasBlockChecksum"), iBuilder->getSize(4), iBuilder->getSize(0));
144    newOffset = iBuilder->CreateAdd(newOffset, blockChecksumOffset);
145
146    sOffset->addIncoming(newOffset, block_decoder_body);
147    phiIsCompressed->addIncoming(isCompressed, block_decoder_body);
148    phiBlockStart->addIncoming(blockStart, block_decoder_body);
149    phiBlockEnd->addIncoming(blockEnd, block_decoder_body);
150    iBuilder->CreateBr(processCon);
151
152    // block_decoder_exit_block
153    iBuilder->SetInsertPoint(block_decoder_exit);
154    iBuilder->setScalarField("pendingIsCompressed", phiIsCompressed);
155    iBuilder->setScalarField("pendingBlockStart", phiBlockStart);
156    iBuilder->setScalarField("pendingBlockEnd", phiBlockEnd);
157    iBuilder->setScalarField("previousOffset", sOffset);
158    iBuilder->setProcessedItemCount("byteStream", availableItemCount);
159    iBuilder->setTerminationSignal(mIsFinal);
160}
161
162void LZ4BlockDecoderNewKernel::appendOutput(const std::unique_ptr<KernelBuilder> & iBuilder, Value * const isCompressed, Value * const blockStart, Value * const blockEnd) {
163    Value * const offset = iBuilder->getProducedItemCount("isCompressed");
164    generateStoreNumberOutput(iBuilder, "isCompressed", offset, iBuilder->CreateZExt(isCompressed, iBuilder->getInt8Ty()));
165    generateStoreNumberOutput(iBuilder, "blockStart", offset, blockStart);
166    generateStoreNumberOutput(iBuilder, "blockEnd", offset, blockEnd);
167    iBuilder->setProducedItemCount("isCompressed", iBuilder->CreateAdd(offset, iBuilder->getSize(1)));
168}
169
170Value* LZ4BlockDecoderNewKernel::generateLoadInput(const std::unique_ptr<KernelBuilder> & iBuilder, llvm::Value* offset) {
171    return iBuilder->CreateLoad(iBuilder->getRawInputPointer("byteStream", offset));
172}
173
174void LZ4BlockDecoderNewKernel::generateStoreNumberOutput(const unique_ptr<KernelBuilder> &iBuilder, const string &outputBufferName, Value * offset, Value *value) {
175    iBuilder->CreateStore(value, iBuilder->getRawOutputPointer(outputBufferName, offset));
176}
177
178}
Note: See TracBrowser for help on using the repository browser.