source: icGREP/icgrep-devel/icgrep/kernels/stdout_kernel.cpp @ 5188

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

Do segment method now handles partial/final segment

File size: 6.1 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5#include <kernels/stdout_kernel.h>
6#include <kernels/kernel.h>
7#include <IDISA/idisa_builder.h>
8#include <llvm/IR/TypeBuilder.h>
9
10namespace kernel {
11
12static Function * create_write(Module * const mod) {
13    Function * write = mod->getFunction("write");
14    if (write == nullptr) {
15        FunctionType *write_type =
16        TypeBuilder<long(int, char *, long), false>::get(mod->getContext());
17        write = cast<Function>(mod->getOrInsertFunction("write", write_type,
18                                                         AttributeSet().addAttribute(mod->getContext(), 2U, Attribute::NoAlias)));
19    }
20    return write;
21}
22
23// The doBlock method is deprecated.   But incase it is used, just call doSegment with
24// 1 as the number of blocks to do.
25void stdOutKernel::generateDoBlockMethod() {
26    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
27    Module * m = iBuilder->getModule();
28    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
29    Function * doSegmentFunction = m->getFunction(mKernelName + doSegment_suffix);
30    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
31    Value * self = getParameter(doBlockFunction, "self");
32    iBuilder->CreateCall(doSegmentFunction, {self, ConstantInt::get(iBuilder->getSizeTy(), 1)});
33    iBuilder->CreateRetVoid();
34    iBuilder->restoreIP(savePoint);
35}
36           
37void stdOutKernel::generateDoSegmentMethod() {
38    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
39    Module * m = iBuilder->getModule();
40    Function * writefn = create_write(m);
41    Function * doSegmentFunction = m->getFunction(mKernelName + doSegment_suffix);
42    Type * i8PtrTy = iBuilder->getInt8PtrTy();
43   
44    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doSegmentFunction, 0));
45    Constant * stride = ConstantInt::get(iBuilder->getSizeTy(), iBuilder->getStride());
46    Constant * itemBytes = ConstantInt::get(iBuilder->getSizeTy(), mCodeUnitWidth/8);
47   
48    Function::arg_iterator args = doSegmentFunction->arg_begin();
49    Value * self = &*(args++);
50    Value * blocksToDo = &*(args);
51    ////iBuilder->CallPrintInt("blocksToDo", blocksToDo);
52    Value * segmentNo = getLogicalSegmentNo(self);
53    Value * streamStructPtr = getStreamSetStructPtr(self, "codeUnitBuffer");
54    //iBuilder->CallPrintInt("streamStructPtr", iBuilder->CreatePtrToInt(streamStructPtr, iBuilder->getInt64Ty()));
55
56    LoadInst * producerPos = iBuilder->CreateAlignedLoad(mStreamSetInputBuffers[0]->getProducerPosPtr(streamStructPtr), sizeof(size_t));
57    producerPos->setOrdering(AtomicOrdering::Acquire);
58    //iBuilder->CallPrintInt("producerPos", producerPos);
59    Value * endSignal = iBuilder->CreateLoad(mStreamSetInputBuffers[0]->hasEndOfInputPtr(streamStructPtr));
60
61    Value * blockNo = getScalarField(self, blockNoScalar);
62    //iBuilder->CallPrintInt("blockNo", blockNo);
63    Value * basePtr = getStreamSetBlockPtr(self, "codeUnitBuffer", blockNo);
64    //iBuilder->CallPrintInt("basePtr", iBuilder->CreatePtrToInt(basePtr, iBuilder->getInt64Ty()));
65   
66    Value * processed = getProcessedItemCount(self);
67    Value * itemsAvail = iBuilder->CreateSub(producerPos, processed);
68    //iBuilder->CallPrintInt("previously processed", processed);
69    Value * blocksAvail = iBuilder->CreateUDiv(itemsAvail, stride);
70    //iBuilder->CallPrintInt("blocksAvail", blocksAvail);
71   
72    Value * lessThanFullSegment = iBuilder->CreateICmpULT(blocksAvail, blocksToDo);
73    Value * inFinalSegment = iBuilder->CreateAnd(endSignal, lessThanFullSegment);
74    /* Adjust the number of full blocks to do, based on the available data, if necessary. */
75    blocksToDo = iBuilder->CreateSelect(lessThanFullSegment, blocksAvail, blocksToDo);
76   
77    Value * itemsToDo = iBuilder->CreateMul(blocksToDo, stride);
78    itemsToDo = iBuilder->CreateSelect(inFinalSegment, itemsAvail, itemsToDo);
79    //iBuilder->CallPrintInt("bytesToDo", bytesToDo);
80    iBuilder->CreateCall(writefn, std::vector<Value *>({iBuilder->getInt32(1), iBuilder->CreateBitCast(basePtr, i8PtrTy), iBuilder->CreateMul(itemsToDo, itemBytes)}));
81   
82    setScalarField(self, blockNoScalar, iBuilder->CreateAdd(blockNo, blocksToDo));
83    processed = iBuilder->CreateAdd(processed, itemsToDo);
84    setProcessedItemCount(self, processed);
85    mStreamSetInputBuffers[0]->setConsumerPos(streamStructPtr, processed);
86    // Must be the last action, for synchronization.
87    setLogicalSegmentNo(self, iBuilder->CreateAdd(segmentNo, ConstantInt::get(iBuilder->getSizeTy(), 1)));
88   
89    iBuilder->CreateRetVoid();
90    iBuilder->restoreIP(savePoint);
91}
92
93void stdOutKernel::generateFinalBlockMethod() {
94    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
95    Module * m = iBuilder->getModule();
96    Function * writefn = create_write(m);
97    Function * finalBlockFunction = m->getFunction(mKernelName + finalBlock_suffix);
98    Type * i8PtrTy = iBuilder->getInt8PtrTy();
99   
100    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "fb_flush", finalBlockFunction, 0));
101    Value * self = getParameter(finalBlockFunction, "self");
102    Value * streamStructPtr = getStreamSetStructPtr(self, "codeUnitBuffer");
103    LoadInst * producerPos = iBuilder->CreateAlignedLoad(mStreamSetInputBuffers[0]->getProducerPosPtr(streamStructPtr), sizeof(size_t));
104    producerPos->setOrdering(AtomicOrdering::Acquire);
105    Value * processed = getProcessedItemCount(self);
106    Value * itemsAvail = iBuilder->CreateSub(producerPos, processed);
107    Value * blockNo = getScalarField(self, blockNoScalar);
108    Value * basePtr = getStreamSetBlockPtr(self, "codeUnitBuffer", blockNo);
109    Value * bytesToDo = iBuilder->CreateMul(itemsAvail, ConstantInt::get(iBuilder->getSizeTy(), mCodeUnitWidth/8));
110
111    iBuilder->CreateCall(writefn, std::vector<Value *>({iBuilder->getInt32(1), iBuilder->CreateBitCast(basePtr, i8PtrTy), bytesToDo}));
112   
113    setProcessedItemCount(self, producerPos);
114    mStreamSetInputBuffers[0]->setConsumerPos(streamStructPtr, producerPos);
115    iBuilder->CreateRetVoid();
116    iBuilder->restoreIP(savePoint);
117}
118}
Note: See TracBrowser for help on using the repository browser.