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

Last change on this file since 5984 was 5984, checked in by nmedfort, 6 months ago

Made lz4 block decoder a segment oriented kernel; cleaned up processing rates.

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