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

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

Added enable asserts (-ea) command line flag + restructured BlockOrientedKernels? to allow for inlined code.

File size: 5.8 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/Value.h>         // for Value
8#include <llvm/IR/CallingConv.h>   // for ::C
9#include <llvm/IR/DerivedTypes.h>  // for FunctionType (ptr only), PointerType
10#include <llvm/IR/Function.h>      // for Function, Function::arg_iterator
11#include <llvm/IR/Module.h>
12#include <IR_Gen/idisa_builder.h>
13namespace llvm { class Module; }
14namespace llvm { class Type; }
15
16static const auto INIT_SUFFIX = "_Init";
17
18static const auto DO_SEGMENT_SUFFIX = "_DoSegment";
19
20static const auto ACCUMULATOR_INFIX = "_get_";
21
22using namespace llvm;
23
24ProcessingRate FixedRatio(unsigned strmItemsPer, unsigned perPrincipalInputItems) {
25    return ProcessingRate(ProcessingRate::ProcessingRateKind::Fixed, strmItemsPer, perPrincipalInputItems);
26}
27
28ProcessingRate MaxRatio(unsigned strmItemsPer, unsigned perPrincipalInputItems) {
29    return ProcessingRate(ProcessingRate::ProcessingRateKind::Max, strmItemsPer, perPrincipalInputItems);
30}
31
32ProcessingRate RoundUpToMultiple(unsigned itemMultiple) {
33    return ProcessingRate(ProcessingRate::ProcessingRateKind::RoundUp, itemMultiple, itemMultiple);
34}
35
36ProcessingRate UnknownRate() {
37    return ProcessingRate(ProcessingRate::ProcessingRateKind::Unknown, 0, 0);
38}
39
40Value * ProcessingRate::CreateRatioCalculation(IDISA::IDISA_Builder * b, Value * principalInputItems) const {
41    Type * T = principalInputItems->getType();
42    if (mKind == ProcessingRate::ProcessingRateKind::Fixed || mKind == ProcessingRate::ProcessingRateKind::Max) {
43        Value * strmItems = (ratio_numerator == 1) ? principalInputItems : b->CreateMul(principalInputItems, ConstantInt::get(T, ratio_numerator)); 
44        if (ratio_denominator == 1) return strmItems;
45        return b->CreateUDiv(b->CreateAdd(ConstantInt::get(T, ratio_denominator - 1), strmItems), ConstantInt::get(T, ratio_denominator)); 
46    }
47    if (mKind == ProcessingRate::ProcessingRateKind::RoundUp) {
48        Constant * multiple = ConstantInt::get(T, ratio_denominator);
49        Constant * multipleLess1 = ConstantInt::get(T, ratio_denominator - 1);
50        return b->CreateMul(b->CreateUDiv(b->CreateAdd(principalInputItems, multipleLess1), multiple), multiple);
51    }
52    return nullptr;
53}
54
55
56void KernelInterface::addKernelDeclarations(Module * client) {
57    Module * saveModule = iBuilder->getModule();
58    auto savePoint = iBuilder->saveIP();
59    iBuilder->setModule(client);
60    if (mKernelStateType == nullptr) {
61        throw std::runtime_error("Kernel interface " + getName() + " not yet finalized.");
62    }
63    PointerType * selfType = PointerType::getUnqual(mKernelStateType);
64
65    // Create the initialization function prototype
66    std::vector<Type *> initParameters = {selfType};
67    for (auto binding : mScalarInputs) {
68        initParameters.push_back(binding.type);
69    }
70    FunctionType * initType = FunctionType::get(iBuilder->getVoidTy(), initParameters, false);
71    Function * init = Function::Create(initType, GlobalValue::ExternalLinkage, getName() + INIT_SUFFIX, client);
72    init->setCallingConv(CallingConv::C);
73    init->setDoesNotThrow();
74    auto args = init->arg_begin();
75    args->setName("self");
76    for (auto binding : mScalarInputs) {
77        (++args)->setName(binding.name);
78    }
79
80    // Create the doSegment function prototype.
81    std::vector<Type *> doSegmentParameters = {selfType, iBuilder->getInt1Ty()};
82    for (unsigned i = 0; i < mStreamSetInputs.size(); ++i) {
83        doSegmentParameters.push_back(iBuilder->getSizeTy());
84    }
85    FunctionType * doSegmentType = FunctionType::get(iBuilder->getVoidTy(), doSegmentParameters, false);
86    Function * doSegment = Function::Create(doSegmentType, GlobalValue::ExternalLinkage, getName() + DO_SEGMENT_SUFFIX, client);
87    doSegment->setCallingConv(CallingConv::C);
88    doSegment->setDoesNotThrow();
89    doSegment->setDoesNotCapture(1); // for self parameter only.
90    args = doSegment->arg_begin();
91    args->setName("self");
92    (++args)->setName("doFinal");
93    for (auto ss : mStreamSetInputs) {
94        (++args)->setName(ss.name + "_availableItems");
95    }
96
97//    // Add any additional kernel declarations
98//    addAdditionalKernelDeclarations(client, selfType);
99
100    // Create the accumulator get function prototypes
101    for (const auto & binding : mScalarOutputs) {
102        FunctionType * accumFnType = FunctionType::get(binding.type, {selfType}, false);
103        Function * accumFn = Function::Create(accumFnType, GlobalValue::ExternalLinkage, getName() + ACCUMULATOR_INFIX + binding.name, client);
104        accumFn->setCallingConv(CallingConv::C);
105        accumFn->setDoesNotThrow();
106        accumFn->setDoesNotCapture(1);
107        auto args = accumFn->arg_begin();
108        args->setName("self");
109    }
110
111    iBuilder->setModule(saveModule);
112    iBuilder->restoreIP(savePoint);
113}
114
115void KernelInterface::setInitialArguments(std::vector<Value *> args) {
116    mInitialArguments = args;
117}
118
119llvm::Function * KernelInterface::getAccumulatorFunction(const std::string & accumName) const {
120    const auto name = getName() + ACCUMULATOR_INFIX + accumName;
121    Function * f = iBuilder->getModule()->getFunction(name);
122    if (LLVM_UNLIKELY(f == nullptr)) {
123        llvm::report_fatal_error("Cannot find " + name);
124    }
125    return f;
126}
127
128Function * KernelInterface::getInitFunction() const {
129    const auto name = getName() + INIT_SUFFIX;
130    Function * f = iBuilder->getModule()->getFunction(name);
131    if (LLVM_UNLIKELY(f == nullptr)) {
132        llvm::report_fatal_error("Cannot find " + name);
133    }
134    return f;
135}
136
137Function * KernelInterface::getDoSegmentFunction() const {
138    const auto name = getName() + DO_SEGMENT_SUFFIX;
139    Function * f = iBuilder->getModule()->getFunction(name);
140    if (LLVM_UNLIKELY(f == nullptr)) {
141        llvm::report_fatal_error("Cannot find " + name);
142    }
143    return f;
144}
Note: See TracBrowser for help on using the repository browser.