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

Last change on this file since 5260 was 5260, checked in by nmedfort, 9 months ago

Changes working towards simplifying accessing stream elements + some modifications to simplify include / forward declarations within the CodeGen? library.

File size: 5.2 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 "pablo_kernel.h"
7#include <pablo/codegenstate.h>
8#include <pablo/pablo_compiler.h>
9#include <pablo/pe_var.h>
10#include <llvm/IR/Module.h>
11#include <llvm/IR/Verifier.h>
12#include <IR_Gen/idisa_builder.h>
13
14using namespace pablo;
15using namespace kernel;
16using namespace parabix;
17using namespace IDISA;
18
19Var * PabloKernel::addInput(const std::string & name, Type * const type) {
20    Var * param = new (mAllocator) Var(mSymbolTable->make(name, iBuilder), type, mAllocator, true);
21    mInputs.push_back(param);
22    if (isa<ArrayType>(type) || isa<StreamType>(type)) {
23        mStreamSetInputs.emplace_back(type, name);
24    } else {
25        mScalarInputs.emplace_back(type, name);
26    }
27    assert (mStreamSetInputs.size() + mScalarInputs.size() == mInputs.size());
28    return param;
29}
30
31Var * PabloKernel::addOutput(const std::string name, Type * const type) {
32    Var * result = new (mAllocator) Var(mSymbolTable->make(name, iBuilder), type, mAllocator, false);
33    mOutputs.push_back(result);
34    if (isa<ArrayType>(type) || isa<StreamType>(type)) {
35        mStreamSetOutputs.emplace_back(type, name);
36    } else {
37        mScalarOutputs.emplace_back(type, name);
38    }
39    assert (mStreamSetOutputs.size() + mScalarOutputs.size() == mOutputs.size());
40    return result;
41}
42
43Var * PabloKernel::makeVariable(PabloAST * name, Type * const type) {
44    Var * const var = new (mAllocator) Var(name, type, mAllocator);
45    mVariables.push_back(var);
46    return var;
47}
48
49Zeroes * PabloKernel::getNullValue(Type * type) {
50    if (type == nullptr) {
51        type = getStreamTy();
52    }
53    for (PabloAST * constant : mConstants) {
54        if (isa<Zeroes>(constant) && constant->getType() == type) {
55            return cast<Zeroes>(constant);
56        }
57    }
58    Zeroes * value = new (mAllocator) Zeroes(type, mAllocator);
59    mConstants.push_back(value);
60    return value;
61}
62
63Ones * PabloKernel::getAllOnesValue(Type * type) {
64    if (type == nullptr) {
65        type = getStreamTy();
66    }
67    for (PabloAST * constant : mConstants) {
68        if (isa<Ones>(constant) && constant->getType() == type) {
69            return cast<Ones>(constant);
70        }
71    }
72    Ones * value = new (mAllocator) Ones(type, mAllocator);
73    mConstants.push_back(value);
74    return value;
75}
76
77void PabloKernel::prepareKernel() {
78    mPabloCompiler->initializeKernelData();
79    KernelBuilder::prepareKernel();
80}
81
82void PabloKernel::generateDoBlockMethod() const {
83    auto savePoint = iBuilder->saveIP();
84    Module * const m = iBuilder->getModule();
85    Function * const f = m->getFunction(mKernelName + doBlock_suffix);
86    Value * const self = &*(f->arg_begin());
87    mPabloCompiler->compile(self, f);
88    for (auto ss : mStreamSetOutputs) {
89        Value * produced = getProducedItemCount(self, ss.name);
90        produced = iBuilder->CreateAdd(produced, iBuilder->getSize(iBuilder->getStride()));
91        setProducedItemCount(self, ss.name, produced);
92    }
93    iBuilder->CreateRetVoid();
94    #ifndef NDEBUG
95    llvm::verifyFunction(*f, &errs());
96    #endif
97    iBuilder->restoreIP(savePoint);
98}
99
100void PabloKernel::generateFinalBlockMethod() const {
101    auto savePoint = iBuilder->saveIP();
102    Module * m = iBuilder->getModule();
103    Function * doBlockFunction = m->getFunction(mKernelName + doBlock_suffix);
104    Function * finalBlockFunction = m->getFunction(mKernelName + finalBlock_suffix);
105    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "fb_entry", finalBlockFunction, 0));
106    // Final Block arguments: self, remaining, then the standard DoBlock args.
107    Function::arg_iterator args = finalBlockFunction->arg_begin();
108    Value * self = &*(args++);
109    Value * remaining = &*(args++);
110    std::vector<Value *> doBlockArgs = {self};
111    while (args != finalBlockFunction->arg_end()){
112        doBlockArgs.push_back(&*args++);
113    }
114    // Standard Pablo convention for final block processing: set a bit marking
115    // the position just past EOF, as well as a mask marking all positions past EOF.
116    setScalarField(self, "EOFbit", iBuilder->bitblock_set_bit(remaining));
117    setScalarField(self, "EOFmask", iBuilder->bitblock_mask_from(remaining));
118    iBuilder->CreateCall(doBlockFunction, doBlockArgs);
119    /* Adjust the produced item count */
120    for (auto ss : mStreamSetOutputs) {
121        Value * produced = getProducedItemCount(self, ss.name);
122        produced = iBuilder->CreateSub(produced, iBuilder->getSize(iBuilder->getStride()));
123        produced = iBuilder->CreateAdd(produced, remaining);
124        setProducedItemCount(self, ss.name, produced);
125    }
126    iBuilder->CreateRetVoid();
127    #ifndef NDEBUG
128    llvm::verifyFunction(*finalBlockFunction, &errs());
129    #endif
130    iBuilder->restoreIP(savePoint);
131}
132
133PabloKernel::PabloKernel(IDISA::IDISA_Builder * builder, const std::string & kernelName)
134: KernelBuilder(builder, kernelName, {}, {}, {}, {}, {Binding{builder->getBitBlockType(), "EOFbit"}, Binding{builder->getBitBlockType(), "EOFmask"}})
135, mPabloCompiler(new PabloCompiler(this))
136, mSymbolTable(new SymbolGenerator(mAllocator))
137, mEntryBlock(PabloBlock::Create(this)) {
138
139}
140
141PabloKernel::~PabloKernel() {
142    delete mPabloCompiler;
143    delete mSymbolTable; 
144}
145
Note: See TracBrowser for help on using the repository browser.