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

Last change on this file since 5985 was 5985, checked in by nmedfort, 13 months ago

Restructured MultiBlock? kernel. Removal of Swizzled buffers. Inclusion of PopCount? rates / non-linear access. Modifications to several kernels to better align them with the kernel and pipeline changes.

File size: 5.2 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>
[5436]12#include <kernels/kernel_builder.h>
[5047]13
[5287]14
[5047]15using namespace llvm;
16
[5706]17namespace kernel {
[5328]18
[5985]19const static auto INIT_SUFFIX = "_Init";
20const static auto DO_SEGMENT_SUFFIX = "_DoSegment";
21const static auto TERMINATE_SUFFIX = "_Terminate";
22
[5440]23void KernelInterface::addKernelDeclarations(const std::unique_ptr<kernel::KernelBuilder> & idb) {
[5431]24
[5060]25    if (mKernelStateType == nullptr) {
[5297]26        throw std::runtime_error("Kernel interface " + getName() + " not yet finalized.");
[5047]27    }
[5431]28
[5440]29    Module * const module = idb->getModule();
[5408]30    PointerType * const selfType = mKernelStateType->getPointerTo();
[5440]31    IntegerType * const sizeTy = idb->getSizeTy();
[5733]32    PointerType * const consumerTy = StructType::get(idb->getContext(), {sizeTy, sizeTy->getPointerTo()->getPointerTo()})->getPointerTo();
[5440]33    Type * const voidTy = idb->getVoidTy();
[5227]34
[5047]35    // Create the initialization function prototype
[5431]36    std::vector<Type *> initParameters = {selfType};
[5047]37    for (auto binding : mScalarInputs) {
[5706]38        initParameters.push_back(binding.getType());
[5047]39    }
[5408]40    initParameters.insert(initParameters.end(), mStreamSetOutputs.size(), consumerTy);
41
[5418]42    FunctionType * const initType = FunctionType::get(voidTy, initParameters, false);
[5431]43    Function * const initFunc = Function::Create(initType, GlobalValue::ExternalLinkage, getName() + INIT_SUFFIX, module);
[5418]44    initFunc->setCallingConv(CallingConv::C);
45    initFunc->setDoesNotThrow();
46    auto args = initFunc->arg_begin();
[5297]47    args->setName("self");
[5706]48    for (const Binding & binding : mScalarInputs) {
49        (++args)->setName(binding.getName());
[5049]50    }
[5706]51    for (const Binding & binding : mStreamSetOutputs) {
52        (++args)->setName(binding.getName() + "ConsumerLocks");
[5408]53    }
[5047]54
[5408]55    // Create the doSegment function prototype.
[5440]56    std::vector<Type *> params = {selfType, idb->getInt1Ty()};
[5401]57
[5706]58    const auto count = mStreamSetInputs.size();
59    params.insert(params.end(), count, sizeTy);
60
[5418]61    FunctionType * const doSegmentType = FunctionType::get(voidTy, params, false);
[5431]62    Function * const doSegment = Function::Create(doSegmentType, GlobalValue::ExternalLinkage, getName() + DO_SEGMENT_SUFFIX, module);
[5292]63    doSegment->setCallingConv(CallingConv::C);
64    doSegment->setDoesNotThrow();
65    args = doSegment->arg_begin();
[5297]66    args->setName("self");
[5985]67    (++args)->setName("isFinal");
[5398]68    for (const Binding & input : mStreamSetInputs) {
[5985]69        (++args)->setName(input.getName() + "AvailableItems");
[5263]70    }
[5287]71
[5411]72    // Create the terminate function prototype
[5418]73    Type * resultType = nullptr;
74    if (mScalarOutputs.empty()) {
[5440]75        resultType = idb->getVoidTy();
[5418]76    } else {
77        const auto n = mScalarOutputs.size();
78        Type * outputType[n];
79        for (unsigned i = 0; i < n; ++i) {
[5706]80            outputType[i] = mScalarOutputs[i].getType();
[5418]81        }
82        if (n == 1) {
83            resultType = outputType[0];
84        } else {
[5440]85            resultType = StructType::get(idb->getContext(), ArrayRef<Type *>(outputType, n));
[5418]86        }
87    }
88    FunctionType * const terminateType = FunctionType::get(resultType, {selfType}, false);
[5431]89    Function * const terminateFunc = Function::Create(terminateType, GlobalValue::ExternalLinkage, getName() + TERMINATE_SUFFIX, module);
[5411]90    terminateFunc->setCallingConv(CallingConv::C);
91    terminateFunc->setDoesNotThrow();
92    args = terminateFunc->arg_begin();
93    args->setName("self");
94
[5440]95    linkExternalMethods(idb);
[5047]96}
97
[5706]98void  KernelInterface::setInstance(Value * const instance) {
99    assert ("kernel instance cannot be null!" && instance);
100    assert ("kernel instance must point to a valid kernel state type!" && (instance->getType()->getPointerElementType() == mKernelStateType));
101    mKernelInstance = instance;
102}
103
[5431]104Function * KernelInterface::getInitFunction(Module * const module) const {
[5297]105    const auto name = getName() + INIT_SUFFIX;
[5431]106    Function * f = module->getFunction(name);
[5287]107    if (LLVM_UNLIKELY(f == nullptr)) {
108        llvm::report_fatal_error("Cannot find " + name);
[5053]109    }
[5287]110    return f;
[5053]111}
112
[5706]113Function * KernelInterface::getDoSegmentFunction(Module * const module) const {
[5297]114    const auto name = getName() + DO_SEGMENT_SUFFIX;
[5431]115    Function * f = module->getFunction(name);
[5287]116    if (LLVM_UNLIKELY(f == nullptr)) {
117        llvm::report_fatal_error("Cannot find " + name);
118    }
119    return f;
[5285]120}
[5411]121
[5431]122Function * KernelInterface::getTerminateFunction(Module * const module) const {
[5411]123    const auto name = getName() + TERMINATE_SUFFIX;
[5431]124    Function * f = module->getFunction(name);
[5411]125    if (LLVM_UNLIKELY(f == nullptr)) {
126        llvm::report_fatal_error("Cannot find " + name);
127    }
128    return f;
129}
[5706]130
131CallInst * KernelInterface::makeDoSegmentCall(kernel::KernelBuilder & idb, const std::vector<llvm::Value *> & args) const {
132    Function * const doSegment = getDoSegmentFunction(idb.getModule());
133    assert (doSegment->getArgumentList().size() <= args.size());
134    return idb.CreateCall(doSegment, args);
135}
136
137}
Note: See TracBrowser for help on using the repository browser.