Ignore:
Timestamp:
Aug 15, 2017, 12:19:01 AM (22 months ago)
Author:
cameron
Message:

Dynamic buffer capacity doubling - initial check-in

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/kernels/streamset.cpp

    r5597 r5612  
    655655}
    656656
     657Value * DynamicBuffer::getBufferedSize(IDISA::IDISA_Builder * const iBuilder, Value * self) const {
     658    Value * ptr = iBuilder->CreateGEP(self, {iBuilder->getInt32(0), iBuilder->getInt32(int(Field::WorkingBlocks))});
     659    return iBuilder->CreateMul(iBuilder->CreateLoad(ptr), iBuilder->getSize(iBuilder->getBitBlockWidth()));
     660}
     661
     662
     663
    657664void DynamicBuffer::allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) {
    658665    Value * handle = b->CreateCacheAlignedAlloca(mBufferStructType);
     
    665672    bufSize = b->CreateRoundUp(bufSize, b->getSize(b->getCacheAlignment()));
    666673    Value * bufBasePtrField = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(Field::BaseAddress))});
    667     Value * bufPtr = b->CreatePointerCast(b->CreateCacheAlignedMalloc(bufSize), bufBasePtrField->getType()->getPointerElementType());
     674    Type * bufPtrType = bufBasePtrField->getType()->getPointerElementType();
     675    Value * bufPtr = b->CreatePointerCast(b->CreateCacheAlignedMalloc(bufSize), bufPtrType);
    668676    b->CreateStore(bufPtr, bufBasePtrField);
     677    b->CreateStore(ConstantPointerNull::getNullValue(bufPtrType), b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::PriorBaseAddress))}));
    669678    b->CreateStore(bufSize, b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(Field::AllocatedCapacity))}));
    670679    b->CreateStore(b->getSize(mBufferBlocks), b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(Field::WorkingBlocks))}));
     
    676685
    677686void DynamicBuffer::releaseBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) const {
     687    Value * handle = mStreamSetBufferPtr;
    678688    /* Free the dynamically allocated buffer, but not the stack-allocated buffer struct. */
    679     b->CreateFree(b->CreateLoad(b->CreateGEP(mStreamSetBufferPtr, {b->getInt32(0), b->getInt32(int(Field::BaseAddress))})));
    680 }
    681 
     689    Value * bufBasePtrField = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::BaseAddress))});
     690    Type * bufPtrType = bufBasePtrField->getType()->getPointerElementType();
     691    Value * priorBasePtrField = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::PriorBaseAddress))});
     692    BasicBlock * freePrior = b->CreateBasicBlock("freePrior");
     693    BasicBlock * freeCurrent = b->CreateBasicBlock("freeCurrent");
     694    Value * priorBuf = b->CreateLoad(priorBasePtrField);
     695    Value * priorBufIsNonNull = b->CreateICmpNE(priorBuf, ConstantPointerNull::get(cast<PointerType>(bufPtrType)));
     696    b->CreateCondBr(priorBufIsNonNull, freePrior, freeCurrent);
     697    b->SetInsertPoint(freePrior);
     698    b->CreateFree(priorBuf);
     699    b->CreateBr(freeCurrent);
     700    b->SetInsertPoint(freeCurrent);
     701    b->CreateFree(b->CreateLoad(bufBasePtrField));
     702}
     703
     704//
     705//  Simple capacity doubling.  Use the circular buffer property: duplicating buffer data
     706//  ensures that we have correct data.   TODO: consider optimizing based on actual
     707//  consumer and producer positions.
     708//
     709void DynamicBuffer::doubleCapacity(IDISA::IDISA_Builder * const b, Value * handle) {
     710    size_t numStreams = 1;
     711    if (isa<ArrayType>(mBaseType)) {
     712        numStreams = mBaseType->getArrayNumElements();
     713    }
     714    const auto fieldWidth = mBaseType->getArrayElementType()->getScalarSizeInBits();
     715    Constant * blockBytes = b->getSize(b->getBitBlockWidth() * numStreams * fieldWidth/8);
     716    Value * bufBasePtrField = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::BaseAddress))});
     717    Type * bufPtrType = bufBasePtrField->getType()->getPointerElementType();
     718    Value * priorBasePtrField = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::PriorBaseAddress))});
     719    Value * workingBlocksField = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::WorkingBlocks))});
     720    Value * capacityField = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::AllocatedCapacity))});
     721   
     722    Value * oldBufPtr = b->CreateLoad(bufBasePtrField);
     723    Value * const currentWorkingBlocks = b->CreateLoad(workingBlocksField);
     724    Value * workingBytes = b->CreateMul(currentWorkingBlocks, blockBytes);
     725    Value * const curAllocated = b->CreateLoad(capacityField);
     726    Value * neededCapacity = b->CreateAdd(workingBytes, workingBytes);
     727    if (mOverflowBlocks > 0) {
     728        Constant * overflowBytes = b->getSize(mOverflowBlocks * b->getBitBlockWidth() * numStreams * fieldWidth/8);
     729        neededCapacity = b->CreateAdd(neededCapacity, overflowBytes);
     730    }
     731    neededCapacity = b->CreateRoundUp(neededCapacity, b->getSize(b->getCacheAlignment()));
     732    BasicBlock * doubleEntry = b->GetInsertBlock();
     733    BasicBlock * doRealloc = b->CreateBasicBlock("doRealloc");
     734    BasicBlock * doCopy2 = b->CreateBasicBlock("doCopy2");
     735    b->CreateCondBr(b->CreateICmpULT(curAllocated, neededCapacity), doRealloc, doCopy2);
     736    b->SetInsertPoint(doRealloc);
     737    // If there is a non-null priorBasePtr, free it.
     738    Value * priorBuf = b->CreateLoad(priorBasePtrField);
     739    Value * priorBufIsNonNull = b->CreateICmpNE(priorBuf, ConstantPointerNull::get(cast<PointerType>(bufPtrType)));
     740    BasicBlock * deallocatePrior = b->CreateBasicBlock("deallocatePrior");
     741    BasicBlock * allocateNew = b->CreateBasicBlock("allocateNew");
     742    b->CreateCondBr(priorBufIsNonNull, deallocatePrior, allocateNew);
     743    b->SetInsertPoint(deallocatePrior);
     744    b->CreateFree(priorBuf);
     745    b->CreateBr(allocateNew);
     746    b->SetInsertPoint(allocateNew);
     747    b->CreateStore(oldBufPtr, priorBasePtrField);
     748    Value * newBufPtr = b->CreatePointerCast(b->CreateCacheAlignedMalloc(neededCapacity), bufPtrType);
     749    b->CreateStore(newBufPtr, bufBasePtrField);
     750    createBlockCopy(b, newBufPtr, oldBufPtr, currentWorkingBlocks);
     751    b->CreateStore(neededCapacity, capacityField);
     752    b->CreateBr(doCopy2);
     753    b->SetInsertPoint(doCopy2);
     754    PHINode * bufPtr = b->CreatePHI(oldBufPtr->getType(), 2);
     755    bufPtr->addIncoming(oldBufPtr, doubleEntry);
     756    bufPtr->addIncoming(newBufPtr, doRealloc);
     757    createBlockCopy(b, b->CreateGEP(bufPtr, currentWorkingBlocks), bufPtr, currentWorkingBlocks);
     758    b->CreateStore(b->CreateAdd(currentWorkingBlocks, currentWorkingBlocks), workingBlocksField);
     759}
    682760
    683761DynamicBuffer::DynamicBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, Type * type, size_t initialCapacity, size_t overflow, unsigned swizzle, unsigned addrSpace)
    684762: StreamSetBuffer(BufferKind::DynamicBuffer, type, resolveStreamSetType(b, type), initialCapacity, addrSpace)
    685 , mBufferStructType(StructType::get(resolveStreamSetType(b, type)->getPointerTo(addrSpace),
     763, mBufferStructType(StructType::get(resolveStreamSetType(b, type)->getPointerTo(addrSpace), resolveStreamSetType(b, type)->getPointerTo(addrSpace),
    686764                                    b->getSizeTy(), b->getSizeTy(), b->getSizeTy(), b->getSizeTy(), b->getSizeTy(), nullptr))
    687765, mSwizzleFactor(swizzle)
Note: See TracChangeset for help on using the changeset viewer.