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

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

doSegment with termination signal processing for stdout kernel

File size: 7.0 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 in case 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           
37// Rather than using doBlock logic to write one block at a time, this custom
38// doSegment method, writes the entire segment with a single write call.
39void stdOutKernel::generateDoSegmentMethod() {
40    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
41    Module * m = iBuilder->getModule();
42    Function * writefn = create_write(m);
43    Function * doSegmentFunction = m->getFunction(mKernelName + doSegment_suffix);
44    Type * i8PtrTy = iBuilder->getInt8PtrTy();
45   
46    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doSegmentFunction, 0));
47    BasicBlock * setTermination = BasicBlock::Create(iBuilder->getContext(), "setTermination", doSegmentFunction, 0);
48    BasicBlock * stdOutexit = BasicBlock::Create(iBuilder->getContext(), "stdOutexit", doSegmentFunction, 0);
49    Constant * blockItems = ConstantInt::get(iBuilder->getSizeTy(), iBuilder->getBitBlockWidth());
50    Constant * itemBytes = ConstantInt::get(iBuilder->getSizeTy(), mCodeUnitWidth/8);
51   
52    Function::arg_iterator args = doSegmentFunction->arg_begin();
53    Value * self = &*(args++);
54    Value * blocksToDo = &*(args);
55    ////iBuilder->CallPrintInt("blocksToDo", blocksToDo);
56    Value * segmentNo = getLogicalSegmentNo(self);
57    Value * streamStructPtr = getStreamSetStructPtr(self, "codeUnitBuffer");
58    //iBuilder->CallPrintInt("streamStructPtr", iBuilder->CreatePtrToInt(streamStructPtr, iBuilder->getInt64Ty()));
59
60    LoadInst * producerPos = iBuilder->CreateAtomicLoadAcquire(mStreamSetInputBuffers[0]->getProducerPosPtr(streamStructPtr));
61    //iBuilder->CallPrintInt("producerPos", producerPos);
62    Value * processed = getProcessedItemCount(self);
63    Value * itemsAvail = iBuilder->CreateSub(producerPos, processed);
64    Value * itemsMax = iBuilder->CreateMul(blocksToDo, blockItems);
65    Value * lessThanFullSegment = iBuilder->CreateICmpULT(itemsAvail, itemsMax);
66    Value * itemsToDo = iBuilder->CreateSelect(lessThanFullSegment, itemsAvail, itemsMax);
67   
68    Value * blockNo = getScalarField(self, blockNoScalar);
69    //iBuilder->CallPrintInt("blockNo", blockNo);
70    Value * basePtr = getStreamSetBlockPtr(self, "codeUnitBuffer", blockNo);
71    //iBuilder->CallPrintInt("basePtr", iBuilder->CreatePtrToInt(basePtr, iBuilder->getInt64Ty()));
72    Value * byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(processed, blockItems), itemBytes);
73    Value * bytePtr = iBuilder->CreateGEP(iBuilder->CreateBitCast(basePtr, i8PtrTy), byteOffset);
74//#undef NDEBUG
75#ifndef NDEBUG
76    iBuilder->CallPrintInt(mKernelName + "_segmentNo", segmentNo);
77    iBuilder->CallPrintInt(mKernelName + "_itemsAvail", itemsAvail);
78    iBuilder->CallPrintInt(mKernelName + "_itemsToDo", itemsToDo);
79#endif
80    iBuilder->CreateCall(writefn, std::vector<Value *>({iBuilder->getInt32(1), bytePtr, iBuilder->CreateMul(itemsToDo, itemBytes)}));
81   
82    processed = iBuilder->CreateAdd(processed, itemsToDo);
83    setProcessedItemCount(self, processed);
84    setScalarField(self, blockNoScalar, iBuilder->CreateUDiv(processed, blockItems));
85    mStreamSetInputBuffers[0]->setConsumerPos(streamStructPtr, processed);
86
87    Value * endSignal = iBuilder->CreateLoad(mStreamSetInputBuffers[0]->hasEndOfInputPtr(streamStructPtr));
88    Value * inFinalSegment = iBuilder->CreateAnd(endSignal, lessThanFullSegment);
89   
90    iBuilder->CreateCondBr(inFinalSegment, setTermination, stdOutexit);
91    iBuilder->SetInsertPoint(setTermination);
92#ifndef NDEBUG
93    iBuilder->CallPrintInt(mKernelName + " termination in segment ", segmentNo);
94#endif
95    setTerminationSignal(self);
96
97    iBuilder->CreateBr(stdOutexit);
98    iBuilder->SetInsertPoint(stdOutexit);
99    // Must be the last action, for synchronization.
100    setLogicalSegmentNo(self, iBuilder->CreateAdd(segmentNo, ConstantInt::get(iBuilder->getSizeTy(), 1)));
101    iBuilder->CreateRetVoid();
102    iBuilder->restoreIP(savePoint);
103}
104
105void stdOutKernel::generateFinalBlockMethod() {
106    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
107    Module * m = iBuilder->getModule();
108    Function * writefn = create_write(m);
109    Function * finalBlockFunction = m->getFunction(mKernelName + finalBlock_suffix);
110    Type * i8PtrTy = iBuilder->getInt8PtrTy();
111   
112    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "fb_flush", finalBlockFunction, 0));
113    Constant * blockItems = ConstantInt::get(iBuilder->getSizeTy(), iBuilder->getBitBlockWidth());
114    Constant * itemBytes = ConstantInt::get(iBuilder->getSizeTy(), mCodeUnitWidth/8);
115    Value * self = getParameter(finalBlockFunction, "self");
116    Value * streamStructPtr = getStreamSetStructPtr(self, "codeUnitBuffer");
117    LoadInst * producerPos = iBuilder->CreateAtomicLoadAcquire(mStreamSetInputBuffers[0]->getProducerPosPtr(streamStructPtr));
118    Value * processed = getProcessedItemCount(self);
119    Value * itemsAvail = iBuilder->CreateSub(producerPos, processed);
120    Value * segmentNo = getLogicalSegmentNo(self);
121    Value * blockNo = getScalarField(self, blockNoScalar);
122    Value * basePtr = getStreamSetBlockPtr(self, "codeUnitBuffer", blockNo);
123    Value * byteOffset = iBuilder->CreateMul(iBuilder->CreateURem(processed, blockItems), itemBytes);
124    Value * bytePtr = iBuilder->CreateGEP(iBuilder->CreateBitCast(basePtr, i8PtrTy), byteOffset);
125    iBuilder->CreateCall(writefn, std::vector<Value *>({iBuilder->getInt32(1), bytePtr, iBuilder->CreateMul(itemsAvail, itemBytes)}));
126    setProcessedItemCount(self, producerPos);
127    mStreamSetInputBuffers[0]->setConsumerPos(streamStructPtr, producerPos);
128    setTerminationSignal(self);
129    iBuilder->CreateRetVoid();
130    iBuilder->restoreIP(savePoint);
131}
132}
Note: See TracBrowser for help on using the repository browser.