source: icGREP/icgrep-devel/icgrep/kernels/p2s_kernel.cpp @ 5261

Last change on this file since 5261 was 5261, checked in by cameron, 9 months ago

Move responsibility for ProducedItemCount? into doSegment unless overridden

File size: 12.1 KB
Line 
1#include "p2s_kernel.h"
2#include "kernels/kernel.h"
3#include "IR_Gen/idisa_builder.h"
4#include <llvm/IR/Type.h>
5#include <llvm/IR/Module.h>
6#include <iostream>
7#include <stdint.h>
8#include <llvm/Support/FileSystem.h>
9#include <llvm/Support/raw_ostream.h>
10
11using namespace llvm;
12
13namespace kernel{
14       
15void p2s_step(IDISA::IDISA_Builder * iBuilder, Value * p0, Value * p1, Value * hi_mask, unsigned shift, Value * &s1, Value * &s0) {
16    Value * t0 = iBuilder->simd_if(1, hi_mask, p0, iBuilder->simd_srli(16, p1, shift));
17    Value * t1 = iBuilder->simd_if(1, hi_mask, iBuilder->simd_slli(16, p0, shift), p1);
18    s1 = iBuilder->esimd_mergeh(8, t1, t0);
19    s0 = iBuilder->esimd_mergel(8, t1, t0);
20}
21
22inline void p2s(IDISA::IDISA_Builder * iBuilder, Value * p[], Value * s[]) {
23    Value * bit00004444[2];
24    Value * bit22226666[2];
25    Value * bit11115555[2];
26    Value * bit33337777[2];
27    p2s_step(iBuilder, p[0], p[4], iBuilder->simd_himask(8), 4, bit00004444[1], bit00004444[0]);
28    p2s_step(iBuilder, p[1], p[5], iBuilder->simd_himask(8), 4, bit11115555[1], bit11115555[0]);
29    p2s_step(iBuilder, p[2], p[6], iBuilder->simd_himask(8), 4, bit22226666[1], bit22226666[0]);
30    p2s_step(iBuilder, p[3], p[7], iBuilder->simd_himask(8), 4, bit33337777[1], bit33337777[0]);
31
32    Value * bit00224466[4];
33    Value * bit11335577[4];
34    for (unsigned j = 0; j<2; j++) {
35        p2s_step(iBuilder, bit00004444[j], bit22226666[j],iBuilder->simd_himask(4), 2, bit00224466[2*j+1], bit00224466[2*j]);
36        p2s_step(iBuilder, bit11115555[j], bit33337777[j],iBuilder->simd_himask(4), 2, bit11335577[2*j+1], bit11335577[2*j]);
37    }
38    for (unsigned j = 0; j<4; j++) {
39        p2s_step(iBuilder, bit00224466[j], bit11335577[j], iBuilder->simd_himask(2), 1, s[2*j+1], s[2*j]);
40    }
41}
42               
43void P2SKernel::generateDoBlockMethod() const {
44    auto savePoint = iBuilder->saveIP();
45    Module * m = iBuilder->getModule();
46   
47    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
48   
49    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
50   
51    Value * self = getParameter(doBlockFunction, "self");
52    Value * blockNo = getScalarField(self, blockNoScalar);
53    Value * p_bitblock[8];
54    for (unsigned i = 0; i < 8; i++) {
55        Value * ptr = getStream(self, "basisBits", blockNo, iBuilder->getInt32(i));
56        p_bitblock[i] = iBuilder->CreateBlockAlignedLoad(ptr);
57    }
58    Value * s_bytepack[8];
59    p2s(iBuilder, p_bitblock, s_bytepack);
60    for (unsigned j = 0; j < 8; ++j) {
61        Value * ptr = getStream(self, "byteStream", blockNo, iBuilder->getInt32(0), iBuilder->getInt32(j));
62        iBuilder->CreateBlockAlignedStore(s_bytepack[j], ptr);
63    }
64    iBuilder->CreateRetVoid();
65    iBuilder->restoreIP(savePoint);
66}
67
68P2SKernel::P2SKernel(IDISA::IDISA_Builder * iBuilder) :
69    KernelBuilder(iBuilder, "p2s",
70                  {Binding{iBuilder->getStreamSetTy(8, 1), "basisBits"}},
71                  {Binding{iBuilder->getStreamSetTy(1, 8), "byteStream"}},
72                  {}, {}, {}) {
73
74    }
75   
76
77void P2SKernelWithCompressedOutput::generateDoBlockMethod() const {
78    auto savePoint = iBuilder->saveIP();
79    Module * m = iBuilder->getModule();
80    Type * i8PtrTy = iBuilder->getInt8PtrTy();
81    Type * i32 = iBuilder->getIntNTy(32);
82    Type * bitBlockPtrTy = llvm::PointerType::get(iBuilder->getBitBlockType(), 0);
83
84    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
85
86    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
87    Value * self = getParameter(doBlockFunction, "self");
88    Value * blockNo = getScalarField(self, blockNoScalar);
89
90
91
92    Value * basisBits[8];
93    for (unsigned i = 0; i < 8; i++) {
94        Value * basisBitsBlock_ptr = getStream(self, "basisBits", blockNo, iBuilder->getInt32(i));
95        basisBits[i] = iBuilder->CreateBlockAlignedLoad(basisBitsBlock_ptr);
96    }
97    Value * bytePack[8];
98    p2s(iBuilder, basisBits, bytePack);
99
100    unsigned units_per_register = iBuilder->getBitBlockWidth()/8;
101    Value * delCountBlock_ptr = getStream(self, "deletionCounts", blockNo, iBuilder->getInt32(0));
102    Value * unit_counts = iBuilder->fwCast(units_per_register, iBuilder->CreateBlockAlignedLoad(delCountBlock_ptr));
103
104    Value * unitsGenerated = getProducedItemCount(self, "byteStream"); // units generated to buffer
105    Value * output_ptr = getStreamView(i8PtrTy, self, "byteStream", blockNo, iBuilder->getInt32(0));
106    Value * offset = iBuilder->getInt32(0);
107    for (unsigned j = 0; j < 8; ++j) {
108        iBuilder->CreateAlignedStore(bytePack[j], iBuilder->CreateBitCast(iBuilder->CreateGEP(output_ptr, offset), bitBlockPtrTy), 1);
109        offset = iBuilder->CreateZExt(iBuilder->CreateExtractElement(unit_counts, iBuilder->getInt32(j)), i32);
110    }
111    unitsGenerated = iBuilder->CreateAdd(unitsGenerated, iBuilder->CreateZExt(offset, iBuilder->getSizeTy()));
112    setProducedItemCount(self, "byteStream", unitsGenerated);
113
114    iBuilder->CreateRetVoid();
115    iBuilder->restoreIP(savePoint);
116}
117   
118P2SKernelWithCompressedOutput::P2SKernelWithCompressedOutput(IDISA::IDISA_Builder * iBuilder) :
119    KernelBuilder(iBuilder, "p2s_compress",
120                  {Binding{iBuilder->getStreamSetTy(8, 1), "basisBits"}, Binding{iBuilder->getStreamSetTy(1, 1), "deletionCounts"}},
121                  {Binding{iBuilder->getStreamSetTy(1, 8), "byteStream"}},
122                  {}, {}, {}) {
123        setDoBlockUpdatesProducedItemCountsAttribute(true);
124
125    }
126   
127   
128
129void P2S16Kernel::generateDoBlockMethod() const {
130    auto savePoint = iBuilder->saveIP();
131    Module * m = iBuilder->getModule();
132   
133    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
134   
135    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
136    Value * self = getParameter(doBlockFunction, "self");
137    Value * blockNo = getScalarField(self, blockNoScalar);   
138   
139    Value * hi_input[8];
140    for (unsigned j = 0; j < 8; ++j) {
141        Value * ptr = getStream(self, "basisBits", blockNo, iBuilder->getInt32(0), iBuilder->getInt32(j));
142        hi_input[j] = iBuilder->CreateBlockAlignedLoad(ptr);
143    }
144    Value * hi_bytes[8];
145    p2s(iBuilder, hi_input, hi_bytes);
146   
147    Value * lo_input[8];
148    for (unsigned j = 0; j < 8; ++j) {
149        Value * ptr = getStream(self, "basisBits", blockNo, iBuilder->getInt32(0), iBuilder->getInt32(j + 8));
150        lo_input[j] = iBuilder->CreateBlockAlignedLoad(ptr);
151    }
152    Value * lo_bytes[8];
153    p2s(iBuilder, lo_input, lo_bytes);
154   
155    for (unsigned j = 0; j < 8; ++j) {
156        Value * merge0 = iBuilder->bitCast(iBuilder->esimd_mergel(8, hi_bytes[j], lo_bytes[j]));
157        Value * merge1 = iBuilder->bitCast(iBuilder->esimd_mergeh(8, hi_bytes[j], lo_bytes[j]));
158        Value * ptr0 = getStream(self, "i16Stream", blockNo, iBuilder->getInt32(2 * j));
159        iBuilder->CreateBlockAlignedStore(merge0, ptr0);
160        Value * ptr1 = getStream(self, "i16Stream", blockNo, iBuilder->getInt32(2 * j + 1));
161        iBuilder->CreateBlockAlignedStore(merge1, ptr1);
162    }
163    iBuilder->CreateRetVoid();
164    iBuilder->restoreIP(savePoint);
165}
166   
167
168P2S16Kernel::P2S16Kernel(IDISA::IDISA_Builder * iBuilder) :
169    KernelBuilder(iBuilder, "p2s_16",
170                  {Binding{iBuilder->getStreamSetTy(16, 1), "basisBits"}},
171                  {Binding{iBuilder->getStreamSetTy(1, 16), "i16Stream"}},
172                  {}, {}, {}) {
173       
174    }
175
176   
177void P2S16KernelWithCompressedOutput::generateDoBlockMethod() const {
178    auto savePoint = iBuilder->saveIP();
179    Module * m = iBuilder->getModule();
180    Type * i32 = iBuilder->getIntNTy(32);
181    Type * bitBlockPtrTy = llvm::PointerType::get(iBuilder->getBitBlockType(), 0);
182
183    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
184
185    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
186
187    Value * self = getParameter(doBlockFunction, "self");
188    Value * blockNo = getScalarField(self, blockNoScalar);
189
190    Value * hi_input[8];
191    for (unsigned j = 0; j < 8; ++j) {
192        Value * ptr = getStream(self, "basisBits", blockNo, iBuilder->getInt32(j));
193        hi_input[j] = iBuilder->CreateBlockAlignedLoad(ptr);
194    }
195    Value * hi_bytes[8];
196    p2s(iBuilder, hi_input, hi_bytes);
197
198    Value * lo_input[8];
199    for (unsigned j = 0; j < 8; ++j) {
200        Value * ptr = getStream(self, "basisBits", blockNo, iBuilder->getInt32(j + 8));
201        lo_input[j] = iBuilder->CreateBlockAlignedLoad(ptr);
202    }
203    Value * lo_bytes[8];
204    p2s(iBuilder, lo_input, lo_bytes);
205
206    Value * delCountBlock_ptr = getStream(self, "deletionCounts", blockNo, iBuilder->getInt32(0));
207    Value * unit_counts = iBuilder->fwCast(iBuilder->getBitBlockWidth() / 16, iBuilder->CreateBlockAlignedLoad(delCountBlock_ptr));
208
209    PointerType * int16PtrTy = PointerType::get(iBuilder->getInt16Ty(), 0);
210    ConstantInt * stride = iBuilder->getSize(iBuilder->getStride());
211    Value * i16UnitsGenerated = getProducedItemCount(self, "i16Stream"); // units generated to buffer
212    Value * i16BlockNo = iBuilder->CreateUDiv(i16UnitsGenerated, stride);
213    Value * u16_output_ptr = getStreamView(int16PtrTy, self, "i16Stream", i16BlockNo, iBuilder->CreateURem(i16UnitsGenerated, stride));
214    Value * offset = ConstantInt::get(i32, 0);
215    for (unsigned j = 0; j < 8; ++j) {
216        Value * merge0 = iBuilder->bitCast(iBuilder->esimd_mergel(8, hi_bytes[j], lo_bytes[j]));
217        Value * merge1 = iBuilder->bitCast(iBuilder->esimd_mergeh(8, hi_bytes[j], lo_bytes[j]));
218        iBuilder->CreateAlignedStore(merge0, iBuilder->CreateBitCast(iBuilder->CreateGEP(u16_output_ptr, offset), bitBlockPtrTy), 1);
219        offset = iBuilder->CreateZExt(iBuilder->CreateExtractElement(unit_counts, iBuilder->getInt32(2 * j)), i32);
220        iBuilder->CreateAlignedStore(merge1, iBuilder->CreateBitCast(iBuilder->CreateGEP(u16_output_ptr, offset), bitBlockPtrTy), 1);
221        offset = iBuilder->CreateZExt(iBuilder->CreateExtractElement(unit_counts, iBuilder->getInt32(2 * j + 1)), i32);
222    }
223    i16UnitsGenerated = iBuilder->CreateAdd(i16UnitsGenerated, iBuilder->CreateZExt(offset, iBuilder->getSizeTy()));
224    setProducedItemCount(self, "i16Stream", i16UnitsGenerated);
225    iBuilder->CreateRetVoid();
226    iBuilder->restoreIP(savePoint);
227}
228
229void P2S16KernelWithCompressedOutput::generateFinalBlockMethod() const {
230    auto savePoint = iBuilder->saveIP();
231    Module * m = iBuilder->getModule();
232    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
233    Function * finalBlockFunction = m->getFunction(mKernelName + finalBlock_suffix);
234    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "fb_entry", finalBlockFunction, 0));
235    // Final Block arguments: self, remaining, then the standard DoBlock args.
236    Function::arg_iterator args = finalBlockFunction->arg_begin();
237    Value * self = &*(args++);
238    /* Skip "remaining" arg */ args++;
239    std::vector<Value *> doBlockArgs = {self};
240    while (args != finalBlockFunction->arg_end()){
241        doBlockArgs.push_back(&*args++);
242    }
243    Value * i16UnitsGenerated = getProducedItemCount(self, "i16Stream"); // units generated to buffer
244    iBuilder->CreateCall(doBlockFunction, doBlockArgs);
245    i16UnitsGenerated = getProducedItemCount(self, "i16Stream"); // units generated to buffer
246    for (unsigned i = 0; i < mStreamSetOutputs.size(); i++) {
247        Value * ssStructPtr = getStreamSetStructPtr(self, mStreamSetOutputs[i].name);
248        Value * producerPosPtr = mStreamSetOutputBuffers[i]->getProducerPosPtr(ssStructPtr);
249        iBuilder->CreateAtomicStoreRelease(i16UnitsGenerated, producerPosPtr);
250    }
251    iBuilder->CreateRetVoid();
252    iBuilder->restoreIP(savePoint);
253}
254   
255P2S16KernelWithCompressedOutput::P2S16KernelWithCompressedOutput(IDISA::IDISA_Builder * iBuilder) :
256    KernelBuilder(iBuilder, "p2s_16_compress",
257                  {Binding{iBuilder->getStreamSetTy(16, 1), "basisBits"}, Binding{iBuilder->getStreamSetTy(1, 1), "deletionCounts"}},
258                  {Binding{iBuilder->getStreamSetTy(1, 16), "i16Stream"}},
259                  {},
260                  {},
261                  {Binding{iBuilder->getSizeTy(), "unitsGenerated"}, Binding{iBuilder->getSizeTy(), "unitsWritten"}}) {
262        setDoBlockUpdatesProducedItemCountsAttribute(true);
263}
264   
265   
266}
Note: See TracBrowser for help on using the repository browser.