source: icGREP/icgrep-devel/icgrep/kernels/source_kernel.cpp @ 6133

Last change on this file since 6133 was 6067, checked in by cameron, 12 months ago

Source kernels bug fix: size/items calculations when codeUnitSize != 8

File size: 22.4 KB
Line 
1/*
2 *  Copyright (c) 2018 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5#include "source_kernel.h"
6#include <kernels/kernel_builder.h>
7#include <kernels/streamset.h>
8#include <llvm/IR/Module.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <toolchain/toolchain.h>
12
13using namespace llvm;
14
15extern "C" uint64_t file_size(const uint32_t fd) {
16    struct stat st;
17    if (LLVM_UNLIKELY(fstat(fd, &st) != 0)) {
18        st.st_size = 0;
19    }
20    return st.st_size;
21}
22
23namespace kernel {
24
25/// MMAP SOURCE KERNEL
26
27Function * MMapSourceKernel::linkFileSizeMethod(const std::unique_ptr<kernel::KernelBuilder> & b) {
28    return b->LinkFunction("file_size", &file_size);
29}
30
31void MMapSourceKernel::generateInitializeMethod(Function * const fileSizeMethod, const unsigned codeUnitWidth, const std::unique_ptr<KernelBuilder> & b) {
32
33    BasicBlock * const emptyFile = b->CreateBasicBlock("emptyFile");
34    BasicBlock * const nonEmptyFile = b->CreateBasicBlock("NonEmptyFile");
35    BasicBlock * const exit = b->CreateBasicBlock("Exit");
36    IntegerType * const sizeTy = b->getSizeTy();
37    ConstantInt * const PAGE_SIZE = b->getSize(getpagesize());
38    Constant * const PAGE_ITEMS = b->getSize(getpagesize()/(codeUnitWidth/8));
39    Value * const fd = b->getScalarField("fileDescriptor");
40    assert (fileSizeMethod);
41    Value * fileSize = b->CreateZExtOrTrunc(b->CreateCall(fileSizeMethod, fd), sizeTy);
42    b->CreateLikelyCondBr(b->CreateIsNotNull(fileSize), nonEmptyFile, emptyFile);
43
44    b->SetInsertPoint(nonEmptyFile);
45    PointerType * const codeUnitPtrTy = b->getIntNTy(codeUnitWidth)->getPointerTo();
46    Value * const fileBuffer = b->CreatePointerCast(b->CreateFileSourceMMap(fd, fileSize), codeUnitPtrTy);
47    b->setScalarField("buffer", fileBuffer);
48    b->setBaseAddress("sourceBuffer", fileBuffer);
49    b->CreateMAdvise(fileBuffer, fileSize, CBuilder::ADVICE_WILLNEED);
50    Value * fileItems = fileSize;
51    if (LLVM_UNLIKELY(codeUnitWidth > 8)) {
52        fileItems = b->CreateUDiv(fileSize, b->getSize(codeUnitWidth / 8));
53    }
54    b->setScalarField("fileItems", fileItems);
55    b->CreateBr(exit);
56
57    b->SetInsertPoint(emptyFile);
58    Value * const emptyFilePtr = b->CreatePointerCast(b->CreateAnonymousMMap(PAGE_SIZE), codeUnitPtrTy);
59    b->setScalarField("buffer", emptyFilePtr);
60    b->setBaseAddress("sourceBuffer", emptyFilePtr);
61    b->setScalarField("fileItems", PAGE_ITEMS);
62    b->setTerminationSignal();
63    b->CreateBr(exit);
64
65    b->SetInsertPoint(exit);
66}
67
68
69void MMapSourceKernel::generateDoSegmentMethod(const unsigned codeUnitWidth, const std::unique_ptr<KernelBuilder> & b) {
70
71    BasicBlock * const dropPages = b->CreateBasicBlock("dropPages");
72    BasicBlock * const checkRemaining = b->CreateBasicBlock("checkRemaining");
73    BasicBlock * const setTermination = b->CreateBasicBlock("setTermination");
74    BasicBlock * const exit = b->CreateBasicBlock("mmapSourceExit");
75
76    Constant * const PAGE_SIZE = b->getSize(getpagesize());
77    Constant * const PAGE_ITEMS = b->getSize(getpagesize()/(codeUnitWidth/8));
78    Constant * const BLOCK_WIDTH = b->getSize(b->getBitBlockWidth());
79    Constant * const CODE_UNIT_BYTES = b->getSize(codeUnitWidth / 8);
80
81    Value * const fileItems = b->getScalarField("fileItems");
82    Value * const consumedItems = b->getConsumedItemCount("sourceBuffer");
83    Value * const consumedBytes = b->CreateMul(consumedItems, CODE_UNIT_BYTES);
84    Value * const consumedPageOffset = b->CreateAnd(consumedBytes, ConstantExpr::getNeg(PAGE_SIZE));
85    Value * const consumedBuffer = b->getRawOutputPointer("sourceBuffer", consumedPageOffset);
86    Value * const readableBuffer = b->getScalarField("buffer");
87    Value * const unnecessaryBytes = b->CreatePtrDiff(consumedBuffer, readableBuffer);
88
89    // avoid calling madvise unless an actual page table change could occur
90    b->CreateLikelyCondBr(b->CreateIsNotNull(unnecessaryBytes), dropPages, checkRemaining);
91
92    b->SetInsertPoint(dropPages);
93    // instruct the OS that it can safely drop any fully consumed pages
94    b->CreateMAdvise(readableBuffer, unnecessaryBytes, CBuilder::ADVICE_DONTNEED);
95    b->setScalarField("buffer", b->CreateGEP(readableBuffer, unnecessaryBytes));
96    b->CreateBr(checkRemaining);
97
98    // determine whether or not we've exhausted the file buffer
99    b->SetInsertPoint(checkRemaining);
100    Value * const producedItems = b->getProducedItemCount("sourceBuffer");
101    Value * const nextProducedItems = b->CreateAdd(producedItems, PAGE_ITEMS);
102    Value * const lastPage = b->CreateICmpULE(fileItems, nextProducedItems);
103    b->CreateUnlikelyCondBr(lastPage, setTermination, exit);
104
105    // If this is the last page, create a temporary buffer of up to two pages size, copy the unconsumed data
106    // and zero any bytes that are not used.
107    b->SetInsertPoint(setTermination);
108    Value * const consumedOffset = b->CreateAnd(consumedItems, ConstantExpr::getNeg(BLOCK_WIDTH));
109    Value * const readStart = b->getRawOutputPointer("sourceBuffer", consumedOffset);
110    Value * const readEnd = b->getRawOutputPointer("sourceBuffer", fileItems);
111    Value * unconsumedBytes = b->CreateTrunc(b->CreatePtrDiff(readEnd, readStart), b->getSizeTy());
112    if (LLVM_UNLIKELY(codeUnitWidth > 8)) {
113        unconsumedBytes = b->CreateMul(unconsumedBytes, CODE_UNIT_BYTES);
114    }
115    Value * const bufferSize = b->CreateRoundUp(b->CreateAdd(unconsumedBytes, BLOCK_WIDTH), PAGE_SIZE);
116    Value * const buffer = b->CreateAlignedMalloc(bufferSize, b->getCacheAlignment());
117    b->CreateMemCpy(buffer, readStart, unconsumedBytes, 1);
118    b->CreateMemZero(b->CreateGEP(buffer, unconsumedBytes), b->CreateSub(bufferSize, unconsumedBytes), 1);
119    // get the difference between our base and from position then compute an offsetted temporary buffer address
120    Value * const base = b->getBaseAddress("sourceBuffer");
121    Value * const diff = b->CreatePtrDiff(b->CreatePointerCast(base, readStart->getType()), readStart);
122    Value * const offsettedBuffer = b->CreateGEP(buffer, diff);
123    b->CreateConsumerWait();
124    // Unmap the file buffer and set the temporary buffer as the new source buffer
125    Value * const fileSize = b->CreateMul(fileItems, CODE_UNIT_BYTES);
126    b->CreateMUnmap(base, fileSize);
127    PointerType * const codeUnitPtrTy = b->getIntNTy(codeUnitWidth)->getPointerTo();
128    b->setScalarField("buffer", b->CreatePointerCast(buffer, codeUnitPtrTy));
129    b->setBaseAddress("sourceBuffer", b->CreatePointerCast(offsettedBuffer, codeUnitPtrTy));
130    b->setTerminationSignal();
131    BasicBlock * const terminationExit = b->GetInsertBlock();
132    b->CreateBr(exit);
133
134    // finally, set the "produced" count to reflect current position in the file
135    b->SetInsertPoint(exit);
136    PHINode * const newProducedItems = b->CreatePHI(b->getSizeTy(), 2);
137    newProducedItems->addIncoming(nextProducedItems, checkRemaining);
138    newProducedItems->addIncoming(fileItems, terminationExit);
139    b->setProducedItemCount("sourceBuffer", newProducedItems);
140}
141
142void MMapSourceKernel::freeBuffer(const std::unique_ptr<KernelBuilder> & b) {
143    b->CreateFree(b->getScalarField("buffer"));
144}
145
146/// READ SOURCE KERNEL
147
148void ReadSourceKernel::generateInitializeMethod(const unsigned codeUnitWidth, const std::unique_ptr<KernelBuilder> & b) {
149    const unsigned pageSize = getpagesize();
150    ConstantInt * const bufferItems = b->getSize(pageSize * 4);
151    const auto codeUnitSize = codeUnitWidth / 8;
152    ConstantInt * const bufferBytes = b->getSize(pageSize * 4 * codeUnitSize);
153    PointerType * const codeUnitPtrTy = b->getIntNTy(codeUnitWidth)->getPointerTo();
154    Value * const buffer = b->CreatePointerCast(b->CreateCacheAlignedMalloc(bufferBytes), codeUnitPtrTy);
155    b->setBaseAddress("sourceBuffer", buffer);
156    b->setScalarField("buffer", buffer);
157    b->setCapacity("sourceBuffer", bufferItems);
158}
159
160void ReadSourceKernel::generateDoSegmentMethod(const unsigned codeUnitWidth, const std::unique_ptr<KernelBuilder> & b) {
161
162    const unsigned pageSize = getpagesize();
163    ConstantInt * const itemsToRead = b->getSize(pageSize);
164    ConstantInt * const codeUnitBytes = b->getSize(codeUnitWidth / 8);
165
166    BasicBlock * const moveData = b->CreateBasicBlock("MoveData");
167    BasicBlock * const prepareBuffer = b->CreateBasicBlock("PrepareBuffer");
168    BasicBlock * const readData = b->CreateBasicBlock("ReadData");
169    BasicBlock * const setTermination = b->CreateBasicBlock("SetTermination");
170    BasicBlock * const readExit = b->CreateBasicBlock("ReadExit");
171
172    // Do we have enough unread data to support one segment?
173    Value * const produced = b->getProducedItemCount("sourceBuffer");
174    Value * const itemsPending = b->CreateAdd(produced, itemsToRead);
175
176    // Can we append to our existing buffer without impacting any subsequent kernel?
177    Value * const capacity = b->getCapacity("sourceBuffer");
178    Value * const readEnd = b->getRawOutputPointer("sourceBuffer", itemsPending);
179    Value * const baseBuffer = b->getScalarField("buffer");
180    Value * const bufferLimit = b->CreateGEP(baseBuffer, capacity);
181    b->CreateLikelyCondBr(b->CreateICmpULE(readEnd, bufferLimit), readData, moveData);
182
183    // First wait on any consumers to finish processing then check how much data has been consumed.
184    b->SetInsertPoint(moveData);
185    b->CreateConsumerWait();
186
187    // Then determine how much data has been consumed and how much needs to be copied back, noting
188    // that our "unproduced" data must be block aligned.
189    BasicBlock * const copyBack = b->CreateBasicBlock("CopyBack");
190    BasicBlock * const expandAndCopyBack = b->CreateBasicBlock("ExpandAndCopyBack");
191
192    const auto blockSize = b->getBitBlockWidth() / 8;
193    Constant * const blockSizeAlignmentMask = ConstantExpr::getNeg(b->getSize(blockSize));
194    Value * const consumed = b->getConsumedItemCount("sourceBuffer");
195    Value * const offset = b->CreateAnd(consumed, blockSizeAlignmentMask);
196    Value * const unreadData = b->getRawOutputPointer("sourceBuffer", offset);
197    Value * const remainingItems = b->CreateSub(produced, offset);
198    Value * const remainingBytes = b->CreateMul(remainingItems, codeUnitBytes);
199
200    // Have we consumed enough data that we can safely copy back the unconsumed data without needing a temporary buffer?
201    Value * const canCopy = b->CreateICmpULT(b->CreateGEP(baseBuffer, remainingItems), b->getRawOutputPointer("sourceBuffer", offset));
202    b->CreateLikelyCondBr(canCopy, copyBack, expandAndCopyBack);
203
204    // If so, just copy the data ...
205    b->SetInsertPoint(copyBack);
206    b->CreateMemCpy(baseBuffer, unreadData, remainingBytes, blockSize);
207    b->CreateBr(prepareBuffer);
208
209    // Otherwise, allocate a buffer with twice the capacity and copy the unconsumed data back into it
210    b->SetInsertPoint(expandAndCopyBack);
211    Value * const expandedCapacity = b->CreateShl(capacity, 1);
212    Value * const expandedBytes = b->CreateMul(expandedCapacity, codeUnitBytes);
213    Value * const expandedBuffer = b->CreatePointerCast(b->CreateCacheAlignedMalloc(expandedBytes), unreadData->getType());
214    b->CreateMemCpy(expandedBuffer, unreadData, remainingBytes, blockSize);
215    b->setScalarField("buffer", expandedBuffer);
216    b->setCapacity("sourceBuffer", expandedCapacity);
217    b->CreateFree(baseBuffer);
218    b->CreateBr(prepareBuffer);
219
220    b->SetInsertPoint(prepareBuffer);
221    PHINode * const newBaseBuffer = b->CreatePHI(baseBuffer->getType(), 2);
222    newBaseBuffer->addIncoming(baseBuffer, copyBack);
223    newBaseBuffer->addIncoming(expandedBuffer, expandAndCopyBack);
224    b->setBaseAddress("sourceBuffer", b->CreateGEP(newBaseBuffer, b->CreateNeg(offset)));
225    b->CreateBr(readData);
226
227    // Regardless of whether we're simply appending data or had to allocate a new buffer, read a new page
228    // of data into the input source buffer. If we fail to read a full page ...
229    b->SetInsertPoint(readData);
230    Value * const sourceBuffer = b->getRawOutputPointer("sourceBuffer", produced);
231    Value * const fd = b->getScalarField("fileDescriptor");
232    Constant * const bytesToRead = ConstantExpr::getMul(itemsToRead, codeUnitBytes);
233    Value * const bytesRead = b->CreateReadCall(fd, sourceBuffer, bytesToRead);
234    Value * const itemsRead = b->CreateUDiv(bytesRead, codeUnitBytes);
235    Value * const itemsBuffered = b->CreateAdd(produced, itemsRead);
236    b->CreateUnlikelyCondBr(b->CreateICmpULT(itemsBuffered, itemsPending), setTermination, readExit);
237
238    // ... set the termination signal.
239    b->SetInsertPoint(setTermination);
240    Value * const bytesToZero = b->CreateMul(b->CreateSub(itemsPending, itemsBuffered), codeUnitBytes);
241    b->CreateMemZero(b->getRawOutputPointer("sourceBuffer", itemsBuffered), bytesToZero);
242    b->setTerminationSignal();
243    b->CreateBr(readExit);
244
245    b->SetInsertPoint(readExit);
246    PHINode * const itemsProduced = b->CreatePHI(itemsPending->getType(), 2);
247    itemsProduced->addIncoming(itemsPending, readData);
248    itemsProduced->addIncoming(itemsBuffered, setTermination);
249    b->setProducedItemCount("sourceBuffer", itemsProduced);
250}
251
252void ReadSourceKernel::freeBuffer(const std::unique_ptr<KernelBuilder> & b) {
253    b->CreateFree(b->getScalarField("buffer"));
254}
255
256/// Hybrid MMap/Read source kernel
257
258void FDSourceKernel::linkExternalMethods(const std::unique_ptr<kernel::KernelBuilder> & b) {
259    mFileSizeFunction = MMapSourceKernel::linkFileSizeMethod(b);
260}
261
262void FDSourceKernel::generateFinalizeMethod(const std::unique_ptr<KernelBuilder> & b) {
263    BasicBlock * finalizeRead = b->CreateBasicBlock("finalizeRead");
264    BasicBlock * finalizeMMap = b->CreateBasicBlock("finalizeMMap");
265    BasicBlock * finalizeDone = b->CreateBasicBlock("finalizeDone");
266    b->CreateCondBr(b->CreateTrunc(b->getScalarField("useMMap"), b->getInt1Ty()), finalizeMMap, finalizeRead);
267    b->SetInsertPoint(finalizeMMap);
268    MMapSourceKernel::freeBuffer(b);
269    b->CreateBr(finalizeDone);
270    b->SetInsertPoint(finalizeRead);
271    ReadSourceKernel::freeBuffer(b);
272    b->CreateBr(finalizeDone);
273    b->SetInsertPoint(finalizeDone);
274}
275
276void FDSourceKernel::generateInitializeMethod(const std::unique_ptr<KernelBuilder> & b) {
277    BasicBlock * initializeRead = b->CreateBasicBlock("initializeRead");
278    BasicBlock * tryMMap = b->CreateBasicBlock("tryMMap");
279    BasicBlock * initializeMMap = b->CreateBasicBlock("initializeMMap");
280    BasicBlock * initializeDone = b->CreateBasicBlock("initializeDone");
281
282    // The source will use MMapSource or readSoure kernel logic depending on the useMMap
283    // parameter, possibly overridden.
284    Value * useMMap = b->CreateTrunc(b->getScalarField("useMMap"), b->getInt1Ty());
285    // if the fileDescriptor is 0, the file is stdin, use readSource kernel logic.
286    Value * fd = b->getScalarField("fileDescriptor");
287    useMMap = b->CreateAnd(useMMap, b->CreateICmpNE(fd, b->getInt32(STDIN_FILENO)));
288    b->CreateCondBr(useMMap, tryMMap, initializeRead);
289
290    b->SetInsertPoint(tryMMap);
291    // If the fileSize is 0, we may have a virtual file such as /proc/cpuinfo
292    Value * fileSize = b->CreateZExtOrTrunc(b->CreateCall(mFileSizeFunction, fd), b->getSizeTy());
293    useMMap = b->CreateICmpNE(fileSize, b->getSize(0));
294    b->CreateCondBr(useMMap, initializeMMap, initializeRead);
295    b->SetInsertPoint(initializeMMap);
296    MMapSourceKernel::generateInitializeMethod(mFileSizeFunction, mCodeUnitWidth, b);
297    b->CreateBr(initializeDone);
298
299    b->SetInsertPoint(initializeRead);
300    // Ensure that readSource logic is used throughout.
301    b->setScalarField("useMMap", b->getInt8(0));
302    ReadSourceKernel::generateInitializeMethod(mCodeUnitWidth,b);
303    b->CreateBr(initializeDone);
304    b->SetInsertPoint(initializeDone);
305}
306
307void FDSourceKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & b) {
308    BasicBlock * DoSegmentRead = b->CreateBasicBlock("DoSegmentRead");
309    BasicBlock * DoSegmentMMap = b->CreateBasicBlock("DoSegmentMMap");
310    BasicBlock * DoSegmentDone = b->CreateBasicBlock("DoSegmentDone");
311    b->CreateCondBr(b->CreateTrunc(b->getScalarField("useMMap"), b->getInt1Ty()), DoSegmentMMap, DoSegmentRead);
312    b->SetInsertPoint(DoSegmentMMap);
313    MMapSourceKernel::generateDoSegmentMethod(mCodeUnitWidth, b);
314    b->CreateBr(DoSegmentDone);
315    b->SetInsertPoint(DoSegmentRead);
316    ReadSourceKernel::generateDoSegmentMethod(mCodeUnitWidth, b);
317    b->CreateBr(DoSegmentDone);
318    b->SetInsertPoint(DoSegmentDone);
319}
320
321/// MEMORY SOURCE KERNEL
322
323void MemorySourceKernel::generateInitializeMethod(const std::unique_ptr<KernelBuilder> & b) {
324    Value * const fileSource = b->getScalarField("fileSource");
325    b->setBaseAddress("sourceBuffer", fileSource);
326    Value * const fileItems = b->getScalarField("fileItems");
327    b->setCapacity("sourceBuffer", fileItems);
328    if (mStreamSetCount > 1) {
329        b->setProducedItemCount("sourceBuffer", fileItems);
330        b->setTerminationSignal();
331    }
332}
333
334void MemorySourceKernel::generateDoSegmentMethod(const std::unique_ptr<KernelBuilder> & b) {
335    if (mStreamSetCount == 1) {
336        Constant * const PAGE_SIZE = b->getSize(getStride());
337        Constant * const PAGE_ITEMS = b->getSize(getStride()/(mCodeUnitWidth/8));
338        Constant * const BLOCK_WIDTH = b->getSize(b->getBitBlockWidth());
339        Constant * const CODE_UNIT_BYTES = b->getSize(mCodeUnitWidth / 8);
340
341        BasicBlock * const entry = b->GetInsertBlock();
342        BasicBlock * const createTemporary = b->CreateBasicBlock("createTemporary");
343        BasicBlock * const exit = b->CreateBasicBlock("exit");
344
345        Value * const fileItems = b->getScalarField("fileItems");
346        Value * const producedItems = b->getProducedItemCount("sourceBuffer");
347        Value * const nextProducedItems = b->CreateAdd(producedItems, PAGE_ITEMS);
348        Value * const lastPage = b->CreateICmpULE(fileItems, nextProducedItems);
349        b->CreateUnlikelyCondBr(lastPage, createTemporary, exit);
350
351        b->SetInsertPoint(createTemporary);
352        Value * const consumedItems = b->getConsumedItemCount("sourceBuffer");
353        Value * const consumedOffset = b->CreateAnd(consumedItems, ConstantExpr::getNeg(BLOCK_WIDTH));
354        Value * const readStart = b->getRawOutputPointer("sourceBuffer", consumedOffset);
355        Value * const readEnd = b->getRawOutputPointer("sourceBuffer", fileItems);
356        Value * unconsumedBytes = b->CreateTrunc(b->CreatePtrDiff(readEnd, readStart), b->getSizeTy());
357        if (LLVM_UNLIKELY(mCodeUnitWidth > 8)) {
358            unconsumedBytes = b->CreateMul(unconsumedBytes, CODE_UNIT_BYTES);
359        }
360        Value * const bufferSize = b->CreateRoundUp(b->CreateAdd(unconsumedBytes, BLOCK_WIDTH), PAGE_SIZE);
361        Value * const buffer = b->CreateAlignedMalloc(bufferSize, b->getCacheAlignment());
362        b->CreateMemCpy(buffer, readStart, unconsumedBytes, 1);
363        b->CreateMemZero(b->CreateGEP(buffer, unconsumedBytes), b->CreateSub(bufferSize, unconsumedBytes), 1);
364
365        // get the difference between our base and from position then compute an offsetted temporary buffer address
366        Value * const base = b->getBaseAddress("sourceBuffer");
367        Value * const diff = b->CreatePtrDiff(b->CreatePointerCast(base, readStart->getType()), readStart);
368        Value * const offsettedBuffer = b->CreateGEP(buffer, diff);
369        b->CreateConsumerWait();
370
371        // set the temporary buffer as the new source buffer
372        PointerType * const codeUnitPtrTy = b->getIntNTy(mCodeUnitWidth)->getPointerTo();
373        b->setScalarField("buffer", b->CreatePointerCast(buffer, codeUnitPtrTy));
374        b->setBaseAddress("sourceBuffer", b->CreatePointerCast(offsettedBuffer, codeUnitPtrTy));
375        b->setTerminationSignal();
376        BasicBlock * const terminationExit = b->GetInsertBlock();
377        b->CreateBr(exit);
378
379        b->SetInsertPoint(exit);
380        PHINode * const newProducedItems = b->CreatePHI(b->getSizeTy(), 2);
381        newProducedItems->addIncoming(nextProducedItems, entry);
382        newProducedItems->addIncoming(fileItems, terminationExit);
383        b->setProducedItemCount("sourceBuffer", newProducedItems);
384    }
385}
386
387void MemorySourceKernel::generateFinalizeMethod(const std::unique_ptr<KernelBuilder> & b) {
388    if (mStreamSetCount == 1) {
389        b->CreateFree(b->getScalarField("buffer"));
390    }
391}
392
393MMapSourceKernel::MMapSourceKernel(const std::unique_ptr<kernel::KernelBuilder> & b, const unsigned codeUnitWidth)
394: SegmentOrientedKernel("mmap_source@" + std::to_string(codeUnitWidth)
395// input streams
396, {}
397// output streams
398, {Binding{b->getStreamSetTy(1, codeUnitWidth), "sourceBuffer"}}
399// input scalars
400, {Binding{b->getInt32Ty(), "fileDescriptor"}}
401// output scalars
402, {}
403// internal scalars
404, {Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "buffer"}
405,  Binding{b->getSizeTy(), "fileItems"}})
406, mCodeUnitWidth(codeUnitWidth)
407, mFileSizeFunction(nullptr) {
408    addAttribute(MustExplicitlyTerminate());
409    setStride(getpagesize());
410}
411
412ReadSourceKernel::ReadSourceKernel(const std::unique_ptr<kernel::KernelBuilder> & b, const unsigned codeUnitWidth)
413: SegmentOrientedKernel("read_source" + std::to_string(codegen::SegmentSize) + "@" + std::to_string(codeUnitWidth)
414// input streams
415, {}
416// output streams
417, {Binding{b->getStreamSetTy(1, codeUnitWidth), "sourceBuffer"}}
418// input scalars
419, {Binding{b->getInt32Ty(), "fileDescriptor"}}
420// output scalars
421, {}
422// internal scalars
423, {Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "buffer"}})
424, mCodeUnitWidth(codeUnitWidth) {
425    addAttribute(MustExplicitlyTerminate());
426    setStride(getpagesize());
427}
428
429
430FDSourceKernel::FDSourceKernel(const std::unique_ptr<kernel::KernelBuilder> & b, const unsigned codeUnitWidth)
431: SegmentOrientedKernel("FD_source@" + std::to_string(codeUnitWidth)
432// input streams
433, {}
434// output stream
435, {Binding{b->getStreamSetTy(1, codeUnitWidth), "sourceBuffer"}}
436// input scalar
437, {Binding{b->getInt8Ty(), "useMMap"}, Binding{b->getInt32Ty(), "fileDescriptor"}}
438, {}
439// internal scalars
440, {Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "buffer"},
441   Binding{b->getSizeTy(), "fileItems"}})
442, mCodeUnitWidth(codeUnitWidth)
443, mFileSizeFunction(nullptr) {
444    addAttribute(MustExplicitlyTerminate());
445    setStride(getpagesize());
446}
447
448MemorySourceKernel::MemorySourceKernel(const std::unique_ptr<kernel::KernelBuilder> & b, const unsigned streamSetCount, const unsigned codeUnitWidth)
449: SegmentOrientedKernel("memory_source@" + std::to_string(streamSetCount) + ":" + std::to_string(codeUnitWidth),
450// input streams
451{},
452// output stream
453{Binding{b->getStreamSetTy(streamSetCount, codeUnitWidth), "sourceBuffer"}},
454// input scalar
455{Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "fileSource"}, Binding{b->getSizeTy(), "fileItems"}},
456{},
457// internal scalar
458{Binding{b->getIntNTy(codeUnitWidth)->getPointerTo(), "buffer"}})
459, mStreamSetCount(streamSetCount)
460, mCodeUnitWidth(codeUnitWidth) {
461    addAttribute(MustExplicitlyTerminate());
462    setStride(getpagesize());
463}
464
465}
Note: See TracBrowser for help on using the repository browser.