source: icGREP/icgrep-devel/icgrep/kernels/interface.cpp @ 5142

Last change on this file since 5142 was 5135, checked in by lindanl, 3 years ago

Add pipeline parallel strategy to the framework.

File size: 7.6 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
6#include "interface.h"
7#include <llvm/IR/Module.h>
8#include <llvm/IR/Type.h>
9#include <llvm/IR/Value.h>
10#include <llvm/Support/raw_ostream.h>
11
12using namespace llvm;
13using namespace parabix;
14
15void KernelInterface::addKernelDeclarations(Module * client) {
16    Module * saveModule = iBuilder->getModule();
17    IDISA::IDISA_Builder::InsertPoint savePoint = iBuilder->saveIP();
18    iBuilder->setModule(client);
19    if (mKernelStateType == nullptr) {
20        throw std::runtime_error("Kernel interface " + mKernelName + " not yet finalized.");
21    }
22    Type * selfType = PointerType::getUnqual(mKernelStateType);
23    // Create the accumulator get function prototypes
24    for (auto binding : mScalarOutputs) {
25        FunctionType * accumFnType = FunctionType::get(binding.scalarType, {selfType}, false);
26        std::string fnName = mKernelName + accumulator_infix + binding.scalarName;
27        Function * accumFn = Function::Create(accumFnType, GlobalValue::ExternalLinkage, fnName, client);
28        accumFn->setCallingConv(CallingConv::C);
29        accumFn->setDoesNotThrow();
30        Value * self = &*(accumFn->arg_begin());
31        self->setName("self");       
32    }
33    // Create the initialization function prototype
34
35    std::vector<Type *> initParameters = {selfType};
36    for (auto binding : mScalarInputs) {
37        initParameters.push_back(binding.scalarType);
38    }
39    FunctionType * initFunctionType = FunctionType::get(iBuilder->getVoidTy(), initParameters, false);
40    std::string initFnName = mKernelName + init_suffix;
41    Function * initFn = Function::Create(initFunctionType, GlobalValue::ExternalLinkage, initFnName, client);
42    initFn->setCallingConv(CallingConv::C);
43    initFn->setDoesNotThrow();
44    Function::arg_iterator initArgs = initFn->arg_begin();
45    Value * initArg = &*(initArgs++);
46    initArg->setName("self");
47    for (auto binding : mScalarInputs) {
48        initArg = &*(initArgs++);
49        initArg->setName(binding.scalarName);
50    }
51
52    // Create the doBlock and finalBlock function prototypes
53   
54    std::vector<Type *> doBlockParameters = {selfType};
55    std::vector<Type *> finalBlockParameters = {selfType, iBuilder->getSizeTy()};
56    FunctionType * doBlockFunctionType = FunctionType::get(iBuilder->getVoidTy(), doBlockParameters, false);
57    std::string doBlockName = mKernelName + doBlock_suffix;
58    Function * doBlockFn = Function::Create(doBlockFunctionType, GlobalValue::ExternalLinkage, doBlockName, client);
59    doBlockFn->setCallingConv(CallingConv::C);
60    doBlockFn->setDoesNotThrow();
61    for (int i = 1; i <= doBlockParameters.size(); i++) {
62        doBlockFn->setDoesNotCapture(i);
63    }
64   
65    FunctionType * finalBlockType = FunctionType::get(iBuilder->getVoidTy(), finalBlockParameters, false);
66    std::string finalBlockName = mKernelName + finalBlock_suffix;
67    Function * finalBlockFn = Function::Create(finalBlockType, GlobalValue::ExternalLinkage, finalBlockName, client);
68    finalBlockFn->setCallingConv(CallingConv::C);
69    finalBlockFn->setDoesNotThrow();
70    finalBlockFn->setDoesNotCapture(1);
71    // Parameter #2 is not a pointer; nocapture is irrelevant
72    for (int i = 3; i <= finalBlockParameters.size(); i++) {
73        finalBlockFn->setDoesNotCapture(i);
74    }
75   
76    Function::arg_iterator doBlockArgs = doBlockFn->arg_begin();
77    Function::arg_iterator finalBlockArgs = finalBlockFn->arg_begin();
78    Value * doBlockArg = &*(doBlockArgs++);
79    doBlockArg->setName("self");
80    Value * finalBlockArg = &*(finalBlockArgs++);
81    finalBlockArg->setName("self");
82    finalBlockArg = &*(finalBlockArgs++);
83    finalBlockArg->setName("remainingBytes");
84
85    // Create the doSegment function prototype.
86    std::vector<Type *> doSegmentParameters = {selfType, iBuilder->getSizeTy()};
87    FunctionType * doSegmentFunctionType = FunctionType::get(iBuilder->getVoidTy(), doSegmentParameters, false);
88    std::string doSegmentName = mKernelName + doSegment_suffix;
89    Function * doSegmentFn = Function::Create(doSegmentFunctionType, GlobalValue::ExternalLinkage, doSegmentName, client);
90    doSegmentFn->setCallingConv(CallingConv::C);
91    doSegmentFn->setDoesNotThrow();
92    Function::arg_iterator args = doSegmentFn->arg_begin();
93    Value * arg = &*(args++);
94    arg->setName("self");
95    arg = &*(args++);
96    arg->setName("blockCnt");
97    doSegmentFn->setDoesNotCapture(1); // for self parameter only.
98    iBuilder->setModule(saveModule);
99    iBuilder->restoreIP(savePoint);
100}
101
102
103Value * KernelInterface::createInstance(std::vector<Value *> args) {
104    Value * kernelInstance = iBuilder->CreateAlloca(mKernelStateType);
105    Module * m = iBuilder->getModule();
106    std::vector<Value *> init_args = {kernelInstance};
107    for (auto a : args) {
108        init_args.push_back(a);
109    }
110    std::string initFnName = mKernelName + init_suffix;
111    Function * initMethod = m->getFunction(initFnName);
112    if (!initMethod) {
113        throw std::runtime_error("Cannot find " + initFnName);
114    }
115    iBuilder->CreateCall(initMethod, init_args);
116    return kernelInstance;
117}
118
119Value * KernelInterface::createInstance(std::vector<Value *> args, 
120                                        std::vector<StreamSetBuffer *> inputBuffers,
121                                        std::vector<StreamSetBuffer *> outputBuffers) {
122    Value * kernelInstance = iBuilder->CreateAlloca(mKernelStateType);
123    Module * m = iBuilder->getModule();
124    std::vector<Value *> init_args = {kernelInstance};
125    for (auto a : args) {
126        init_args.push_back(a);
127    }
128    for (auto b : inputBuffers) { 
129        init_args.push_back(b->getStreamSetStructPtr());
130    }
131    for (auto b : outputBuffers) { 
132        init_args.push_back(b->getStreamSetStructPtr());
133    }
134    std::string initFnName = mKernelName + init_suffix;
135    Function * initMethod = m->getFunction(initFnName);
136    if (!initMethod) {
137        throw std::runtime_error("Cannot find " + initFnName);
138    }
139    iBuilder->CreateCall(initMethod, init_args);
140    return kernelInstance;
141}
142
143Value * KernelInterface::createDoBlockCall(Value * self) {
144    Module * m = iBuilder->getModule();
145    std::string doBlockName = mKernelName + doBlock_suffix;
146    Function * doBlockMethod = m->getFunction(doBlockName);
147    if (!doBlockMethod) {
148        throw std::runtime_error("Cannot find " + doBlockName);
149    }
150    std::vector<Value *> args = {self};
151    return iBuilder->CreateCall(doBlockMethod, args);
152}
153
154Value * KernelInterface::createFinalBlockCall(Value * self, Value * remainingBytes) {
155    Module * m = iBuilder->getModule();
156    std::string finalBlockName = mKernelName + finalBlock_suffix;
157    Function * finalBlockMethod = m->getFunction(finalBlockName);
158    if (!finalBlockMethod) {
159        throw std::runtime_error("Cannot find " + finalBlockName);
160    }
161    std::vector<Value *> args = {self, remainingBytes};
162    return iBuilder->CreateCall(finalBlockMethod, args);
163}
164
165
166Value * KernelInterface::createDoSegmentCall(Value * self, Value * blksToDo) {
167    Module * m = iBuilder->getModule();
168    std::string fnName = mKernelName + doSegment_suffix;
169    Function * method = m->getFunction(fnName);
170    if (!method) {
171        throw std::runtime_error("Cannot find " + fnName);
172    }
173    std::vector<Value *> args = {self, blksToDo};
174    return iBuilder->CreateCall(method, args);
175}
176
177Value * KernelInterface::createGetAccumulatorCall(Value * self, std::string accumName) {
178    Module * m = iBuilder->getModule();
179    std::string fnName = mKernelName + accumulator_infix + accumName;
180    Function * accumMethod = m->getFunction(fnName);
181    if (!accumMethod) {
182        throw std::runtime_error("Cannot find " + fnName);
183    }
184    return iBuilder->CreateCall(accumMethod, {self});
185}
186
187
Note: See TracBrowser for help on using the repository browser.