source: icGREP/icgrep-devel/icgrep/kernels/stdin_kernel.cpp @ 5411

Last change on this file since 5411 was 5411, checked in by nmedfort, 2 years ago

Potential bug fix for 32-bit. Modified MRemap to check for Linux OS support. Added MMapAdvise to CBuilder.

File size: 5.3 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5#include <kernels/stdin_kernel.h>
6#include <llvm/IR/Module.h>
7#include <kernels/kernel.h>
8#include <IR_Gen/idisa_builder.h>
9#include <llvm/Support/raw_ostream.h>
10
11using namespace llvm;
12
13inline static size_t round_up_to_nearest(const size_t x, const size_t y) {
14    return (((x - 1) | (y - 1)) + 1);
15}
16
17namespace kernel {
18
19void StdInKernel::generateDoSegmentMethod(Value * /* doFinal */, const std::vector<Value *> & /* producerPos */) {
20
21    BasicBlock * const entryBlock = iBuilder->GetInsertBlock();
22    BasicBlock * const readBlock = CreateBasicBlock("ReadMoreData");
23    BasicBlock * const setTermination = CreateBasicBlock("SetTermination");
24    BasicBlock * const stdInExit = CreateBasicBlock("StdInExit");
25
26    ConstantInt * const segmentSize = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
27    Value * bufferedSize = getBufferedSize("InputStream");
28    Value * const itemsAlreadyRead = getProducedItemCount("InputStream");
29    Value * const bytesAlreadyRead = iBuilder->CreateMul(itemsAlreadyRead, iBuilder->getSize(mCodeUnitWidth / 8));
30    Value * unreadSize = iBuilder->CreateSub(bufferedSize, bytesAlreadyRead);
31
32    Value * const exaustedBuffer = iBuilder->CreateICmpULT(unreadSize, segmentSize);
33    iBuilder->CreateUnlikelyCondBr(exaustedBuffer, readBlock, stdInExit);
34
35    iBuilder->SetInsertPoint(readBlock);
36
37    // how many pages are required to have enough data for the segment plus one overflow block?
38    const auto PageAlignedSegmentSize = round_up_to_nearest((mSegmentBlocks + 1) * iBuilder->getBitBlockWidth() * (mCodeUnitWidth / 8), getpagesize());
39    ConstantInt * const bytesToRead = iBuilder->getSize(PageAlignedSegmentSize);
40    reserveBytes("InputStream", bytesToRead);
41    BasicBlock * const readExit = iBuilder->GetInsertBlock();
42    Value * const ptr = getRawOutputPointer("InputStream", iBuilder->getInt32(0), bufferedSize);
43    Value * const bytePtr = iBuilder->CreatePointerCast(ptr, iBuilder->getInt8PtrTy());
44    Value * const bytesRead = iBuilder->CreateReadCall(iBuilder->getInt32(STDIN_FILENO), bytePtr, bytesToRead);
45
46    unreadSize = iBuilder->CreateAdd(unreadSize, bytesRead);
47    bufferedSize = iBuilder->CreateAdd(bufferedSize, bytesRead);
48    setBufferedSize("InputStream", bufferedSize);
49
50    iBuilder->CreateUnlikelyCondBr(iBuilder->CreateICmpULT(unreadSize, segmentSize), setTermination, stdInExit);
51
52    iBuilder->SetInsertPoint(setTermination);
53    Value * const itemsRemaining = iBuilder->CreateUDiv(unreadSize, iBuilder->getSize(mCodeUnitWidth / 8));
54    setTerminationSignal();
55    iBuilder->CreateBr(stdInExit);
56
57    stdInExit->moveAfter(iBuilder->GetInsertBlock());
58
59    iBuilder->SetInsertPoint(stdInExit);
60    PHINode * const produced = iBuilder->CreatePHI(itemsAlreadyRead->getType(), 3);
61
62    produced->addIncoming(segmentSize, entryBlock);
63    produced->addIncoming(segmentSize, readExit);
64    produced->addIncoming(itemsRemaining, setTermination);
65    Value * const itemsRead = iBuilder->CreateAdd(itemsAlreadyRead, produced);
66
67    setProducedItemCount("InputStream", itemsRead);
68}
69
70StdInKernel::StdInKernel(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
71: SegmentOrientedKernel(iBuilder, "Parabix:stdin_source", {}, {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "InputStream"}}, {}, {}, {})
72, mSegmentBlocks(blocksPerSegment)
73, mCodeUnitWidth(codeUnitWidth) {
74   
75}
76
77void FileSourceKernel::generateDoSegmentMethod(Value *doFinal, const std::vector<Value *> &) {
78
79    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
80    BasicBlock * setTermination = CreateBasicBlock("setTermination");
81    BasicBlock * mmapSourceExit = CreateBasicBlock("mmapSourceExit");
82    ConstantInt * segmentItems = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
83    Value * fileItems = getScalarField("fileSize");
84    if (mCodeUnitWidth > 8) {
85        fileItems = iBuilder->CreateUDiv(fileItems, iBuilder->getSize(mCodeUnitWidth / 8));
86    }
87    Value * produced = getProducedItemCount("sourceBuffer");
88    produced = iBuilder->CreateAdd(produced, segmentItems);
89    Value * lessThanFullSegment = iBuilder->CreateICmpULT(fileItems, produced);
90    iBuilder->CreateCondBr(lessThanFullSegment, setTermination, mmapSourceExit);
91    iBuilder->SetInsertPoint(setTermination);
92    setTerminationSignal();
93    iBuilder->CreateBr(mmapSourceExit);
94
95    iBuilder->SetInsertPoint(mmapSourceExit);
96
97    PHINode * itemsRead = iBuilder->CreatePHI(produced->getType(), 2);
98    itemsRead->addIncoming(produced, entryBlock);
99    itemsRead->addIncoming(fileItems, setTermination);
100    setProducedItemCount("sourceBuffer", itemsRead);
101}
102
103void FileSourceKernel::generateInitMethod() {
104    setBaseAddress("sourceBuffer", getScalarField("fileSource"));
105    setBufferedSize("sourceBuffer", getScalarField("fileSize"));
106}
107
108FileSourceKernel::FileSourceKernel(IDISA::IDISA_Builder * iBuilder, Type * fileSourceTy, unsigned blocksPerSegment, unsigned codeUnitWidth)
109: SegmentOrientedKernel(iBuilder, "Parabix:file_source",
110    {},
111    {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "sourceBuffer"}},
112    {Binding{fileSourceTy, "fileSource"}, Binding{iBuilder->getSizeTy(), "fileSize"}}, {}, {})
113, mSegmentBlocks(blocksPerSegment)
114, mCodeUnitWidth(codeUnitWidth) {
115
116}
117
118
119
120}
Note: See TracBrowser for help on using the repository browser.