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

Last change on this file since 5301 was 5301, checked in by cameron, 3 years ago

Circular copy-back buffers: initial check-in

File size: 8.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 <assert.h>                // for assert
9#include <llvm/IR/Type.h>          // for Type
10#include <stdexcept>               // for runtime_error
11#include <llvm/IR/BasicBlock.h>    // for BasicBlock
12#include <llvm/IR/Constants.h>     // for ConstantInt
13#include <llvm/IR/DataLayout.h>    // for DataLayout
14#include <llvm/IR/DerivedTypes.h>  // for IntegerType (ptr only), PointerType
15#include <llvm/IR/Module.h>        // for Module
16#include <llvm/IR/Value.h>         // for Value
17namespace llvm { class Constant; }
18namespace llvm { class Function; }
19
20using namespace parabix;
21using namespace llvm;
22using namespace IDISA;
23
24Type * resolveVectorTy(IDISA_Builder * const b, Type * type) {
25    if (LLVM_LIKELY(type->isVectorTy() && type->getVectorNumElements() == 0)) {
26        type = type->getVectorElementType();
27        if (LLVM_LIKELY(type->isIntegerTy())) {
28            const auto fieldWidth = cast<IntegerType>(type)->getBitWidth();
29            type = b->getBitBlockType();
30            if (fieldWidth != 1) {
31                type = llvm::ArrayType::get(type, fieldWidth);
32            }
33        }
34    }
35    return type;
36}
37
38Type * StreamSetBuffer::resolveStreamSetBufferType(Type * const type) const {
39    if (type->isArrayTy()) {
40        return ArrayType::get(resolveVectorTy(iBuilder, type->getArrayElementType()), type->getArrayNumElements());
41    } else if (type->isVectorTy()) {
42        return resolveVectorTy(iBuilder, type);
43    }
44    return type;
45}
46
47void StreamSetBuffer::allocateBuffer() {
48    mStreamSetBufferPtr = iBuilder->CreateCacheAlignedAlloca(getType(), iBuilder->getSize(mBufferBlocks));
49}
50
51Value * StreamSetBuffer::getStream(Value * self, Value * blockNo, Value * index) const {
52    return iBuilder->CreateGEP(getStreamSetPtr(self, blockNo), {iBuilder->getInt32(0), index});
53}
54
55Value * StreamSetBuffer::getStream(Value * self, Value * blockNo, Value * index1, Value * index2) const {
56    return iBuilder->CreateGEP(getStreamSetPtr(self, blockNo), {iBuilder->getInt32(0), index1, index2});
57}
58
59Value * StreamSetBuffer::getStreamView(llvm::Type * type, llvm::Value * self, Value * blockNo, llvm::Value * index) const {
60    return iBuilder->CreateGEP(iBuilder->CreatePointerCast(getStreamSetPtr(self, blockNo), type), index, "view");
61}
62
63Value * StreamSetBuffer::getLinearlyAccessibleItems(llvm::Value * fromPosition) const {
64    if (isa<ArrayType>(mStreamSetType) && dyn_cast<ArrayType>(mStreamSetType)->getNumElements() > 1) {
65        Constant * stride = iBuilder->getSize(iBuilder->getStride());
66        return iBuilder->CreateSub(stride, iBuilder->CreateURem(fromPosition, stride));
67    }
68    else {
69        Constant * bufSize = iBuilder->getSize(mBufferBlocks * iBuilder->getStride());
70        return iBuilder->CreateSub(bufSize, iBuilder->CreateURem(fromPosition, bufSize));
71    }
72}
73
74
75// Single Block Buffer
76
77// For a single block buffer, the block pointer is always the buffer base pointer.
78Value * SingleBlockBuffer::getStreamSetPtr(Value * self, Value *) const {
79    return self;
80}
81
82// External File Buffer
83void ExternalFileBuffer::setStreamSetBuffer(Value * ptr, Value * /* fileSize */) {
84    mStreamSetBufferPtr = iBuilder->CreatePointerBitCastOrAddrSpaceCast(ptr, getPointerType());
85}
86
87void ExternalFileBuffer::setEmptyBuffer(Value * ptr) {   
88    mStreamSetBufferPtr = iBuilder->CreatePointerBitCastOrAddrSpaceCast(ptr, getPointerType());
89}
90
91void ExternalFileBuffer::allocateBuffer() {
92    throw std::runtime_error("External buffers cannot be allocated.");
93}
94
95Value * ExternalFileBuffer::getStreamSetPtr(Value * self, Value * blockNo) const {
96    return iBuilder->CreateGEP(self, blockNo);
97}
98
99Value * ExternalFileBuffer::getLinearlyAccessibleItems(llvm::Value * fromPosition) const {
100    throw std::runtime_error("External buffers: getLinearlyAccessibleItems not supported.");
101}
102
103// Circular Buffer
104
105Value * CircularBuffer::getStreamSetPtr(Value * self, Value * blockNo) const {
106    assert (blockNo->getType()->isIntegerTy());
107
108    Value * offset = nullptr;
109    if (mBufferBlocks == 1) {
110        offset = ConstantInt::getNullValue(iBuilder->getSizeTy());
111    } else if ((mBufferBlocks & (mBufferBlocks - 1)) == 0) { // is power of 2
112        offset = iBuilder->CreateAnd(blockNo, ConstantInt::get(blockNo->getType(), mBufferBlocks - 1));
113    } else {
114        offset = iBuilder->CreateURem(blockNo, ConstantInt::get(blockNo->getType(), mBufferBlocks));
115    }
116    return iBuilder->CreateGEP(self, offset);
117}
118
119
120// CircularCopybackBuffer Buffer
121
122void CircularCopybackBuffer::allocateBuffer() {
123    mStreamSetBufferPtr = iBuilder->CreateCacheAlignedAlloca(getType(), iBuilder->getSize(mBufferBlocks + mOverflowBlocks));
124}
125
126void CircularCopybackBuffer::createCopyBack(Value * self, Value * overFlowItems) {
127    // Must copy back one full block for each of the streams in the stream set.
128    Constant * blockSize = iBuilder->getSize(iBuilder->getBitBlockWidth());
129    Constant * blockSizeLess1 = iBuilder->getSize(iBuilder->getBitBlockWidth() - 1);
130    Value * overFlowBlocks = iBuilder->CreateUDiv(iBuilder->CreateAdd(overFlowItems, blockSizeLess1), blockSize);
131    Value * overFlowAreaPtr = iBuilder->CreateGEP(mStreamSetBufferPtr, iBuilder->getSize(mBufferBlocks));
132    DataLayout dl(iBuilder->getModule());
133    Constant * blockBytes = ConstantInt::get(iBuilder->getSizeTy(), dl.getTypeAllocSize(mStreamSetType) * iBuilder->getBitBlockWidth());
134    Value * copyLength = iBuilder->CreateMul(overFlowBlocks, blockBytes);
135    Type * i8ptr = iBuilder->getInt8Ty()->getPointerTo();
136    unsigned alignment = iBuilder->getBitBlockWidth() / 8;
137    iBuilder->CreateMemMove(iBuilder->CreateBitCast(mStreamSetBufferPtr, i8ptr), iBuilder->CreateBitCast(overFlowAreaPtr, i8ptr), copyLength, alignment);
138}
139
140Value * CircularCopybackBuffer::getStreamSetPtr(Value * self, Value * blockNo) const {
141    assert (blockNo->getType()->isIntegerTy());
142   
143    Value * offset = nullptr;
144    if (mBufferBlocks == 1) {
145        offset = ConstantInt::getNullValue(iBuilder->getSizeTy());
146    } else if ((mBufferBlocks & (mBufferBlocks - 1)) == 0) { // is power of 2
147        offset = iBuilder->CreateAnd(blockNo, ConstantInt::get(blockNo->getType(), mBufferBlocks - 1));
148    } else {
149        offset = iBuilder->CreateURem(blockNo, ConstantInt::get(blockNo->getType(), mBufferBlocks));
150    }
151    return iBuilder->CreateGEP(self, offset);
152}
153
154
155
156// Expandable Buffer
157
158Value * ExpandableBuffer::getStreamSetPtr(Value * self, Value * blockNo) const {
159    return nullptr;
160}
161
162llvm::Value * ExpandableBuffer::getStream(llvm::Value * self, llvm::Value * blockNo, llvm::Value * index) const {
163    return nullptr;
164}
165
166llvm::Value * ExpandableBuffer::getStream(llvm::Value * self, llvm::Value * blockNo, Value *index1, Value *index2) const {
167    return nullptr;
168}
169
170llvm::Value * ExpandableBuffer::getStreamView(llvm::Type * type, llvm::Value * self, llvm::Value * blockNo, llvm::Value * index) const {
171    return nullptr;
172}
173
174// Constructors
175
176SingleBlockBuffer::SingleBlockBuffer(IDISA::IDISA_Builder * b, llvm::Type * type)
177: StreamSetBuffer(BufferKind::BlockBuffer, b, type, 1, 0) {
178
179}
180
181ExternalFileBuffer::ExternalFileBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, unsigned AddressSpace)
182: StreamSetBuffer(BufferKind::ExternalFileBuffer, b, type, 0, AddressSpace) {
183
184}
185
186CircularBuffer::CircularBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace)
187: StreamSetBuffer(BufferKind::CircularBuffer, b, type, bufferBlocks, AddressSpace) {
188
189}
190
191CircularCopybackBuffer::CircularCopybackBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, size_t bufferBlocks, size_t overflowBlocks, unsigned AddressSpace)
192: StreamSetBuffer(BufferKind::CircularCopybackBuffer, b, type, bufferBlocks, AddressSpace), mOverflowBlocks(overflowBlocks) {
193
194}
195
196
197ExpandableBuffer::ExpandableBuffer(IDISA::IDISA_Builder * b, llvm::Type * type, size_t bufferBlocks, unsigned AddressSpace)
198: StreamSetBuffer(BufferKind::ExpandableBuffer, b, type, bufferBlocks, AddressSpace) {
199
200}
201
202Value * ExpandableBuffer::getLinearlyAccessibleItems(llvm::Value * fromPosition) const {
203    throw std::runtime_error("Expandable buffers: getLinearlyAccessibleItems not supported.");
204}
205
206
207StreamSetBuffer::StreamSetBuffer(BufferKind k, IDISA::IDISA_Builder * b, Type * type, unsigned blocks, unsigned AddressSpace)
208: mBufferKind(k)
209, iBuilder(b)
210, mStreamSetType(resolveStreamSetBufferType(type))
211, mBufferBlocks(blocks)
212, mAddressSpace(AddressSpace)
213, mStreamSetBufferPtr(nullptr)
214, mBaseStreamSetType(type) {
215
216}
Note: See TracBrowser for help on using the repository browser.