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

Last change on this file since 5071 was 5071, checked in by cameron, 3 years ago

Update u8u16 to use new kernel infrastructure

File size: 8.5 KB
Line 
1#include "p2s_kernel.h"
2#include "kernels/kernel.h"
3#include "IDISA/idisa_builder.h"
4#include <llvm/IR/TypeBuilder.h>
5#include <llvm/IR/Type.h>
6#include <iostream>
7#include <stdint.h>
8#include <llvm/Support/FileSystem.h>
9#include <llvm/Support/raw_ostream.h>
10
11
12
13extern "C" {
14    void buffered_write(const char * ptr, size_t bytes) {
15        outs().write(ptr, bytes);
16    }
17};
18
19namespace kernel{
20       
21void p2s_step(IDISA::IDISA_Builder * iBuilder, Value * p0, Value * p1, Value * hi_mask, unsigned shift, Value * &s1, Value * &s0) {
22    Value * t0 = iBuilder->simd_if(1, hi_mask, p0, iBuilder->simd_srli(16, p1, shift));
23    Value * t1 = iBuilder->simd_if(1, hi_mask, iBuilder->simd_slli(16, p0, shift), p1);
24    s1 = iBuilder->esimd_mergeh(8, t1, t0);
25    s0 = iBuilder->esimd_mergel(8, t1, t0);
26}
27
28inline void p2s(IDISA::IDISA_Builder * iBuilder, Value * p[], Value * s[]) {
29    Value * bit00004444[2];
30    Value * bit22226666[2];
31    Value * bit11115555[2];
32    Value * bit33337777[2];
33    p2s_step(iBuilder, p[0], p[4], iBuilder->simd_himask(8), 4, bit00004444[1], bit00004444[0]);
34    p2s_step(iBuilder, p[1], p[5], iBuilder->simd_himask(8), 4, bit11115555[1], bit11115555[0]);
35    p2s_step(iBuilder, p[2], p[6], iBuilder->simd_himask(8), 4, bit22226666[1], bit22226666[0]);
36    p2s_step(iBuilder, p[3], p[7], iBuilder->simd_himask(8), 4, bit33337777[1], bit33337777[0]);
37
38    Value * bit00224466[4];
39    Value * bit11335577[4];
40    for (unsigned j = 0; j<2; j++) {
41        p2s_step(iBuilder, bit00004444[j], bit22226666[j],iBuilder->simd_himask(4), 2, bit00224466[2*j+1], bit00224466[2*j]);
42        p2s_step(iBuilder, bit11115555[j], bit33337777[j],iBuilder->simd_himask(4), 2, bit11335577[2*j+1], bit11335577[2*j]);
43    }
44    for (unsigned j = 0; j<4; j++) {
45        p2s_step(iBuilder, bit00224466[j], bit11335577[j], iBuilder->simd_himask(2), 1, s[2*j+1], s[2*j]);
46    }
47}
48               
49void p2sKernel::generateKernel() {
50    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
51    if (mKernelStateType == nullptr) finalizeKernelStateType();
52    KernelBuilder::generateKernel();
53
54    Module * m = iBuilder->getModule();
55    addTrivialFinalBlockMethod(m);
56    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
57   
58    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
59   
60    Value * basisBitsBlock_ptr = getParameter(doBlockFunction, "basisBits");  // input
61    Value * byteStreamBlock_ptr = getParameter(doBlockFunction, "byteStream"); // output
62    Value * p_bitblock[8];
63    for (unsigned i = 0; i < 8; i++) {
64        p_bitblock[i] = iBuilder->CreateBlockAlignedLoad(basisBitsBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(i)});
65    }
66    Value * s_bytepack[8];
67    p2s(iBuilder, p_bitblock, s_bytepack);
68    for (unsigned j = 0; j < 8; ++j) {
69        iBuilder->CreateBlockAlignedStore(s_bytepack[j], byteStreamBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(j)});
70    }
71    iBuilder->CreateRetVoid();
72    iBuilder->restoreIP(savePoint);
73}
74       
75void p2s_16Kernel::generateKernel() {
76    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
77    if (mKernelStateType == nullptr) finalizeKernelStateType();
78    KernelBuilder::generateKernel();
79
80    Module * m = iBuilder->getModule();
81    addTrivialFinalBlockMethod(m);
82    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
83   
84    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
85   
86    Value * basisBitsBlock_ptr = getParameter(doBlockFunction, "basisBits");  // input
87    Value * i16StreamBlock_ptr = getParameter(doBlockFunction, "i16Stream"); // output
88   
89    Value * hi_input[8];
90    for (unsigned j = 0; j < 8; ++j) {
91        hi_input[j] = iBuilder->CreateBlockAlignedLoad(basisBitsBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(j)});
92    }
93    Value * hi_bytes[8];
94    p2s(iBuilder, hi_input, hi_bytes);
95   
96    Value * lo_input[8];
97    for (unsigned j = 0; j < 8; ++j) {
98        lo_input[j] = iBuilder->CreateBlockAlignedLoad(basisBitsBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(j+8)});
99    }
100    Value * lo_bytes[8];
101    p2s(iBuilder, lo_input, lo_bytes);
102   
103    for (unsigned j = 0; j < 8; ++j) {
104        Value * merge0 = iBuilder->bitCast(iBuilder->esimd_mergel(8, hi_bytes[j], lo_bytes[j]));
105        Value * merge1 = iBuilder->bitCast(iBuilder->esimd_mergeh(8, hi_bytes[j], lo_bytes[j]));
106        iBuilder->CreateBlockAlignedStore(merge0, i16StreamBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(2*j)});
107        iBuilder->CreateBlockAlignedStore(merge1, i16StreamBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(2*j+1)});
108    }
109    iBuilder->CreateRetVoid();
110    iBuilder->restoreIP(savePoint);
111}
112       
113   
114Function * create_write(Module * const mod) {
115    Function * write = mod->getFunction("write");
116    if (write == nullptr) {
117        FunctionType *write_type =
118        TypeBuilder<long(int, char *, long), false>::get(mod->getContext());
119        write = cast<Function>(mod->getOrInsertFunction("write", write_type,
120                                                        AttributeSet().addAttribute(mod->getContext(), 2U, Attribute::NoAlias)));
121    }
122    return write;
123}
124
125const size_t OutputBufferSize=65536;
126
127void p2s_16Kernel_withCompressedOutputKernel::generateKernel() {
128    outs().SetBufferSize(OutputBufferSize);
129    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
130    if (mKernelStateType == nullptr) finalizeKernelStateType();
131    KernelBuilder::generateKernel();
132
133   
134    Module * m = iBuilder->getModule();
135    Type * i8PtrTy = iBuilder->getInt8PtrTy(); 
136    Type * i64 = iBuilder->getIntNTy(64); 
137    Type * bitBlockPtrTy = llvm::PointerType::get(iBuilder->getBitBlockType(), 0); 
138   
139    Function * writefn = cast<Function>(m->getOrInsertFunction("buffered_write", iBuilder->getVoidTy(), i8PtrTy, i64, nullptr));
140
141    addTrivialFinalBlockMethod(m);
142    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
143   
144    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
145   
146    Value * basisBitsBlock_ptr = getParameter(doBlockFunction, "basisBits");  // input
147    Value * delCountBlock_ptr = getParameter(doBlockFunction, "deletionCounts");
148    Value * i16StreamBlock_ptr = getParameter(doBlockFunction, "i16Stream"); // output
149
150    Value * hi_input[8];
151    for (unsigned j = 0; j < 8; ++j) {
152        hi_input[j] = iBuilder->CreateBlockAlignedLoad(basisBitsBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(j)});
153    }
154    Value * hi_bytes[8];
155    p2s(iBuilder, hi_input, hi_bytes);
156   
157    Value * lo_input[8];
158    for (unsigned j = 0; j < 8; ++j) {
159        lo_input[j] = iBuilder->CreateBlockAlignedLoad(basisBitsBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(j+8)});
160    }
161    Value * lo_bytes[8];
162    p2s(iBuilder, lo_input, lo_bytes);
163   
164    unsigned UTF_16_units_per_register = iBuilder->getBitBlockWidth()/16;
165   
166    Value * unit_counts = iBuilder->fwCast(UTF_16_units_per_register, iBuilder->CreateBlockAlignedLoad(delCountBlock_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(0)}));
167   
168    Value * u16_output_ptr = iBuilder->CreateBitCast(i16StreamBlock_ptr, PointerType::get(iBuilder->getInt16Ty(), 0));
169    Value * offset = ConstantInt::get(i64, 0);
170   
171    for (unsigned j = 0; j < 8; ++j) {
172        Value * merge0 = iBuilder->bitCast(iBuilder->esimd_mergel(8, hi_bytes[j], lo_bytes[j]));
173        Value * merge1 = iBuilder->bitCast(iBuilder->esimd_mergeh(8, hi_bytes[j], lo_bytes[j]));
174        //iBuilder->CallPrintRegister("merge0", merge0);
175        iBuilder->CreateAlignedStore(merge0, iBuilder->CreateBitCast(iBuilder->CreateGEP(u16_output_ptr, offset), bitBlockPtrTy), 1);
176        offset = iBuilder->CreateZExt(iBuilder->CreateExtractElement(unit_counts, iBuilder->getInt32(2*j)), i64);
177        //iBuilder->CallPrintInt("offset", offset);
178        iBuilder->CreateAlignedStore(merge1, iBuilder->CreateBitCast(iBuilder->CreateGEP(u16_output_ptr, offset), bitBlockPtrTy), 1);
179        //iBuilder->CallPrintRegister("merge1", merge1);
180        offset = iBuilder->CreateZExt(iBuilder->CreateExtractElement(unit_counts, iBuilder->getInt32(2*j+1)), i64);
181        //iBuilder->CallPrintInt("offset", offset);
182    }
183    Value * byte_offset = iBuilder->CreateAdd(offset, offset);
184    iBuilder->CreateCall(writefn, std::vector<Value *>({iBuilder->CreateBitCast(i16StreamBlock_ptr, i8PtrTy), byte_offset}));
185    iBuilder->CreateRetVoid();
186    iBuilder->restoreIP(savePoint);
187}
188       
189}
Note: See TracBrowser for help on using the repository browser.