Ignore:
Timestamp:
Mar 7, 2016, 3:37:30 PM (3 years ago)
Author:
nmedfort
Message:

Initial modifications to Pablo Compiler and Kernel Builder to support circular buffers for Lookahead.

Location:
icGREP/icgrep-devel/icgrep/kernels
Files:
2 added
8 edited

Legend:

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

    r4945 r4959  
    55
    66#include "kernel.h"
    7 #include <iostream>
     7#include <pablo/function.h>
     8#include <IDISA/idisa_builder.h>
     9
     10using namespace llvm;
     11using namespace pablo;
     12
     13inline bool isPowerOfTwo(const unsigned x) {
     14    return (x != 0) && (x & (x - 1)) == 0;
     15}
    816
    917// sets name & sets internal state to the kernel superclass state
     
    1220, iBuilder(b)
    1321, mKernelName(name)
    14 , mPredifinedStates(2)
    1522, mBitBlockType(b->getBitBlockType())
    16 , mBlockSize(b->getBitBlockWidth()){
    17     mStates = std::vector<Type *>(4, b->getIntNTy(64));
    18     mSegmentBlocks = 1;
    19     mBufferSize = mSegmentBlocks * mBlockSize;
    20 }
    21 
    22 KernelBuilder::~KernelBuilder(){
    23 }
    24 
    25 int KernelBuilder::extendKernelInternalStateType(Type * t){
    26     int idx = mStates.size();
    27     mStates.push_back(t);
     23, mBlockSize(b->getBitBlockWidth())
     24, mBlocksPerSegment(1)
     25, mCircularBufferModulo(1)
     26, mSegmentIndex(0)
     27, mStartIndex(0) {
     28    addInternalStateType(b->getInt64Ty());
     29    addInternalStateType(b->getInt64Ty());
     30    addInternalStateType(b->getInt64Ty());
     31    addInternalStateType(b->getInt64Ty());
     32}
     33
     34unsigned KernelBuilder::addInternalStateType(Type * type){
     35    unsigned idx = mStates.size();
     36    mStates.push_back(type);
    2837    return idx;
    2938}
    30 void KernelBuilder::addKernelOutputStream(int fw){
    31     if (fw == 1){
     39void KernelBuilder::addOutputStream(const unsigned fields){
     40    if (fields == 1){
    3241        mOutputStreams.push_back(mBitBlockType);
    3342    }
    3443    else {
    35         mOutputStreams.push_back(ArrayType::get(mBitBlockType, fw));
    36     }
    37 
    38 }
    39 void KernelBuilder::addKernelOutputAccum(Type * t){
     44        mOutputStreams.push_back(ArrayType::get(mBitBlockType, fields));
     45    }
     46
     47}
     48void KernelBuilder::addOutputAccum(Type * t){
    4049    mOutputAccums.push_back(t);
    4150
    4251}
    43 void KernelBuilder::addKernelInputStream(int fw, std::string name = ""){
    44     if (name=="")
     52void KernelBuilder::addInputStream(const unsigned fields, std::string name){
     53    if (name.empty())
    4554        mInputStreamNames.push_back(mKernelName + "_inputstream_" + std::to_string(mInputStreams.size()));
    4655    else
    4756        mInputStreamNames.push_back(name);
    4857
    49     if (fw == 1){
     58    if (fields == 1){
    5059        mInputStreams.push_back(mBitBlockType);
    51     }
    52     else {
    53         mInputStreams.push_back(ArrayType::get(mBitBlockType, fw));
    54     }
    55 }
    56 void KernelBuilder::addKernelInputScalar(Type * t, std::string name = ""){
    57     if (name=="")
     60    } else {
     61        mInputStreams.push_back(ArrayType::get(mBitBlockType, fields));
     62    }
     63}
     64void KernelBuilder::addInputScalar(Type * t, std::string name){
     65    if (name.empty())
    5866        mInputScalarNames.push_back(mKernelName + "_inputscalar_" + std::to_string(mInputScalars.size()));
    5967    else
     
    6371}
    6472
    65 void KernelBuilder::PrepareDoBlockFunction(){
    66     mInputStreamType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), mInputStreams), mSegmentBlocks), 0);
     73/** ------------------------------------------------------------------------------------------------------------- *
     74 * @brief prepareFunction
     75 ** ------------------------------------------------------------------------------------------------------------- */
     76Function * KernelBuilder::prepareFunction() {   
     77    if (mCircularBufferModulo > 1) {
     78        mStartIndex = addInternalStateType(iBuilder->getInt32Ty());
     79    }
     80    const unsigned capacity = mBlocksPerSegment + mCircularBufferModulo - 1;
     81    mInputStreamType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), mInputStreams), capacity), 0);
    6782    mInputScalarType = PointerType::get(StructType::get(mMod->getContext(), mInputScalars), 0);
    68     Type * outputStreamType = ArrayType::get(StructType::get(mMod->getContext(), mOutputStreams), mSegmentBlocks);
     83    Type * outputStreamType = ArrayType::get(StructType::get(mMod->getContext(), mOutputStreams), capacity);
    6984    Type * outputAccumType = StructType::get(mMod->getContext(), mOutputAccums);
    7085    Type * stateType = StructType::create(mMod->getContext(), mStates, mKernelName);
    71     mKernelStructType = StructType::create(mMod->getContext(),std::vector<Type *>({stateType, outputStreamType, outputAccumType}), "KernelStruct_"+mKernelName);
    72 }
    73 
    74 struct Inputs KernelBuilder::openDoBlock(){
    75     // FunctionType * functionType = FunctionType::get(Type::getVoidTy(mMod->getContext()),
    76     //     std::vector<Type *>({PointerType::get(mKernelStructType, 0), mInputStreamType, mInputScalarType}), false);
    77        
    78     FunctionType * functionType = FunctionType::get(Type::getVoidTy(mMod->getContext()),
    79         std::vector<Type *>({PointerType::get(mKernelStructType, 0), mInputStreamType}), false);
    80 
    81     mDoBlockFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, mKernelName + "_DoBlock", mMod);
    82     mDoBlockFunction->setCallingConv(CallingConv::C);
    83    
    84     Function::arg_iterator args = mDoBlockFunction->arg_begin();
    85     mKernelStructParam = args++;
    86     mKernelStructParam->setName("this");
    87     Value* input_stream_param = args++;
    88     input_stream_param->setName("input_stream");
    89     // Value* input_scalar_param = args++;
    90     // input_scalar_param->setName("input_scalar");
    91 
    92     iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mDoBlockFunction,0));
    93 
    94     struct Inputs inputs;
    95     for(int j = 0; j<mSegmentBlocks; j++){
    96         for(int i = 0; i<mInputStreams.size(); i++){
    97             Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(j), iBuilder->getInt32(i)};
    98             Value * gep = iBuilder->CreateGEP(input_stream_param, indices);
    99             Type * t = gep->getType()->getPointerElementType();
    100             if (t != mBitBlockType) {
    101                 int arraySize = t->getArrayNumElements();
    102                 inputs.streams.resize(mSegmentBlocks, std::vector<valptr>(arraySize));
    103                 for (int k=0; k<arraySize; k++){
    104                     Value * gep_array_elem = iBuilder->CreateGEP(gep, {iBuilder->getInt32(0), iBuilder->getInt32(k)});
    105                     inputs.streams[j][k] = iBuilder->CreateAlignedLoad(gep_array_elem, mBlockSize/8, false, mInputStreamNames.at(i));
    106                 }
    107             }
    108             else{
    109                 inputs.streams.resize(mSegmentBlocks, std::vector<valptr>(mInputStreams.size()));
    110                 inputs.streams[j][i] = iBuilder->CreateAlignedLoad(gep, mBlockSize/8, false, mInputStreamNames.at(i));
    111             }
    112            
     86    mKernelStructType = StructType::create(mMod->getContext(),std::vector<Type *>({stateType, outputStreamType, outputAccumType}), "KernelStruct_"+ mKernelName);
     87
     88    FunctionType * functionType = FunctionType::get(Type::getVoidTy(mMod->getContext()),
     89        std::vector<Type *>({PointerType::get(mKernelStructType, 0), mInputStreamType}), false);
     90
     91    mFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, mKernelName + "_DoBlock", mMod);
     92    mFunction->setCallingConv(CallingConv::C);
     93
     94    Function::arg_iterator args = mFunction->arg_begin();
     95    mKernelParam = args++;
     96    mKernelParam->setName("this");
     97
     98    mInputParam = args++;
     99    mInputParam->setName("input_stream");
     100
     101    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mFunction, 0));
     102
     103    mSegmentIndex = 0;
     104
     105    return mFunction;
     106}
     107
     108/** ------------------------------------------------------------------------------------------------------------- *
     109 * @brief finalize
     110 ** ------------------------------------------------------------------------------------------------------------- */
     111void KernelBuilder::finalize() {
     112    Type * const int64Ty = iBuilder->getInt64Ty();
     113
     114    // Finish the actual function
     115    if (mCircularBufferModulo > 1) {
     116        Value * startIdx = getInternalState(mStartIndex);
     117        Value * value = iBuilder->CreateAdd(iBuilder->CreateBlockAlignedLoad(startIdx), iBuilder->getInt32(1));
     118        iBuilder->CreateBlockAlignedStore(value, startIdx);
     119    }
     120    iBuilder->CreateRetVoid();
     121
     122
     123    // Generate the zero initializer
     124    Function * initializer = cast<Function>(mMod->getOrInsertFunction(mKernelName + "_Init", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), nullptr));
     125    initializer->setCallingConv(CallingConv::C);
     126    Function::arg_iterator args = initializer->arg_begin();
     127
     128    mKernelParam = args++;
     129    mKernelParam->setName("this");
     130
     131    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", initializer, 0));
     132
     133    for (unsigned i = 0; i < mStates.size(); ++i) {
     134        Value * const gep = getInternalState(i);
     135        Type * const type = gep->getType();
     136        if (type->isIntegerTy() || type->isArrayTy() || type->isVectorTy()) {
     137            setInternalState(i, Constant::getNullValue(type));
     138        } else {
     139            Value * gep_next = iBuilder->CreateGEP(gep, iBuilder->getInt32(1));
     140            Value * get_int = iBuilder->CreatePtrToInt(gep, int64Ty);
     141            Value * get_next_int = iBuilder->CreatePtrToInt(gep_next, int64Ty);
     142            Value * state_size = iBuilder->CreateSub(get_next_int, get_int);
     143            iBuilder->CreateMemSet(gep, iBuilder->getInt8(0), state_size, 4);
    113144        }
    114145    }
    115146
    116     // inputs.scalars.resize(mInputScalars.size());
    117     // for(int i = 0; i<mInputScalars.size(); i++){
    118     //     Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(i)};
    119     //     Value * gep = iBuilder->CreateGEP(input_scalar_param, indices);
    120     //     inputs.scalars[i] = iBuilder->CreateAlignedLoad(gep, mBlockSize/8, false, mInputScalarNames.at(i));
    121     // }
    122 
    123     return inputs;
    124 }
    125 
    126 void KernelBuilder::closeDoBlock(struct Outputs result){
    127    
    128 
    129     for(int j=0; j<mSegmentBlocks; j++){
    130         for(int i = 0; i<mOutputStreams.size(); i++){   
    131             Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(1), iBuilder->getInt32(j), iBuilder->getInt32(i)};
    132             Value* gep = iBuilder->CreateGEP(mKernelStructParam, indices);
    133             iBuilder->CreateAlignedStore(result.streams[j][i], gep, mBlockSize/8, false);
    134         }
    135     }
    136 
    137     for(int i = 0; i<mOutputAccums.size(); i++){   
    138         Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(2), iBuilder->getInt32(i)};
    139         Value* gep = iBuilder->CreateGEP(mKernelStructParam, indices);
    140         iBuilder->CreateAlignedStore(result.accums[i], gep, mBlockSize/8, false);
    141     }
    142 
    143147    iBuilder->CreateRetVoid();
    144 }
    145 
    146 void KernelBuilder::changeKernelInternalState(Value * kernelStruct, int idx, Value * stateValue){
    147     Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(idx)};
    148     Value* gep = iBuilder->CreateGEP(kernelStruct, indices);
    149     iBuilder->CreateAlignedStore(stateValue, gep, mBlockSize/8, false);
    150 }
    151 
    152 Value * KernelBuilder::getKernelInternalState(Value * kernelStruct, int idx){
    153     Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(idx)};
    154     Value* gep = iBuilder->CreateGEP(kernelStruct, indices);
    155     return iBuilder->CreateAlignedLoad(gep, mBlockSize/8, false, "state"+std::to_string(idx));
    156 }
    157 
    158 Value * KernelBuilder::getKernelInternalStatePtr(Value * kernelStruct, int idx){
    159     Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(idx)};
    160     Value* gep = iBuilder->CreateGEP(kernelStruct, indices);
    161     return gep;
    162 }
    163 
    164 void KernelBuilder::finalizeMethods(){
    165     Type * T = iBuilder->getIntNTy(64);
    166 
    167     Constant* c = mMod->getOrInsertFunction(mKernelName+"_Init", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), NULL);
    168     Function* mInitFunction = cast<Function>(c);
    169     mInitFunction->setCallingConv(CallingConv::C);
    170     Function::arg_iterator args = mInitFunction->arg_begin();
    171 
    172     Value* this_param = args++;
    173     this_param->setName("this");
    174 
    175     int i = mPredifinedStates;
    176     iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mInitFunction, 0));
    177     Value * gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(i++) }));
    178     iBuilder->CreateStore(iBuilder->getInt64(0), gep);  //FileBasePos
    179     gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(i++) }));
    180     iBuilder->CreateStore(iBuilder->getInt64(0), gep);  //AvailableBlocks
    181 
    182     while(i < mStates.size()){
    183         gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(i++) }));
    184         Value * gep_next = iBuilder->CreateGEP(gep, std::vector<Value *>({iBuilder->getInt32(1)}));
    185         Value * get_int = iBuilder->CreatePtrToInt(gep, T);
    186         Value * get_next_int = iBuilder->CreatePtrToInt(gep_next, T);
    187         Value * state_size = iBuilder->CreateSub(get_next_int, get_int);
    188         iBuilder->CreateMemSet(gep, iBuilder->getInt8(0), state_size, 4);
    189     }
    190 
    191     iBuilder->CreateRetVoid();
    192 
    193     c = mMod->getOrInsertFunction(mKernelName+"_Create_Default", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), T, T, NULL);
    194     mConstructor = cast<Function>(c);
     148
     149    // and then the constructor
     150    mConstructor = cast<Function>(mMod->getOrInsertFunction(mKernelName+"_Create_Default", Type::getVoidTy(mMod->getContext()), PointerType::get(mKernelStructType, 0), int64Ty, int64Ty, nullptr));
    195151    mConstructor->setCallingConv(CallingConv::C);
    196152    args = mConstructor->arg_begin();
    197153
    198     this_param = args++;
    199     this_param->setName("this");
     154    mKernelParam = args++;
     155    mKernelParam->setName("this");
     156
    200157    Value* block_size_param = args++;
    201158    block_size_param->setName("block_size");
    202159    Value* seg_size_param = args++;
    203160    seg_size_param->setName("seg_size");
    204  
    205161    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mConstructor, 0));
    206     gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(0) }));
    207     iBuilder->CreateStore(block_size_param, gep);   
    208     gep = iBuilder->CreateGEP(this_param, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(1) }));
    209     iBuilder->CreateStore(seg_size_param, gep);
    210 
    211     iBuilder->CreateCall(mInitFunction, this_param);
     162    iBuilder->CreateStore(block_size_param, getInternalState(0));
     163    iBuilder->CreateStore(seg_size_param, getInternalState(1));
     164    iBuilder->CreateCall(initializer, mKernelParam);
    212165    iBuilder->CreateRetVoid();
    213 
    214 }
    215 
    216 Value * KernelBuilder::generateKernelInstance(){
    217 
    218     mKernelStruct = iBuilder->CreateAlloca(mKernelStructType);
    219     iBuilder->CreateCall3(mConstructor, mKernelStruct,
    220         ConstantInt::get(iBuilder->getIntNTy(64), mBlockSize),
    221         ConstantInt::get(iBuilder->getIntNTy(64), mBufferSize));
     166}
     167
     168/** ------------------------------------------------------------------------------------------------------------- *
     169 * @brief generateKernelInstance
     170 ** ------------------------------------------------------------------------------------------------------------- */
     171Value * KernelBuilder::generateKernelInstance() {
     172    mKernelStruct = iBuilder->CreateAlloca(mKernelStructType);
     173    iBuilder->CreateCall3(mConstructor, mKernelStruct,
     174        ConstantInt::get(iBuilder->getIntNTy(64), mBlockSize),
     175        ConstantInt::get(iBuilder->getIntNTy(64), (mBlocksPerSegment + mCircularBufferModulo) * mBlockSize));
    222176    return mKernelStruct;
    223177
    224178}
     179
     180Value * KernelBuilder::getInputStream(const unsigned index, const unsigned streamOffset) {
     181    Value * const indices[] = {iBuilder->getInt32(0), getOffset(streamOffset), iBuilder->getInt32(index)};
     182    return iBuilder->CreateGEP(mInputParam, indices);
     183}
     184
     185Value * KernelBuilder::getKernelState(const unsigned index, const unsigned streamOffset) {
     186    Value * const indices[] = {iBuilder->getInt32(0), iBuilder->getInt32(0), getOffset(streamOffset), iBuilder->getInt32(index)};
     187    return iBuilder->CreateGEP(mKernelParam, indices);
     188}
     189
     190Value * KernelBuilder::getOutputStream(const unsigned index, const unsigned streamOffset) {
     191    Value * const indices[] = {iBuilder->getInt32(0), iBuilder->getInt32(1), getOffset(streamOffset), iBuilder->getInt32(index)};
     192    return iBuilder->CreateGEP(mKernelParam, indices);
     193}
     194
     195Value * KernelBuilder::getOutputScalar(const unsigned index, const unsigned streamOffset) {
     196    Value * const indices[] = {iBuilder->getInt32(0), iBuilder->getInt32(2), getOffset(streamOffset), iBuilder->getInt32(index)};
     197    return iBuilder->CreateGEP(mKernelParam, indices);
     198}
     199
     200Value * KernelBuilder::getInternalState(const unsigned index){
     201    Value* indices[] = {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(index)};
     202    return iBuilder->CreateGEP(mKernelParam, indices);
     203}
     204
     205void KernelBuilder::setInternalState(const unsigned index, Value * const value) {
     206    iBuilder->CreateBlockAlignedStore(value, getInternalState(index));
     207}
     208
    225209void KernelBuilder::generateInitCall(){
    226210    iBuilder->CreateCall(mInitFunction, mKernelStruct);
    227211}
    228212
    229 // void KernelBuilder::generateDoBlockCall(Value * inputStreams, Value * inputScalars){
    230 //     iBuilder->CreateCall3(mDoBlockFunction, mKernelStruct, inputStreams, inputScalars);
    231 // }
    232213void KernelBuilder::generateDoBlockCall(Value * inputStreams){
    233     iBuilder->CreateCall2(mDoBlockFunction, mKernelStruct, inputStreams);
    234 }
    235 
    236 int KernelBuilder::getSegmentBlocks(){
    237     return mSegmentBlocks;
    238 }
    239 
    240 Function * KernelBuilder::getDoBlockFunction(){
    241     return mDoBlockFunction;
    242 }
    243 
    244 Type * KernelBuilder::getKernelStructType(){
    245     return mKernelStructType;
    246 }
    247 
    248 Value * KernelBuilder::getKernelStructParam(){
    249     return mKernelStructParam;
    250 }
    251 
     214    iBuilder->CreateCall2(mFunction, mKernelStruct, inputStreams);
     215}
     216
     217/** ------------------------------------------------------------------------------------------------------------- *
     218 * @brief offset
     219 *
     220 * Compute the index of the given offset value.
     221 ** ------------------------------------------------------------------------------------------------------------- */
     222Value * KernelBuilder::getOffset(const unsigned offset) {
     223    Value * index = iBuilder->getInt32(mSegmentIndex + offset);
     224    if (mStartIndex) {
     225        index = iBuilder->CreateAdd(iBuilder->CreateBlockAlignedLoad(getInternalState(mStartIndex)), index);
     226        const unsigned capacity = (mBlocksPerSegment + mCircularBufferModulo);
     227        if (isPowerOfTwo(capacity)) {
     228            index = iBuilder->CreateAnd(index, ConstantInt::get(index->getType(), capacity - 1));
     229        } else {
     230            index = iBuilder->CreateURem(index, ConstantInt::get(index->getType(), capacity));
     231        }
     232        // TODO: generate branch / phi node when it's sufficiently unlikely that we'll wrap around.
     233    }
     234    return index;
     235}
     236
  • icGREP/icgrep-devel/icgrep/kernels/kernel.h

    r4945 r4959  
    66 */
    77
    8 
    9 #include <IDISA/idisa_builder.h>
    10 #include <llvm/IR/Function.h>
    11 #include <llvm/IR/Module.h>
     8#include <string>
     9#include <vector>
    1210
    1311namespace llvm {
     
    2422}
    2523
    26 using namespace llvm;
     24namespace pablo {
     25    class PabloAST;
     26    class PabloFunction;
     27}
    2728
    28 typedef Value* valptr;
     29namespace IDISA {
     30    class IDISA_Builder;
     31}
    2932
    30 struct Inputs {
    31     std::vector<std::vector<valptr>> streams;
    32     std::vector<valptr> scalars;
     33class KernelBuilder {
     34
     35public:
     36    // sets name & sets internal state to the kernel superclass state
     37    KernelBuilder(std::string name, llvm::Module * m, IDISA::IDISA_Builder * b);
     38
     39    unsigned addInternalStateType(llvm::Type * type);
     40    void addOutputStream(const unsigned fields);
     41    void addOutputAccum(llvm::Type * t);
     42    void addInputStream(const unsigned fields, std::string name);
     43    void addInputScalar(llvm::Type * t, std::string name);
     44
     45    llvm::Function * prepareFunction();
     46
     47    void increment();
     48    void incrementCircularBuffer();
     49
     50    llvm::Value * getInputStream(const unsigned index, const unsigned streamOffset = 0);
     51    llvm::Value * getKernelState(const unsigned index, const unsigned streamOffset = 0);
     52    llvm::Value * getOutputStream(const unsigned index, const unsigned streamOffset = 0);
     53    llvm::Value * getOutputScalar(const unsigned index, const unsigned streamOffset = 0);
     54
     55    void finalize();
     56
     57    llvm::Value * generateKernelInstance();
     58        void generateInitCall();
     59    void generateDoBlockCall(llvm::Value * inputStreams);
     60
     61    unsigned getSegmentBlocks() const;
     62    llvm::Function * getDoBlockFunction() const;
     63    llvm::Type * getKernelStructType() const;
     64    llvm::Value * getKernelStructParam() const;
     65
     66    void setCircularBufferSize(const unsigned blocks);
     67    void setBlocksPerSegment(const unsigned blocks);
     68
     69    void setInternalState(const unsigned index, llvm::Value * const value);
     70    llvm::Value * getInternalState(const unsigned index);
     71
     72protected:
     73
     74    llvm::Value * getOffset(const unsigned offset);
     75
     76private:
     77    llvm::Module *                      mMod;
     78    IDISA::IDISA_Builder *              iBuilder;
     79    std::string                                                 mKernelName;
     80    llvm::Type *                        mBitBlockType;
     81    std::vector<llvm::Type *>                   mStates;
     82    std::vector<llvm::Type *>           mInputStreams;
     83    std::vector<llvm::Type *>           mOutputStreams;
     84    std::vector<llvm::Type *>           mInputScalars;
     85    std::vector<llvm::Type *>           mOutputAccums;
     86    std::vector<std::string>            mInputStreamNames;
     87    std::vector<std::string>            mInputScalarNames;
     88    llvm::Function*                                     mConstructor;
     89    llvm::Function*                                             mInitFunction;
     90    llvm::Function*                                             mFunction;
     91    unsigned                            mBlockSize;
     92    unsigned                            mBlocksPerSegment;
     93    unsigned                            mCircularBufferModulo;
     94    llvm::Type *                        mKernelStructType;
     95    llvm::Type *                        mInputStreamType;
     96    llvm::Type *                        mInputScalarType;
     97    llvm::Value *                       mInputParam;
     98    llvm::Value *                       mKernelStruct;
     99    llvm::Value *                       mKernelParam;
     100    unsigned                            mSegmentIndex;
     101    unsigned                            mStartIndex;
    33102};
    34103
    35 struct Outputs {
    36     std::vector<valptr *> streams;
    37     std::vector<valptr> accums;
    38 };
     104inline unsigned KernelBuilder::getSegmentBlocks() const {
     105    return mBlocksPerSegment;
     106}
    39107
    40 class KernelBuilder{
    41 public:
    42     // sets name & sets internal state to the kernel superclass state
    43         KernelBuilder(std::string name, Module * m, IDISA::IDISA_Builder * b);
    44         ~KernelBuilder();
     108inline llvm::Function * KernelBuilder::getDoBlockFunction() const {
     109    return mFunction;
     110}
    45111
    46         int extendKernelInternalStateType(Type * t);
    47         void addKernelOutputStream(int fw);
    48         void addKernelOutputAccum(Type * t);
    49         void addKernelInputStream(int fw, std::string name);
    50         void addKernelInputScalar(Type * t, std::string name);
    51     void PrepareDoBlockFunction();
    52         struct Inputs openDoBlock();
    53         void closeDoBlock(struct Outputs);
    54         void finalizeMethods();
    55         Value * generateKernelInstance();
    56         void generateInitCall();
    57         // void generateDoBlockCall(Value * inputStreams, Value * inputScalars);
    58     void generateDoBlockCall(Value * inputStreams);
    59     int getSegmentBlocks();
    60     Function * getDoBlockFunction();
    61     Type * getKernelStructType();
    62     Value * getKernelStructParam();
     112inline llvm::Type * KernelBuilder::getKernelStructType() const{
     113    return mKernelStructType;
     114}
    63115
    64     void changeKernelInternalState(Value * kernelStruct, int idx, Value * stateValue);
    65     Value * getKernelInternalState(Value * kernelStruct, int idx);
    66     Value * getKernelInternalStatePtr(Value * kernelStruct, int idx);
     116inline llvm::Value * KernelBuilder::getKernelStructParam() const {
     117    return mKernelParam;
     118}
    67119
    68 private:
    69         Module *                            mMod;
    70     IDISA::IDISA_Builder *              iBuilder;
    71     std::string                                                 mKernelName;
    72     int                                 mPredifinedStates;
    73     Type*                               mBitBlockType;
    74     std::vector<Type *>                                 mStates;
    75     std::vector<Type *>                 mInputStreams;
    76     std::vector<Type *>                 mOutputStreams;
    77     std::vector<Type *>                 mInputScalars;
    78     std::vector<Type *>                 mOutputAccums;
    79     std::vector<std::string>            mInputStreamNames;
    80     std::vector<std::string>            mInputScalarNames;
    81     Function*                                                   mConstructor;
    82     Function*                                                   mInitFunction;
    83     Function*                                                   mDoBlockFunction;
    84     int                                 mBufferSize;
    85     int                                 mBlockSize;
    86     int                                 mSegmentBlocks;
    87     Type *                              mKernelStructType;
    88     Type *                              mInputStreamType;   
    89     Type *                              mInputScalarType;
    90     Value*                              mKernelStruct;
    91     Value*                              mKernelStructParam;
    92 };
     120inline void KernelBuilder::setCircularBufferSize(const unsigned blocks) {
     121    mCircularBufferModulo = blocks;
     122}
     123
     124inline void KernelBuilder::setBlocksPerSegment(const unsigned blocks) {
     125    mBlocksPerSegment = blocks;
     126}
     127
     128inline void KernelBuilder::increment() {
     129    ++mSegmentIndex;
     130}
    93131
    94132#endif // KERNEL_H
  • icGREP/icgrep-devel/icgrep/kernels/pipeline.cpp

    r4945 r4959  
    1414#include <pablo/pablo_compiler.h>
    1515
     16using namespace pablo;
    1617
    1718PipelineBuilder::PipelineBuilder(Module * m, IDISA::IDISA_Builder * b)
     
    2526
    2627}
     28
    2729PipelineBuilder::~PipelineBuilder(){
     30    delete mS2PKernel;
     31    delete mICgrepKernel;
     32    delete mScanMatchKernel;
    2833}
    2934
    30 void PipelineBuilder::CreateKernels(pablo::PabloFunction * function, bool isNameExpression){
     35void PipelineBuilder::CreateKernels(PabloFunction * function, bool isNameExpression){
    3136    mS2PKernel = new KernelBuilder("s2p", mMod, iBuilder);
    3237    mICgrepKernel = new KernelBuilder("icgrep", mMod, iBuilder);
    3338    mScanMatchKernel = new KernelBuilder("scanMatch", mMod, iBuilder);
    34 
    3539
    3640    generateS2PKernel(mMod, iBuilder, mS2PKernel);
     
    3842
    3943    pablo_function_passes(function);
    40          
    41     pablo::PabloCompiler pablo_compiler(mMod, iBuilder);
     44
     45    PabloCompiler pablo_compiler(mMod, iBuilder);
    4246    try {
    4347        pablo_compiler.setKernel(mICgrepKernel);
     
    5155        exit(1);
    5256    }
    53 
    5457}
    5558
     
    5760    Type * T = iBuilder->getIntNTy(64);   
    5861    Type * S = PointerType::get(iBuilder->getIntNTy(8), 0);
    59     Type * inputType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), std::vector<Type *>({ArrayType::get(mBitBlockType, 8)})), 1), 0);
    60  
    61     Constant* c = mMod->getOrInsertFunction("Main", Type::getVoidTy(mMod->getContext()), inputType, T, S, T, NULL);
    62     Function* mMainFunction = cast<Function>(c);
    63     mMainFunction->setCallingConv(CallingConv::C);
    64     Function::arg_iterator args = mMainFunction->arg_begin();
    65 
     62    Type * inputType = PointerType::get(ArrayType::get(StructType::get(mMod->getContext(), std::vector<Type *>({ArrayType::get(mBitBlockType, 8)})), 1), 0);
     63    Function * const main = cast<Function>(mMod->getOrInsertFunction("Main", Type::getVoidTy(mMod->getContext()), inputType, T, S, T, nullptr));
     64    main->setCallingConv(CallingConv::C);
     65    Function::arg_iterator args = main->arg_begin();
    6666
    6767    Value* input_param = args++;
     
    7474    finalLineUnterminated_param->setName("finalLineUnterminated");
    7575
    76     iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", mMainFunction,0));
    77 
     76    iBuilder->SetInsertPoint(BasicBlock::Create(mMod->getContext(), "entry", main,0));
    7877
    7978    BasicBlock * entry_block = iBuilder->GetInsertBlock();
    80     BasicBlock * pipeline_test_block = BasicBlock::Create(mMod->getContext(), "pipeline_test_block", mMainFunction, 0);
    81     BasicBlock * pipeline_do_block = BasicBlock::Create(mMod->getContext(), "pipeline_do_block", mMainFunction, 0);
    82     BasicBlock * pipeline_final_block = BasicBlock::Create(mMod->getContext(), "pipeline_final_block", mMainFunction, 0);
    83     BasicBlock * pipeline_partial_block = BasicBlock::Create(mMod->getContext(), "pipeline_partial_block", mMainFunction, 0);
    84     BasicBlock * pipeline_empty_block = BasicBlock::Create(mMod->getContext(), "pipeline_empty_block", mMainFunction, 0);
    85     BasicBlock * pipeline_end_block = BasicBlock::Create(mMod->getContext(), "pipeline_end_block", mMainFunction, 0);   
    86     BasicBlock * pipeline_Unterminated_block = BasicBlock::Create(mMod->getContext(), "pipeline_Unterminated_block", mMainFunction, 0);
    87     BasicBlock * pipeline_return_block = BasicBlock::Create(mMod->getContext(), "pipeline_return_block", mMainFunction, 0);
     79    BasicBlock * pipeline_test_block = BasicBlock::Create(mMod->getContext(), "pipeline_test_block", main, 0);
     80    BasicBlock * pipeline_do_block = BasicBlock::Create(mMod->getContext(), "pipeline_do_block", main, 0);
     81    BasicBlock * pipeline_final_block = BasicBlock::Create(mMod->getContext(), "pipeline_final_block", main, 0);
     82    BasicBlock * pipeline_partial_block = BasicBlock::Create(mMod->getContext(), "pipeline_partial_block", main, 0);
     83    BasicBlock * pipeline_empty_block = BasicBlock::Create(mMod->getContext(), "pipeline_empty_block", main, 0);
     84    BasicBlock * pipeline_end_block = BasicBlock::Create(mMod->getContext(), "pipeline_end_block", main, 0);
     85    BasicBlock * pipeline_Unterminated_block = BasicBlock::Create(mMod->getContext(), "pipeline_Unterminated_block", main, 0);
     86    BasicBlock * pipeline_return_block = BasicBlock::Create(mMod->getContext(), "pipeline_return_block", main, 0);
    8887
    8988    Value * s2pKernelStruct = mS2PKernel->generateKernelInstance();
     
    9190    Value * scanMatchKernelStruct = mScanMatchKernel->generateKernelInstance();
    9291
     92    Value * gep = iBuilder->CreateGEP(scanMatchKernelStruct, {iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(mFileBufIdx)});
    9393    Value* filebuf = iBuilder->CreateBitCast(input_param, S);
    94     mScanMatchKernel->changeKernelInternalState(scanMatchKernelStruct, mFileBufIdx, filebuf);
    95     mScanMatchKernel->changeKernelInternalState(scanMatchKernelStruct, mFileSizeIdx, buffersize_param);
    96     mScanMatchKernel->changeKernelInternalState(scanMatchKernelStruct, mFileNameIdx, filename_param);
     94    iBuilder->CreateStore(filebuf, gep);
     95    gep = iBuilder->CreateGEP(scanMatchKernelStruct, {iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(mFileSizeIdx)});
     96    iBuilder->CreateStore(buffersize_param, gep);
     97    gep = iBuilder->CreateGEP(scanMatchKernelStruct, {iBuilder->getInt32(0), iBuilder->getInt32(0), iBuilder->getInt32(mFileNameIdx)});
     98    iBuilder->CreateStore(filename_param, gep);
    9799
    98100    Value * basis_bits = iBuilder->CreateGEP(s2pKernelStruct, {iBuilder->getInt32(0), iBuilder->getInt32(1)});
     
    112114    iBuilder->SetInsertPoint(pipeline_do_block);
    113115
    114     Value * gep = iBuilder->CreateGEP(input_param, {blkNo_phi});
     116    gep = iBuilder->CreateGEP(input_param, {blkNo_phi});
    115117    Value * update_blkNo = iBuilder->CreateAdd(blkNo_phi, iBuilder->getInt64(1));
    116118    blkNo_phi->addIncoming(update_blkNo, pipeline_do_block);
     
    169171
    170172}
    171 
    172 
    173 
  • icGREP/icgrep-devel/icgrep/kernels/pipeline.h

    r4939 r4959  
    2525}
    2626
    27 namespace pablo { class PabloFunction; }
     27namespace pablo { class PabloFunction; class PabloBlock; }
    2828
    2929using namespace llvm;
  • icGREP/icgrep-devel/icgrep/kernels/s2p_kernel.cpp

    r4957 r4959  
    11/*
    2  *  Copyright (c) 2015 International Characters.
     2 *  Copyright (c) 2016 International Characters.
    33 *  This software is licensed to the public under the Open Software License 3.0.
    44 */
    5 #include "kernel.h"
    65#include "s2p_kernel.h"
    7 #include <iostream>
     6#include <kernels/kernel.h>
     7#include <IDISA/idisa_builder.h>
    88
    99const int PACK_LANES = 1;
     
    2626}
    2727
    28 void s2p(IDISA::IDISA_Builder * iBuilder, std::vector<Value*> s, Value* p[]) {
     28inline void s2p(IDISA::IDISA_Builder * iBuilder, Value * input, Value * output[]) {
    2929    Value * bit00224466[4];
    3030    Value * bit11335577[4];
    3131    for (unsigned i = 0; i<4; i++) {
    32         s2p_step(iBuilder, s[2*i], s[2*i+1], iBuilder->simd_himask(2), 1, bit00224466[i], bit11335577[i]);
     32        Value * s0 = iBuilder->CreateBlockAlignedLoad(input, {iBuilder->getInt32(0), iBuilder->getInt32(2 * i)});
     33        Value * s1 = iBuilder->CreateBlockAlignedLoad(input, {iBuilder->getInt32(0), iBuilder->getInt32(2 * i + 1)});
     34        s2p_step(iBuilder, s0, s1, iBuilder->simd_himask(2), 1, bit00224466[i], bit11335577[i]);
    3335    }
    3436    Value * bit00004444[2];
     
    4244                 iBuilder->simd_himask(4), 2, bit11115555[j], bit33337777[j]);
    4345    }
    44     s2p_step(iBuilder, bit00004444[0], bit00004444[1], iBuilder->simd_himask(8), 4, p[0], p[4]);
    45     s2p_step(iBuilder, bit11115555[0], bit11115555[1], iBuilder->simd_himask(8), 4, p[1], p[5]);
    46     s2p_step(iBuilder, bit22226666[0], bit22226666[1], iBuilder->simd_himask(8), 4, p[2], p[6]);
    47     s2p_step(iBuilder, bit33337777[0], bit33337777[1], iBuilder->simd_himask(8), 4, p[3], p[7]);
     46    s2p_step(iBuilder, bit00004444[0], bit00004444[1], iBuilder->simd_himask(8), 4, output[0], output[4]);
     47    s2p_step(iBuilder, bit11115555[0], bit11115555[1], iBuilder->simd_himask(8), 4, output[1], output[5]);
     48    s2p_step(iBuilder, bit22226666[0], bit22226666[1], iBuilder->simd_himask(8), 4, output[2], output[6]);
     49    s2p_step(iBuilder, bit33337777[0], bit33337777[1], iBuilder->simd_himask(8), 4, output[3], output[7]);
    4850}
    4951
    50 
    51 void generateS2PKernel(Module * m, IDISA::IDISA_Builder * iBuilder, KernelBuilder * kBuilder){
    52 
    53     kBuilder->addKernelInputStream(8, "byte_pack");
    54     for(int i=0; i<8; i++)
    55         kBuilder->addKernelOutputStream(1);
    56 
    57     int segBlocks = kBuilder->getSegmentBlocks();
    58 
    59     kBuilder->PrepareDoBlockFunction();   
    60     struct Inputs inputs = kBuilder->openDoBlock();
    61     struct Outputs outputs;
    62 
    63     valptr basis_bit[segBlocks][8];
    64     for(int i=0; i<segBlocks; i++){
    65         s2p(iBuilder, inputs.streams[i], basis_bit[i]);
    66         outputs.streams.push_back(basis_bit[i]);
     52void generateS2PKernel(Module *, IDISA::IDISA_Builder * iBuilder, KernelBuilder * kBuilder) {
     53    kBuilder->addInputStream(8, "byte_pack");
     54    for(unsigned i = 0; i < 8; ++i) {
     55        kBuilder->addOutputStream(1);
    6756    }
    68 
    69     kBuilder->closeDoBlock(outputs);
    70 
    71     kBuilder->finalizeMethods();
    72 
     57    kBuilder->prepareFunction();
     58    for(unsigned i = 0; i < kBuilder->getSegmentBlocks(); ++i){
     59        Value * output[8];
     60        s2p(iBuilder, kBuilder->getInputStream(0), output);
     61        for (unsigned j = 0; j < 8; ++j) {
     62            iBuilder->CreateBlockAlignedStore(output[j], kBuilder->getOutputStream(j));
     63        }
     64        kBuilder->increment();
     65    }
     66    kBuilder->finalize();
    7367}
    7468
     
    8377
    8478
     79
  • icGREP/icgrep-devel/icgrep/kernels/s2p_kernel.h

    r4939 r4959  
    11/*
    2  *  Copyright (c) 2015 International Characters.
     2 *  Copyright (c) 2016 International Characters.
    33 *  This software is licensed to the public under the Open Software License 3.0.
    44 */
    5 
    6 
    75#ifndef S2P_KERNEL_H
    86#define S2P_KERNEL_H
    97
    10 #include <stdio.h>
    11 #include <IDISA/idisa_builder.h>
    12 #include <llvm/IR/Module.h>
     8class KernelBuilder;
    139
    14 void generateS2PKernel(Module * m, IDISA::IDISA_Builder * iBuilder, KernelBuilder * kBuilder);
     10namespace llvm { class Module; }
     11
     12namespace IDISA { class IDISA_Builder; }
     13
     14
     15void generateS2PKernel(llvm::Module *, IDISA::IDISA_Builder * iBuilder, KernelBuilder * kBuilder);
    1516
    1617#endif
    17 
  • icGREP/icgrep-devel/icgrep/kernels/scanmatchgen.cpp

    r4946 r4959  
    77#include "scanmatchgen.h"
    88#include <llvm/IR/Intrinsics.h>
     9#include <IDISA/idisa_builder.h>
     10#include <llvm/Support/raw_os_ostream.h>
     11
     12using namespace llvm;
    913
    1014Value * generateForwardZeroesMask(IDISA::IDISA_Builder * iBuilder, Value * bits) {
     
    3236    return iBuilder->CreateAnd(bits_minus1, bits);
    3337}
    34        
    35        
    36 void generateScanWordRoutine(Module * m, IDISA::IDISA_Builder * iBuilder, KernelBuilder * kBuilder, int scanwordBitWidth, bool isNameExpression) {
     38
     39Function * generateScanWordRoutine(Module * m, IDISA::IDISA_Builder * iBuilder, unsigned scanwordBitWidth, Type * kernelStuctType, bool isNameExpression) {
     40
     41    Function * function = m->getFunction("scan_matches_in_scanword");
     42    if (LLVM_UNLIKELY(function != nullptr)) {
     43        return function;
     44    }
     45
    3746    LLVMContext & ctxt = m->getContext();
    38     Type * T = iBuilder->getIntNTy(scanwordBitWidth);   
     47    Type * T = iBuilder->getIntNTy(scanwordBitWidth);
    3948    Type * S = PointerType::get(iBuilder->getIntNTy(8), 0);
    4049    Type * returnType = StructType::get(ctxt, std::vector<Type *>({T, T}));
    41     Type * kernelStuctType = PointerType::get(kBuilder->getKernelStructType(), 0);
    4250    FunctionType * functionType = FunctionType::get(returnType, std::vector<Type *>({kernelStuctType, T, T, T, T, T}), false);
    43     Function * sFunction;
    44        
     51
    4552    SmallVector<AttributeSet, 6> Attrs;
    4653    Attrs.push_back(AttributeSet::get(ctxt, ~0U, std::vector<Attribute::AttrKind>({ Attribute::NoUnwind, Attribute::UWTable })));
     
    5158    Attrs.push_back(AttributeSet::get(ctxt, 5, std::vector<Attribute::AttrKind>({})));
    5259    AttributeSet AttrSet = AttributeSet::get(ctxt, Attrs);
    53    
    54     sFunction = Function::Create(functionType, GlobalValue::ExternalLinkage, "scan_matches_in_scanword", m);
    55     sFunction->setCallingConv(CallingConv::C);
    56     sFunction->setAttributes(AttrSet);
    57     sFunction->addFnAttr(llvm::Attribute::AlwaysInline);
    58        
    59     Function::arg_iterator args = sFunction->arg_begin();
     60
     61    function = Function::Create(functionType, GlobalValue::ExternalLinkage, "scan_matches_in_scanword", m);
     62    function->setCallingConv(CallingConv::C);
     63    function->setAttributes(AttrSet);
     64    function->addFnAttr(llvm::Attribute::AlwaysInline);
     65
     66    Function::arg_iterator args = function->arg_begin();
    6067    Value * this_input_parm = args++;
    6168    this_input_parm->setName("this");
     
    7582    else
    7683        matchProcessor = m->getOrInsertFunction("wrapped_report_match", Type::getVoidTy(ctxt), T, T, T, S, T, S, nullptr);
    77    
    78     iBuilder->SetInsertPoint(BasicBlock::Create(ctxt, "entry", sFunction,0));
     84
     85    iBuilder->SetInsertPoint(BasicBlock::Create(ctxt, "entry", function,0));
    7986
    8087    BasicBlock * entry_block = iBuilder->GetInsertBlock();
    81     BasicBlock * matches_test_block = BasicBlock::Create(ctxt, "matches_test_block", sFunction, 0);
    82     BasicBlock * process_matches_loop_entry = BasicBlock::Create(ctxt, "process_matches_loop", sFunction, 0);
    83     BasicBlock * prior_breaks_block = BasicBlock::Create(ctxt, "prior_breaks_block", sFunction, 0);
    84     BasicBlock * loop_final_block = BasicBlock::Create(ctxt, "loop_final_block", sFunction, 0);
    85     BasicBlock * matches_done_block = BasicBlock::Create(ctxt, "matches_done_block", sFunction, 0);
    86     BasicBlock * remaining_breaks_block = BasicBlock::Create(ctxt, "remaining_breaks_block", sFunction, 0);
    87     BasicBlock * return_block = BasicBlock::Create(ctxt, "return_block", sFunction, 0);
    88        
    89        
     88    BasicBlock * matches_test_block = BasicBlock::Create(ctxt, "matches_test_block", function, 0);
     89    BasicBlock * process_matches_loop_entry = BasicBlock::Create(ctxt, "process_matches_loop", function, 0);
     90    BasicBlock * prior_breaks_block = BasicBlock::Create(ctxt, "prior_breaks_block", function, 0);
     91    BasicBlock * loop_final_block = BasicBlock::Create(ctxt, "loop_final_block", function, 0);
     92    BasicBlock * matches_done_block = BasicBlock::Create(ctxt, "matches_done_block", function, 0);
     93    BasicBlock * remaining_breaks_block = BasicBlock::Create(ctxt, "remaining_breaks_block", function, 0);
     94    BasicBlock * return_block = BasicBlock::Create(ctxt, "return_block", function, 0);
     95
     96
    9097    // The match scanner works with a loop involving four variables:
    9198    // (a) the bit stream scanword of matches marking the ends of selected records,
    9299    // (b) the bit stream scanword of record_breaks marking the ends of all records,
    93     // (c) the integer lastRecordNum indicating the number of records processed so far, 
     100    // (c) the integer lastRecordNum indicating the number of records processed so far,
    94101    // (d) the index lastRecordStart indicating the file position of the last record.
    95102    // We set up a loop structure, in which a set of 4 phi nodes initialize these
     
    97104    // the loop body.
    98105
    99    
     106
    100107    iBuilder->CreateBr(matches_test_block);
    101108
    102     // LOOP Test Block 
     109    // LOOP Test Block
    103110    iBuilder->SetInsertPoint(matches_test_block);
    104111    PHINode * matches_phi = iBuilder->CreatePHI(T, 2, "matches");
     
    112119    Value * have_matches_cond = iBuilder->CreateICmpNE(matches_phi, ConstantInt::get(T, 0));
    113120    iBuilder->CreateCondBr(have_matches_cond, process_matches_loop_entry, matches_done_block);
    114    
     121
    115122    // LOOP BODY
    116123    // The loop body is entered if we have more matches to process.
    117124    iBuilder->SetInsertPoint(process_matches_loop_entry);
    118125    Value * prior_breaks = iBuilder->CreateAnd(generateForwardZeroesMask(iBuilder, matches_phi), record_breaks_phi);
    119     // Within the loop we have a conditional block that is executed if there are any prior 
     126    // Within the loop we have a conditional block that is executed if there are any prior
    120127    // record breaks.
    121128    Value * prior_breaks_cond = iBuilder->CreateICmpNE(prior_breaks, ConstantInt::get(T, 0));
     
    130137    Value * matchRecordStart = iBuilder->CreateAdd(scanwordPos, iBuilder->CreateSub(width, reverseDistance));
    131138    iBuilder->CreateBr(loop_final_block);
    132    
     139
    133140    // LOOP FINAL BLOCK
    134141    // The prior breaks, if any have been counted.  Set up phi nodes for the recordNum
     
    143150    Value * matchRecordEnd = iBuilder->CreateAdd(scanwordPos, generateCountForwardZeroes(iBuilder, matches_phi));
    144151
    145     Value* filebufptr = kBuilder->getKernelInternalState(this_input_parm, 7);
    146     Value* filesize = kBuilder->getKernelInternalState(this_input_parm, 8);
    147     Value* filenameptr = kBuilder->getKernelInternalState(this_input_parm, 9);
     152    Value* filebuf_gep = iBuilder->CreateGEP(this_input_parm, {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(7)});
     153    Value* filebufptr = iBuilder->CreateLoad(filebuf_gep, "filebuf");
     154
     155    Value* filesize_gep = iBuilder->CreateGEP(this_input_parm, {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(8)});
     156    Value* filesize = iBuilder->CreateLoad(filesize_gep, "filensize");
     157
     158    Value* filename_gep = iBuilder->CreateGEP(this_input_parm, {iBuilder->getInt64(0), iBuilder->getInt32(0), iBuilder->getInt32(9)});
     159    Value* filenameptr = iBuilder->CreateLoad(filename_gep, "filename");
    148160
    149161    if(isNameExpression)
     
    158170    recordStart_phi->addIncoming(matchRecordStart_phi, loop_final_block);
    159171    iBuilder->CreateBr(matches_test_block);
    160    
    161    
     172
     173
    162174    // LOOP EXIT/MATCHES_DONE
    163175    iBuilder->SetInsertPoint(matches_done_block);
     
    165177    Value * more_breaks_cond = iBuilder->CreateICmpNE(record_breaks_phi, ConstantInt::get(T, 0));
    166178    iBuilder->CreateCondBr(more_breaks_cond, remaining_breaks_block, return_block);
    167    
     179
    168180    // REMAINING_BREAKS_BLOCK: process remaining record breaks after all matches are processed
    169181    iBuilder->SetInsertPoint(remaining_breaks_block);
     
    173185    Value * pendingLineStart = iBuilder->CreateAdd(scanwordPos, iBuilder->CreateSub(width, reverseZeroes));
    174186    iBuilder->CreateBr(return_block);
    175    
     187
    176188    // RETURN block
    177189    iBuilder->SetInsertPoint(return_block);
     
    186198    retVal = iBuilder->CreateInsertValue(retVal, finalRecordCount_phi, 1);
    187199    iBuilder->CreateRet(retVal);
    188    
    189 }
    190 
    191 
    192 void generateScanMatch(Module * m, IDISA::IDISA_Builder * iBuilder, int scanwordBitWidth, KernelBuilder * kBuilder, bool isNameExpression){
    193    
    194    
    195     Type * T = iBuilder->getIntNTy(scanwordBitWidth);
     200
     201    return function;
     202}
     203
     204
     205void generateScanMatch(Module * m, IDISA::IDISA_Builder * iBuilder, unsigned scanWordBitWidth, KernelBuilder * kBuilder, bool isNameExpression){
     206
     207
     208    Type * T = iBuilder->getIntNTy(scanWordBitWidth);
    196209    Type * S = PointerType::get(iBuilder->getIntNTy(8), 0);
    197     int fieldCount = iBuilder->getBitBlockWidth()/scanwordBitWidth;
     210    const unsigned fieldCount = iBuilder->getBitBlockWidth() / scanWordBitWidth;
    198211    Type * scanwordVectorType =  VectorType::get(T, fieldCount);
    199212
    200     kBuilder->addKernelInputStream(1, "matches");
    201     kBuilder->addKernelInputStream(1, "breaks");
     213    kBuilder->addInputStream(1, "matches");
     214    kBuilder->addInputStream(1, "breaks");
    202215    //use index
    203     int blockPosIdx = kBuilder->extendKernelInternalStateType(T);
    204     int lineStartIdx = kBuilder->extendKernelInternalStateType(T);
    205     int lineNumIdx = kBuilder->extendKernelInternalStateType(T);
    206     kBuilder->extendKernelInternalStateType(S);
    207     kBuilder->extendKernelInternalStateType(T);
    208     kBuilder->extendKernelInternalStateType(S);
    209 
    210     int segBlocks = kBuilder->getSegmentBlocks();
    211 
    212     kBuilder->PrepareDoBlockFunction();
    213 
    214     generateScanWordRoutine(m, iBuilder, kBuilder, scanwordBitWidth, isNameExpression);
    215 
    216     struct Inputs inputs = kBuilder->openDoBlock();
    217     struct Outputs outputs;   
     216    unsigned blockPosIdx = kBuilder->addInternalStateType(T);
     217    unsigned lineStartIdx = kBuilder->addInternalStateType(T);
     218    unsigned lineNumIdx = kBuilder->addInternalStateType(T);
     219    kBuilder->addInternalStateType(S);
     220    kBuilder->addInternalStateType(T);
     221    kBuilder->addInternalStateType(S);
     222
     223    Function * function = kBuilder->prepareFunction();
     224
     225    Type * kernelStuctType = PointerType::get(kBuilder->getKernelStructType(), 0);
     226
     227    Function * scanWordFunction = generateScanWordRoutine(m, iBuilder, scanWordBitWidth, kernelStuctType, isNameExpression);
     228
     229    iBuilder->SetInsertPoint(&function->getEntryBlock());
     230
    218231    Value * kernelStuctParam = kBuilder->getKernelStructParam();
    219    
    220     Value * scanwordPos = kBuilder->getKernelInternalState(kernelStuctParam, blockPosIdx);
    221     Value * recordStart = kBuilder->getKernelInternalState(kernelStuctParam, lineStartIdx);
    222     Value * recordNum = kBuilder->getKernelInternalState(kernelStuctParam, lineNumIdx);
     232
     233    Value * scanwordPos = iBuilder->CreateBlockAlignedLoad(kBuilder->getInternalState(blockPosIdx));
     234    Value * recordStart = iBuilder->CreateBlockAlignedLoad(kBuilder->getInternalState(lineStartIdx));
     235    Value * recordNum = iBuilder->CreateBlockAlignedLoad(kBuilder->getInternalState(lineNumIdx));
    223236    Value * wordResult = nullptr;
    224237
    225     Function * wordScanFcn = m->getFunction("scan_matches_in_scanword");
    226     for(int j=0; j<segBlocks; j++){
    227         Value * matchWordVector = iBuilder->CreateBitCast(inputs.streams[j][0], scanwordVectorType);
    228         Value * breakWordVector = iBuilder->CreateBitCast(inputs.streams[j][1], scanwordVectorType);
    229         for(int i=0; i<segBlocks*iBuilder->getBitBlockWidth()/scanwordBitWidth; i++){
    230 
     238    const unsigned segmentBlocks = kBuilder->getSegmentBlocks();
     239    const unsigned scanWordBlocks =  segmentBlocks * fieldCount;
     240
     241    for(unsigned j = 0; j < segmentBlocks; ++j) {
     242
     243        Value * matchWordVector = iBuilder->CreateBitCast(iBuilder->CreateBlockAlignedLoad(kBuilder->getInputStream(0)), scanwordVectorType);
     244        Value * breakWordVector = iBuilder->CreateBitCast(iBuilder->CreateBlockAlignedLoad(kBuilder->getInputStream(1)), scanwordVectorType);
     245
     246        for(unsigned i = 0; i < scanWordBlocks; ++i){
    231247            Value * matchWord = iBuilder->CreateExtractElement(matchWordVector, ConstantInt::get(T, i));
    232248            Value * recordBreaksWord = iBuilder->CreateExtractElement(breakWordVector, ConstantInt::get(T, i));
    233             wordResult = iBuilder->CreateCall(wordScanFcn, std::vector<Value *>({kernelStuctParam, matchWord, recordBreaksWord, scanwordPos, recordStart, recordNum}));
    234             scanwordPos = iBuilder->CreateAdd(scanwordPos, ConstantInt::get(T, scanwordBitWidth));
     249            wordResult = iBuilder->CreateCall(scanWordFunction, std::vector<Value *>({kernelStuctParam, matchWord, recordBreaksWord, scanwordPos, recordStart, recordNum}));
     250            scanwordPos = iBuilder->CreateAdd(scanwordPos, ConstantInt::get(T, scanWordBitWidth));
    235251            recordStart = iBuilder->CreateExtractValue(wordResult, std::vector<unsigned>({0}));
    236252            recordNum = iBuilder->CreateExtractValue(wordResult, std::vector<unsigned>({1}));
    237253        }
     254        kBuilder->increment();
    238255    }
    239256
    240     kBuilder->changeKernelInternalState(kernelStuctParam, blockPosIdx, scanwordPos);
    241     kBuilder->changeKernelInternalState(kernelStuctParam, lineStartIdx, recordStart);
    242     kBuilder->changeKernelInternalState(kernelStuctParam, lineNumIdx, recordNum);
    243 
    244     kBuilder->closeDoBlock(outputs);
    245 
    246     kBuilder->finalizeMethods();
    247 }
    248 
    249 
    250 
     257    kBuilder->setInternalState(blockPosIdx, scanwordPos);
     258    kBuilder->setInternalState(lineStartIdx, recordStart);
     259    kBuilder->setInternalState(lineNumIdx, recordNum);
     260
     261    kBuilder->finalize();
     262}
  • icGREP/icgrep-devel/icgrep/kernels/scanmatchgen.h

    r4939 r4959  
    1 #ifndef SCANMATCHGEN_H
    2 #define SCANMATCHGEN_H
    31/*
    42 *  Copyright (c) 2016 International Characters.
    53 *  This software is licensed to the public under the Open Software License 3.0.
    64 */
     5#ifndef SCANMATCHGEN_H
     6#define SCANMATCHGEN_H
    77
     8class KernelBuilder;
    89
    9 #include <IDISA/idisa_builder.h>
    10 #include <llvm/IR/Function.h>
    11 #include <llvm/IR/Module.h>
    12        
    13 void generateScanBitBlockRoutine(Module * m, IDISA::IDISA_Builder * iBuilder, int segBitWidth, Type * kernelStuctType, bool isNameExpression);
     10namespace llvm { class Module; }
    1411
    15 void generateScanMatch(Module * m, IDISA::IDISA_Builder * iBuilder, int segBitWidth, KernelBuilder * kBuilder, bool isNameExpression);
     12namespace IDISA { class IDISA_Builder; }
     13
     14void generateScanMatch(llvm::Module * m, IDISA::IDISA_Builder * iBuilder, unsigned scanWordBitWidth, KernelBuilder * kBuilder, bool isNameExpression);
    1615
    1716#endif // SCANMATCHGEN_H
Note: See TracChangeset for help on using the changeset viewer.