Changeset 5541 for icGREP/icgrep-devel


Ignore:
Timestamp:
Jul 1, 2017, 2:08:30 PM (2 years ago)
Author:
cameron
Message:

Dynamic Buffers - initial check-in

Location:
icGREP/icgrep-devel/icgrep
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/IR_Gen/CBuilder.cpp

    r5502 r5541  
    4141
    4242using namespace llvm;
     43
     44
     45Value * CBuilder::CreateURem(Value * number, Value * divisor, const Twine &Name) {
     46    if (ConstantInt * c = dyn_cast<ConstantInt>(divisor)) {
     47        uint64_t d = c->getZExtValue();
     48        if ((d & (d - 1)) == 0) { // is a power of 2 or 0
     49            if (d > 0) return CreateAnd(number, ConstantInt::get(divisor->getType(), d - 1), Name);
     50        }
     51    }
     52    return Insert(BinaryOperator::CreateURem(number, divisor), Name);
     53}
     54
     55Value * CBuilder::CreateUDiv(Value * number, Value * divisor, const Twine &Name) {
     56    if (ConstantInt * c = dyn_cast<ConstantInt>(divisor)) {
     57        uint64_t d = c->getZExtValue();
     58        if ((d & (d - 1)) == 0) { // is a power of 2 or 0
     59            if (d > 1) return CreateLShr(number, ConstantInt::get(divisor->getType(), std::log2(d)), Name);
     60            else if (d == 1) return number;
     61        }
     62    }
     63    return Insert(BinaryOperator::CreateUDiv(number, divisor), Name);
     64}
     65
     66Value * CBuilder::CreateUDivCeil(Value * number, Value * divisor, const Twine &Name) {
     67    if (ConstantInt * c = dyn_cast<ConstantInt>(divisor)) {
     68        uint64_t d = c->getZExtValue();
     69        if ((d & (d - 1)) == 0) { // is a power of 2 or 0
     70            if (d > 1) {
     71                Value * n = CreateAdd(number, ConstantInt::get(divisor->getType(), d - 1));
     72                return CreateLShr(n, ConstantInt::get(divisor->getType(), std::log2(d)), Name);
     73            }
     74            else if (d == 1) return number;
     75        }
     76    }
     77    return CreateUDiv(CreateAdd(number, CreateSub(divisor, ConstantInt::get(divisor->getType(), 1))), divisor, Name);
     78}
     79
     80
    4381
    4482Value * CBuilder::CreateOpenCall(Value * filename, Value * oflag, Value * mode) {
  • icGREP/icgrep-devel/icgrep/IR_Gen/CBuilder.h

    r5510 r5541  
    4848        ClearInsertionPoint();
    4949    }
    50 
     50   
     51    // UDiv and URem with optimization for division by power-of-2 constants
     52    llvm::Value * CreateUDiv(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "");
     53    llvm::Value * CreateURem(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "");
     54
     55    // Division with rounding up to the ceiling
     56    // Equivalent to CreateUDiv(CreateAdd(number, CreateSub(divisor, ConstantInt::get(divisor->getType(), 1))), divisor)
     57    llvm::Value * CreateUDivCeil(llvm::Value * number, llvm::Value * divisor, const llvm::Twine &Name = "");
     58       
    5159    llvm::Value * CreateMalloc(llvm::Value * size);
    5260
  • icGREP/icgrep-devel/icgrep/kernels/streamset.cpp

    r5506 r5541  
    577577}
    578578
     579Type * DynamicBuffer::getStreamSetBlockType() const {
     580    return cast<PointerType>(mType->getStructElementType(int(DynamicBuffer::Field::BaseAddress)))->getElementType();
     581}
     582
     583
     584
     585
     586Value * DynamicBuffer::getBaseAddress(IDISA::IDISA_Builder * const b, Value * const handle) const {
     587    b->CreateAssert(handle, "DynamicBuffer: instance cannot be null");
     588    Value * const p = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::BaseAddress))});
     589    Value * const addr = b->CreateLoad(p);
     590    b->CreateAssert(addr, "DynamicBuffer: base address cannot be 0");
     591    return addr;
     592}
     593
     594Value * DynamicBuffer::getStreamSetBlockPtr(IDISA::IDISA_Builder * const b, Value * handle, Value * blockIndex) const {
     595    Value * const wkgBlocks = b->CreateLoad(b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::WorkingBlocks))}));
     596    return b->CreateGEP(getBaseAddress(b, handle), b->CreateURem(blockIndex, wkgBlocks));
     597}
     598
     599Value * DynamicBuffer::getRawItemPointer(IDISA::IDISA_Builder * const b, Value * handle, Value * streamIndex, Value * absolutePosition) const {
     600    Value * absBlock = b->CreateUDiv(absolutePosition, b->getSize(b->getBitBlockWidth()));
     601    Value * blockPos = b->CreateURem(absolutePosition, b->getSize(b->getBitBlockWidth()));
     602    Value * blockPtr = b->CreateGEP(getStreamSetBlockPtr(b, handle, absBlock), {b->getInt32(0), streamIndex});
     603    const auto bw = mBaseType->getArrayElementType()->getScalarSizeInBits();
     604    if (bw < 8) {
     605        assert (bw  == 1 || bw == 2 || bw == 4);
     606        blockPos = b->CreateUDiv(blockPos, ConstantInt::get(blockPos->getType(), 8 / bw));
     607        blockPtr = b->CreatePointerCast(blockPtr, b->getInt8PtrTy());
     608    } else {
     609        blockPtr = b->CreatePointerCast(blockPtr, b->getIntNTy(bw)->getPointerTo());
     610    }
     611    return b->CreateGEP(blockPtr, blockPos);
     612}
     613
     614Value * DynamicBuffer::getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, Value * handle, Value * fromPosition) const {
     615    Constant * blockSize = b->getSize(b->getBitBlockWidth());
     616    if (isa<ArrayType>(mType) && dyn_cast<ArrayType>(mType)->getNumElements() > 1) {
     617        return b->CreateSub(blockSize, b->CreateURem(fromPosition, blockSize));
     618    } else {
     619        Value * const bufBlocks = b->CreateLoad(b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::WorkingBlocks))}));
     620        Value * bufSize = b->CreateMul(bufBlocks, blockSize);
     621        return b->CreateSub(bufSize, b->CreateURem(fromPosition, bufSize, "linearItems"));
     622    }
     623}
     624
     625Value * DynamicBuffer::getLinearlyAccessibleBlocks(IDISA::IDISA_Builder * const b, Value * handle, Value * fromBlock) const {
     626    Value * const bufBlocks = b->CreateLoad(b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::WorkingBlocks))}));
     627    return b->CreateSub(bufBlocks, b->CreateURem(fromBlock, bufBlocks), "linearBlocks");
     628}
     629
     630void DynamicBuffer::allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) {
     631    Value * handle = b->CreateCacheAlignedAlloca(getType());
     632    size_t numStreams = 1;
     633    if (isa<ArrayType>(mBaseType)) {
     634        numStreams = mBaseType->getArrayNumElements();
     635    }
     636    const auto fieldWidth = mBaseType->getArrayElementType()->getScalarSizeInBits();
     637    Value * bufSize = b->getSize((mBufferBlocks + mOverflowBlocks) * b->getBitBlockWidth() * numStreams * fieldWidth/8);
     638    Value * bufBasePtrField = b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::BaseAddress))});
     639    Value * bufPtr = b->CreatePointerCast(b->CreateCacheAlignedMalloc(bufSize), bufBasePtrField->getType()->getPointerElementType());
     640    b->CreateStore(bufPtr, bufBasePtrField);
     641    b->CreateStore(bufSize, b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::AllocatedCapacity))}));
     642    b->CreateStore(b->getSize(mBufferBlocks), b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::WorkingBlocks))}));
     643    b->CreateStore(b->getSize(-1), b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::Length))}));
     644    b->CreateStore(b->getSize(0), b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::ProducedPosition))}));
     645    b->CreateStore(b->getSize(0), b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::ConsumedPosition))}));
     646    mStreamSetBufferPtr = handle;
     647}
     648
     649void DynamicBuffer::releaseBuffer(IDISA::IDISA_Builder * const b, Value * handle) const {
     650    /* Free the dynamically allocated buffer, but not the stack-allocated buffer struct. */
     651    b->CreateFree(b->CreateLoad(b->CreateGEP(handle, {b->getInt32(0), b->getInt32(int(DynamicBuffer::Field::BaseAddress))})));
     652}
     653
     654
     655DynamicBuffer::DynamicBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, Type * type, size_t initialCapacity, size_t overflow, unsigned swizzle, unsigned addrSpace)
     656: StreamSetBuffer(BufferKind::DynamicBuffer, type,
     657                  StructType::get(resolveStreamSetType(b, type)->getPointerTo(addrSpace),
     658                                  b->getSizeTy(), b->getSizeTy(), b->getSizeTy(), b->getSizeTy(), b->getSizeTy(), nullptr),
     659                  initialCapacity, addrSpace)
     660, mSwizzleFactor(swizzle)
     661, mOverflowBlocks(overflow)
     662{
     663    mUniqueID = "DB";
     664    if (swizzle != 1) {
     665        mUniqueID += "s" + std::to_string(swizzle);
     666    }
     667        if (overflow != 0) {
     668        mUniqueID += "o" + std::to_string(overflow);
     669    }
     670    if (addrSpace != 0) {
     671        mUniqueID += "@" + std::to_string(addrSpace);
     672    }
     673}
     674
     675
    579676inline StreamSetBuffer::StreamSetBuffer(BufferKind k, Type * baseType, Type * resolvedType, unsigned BufferBlocks, unsigned AddressSpace)
    580677: mBufferKind(k)
  • icGREP/icgrep-devel/icgrep/kernels/streamset.h

    r5506 r5541  
    2727        , SwizzledCopybackBuffer
    2828        , ExpandableBuffer
     29        , DynamicBuffer
    2930    };
    3031
     
    296297
    297298};
     299   
     300// Dynamically allocated circular buffers: TODO: add copyback, swizzle support, dynamic allocation, producer, consumer, length
     301class DynamicBuffer: public StreamSetBuffer {
     302public:
     303    static inline bool classof(const StreamSetBuffer * b) {return b->getBufferKind() == BufferKind::DynamicBuffer;}
     304   
     305    DynamicBuffer(const std::unique_ptr<kernel::KernelBuilder> & b, llvm::Type * type, size_t initialCapacity, size_t overflowBlocks = 0, unsigned swizzleFactor = 1, unsigned addrSpace = 0);
     306   
     307    llvm::Value * getLinearlyAccessibleItems(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * fromPosition) const override;
     308   
     309    llvm::Value * getLinearlyAccessibleBlocks(IDISA::IDISA_Builder * const iBuilder, llvm::Value * self, llvm::Value * fromBlock) const override;
     310
     311    void allocateBuffer(const std::unique_ptr<kernel::KernelBuilder> & b) override;
     312
     313    void releaseBuffer(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
     314
     315    llvm::Value * getRawItemPointer(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * streamIndex, llvm::Value * absolutePosition) const override;
     316
     317    llvm::Type * getStreamSetBlockType() const override;
     318   
     319protected:
     320    llvm::Value * getBaseAddress(IDISA::IDISA_Builder * const b, llvm::Value * handle) const override;
     321   
     322    llvm::Value * getStreamSetBlockPtr(IDISA::IDISA_Builder * const b, llvm::Value * handle, llvm::Value * blockIndex) const override;
     323   
     324private:
     325    /* Static data */
     326    unsigned   mSwizzleFactor;     /* Number of streams swizzled together per block.  Must be a small power of 2. Default: 1. */
     327    size_t     mOverflowBlocks;    /* Number of data blocks of additional space at the end of the buffer for writing only. */
     328   
     329    /* Dynamic data fields stored in the buffer struct */
     330   
     331    enum class Field {BaseAddress, AllocatedCapacity, WorkingBlocks, Length, ProducedPosition, ConsumedPosition, FieldCount};
     332   
     333    /* BaseAddress - the physical base address of the memory area for stream set data.
     334     WorkingBlocks - the physical size of the buffer for use in reading and writing data.
     335     AllocatedCapacity - physical size available for expansion in place
     336     Length - actual final length of stream set or -1 for unknown
     337     ProducedPosition - the total number of items ever generated and stored in the buffer
     338     ConsumedPosition - the number of buffer items that are known to have been fully processed by all users
     339     */
     340   
     341};
     342
    298343
    299344}
Note: See TracChangeset for help on using the changeset viewer.