Changeset 6214 for icGREP


Ignore:
Timestamp:
Nov 27, 2018, 8:08:21 AM (4 months ago)
Author:
cameron
Message:

abort-on-null functionality for s2p

Location:
icGREP/icgrep-devel/icgrep/kernels
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/kernels/callback.h

    r6207 r6214  
    3737 
    3838*/
     39   
     40enum {NULL_SIGNAL = 0};
    3941 
    4042class SignallingObject {
  • icGREP/icgrep-devel/icgrep/kernels/s2p_kernel.cpp

    r6184 r6214  
    55
    66#include "s2p_kernel.h"
     7#include <kernels/callback.h>
    78#include <kernels/kernel_builder.h>
    89#include <pablo/pabloAST.h>
    910#include <pablo/builder.hpp>
    1011#include <pablo/pe_pack.h>
    11 
     12#include <llvm/IR/Module.h>
    1213#include <llvm/Support/raw_ostream.h>
    1314
     
    114115
    115116void S2PKernel::generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & kb, Value * const numOfBlocks) {
     117    Module * m = kb->getModule();
     118    DataLayout DL(m);
     119    IntegerType * const intPtrTy = DL.getIntPtrType(kb->getContext());
     120    PointerType * const voidPtrTy = kb->getVoidPtrTy();
    116121    BasicBlock * entry = kb->GetInsertBlock();
    117     BasicBlock * processBlock = kb->CreateBasicBlock("processBlock");
    118     BasicBlock * s2pDone = kb->CreateBasicBlock("s2pDone");
     122    BasicBlock * s2pLoop = kb->CreateBasicBlock("s2pLoop");
     123    BasicBlock * s2pFinalize = kb->CreateBasicBlock("s2pFinalize");
    119124    Constant * const ZERO = kb->getSize(0);
    120 
    121     kb->CreateBr(processBlock);
    122    
    123     kb->SetInsertPoint(processBlock);
     125    // Declarations for AbortOnNull mode:
     126    PHINode * nullCheckPhi = nullptr;
     127    Value * nonNullSoFar = nullptr;
     128   
     129    kb->CreateBr(s2pLoop);
     130   
     131    kb->SetInsertPoint(s2pLoop);
    124132    PHINode * blockOffsetPhi = kb->CreatePHI(kb->getSizeTy(), 2); // block offset from the base block, e.g. 0, 1, 2, ...
    125133    blockOffsetPhi->addIncoming(ZERO, entry);
    126 
     134    if (mAbortOnNull) {
     135        nullCheckPhi = kb->CreatePHI(kb->getBitBlockType(), 2);
     136        nullCheckPhi->addIncoming(kb->allOnes(), entry);
     137    }
    127138    Value * bytepack[8];
    128139    for (unsigned i = 0; i < 8; i++) {
    129         if (mAligned) {
    130             bytepack[i] = kb->loadInputStreamPack("byteStream", ZERO, kb->getInt32(i), blockOffsetPhi);
    131         } else {
    132             Value * ptr = kb->getInputStreamPackPtr("byteStream", ZERO, kb->getInt32(i), blockOffsetPhi);
    133             // CreateLoad defaults to aligned here, so we need to force the alignment to 1 byte.
    134             bytepack[i] = kb->CreateAlignedLoad(ptr, 1);
    135         }
     140        bytepack[i] = kb->loadInputStreamPack("byteStream", ZERO, kb->getInt32(i), blockOffsetPhi);
    136141    }
    137142    Value * basisbits[8];
     
    140145        kb->storeOutputStreamBlock("basisBits", kb->getInt32(i), blockOffsetPhi, basisbits[i]);
    141146    }
     147    if (mAbortOnNull) {
     148        Value * nonNull = kb->simd_or(kb->simd_or(kb->simd_or(basisbits[0], basisbits[1]),
     149                                                  kb->simd_or(basisbits[2], basisbits[3])),
     150                                      kb->simd_or(kb->simd_or(basisbits[4], basisbits[5]),
     151                                                  kb->simd_or(basisbits[6], basisbits[7])));
     152        nonNullSoFar = kb->simd_and(nonNull, nullCheckPhi);
     153        nullCheckPhi->addIncoming(nonNullSoFar, s2pLoop);
     154    }
    142155    Value * nextBlk = kb->CreateAdd(blockOffsetPhi, kb->getSize(1));
    143     blockOffsetPhi->addIncoming(nextBlk, processBlock);
     156    blockOffsetPhi->addIncoming(nextBlk, s2pLoop);
    144157    Value * moreToDo = kb->CreateICmpNE(nextBlk, numOfBlocks);
    145     kb->CreateCondBr(moreToDo, processBlock, s2pDone);
    146     kb->SetInsertPoint(s2pDone);
    147 }
    148 
    149 S2PKernel::S2PKernel(const std::unique_ptr<KernelBuilder> &, StreamSet * const codeUnitStream, StreamSet * const BasisBits, const cc::BitNumbering numbering, const bool aligned)
    150 : MultiBlockKernel("s2p" + std::to_string(BasisBits->getNumElements()) + (aligned ? "a" : "u") + cc::numberingSuffix(numbering),
     158   
     159    kb->CreateCondBr(moreToDo, s2pLoop, s2pFinalize);
     160   
     161    kb->SetInsertPoint(s2pFinalize);
     162    //  s2p is complete, except for null byte check.
     163    if (mAbortOnNull) {
     164        BasicBlock * nullByteDetected = kb->CreateBasicBlock("nullByteDetected");
     165        BasicBlock * nullInFileDetected = kb->CreateBasicBlock("nullInFileDetected");
     166        BasicBlock * s2pExit = kb->CreateBasicBlock("s2pExit");
     167        Value * itemsToDo = kb->getAccessibleItemCount("byteStream");
     168        Value * anyNull = kb->bitblock_any(kb->simd_not(nonNullSoFar));
     169        kb->CreateCondBr(anyNull, nullByteDetected, s2pExit);
     170       
     171        kb->SetInsertPoint(nullByteDetected);
     172        // A null byte has been detected, determine its position and whether it is past EOF.
     173        Value * byteStreamBasePtr = kb->getInputStreamBlockPtr("byteStream", ZERO, ZERO);
     174        Value * ptrToNull = kb->CreateMemChr(kb->CreatePointerCast(byteStreamBasePtr, voidPtrTy), kb->getInt32(0), itemsToDo);
     175        Value * nullInFile = kb->CreateICmpNE(ptrToNull, ZERO);
     176        kb->CreateCondBr(nullInFile, nullInFileDetected, s2pExit);
     177        kb->SetInsertPoint(nullInFileDetected);
     178        // A null byte has been located within the file; set the termination code and call the signal handler.
     179        Value * nullPosn = kb->CreateSub(kb->CreatePtrToInt(ptrToNull, intPtrTy), kb->CreatePtrToInt(byteStreamBasePtr, intPtrTy));
     180        kb->setTerminationSignal();
     181        Function * const dispatcher = m->getFunction("signal_dispatcher"); assert (dispatcher);
     182        Value * handler = kb->getScalarField("handler_address");
     183        kb->CreateCall(dispatcher, {handler, ConstantInt::get(kb->getInt32Ty(), NULL_SIGNAL)});
     184        kb->CreateBr(s2pExit);
     185        kb->SetInsertPoint(s2pExit);
     186        PHINode * const produced = kb->CreatePHI(kb->getSizeTy(), 3);
     187        produced->addIncoming(itemsToDo, nullByteDetected);
     188        produced->addIncoming(nullPosn, nullInFileDetected);
     189        produced->addIncoming(itemsToDo, s2pFinalize);
     190        Value * producedCount = kb->getProducedItemCount("basisBits");
     191        producedCount = kb->CreateAdd(producedCount, produced);
     192        kb->setProducedItemCount("basisBits", producedCount);
     193    }
     194}
     195
     196Bindings S2PKernel::makeOutputBindings(StreamSet * const BasisBits, bool abortOnNull) {
     197    if (abortOnNull) {
     198        return {Binding("basisBits", BasisBits, FixedRate(), Deferred())};
     199    } else {
     200        return {Binding("basisBits", BasisBits)};
     201    }
     202}
     203
     204Bindings S2PKernel::makeInputScalarBindings(bool abortOnNull, Scalar * signalNullObject) {
     205    if (abortOnNull) {
     206        return {Binding{"handler_address", signalNullObject}};
     207    } else {
     208        return {};
     209    }
     210}
     211
     212S2PKernel::S2PKernel(const std::unique_ptr<KernelBuilder> &, StreamSet * const codeUnitStream, StreamSet * const BasisBits, const cc::BitNumbering numbering,
     213                     bool abortOnNull, Scalar * signalNullObject)
     214    : MultiBlockKernel((abortOnNull ? "s2pa" : "s2p") + std::to_string(BasisBits->getNumElements()) + cc::numberingSuffix(numbering),
    151215{Binding{"byteStream", codeUnitStream, FixedRate(), Principal()}},
    152 {Binding{"basisBits", BasisBits}}, {}, {}, {}),
     216makeOutputBindings(BasisBits, abortOnNull), makeInputScalarBindings(abortOnNull, signalNullObject), {}, {}),
    153217mBasisSetNumbering(numbering),
    154 mAligned(aligned),
     218mAbortOnNull(abortOnNull),
    155219mNumOfStreams(BasisBits->getNumElements()) {
    156220    assert (codeUnitStream->getFieldWidth() == BasisBits->getNumElements());
    157     if (!aligned) {
    158         mInputStreamSets[0].addAttribute(Misaligned());
    159     }
     221    addAttribute(CanTerminateEarly());
    160222}
    161223
  • icGREP/icgrep-devel/icgrep/kernels/s2p_kernel.h

    r6184 r6214  
    2323              StreamSet * const BasisBits,
    2424              const cc::BitNumbering basisNumbering = cc::BitNumbering::LittleEndian,
    25               const bool aligned = true);
     25              bool abortOnNull = false, Scalar * signalNullObject = nullptr);
    2626
    2727
     
    2929    bool hasSignature() const override { return false; }
    3030protected:
     31    Bindings makeOutputBindings(StreamSet * const BasisBits, bool abortOnNull);
     32    Bindings makeInputScalarBindings(bool abortOnNull, Scalar * signalNullObject);
    3133    void generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> & kb, llvm::Value * const numOfStrides) override;
    3234private:
    3335    const cc::BitNumbering mBasisSetNumbering;
    34     const bool mAligned;
     36    bool mAbortOnNull;
    3537    unsigned mNumOfStreams;
    3638};
Note: See TracChangeset for help on using the changeset viewer.