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

Last change on this file since 6020 was 6020, checked in by xwa163, 15 months ago
  1. New version of lz4_swizzled_match_copy kernel with higher performance
  2. Adjust related pipeline code
  3. Remove legacy comments
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)
18: SegmentOrientedKernel("LZ4BlockDecoderNewKernel",
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.