source: icGREP/icgrep-devel/icgrep/kernels/streamset.cpp @ 5357

Last change on this file since 5357 was 5355, checked in by cameron, 2 years ago

Swizzled bitstream deletion and -enable-AVX-deletion in u8u16

File size: 23.5 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 "streamset.h"
7#include <IR_Gen/idisa_builder.h>  // for IDISA_Builder
8#include <llvm/IR/BasicBlock.h>    // for BasicBlock
9#include <llvm/IR/Constants.h>     // for ConstantInt
10#include <llvm/IR/DataLayout.h>    // for DataLayout
11#include <llvm/IR/DerivedTypes.h>  // for IntegerType (ptr only), PointerType
12#include <llvm/IR/Module.h>        // for Module
13#include <llvm/IR/Value.h>         // for Value
14#include <llvm/Support/raw_ostream.h>
15#include <llvm/IR/CFG.h>
16
17namespace llvm { class Constant; }
18namespace llvm { class Function; }
19
20using namespace parabix;
21using namespace llvm;
22using namespace IDISA;
23
24ArrayType * resolveStreamSetType(IDISA_Builder * const b, Type * type);
25
26StructType * resolveExpandableStreamSetType(IDISA_Builder * const b, Type * type);
27
28void StreamSetBuffer::allocateBuffer() {
29    Type * const ty = getType();
30    ConstantInt * blocks = iBuilder->getSize(mBufferBlocks);
31    mStreamSetBufferPtr = iBuilder->CreateCacheAlignedAlloca(ty, iBuilder->getSize(mBufferBlocks));
32    Constant * width = ConstantExpr::getMul(ConstantExpr::getSizeOf(ty), blocks);
33    iBuilder->CreateMemZero(mStreamSetBufferPtr, width, iBuilder->getCacheAlignment());
34}
35
36Value * StreamSetBuffer::getStreamBlockPtr(Value * self, Value * streamIndex, Value * blockIndex, const bool /* readOnly */) const {
37    iBuilder->CreateAssert(iBuilder->CreateICmpULT(streamIndex, getStreamSetCount(self)), "StreamSetBuffer: out-of-bounds stream access");
38    return iBuilder->CreateGEP(getStreamSetBlockPtr(self, blockIndex), {iBuilder->getInt32(0), streamIndex});
39}
40
41Value * StreamSetBuffer::getStreamPackPtr(Value * self, Value * streamIndex, Value * blockIndex, Value * packIndex, const bool /* readOnly */) const {
42    iBuilder->CreateAssert(iBuilder->CreateICmpULT(streamIndex, getStreamSetCount(self)), "StreamSetBuffer: out-of-bounds stream access");
43    return iBuilder->CreateGEP(getStreamSetBlockPtr(self, blockIndex), {iBuilder->getInt32(0), streamIndex, packIndex});
44}
45
46inline bool StreamSetBuffer::isCapacityGuaranteed(const llvm::Value * const index, const size_t capacity) const {
47    if (LLVM_UNLIKELY(isa<ConstantInt>(index))) {
48        if (LLVM_LIKELY(cast<ConstantInt>(index)->getLimitedValue() < capacity)) {
49            return true;
50        }
51    }
52    return false;
53}
54
55llvm::Value * StreamSetBuffer::getStreamSetCount(Value *) const {
56    uint64_t count = 1;
57    if (isa<ArrayType>(mBaseType)) {
58        count = mBaseType->getArrayNumElements();
59    }
60    return iBuilder->getSize(count);
61}
62
63inline llvm::Value * StreamSetBuffer::modByBufferBlocks(llvm::Value * const offset) const {
64    assert (offset->getType()->isIntegerTy());
65    if (isCapacityGuaranteed(offset, mBufferBlocks)) {
66        return offset;
67    } else if (mBufferBlocks == 1) {
68        return ConstantInt::getNullValue(iBuilder->getSizeTy());
69    } else if ((mBufferBlocks & (mBufferBlocks - 1)) == 0) { // is power of 2
70        return iBuilder->CreateAnd(offset, ConstantInt::get(offset->getType(), mBufferBlocks - 1));
71    } else {
72        return iBuilder->CreateURem(offset, ConstantInt::get(offset->getType(), mBufferBlocks));
73    }
74}
75
76/**
77 * @brief getRawItemPointer
78 *
79 * get a raw pointer the iN field at position absoluteItemPosition of the stream number streamIndex of the stream set.
80 * In the case of a stream whose fields are less than one byte (8 bits) in size, the pointer is to the containing byte.
81 * The type of the pointer is i8* for fields of 8 bits or less, otherwise iN* for N-bit fields.
82 */
83Value * StreamSetBuffer::getRawItemPointer(Value * self, Value * streamIndex, Value * absolutePosition) const {
84    Value * ptr = self;
85    if (isa<ConstantInt>(streamIndex) && cast<ConstantInt>(streamIndex)->isZero()) {
86        ptr = iBuilder->CreateGEP(ptr, {iBuilder->getInt32(0), streamIndex});
87    }
88    IntegerType * const ty = cast<IntegerType>(mBaseType->getArrayElementType()->getVectorElementType());
89    ptr = iBuilder->CreatePointerCast(ptr, ty->getPointerTo());
90    if (LLVM_UNLIKELY(ty->getBitWidth() < 8)) {
91        const auto bw = ty->getBitWidth();
92        if (LLVM_LIKELY((bw & (bw - 1)) == 0)) { // is power of 2
93            absolutePosition = iBuilder->CreateUDiv(absolutePosition, ConstantInt::get(absolutePosition->getType(), 8 / bw));
94        } else {
95            absolutePosition = iBuilder->CreateMul(absolutePosition, ConstantInt::get(absolutePosition->getType(), bw));
96            absolutePosition = iBuilder->CreateUDiv(absolutePosition, ConstantInt::get(absolutePosition->getType(), 8));
97        }
98    }
99    return iBuilder->CreateGEP(ptr, absolutePosition);
100}
101
102Value * StreamSetBuffer::getLinearlyAccessibleItems(llvm::Value * fromPosition) const {
103    if (isa<ArrayType>(mType) && dyn_cast<ArrayType>(mType)->getNumElements() > 1) {
104        Constant * stride = iBuilder->getSize(iBuilder->getStride());
105        return iBuilder->CreateSub(stride, iBuilder->CreateURem(fromPosition, stride));
106    }
107    else {
108        Constant * bufSize = iBuilder->getSize(mBufferBlocks * iBuilder->getStride());
109        return iBuilder->CreateSub(bufSize, iBuilder->CreateURem(fromPosition, bufSize));
110    }
111}
112
113Value * StreamSetBuffer::getLinearlyAccessibleBlocks(llvm::Value * fromBlock) const {
114    Constant * bufBlocks = iBuilder->getSize(mBufferBlocks);
115    return iBuilder->CreateSub(bufBlocks, iBuilder->CreateURem(fromBlock, bufBlocks));
116}
117
118
119// Single Block Buffer
120
121// For a single block buffer, the block pointer is always the buffer base pointer.
122Value * SingleBlockBuffer::getStreamSetBlockPtr(Value * self, Value *) const {
123    return self;
124}
125
126// External File Buffer
127void ExternalFileBuffer::setStreamSetBuffer(Value * ptr, Value * /* fileSize */) {
128    mStreamSetBufferPtr = iBuilder->CreatePointerBitCastOrAddrSpaceCast(ptr, getPointerType());
129}
130
131void ExternalFileBuffer::setEmptyBuffer(Value * ptr) {   
132    mStreamSetBufferPtr = iBuilder->CreatePointerBitCastOrAddrSpaceCast(ptr, getPointerType());
133}
134
135void ExternalFileBuffer::allocateBuffer() {
136    report_fatal_error("External buffers cannot be allocated.");
137}
138
139Value * ExternalFileBuffer::getStreamSetBlockPtr(Value * self, Value * blockNo) const {
140    return iBuilder->CreateGEP(self, blockNo);
141}
142
143Value * ExternalFileBuffer::getLinearlyAccessibleItems(llvm::Value *) const {
144    report_fatal_error("External buffers: getLinearlyAccessibleItems is not supported.");
145}
146
147// Circular Buffer
148
149Value * CircularBuffer::getStreamSetBlockPtr(Value * self, Value * blockIndex) const {
150    return iBuilder->CreateGEP(self, modByBufferBlocks(blockIndex));
151}
152
153// CircularCopybackBuffer Buffer
154
155void CircularCopybackBuffer::allocateBuffer() {
156    mStreamSetBufferPtr = iBuilder->CreateCacheAlignedAlloca(getType(), iBuilder->getSize(mBufferBlocks + mOverflowBlocks));
157}
158
159void CircularCopybackBuffer::createCopyBack(Value * self, Value * overFlowItems) const {
160    Type * size_ty = iBuilder->getSizeTy();
161    Type * i8ptr = iBuilder->getInt8PtrTy();
162    Constant * blockSize = iBuilder->getSize(iBuilder->getBitBlockWidth());
163    Function * f = iBuilder->GetInsertBlock()->getParent();
164    BasicBlock * wholeBlockCopy = BasicBlock::Create(iBuilder->getContext(), "wholeBlockCopy", f, 0);
165    BasicBlock * partialBlockCopy = BasicBlock::Create(iBuilder->getContext(), "partialBlockCopy", f, 0);
166    BasicBlock * copyBackDone = BasicBlock::Create(iBuilder->getContext(), "copyBackDone", f, 0);
167    unsigned numStreams = getType()->getArrayNumElements();
168    auto elemTy = getType()->getArrayElementType();
169    unsigned fieldWidth = isa<ArrayType>(elemTy) ? elemTy->getArrayNumElements() : 1;
170    Value * overFlowAreaPtr = iBuilder->CreateGEP(self, iBuilder->getSize(mBufferBlocks));
171    Value * overFlowBlocks = iBuilder->CreateUDiv(overFlowItems, blockSize);
172    Value * partialItems = iBuilder->CreateURem(overFlowItems, blockSize);
173    Value * partialBlockTargetPtr = iBuilder->CreateGEP(self, overFlowBlocks);
174    Value * partialBlockSourcePtr = iBuilder->CreateGEP(overFlowAreaPtr, overFlowBlocks);
175    iBuilder->CreateCondBr(iBuilder->CreateICmpUGT(overFlowBlocks, iBuilder->getSize(0)), wholeBlockCopy, partialBlockCopy);
176    iBuilder->SetInsertPoint(wholeBlockCopy);
177    unsigned alignment = iBuilder->getBitBlockWidth() / 8;
178    Value * copyLength = iBuilder->CreateSub(iBuilder->CreatePtrToInt(partialBlockTargetPtr, size_ty), iBuilder->CreatePtrToInt(self, size_ty));
179    iBuilder->CreateMemMove(iBuilder->CreateBitCast(self, i8ptr), iBuilder->CreateBitCast(overFlowAreaPtr, i8ptr), copyLength, alignment);
180    iBuilder->CreateCondBr(iBuilder->CreateICmpUGT(partialItems, iBuilder->getSize(0)), partialBlockCopy, copyBackDone);
181    iBuilder->SetInsertPoint(partialBlockCopy);
182    Value * copyBits = iBuilder->CreateMul(overFlowItems, iBuilder->getSize(fieldWidth));
183    Value * copyBytes = iBuilder->CreateLShr(iBuilder->CreateAdd(copyBits, iBuilder->getSize(7)), iBuilder->getSize(3));
184    for (unsigned strm = 0; strm < numStreams; strm++) {
185        Value * strmTargetPtr = iBuilder->CreateGEP(partialBlockTargetPtr, {iBuilder->getInt32(0), iBuilder->getInt32(strm)});
186        Value * strmSourcePtr = iBuilder->CreateGEP(partialBlockSourcePtr, {iBuilder->getInt32(0), iBuilder->getInt32(strm)});
187        iBuilder->CreateMemMove(iBuilder->CreateBitCast(strmTargetPtr, i8ptr), iBuilder->CreateBitCast(strmSourcePtr, i8ptr), copyBytes, alignment);
188    }
189    iBuilder->CreateBr(copyBackDone);
190    iBuilder->SetInsertPoint(copyBackDone);
191}
192
193Value * CircularCopybackBuffer::getStreamSetBlockPtr(Value * self, Value * blockIndex) const {
194    return iBuilder->CreateGEP(self, modByBufferBlocks(blockIndex));
195}
196
197// SwizzledCopybackBuffer Buffer
198
199void SwizzledCopybackBuffer::allocateBuffer() {
200    mStreamSetBufferPtr = iBuilder->CreateCacheAlignedAlloca(getType(), iBuilder->getSize(mBufferBlocks + mOverflowBlocks));
201}
202
203void SwizzledCopybackBuffer::createCopyBack(Value * self, Value * overFlowItems) const {
204    Type * size_ty = iBuilder->getSizeTy();
205    Type * i8ptr = iBuilder->getInt8PtrTy();
206    Constant * blockSize = iBuilder->getSize(iBuilder->getBitBlockWidth());
207    Function * f = iBuilder->GetInsertBlock()->getParent();
208    BasicBlock * wholeBlockCopy = BasicBlock::Create(iBuilder->getContext(), "wholeBlockCopy", f, 0);
209    BasicBlock * partialBlockCopy = BasicBlock::Create(iBuilder->getContext(), "partialBlockCopy", f, 0);
210    BasicBlock * copyBackDone = BasicBlock::Create(iBuilder->getContext(), "copyBackDone", f, 0);
211    unsigned numStreams = getType()->getArrayNumElements();
212    unsigned swizzleFactor = iBuilder->getBitBlockWidth()/mFieldWidth;
213    auto elemTy = getType()->getArrayElementType();
214    unsigned fieldWidth = isa<ArrayType>(elemTy) ? elemTy->getArrayNumElements() : 1;
215    Value * overFlowAreaPtr = iBuilder->CreateGEP(self, iBuilder->getSize(mBufferBlocks));
216    Value * overFlowBlocks = iBuilder->CreateUDiv(overFlowItems, blockSize);
217    Value * partialItems = iBuilder->CreateURem(overFlowItems, blockSize);
218    Value * partialBlockTargetPtr = iBuilder->CreateGEP(self, overFlowBlocks);
219    Value * partialBlockSourcePtr = iBuilder->CreateGEP(overFlowAreaPtr, overFlowBlocks);
220    iBuilder->CreateCondBr(iBuilder->CreateICmpUGT(overFlowBlocks, iBuilder->getSize(0)), wholeBlockCopy, partialBlockCopy);
221    iBuilder->SetInsertPoint(wholeBlockCopy);
222    unsigned alignment = iBuilder->getBitBlockWidth() / 8;
223    Value * copyLength = iBuilder->CreateSub(iBuilder->CreatePtrToInt(partialBlockTargetPtr, size_ty), iBuilder->CreatePtrToInt(self, size_ty));
224    iBuilder->CreateMemMove(iBuilder->CreateBitCast(self, i8ptr), iBuilder->CreateBitCast(overFlowAreaPtr, i8ptr), copyLength, alignment);
225    iBuilder->CreateCondBr(iBuilder->CreateICmpUGT(partialItems, iBuilder->getSize(0)), partialBlockCopy, copyBackDone);
226    iBuilder->SetInsertPoint(partialBlockCopy);
227    Value * copyBits = iBuilder->CreateMul(overFlowItems, iBuilder->getSize(fieldWidth * swizzleFactor));
228    Value * copyBytes = iBuilder->CreateLShr(iBuilder->CreateAdd(copyBits, iBuilder->getSize(7)), iBuilder->getSize(3));
229    for (unsigned strm = 0; strm < numStreams; strm += swizzleFactor) {
230        Value * strmTargetPtr = iBuilder->CreateGEP(partialBlockTargetPtr, {iBuilder->getInt32(0), iBuilder->getInt32(strm)});
231        Value * strmSourcePtr = iBuilder->CreateGEP(partialBlockSourcePtr, {iBuilder->getInt32(0), iBuilder->getInt32(strm)});
232        iBuilder->CreateMemMove(iBuilder->CreateBitCast(strmTargetPtr, i8ptr), iBuilder->CreateBitCast(strmSourcePtr, i8ptr), copyBytes, alignment);
233    }
234    iBuilder->CreateBr(copyBackDone);
235    iBuilder->SetInsertPoint(copyBackDone);
236}
237
238Value * SwizzledCopybackBuffer::getStreamSetBlockPtr(Value * self, Value * blockIndex) const {
239    assert (blockIndex->getType()->isIntegerTy());
240   
241    Value * offset = nullptr;
242    if (mBufferBlocks == 1) {
243        offset = ConstantInt::getNullValue(iBuilder->getSizeTy());
244    } else if ((mBufferBlocks & (mBufferBlocks - 1)) == 0) { // is power of 2
245        offset = iBuilder->CreateAnd(blockIndex, ConstantInt::get(blockIndex->getType(), mBufferBlocks - 1));
246    } else {
247        offset = iBuilder->CreateURem(blockIndex, ConstantInt::get(blockIndex->getType(), mBufferBlocks));
248    }
249    return iBuilder->CreateGEP(self, offset);
250}
251
252SwizzledCopybackBuffer::SwizzledCopybackBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned fieldwidth, unsigned AddressSpace)
253: StreamSetBuffer(BufferKind::SwizzledCopybackBuffer, b, type, resolveStreamSetType(b, type), bufferBlocks, AddressSpace), mOverflowBlocks(overflowBlocks), mFieldWidth(fieldwidth) {
254   
255}
256
257
258
259// Expandable Buffer
260
261void ExpandableBuffer::allocateBuffer() {
262    mStreamSetBufferPtr = iBuilder->CreateCacheAlignedAlloca(getType());
263    Value * const capacityPtr = iBuilder->CreateGEP(mStreamSetBufferPtr, {iBuilder->getInt32(0), iBuilder->getInt32(0)});
264    iBuilder->CreateStore(iBuilder->getSize(mInitialCapacity), capacityPtr);
265    Type * const bufferType = getType()->getStructElementType(1)->getPointerElementType();
266    ConstantInt * const size = iBuilder->getSize(mBufferBlocks * mInitialCapacity);
267    Value * const ptr = iBuilder->CreateAlignedMalloc(bufferType, size, iBuilder->getCacheAlignment());
268    const auto alignment = bufferType->getPrimitiveSizeInBits() / 8;
269    Constant * bufferWidth = ConstantExpr::getIntegerCast(ConstantExpr::getSizeOf(bufferType), size->getType(), false);
270    iBuilder->CreateMemZero(ptr, iBuilder->CreateMul(size, bufferWidth), alignment);
271    Value * const streamSetPtr = iBuilder->CreateGEP(mStreamSetBufferPtr, {iBuilder->getInt32(0), iBuilder->getInt32(1)});
272    iBuilder->CreateStore(ptr, streamSetPtr);
273}
274
275std::pair<Value *, Value *> ExpandableBuffer::getInternalStreamBuffer(llvm::Value * self, llvm::Value * streamIndex, Value * blockIndex, const bool readOnly) const {
276
277    // ENTRY
278    Value * const capacityPtr = iBuilder->CreateGEP(self, {iBuilder->getInt32(0), iBuilder->getInt32(0)});
279    Value * const capacity = iBuilder->CreateLoad(capacityPtr);
280    Value * const streamSetPtr = iBuilder->CreateGEP(self, {iBuilder->getInt32(0), iBuilder->getInt32(1)});
281    Value * const streamSet = iBuilder->CreateLoad(streamSetPtr);
282    blockIndex = modByBufferBlocks(blockIndex);
283
284    assert (streamIndex->getType() == capacity->getType());
285    Value * const cond = iBuilder->CreateICmpULT(streamIndex, capacity);
286
287    // Are we guaranteed that we can access this stream?
288    if (readOnly || isCapacityGuaranteed(streamIndex, mInitialCapacity)) {
289        iBuilder->CreateAssert(cond, "ExpandableBuffer: out-of-bounds stream access");
290        Value * offset = iBuilder->CreateAdd(iBuilder->CreateMul(blockIndex, capacity), streamIndex);
291        return {streamSet, offset};
292    }
293
294    BasicBlock * const entry = iBuilder->GetInsertBlock();
295    BasicBlock * const expand = BasicBlock::Create(iBuilder->getContext(), "expand", entry->getParent());
296    BasicBlock * const resume = BasicBlock::Create(iBuilder->getContext(), "resume", entry->getParent());
297
298    iBuilder->CreateLikelyCondBr(cond, resume, expand);
299
300    // EXPAND
301    iBuilder->SetInsertPoint(expand);
302
303    Type * elementType = getType()->getStructElementType(1)->getPointerElementType();
304    Constant * const vectorWidth = ConstantExpr::getIntegerCast(ConstantExpr::getSizeOf(elementType), capacity->getType(), false);
305    Value * newCapacity = iBuilder->CreateMul(iBuilder->CreateAdd(streamIndex, iBuilder->getSize(1)), iBuilder->getSize(2), "newCapacity");
306
307    std::string tmp;
308    raw_string_ostream out(tmp);
309    out << "__expand";
310    elementType->print(out);
311    std::string name = out.str();
312
313    Module * const m = iBuilder->getModule();
314    Function * expandFunction = m->getFunction(name);
315
316    if (expandFunction == nullptr) {
317
318        const auto ip = iBuilder->saveIP();
319
320        FunctionType * fty = FunctionType::get(elementType->getPointerTo(), {elementType->getPointerTo(), iBuilder->getSizeTy(), iBuilder->getSizeTy()}, false);
321        expandFunction = Function::Create(fty, GlobalValue::PrivateLinkage, name, m);
322
323        auto args = expandFunction->arg_begin();
324        Value * streamSet = &*args++;
325        Value * capacity = &*args++;
326        Value * newCapacity = &*args;
327
328        BasicBlock * entry = BasicBlock::Create(iBuilder->getContext(), "entry", expandFunction);
329        iBuilder->SetInsertPoint(entry);
330
331        Value * size = iBuilder->CreateMul(newCapacity, iBuilder->getSize(mBufferBlocks));
332        Value * newStreamSet = iBuilder->CreateAlignedMalloc(elementType, size, iBuilder->getCacheAlignment());
333        Value * const diffCapacity = iBuilder->CreateMul(iBuilder->CreateSub(newCapacity, capacity), vectorWidth);
334
335        const auto alignment = elementType->getPrimitiveSizeInBits() / 8;
336        for (unsigned i = 0; i < mBufferBlocks; ++i) {
337            ConstantInt * const offset = iBuilder->getSize(i);
338            Value * srcOffset = iBuilder->CreateMul(capacity, offset);
339            Value * srcPtr = iBuilder->CreateGEP(streamSet, srcOffset);
340            Value * destOffset = iBuilder->CreateMul(newCapacity, offset);
341            Value * destPtr = iBuilder->CreateGEP(newStreamSet, destOffset);
342            iBuilder->CreateMemCpy(destPtr, srcPtr, iBuilder->CreateMul(capacity, vectorWidth), alignment);
343            Value * destZeroOffset = iBuilder->CreateAdd(destOffset, capacity);
344            Value * destZeroPtr = iBuilder->CreateGEP(newStreamSet, destZeroOffset);
345            iBuilder->CreateMemZero(destZeroPtr, diffCapacity, alignment);
346        }
347
348        iBuilder->CreateAlignedFree(streamSet);
349
350        iBuilder->CreateRet(newStreamSet);
351
352        iBuilder->restoreIP(ip);
353    }
354
355    Value * newStreamSet = iBuilder->CreateCall(expandFunction, {streamSet, capacity, newCapacity});
356    iBuilder->CreateStore(newStreamSet, streamSetPtr);
357    iBuilder->CreateStore(newCapacity, capacityPtr);
358
359    iBuilder->CreateBr(resume);
360
361    // RESUME
362    iBuilder->SetInsertPoint(resume);
363
364    PHINode * phiStreamSet = iBuilder->CreatePHI(streamSet->getType(), 2);
365    phiStreamSet->addIncoming(streamSet, entry);
366    phiStreamSet->addIncoming(newStreamSet, expand);
367
368    PHINode * phiCapacity = iBuilder->CreatePHI(capacity->getType(), 2);
369    phiCapacity->addIncoming(capacity, entry);
370    phiCapacity->addIncoming(newCapacity, expand);
371
372    Value * offset = iBuilder->CreateAdd(iBuilder->CreateMul(blockIndex, phiCapacity), streamIndex);
373
374    return {phiStreamSet, offset};
375}
376
377llvm::Value * ExpandableBuffer::getStreamBlockPtr(llvm::Value * self, Value * streamIndex, Value * blockIndex, const bool readOnly) const {
378    Value * ptr, * offset;
379    std::tie(ptr, offset) = getInternalStreamBuffer(self, streamIndex, blockIndex, readOnly);
380    return iBuilder->CreateGEP(ptr, offset);
381}
382
383llvm::Value * ExpandableBuffer::getStreamPackPtr(llvm::Value * self, llvm::Value * streamIndex, Value * blockIndex, Value * packIndex, const bool readOnly) const {
384    Value * ptr, * offset;
385    std::tie(ptr, offset) = getInternalStreamBuffer(self, streamIndex, blockIndex, readOnly);
386    return iBuilder->CreateGEP(ptr, {offset, packIndex});
387}
388
389llvm::Value * ExpandableBuffer::getStreamSetCount(llvm::Value * self) const {
390    return iBuilder->CreateLoad(iBuilder->CreateGEP(self, {iBuilder->getInt32(0), iBuilder->getInt32(0)}));
391}
392
393Value * ExpandableBuffer::getStreamSetBlockPtr(Value *, Value *) const {
394    report_fatal_error("Expandable buffers: getStreamSetBlockPtr is not supported.");
395}
396
397Value * ExpandableBuffer::getLinearlyAccessibleItems(llvm::Value *) const {
398    report_fatal_error("Expandable buffers: getLinearlyAccessibleItems is not supported.");
399}
400
401// Constructors
402SingleBlockBuffer::SingleBlockBuffer(IDISA::IDISA_Builder * b, llvm::Type * type)
403: StreamSetBuffer(BufferKind::BlockBuffer, b, type, resolveStreamSetType(b, type), 1, 0) {
404
405}
406
407ExternalFileBuffer::ExternalFileBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, unsigned AddressSpace)
408: StreamSetBuffer(BufferKind::ExternalFileBuffer, b, type, resolveStreamSetType(b, type), 0, AddressSpace) {
409
410}
411
412CircularBuffer::CircularBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace)
413: StreamSetBuffer(BufferKind::CircularBuffer, b, type, resolveStreamSetType(b, type), bufferBlocks, AddressSpace) {
414
415}
416
417CircularCopybackBuffer::CircularCopybackBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace)
418: StreamSetBuffer(BufferKind::CircularCopybackBuffer, b, type, resolveStreamSetType(b, type), bufferBlocks, AddressSpace), mOverflowBlocks(overflowBlocks) {
419
420}
421
422ExpandableBuffer::ExpandableBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace)
423: StreamSetBuffer(BufferKind::ExpandableBuffer, b, type, resolveExpandableStreamSetType(b, type), bufferBlocks, AddressSpace)
424, mInitialCapacity(type->getArrayNumElements()) {
425
426}
427
428inline StreamSetBuffer::StreamSetBuffer(BufferKind k, IDISA::IDISA_Builder * b, Type * baseType, Type * resolvedType, unsigned blocks, unsigned AddressSpace)
429: mBufferKind(k)
430, iBuilder(b)
431, mType(resolvedType)
432, mBufferBlocks(blocks)
433, mAddressSpace(AddressSpace)
434, mStreamSetBufferPtr(nullptr)
435, mBaseType(baseType) {
436
437}
438
439// Helper routines
440ArrayType * resolveStreamSetType(IDISA_Builder * const b, Type * type) {
441    unsigned numElements = 1;
442    if (LLVM_LIKELY(type->isArrayTy())) {
443        numElements = type->getArrayNumElements();
444        type = type->getArrayElementType();
445    }
446    if (LLVM_LIKELY(type->isVectorTy() && type->getVectorNumElements() == 0)) {
447        type = type->getVectorElementType();
448        if (LLVM_LIKELY(type->isIntegerTy())) {
449            const auto fieldWidth = cast<IntegerType>(type)->getBitWidth();
450            type = b->getBitBlockType();
451            if (fieldWidth != 1) {
452                type = ArrayType::get(type, fieldWidth);
453            }
454            return ArrayType::get(type, numElements);
455        }
456    }
457    std::string tmp;
458    raw_string_ostream out(tmp);
459    type->print(out);
460    out << " is an unvalid stream set buffer type.";
461    report_fatal_error(out.str());
462}
463
464StructType * resolveExpandableStreamSetType(IDISA_Builder * const b, Type * type) {
465    if (LLVM_LIKELY(type->isArrayTy())) {
466        type = type->getArrayElementType();
467    }
468    if (LLVM_LIKELY(type->isVectorTy() && type->getVectorNumElements() == 0)) {
469        type = type->getVectorElementType();
470        if (LLVM_LIKELY(type->isIntegerTy())) {
471            const auto fieldWidth = cast<IntegerType>(type)->getBitWidth();
472            type = b->getBitBlockType();
473            if (fieldWidth != 1) {
474                type = ArrayType::get(type, fieldWidth);
475            }
476            return StructType::get(b->getSizeTy(), type->getPointerTo(), nullptr);
477        }
478    }
479    std::string tmp;
480    raw_string_ostream out(tmp);
481    type->print(out);
482    out << " is an unvalid stream set buffer type.";
483    report_fatal_error(out.str());
484}
Note: See TracBrowser for help on using the repository browser.