Changeset 6253


Ignore:
Timestamp:
Dec 23, 2018, 5:17:27 PM (3 months ago)
Author:
nmedfort
Message:

Moved consumed item counts for all buffers into pipeline state. Initial work on conditional kernel logic.

Location:
icGREP/icgrep-devel/icgrep
Files:
2 added
32 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/CMakeLists.txt

    r6224 r6253  
    7272
    7373SET(KERNEL_SRC kernels/attributes.cpp kernels/binding.cpp kernels/relationship.cpp kernels/processing_rate.cpp)
    74 SET(KERNEL_SRC ${KERNEL_SRC} kernels/kernel.cpp kernels/streamset.cpp kernels/multiblock_kernel.cpp kernels/block_kernel.cpp kernels/callback.cpp)
     74SET(KERNEL_SRC ${KERNEL_SRC} kernels/kernel.cpp kernels/streamset.cpp kernels/multiblock_kernel.cpp kernels/block_kernel.cpp)
    7575SET(KERNEL_SRC ${KERNEL_SRC} kernels/pipeline/pipeline_kernel.cpp kernels/pipeline/pipeline_builder.cpp)
    76 SET(KERNEL_SRC ${KERNEL_SRC} kernels/source_kernel.cpp kernels/s2p_kernel.cpp kernels/deletion.cpp kernels/swizzle.cpp kernels/p2s_kernel.cpp kernels/stdout_kernel.cpp kernels/hex_convert.cpp)
     76SET(KERNEL_SRC ${KERNEL_SRC} kernels/optimizationbranch.cpp)
     77SET(KERNEL_SRC ${KERNEL_SRC} kernels/callback.cpp)
     78
     79SET(KERNEL_SRC ${KERNEL_SRC} kernels/source_kernel.cpp kernels/stdout_kernel.cpp)
     80SET(KERNEL_SRC ${KERNEL_SRC} kernels/s2p_kernel.cpp kernels/p2s_kernel.cpp)
     81SET(KERNEL_SRC ${KERNEL_SRC} kernels/deletion.cpp kernels/swizzle.cpp kernels/hex_convert.cpp)
    7782SET(KERNEL_SRC ${KERNEL_SRC} kernels/kernel_builder.cpp)
    7883
  • icGREP/icgrep-devel/icgrep/grep/grep_engine.cpp

    r6250 r6253  
    206206// All engines share a common pipeline to compute a stream of Matches from a given input Bytestream.
    207207
    208 std::pair<StreamSet *, StreamSet *> GrepEngine::grepPipeline(const std::unique_ptr<PipelineBuilder> & P, StreamSet *SourceStream) {
     208std::pair<StreamSet *, StreamSet *> GrepEngine::grepPipeline(const std::unique_ptr<ProgramBuilder> & P, StreamSet *SourceStream) {
    209209
    210210    Scalar * const callbackObject = P->getInputScalar("callbackObject");
     
    309309        StreamSet * const RequiredStreams = P->CreateStreamSet();
    310310        StreamSet * UnicodeLB = nullptr;
    311        
    312         if (mGrepRecordBreak == GrepRecordBreakKind::Unicode) { 
     311
     312        if (mGrepRecordBreak == GrepRecordBreakKind::Unicode) {
    313313            UnicodeLB = P->CreateStreamSet();
    314314            StreamSet * const LineFeedStream = P->CreateStreamSet();
  • icGREP/icgrep-devel/icgrep/grep/grep_engine.h

    r6229 r6253  
    1919namespace re { class RE; }
    2020namespace llvm { namespace cl { class OptionCategory; } }
    21 namespace kernel { class PipelineBuilder; }
     21namespace kernel { class ProgramBuilder; }
    2222namespace kernel { class StreamSet; }
    2323class BaseDriver;
     
    100100    void setComponent(Component & compon_set, Component c);
    101101
    102     std::pair<kernel::StreamSet *, kernel::StreamSet *> grepPipeline(const std::unique_ptr<kernel::PipelineBuilder> & P,
     102    std::pair<kernel::StreamSet *, kernel::StreamSet *> grepPipeline(const std::unique_ptr<kernel::ProgramBuilder> &P,
    103103                                                                     kernel::StreamSet * ByteStream);
    104104
  • icGREP/icgrep-devel/icgrep/icgrep.files

    r6233 r6253  
    11CMakeLists.txt
    22grep/searchable_buffer.h
     3kernels/optimizationbranch.cpp
     4kernels/optimizationbranch.h
    35wc.cpp
    46base64.cpp
  • icGREP/icgrep-devel/icgrep/idisa_test.cpp

    r6184 r6253  
    353353typedef size_t (*IDISAtestFunctionType)(int32_t fd1, int32_t fd2);
    354354
    355 StreamSet * readHexToBinary(std::unique_ptr<PipelineBuilder> & P, const std::string & fd) {
     355StreamSet * readHexToBinary(std::unique_ptr<ProgramBuilder> & P, const std::string & fd) {
    356356    StreamSet * const hexStream = P->CreateStreamSet(1, 8);
    357357    Scalar * const fileDecriptor = P->getInputScalar(fd);
     
    362362}
    363363
    364 inline StreamSet * applyShiftLimit(std::unique_ptr<PipelineBuilder> & P, StreamSet * const input) {
     364inline StreamSet * applyShiftLimit(std::unique_ptr<ProgramBuilder> & P, StreamSet * const input) {
    365365    if (ShiftLimit > 0) {
    366366        StreamSet * output = P->CreateStreamSet(1, 1);
     
    418418    CPUDriver pxDriver("idisa_test");
    419419    auto idisaTestFunction = pipelineGen(pxDriver);
    420    
     420
    421421    const int32_t fd1 = openFile(Operand1TestFile, llvm::outs());
    422422    const int32_t fd2 = openFile(Operand2TestFile, llvm::outs());
  • icGREP/icgrep-devel/icgrep/kernels/block_kernel.cpp

    r6252 r6253  
    412412                                         Bindings && scalar_outputs,
    413413                                         Bindings && internal_scalars)
    414 : MultiBlockKernel(std::move(kernelName),
     414: MultiBlockKernel(TypeId::BlockOriented,
     415                   std::move(kernelName),
    415416                   std::move(stream_inputs),
    416417                   std::move(stream_outputs),
  • icGREP/icgrep-devel/icgrep/kernels/kernel.cpp

    r6249 r6253  
    111111    }
    112112
    113     IntegerType * const sizeTy = b->getSizeTy();
    114 
    115     // If an output is a managed buffer, we need to store both the buffer and a set of consumers.
     113    // If an output is a managed buffer, store its handle.
    116114    for (unsigned i = 0; i < numOfOutputStreams; ++i) {
    117115        const Binding & output = mOutputStreamSets[i];
     
    119117            Type * const handleTy = mStreamSetOutputBuffers[i]->getHandleType(b);
    120118            addInternalScalar(handleTy, output.getName() + BUFFER_HANDLE_SUFFIX);
    121             addInternalScalar(sizeTy, output.getName() + CONSUMED_ITEM_COUNT_SUFFIX);
    122119        }
    123120    }
     
    310307            params.push_back(sizeTy); // constant
    311308        }
    312         // writable output items (after non-deferred produced item count)
    313         if (LLVM_LIKELY(!isLocalBuffer(output))) {
    314             params.push_back(sizeTy);
    315         }
     309        // If this is a local buffer, the next param is its consumed item count;
     310        // otherwise it'll hold its writable output items.
     311        params.push_back(sizeTy);
    316312    }
    317313
     
    347343            (++args)->setName(output.getName() + "_produced");
    348344        }
    349         if (LLVM_LIKELY(!isLocalBuffer(output))) {
     345        if (LLVM_LIKELY(isLocalBuffer(output))) {
     346            (++args)->setName(output.getName() + "_consumed");
     347        } else {
    350348            (++args)->setName(output.getName() + "_writable");
    351349        }
     
    458456    reset(mProducedOutputItems, numOfOutputs);
    459457    reset(mWritableOutputItems, numOfOutputs);
     458    reset(mConsumedOutputItems, numOfOutputs);
    460459    std::vector<Value *> updatableProducedOutputItems;
    461460    reset(updatableProducedOutputItems, numOfOutputs);
     
    511510        mProducedOutputItems[i] = producedItems;
    512511        /// ----------------------------------------------------
    513         /// writable item count
     512        /// consumed or writable item count
    514513        /// ----------------------------------------------------
    515         if (LLVM_UNLIKELY(!isLocalBuffer(output))) {
    516             Value * const writable = &*(args++);
    517             mWritableOutputItems[i] = writable;
    518             Value * const capacity = b->CreateAdd(produced, writable);
     514        Value * const arg = &*(args++);
     515        if (LLVM_UNLIKELY(isLocalBuffer(output))) {
     516            mConsumedOutputItems[i] = arg;
     517        } else {
     518            mWritableOutputItems[i] = arg;
     519            Value * const capacity = b->CreateAdd(produced, arg);
    519520            buffer->setCapacity(b.get(), capacity);
    520521        }
     
    11631164
    11641165// CONSTRUCTOR
    1165 Kernel::Kernel(std::string && kernelName,
     1166Kernel::Kernel(const TypeId typeId,
     1167               std::string && kernelName,
    11661168               Bindings && stream_inputs,
    11671169               Bindings && stream_outputs,
     
    11831185, mIsFinal(nullptr)
    11841186, mNumOfStrides(nullptr)
    1185 , mKernelName(annotateKernelNameWithDebugFlags(std::move(kernelName))) {
     1187, mKernelName(annotateKernelNameWithDebugFlags(std::move(kernelName)))
     1188, mTypeId(typeId) {
    11861189
    11871190}
     
    11961199                                             Bindings && scalar_outputs,
    11971200                                             Bindings && internal_scalars)
    1198 : Kernel(std::move(kernelName),
     1201: Kernel(TypeId::SegmentOriented, std::move(kernelName),
    11991202         std::move(stream_inputs), std::move(stream_outputs),
    12001203         std::move(scalar_parameters), std::move(scalar_outputs),
  • icGREP/icgrep-devel/icgrep/kernels/kernel.h

    r6249 r6253  
    3434class BaseDriver;
    3535
    36 const static std::string CONSUMED_ITEM_COUNT_SUFFIX = "_consumedItemCount";
    3736const static std::string BUFFER_HANDLE_SUFFIX = "_buffer";
    3837const static std::string CYCLECOUNT_SCALAR = "CPUcycles";
     
    4948    friend class PipelineCompiler;
    5049    friend class PipelineKernel;
     50    friend class OptimizationBranch;
    5151    friend class BaseDriver;
     52public:
     53
     54    enum class TypeId {
     55        SegmentOriented
     56        , MultiBlock
     57        , BlockOriented
     58        , Pipeline
     59        , OptimizationBranch
     60    };
     61
     62    static bool classof(const Kernel *) { return true; }
     63
     64    static bool classof(const void *) { return false; }
     65
     66    LLVM_READNONE TypeId getTypeId() const {
     67        return mTypeId;
     68    }
     69
    5270public:
    5371
     
    450468    }
    451469
     470    LLVM_READNONE llvm::Value * getConsumedOutputItems(const llvm::StringRef name) const {
     471        Port port; unsigned index;
     472        std::tie(port, index) = getStreamPort(name);
     473        assert (port == Port::Output);
     474        return mConsumedOutputItems[index];
     475    }
     476
    452477    LLVM_READNONE llvm::Value * isFinal() const {
    453478        return mIsFinal;
     
    455480
    456481    // Constructor
    457     Kernel(std::string && kernelName,
     482    Kernel(const TypeId typeId, std::string && kernelName,
    458483           Bindings && stream_inputs, Bindings && stream_outputs,
    459484           Bindings && scalar_inputs, Bindings && scalar_outputs,
     
    510535    std::vector<llvm::Value *>      mProducedOutputItems;
    511536    std::vector<llvm::Value *>      mWritableOutputItems;
     537    std::vector<llvm::Value *>      mConsumedOutputItems;
    512538
    513539    ScalarFieldMap                  mScalarMap;
     
    515541
    516542    const std::string               mKernelName;
    517 
     543    const TypeId                    mTypeId;
    518544
    519545    OwnedStreamSetBuffers           mStreamSetInputBuffers;
     
    523549
    524550class SegmentOrientedKernel : public Kernel {
     551public:
     552
     553    static bool classof(const Kernel * const k) {
     554        return k->getTypeId() == TypeId::SegmentOriented;
     555    }
     556
     557    static bool classof(const void *) { return false; }
     558
    525559protected:
    526560
     
    543577class MultiBlockKernel : public Kernel {
    544578    friend class BlockOrientedKernel;
     579public:
     580
     581    static bool classof(const Kernel * const k) {
     582        return k->getTypeId() == TypeId::MultiBlock;
     583    }
     584
     585    static bool classof(const void *) { return false; }
     586
    545587protected:
    546588
     
    556598private:
    557599
     600    MultiBlockKernel(const TypeId kernelTypId,
     601                     std::string && kernelName,
     602                     Bindings && stream_inputs,
     603                     Bindings && stream_outputs,
     604                     Bindings && scalar_parameters,
     605                     Bindings && scalar_outputs,
     606                     Bindings && internal_scalars);
     607
     608private:
     609
    558610    void generateKernelMethod(const std::unique_ptr<KernelBuilder> & b) final;
    559611
     
    562614
    563615class BlockOrientedKernel : public MultiBlockKernel {
     616public:
     617
     618    static bool classof(const Kernel * const k) {
     619        return k->getTypeId() == TypeId::BlockOriented;
     620    }
     621
     622    static bool classof(const void *) { return false; }
     623
    564624protected:
    565625
  • icGREP/icgrep-devel/icgrep/kernels/kernel_builder.cpp

    r6249 r6253  
    8484
    8585/** ------------------------------------------------------------------------------------------------------------- *
    86  * @brief getNamedItemCount
    87  ** ------------------------------------------------------------------------------------------------------------- */
    88 Value * KernelBuilder::getNamedItemCount(const std::string & name, const std::string & suffix) {
    89     const ProcessingRate & rate = mKernel->getStreamBinding(name).getRate();
    90     Value * itemCount = nullptr;
    91     if (LLVM_UNLIKELY(rate.isRelative())) {
    92         Port port; unsigned index;
    93         std::tie(port, index) = mKernel->getStreamPort(rate.getReference());
    94         if (port == Port::Input) {
    95             itemCount = getProcessedItemCount(rate.getReference());
    96         } else {
    97             itemCount = getProducedItemCount(rate.getReference());
    98         }
    99         itemCount = CreateMul2(itemCount, rate.getRate());
    100     } else {
    101         itemCount = getScalarField(name + suffix);
    102     }
    103     return itemCount;
    104 }
    105 
    106 /** ------------------------------------------------------------------------------------------------------------- *
    107  * @brief setNamedItemCount
    108  ** ------------------------------------------------------------------------------------------------------------- */
    109 void KernelBuilder::setNamedItemCount(const std::string & name, const std::string & suffix, Value * const value) {
    110     const ProcessingRate & rate = mKernel->getStreamBinding(name).getRate();
    111     if (LLVM_UNLIKELY(rate.isDerived())) {
    112         report_fatal_error("cannot set item count: " + name + " is a derived rate stream");
    113     }
    114     if (codegen::DebugOptionIsSet(codegen::TraceCounts)) {
    115         CallPrintInt(mKernel->getName() + ": " + name + suffix, value);
    116     }
    117     if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
    118         Value * const current = getScalarField(name + suffix);
    119         CreateAssert(CreateICmpUGE(value, current), name + suffix + " must be monotonically non-decreasing");
    120     }
    121     setScalarField(name + suffix, value);
     86 * @brief getConsumedItemCount
     87 ** ------------------------------------------------------------------------------------------------------------- */
     88Value * KernelBuilder::getConsumedItemCount(const StringRef name) const {
     89    return mKernel->getConsumedOutputItems(name);
    12290}
    12391
  • icGREP/icgrep-devel/icgrep/kernels/kernel_builder.h

    r6249 r6253  
    4141    void setProducedItemCount(const llvm::StringRef name, llvm::Value * value);
    4242
    43     llvm::Value * getConsumedItemCount(const std::string & name) {
    44         return getNamedItemCount(name, CONSUMED_ITEM_COUNT_SUFFIX);
    45     }
    46 
    47     void setConsumedItemCount(const std::string & name, llvm::Value * value) {
    48         setNamedItemCount(name, CONSUMED_ITEM_COUNT_SUFFIX, value);
    49     }
     43    llvm::Value * getConsumedItemCount(const llvm::StringRef name) const;
    5044
    5145    llvm::Value * getTerminationSignal();
     
    168162    llvm::Value * getScalarFieldPtr(llvm::Value * instance, const std::string & fieldName);
    169163
    170     llvm::Value * getNamedItemCount(const std::string & name, const std::string & suffix);
    171 
    172     void setNamedItemCount(const std::string & name, const std::string & suffix, llvm::Value * const value);
    173 
    174164    std::string getKernelName() const final;
    175165
  • icGREP/icgrep-devel/icgrep/kernels/multiblock_kernel.cpp

    r6228 r6253  
    4141
    4242// MULTI-BLOCK KERNEL CONSTRUCTOR
    43 MultiBlockKernel::MultiBlockKernel(std::string && kernelName,
    44                                    Bindings && stream_inputs,
    45                                    Bindings && stream_outputs,
    46                                    Bindings && scalar_parameters,
    47                                    Bindings && scalar_outputs,
    48                                    Bindings && internal_scalars)
    49 : Kernel(std::move(kernelName),
    50          std::move(stream_inputs),
    51          std::move(stream_outputs),
    52          std::move(scalar_parameters),
    53          std::move(scalar_outputs),
    54          std::move(internal_scalars)) {
     43MultiBlockKernel::MultiBlockKernel(
     44    std::string && kernelName,
     45    Bindings && stream_inputs,
     46    Bindings && stream_outputs,
     47    Bindings && scalar_parameters,
     48    Bindings && scalar_outputs,
     49    Bindings && internal_scalars)
     50: MultiBlockKernel(TypeId::MultiBlock,
     51    std::move(kernelName),
     52    std::move(stream_inputs),
     53    std::move(stream_outputs),
     54    std::move(scalar_parameters),
     55    std::move(scalar_outputs),
     56    std::move(internal_scalars)) {
     57
     58}
     59
     60MultiBlockKernel::MultiBlockKernel(
     61    const TypeId typeId,
     62    std::string && kernelName,
     63    Bindings && stream_inputs,
     64    Bindings && stream_outputs,
     65    Bindings && scalar_parameters,
     66    Bindings && scalar_outputs,
     67    Bindings && internal_scalars)
     68: Kernel(typeId,
     69     std::move(kernelName),
     70     std::move(stream_inputs),
     71     std::move(stream_outputs),
     72     std::move(scalar_parameters),
     73     std::move(scalar_outputs),
     74     std::move(internal_scalars)) {
    5575
    5676}
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/buffer_management_logic.hpp

    r6252 r6253  
    356356 ** ------------------------------------------------------------------------------------------------------------- */
    357357inline void PipelineCompiler::addBufferHandlesToPipelineKernel(BuilderRef b, const unsigned index) {
    358     IntegerType * const sizeTy = b->getSizeTy();
    359358    const Kernel * const kernel = mPipeline[index];
    360359    if (!kernel->hasFamilyName()) {
     
    365364        const auto bufferVertex = target(e, mBufferGraph);
    366365        const BufferNode & bn = mBufferGraph[bufferVertex];
    367         if (LLVM_UNLIKELY(bn.Type == BufferType::Managed)) {
    368             continue;
    369         }
    370         const Binding & output = kernel->getOutputStreamSetBinding(mBufferGraph[e].Port);
    371         const auto bufferName = makeBufferName(index, output);
    372         mPipelineKernel->addInternalScalar(bn.Buffer->getHandleType(b), bufferName);
    373         mPipelineKernel->addInternalScalar(sizeTy, bufferName + CONSUMED_ITEM_COUNT_SUFFIX);
    374     }
    375 }
    376 
     366        if (LLVM_LIKELY(bn.Type != BufferType::Managed)) {
     367            const auto outputPort = mBufferGraph[e].Port;
     368            const Binding & output = kernel->getOutputStreamSetBinding(outputPort);
     369            const auto prefix = makeBufferName(index, output);
     370            mPipelineKernel->addInternalScalar(bn.Buffer->getHandleType(b), prefix);
     371        }
     372    }
     373}
    377374
    378375/** ------------------------------------------------------------------------------------------------------------- *
     
    452449        const auto prefix = makeBufferName(mKernelIndex, input);
    453450        mInitiallyProcessedItemCount[i] = b->getScalarField(prefix + ITEM_COUNT_SUFFIX);
    454         #ifdef PRINT_DEBUG_MESSAGES
    455         b->CallPrintInt(prefix + "_initialProcessed", mInitiallyProcessedItemCount[i]);
    456         #endif
    457451        if (input.isDeferred()) {
    458452            mInitiallyProcessedDeferredItemCount[i] = b->getScalarField(prefix + DEFERRED_ITEM_COUNT_SUFFIX);
    459             #ifdef PRINT_DEBUG_MESSAGES
    460             b->CallPrintInt(prefix + "_initialProducedDeferred", mInitiallyProcessedDeferredItemCount[i]);
    461             #endif
    462453        }
    463454    }
     
    467458        const auto prefix = makeBufferName(mKernelIndex, output);
    468459        mInitiallyProducedItemCount[i] = b->getScalarField(prefix + ITEM_COUNT_SUFFIX);
    469         #ifdef PRINT_DEBUG_MESSAGES
    470         b->CallPrintInt(prefix + "_initialProduced", mInitiallyProducedItemCount[i]);
    471         #endif
    472460    }
    473461    b->setKernel(mKernel);
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/consumer_logic.hpp

    r6249 r6253  
    1414        return;
    1515    }
    16     if (LLVM_UNLIKELY(out_degree(bufferVertex, mConsumerGraph) == 0)) {
    17         setConsumedItemCount(b, bufferVertex, produced);
    18     } else { // otherwise set the initial consumed amount to the produced amount
     16    if (LLVM_UNLIKELY(out_degree(bufferVertex, mConsumerGraph) != 0)) {
    1917        ConsumerNode & cn = mConsumerGraph[bufferVertex];
    2018        assert (cn.Consumed == nullptr);
     
    7068
    7169/** ------------------------------------------------------------------------------------------------------------- *
     70 * @brief addConsumerKernelProperties
     71 ** ------------------------------------------------------------------------------------------------------------- */
     72inline void PipelineCompiler::addConsumerKernelProperties(BuilderRef b, const unsigned kernelIndex) {
     73    IntegerType * const sizeTy = b->getSizeTy();
     74    const Kernel * const kernel = mPipeline[kernelIndex];
     75    const auto numOfOutputs = kernel->getNumOfStreamOutputs();
     76    for (unsigned i = 0; i < numOfOutputs; i++) {
     77        const Binding & output = kernel->getOutputStreamSetBinding(i);
     78        const auto prefix = makeBufferName(kernelIndex, output);
     79        const auto bufferVertex = getOutputBufferVertex(kernelIndex, i);
     80        // If the out-degree for this buffer is zero, then either the stream has no consumers
     81        // or we've proven that its consumption rate is identical to its production rate.
     82        if (out_degree(bufferVertex, mConsumerGraph) != 0) {
     83            mPipelineKernel->addInternalScalar(sizeTy, prefix + CONSUMED_ITEM_COUNT_SUFFIX);
     84        }
     85    }
     86
     87}
     88
     89/** ------------------------------------------------------------------------------------------------------------- *
    7290 * @brief getConsumedItemCount
    7391 ** ------------------------------------------------------------------------------------------------------------- */
    74 Value * PipelineCompiler::getConsumedItemCount(BuilderRef b, const unsigned outputPort) const {
    75     // TODO: if we can prove that this stream is always fully consumed, its consumed count
    76     // is its produced count.
    77     assert (mPipeline[mKernelIndex] == mKernel);
    78     assert (b->getKernel() == mKernel);
    79     const Binding & output = mKernel->getOutputStreamSetBinding(outputPort);
     92Value * PipelineCompiler::getConsumedItemCount(BuilderRef b, const unsigned outputPort) {
    8093    Value * consumed = nullptr;
    81     const BufferNode & bn = mBufferGraph[getOutputBufferVertex(mKernelIndex, outputPort)];
    82     if (LLVM_LIKELY(bn.Type == BufferType::Internal)) {
    83         b->setKernel(mPipelineKernel);
    84         consumed = b->getScalarField(makeBufferName(mKernelIndex, output) + CONSUMED_ITEM_COUNT_SUFFIX);
    85         b->setKernel(mKernel);
    86     } else if (bn.Type == BufferType::Managed) {
    87         b->setKernel(mKernel);
    88         consumed = b->getScalarField(output.getName() + CONSUMED_ITEM_COUNT_SUFFIX);
    89     } else if (bn.Type == BufferType::External) {
    90         consumed = b->getSize(0);
     94    const auto bufferVertex = getOutputBufferVertex(mKernelIndex, outputPort);
     95    if (LLVM_UNLIKELY(out_degree(bufferVertex, mConsumerGraph) == 0)) {
     96        // This stream either has no consumers or we've proven that its consumption rate
     97        // is identical to its production rate.
     98        consumed = mInitiallyProducedItemCount[outputPort];
     99    } else {
     100        const BufferNode & bn = mBufferGraph[bufferVertex];
     101        if (LLVM_UNLIKELY(bn.Type == BufferType::External)) {
     102            consumed = b->getSize(0);
     103        } else {
     104            b->setKernel(mPipelineKernel);
     105            const Binding & output = mKernel->getOutputStreamSetBinding(outputPort);
     106            const auto prefix = makeBufferName(mKernelIndex, output);
     107            consumed = b->getScalarField(prefix + CONSUMED_ITEM_COUNT_SUFFIX);
     108            b->setKernel(mKernel);
     109        }
    91110    }
    92     assert (consumed);
    93111    return consumed;
     112}
     113
     114/** ------------------------------------------------------------------------------------------------------------- *
     115 * @brief readConsumedItemCounts
     116 ** ------------------------------------------------------------------------------------------------------------- */
     117void PipelineCompiler::readConsumedItemCounts(BuilderRef b) {
     118    const auto numOfOutputs = mKernel->getNumOfStreamOutputs();
     119    for (unsigned i = 0; i < numOfOutputs; i++) {
     120        mConsumedItemCount[i] = getConsumedItemCount(b, i);
     121    }
    94122}
    95123
     
    98126 ** ------------------------------------------------------------------------------------------------------------- */
    99127void PipelineCompiler::setConsumedItemCount(BuilderRef b, const unsigned bufferVertex, Value * const consumed) const {
     128    const BufferNode & bn = mBufferGraph[bufferVertex];
     129    if (LLVM_LIKELY(bn.Type == BufferType::External)) {
     130        return;
     131    }
    100132    const auto pe = in_edge(bufferVertex, mConsumerGraph);
    101133    const auto producerVertex = source(pe, mConsumerGraph);
    102     const Kernel * const producer = mBufferGraph[producerVertex].Kernel;
    103     assert (producer->getHandle());
    104     const Binding & output = producer->getOutputStreamSetBinding(mConsumerGraph[pe]);
     134    const Kernel * const producer = mPipeline[producerVertex]; assert (producer->getHandle());
     135    const auto outputPort = mConsumerGraph[pe];
     136    const Binding & output = producer->getOutputStreamSetBinding(outputPort);
     137    const auto prefix = makeBufferName(producerVertex, output);
    105138    #ifdef PRINT_DEBUG_MESSAGES
    106     const auto prefix = makeBufferName(producerVertex, output);
    107139    b->CallPrintInt(prefix + CONSUMED_ITEM_COUNT_SUFFIX, consumed);
    108140    #endif
    109     if (LLVM_UNLIKELY(storedInNestedKernel(output))) {
    110         b->setKernel(producer);
    111         if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableMProtect))) {
    112             b->CreateMProtect(producer->getHandle(), CBuilder::Protect::WRITE);
    113         }
    114         b->setScalarField(output.getName() + CONSUMED_ITEM_COUNT_SUFFIX, consumed);
    115         if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableMProtect))) {
    116             b->CreateMProtect(producer->getHandle(), CBuilder::Protect::READ);
    117         }
    118     } else {
    119         b->setKernel(mPipelineKernel);
    120         b->setScalarField(makeBufferName(producerVertex, output) + CONSUMED_ITEM_COUNT_SUFFIX, consumed);
    121     }
     141    b->setKernel(mPipelineKernel);
     142    b->setScalarField(prefix + CONSUMED_ITEM_COUNT_SUFFIX, consumed);
    122143    b->setKernel(mKernel);
    123144}
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/core_logic.hpp

    r6252 r6253  
    11#include "pipeline_compiler.hpp"
    2 
    3 const static std::string TERMINATION_SIGNAL_SUFFIX = "terminationSignal";
    42
    53namespace kernel {
     
    1513        addBufferHandlesToPipelineKernel(b, i);
    1614        addInternalKernelProperties(b, i);
     15        addConsumerKernelProperties(b, i);
    1716        addPopCountScalarsToPipelineKernel(b, i);
    1817    }
     
    3231    mPipelineKernel->addInternalScalar(sizeTy, name + LOGICAL_SEGMENT_SUFFIX);
    3332
    34     // TODO: non deferred item count for fixed rates could be calculated from seg no.
    35     // Should I seperate non-deferred from normal item counts to improve cache locality?
     33    // TODO: non deferred item count for fixed rates could be calculated from total # of segments.
    3634    const Kernel * const kernel = mPipeline[kernelIndex];
    3735    const auto numOfInputs = kernel->getNumOfStreamInputs();
     
    4947        const Binding & output = kernel->getOutputStreamSetBinding(i);
    5048        const auto prefix = makeBufferName(kernelIndex, output);
    51         if (output.isDeferred()) {
    52             mPipelineKernel->addInternalScalar(sizeTy, prefix + DEFERRED_ITEM_COUNT_SUFFIX);
    53         }
    5449        mPipelineKernel->addInternalScalar(sizeTy, prefix + ITEM_COUNT_SUFFIX);
    5550    }
     
    166161
    167162    b->SetInsertPoint(mKernelLoopEntry);
     163    readConsumedItemCounts(b);
    168164    checkForSufficientInputDataAndOutputSpace(b);
    169165    determineNumOfLinearStrides(b);
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/kernel_logic.hpp

    r6252 r6253  
    164164    const StreamSetBuffer * const buffer = getOutputBuffer(outputPort);
    165165    Value * const produced = mAlreadyProducedPhi[outputPort]; assert (produced);
    166     Value * const consumed = getConsumedItemCount(b, outputPort); assert (consumed);
     166    Value * const consumed = mConsumedItemCount[outputPort]; assert (consumed);
    167167    #ifdef PRINT_DEBUG_MESSAGES
    168168    const auto prefix = makeBufferName(mKernelIndex, output);
     
    378378inline Value * PipelineCompiler::calculateBufferExpansionSize(BuilderRef b, const unsigned outputPort) {
    379379    Value * const produced = mAlreadyProducedPhi[outputPort];
    380     Value * const consumed = getConsumedItemCount(b, outputPort);
     380    Value * const consumed = mConsumedItemCount[outputPort];
    381381    Value * const unconsumed = b->CreateSub(produced, consumed);
    382382    Value * const strideLength = getOutputStrideLength(b, outputPort);
     
    499499        if (LLVM_LIKELY(nonManaged)) {
    500500            args.push_back(mLinearOutputItemsPhi[i]);
     501        } else {
     502            args.push_back(mConsumedItemCount[i]);
    501503        }
    502504    }
     
    930932    reset(mOutputStrideLength, numOfOutputs);
    931933    reset(mWritableOutputItems, numOfOutputs);
     934    reset(mConsumedItemCount, numOfOutputs);
    932935    reset(mLinearOutputItemsPhi, numOfOutputs);
    933936    reset(mReturnedProducedItemCountPtr, numOfOutputs);
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/pipeline_analysis.hpp

    r6252 r6253  
    219219namespace {
    220220
     221#if 0
     222
    221223/** ------------------------------------------------------------------------------------------------------------- *
    222224 * @brief minimumConsumed
     
    239241    return ub;
    240242}
     243
     244#endif
    241245
    242246}
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/pipeline_builder.cpp

    r6237 r6253  
    11#include <kernels/pipeline_builder.h>
     2#include <kernels/optimizationbranch.h>
    23#include <kernels/kernel_builder.h>
    34#include <boost/container/flat_map.hpp>
     
    89#include <llvm/IR/Module.h>
    910#include <llvm/IR/Constants.h>
     11#include <toolchain/toolchain.h>
    1012#include <queue>
    11 
    1213
    1314#warning if two kernels have an identical signature and take the same inputs, they ought to produce the same outputs unless they are nondeterministic.
     
    2122
    2223namespace kernel {
     24
     25#warning TODO: make a templated compile method to automatically validate and cast the main function to the correct type?
     26
     27/** ------------------------------------------------------------------------------------------------------------- *
     28 * @brief compile()
     29 ** ------------------------------------------------------------------------------------------------------------- */
     30void * ProgramBuilder::compile() {
     31    PipelineKernel * const pk =
     32        cast<PipelineKernel>(makeKernel());
     33    pk->initializeBindings(mDriver);
     34    mDriver.addKernel(pk);
     35    mDriver.generateUncachedKernels();
     36    Function * const main =
     37        addOrDeclareMainFunction(pk);
     38    return mDriver.finalizeObject(main);
     39}
    2340
    2441/** ------------------------------------------------------------------------------------------------------------- *
     
    3047    mKernels.emplace_back(kernel);
    3148    return kernel;
    32 }
    33 
    34 #warning TODO: make a templated method to automatically validate and cast the main function to the correct type?
    35 
    36 /** ------------------------------------------------------------------------------------------------------------- *
    37  * @brief finalizeObject
    38  ** ------------------------------------------------------------------------------------------------------------- */
    39 void * PipelineBuilder::compile() {
    40     PipelineKernel * const pk = makePipelineKernel();
    41     pk->initializeBindings(mDriver);
    42     mDriver.addKernel(pk);
    43     mDriver.generateUncachedKernels();
    44     Function * const main = addOrDeclareMainFunction(pk);
    45     return mDriver.finalizeObject(main);
    4649}
    4750
     
    182185}
    183186
    184 /** ------------------------------------------------------------------------------------------------------------- *
    185  * @brief finalizeObject
    186  ** ------------------------------------------------------------------------------------------------------------- */
    187 PipelineKernel * PipelineBuilder::makePipelineKernel() {
     187#warning pipeline builder needs to be able to return the name of a kernel without generating it
     188
     189/** ------------------------------------------------------------------------------------------------------------- *
     190 * @brief makeKernel
     191 ** ------------------------------------------------------------------------------------------------------------- */
     192Kernel * PipelineBuilder::makeKernel() {
     193
     194    for (const auto & builder : mNestedBuilders) {
     195        mKernels.push_back(builder->makeKernel());
     196    }
    188197
    189198    const auto numOfKernels = mKernels.size();
     
    299308}
    300309
     310/** ------------------------------------------------------------------------------------------------------------- *
     311 * @brief makeKernel
     312 ** ------------------------------------------------------------------------------------------------------------- */
     313Kernel * OptimizationBranchBuilder::makeKernel() {
     314
     315    Kernel * const trueBranch = mTrueBranch->makeKernel();
     316
     317    Kernel * const falseBranch = mFalseBranch->makeKernel();
     318
     319    std::string name;
     320    raw_string_ostream out(name);
     321
     322    out << "OptimizationBranch:";
     323
     324    mCondition->getType()->print(out);
     325
     326    out << ";True=\"";
     327
     328    if (trueBranch->hasFamilyName()) {
     329        out << trueBranch->getFamilyName();
     330    } else {
     331        out << trueBranch->getName();
     332    }
     333
     334    out << "\";False=\"";
     335
     336    if (falseBranch->hasFamilyName()) {
     337        out << falseBranch->getFamilyName();
     338    } else {
     339        out << falseBranch->getName();
     340    }
     341
     342    out << "\"";
     343    out.flush();
     344
     345    OptimizationBranch * const br =
     346            new OptimizationBranch(std::move(name),
     347                                   mCondition, trueBranch, falseBranch,
     348                                   std::move(mInputStreamSets), std::move(mOutputStreamSets),
     349                                   std::move(mInputScalars), std::move(mOutputScalars));
     350
     351
     352    return br;
     353}
     354
     355/** ------------------------------------------------------------------------------------------------------------- *
     356 * @brief makeMainFunction
     357 ** ------------------------------------------------------------------------------------------------------------- */
    301358inline void PipelineBuilder::addInputScalar(llvm::Type * type, std::string name) {
    302359    mInputScalars.emplace_back(name, CreateConstant(Constant::getNullValue(type)), FixedRate(1), Family());
     
    359416
    360417PipelineBuilder::PipelineBuilder(BaseDriver & driver,
    361                                  Bindings && stream_inputs, Bindings && stream_outputs,
    362                                  Bindings && scalar_inputs, Bindings && scalar_outputs,
    363                                  const unsigned numOfThreads)
     418    Bindings && stream_inputs, Bindings && stream_outputs,
     419    Bindings && scalar_inputs, Bindings && scalar_outputs, const unsigned numOfThreads)
    364420: mDriver(driver)
    365421, mNumOfThreads(numOfThreads)
     
    396452}
    397453
    398 
    399 }
     454ProgramBuilder::ProgramBuilder(
     455    BaseDriver & driver,
     456    Bindings && stream_inputs, Bindings && stream_outputs,
     457    Bindings && scalar_inputs, Bindings && scalar_outputs)
     458: PipelineBuilder(
     459      driver,
     460      std::move(stream_inputs), std::move(stream_outputs),
     461      std::move(scalar_inputs), std::move(scalar_outputs),
     462      codegen::ThreadNum) {
     463
     464}
     465
     466OptimizationBranchBuilder::OptimizationBranchBuilder(
     467      BaseDriver & driver,
     468      StreamSet * const condition,
     469      Bindings && stream_inputs, Bindings && stream_outputs,
     470      Bindings && scalar_inputs, Bindings && scalar_outputs)
     471: PipelineBuilder(
     472      driver,
     473      std::move(stream_inputs), std::move(stream_outputs),
     474      std::move(scalar_inputs), std::move(scalar_outputs))
     475, mCondition(condition)
     476, mTrueBranch()
     477, mFalseBranch() {
     478
     479}
     480
     481OptimizationBranchBuilder::~OptimizationBranchBuilder() {
     482
     483}
     484
     485}
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/pipeline_compiler.hpp

    r6252 r6253  
    162162
    163163const static std::string LOGICAL_SEGMENT_SUFFIX = ".LSN";
     164const static std::string TERMINATION_SIGNAL_SUFFIX = ".TERM";
    164165const static std::string ITEM_COUNT_SUFFIX = ".IC";
    165166const static std::string DEFERRED_ITEM_COUNT_SUFFIX = ".ICD";
     167const static std::string CONSUMED_ITEM_COUNT_SUFFIX = ".CON";
    166168
    167169class PipelineCompiler {
     
    327329
    328330    ConsumerGraph makeConsumerGraph() const;
     331    void addConsumerKernelProperties(BuilderRef b, const unsigned kernelIndex);
    329332    void createConsumedPhiNodes(BuilderRef b);
    330333    void initializeConsumedItemCount(BuilderRef b, const unsigned bufferVertex, Value * const produced);
     334    void readConsumedItemCounts(BuilderRef b);
     335    Value * getConsumedItemCount(BuilderRef b, const unsigned outputPort);
    331336    void setConsumedItemCount(BuilderRef b, const unsigned bufferVertex, Value * const consumed) const;
    332     Value * getConsumedItemCount(BuilderRef b, const unsigned outputPort) const;
    333337
    334338// buffer analysis/management functions
     
    456460    std::vector<Value *>                        mOutputStrideLength;
    457461    std::vector<Value *>                        mWritableOutputItems;
     462    std::vector<Value *>                        mConsumedItemCount;
    458463    std::vector<PHINode *>                      mLinearOutputItemsPhi;
    459464    std::vector<Value *>                        mReturnedProducedItemCountPtr; // written by the kernel
     
    554559
    555560/** ------------------------------------------------------------------------------------------------------------- *
    556  * @brief storedInKernel
    557  ** ------------------------------------------------------------------------------------------------------------- */
    558 inline LLVM_READNONE bool storedInNestedKernel(const Binding & output) {
    559     return output.getRate().isUnknown() || output.hasAttribute(AttrId::ManagedBuffer);
    560 }
    561 
    562 /** ------------------------------------------------------------------------------------------------------------- *
    563561 * @brief upperBound
    564562 ** ------------------------------------------------------------------------------------------------------------- */
    565563inline LLVM_READNONE RateValue upperBound(not_null<const Kernel *> kernel, const Binding & binding) {
    566564    assert (kernel->getStride() > 0);
    567 //    const auto ub = kernel->getUpperBound(binding);
    568 //    const auto stride = kernel->getStride();
    569 //    return (ub == 0) ? stride : ub * stride;
    570565    return kernel->getUpperBound(binding) * kernel->getStride();
    571566}
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/pipeline_kernel.cpp

    r6249 r6253  
    326326                               Bindings && stream_inputs, Bindings && stream_outputs,
    327327                               Bindings &&scalar_inputs, Bindings && scalar_outputs)
    328 : Kernel("p" + std::to_string(numOfThreads) + "_" + getStringHash(signature),
     328: Kernel(TypeId::Pipeline,
     329         "p" + std::to_string(numOfThreads) + "_" + getStringHash(signature),
    329330         std::move(stream_inputs), std::move(stream_outputs),
    330331         std::move(scalar_inputs), std::move(scalar_outputs), {})
  • icGREP/icgrep-devel/icgrep/kernels/pipeline/popcount_logic.hpp

    r6252 r6253  
    416416inline Value * PipelineCompiler::getPopCountReferenceConsumedCount(BuilderRef b, const unsigned bufferVertex) {
    417417    const auto e = in_edge(bufferVertex, mBufferGraph);
    418     const auto port = mBufferGraph[e].Port;
     418    const auto outputPort = mBufferGraph[e].Port;
    419419    PopCountData & pc = getPopCountReference(bufferVertex);
    420420    if (pc.UsesConsumedCount) {
    421         return getConsumedItemCount(b, port);
     421        return mConsumedItemCount[outputPort];
    422422    } else {
    423423        b->setKernel(mPipelineKernel);
    424         const Binding & output = mKernel->getOutputStreamSetBinding(port);
     424        const Binding & output = mKernel->getOutputStreamSetBinding(outputPort);
    425425        const auto bufferName = makeBufferName(mKernelIndex, output);
    426426        const auto fieldName = bufferName + REFERENCE_PROCESSED_COUNT;
  • icGREP/icgrep-devel/icgrep/kernels/pipeline_builder.h

    r6237 r6253  
    88namespace kernel {
    99
     10class OptimizationBranchBuilder;
     11
    1012class PipelineBuilder {
     13    friend class PipelineKernel;
     14    friend class OptimizationBranchBuilder;
    1115public:
    1216
     
    1418    using CallBinding = PipelineKernel::CallBinding;
    1519    using CallBindings = PipelineKernel::CallBindings;
     20    using NestedBuilders = std::vector<std::shared_ptr<PipelineBuilder>>;
    1621
    1722    template<typename KernelType, typename... Args>
     
    1924        return initializeKernel(new KernelType(mDriver.getBuilder(), std::forward<Args>(args) ...));
    2025    }
     26
     27    std::shared_ptr<OptimizationBranchBuilder>
     28        CreateOptimizationBranch(StreamSet * const condition,
     29                                 Bindings && stream_inputs = {}, Bindings && stream_outputs = {},
     30                                 Bindings && scalar_inputs = {}, Bindings && scalar_outputs = {});
    2131
    2232    StreamSet * CreateStreamSet(const unsigned NumElements = 1, const unsigned FieldWidth = 1) {
     
    3545        // Since the pipeline kernel module has not been made yet, just record the function info and its arguments.
    3646        mCallBindings.emplace_back(name, type, reinterpret_cast<void *>(&functionPtr), std::move(args));
    37     }
    38 
    39     void * compile();
    40 
    41     void setNumOfThreads(const unsigned threads) {
    42         mNumOfThreads = threads;
    4347    }
    4448
     
    6670protected:
    6771
    68     PipelineKernel * makePipelineKernel();
     72    virtual Kernel * makeKernel();
    6973
    7074    Kernel * initializeKernel(Kernel * const kernel);
     
    7478    llvm::Function * addOrDeclareMainFunction(PipelineKernel * const pk);
    7579
     80protected:
     81
     82    BaseDriver &        mDriver;
     83    // eventual pipeline configuration
     84    unsigned            mNumOfThreads;
     85    Bindings            mInputStreamSets;
     86    Bindings            mOutputStreamSets;
     87    Bindings            mInputScalars;
     88    Bindings            mOutputScalars;
     89    Bindings            mInternalScalars;
     90    Kernels             mKernels;
     91    CallBindings        mCallBindings;
     92    NestedBuilders      mNestedBuilders;
     93};
     94
     95/** ------------------------------------------------------------------------------------------------------------- *
     96 * @brief ProgramBuilder
     97 ** ------------------------------------------------------------------------------------------------------------- */
     98class ProgramBuilder : public PipelineBuilder {
     99    friend class PipelineBuilder;
     100public:
     101
     102    void * compile();
     103
     104    void setNumOfThreads(const unsigned threads) {
     105        mNumOfThreads = threads;
     106    }
     107
     108    ProgramBuilder(BaseDriver & driver,
     109                   Bindings && stream_inputs, Bindings && stream_outputs,
     110                   Bindings && scalar_inputs, Bindings && scalar_outputs);
     111
    76112private:
    77113
    78     BaseDriver &       mDriver;
     114};
    79115
    80     // eventual pipeline configuration
    81     unsigned                        mNumOfThreads;
    82     Bindings                        mInputStreamSets;
    83     Bindings                        mOutputStreamSets;
    84     Bindings                        mInputScalars;
    85     Bindings                        mOutputScalars;
    86     Bindings                        mInternalScalars;
    87     Kernels                         mKernels;
    88     CallBindings                    mCallBindings;
     116/** ------------------------------------------------------------------------------------------------------------- *
     117 * @brief PipelineBranchBuilder
     118 ** ------------------------------------------------------------------------------------------------------------- */
     119class OptimizationBranchBuilder final : public PipelineBuilder {
     120    friend class PipelineKernel;
     121    friend class PipelineBuilder;
     122public:
    89123
     124    const std::unique_ptr<PipelineBuilder> & getTrueBranch() const {
     125        return mTrueBranch;
     126    }
     127
     128    const std::unique_ptr<PipelineBuilder> & getFalseBranch() const {
     129        return mFalseBranch;
     130    }
     131
     132    ~OptimizationBranchBuilder();
     133
     134protected:
     135
     136    OptimizationBranchBuilder(BaseDriver & driver, StreamSet * const condition,
     137                              Bindings && stream_inputs, Bindings && stream_outputs,
     138                              Bindings && scalar_inputs, Bindings && scalar_outputs);
     139
     140    Kernel * makeKernel() override;
     141
     142private:
     143    StreamSet * const                mCondition;
     144    std::unique_ptr<PipelineBuilder> mTrueBranch;
     145    std::unique_ptr<PipelineBuilder> mFalseBranch;
    90146};
     147
     148inline std::shared_ptr<OptimizationBranchBuilder> PipelineBuilder::CreateOptimizationBranch (
     149        StreamSet * const condition,
     150        Bindings && stream_inputs, Bindings && stream_outputs,
     151        Bindings && scalar_inputs, Bindings && scalar_outputs) {
     152    std::shared_ptr<OptimizationBranchBuilder> branch(
     153        new OptimizationBranchBuilder(mDriver, condition,
     154            std::move(stream_inputs), std::move(stream_outputs),
     155            std::move(scalar_inputs), std::move(scalar_outputs)));
     156    mNestedBuilders.emplace_back(std::static_pointer_cast<PipelineBuilder>(branch));
     157    return branch;
     158}
    91159
    92160}
  • icGREP/icgrep-devel/icgrep/kernels/pipeline_kernel.h

    r6184 r6253  
    1919
    2020class PipelineKernel : public Kernel {
    21 public:
    2221    friend class PipelineCompiler;
    2322    friend class PipelineBuilder;
     23public:
     24
     25    static bool classof(const Kernel * const k) {
     26        return k->getTypeId() == TypeId::Pipeline;
     27    }
     28
     29    static bool classof(const void *) { return false; }
     30
     31public:
    2432
    2533    using Scalars = std::vector<Scalar *>;
  • icGREP/icgrep-devel/icgrep/kernels/processing_rate.cpp

    r6184 r6253  
    77
    88using RateValue = ProcessingRate::RateValue;
     9using RateId = ProcessingRate::KindId;
    910
    1011/** ------------------------------------------------------------------------------------------------------------- *
     
    111112}
    112113
    113 }
     114/** ------------------------------------------------------------------------------------------------------------- *
     115 * @brief equals
     116 ** ------------------------------------------------------------------------------------------------------------- */
     117inline bool equals(const ProcessingRate & A, const RateValue & AF, const ProcessingRate & B, const RateValue & BF) {
     118    return (A.getLowerBound() == B.getLowerBound()) && (A.getUpperBound() == B.getUpperBound()) && AF == BF;
     119}
     120
     121/** ------------------------------------------------------------------------------------------------------------- *
     122 * @brief atLeast
     123 ** ------------------------------------------------------------------------------------------------------------- */
     124inline bool atLeast(const ProcessingRate & A, const RateValue & AF, const ProcessingRate & B, const RateValue & BF) {
     125    return A.getLowerBound() * AF <= B.getLowerBound() * BF;
     126}
     127
     128/** ------------------------------------------------------------------------------------------------------------- *
     129 * @brief atMost
     130 ** ------------------------------------------------------------------------------------------------------------- */
     131inline bool atMost(const ProcessingRate & A, const RateValue & AF, const ProcessingRate & B, const RateValue & BF) {
     132    return B.getUpperBound() * BF <= A.getUpperBound() * AF;
     133}
     134
     135/** ------------------------------------------------------------------------------------------------------------- *
     136 * @brief within
     137 ** ------------------------------------------------------------------------------------------------------------- */
     138inline bool within(const ProcessingRate & A, const RateValue & AF, const ProcessingRate & B, const RateValue & BF) {
     139    return atLeast(A, AF, B, BF) && atMost(A, AF, B, BF);
     140}
     141
     142/** ------------------------------------------------------------------------------------------------------------- *
     143 * @brief permits
     144 ** ------------------------------------------------------------------------------------------------------------- */
     145bool permits(const Kernel * const hostKernel,
     146             const Binding & hostBinding,
     147             const RateValue & hostFactor,
     148             const Kernel * const visitorKernel,
     149             const Binding & visitorBinding,
     150             const RateValue & visitorFactor) {
     151
     152    const ProcessingRate & hostRate = hostBinding.getRate();
     153    const RateId hostRateId = hostRate.getKind();
     154    const ProcessingRate & visitorRate = visitorBinding.getRate();
     155    const RateId visitorRateId = visitorRate.getKind();
     156
     157    if (LLVM_LIKELY(hostRateId == visitorRateId)) {
     158        switch (hostRateId) {
     159            case RateId::Fixed:
     160                return equals(hostRate, hostFactor, visitorRate, visitorFactor);
     161            case RateId::PopCount:
     162            case RateId::NegatedPopCount:
     163            case RateId::Relative: { // is the reference rate processed at the same rate?
     164                const Binding & branchRef = hostKernel->getStreamBinding(hostRate.getReference());
     165                const Binding & sourceRef = visitorKernel->getStreamBinding(visitorRate.getReference());
     166                return permits(hostKernel, branchRef, hostFactor * hostRate.getRate(),
     167                               visitorKernel, sourceRef, visitorFactor * visitorRate.getRate());
     168            }
     169            case RateId::Bounded:
     170                return within(hostRate, hostFactor, visitorRate, visitorFactor);
     171            case RateId::Unknown:
     172                return atLeast(hostRate, hostFactor, visitorRate, visitorFactor);
     173            default: return false;
     174        }
     175    } else {
     176        switch (hostRateId) {
     177            case RateId::Fixed:
     178                return false;
     179            case RateId::Bounded:
     180                switch (visitorRateId) {
     181                    case RateId::Fixed:
     182                    case RateId::PopCount:
     183                    case RateId::NegatedPopCount:
     184                        return within(hostRate, hostFactor, visitorRate, visitorFactor);
     185                    case RateId::Relative: { // is the reference rate processed at the same rate?
     186                        const Binding & sourceRef = visitorKernel->getStreamBinding(visitorRate.getReference());
     187                        return permits(hostKernel, hostBinding, hostFactor,
     188                                       visitorKernel, sourceRef, visitorFactor * visitorRate.getRate());
     189                    }
     190                    default: return false;
     191                }
     192            default: return false;
     193        }
     194    }
     195}
     196
     197/** ------------------------------------------------------------------------------------------------------------- *
     198 * @brief permits
     199 ** ------------------------------------------------------------------------------------------------------------- */
     200bool permits(const Kernel * const hostKernel, const Binding & host,
     201             const Kernel * const visitorKernel, const Binding & visitor) {
     202    const RateValue ONE{1};
     203    return permits(hostKernel, host, ONE, visitorKernel, visitor, ONE);
     204}
     205
     206
     207}
  • icGREP/icgrep-devel/icgrep/kernels/processing_rate.h

    r6228 r6253  
    2323
    2424class Kernel;
     25struct Binding;
    2526
    2627struct ProcessingRate  {
     
    184185unsigned ceiling(const ProcessingRate::RateValue & r);
    185186
     187bool permits(const Kernel * const hostKernel, const Binding & host,
     188             const Kernel * const visitorKernel, const Binding & visitor);
     189
    186190}
    187191
  • icGREP/icgrep-devel/icgrep/lz4/grep/lz4_grep_base_generator.cpp

    r6247 r6253  
    8080}
    8181
    82 inline std::unique_ptr<kernel::PipelineBuilder> LZ4GrepBaseGenerator::makeInternalPipeline(const FunctionType type) {
     82inline std::unique_ptr<kernel::ProgramBuilder> LZ4GrepBaseGenerator::makeInternalPipeline(const FunctionType type) {
    8383    Bindings inputs;
    8484    Bindings outputs;
     
    228228                StreamSet * u8FinalStream = mPipeline->CreateStreamSet();
    229229                RE * const mpxU8FinalRe = transformCCs(mpx, u8FinalRe);
    230                
     230
    231231                std::unique_ptr<GrepKernelOptions> options = make_unique<GrepKernelOptions>();
    232232                options->addAlphabet(mpx, uncompressedCharClasses);
     
    241241            } else {
    242242                StreamSet * compressedNonFinalStream = mPipeline->CreateStreamSet(1, 1);
    243  
     243
    244244                std::unique_ptr<GrepKernelOptions> options = make_unique<GrepKernelOptions>();
    245245                options->setSource(compressedBitStream);
  • icGREP/icgrep-devel/icgrep/lz4/grep/lz4_grep_base_generator.h

    r6184 r6253  
    5252private:
    5353
    54     std::unique_ptr<kernel::PipelineBuilder> makeInternalPipeline(const FunctionType type);
     54    std::unique_ptr<kernel::ProgramBuilder> makeInternalPipeline(const FunctionType type);
    5555
    5656    grep::GrepRecordBreakKind mGrepRecordBreak;
  • icGREP/icgrep-devel/icgrep/lz4/lz4_base_generator.h

    r6184 r6253  
    6060    // Driver
    6161    CPUDriver mPxDriver;
    62     std::unique_ptr<kernel::PipelineBuilder> mPipeline;
     62    std::unique_ptr<kernel::ProgramBuilder> mPipeline;
    6363
    6464    // Runtime Arguments
  • icGREP/icgrep-devel/icgrep/lz4/lz4_decompression_generator.cpp

    r6186 r6253  
    2020}
    2121
    22 inline std::unique_ptr<kernel::PipelineBuilder> LZ4DecompressionGenerator::makeInternalPipeline() {
     22inline std::unique_ptr<kernel::ProgramBuilder> LZ4DecompressionGenerator::makeInternalPipeline() {
    2323    Bindings inputs;
    2424
  • icGREP/icgrep-devel/icgrep/lz4/lz4_decompression_generator.h

    r6184 r6253  
    3333private:
    3434
    35     std::unique_ptr<kernel::PipelineBuilder> makeInternalPipeline();
     35    std::unique_ptr<kernel::ProgramBuilder> makeInternalPipeline();
    3636
    3737    MainFunctionType generateDecompressionPipeline();
  • icGREP/icgrep-devel/icgrep/toolchain/driver.cpp

    r6237 r6253  
    1414 * @brief makePipelineWithIO
    1515 ** ------------------------------------------------------------------------------------------------------------- */
    16 std::unique_ptr<PipelineBuilder> BaseDriver::makePipelineWithIO(Bindings stream_inputs, Bindings stream_outputs, Bindings scalar_inputs, Bindings scalar_outputs) {
    17     return llvm::make_unique<PipelineBuilder>(*this, std::move(stream_inputs), std::move(stream_outputs), std::move(scalar_inputs), std::move(scalar_outputs), codegen::ThreadNum);
     16std::unique_ptr<ProgramBuilder> BaseDriver::makePipelineWithIO(Bindings stream_inputs, Bindings stream_outputs, Bindings scalar_inputs, Bindings scalar_outputs) {
     17    return llvm::make_unique<ProgramBuilder>(*this, std::move(stream_inputs), std::move(stream_outputs), std::move(scalar_inputs), std::move(scalar_outputs));
    1818}
    1919
     
    2121 * @brief makePipeline
    2222 ** ------------------------------------------------------------------------------------------------------------- */
    23 std::unique_ptr<kernel::PipelineBuilder> BaseDriver::makePipeline(Bindings scalar_inputs, Bindings scalar_outputs) {
    24     return llvm::make_unique<PipelineBuilder>(*this, Bindings{}, Bindings{}, std::move(scalar_inputs), std::move(scalar_outputs), codegen::ThreadNum);
     23std::unique_ptr<ProgramBuilder> BaseDriver::makePipeline(Bindings scalar_inputs, Bindings scalar_outputs) {
     24    return llvm::make_unique<ProgramBuilder>(*this, Bindings{}, Bindings{}, std::move(scalar_inputs), std::move(scalar_outputs));
    2525}
    2626
  • icGREP/icgrep-devel/icgrep/toolchain/driver.h

    r6209 r6253  
    1414namespace llvm { class Function; }
    1515namespace kernel { class KernelBuilder; }
    16 namespace kernel { class PipelineBuilder; }
     16namespace kernel { class ProgramBuilder; }
    1717class CBuilder;
    1818
    1919class BaseDriver {
    2020    friend class CBuilder;
    21     friend class kernel::PipelineBuilder;
     21    friend class kernel::ProgramBuilder;
    2222    using Kernel = kernel::Kernel;
    2323    using Relationship = kernel::Relationship;
     
    2727public:
    2828
    29     std::unique_ptr<kernel::PipelineBuilder> makePipelineWithIO(Bindings stream_inputs = {}, Bindings stream_outputs = {}, Bindings scalar_inputs = {}, Bindings scalar_outputs = {});
     29    std::unique_ptr<kernel::ProgramBuilder> makePipelineWithIO(Bindings stream_inputs = {}, Bindings stream_outputs = {}, Bindings scalar_inputs = {}, Bindings scalar_outputs = {});
    3030
    31     std::unique_ptr<kernel::PipelineBuilder> makePipeline(Bindings scalar_inputs = {}, Bindings scalar_outputs = {});
     31    std::unique_ptr<kernel::ProgramBuilder> makePipeline(Bindings scalar_inputs = {}, Bindings scalar_outputs = {});
    3232
    3333    const std::unique_ptr<kernel::KernelBuilder> & getBuilder() {
  • icGREP/icgrep-devel/icgrep/u32u8.cpp

    r6235 r6253  
    270270}
    271271
    272 void deposit(const std::unique_ptr<PipelineBuilder> & P, const unsigned base, const unsigned count, StreamSet * mask, StreamSet * inputs, StreamSet * outputs) {
     272void deposit(const std::unique_ptr<ProgramBuilder> & P, const unsigned base, const unsigned count, StreamSet * mask, StreamSet * inputs, StreamSet * outputs) {
    273273    StreamSet * const expanded = P->CreateStreamSet(count);
    274274    P->CreateKernelCall<StreamExpandKernel>(inputs, base, mask, expanded);
Note: See TracChangeset for help on using the changeset viewer.