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

Last change on this file since 5204 was 5204, checked in by nmedfort, 2 years ago

More 32-bit fixes.

File size: 11.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   
7#include <kernels/streamset.h>
8#include <vector>
9#include <IDISA/idisa_builder.h>
10#include <llvm/IR/Type.h>
11
12using namespace parabix;
13
14enum SS_struct_index {iProducer_pos = 0, iConsumer_pos = 1, iEnd_of_input = 2, iBuffer_ptr = 3};
15
16llvm::PointerType * StreamSetBuffer::getStreamBufferPointerType() {
17    return PointerType::get(mStreamSetType, mAddrSpace);
18}
19
20llvm::PointerType * StreamSetBuffer::getStreamSetStructPointerType() {
21    return PointerType::get(mStreamSetStructType, 0);
22}
23
24llvm::Value * StreamSetBuffer::getProducerPosPtr(Value * bufferStructPtr) {
25    return iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iProducer_pos)});
26}
27
28void StreamSetBuffer::setProducerPos(Value * bufferStructPtr, llvm::Value * pos){
29    iBuilder->CreateStore(pos, iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iProducer_pos)}));
30}
31
32llvm::Value * StreamSetBuffer::getConsumerPosPtr(Value * bufferStructPtr) {
33    return iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iConsumer_pos)});
34}
35
36void StreamSetBuffer::setConsumerPos(Value * bufferStructPtr, Value * pos){
37    iBuilder->CreateStore(pos, iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iConsumer_pos)}));
38}
39
40llvm::Value * StreamSetBuffer::hasEndOfInputPtr(Value * bufferStructPtr) {
41    return iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iEnd_of_input)});
42}
43
44void StreamSetBuffer::setEndOfInput(Value * bufferStructPtr){
45    iBuilder->CreateStore(ConstantInt::get(iBuilder->getInt1Ty(), 1), iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iEnd_of_input)}));
46}
47
48llvm::Value * StreamSetBuffer::getStreamSetStructPtr(){
49    return mStreamSetStructPtr;
50}
51
52llvm::Value * StreamSetBuffer::allocateBuffer() {
53    Type * const size_ty = iBuilder->getSizeTy();
54    Type * const int1ty = iBuilder->getInt1Ty();
55    mStreamSetBufferPtr = iBuilder->CreateCacheAlignedAlloca(mStreamSetType, ConstantInt::get(iBuilder->getSizeTy(), mBufferBlocks));
56    mStreamSetStructPtr = iBuilder->CreateCacheAlignedAlloca(mStreamSetStructType);
57
58    iBuilder->CreateStore(ConstantInt::get(size_ty, 0), iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iProducer_pos)}));
59    iBuilder->CreateStore(ConstantInt::get(size_ty, 0), iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iConsumer_pos)}));
60    iBuilder->CreateStore(ConstantInt::get(int1ty, 0), iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iEnd_of_input)}));
61    iBuilder->CreateStore(mStreamSetBufferPtr, iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)}));
62   
63    return mStreamSetBufferPtr;
64}
65
66llvm::Value * StreamSetBuffer::getStreamSetBlockPointer(llvm::Value * bufferStructPtr, llvm::Value * blockNo) {
67    Value * handle = iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)});
68    return iBuilder->CreateGEP(iBuilder->CreateLoad(handle), {blockNo});
69}
70
71// Single Block Buffer
72// For a single block buffer, the block pointer is always the buffer base pointer.
73llvm::Value * SingleBlockBuffer::getStreamSetBlockPointer(llvm::Value * bufferStructPtr, llvm::Value * blockNo) {
74    Value * handle = iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)});
75    return iBuilder->CreateLoad(handle);
76}
77
78
79// External File Buffer
80
81void ExternalFileBuffer::setStreamSetBuffer(llvm::Value * ptr, Value * fileSize) {
82   
83    Type * const size_ty = iBuilder->getSizeTy();
84    Type * const int1ty = iBuilder->getInt1Ty();
85   
86    PointerType * t = getStreamBufferPointerType();   
87    mStreamSetBufferPtr = iBuilder->CreatePointerBitCastOrAddrSpaceCast(ptr, t);
88   
89    mStreamSetStructPtr = iBuilder->CreateCacheAlignedAlloca(mStreamSetStructType);
90    iBuilder->CreateStore(fileSize, iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iProducer_pos)}));
91    iBuilder->CreateStore(ConstantInt::get(size_ty, 0), iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iConsumer_pos)}));
92    iBuilder->CreateStore(ConstantInt::get(int1ty, 1), iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iEnd_of_input)}));
93    iBuilder->CreateStore(mStreamSetBufferPtr, iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)}));
94}
95
96void ExternalFileBuffer::setEmptyBuffer(llvm::Value * ptr) {
97   
98    Type * const size_ty = iBuilder->getSizeTy();
99    Type * const int1ty = iBuilder->getInt1Ty();
100   
101    PointerType * t = getStreamBufferPointerType();   
102    mStreamSetBufferPtr = iBuilder->CreatePointerBitCastOrAddrSpaceCast(ptr, t);
103   
104    mStreamSetStructPtr = iBuilder->CreateCacheAlignedAlloca(mStreamSetStructType);
105    iBuilder->CreateStore(ConstantInt::get(size_ty, 0), iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iProducer_pos)}));
106    iBuilder->CreateStore(ConstantInt::get(size_ty, 0), iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iConsumer_pos)}));
107    iBuilder->CreateStore(ConstantInt::get(int1ty,0), iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iEnd_of_input)}));
108    iBuilder->CreateStore(mStreamSetBufferPtr, iBuilder->CreateGEP(mStreamSetStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)}));
109}
110
111llvm::Value * ExternalFileBuffer::allocateBuffer() {
112    throw std::runtime_error("External buffers cannot be allocated.");
113}
114
115llvm::Value * ExternalFileBuffer::getStreamSetBlockPointer(llvm::Value * bufferStructPtr, llvm::Value * blockNo) {
116    Value * handle = iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)});
117    return iBuilder->CreateGEP(iBuilder->CreateLoad(handle), {blockNo});
118}
119
120// Circular Stack Allocated Buffer
121
122llvm::Value * CircularBuffer::getStreamSetBlockPointer(llvm::Value * bufferStructPtr, llvm::Value * blockNo) {
123    Value * handle = iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)});
124    // Circular access is based on blockNo mod mBufferBlocks.  For power of 2 buffer sizes (required), we
125    // use bitwise masking to efficiently compute the mod function  (blockNo & (mBufferBlocks - 1)
126    Value * bufPtr = iBuilder->CreateLoad(handle);
127    //iBuilder->CallPrintInt("CircularBuffer bufPtr", iBuilder->CreatePtrToInt(bufPtr, iBuilder->getSizeTy()));
128    return iBuilder->CreateGEP(bufPtr, {iBuilder->CreateAnd(blockNo, ConstantInt::get(iBuilder->getSizeTy(), mBufferBlocks-1))});
129}
130
131llvm::Value * LinearCopybackBuffer::getStreamSetBlockPointer(llvm::Value * bufferStructPtr, llvm::Value * blockNo) {
132    Constant * blockWidth = ConstantInt::get(iBuilder->getSizeTy(), iBuilder->getStride());
133    Value * consumerPos_ptr = iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iConsumer_pos)});
134    Value * consumerPos = iBuilder->CreateLoad(consumerPos_ptr);
135    Value * consumerBlock = iBuilder->CreateUDiv(consumerPos, blockWidth);
136    Value * handle = iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)});
137    Value * bufPtr = iBuilder->CreateLoad(handle);
138    //iBuilder->CallPrintInt("LinearBuffer bufPtr", iBuilder->CreatePtrToInt(bufPtr, iBuilder->getSizeTy()));
139    return iBuilder->CreateGEP(bufPtr, {iBuilder->CreateSub(blockNo, consumerBlock)});
140}
141
142void LinearCopybackBuffer::setConsumerPos(Value * bufferStructPtr, Value * new_consumer_pos) {
143    Type * const i1 = iBuilder->getInt1Ty();
144    Type * const i8 = iBuilder->getInt8Ty();
145    Type * const i32 = iBuilder->getInt32Ty();
146    Type * const i8_ptr = PointerType::get(i8, mAddrSpace);
147
148
149    Module * M = iBuilder->getModule();
150
151    IntegerType * sizeTy = iBuilder->getSizeTy();
152
153    Function * memmoveFunc = cast<Function>(M->getOrInsertFunction("llvm.memmove.p0i8.p0i8.i" + std::to_string(sizeTy->getBitWidth()),
154                                                                  iBuilder->getVoidTy(), i8_ptr, i8_ptr, sizeTy, i32, i1, nullptr));
155    Function * current = iBuilder->GetInsertBlock()->getParent();
156    BasicBlock * copyBackBody = BasicBlock::Create(M->getContext(), "copy_back", current, 0);
157    BasicBlock * setConsumerPosExit = BasicBlock::Create(M->getContext(), "setConsumerPos_done", current, 0);
158    Constant * blockWidth = ConstantInt::get(sizeTy, iBuilder->getStride());
159    Constant * one = ConstantInt::get(sizeTy, 1);
160    Value * consumerPos_ptr = iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iConsumer_pos)});
161    Value * consumerPos = iBuilder->CreateLoad(consumerPos_ptr);
162    Value * consumerBlock = iBuilder->CreateUDiv(consumerPos, blockWidth);
163    // Ensure that the new consumer position is no less than the current position.
164    new_consumer_pos = iBuilder->CreateSelect(iBuilder->CreateICmpULT(new_consumer_pos, consumerPos), consumerPos, new_consumer_pos);
165    Value * producerPos = iBuilder->CreateLoad(iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iProducer_pos)}));
166    // Ensure that the new consumer position is no greater than the current producer position.
167    Value * new_pos_lt_producer_pos = iBuilder->CreateICmpULT(new_consumer_pos, producerPos);
168    new_consumer_pos = iBuilder->CreateSelect(new_pos_lt_producer_pos, new_consumer_pos, producerPos);
169    // Now, the new_consumer_pos is at most = to the producer_pos; if =, we're done.
170    iBuilder->CreateCondBr(new_pos_lt_producer_pos, copyBackBody, setConsumerPosExit);
171    iBuilder->SetInsertPoint(copyBackBody);
172   
173    Value * new_consumer_block = iBuilder->CreateUDiv(new_consumer_pos, blockWidth);
174   
175    Value * lastProducerBlock = iBuilder->CreateUDiv(iBuilder->CreateSub(producerPos, one), blockWidth);
176    //iBuilder->CallPrintInt("new_consumer_block", new_consumer_block);
177    //iBuilder->CallPrintInt("lastProducerBlock", lastProducerBlock);
178
179    Value * copyBlocks = iBuilder->CreateAdd(iBuilder->CreateSub(lastProducerBlock, new_consumer_block), one);
180
181    DataLayout dl(iBuilder->getModule());
182
183    Constant * blockBytes = ConstantInt::get(sizeTy, dl.getTypeAllocSize(mStreamSetType) * iBuilder->getStride());
184    Value * copyLength = iBuilder->CreateMul(copyBlocks, blockBytes);
185    //iBuilder->CallPrintInt("memmove copyLength", copyLength);
186    // Must copy back one full block for each of the streams in the stream set.
187    Value * handle = iBuilder->CreateGEP(bufferStructPtr, {iBuilder->getInt32(0), iBuilder->getInt32(iBuffer_ptr)});
188    Value * bufferPtr = iBuilder->CreateLoad(handle);
189    //iBuilder->CallPrintInt("memmove bufferPtr", iBuilder->CreatePtrToInt(bufferPtr, sizeTy));
190
191    Value * copyFrom = iBuilder->CreateGEP(bufferPtr, {iBuilder->CreateSub(new_consumer_block, consumerBlock)});
192    //iBuilder->CallPrintInt("memmove copyFrom", iBuilder->CreatePtrToInt(copyFrom, sizeTy));
193    Value * alignment = ConstantInt::get(iBuilder->getInt32Ty(), iBuilder->getBitBlockWidth()/8);
194   
195    iBuilder->CreateCall(memmoveFunc, {iBuilder->CreateBitCast(bufferPtr, i8_ptr), iBuilder->CreateBitCast(copyFrom, i8_ptr), copyLength, alignment, ConstantInt::getNullValue(i1)});
196    iBuilder->CreateBr(setConsumerPosExit);
197    // Copy back done, store the new consumer position.
198    iBuilder->SetInsertPoint(setConsumerPosExit);
199    iBuilder->CreateStore(new_consumer_pos, consumerPos_ptr);
200}   
Note: See TracBrowser for help on using the repository browser.