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

Last change on this file was 6274, checked in by nmedfort, 6 months ago

Fixed cycle counter logic and moved counters into pipeline struct

File size: 13.3 KB
Line 
1#include "kernel_builder.h"
2#include <toolchain/toolchain.h>
3#include <kernels/kernel.h>
4#include <kernels/streamset.h>
5#include <llvm/Support/raw_ostream.h>
6#include <llvm/IR/Module.h>
7
8using namespace llvm;
9
10inline static bool is_power_2(const uint64_t n) {
11    return ((n & (n - 1)) == 0) && n;
12}
13
14namespace kernel {
15
16using Port = Kernel::Port;
17
18Value * KernelBuilder::getScalarFieldPtr(const StringRef fieldName) {
19    return mKernel->getScalarFieldPtr(*this, fieldName);
20}
21
22Value * KernelBuilder::getScalarField(const StringRef fieldName) {
23    return CreateLoad(getScalarFieldPtr(fieldName));
24}
25
26void KernelBuilder::setScalarField(const StringRef fieldName, Value * const value) {
27    CreateStore(value, getScalarFieldPtr(fieldName));
28}
29
30/** ------------------------------------------------------------------------------------------------------------- *
31 * @brief getProcessedItemCount
32 ** ------------------------------------------------------------------------------------------------------------- */
33Value * KernelBuilder::getProcessedItemCount(const StringRef name) {
34    return CreateLoad(mKernel->getProcessedInputItemsPtr(name));
35}
36
37/** ------------------------------------------------------------------------------------------------------------- *
38 * @brief setProcessedItemCount
39 ** ------------------------------------------------------------------------------------------------------------- */
40void KernelBuilder::setProcessedItemCount(const StringRef name, Value * value) {
41    CreateStore(value, mKernel->getProcessedInputItemsPtr(name));
42}
43
44/** ------------------------------------------------------------------------------------------------------------- *
45 * @brief getProducedItemCount
46 ** ------------------------------------------------------------------------------------------------------------- */
47Value * KernelBuilder::getProducedItemCount(const StringRef name) {
48    return CreateLoad(mKernel->getProducedOutputItemsPtr(name));
49}
50
51/** ------------------------------------------------------------------------------------------------------------- *
52 * @brief setProducedItemCount
53 ** ------------------------------------------------------------------------------------------------------------- */
54void KernelBuilder::setProducedItemCount(const StringRef name, Value * value) {
55    CreateStore(value, mKernel->getProducedOutputItemsPtr(name));
56}
57
58/** ------------------------------------------------------------------------------------------------------------- *
59 * @brief getConsumedItemCount
60 ** ------------------------------------------------------------------------------------------------------------- */
61Value * KernelBuilder::getConsumedItemCount(const StringRef name) const {
62    return mKernel->getConsumedOutputItems(name);
63}
64
65/** ------------------------------------------------------------------------------------------------------------- *
66 * @brief getTerminationSignal
67 ** ------------------------------------------------------------------------------------------------------------- */
68Value * KernelBuilder::getTerminationSignal() {
69    Value * const ptr = mKernel->getTerminationSignalPtr();
70    if (ptr) {
71        return CreateLoad(ptr);
72    } else {
73        return getFalse();
74    }
75}
76
77/** ------------------------------------------------------------------------------------------------------------- *
78 * @brief setTerminationSignal
79 ** ------------------------------------------------------------------------------------------------------------- */
80void KernelBuilder::setTerminationSignal(Value * const value) {
81    assert (value);
82    assert (value->getType() == getInt1Ty());
83    if (codegen::DebugOptionIsSet(codegen::TraceCounts)) {
84        CallPrintInt(mKernel->getName() + ": setTerminationSignal", value);
85    }
86    Value * const ptr = mKernel->getTerminationSignalPtr();
87    if (LLVM_UNLIKELY(ptr == nullptr)) {
88        report_fatal_error(mKernel->getName() + " does not have CanTerminateEarly or MustExplicitlyTerminate set.");
89    }
90    CreateStore(value, ptr);
91}
92
93Value * KernelBuilder::getInputStreamBlockPtr(const std::string & name, Value * const streamIndex, Value * const blockOffset) {
94    const StreamSetBuffer * const buf = mKernel->getInputStreamSetBuffer(name);
95    Value * const processed = getProcessedItemCount(name);
96    Value * blockIndex = CreateLShr(processed, std::log2(getBitBlockWidth()));
97    if (blockOffset) {
98        blockIndex = CreateAdd(blockIndex, CreateZExtOrTrunc(blockOffset, blockIndex->getType()));
99    }
100    return buf->getStreamBlockPtr(this, streamIndex, blockIndex);
101}
102
103Value * KernelBuilder::getInputStreamPackPtr(const std::string & name, Value * const streamIndex, Value * const packIndex, Value * const blockOffset) {
104    const StreamSetBuffer * const buf = mKernel->getInputStreamSetBuffer(name);
105    Value * const processed = getProcessedItemCount(name);
106    Value * blockIndex = CreateLShr(processed, std::log2(getBitBlockWidth()));
107    if (blockOffset) {
108        blockIndex = CreateAdd(blockIndex, CreateZExtOrTrunc(blockOffset, blockIndex->getType()));
109    }
110    return buf->getStreamPackPtr(this, streamIndex, blockIndex, packIndex);
111}
112
113Value * KernelBuilder::loadInputStreamBlock(const std::string & name, Value * const streamIndex, Value * const blockOffset) {
114    return CreateBlockAlignedLoad(getInputStreamBlockPtr(name, streamIndex, blockOffset));
115}
116
117Value * KernelBuilder::loadInputStreamPack(const std::string & name, Value * const streamIndex, Value * const packIndex, Value * const blockOffset) {
118    return CreateBlockAlignedLoad(getInputStreamPackPtr(name, streamIndex, packIndex, blockOffset));
119}
120
121Value * KernelBuilder::getInputStreamSetCount(const std::string & name) {
122    const StreamSetBuffer * const buf = mKernel->getInputStreamSetBuffer(name);
123    return buf->getStreamSetCount(this);
124}
125
126Value * KernelBuilder::getOutputStreamBlockPtr(const std::string & name, Value * streamIndex, Value * const blockOffset) {
127    const StreamSetBuffer * const buf = mKernel->getOutputStreamSetBuffer(name);
128    Value * const produced = getProducedItemCount(name);
129    Value * blockIndex = CreateLShr(produced, std::log2(getBitBlockWidth()));
130    if (blockOffset) {
131        blockIndex = CreateAdd(blockIndex, CreateZExtOrTrunc(blockOffset, blockIndex->getType()));
132    }
133    return buf->getStreamBlockPtr(this, streamIndex, blockIndex);
134}
135
136Value * KernelBuilder::getOutputStreamPackPtr(const std::string & name, Value * streamIndex, Value * packIndex, Value * blockOffset) {
137    const StreamSetBuffer * const buf = mKernel->getOutputStreamSetBuffer(name);
138    Value * const produced = getProducedItemCount(name);
139    Value * blockIndex = CreateLShr(produced, std::log2(getBitBlockWidth()));
140    if (blockOffset) {
141        blockIndex = CreateAdd(blockIndex, CreateZExtOrTrunc(blockOffset, blockIndex->getType()));
142    }
143    return buf->getStreamPackPtr(this, streamIndex, blockIndex, packIndex);
144}
145
146StoreInst * KernelBuilder::storeOutputStreamBlock(const std::string & name, Value * streamIndex, Value * blockOffset, Value * toStore) {
147    Value * const ptr = getOutputStreamBlockPtr(name, streamIndex, blockOffset);
148    Type * const storeTy = toStore->getType();
149    Type * const ptrElemTy = ptr->getType()->getPointerElementType();
150    if (LLVM_UNLIKELY(storeTy != ptrElemTy)) {
151        if (LLVM_LIKELY(storeTy->canLosslesslyBitCastTo(ptrElemTy))) {
152            toStore = CreateBitCast(toStore, ptrElemTy);
153        } else {
154            std::string tmp;
155            raw_string_ostream out(tmp);
156            out << "invalid type conversion when calling storeOutputStreamBlock on " <<  name << ": ";
157            ptrElemTy->print(out);
158            out << " vs. ";
159            storeTy->print(out);
160        }
161    }
162    return CreateBlockAlignedStore(toStore, ptr);
163}
164
165StoreInst * KernelBuilder::storeOutputStreamPack(const std::string & name, Value * streamIndex, Value * packIndex, Value * blockOffset, Value * toStore) {
166    Value * const ptr = getOutputStreamPackPtr(name, streamIndex, packIndex, blockOffset);
167    Type * const storeTy = toStore->getType();
168    Type * const ptrElemTy = ptr->getType()->getPointerElementType();
169    if (LLVM_UNLIKELY(storeTy != ptrElemTy)) {
170        if (LLVM_LIKELY(storeTy->canLosslesslyBitCastTo(ptrElemTy))) {
171            toStore = CreateBitCast(toStore, ptrElemTy);
172        } else {
173            std::string tmp;
174            raw_string_ostream out(tmp);
175            out << "invalid type conversion when calling storeOutputStreamPack on " <<  name << ": ";
176            ptrElemTy->print(out);
177            out << " vs. ";
178            storeTy->print(out);
179        }
180    }
181    return CreateBlockAlignedStore(toStore, ptr);
182}
183
184Value * KernelBuilder::getOutputStreamSetCount(const std::string & name) {
185    const StreamSetBuffer * const buf = mKernel->getOutputStreamSetBuffer(name);
186    return buf->getStreamSetCount(this);
187}
188
189Value * KernelBuilder::getRawInputPointer(const std::string & name, Value * absolutePosition) {
190    const StreamSetBuffer * const buf = mKernel->getInputStreamSetBuffer(name);
191    return buf->getRawItemPointer(this, absolutePosition);
192}
193
194Value * KernelBuilder::getRawOutputPointer(const std::string & name, Value * absolutePosition) {
195    const StreamSetBuffer * const buf = mKernel->getOutputStreamSetBuffer(name);
196    return buf->getRawItemPointer(this, absolutePosition);
197}
198
199Value * KernelBuilder::getBaseAddress(const std::string & name) {
200    return mKernel->getStreamSetBuffer(name)->getBaseAddress(this);
201}
202
203void KernelBuilder::setBaseAddress(const std::string & name, Value * const addr) {
204    return mKernel->getStreamSetBuffer(name)->setBaseAddress(this, addr);
205}
206
207Value * KernelBuilder::getCapacity(const std::string & name) {
208    return mKernel->getStreamSetBuffer(name)->getCapacity(this);
209}
210
211void KernelBuilder::setCapacity(const std::string & name, Value * capacity) {
212    mKernel->getStreamSetBuffer(name)->setCapacity(this, capacity);
213}
214
215/** ------------------------------------------------------------------------------------------------------------- *
216 * @brief CreateUDiv2
217 ** ------------------------------------------------------------------------------------------------------------- */
218Value * KernelBuilder::CreateUDiv2(Value * const number, const ProcessingRate::RateValue & divisor, const Twine & Name) {
219    if (divisor.numerator() == 1 && divisor.denominator() == 1) {
220        return number;
221    }
222    Constant * const n = ConstantInt::get(number->getType(), divisor.numerator());
223    if (LLVM_LIKELY(divisor.denominator() == 1)) {
224        return CreateUDiv(number, n, Name);
225    } else {
226        Constant * const d = ConstantInt::get(number->getType(), divisor.denominator());
227        return CreateUDiv(CreateMul(number, d), n);
228    }
229}
230
231/** ------------------------------------------------------------------------------------------------------------- *
232 * @brief CreateCeilUDiv2
233 ** ------------------------------------------------------------------------------------------------------------- */
234Value * KernelBuilder::CreateCeilUDiv2(Value * const number, const ProcessingRate::RateValue & divisor, const Twine & Name) {
235    if (divisor.numerator() == 1 && divisor.denominator() == 1) {
236        return number;
237    }
238    Constant * const n = ConstantInt::get(number->getType(), divisor.numerator());
239    if (LLVM_LIKELY(divisor.denominator() == 1)) {
240        return CreateCeilUDiv(number, n, Name);
241    } else {
242        //   âŒŠ(num + ratio - 1) / ratio⌋
243        // = ⌊(num - 1) / (n/d)⌋ + (ratio/ratio)
244        // = ⌊(d * (num - 1)) / n⌋ + 1
245        Constant * const ONE = ConstantInt::get(number->getType(), 1);
246        Constant * const d = ConstantInt::get(number->getType(), divisor.denominator());
247        return CreateAdd(CreateUDiv(CreateMul(CreateSub(number, ONE), d), n), ONE, Name);
248    }
249}
250
251/** ------------------------------------------------------------------------------------------------------------- *
252 * @brief CreateMul2
253 ** ------------------------------------------------------------------------------------------------------------- */
254Value * KernelBuilder::CreateMul2(Value * const number, const ProcessingRate::RateValue & factor, const Twine & Name) {
255    if (factor.numerator() == 1 && factor.denominator() == 1) {
256        return number;
257    }
258    Constant * const n = ConstantInt::get(number->getType(), factor.numerator());
259    if (LLVM_LIKELY(factor.denominator() == 1)) {
260        return CreateMul(number, n, Name);
261    } else {
262        Constant * const d = ConstantInt::get(number->getType(), factor.denominator());
263        return CreateUDiv(CreateMul(number, n), d, Name);
264    }
265}
266
267/** ------------------------------------------------------------------------------------------------------------- *
268 * @brief CreateMulCeil2
269 ** ------------------------------------------------------------------------------------------------------------- */
270Value * KernelBuilder::CreateCeilUMul2(Value * const number, const ProcessingRate::RateValue & factor, const Twine & Name) {
271    if (factor.denominator() == 1) {
272        return CreateMul2(number, factor, Name);
273    }
274    Constant * const n = ConstantInt::get(number->getType(), factor.numerator());
275    Constant * const d = ConstantInt::get(number->getType(), factor.denominator());
276    return CreateCeilUDiv(CreateMul(number, n), d, Name);
277}
278
279/** ------------------------------------------------------------------------------------------------------------- *
280 * @brief getKernelName
281 ** ------------------------------------------------------------------------------------------------------------- */
282std::string KernelBuilder::getKernelName() const {
283    return mKernel->getName();
284}
285
286}
Note: See TracBrowser for help on using the repository browser.