source: icGREP/icgrep-devel/icgrep/kernels/streams_merge.cpp

Last change on this file was 6261, checked in by nmedfort, 7 months ago

Work on OptimizationBranch?; revisited pipeline termination

File size: 6.5 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
6#include "streams_merge.h"
7#include <kernels/kernel_builder.h>
8#include <llvm/Support/raw_ostream.h>
9
10using namespace llvm;
11
12namespace kernel {
13
14std::string makeKernelName(const std::string & prefix, const std::vector<StreamSet *> & inputs, StreamSet * const output) {
15    std::string tmp;
16    raw_string_ostream out(tmp);
17    out << prefix << inputs.size();
18    char joiner = 'x';
19    unsigned maxNumOfInputStreams = 0;
20    for (unsigned i = 0; i < inputs.size(); ++i) {
21        if (LLVM_UNLIKELY(inputs[i]->getFieldWidth() != 1)) {
22            report_fatal_error("input streams must be of field width 1");
23        }
24        maxNumOfInputStreams = std::max(maxNumOfInputStreams, inputs[i]->getNumElements());
25        out << joiner << inputs[i]->getNumElements();
26        joiner = '_';
27    }
28    if (LLVM_UNLIKELY(output->getNumElements() < maxNumOfInputStreams)) {
29        report_fatal_error("output streamset requires " + std::to_string(maxNumOfInputStreams) + " streams");
30    }
31    out << ':' << output->getNumElements();
32    out.flush();
33    return tmp;
34}
35
36StreamsMerge::StreamsMerge(const std::unique_ptr<kernel::KernelBuilder> & b, const std::vector<StreamSet *> & inputs, StreamSet * output)
37: BlockOrientedKernel(b, makeKernelName("streamsMerge", inputs, output), {}, {}, {}, {}, {}) {
38    for (unsigned i = 0; i < inputs.size(); i++) {
39        mInputStreamSets.push_back(Binding{"input" + std::to_string(i), inputs[i]});
40    }
41    mOutputStreamSets.push_back(Binding{"output", output});
42}
43
44void StreamsMerge::generateDoBlockMethod(const std::unique_ptr<KernelBuilder> &iBuilder) {
45
46    const auto n = getOutputStreamSet(0)->getNumElements();
47    std::vector<Value *> resultStreams(n, nullptr);
48    for (unsigned i = 0; i < getNumOfStreamInputs(); ++i) {
49        const auto m = getInputStreamSet(i)->getNumElements(); assert (m <= n);
50        for (unsigned j = 0; j < m; ++j) {
51            Value * const inputValue = iBuilder->loadInputStreamBlock("input" + std::to_string(i), iBuilder->getInt32(j));
52            if (resultStreams[j]) {
53                resultStreams[j] = iBuilder->CreateOr(resultStreams[j], inputValue);
54            } else {
55                resultStreams[j] = inputValue;
56            }
57        }
58    }
59
60    for (unsigned j = 0; j < n; j++) {
61        Value * output = resultStreams[j];
62        if (LLVM_UNLIKELY(output == nullptr)) {
63            output = iBuilder->allZeroes();
64        }
65        iBuilder->storeOutputStreamBlock("output", iBuilder->getInt32(j), output);
66    }
67}
68
69StreamsIntersect::StreamsIntersect(const std::unique_ptr<kernel::KernelBuilder> & b, const std::vector<StreamSet *> & inputs, StreamSet * output)
70: BlockOrientedKernel(b, makeKernelName("streamsIntersect", inputs, output), {}, {}, {}, {}, {}) {
71    for (unsigned i = 0; i < inputs.size(); i++) {
72        mInputStreamSets.push_back(Binding{"input" + std::to_string(i), inputs[i]});
73    }
74    mOutputStreamSets.push_back(Binding{"output", output});
75}
76
77void StreamsIntersect::generateDoBlockMethod(const std::unique_ptr<KernelBuilder> &iBuilder) {
78    const auto n = getOutputStreamSet(0)->getNumElements();
79    std::vector<Value *> resultStreams(n, nullptr);
80    for (unsigned i = 0; i < getNumOfStreamInputs(); ++i) {
81        const auto m = getInputStreamSet(i)->getNumElements(); assert (m <= n);
82        for (unsigned j = 0; j < m; ++j) {
83            Value * const inputValue = iBuilder->loadInputStreamBlock("input" + std::to_string(i), iBuilder->getInt32(j));
84            if (resultStreams[j]) {
85                resultStreams[j] = iBuilder->CreateAnd(resultStreams[j], inputValue);
86            } else {
87                resultStreams[j] = inputValue;
88            }
89        }
90    }
91
92    for (unsigned j = 0; j < n; j++) {
93        Value * output = resultStreams[j];
94        if (LLVM_UNLIKELY(output == nullptr)) {
95            output = iBuilder->allZeroes();
96        }
97        iBuilder->storeOutputStreamBlock("output", iBuilder->getInt32(j), output);
98    }
99}
100
101StreamsCombineKernel::StreamsCombineKernel(const std::unique_ptr<kernel::KernelBuilder> & b,
102                                                     std::vector<unsigned> streamsNumOfSets)
103: BlockOrientedKernel(b, "StreamsCombineKernel" , {}, {}, {}, {}, {})
104, mStreamsNumOfSets(streamsNumOfSets) {
105    int total = 0;
106    for (unsigned i = 0; i < streamsNumOfSets.size(); i++) {
107        total += streamsNumOfSets[i];
108        mInputStreamSets.push_back(Binding{b->getStreamSetTy(streamsNumOfSets[i], 1), "inputGroup" + std::to_string(i)});
109    }
110    mOutputStreamSets.push_back(Binding{b->getStreamSetTy(total, 1), "output"});
111}
112
113void StreamsCombineKernel::generateDoBlockMethod(const std::unique_ptr<kernel::KernelBuilder> &iBuilder) {
114    unsigned outputIndex = 0;
115    for (unsigned i = 0; i < mStreamsNumOfSets.size(); i++) {
116        unsigned streamNum = mStreamsNumOfSets[i];
117        for (unsigned j = 0; j < streamNum; j++) {
118            iBuilder->storeOutputStreamBlock(
119                    "output",
120                    iBuilder->getInt32(outputIndex),
121                    iBuilder->loadInputStreamBlock(
122                            "inputGroup" + std::to_string(i),
123                            iBuilder->getInt32(j)
124                    )
125            );
126            ++outputIndex;
127        }
128    }
129}
130
131
132StreamsSplitKernel::StreamsSplitKernel(const std::unique_ptr<kernel::KernelBuilder> &b,
133                                       std::vector<unsigned> streamsNumOfSets)
134: BlockOrientedKernel(b, "StreamsSplitKernel" , {}, {}, {}, {}, {})
135, mStreamsNumOfSets(streamsNumOfSets){
136    int total = 0;
137    for (unsigned i = 0; i < streamsNumOfSets.size(); i++) {
138        total += streamsNumOfSets[i];
139        mOutputStreamSets.push_back(Binding{b->getStreamSetTy(streamsNumOfSets[i], 1), "outputGroup" + std::to_string(i)});
140    }
141    mInputStreamSets.push_back(Binding{b->getStreamSetTy(total, 1), "input"});
142}
143
144void StreamsSplitKernel::generateDoBlockMethod(const std::unique_ptr<kernel::KernelBuilder> &iBuilder) {
145    unsigned inputIndex = 0;
146    for (unsigned i = 0; i < mStreamsNumOfSets.size(); i++) {
147        unsigned streamNum = mStreamsNumOfSets[i];
148        for (unsigned j = 0; j < streamNum; j++) {
149            iBuilder->storeOutputStreamBlock(
150                    "outputGroup" + std::to_string(i),
151                    iBuilder->getInt32(j),
152                    iBuilder->loadInputStreamBlock("input", iBuilder->getInt32(inputIndex))
153            );
154            ++inputIndex;
155        }
156    }
157}
158}
Note: See TracBrowser for help on using the repository browser.