source: icGREP/icgrep-devel/icgrep/pablo/pablo_kernel.cpp @ 5486

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

Initial attempt to improve debugging capabilities with compilation stack traces on error.

File size: 7.4 KB
RevLine 
[5057]1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
[5260]6#include "pablo_kernel.h"
[5227]7#include <pablo/codegenstate.h>
[5059]8#include <pablo/pablo_compiler.h>
[5202]9#include <pablo/pe_var.h>
[5267]10#include <pablo/pe_zeroes.h>
11#include <pablo/pe_ones.h>
[5418]12#include <pablo/pablo_toolchain.h>
[5436]13#include <kernels/kernel_builder.h>
[5440]14#include <llvm/IR/Module.h>
[5057]15
[5059]16using namespace kernel;
[5100]17using namespace parabix;
[5217]18using namespace IDISA;
[5267]19using namespace llvm;
[5057]20
[5298]21inline bool isStreamType(const Type * ty) {
22    if (ty->isArrayTy()) {
23        ty = ty->getArrayElementType();
24    }
25    if (ty->isVectorTy()) {
26        return (ty->getVectorNumElements() == 0);
27    }
28    return false;
29}
30
[5464]31namespace pablo {
32
[5398]33Var * PabloKernel::getInputStreamVar(const std::string & name) {
34    Port port; unsigned index;
35    std::tie(port, index) = getStreamPort(name);
36    assert (port == Port::Input);
37    return mInputs[index];
[5299]38}
39
[5398]40Var * PabloKernel::getOutputStreamVar(const std::string & name) {
41    Port port; unsigned index;
42    std::tie(port, index) = getStreamPort(name);
43    assert (port == Port::Output);
44    return mOutputs[index];
[5299]45}
46
[5398]47Var * PabloKernel::getOutputScalarVar(const std::string & name) {
48    const auto f = mScalarOutputNameMap.find(name);
[5300]49    if (LLVM_UNLIKELY(f == mScalarOutputNameMap.end())) {
[5398]50        report_fatal_error("Kernel does not contain scalar: " + name);
[5300]51    }
52    return f->second;
53}
54
[5246]55Var * PabloKernel::addInput(const std::string & name, Type * const type) {
[5440]56    Var * param = new (mAllocator) Var(makeName(name), type, mAllocator, Var::KernelInputParameter);
[5283]57    param->addUser(this);
[5217]58    mInputs.push_back(param);
[5283]59    mVariables.push_back(param);
[5298]60    if (isStreamType(type)) {
[5398]61        mStreamMap.emplace(name, std::make_pair(Port::Input, mStreamSetInputs.size()));
[5310]62        mStreamSetInputs.emplace_back(type, name);       
[5217]63    } else {
64        mScalarInputs.emplace_back(type, name);
[5310]65        param->setScalar();
[5217]66    }
67    assert (mStreamSetInputs.size() + mScalarInputs.size() == mInputs.size());
68    return param;
69}
[5202]70
[5267]71Var * PabloKernel::addOutput(const std::string & name, Type * const type) {
[5440]72    Var * result = new (mAllocator) Var(makeName(name), type, mAllocator, Var::KernelOutputParameter);
[5283]73    result->addUser(this);
[5217]74    mOutputs.push_back(result);
[5283]75    mVariables.push_back(result);
[5298]76    if (isStreamType(type)) {
[5398]77        mStreamMap.emplace(name, std::make_pair(Port::Output, mStreamSetOutputs.size()));
[5227]78        mStreamSetOutputs.emplace_back(type, name);
[5217]79    } else {
80        mScalarOutputs.emplace_back(type, name);
[5300]81        mScalarOutputNameMap.emplace(name, result);
[5310]82        result->setScalar();
[5133]83    }
[5217]84    assert (mStreamSetOutputs.size() + mScalarOutputs.size() == mOutputs.size());
85    return result;
86}
[5057]87
[5283]88Var * PabloKernel::makeVariable(String * name, Type * const type) {
[5230]89    Var * const var = new (mAllocator) Var(name, type, mAllocator);
[5217]90    mVariables.push_back(var);
91    return var;
92}
[5204]93
[5217]94Zeroes * PabloKernel::getNullValue(Type * type) {
[5446]95    if (LLVM_LIKELY(type == nullptr)) {
96        type = getStreamTy();
[5217]97    }
98    for (PabloAST * constant : mConstants) {
99        if (isa<Zeroes>(constant) && constant->getType() == type) {
100            return cast<Zeroes>(constant);
[5202]101        }
[5057]102    }
[5230]103    Zeroes * value = new (mAllocator) Zeroes(type, mAllocator);
[5217]104    mConstants.push_back(value);
105    return value;
[5057]106}
107
[5217]108Ones * PabloKernel::getAllOnesValue(Type * type) {
[5446]109    if (LLVM_LIKELY(type == nullptr)) {
110        type = getStreamTy();
[5217]111    }
112    for (PabloAST * constant : mConstants) {
113        if (isa<Ones>(constant) && constant->getType() == type) {
114            return cast<Ones>(constant);
115        }
116    }
[5230]117    Ones * value = new (mAllocator) Ones(type, mAllocator);
[5217]118    mConstants.push_back(value);
119    return value;
[5202]120}
121
[5440]122void PabloKernel::prepareKernel(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) {
[5446]123    mSizeTy = iBuilder->getSizeTy();
124    mStreamTy = iBuilder->getStreamTy();
125    generatePabloMethod();   
[5436]126    pablo_function_passes(this);
[5435]127    mPabloCompiler->initializeKernelData(iBuilder);
[5446]128    mSizeTy = nullptr;
129    mStreamTy = nullptr;
[5440]130    BlockOrientedKernel::prepareKernel(iBuilder);
[5062]131}
[5059]132
[5440]133void PabloKernel::generateDoBlockMethod(const std::unique_ptr<KernelBuilder> & iBuilder) {
[5446]134    mSizeTy = iBuilder->getSizeTy();
135    mStreamTy = iBuilder->getStreamTy();
[5435]136    mPabloCompiler->compile(iBuilder);
[5446]137    mSizeTy = nullptr;
138    mStreamTy = nullptr;
[5057]139}
140
[5440]141void PabloKernel::generateFinalBlockMethod(const std::unique_ptr<KernelBuilder> & iBuilder, Value * const remainingBytes) {
[5057]142    // Standard Pablo convention for final block processing: set a bit marking
[5121]143    // the position just past EOF, as well as a mask marking all positions past EOF.
[5440]144    iBuilder->setScalarField("EOFbit", iBuilder->bitblock_set_bit(remainingBytes));
145    iBuilder->setScalarField("EOFmask", iBuilder->bitblock_mask_from(remainingBytes));
146    CreateDoBlockMethodCall(iBuilder);
[5057]147}
[5217]148
[5486]149void PabloKernel::generateFinalizeMethod(const std::unique_ptr<kernel::KernelBuilder> & iBuilder) {
150    mPabloCompiler->releaseKernelData(iBuilder);
151}
152
[5436]153String * PabloKernel::makeName(const llvm::StringRef & prefix) const {
[5440]154    return mSymbolTable->makeString(prefix);
[5436]155}
156
157Integer * PabloKernel::getInteger(const int64_t value) const {
[5440]158    return mSymbolTable->getInteger(value);
[5436]159}
160
[5446]161llvm::IntegerType * PabloKernel::getInt1Ty() const {
162    return IntegerType::getInt1Ty(getModule()->getContext());
163}
164
[5454]165static inline std::string annotateKernelNameWithDebugFlags(std::string && name) {
166    if (DebugOptionIsSet(DumpTrace)) {
167        name += "_DumpTrace";
168    }
169    return name;
170}
171
[5436]172PabloKernel::PabloKernel(const std::unique_ptr<KernelBuilder> & b,
[5454]173                         std::string && kernelName,
[5310]174                         std::vector<Binding> stream_inputs,
175                         std::vector<Binding> stream_outputs,
176                         std::vector<Binding> scalar_parameters,
177                         std::vector<Binding> scalar_outputs)
[5454]178: BlockOrientedKernel(std::move(annotateKernelNameWithDebugFlags(std::move(kernelName))),
[5299]179                      std::move(stream_inputs), std::move(stream_outputs), 
[5310]180                      std::move(scalar_parameters), std::move(scalar_outputs),
[5435]181                      {Binding{b->getBitBlockType(), "EOFbit"}, Binding{b->getBitBlockType(), "EOFmask"}})
[5299]182, PabloAST(PabloAST::ClassTypeId::Kernel, nullptr, mAllocator)
183, mPabloCompiler(new PabloCompiler(this))
[5440]184, mSymbolTable(new SymbolGenerator(b->getContext(), mAllocator))
185, mEntryBlock(PabloBlock::Create(this))
[5446]186, mSizeTy(nullptr)
187, mStreamTy(nullptr) {
[5392]188    prepareStreamSetNameMap();
[5310]189    for (const Binding & ss : mStreamSetInputs) {
[5440]190        Var * param = new (mAllocator) Var(makeName(ss.name), ss.type, mAllocator, Var::KernelInputParameter);
[5299]191        param->addUser(this);
192        mInputs.push_back(param);
193        mVariables.push_back(param);
194    }
[5310]195    for (const Binding & ss : mStreamSetOutputs) {
[5440]196        Var * result = new (mAllocator) Var(makeName(ss.name), ss.type, mAllocator, Var::KernelOutputParameter);
[5299]197        result->addUser(this);
198        mOutputs.push_back(result);
199        mVariables.push_back(result);
200    }
[5310]201    for (const Binding & ss : mScalarOutputs) {
[5440]202        Var * result = new (mAllocator) Var(makeName(ss.name), ss.type, mAllocator, Var::KernelOutputParameter);
[5299]203        result->addUser(this);
204        mOutputs.push_back(result);
205        mVariables.push_back(result);
[5300]206        mScalarOutputNameMap.emplace(ss.name, result);
[5319]207        result->setScalar();
[5299]208    }
209}
210
[5217]211PabloKernel::~PabloKernel() {
212    delete mPabloCompiler;
[5240]213    delete mSymbolTable; 
[5217]214}
215
[5464]216}
Note: See TracBrowser for help on using the repository browser.