source: icGREP/icgrep-devel/icgrep/kernels/interface.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: 7.9 KB
RevLine 
[5047]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"
[5260]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
[5047]11#include <llvm/IR/Module.h>
[5260]12#include <IR_Gen/idisa_builder.h>
13namespace llvm { class Module; }
14namespace llvm { class Type; }
[5047]15
[5287]16static const auto INIT_SUFFIX = "_Init";
17
[5411]18static const auto TERMINATE_SUFFIX = "_Terminate";
19
[5287]20static const auto DO_SEGMENT_SUFFIX = "_DoSegment";
21
22static const auto ACCUMULATOR_INFIX = "_get_";
23
[5047]24using namespace llvm;
25
[5401]26ProcessingRate FixedRatio(unsigned strmItemsPer, unsigned perPrincipalInputItems, std::string && referenceStreamSet) {
27    return ProcessingRate(ProcessingRate::ProcessingRateKind::Fixed, strmItemsPer, perPrincipalInputItems, std::move(referenceStreamSet));
[5328]28}
29
[5401]30ProcessingRate MaxRatio(unsigned strmItemsPer, unsigned perPrincipalInputItems, std::string && referenceStreamSet) {
31    return ProcessingRate(ProcessingRate::ProcessingRateKind::Max, strmItemsPer, perPrincipalInputItems, std::move(referenceStreamSet));
[5328]32}
33
[5401]34ProcessingRate RoundUpToMultiple(unsigned itemMultiple, std::string && referenceStreamSet) {
35    return ProcessingRate(ProcessingRate::ProcessingRateKind::RoundUp, itemMultiple, itemMultiple, std::move(referenceStreamSet));
[5328]36}
37
[5401]38ProcessingRate Add1(std::string && referenceStreamSet) {
39    return ProcessingRate(ProcessingRate::ProcessingRateKind::Add1, 0, 0, std::move(referenceStreamSet));
[5370]40}
41
[5328]42ProcessingRate UnknownRate() {
[5375]43    return ProcessingRate(ProcessingRate::ProcessingRateKind::Unknown, 0, 0, "");
[5328]44}
45
[5370]46Value * ProcessingRate::CreateRatioCalculation(IDISA::IDISA_Builder * b, Value * principalInputItems, Value * doFinal) const {
47    if (mKind == ProcessingRate::ProcessingRateKind::Fixed || mKind == ProcessingRate::ProcessingRateKind::Max) {
[5398]48        if (mRatioNumerator == 1) {
[5390]49            return principalInputItems;
50        }
51        Type * const T = principalInputItems->getType();
[5398]52        Constant * const numerator = ConstantInt::get(T, mRatioNumerator);
53        Constant * const denominator = ConstantInt::get(T, mRatioDenominator);
54        Constant * const denominatorLess1 = ConstantInt::get(T, mRatioDenominator - 1);
[5390]55        Value * strmItems = b->CreateMul(principalInputItems, numerator);
56        return b->CreateUDiv(b->CreateAdd(denominatorLess1, strmItems), denominator);
[5370]57    }
58    if (mKind == ProcessingRate::ProcessingRateKind::RoundUp) {
[5390]59        Type * const T = principalInputItems->getType();
[5398]60        Constant * const denominator = ConstantInt::get(T, mRatioDenominator);
61        Constant * const denominatorLess1 = ConstantInt::get(T, mRatioDenominator - 1);
[5390]62        return b->CreateMul(b->CreateUDiv(b->CreateAdd(principalInputItems, denominatorLess1), denominator), denominator);
[5370]63    }
64    if (mKind == ProcessingRate::ProcessingRateKind::Add1) {
[5390]65        if (doFinal) {
66            Type * const T = principalInputItems->getType();
67            principalInputItems = b->CreateAdd(principalInputItems, b->CreateZExt(doFinal, T));
68        }
[5370]69        return principalInputItems;
70    }
[5328]71    return nullptr;
72}
73
[5408]74void KernelInterface::addKernelDeclarations(Module * const client) {
[5060]75    Module * saveModule = iBuilder->getModule();
[5202]76    auto savePoint = iBuilder->saveIP();
[5060]77    iBuilder->setModule(client);
78    if (mKernelStateType == nullptr) {
[5297]79        throw std::runtime_error("Kernel interface " + getName() + " not yet finalized.");
[5047]80    }
[5408]81    PointerType * const selfType = mKernelStateType->getPointerTo();
82    IntegerType * const sizeTy = iBuilder->getSizeTy();
83    PointerType * const consumerTy = StructType::get(sizeTy, sizeTy->getPointerTo()->getPointerTo(), nullptr)->getPointerTo();
[5227]84
[5047]85    // Create the initialization function prototype
[5408]86    std::vector<Type *> initParameters = {selfType};   
[5047]87    for (auto binding : mScalarInputs) {
[5202]88        initParameters.push_back(binding.type);
[5047]89    }
[5408]90    initParameters.insert(initParameters.end(), mStreamSetOutputs.size(), consumerTy);
91
[5292]92    FunctionType * initType = FunctionType::get(iBuilder->getVoidTy(), initParameters, false);
[5297]93    Function * init = Function::Create(initType, GlobalValue::ExternalLinkage, getName() + INIT_SUFFIX, client);
[5292]94    init->setCallingConv(CallingConv::C);
95    init->setDoesNotThrow();
96    auto args = init->arg_begin();
[5297]97    args->setName("self");
[5049]98    for (auto binding : mScalarInputs) {
[5297]99        (++args)->setName(binding.name);
[5049]100    }
[5408]101    for (auto binding : mStreamSetOutputs) {
102        args->setName(binding.name + "ConsumerLogicalSegments");       
103        ++args;
104    }
[5047]105
[5408]106    // Create the doSegment function prototype.
[5398]107    std::vector<Type *> params = {selfType, iBuilder->getInt1Ty()};
[5408]108    params.insert(params.end(), mStreamSetInputs.size(), sizeTy);
[5401]109
[5402]110    FunctionType * const doSegmentType = FunctionType::get(iBuilder->getVoidTy(), params, false);
[5297]111    Function * doSegment = Function::Create(doSegmentType, GlobalValue::ExternalLinkage, getName() + DO_SEGMENT_SUFFIX, client);
[5292]112    doSegment->setCallingConv(CallingConv::C);
113    doSegment->setDoesNotThrow();
114    doSegment->setDoesNotCapture(1); // for self parameter only.
115    args = doSegment->arg_begin();
[5297]116    args->setName("self");
117    (++args)->setName("doFinal");
[5398]118    for (const Binding & input : mStreamSetInputs) {
[5408]119        (++args)->setName(input.name + "AvailableItems");
[5263]120    }
[5287]121
[5411]122    // Create the terminate function prototype
123    FunctionType * terminateType = FunctionType::get(iBuilder->getVoidTy(), {selfType}, false);
124    Function * terminateFunc = Function::Create(terminateType, GlobalValue::ExternalLinkage, getName() + TERMINATE_SUFFIX, client);
125    terminateFunc->setCallingConv(CallingConv::C);
126    terminateFunc->setDoesNotThrow();
127    terminateFunc->setDoesNotCapture(1);
128    args = terminateFunc->arg_begin();
129    args->setName("self");
130
[5401]131    /// INVESTIGATE: replace the accumulator methods with a single Exit method that handles any clean up and returns
132    /// a struct containing all scalar outputs?
133
[5292]134    // Create the accumulator get function prototypes
135    for (const auto & binding : mScalarOutputs) {
136        FunctionType * accumFnType = FunctionType::get(binding.type, {selfType}, false);
[5297]137        Function * accumFn = Function::Create(accumFnType, GlobalValue::ExternalLinkage, getName() + ACCUMULATOR_INFIX + binding.name, client);
[5292]138        accumFn->setCallingConv(CallingConv::C);
139        accumFn->setDoesNotThrow();
[5297]140        accumFn->setDoesNotCapture(1);
141        auto args = accumFn->arg_begin();
142        args->setName("self");
[5292]143    }
144
[5060]145    iBuilder->setModule(saveModule);
146    iBuilder->restoreIP(savePoint);
[5047]147}
148
[5220]149void KernelInterface::setInitialArguments(std::vector<Value *> args) {
150    mInitialArguments = args;
151}
152
[5287]153llvm::Function * KernelInterface::getAccumulatorFunction(const std::string & accumName) const {
[5297]154    const auto name = getName() + ACCUMULATOR_INFIX + accumName;
[5287]155    Function * f = iBuilder->getModule()->getFunction(name);
156    if (LLVM_UNLIKELY(f == nullptr)) {
157        llvm::report_fatal_error("Cannot find " + name);
[5086]158    }
[5287]159    return f;
[5086]160}
161
[5287]162Function * KernelInterface::getInitFunction() const {
[5297]163    const auto name = getName() + INIT_SUFFIX;
[5287]164    Function * f = iBuilder->getModule()->getFunction(name);
165    if (LLVM_UNLIKELY(f == nullptr)) {
166        llvm::report_fatal_error("Cannot find " + name);
[5053]167    }
[5287]168    return f;
[5053]169}
170
[5285]171Function * KernelInterface::getDoSegmentFunction() const {
[5297]172    const auto name = getName() + DO_SEGMENT_SUFFIX;
[5287]173    Function * f = iBuilder->getModule()->getFunction(name);
174    if (LLVM_UNLIKELY(f == nullptr)) {
175        llvm::report_fatal_error("Cannot find " + name);
176    }
177    return f;
[5285]178}
[5411]179
180Function * KernelInterface::getTerminateFunction() const {
181    const auto name = getName() + TERMINATE_SUFFIX;
182    Function * f = iBuilder->getModule()->getFunction(name);
183    if (LLVM_UNLIKELY(f == nullptr)) {
184        llvm::report_fatal_error("Cannot find " + name);
185    }
186    return f;
187}
Note: See TracBrowser for help on using the repository browser.