Ignore:
Timestamp:
Apr 3, 2016, 4:31:22 PM (3 years ago)
Author:
nmedfort
Message:

Redesigned buffer system to allow the pipeline to control selection of the current input and output streams; DoBlock? functions containing lookahead now take multiple input stream arguments. Selection and passing occurs automatically. Some work on Symbol Table.

File:
1 edited

Legend:

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

    r4995 r5000  
    1515using namespace pablo;
    1616
    17 inline bool isPowerOfTwo(const unsigned x) {
    18     return (x != 0) && (x & (x - 1)) == 0;
    19 }
    20 
    2117namespace kernel {
    2218
    23 enum : unsigned {
    24     INTERNAL_STATE = 0
    25     , INPUT_STREAM_SET = 1
    26     , OUTPUT_STREAM_SET = 2
    27     , OUTPUT_SCALAR_SET = 3
    28 };
    29 
    3019// sets name & sets internal state to the kernel superclass state
    31 KernelBuilder::KernelBuilder(std::string name, Module * m, IDISA::IDISA_Builder * b, const unsigned bufferSize)
    32 : mMod(m)
    33 , iBuilder(b)
     20KernelBuilder::KernelBuilder(IDISA::IDISA_Builder * builder, std::string && name, const unsigned defaultBufferSize)
     21: iBuilder(builder)
    3422, mKernelName(name)
    35 , mBitBlockType(b->getBitBlockType())
    36 , mBufferSize(bufferSize)
     23, mDefaultBufferSize(defaultBufferSize)
     24, mBitBlockType(builder->getBitBlockType())
    3725, mBlockNoIndex(0) {
    38     assert (mBufferSize > 0);
    39     mBlockNoIndex = addInternalState(b->getInt64Ty(), "BlockNo");
    40 }
    41 
    42 SlabAllocator<Instance> Instance::mAllocator; // static allocator declaration; should probably be in a "instance.cpp"
     26    assert (mDefaultBufferSize > 0);
     27    mBlockNoIndex = iBuilder->getInt32(addInternalState(builder->getInt64Ty(), "BlockNo"));
     28}
    4329
    4430/** ------------------------------------------------------------------------------------------------------------- *
     
    5743    }
    5844    const unsigned index = addInternalState(type);
    59     mInternalStateNameMap.emplace(name, index);
     45    mInternalStateNameMap.emplace(name, iBuilder->getInt32(index));
    6046    return index;
    6147}
     
    6450 * @brief getInternalState
    6551 ** ------------------------------------------------------------------------------------------------------------- */
    66 Value * KernelBuilder::getInternalState(Value * const instance, const unsigned index) {
    67     assert (index < mInternalState.size());
    68     return getInternalState(instance, iBuilder->getInt32(index));
    69 }
    70 
    71 Value * KernelBuilder::getInternalState(Value * const instance, disable_implicit_conversion<Value *> index) {
    72     assert (index->getType()->isIntegerTy());
    73     return iBuilder->CreateGEP(instance, {iBuilder->getInt64(0), iBuilder->getInt32(INTERNAL_STATE), index});
    74 }
    75 
    76 Value * KernelBuilder::getInternalState(Value * const instance, const std::string & name) {
     52Value * KernelBuilder::getInternalState(Value * const kernelState, disable_implicit_conversion<Value *> index) {
     53    assert (index->getType()->isIntegerTy());   
     54    assert (kernelState->getType()->getPointerElementType() == mKernelStateType);
     55    return iBuilder->CreateGEP(kernelState, {iBuilder->getInt32(0), index});
     56}
     57
     58Value * KernelBuilder::getInternalState(Value * const kernelState, const std::string & name) {
    7759    const auto f = mInternalStateNameMap.find(name);
    7860    if (LLVM_UNLIKELY(f == mInternalStateNameMap.end())) {
    7961        throw std::runtime_error("Kernel does not contain internal state " + name);
    8062    }
    81     return getInternalState(instance, f->second);
     63    return getInternalState(kernelState, f->second);
    8264}
    8365
     
    8567 * @brief setInternalState
    8668 ** ------------------------------------------------------------------------------------------------------------- */
    87 void KernelBuilder::setInternalState(Value * const instance, const std::string & name, Value * const value) {
    88     Value * ptr = getInternalState(instance, name);
     69void KernelBuilder::setInternalState(Value * const kernelState, const std::string & name, Value * const value) {
     70    Value * ptr = getInternalState(kernelState, name);
    8971    assert (ptr->getType()->getPointerElementType() == value->getType());
    9072    if (value->getType() == iBuilder->getBitBlockType()) {
     
    9577}
    9678
    97 void KernelBuilder::setInternalState(Value * const instance, const unsigned index, Value * const value) {
    98     assert (index < mInternalState.size());
    99     return setInternalState(instance, iBuilder->getInt32(index), value);
    100 }
    101 
    102 void KernelBuilder::setInternalState(Value * const instance, disable_implicit_conversion<Value *> index, Value * const value) {
    103     Value * ptr = getInternalState(instance, index);
     79void KernelBuilder::setInternalState(Value * const kernelState, disable_implicit_conversion<Value *> index, Value * const value) {
     80    Value * ptr = getInternalState(kernelState, index);
    10481    assert (ptr->getType()->getPointerElementType() == value->getType());
    10582    if (value->getType() == iBuilder->getBitBlockType()) {
     
    130107 * @brief getInputStream
    131108 ** ------------------------------------------------------------------------------------------------------------- */
    132 Value * KernelBuilder::getInputStream(Value * const instance, const unsigned index, const unsigned streamOffset) {
    133     assert (index < mInputStream.size());
    134     return getInputStream(instance, iBuilder->getInt32(index), streamOffset);
    135 }
    136 
    137 Value * KernelBuilder::getInputStream(Value * const instance, disable_implicit_conversion<Value *> index, const unsigned streamOffset) {
    138     assert (instance && index);
    139     assert (index->getType()->isIntegerTy());
    140     Value * const inputStreamSet = iBuilder->CreateLoad(iBuilder->CreateGEP(instance,
    141         {iBuilder->getInt32(0), iBuilder->getInt32(INPUT_STREAM_SET), iBuilder->getInt32(0)}));
    142     Value * modFunction = iBuilder->CreateLoad(iBuilder->CreateGEP(instance,
    143         {iBuilder->getInt32(0), iBuilder->getInt32(INPUT_STREAM_SET), iBuilder->getInt32(1)}));
    144     Value * offset = iBuilder->CreateLoad(getBlockNo(instance));
    145     if (streamOffset) {
    146         offset = iBuilder->CreateAdd(offset, ConstantInt::get(offset->getType(), streamOffset));
    147     }
    148     if (LLVM_LIKELY(isa<ConstantInt>(index.get()) || inputStreamSet->getType()->getPointerElementType()->isArrayTy())) {
    149         return iBuilder->CreateGEP(inputStreamSet, { iBuilder->CreateCall(modFunction, offset), index });
    150     } else {
    151         throw std::runtime_error("Cannot access the input stream with a non-constant value unless all input stream types are identical!");
    152     }
     109Value * KernelBuilder::getInputStream(Value * const inputStreamSet, disable_implicit_conversion<Value *> index) {
     110    assert ("Parameters cannot be null!" && (inputStreamSet != nullptr && index != nullptr));
     111    assert ("Stream index must be an integer!" && index->getType()->isIntegerTy());
     112    assert ("Illegal input stream set provided!" && inputStreamSet->getType()->getPointerElementType() == mInputStreamType);
     113    if (LLVM_LIKELY(isa<ConstantInt>(index.get()) || getInputStreamType()->isArrayTy())) {
     114        return iBuilder->CreateGEP(inputStreamSet, { iBuilder->getInt32(0), index });
     115    }
     116    #ifndef NDEBUG
     117    iBuilder->getModule()->dump();
     118    #endif
     119    throw std::runtime_error("Cannot access the input stream with a non-constant value unless all input stream types are identical!");
    153120}
    154121
     
    169136 * @brief getInputScalar
    170137 ** ------------------------------------------------------------------------------------------------------------- */
    171 Value * KernelBuilder::getInputScalar(Value * const instance, const unsigned) {
    172     assert (instance);
    173     throw std::runtime_error("currently not supported!");
    174 }
    175 
    176 Value * KernelBuilder::getInputScalar(Value * const instance, disable_implicit_conversion<Value *>) {
    177     assert (instance);
     138Value * KernelBuilder::getInputScalar(Value * const inputScalarSet, disable_implicit_conversion<Value *>) {
     139    assert (inputScalarSet);
    178140    throw std::runtime_error("currently not supported!");
    179141}
     
    202164 * @brief getOutputStream
    203165 ** ------------------------------------------------------------------------------------------------------------- */
    204 Value * KernelBuilder::getOutputStream(Value * const instance, const unsigned index, const unsigned streamOffset) {
    205     assert (index < mOutputStream.size());
    206     return getOutputStream(instance, iBuilder->getInt32(index), streamOffset);
    207 }
    208 
    209 Value * KernelBuilder::getOutputStream(Value * const instance, disable_implicit_conversion<Value *> index, const unsigned streamOffset) {
    210     assert (instance && index);
    211     assert (index->getType()->isIntegerTy());
    212     if (LLVM_LIKELY(isa<ConstantInt>(index.get()))) {
    213         return iBuilder->CreateGEP(instance, {iBuilder->getInt32(0), iBuilder->getInt32(OUTPUT_STREAM_SET), getStreamOffset(instance, streamOffset), index});
    214     } else {
    215         Value * const outputStreamSet = iBuilder->CreateGEP(instance, {iBuilder->getInt32(0), iBuilder->getInt32(OUTPUT_STREAM_SET)});
    216         if (LLVM_LIKELY(outputStreamSet->getType()->getPointerElementType()->isArrayTy())) {
    217             return iBuilder->CreateGEP(outputStreamSet, {getStreamOffset(instance, streamOffset), index});
    218         }
     166Value * KernelBuilder::getOutputStream(Value * const outputStreamSet, disable_implicit_conversion<Value *> index) {
     167    assert ("Parameters cannot be null!" && (outputStreamSet != nullptr && index != nullptr));
     168    assert ("Stream index must be an integer!" && index->getType()->isIntegerTy());
     169    assert ("Illegal output stream set provided!" && outputStreamSet->getType()->getPointerElementType() == getOutputStreamType());
     170    if (LLVM_LIKELY(isa<ConstantInt>(index.get()) || getOutputStreamType()->isArrayTy())) {
     171        return iBuilder->CreateGEP(outputStreamSet, { iBuilder->getInt32(0), index });
    219172    }
    220173    throw std::runtime_error("Cannot access the output stream with a non-constant value unless all output stream types are identical!");
     
    224177 * @brief getOutputScalar
    225178 ** ------------------------------------------------------------------------------------------------------------- */
    226 Value * KernelBuilder::getOutputScalar(Value * const instance, const unsigned) {
     179Value * KernelBuilder::getOutputScalar(Value * const outputScalarSet, disable_implicit_conversion<Value *> ) {
    227180    throw std::runtime_error("currently not supported!");
    228181}
    229182
    230 Value * KernelBuilder::getOutputScalar(Value * const instance, disable_implicit_conversion<Value *> ) {
    231     throw std::runtime_error("currently not supported!");
    232 }
    233 
    234183/** ------------------------------------------------------------------------------------------------------------- *
    235184 * @brief packDataTypes
    236185 ** ------------------------------------------------------------------------------------------------------------- */
    237 llvm::Type * KernelBuilder::packDataTypes(const std::vector<llvm::Type *> & types) {
    238     bool canPackIntoArray = !types.empty();
     186Type * KernelBuilder::packDataTypes(const std::vector<llvm::Type *> & types) {
     187    if (types.empty()) {
     188        return nullptr;
     189    }
    239190    for (Type * type : types) {
    240191        if (type != types.front()) { // use canLosslesslyBitcastInto ?
    241             canPackIntoArray = false;
    242             break;
     192            return StructType::get(iBuilder->getContext(), types);
    243193        }
    244194    }
    245     if (canPackIntoArray) {
    246         return ArrayType::get(types.front(), types.size());
    247     } else {
    248         return StructType::get(mMod->getContext(), types);
    249     }
     195    return ArrayType::get(types.front(), types.size());
    250196}
    251197
     
    253199 * @brief prepareFunction
    254200 ** ------------------------------------------------------------------------------------------------------------- */
    255 Function * KernelBuilder::prepareFunction() {
    256 
    257     PointerType * modFunctionType = PointerType::get(FunctionType::get(iBuilder->getInt64Ty(), {iBuilder->getInt64Ty()}, false), 0);
    258     mInputStreamType = PointerType::get(packDataTypes(mInputStream), 0);
    259     mInputScalarType = PointerType::get(packDataTypes(mInputScalar), 0);
     201Function * KernelBuilder::prepareFunction(std::vector<unsigned> && inputStreamOffsets) {
     202
     203    mKernelStateType = StructType::create(iBuilder->getContext(), mInternalState, mKernelName);
     204    mInputScalarType = packDataTypes(mInputScalar);
     205    mInputStreamType = packDataTypes(mInputStream);
     206    mOutputScalarType = packDataTypes(mInputScalar);
    260207    mOutputStreamType = packDataTypes(mOutputStream);
    261     Type * outputScalarType = packDataTypes(mOutputScalar);
    262     Type * internalStateType = packDataTypes(mInternalState);
    263     Type * inputStateType = StructType::create(mMod->getContext(), { mInputStreamType, modFunctionType});
    264     Type * outputBufferType = ArrayType::get(mOutputStreamType, mBufferSize);
    265     mKernelStateType = StructType::create(mMod->getContext(), {internalStateType, inputStateType, outputBufferType, outputScalarType}, mKernelName);
    266 
    267     FunctionType * const functionType = FunctionType::get(iBuilder->getVoidTy(), {PointerType::get(mKernelStateType, 0)}, false);
    268     mDoBlock = Function::Create(functionType, GlobalValue::ExternalLinkage, mKernelName + "_DoBlock", mMod);
    269     mDoBlock->setCallingConv(CallingConv::C);   
    270     mDoBlock->setDoesNotCapture(1);
     208    mInputStreamOffsets = inputStreamOffsets;
     209
     210    std::vector<Type *> params;
     211    params.push_back(mKernelStateType->getPointerTo());
     212    if (mInputScalarType) {
     213        params.push_back(mInputScalarType->getPointerTo());
     214    }
     215    if (mInputStreamType) {
     216        for (unsigned i = 0; i < mInputStreamOffsets.size(); ++i) {
     217            params.push_back(mInputStreamType->getPointerTo());
     218        }
     219    }
     220    if (mOutputScalarType) {
     221        params.push_back(mOutputScalarType->getPointerTo());
     222    }
     223    if (mOutputStreamType) {
     224        params.push_back(mOutputStreamType->getPointerTo());
     225    }
     226
     227    // A pointer value is captured if the function makes a copy of any part of the pointer that outlives
     228    // the call (e.g., stored in a global or, depending on the context, when returned by the function.)
     229    // Since this does not occur in either our DoBlock or Constructor, all parameters are marked nocapture.
     230
     231    FunctionType * const functionType = FunctionType::get(iBuilder->getVoidTy(), params, false);
     232    mDoBlock = Function::Create(functionType, GlobalValue::ExternalLinkage, mKernelName + "_DoBlock", iBuilder->getModule());
     233    mDoBlock->setCallingConv(CallingConv::C);
     234    for (unsigned i = 1; i <= params.size(); ++i) {
     235        mDoBlock->setDoesNotCapture(i);
     236    }
    271237    mDoBlock->setDoesNotThrow();
    272 
    273238    Function::arg_iterator args = mDoBlock->arg_begin();
    274     mKernelState = args++;
    275     mKernelState->setName("this");
    276 
    277     iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mDoBlock, 0));
    278 
     239    mKernelStateParam = args++;
     240    mKernelStateParam->setName("this");
     241    if (mInputScalarType) {
     242        mInputScalarParam = args++;
     243        mInputScalarParam->setName("inputScalars");
     244    }
     245    if (mInputStreamType) {
     246        for (const unsigned offset : mInputStreamOffsets) {
     247            Value * const inputStreamSet = args++;
     248            inputStreamSet->setName("inputStreamSet" + std::to_string(offset));
     249            mInputStreamParam.emplace(offset, inputStreamSet);
     250        }
     251    }
     252    if (mOutputScalarType) {
     253        mOutputScalarParam = args++;
     254        mOutputScalarParam->setName("outputScalars");
     255    }
     256    if (mOutputStreamType) {
     257        mOutputStreamParam = args;
     258        mOutputStreamParam->setName("outputStreamSet");
     259    }
     260    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", mDoBlock, 0));
    279261    return mDoBlock;
    280262}
     
    284266 ** ------------------------------------------------------------------------------------------------------------- */
    285267void KernelBuilder::finalize() {
    286 
    287268    // Finish the actual function
    288269    Value * blockNo = getBlockNo();
     
    292273    iBuilder->CreateRetVoid();
    293274
    294     eliminateRedundantMemoryOperations(mDoBlock);
    295 
    296     // Generate the zero initializer
    297     PointerType * modFunctionType = PointerType::get(FunctionType::get(iBuilder->getInt64Ty(), {iBuilder->getInt64Ty()}, false), 0);
    298     FunctionType * constructorType = FunctionType::get(iBuilder->getVoidTy(), {PointerType::get(mKernelStateType, 0), mInputStreamType, modFunctionType}, false);
    299 
    300     mConstructor = Function::Create(constructorType, GlobalValue::ExternalLinkage, mKernelName + "_Constructor", mMod);
    301     mConstructor->setCallingConv(CallingConv::C);
    302     mDoBlock->setDoesNotCapture(1);
    303     mConstructor->addAttribute(AttributeSet::FunctionIndex, Attribute::InlineHint);
    304     mDoBlock->setDoesNotThrow();
    305 
    306     auto args = mConstructor->arg_begin();
    307     mKernelState = args++;
    308     mKernelState->setName("this");
    309     Value * const inputStream = args++;
    310     inputStream->setName("inputStream");
    311     Value * const modFunction = args++;
    312     modFunction->setName("modFunction");
    313 
    314     iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mConstructor, 0));
    315     for (unsigned i = 0; i < mInternalState.size(); ++i) {
    316         Type * const type = mInternalState[i];
    317         if (type->isSized()) {
    318             setInternalState(i, Constant::getNullValue(type));
    319         } else {
    320             Value * const ptr = getInternalState(i);
    321             Value * const size = iBuilder->CreatePtrDiff(iBuilder->CreateGEP(ptr, iBuilder->getInt32(1)), ptr);
    322             iBuilder->CallPrintInt(mKernelName + "_zeroinit_" + std::to_string(i), size);
    323             iBuilder->CreateMemSet(ptr, iBuilder->getInt8(0), size, 4);
    324         }
    325     }
    326 
    327     Value * const input = iBuilder->CreateGEP(mKernelState, {iBuilder->getInt32(0), iBuilder->getInt32(INPUT_STREAM_SET)});
    328     iBuilder->CreateStore(inputStream, iBuilder->CreateGEP(input, {iBuilder->getInt32(0), iBuilder->getInt32(0)}));
    329     iBuilder->CreateStore(modFunction, iBuilder->CreateGEP(input, {iBuilder->getInt32(0), iBuilder->getInt32(1)}));
    330     iBuilder->CreateRetVoid();
    331 
    332 //    if (mOutputStreamType->getStructNumElements()) {
    333 //        PointerType * outputStreamType = PointerType::get(mOutputStreamType, 0);
    334 //        FunctionType * type = FunctionType::get(outputStreamType, {outputStreamType, PointerType::get(blockNo->getType(), 0)}, false);
    335 //        mStreamSetFunction = Function::Create(type, Function::ExternalLinkage, mKernelName + "_StreamSet", mMod);
    336 //        auto arg = mStreamSetFunction->arg_begin();
    337 //        Value * stream = arg++;
    338 //        stream->setName("stream");
    339 //        mStreamSetFunction->addAttribute(1, Attribute::NoCapture);
    340 //        mStreamSetFunction->addAttribute(2, Attribute::NoCapture);
    341 //        mStreamSetFunction->addAttribute(AttributeSet::FunctionIndex, Attribute::InlineHint);
    342 //        mStreamSetFunction->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
    343 //        Value * offset = arg;
    344 //        BasicBlock * entry = BasicBlock::Create(mMod->getContext(), "entry", mStreamSetFunction);
    345 //        iBuilder->SetInsertPoint(entry);
    346 //        if (mBufferSize != 1) {
    347 //            offset = iBuilder->CreateLoad(offset);
    348 //            if (isPowerOfTwo(mBufferSize)) {
    349 //                offset = iBuilder->CreateAnd(offset, iBuilder->getInt64(mBufferSize - 1));
    350 //            } else if (mBufferSize > 2) {
    351 //                offset = iBuilder->CreateURem(offset, iBuilder->getInt64(mBufferSize));
    352 //            }
    353 //            stream = iBuilder->CreateGEP(stream, offset);
    354 //        }
    355 //        iBuilder->CreateRet(stream);
    356 //    }
    357 
     275    mKernelStateParam = nullptr;
     276    mInputScalarParam = nullptr;
     277    mInputStreamParam.clear();
     278    mOutputScalarParam = nullptr;
     279    mOutputStreamParam = nullptr;
    358280    iBuilder->ClearInsertionPoint();
    359281}
    360282
    361283/** ------------------------------------------------------------------------------------------------------------- *
    362  * @brief eliminateRedundantMemoryOperations
    363  ** ------------------------------------------------------------------------------------------------------------- */
    364 inline void KernelBuilder::eliminateRedundantMemoryOperations(Function * const function) {
    365 
    366 
     284 * @brief instantiate
     285 *
     286 * Allocate and zero initialize the memory for this kernel and its output scalars and streams
     287 ** ------------------------------------------------------------------------------------------------------------- */
     288Instance * KernelBuilder::instantiate(std::pair<Value *, unsigned> && inputStreamSet, const unsigned outputBufferSize) {
     289    AllocaInst * const kernelState = iBuilder->CreateAlloca(mKernelStateType);
     290    iBuilder->CreateStore(Constant::getNullValue(mKernelStateType), kernelState);
     291    AllocaInst * outputScalars = nullptr;
     292    if (mOutputScalarType) {
     293        outputScalars = iBuilder->CreateAlloca(mOutputScalarType);
     294    }
     295    AllocaInst * outputStreamSets = nullptr;
     296    if (mOutputStreamType) {
     297        outputStreamSets = iBuilder->CreateAlloca(mOutputStreamType, iBuilder->getInt32(outputBufferSize));
     298    }
     299    return new Instance(this, kernelState, nullptr, std::get<0>(inputStreamSet), std::get<1>(inputStreamSet), outputScalars, outputStreamSets, outputBufferSize);
    367300}
    368301
     
    372305 * Generate a new instance of this kernel and call the default constructor to initialize it
    373306 ** ------------------------------------------------------------------------------------------------------------- */
    374 Instance * KernelBuilder::instantiate(std::pair<Value *, unsigned> && inputStream) {
    375     AllocaInst * const memory = iBuilder->CreateAlloca(mKernelStateType);
    376     Value * const indices[] = {iBuilder->getInt32(0), iBuilder->getInt32(OUTPUT_STREAM_SET)};
    377     Value * ptr = iBuilder->CreateGEP(std::get<0>(inputStream), indices);
    378     iBuilder->CreateCall3(mConstructor, memory, iBuilder->CreatePointerCast(ptr, mInputStreamType), CreateModFunction(std::get<1>(inputStream)));
    379     return new Instance(this, memory);
    380 }
    381 
    382 /** ------------------------------------------------------------------------------------------------------------- *
    383  * @brief instantiate
    384  *
    385  * Generate a new instance of this kernel and call the default constructor to initialize it
    386  ** ------------------------------------------------------------------------------------------------------------- */
    387 Instance * KernelBuilder::instantiate(llvm::Value * const inputStream) {
    388     AllocaInst * const memory = iBuilder->CreateAlloca(mKernelStateType);
    389     iBuilder->CreateCall3(mConstructor, memory, iBuilder->CreatePointerCast(inputStream, mInputStreamType), CreateModFunction(0));
    390     return new Instance(this, memory);
    391 }
    392 
    393 /** ------------------------------------------------------------------------------------------------------------- *
    394  * @brief instantiate
    395  *
    396  * Generate a new instance of this kernel and call the default constructor to initialize it
    397  ** ------------------------------------------------------------------------------------------------------------- */
    398 Instance * KernelBuilder::instantiate(std::initializer_list<llvm::Value *> inputStreams) {
    399     if (mInputStreamType->getStructNumElements() != inputStreams.size()) {
    400         throw std::runtime_error(mKernelName + ".instantiate expected " + std::to_string(inputStreams.size()) +
    401                                  "elements but was given " + std::to_string(mInputStreamType->getStructNumElements()));
    402     }
    403     AllocaInst * const memory = iBuilder->CreateAlloca(mKernelStateType);
    404     AllocaInst * inputStruct = iBuilder->CreateAlloca(mInputStreamType, 0);
    405     unsigned i = 0;
    406     for (Value * inputStream : inputStreams) {
    407         Value * ptr = iBuilder->CreateGEP(inputStruct, { iBuilder->getInt32(0), iBuilder->getInt32(i++)});
    408         iBuilder->CreateStore(inputStream, ptr);
    409     }
    410     iBuilder->CreateCall3(mConstructor, memory, iBuilder->CreatePointerCast(inputStruct, mInputStreamType), CreateModFunction(0));
    411     return new Instance(this, memory);
    412 }
    413 
    414 /** ------------------------------------------------------------------------------------------------------------- *
    415  * @brief CreateDoBlockCall
    416  ** ------------------------------------------------------------------------------------------------------------- */
    417 void KernelBuilder::CreateDoBlockCall(Value * const instance) {
    418     assert (mDoBlock && instance);
    419     iBuilder->CreateCall(mDoBlock, instance);
    420 }
    421 
    422 /** ------------------------------------------------------------------------------------------------------------- *
    423  * @brief clearOutputStreamSet
    424  *
    425  * Zero out the i + streamOffset stream set memory, where i is the current stream set indicated by the BlockNo.
    426  ** ------------------------------------------------------------------------------------------------------------- */
    427 void KernelBuilder::clearOutputStreamSet(Value * const instance, const unsigned streamOffset) {
    428     Value * const indices[] = {iBuilder->getInt32(0), iBuilder->getInt32(OUTPUT_STREAM_SET), getStreamOffset(instance, streamOffset)};
    429     Value * ptr = iBuilder->CreateGEP(instance, indices);
    430     unsigned size = 0;
    431     for (unsigned i = 0; i < mOutputStreamType->getStructNumElements(); ++i) {
    432         size += mOutputStreamType->getStructElementType(i)->getPrimitiveSizeInBits();
    433     }
    434     iBuilder->CreateMemSet(ptr, iBuilder->getInt8(0), size / 8, 4);
    435 }
    436 
    437 /** ------------------------------------------------------------------------------------------------------------- *
    438  * @brief offset
    439  *
    440  * Compute the stream index of the given offset value.
    441  ** ------------------------------------------------------------------------------------------------------------- */
    442 Value * KernelBuilder::getStreamOffset(Value * const instance, const unsigned index) {
    443     Value * offset = nullptr;
    444     if (mBufferSize > 1) {
    445         offset = iBuilder->CreateLoad(getBlockNo(instance));
    446         if (index) {
    447             offset = iBuilder->CreateAdd(offset, iBuilder->getInt64(index));
    448         }
    449         if (isPowerOfTwo(mBufferSize)) {
    450             offset = iBuilder->CreateAnd(offset, iBuilder->getInt64(mBufferSize - 1));
    451         } else {
    452             offset = iBuilder->CreateURem(offset, iBuilder->getInt64(mBufferSize));
    453         }
    454     } else {
    455         offset = iBuilder->getInt64(index);
    456     }
    457     return offset;
    458 }
    459 
    460 /** ------------------------------------------------------------------------------------------------------------- *
    461  * @brief CreateModFunction
    462  *
    463  * Generate a "modulo" function that dictates the local offset of a given blockNo
    464  ** ------------------------------------------------------------------------------------------------------------- */
    465 inline Function * KernelBuilder::CreateModFunction(const unsigned size) {
    466     const std::string name((size == 0) ? "continuous" : "finite" + std::to_string(size));
    467     Function * function = mMod->getFunction(name);
    468     if (function) {
    469         return function;
    470     }
    471     const auto ip = iBuilder->saveIP();
    472     FunctionType * type = FunctionType::get(iBuilder->getInt64Ty(), {iBuilder->getInt64Ty()}, false);
    473     function = Function::Create(type, Function::ExternalLinkage, name, mMod);
    474     Value * offset = function->arg_begin();
    475     offset->setName("index");
    476     BasicBlock * entry = BasicBlock::Create(mMod->getContext(), "entry", function);
    477     iBuilder->SetInsertPoint(entry);
    478     if (size) {
    479         if (size == 1) {
    480             offset = iBuilder->getInt64(0);
    481         } else if (isPowerOfTwo(size)) {
    482             offset = iBuilder->CreateAnd(offset, iBuilder->getInt64(size - 1));
    483         } else {
    484             offset = iBuilder->CreateURem(offset, iBuilder->getInt64(size));
    485         }
    486     }
    487     iBuilder->CreateRet(offset);
    488     iBuilder->restoreIP(ip);
    489     return function;
     307Instance * KernelBuilder::instantiate(std::initializer_list<llvm::Value *> inputStreams) {   
     308    throw std::runtime_error("Not supported!");
     309//    AllocaInst * inputStruct = iBuilder->CreateAlloca(mInputStreamType);
     310//    unsigned i = 0;
     311//    for (Value * inputStream : inputStreams) {
     312//        Value * ptr = iBuilder->CreateGEP(inputStruct, { iBuilder->getInt32(0), iBuilder->getInt32(i++)});
     313//        iBuilder->CreateStore(iBuilder->CreatePointerCast(inputStream, ptr);
     314//    }
     315//    return instantiate(std::make_pair(inputStruct, 0));
    490316}
    491317
Note: See TracChangeset for help on using the changeset viewer.