Ignore:
Timestamp:
Mar 29, 2017, 2:29:52 PM (2 years ago)
Author:
nmedfort
Message:

Support for stdin. Needs more testing.

File:
1 edited

Legend:

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

    r5350 r5377  
    3838}
    3939       
     40
     41
    4042void ScanMatchKernel::generateDoBlockMethod() {
    4143
    42     auto savePoint = iBuilder->saveIP();
    43     Function * scanWordFunction = generateScanWordRoutine(iBuilder->getModule());
    44     iBuilder->restoreIP(savePoint);
    45 
    46     IntegerType * T = iBuilder->getSizeTy();
    47     const unsigned fieldCount = iBuilder->getBitBlockWidth() / T->getBitWidth();
    48     Type * scanwordVectorType =  VectorType::get(T, fieldCount);
    49     Value * blockNo = getScalarField("BlockNo");
    50     Value * scanwordPos = iBuilder->CreateMul(blockNo, ConstantInt::get(blockNo->getType(), iBuilder->getBitBlockWidth()));   
    51     Value * recordStart = getScalarField("LineStart");
    52     Value * recordNum = getScalarField("LineNum");
    53     Value * matches = loadInputStreamBlock("matchResult", iBuilder->getInt32(0));
    54     Value * linebreaks = loadInputStreamBlock("lineBreak", iBuilder->getInt32(0));
    55     Value * matchWordVector = iBuilder->CreateBitCast(matches, scanwordVectorType);
    56     Value * breakWordVector = iBuilder->CreateBitCast(linebreaks, scanwordVectorType);
    57     for(unsigned i = 0; i < fieldCount; ++i){
    58         Value * matchWord = iBuilder->CreateExtractElement(matchWordVector, ConstantInt::get(T, i));
    59         Value * recordBreaksWord = iBuilder->CreateExtractElement(breakWordVector, ConstantInt::get(T, i));
    60         Value * wordResult = iBuilder->CreateCall(scanWordFunction, {getSelf(), matchWord, recordBreaksWord, scanwordPos, recordStart, recordNum});
    61         scanwordPos = iBuilder->CreateAdd(scanwordPos, ConstantInt::get(T, T->getBitWidth()));
    62         recordStart = iBuilder->CreateExtractValue(wordResult, std::vector<unsigned>({0}));
    63         recordNum = iBuilder->CreateExtractValue(wordResult, std::vector<unsigned>({1}));
    64     }
    65     setScalarField("LineStart", recordStart);
    66     setScalarField("LineNum", recordNum);
    67     setScalarField("BlockNo", iBuilder->CreateAdd(blockNo, iBuilder->getSize(1)));
    68 }
    69 
    70    
    71 Function * ScanMatchKernel::generateScanWordRoutine(Module * m) const {
    72     Function * function = m->getFunction("scan_matches_in_scanword");
    73     if (LLVM_UNLIKELY(function != nullptr)) {
    74         return function;
    75     }
    76    
    77     LLVMContext & ctxt = m->getContext();
    78 
    79     IntegerType * T = iBuilder->getSizeTy();
    80     Type * S = PointerType::get(iBuilder->getIntNTy(8), 0);
    81     Type * returnType = StructType::get(ctxt, std::vector<Type *>({T, T}));
    82     FunctionType * functionType = FunctionType::get(returnType, std::vector<Type *>({PointerType::get(mKernelStateType, 0), T, T, T, T, T}), false);
    83    
    84     SmallVector<AttributeSet, 6> Attrs;
    85     Attrs.push_back(AttributeSet::get(ctxt, ~0U, std::vector<Attribute::AttrKind>({ Attribute::NoUnwind, Attribute::UWTable })));
    86     Attrs.push_back(AttributeSet::get(ctxt, 1, std::vector<Attribute::AttrKind>({})));
    87     Attrs.push_back(AttributeSet::get(ctxt, 2, std::vector<Attribute::AttrKind>({})));
    88     Attrs.push_back(AttributeSet::get(ctxt, 3, std::vector<Attribute::AttrKind>({})));
    89     Attrs.push_back(AttributeSet::get(ctxt, 4, std::vector<Attribute::AttrKind>({})));
    90     Attrs.push_back(AttributeSet::get(ctxt, 5, std::vector<Attribute::AttrKind>({})));
    91     AttributeSet AttrSet = AttributeSet::get(ctxt, Attrs);
    92    
    93     function = Function::Create(functionType, GlobalValue::ExternalLinkage, "scan_matches_in_scanword", m);
    94     function->setCallingConv(CallingConv::C);
    95     function->setAttributes(AttrSet);
    96     function->addFnAttr(llvm::Attribute::AlwaysInline);
    97    
    98     Function::arg_iterator args = function->arg_begin();
    99     Value * instance = &*(args++);
    100     instance->setName("this");
    101     Value * matches_input_parm = &*(args++);
    102     matches_input_parm->setName("matches");
    103     Value * record_breaks_input_parm = &*(args++);
    104     record_breaks_input_parm->setName("breaks");
    105     Value * scanwordPos = &*(args++);
    106     scanwordPos->setName("scanwordPos");
    107     Value * recordStart_input_parm = &*(args++);
    108     recordStart_input_parm->setName("pendingLineStart");
    109     Value * recordNum_input_parm = &*(args++);
    110     recordNum_input_parm->setName("lineNum");
    111    
     44    Module * const m = iBuilder->getModule();
     45    BasicBlock * const entryBlock = iBuilder->GetInsertBlock();
     46    BasicBlock * const scanWordIteration = CreateBasicBlock("ScanWordIteration");
     47    BasicBlock * const matches_test_block = CreateBasicBlock("matches_test_block");
     48    BasicBlock * const processMatchesEntry = CreateBasicBlock("process_matches_loop");
     49    BasicBlock * const prior_breaks_block = CreateBasicBlock("prior_breaks_block");
     50    BasicBlock * const loop_final_block = CreateBasicBlock("loop_final_block");
     51    BasicBlock * const processMatchesExit = CreateBasicBlock("matches_done_block");
     52    BasicBlock * const remaining_breaks_block = CreateBasicBlock("remaining_breaks_block");
     53    BasicBlock * const return_block = CreateBasicBlock("return_block");
     54    BasicBlock * const scanWordExit = CreateBasicBlock("ScanWordExit");
     55    IntegerType * const sizeTy = iBuilder->getSizeTy();
     56    PointerType * const codeUnitTy = iBuilder->getIntNTy(mCodeUnitWidth)->getPointerTo();
     57    const unsigned fieldCount = iBuilder->getBitBlockWidth() / sizeTy->getBitWidth();
     58    VectorType * const scanwordVectorType =  VectorType::get(sizeTy, fieldCount);
     59    Value * const blockNo = getScalarField("BlockNo");
     60    Value * const scanwordPos = iBuilder->CreateMul(blockNo, ConstantInt::get(blockNo->getType(), iBuilder->getBitBlockWidth()));
     61    Value * const lastRecordStart = getScalarField("LineStart");
     62    Value * const lastRecordNum = getScalarField("LineNum");
     63    Value * const inputStream = iBuilder->CreatePointerCast(getRawInputPointer("InputStream", iBuilder->getInt32(0), iBuilder->getInt32(0)), codeUnitTy);
     64
     65    Value * fileSize = iBuilder->CreateAdd(getProcessedItemCount("InputStream"), getScalarField("PendingBytes"));
     66
    11267    Constant * matchProcessor = nullptr;
     68    Value * fileIdx = nullptr;
    11369    switch (mGrepType) {
    11470        case GrepType::Normal:
    115             matchProcessor = m->getOrInsertFunction("wrapped_report_match", iBuilder->getVoidTy(), T, T, T, S, T, T, nullptr);
     71            fileIdx = getScalarField("FileIdx");
     72            matchProcessor = m->getOrInsertFunction("wrapped_report_match" + std::to_string(mCodeUnitWidth), iBuilder->getVoidTy(), sizeTy, sizeTy, sizeTy, codeUnitTy, sizeTy, sizeTy, nullptr);
    11673            break;
    11774        case GrepType::NameExpression:
    118             matchProcessor = m->getOrInsertFunction("insert_codepoints", iBuilder->getVoidTy(), T, T, T, S, nullptr);
     75            matchProcessor = m->getOrInsertFunction("insert_codepoints", iBuilder->getVoidTy(), sizeTy, sizeTy, sizeTy, codeUnitTy, nullptr);
    11976            break;
    12077        case GrepType::PropertyValue:
    121             matchProcessor = m->getOrInsertFunction("insert_property_values", iBuilder->getVoidTy(), T, T, T, S, nullptr);
     78            matchProcessor = m->getOrInsertFunction("insert_property_values", iBuilder->getVoidTy(), sizeTy, sizeTy, sizeTy, codeUnitTy, nullptr);
    12279            break;
    12380        default: llvm_unreachable("unknown grep type");
    12481    }
    125     iBuilder->SetInsertPoint(BasicBlock::Create(ctxt, "entry", function,0));
    126    
    127     BasicBlock * entry_block = iBuilder->GetInsertBlock();
    128     BasicBlock * matches_test_block = BasicBlock::Create(ctxt, "matches_test_block", function, 0);
    129     BasicBlock * process_matches_loop_entry = BasicBlock::Create(ctxt, "process_matches_loop", function, 0);
    130     BasicBlock * prior_breaks_block = BasicBlock::Create(ctxt, "prior_breaks_block", function, 0);
    131     BasicBlock * loop_final_block = BasicBlock::Create(ctxt, "loop_final_block", function, 0);
    132     BasicBlock * matches_done_block = BasicBlock::Create(ctxt, "matches_done_block", function, 0);
    133     BasicBlock * remaining_breaks_block = BasicBlock::Create(ctxt, "remaining_breaks_block", function, 0);
    134     BasicBlock * return_block = BasicBlock::Create(ctxt, "return_block", function, 0);
    135    
    136    
    137     // The match scanner works with a loop involving four variables:
    138     // (a) the bit stream scanword of matches marking the ends of selected records,
    139     // (b) the bit stream scanword of record_breaks marking the ends of all records,
    140     // (c) the integer lastRecordNum indicating the number of records processed so far,
    141     // (d) the index lastRecordStart indicating the file position of the last record.
    142     // We set up a loop structure, in which a set of 4 phi nodes initialize these
    143     // variables from either the input to the scanner or the computed values within
    144     // the loop body.
    145    
    146    
    147     iBuilder->CreateBr(matches_test_block);
    148    
    149     // LOOP Test Block
    150     iBuilder->SetInsertPoint(matches_test_block);
    151     PHINode * matches_phi = iBuilder->CreatePHI(T, 2, "matches");
    152     PHINode * record_breaks_phi = iBuilder->CreatePHI(T, 2, "record_breaks");
    153     PHINode * recordNum_phi = iBuilder->CreatePHI(T, 2, "recordNum");
    154     PHINode * recordStart_phi = iBuilder->CreatePHI(T, 2, "recordStart");
    155     matches_phi->addIncoming(matches_input_parm, entry_block);
    156     record_breaks_phi->addIncoming(record_breaks_input_parm, entry_block);
    157     recordNum_phi->addIncoming(recordNum_input_parm, entry_block);
    158     recordStart_phi->addIncoming(recordStart_input_parm, entry_block);
    159     Value * have_matches_cond = iBuilder->CreateICmpNE(matches_phi, ConstantInt::get(T, 0));
    160     iBuilder->CreateCondBr(have_matches_cond, process_matches_loop_entry, matches_done_block);
    161    
    162     // LOOP BODY
    163     // The loop body is entered if we have more matches to process.
    164     iBuilder->SetInsertPoint(process_matches_loop_entry);
    165     Value * prior_breaks = iBuilder->CreateAnd(generateForwardZeroesMask(iBuilder, matches_phi), record_breaks_phi);
    166     // Within the loop we have a conditional block that is executed if there are any prior
    167     // record breaks.
    168     Value * prior_breaks_cond = iBuilder->CreateICmpNE(prior_breaks, ConstantInt::get(T, 0));
    169     iBuilder->CreateCondBr(prior_breaks_cond, prior_breaks_block, loop_final_block);
    170    
    171     // PRIOR_BREAKS_BLOCK
    172     // If there are prior breaks, we count them and compute the record start position.
    173     iBuilder->SetInsertPoint(prior_breaks_block);
    174     Value * matchRecordNum = iBuilder->CreateAdd(generatePopcount(iBuilder, prior_breaks), recordNum_phi);
    175     Value * reverseDistance = generateCountReverseZeroes(iBuilder, prior_breaks);
    176     Value * width = ConstantInt::get(T, T->getBitWidth());
    177     Value * matchRecordStart = iBuilder->CreateAdd(scanwordPos, iBuilder->CreateSub(width, reverseDistance));
    178     iBuilder->CreateBr(loop_final_block);
    179    
    180     // LOOP FINAL BLOCK
    181     // The prior breaks, if any have been counted.  Set up phi nodes for the recordNum
    182     // and recortStart depending on whether the conditional execution of prior_breaks_block.
    183     iBuilder->SetInsertPoint(loop_final_block);
    184     PHINode * matchRecordNum_phi = iBuilder->CreatePHI(T, 2, "matchRecordNum");
    185     PHINode * matchRecordStart_phi = iBuilder->CreatePHI(T, 2, "matchRecordStart");
    186     matchRecordNum_phi->addIncoming(recordNum_phi, process_matches_loop_entry);
    187     matchRecordNum_phi->addIncoming(matchRecordNum, prior_breaks_block);
    188     matchRecordStart_phi->addIncoming(recordStart_phi, process_matches_loop_entry);
    189     matchRecordStart_phi->addIncoming(matchRecordStart, prior_breaks_block);   
    190     Value * matchRecordEnd = iBuilder->CreateAdd(scanwordPos, generateCountForwardZeroes(iBuilder, matches_phi));
    191    
    192 
    193     Value * fileBuf = getScalarField(instance, "FileBuf");
    194     switch (mGrepType) {
    195         case GrepType::Normal:
    196         {
    197             Value * fileSize = getScalarField(instance, "FileSize");
    198             Value * fileIdx = getScalarField(instance, "FileIdx");
    199             iBuilder->CreateCall(matchProcessor, std::vector<Value *>({matchRecordNum_phi, matchRecordStart_phi, matchRecordEnd, fileBuf, fileSize, fileIdx}));
    200             break;
    201         }
    202         case GrepType::NameExpression:
    203         case GrepType::PropertyValue:
    204             iBuilder->CreateCall(matchProcessor, std::vector<Value *>({matchRecordNum_phi, matchRecordStart_phi, matchRecordEnd, fileBuf}));
    205             break;
    206         default: llvm_unreachable("unknown grep type");
    207     }
    208    
    209     Value * remaining_matches = generateResetLowestBit(iBuilder, matches_phi);
    210     Value * remaining_breaks = iBuilder->CreateXor(record_breaks_phi, prior_breaks);
    211     matches_phi->addIncoming(remaining_matches, loop_final_block);
    212     record_breaks_phi->addIncoming(remaining_breaks, loop_final_block);
    213     recordNum_phi->addIncoming(matchRecordNum_phi, loop_final_block);
    214     recordStart_phi->addIncoming(matchRecordStart_phi, loop_final_block);
    215     iBuilder->CreateBr(matches_test_block);
    216    
    217    
    218     // LOOP EXIT/MATCHES_DONE
    219     iBuilder->SetInsertPoint(matches_done_block);
    220     // When the matches are done, there may be additional record breaks remaining
    221     Value * more_breaks_cond = iBuilder->CreateICmpNE(record_breaks_phi, ConstantInt::get(T, 0));
    222     iBuilder->CreateCondBr(more_breaks_cond, remaining_breaks_block, return_block);
    223    
    224     // REMAINING_BREAKS_BLOCK: process remaining record breaks after all matches are processed
    225     iBuilder->SetInsertPoint(remaining_breaks_block);
    226     Value * break_count = generatePopcount(iBuilder, record_breaks_phi);
    227     Value * final_record_num = iBuilder->CreateAdd(recordNum_phi, break_count);
    228     Value * reverseZeroes = generateCountReverseZeroes(iBuilder, record_breaks_phi);
    229     Value * pendingLineStart = iBuilder->CreateAdd(scanwordPos, iBuilder->CreateSub(width, reverseZeroes));
    230     iBuilder->CreateBr(return_block);
    231    
    232     // RETURN block
    233     iBuilder->SetInsertPoint(return_block);
    234     PHINode * finalRecordCount_phi = iBuilder->CreatePHI(T, 2, "finalRecordCount");
    235     PHINode * finalRecordStart_phi = iBuilder->CreatePHI(T, 2, "finalRecordStart");
    236     finalRecordCount_phi->addIncoming(recordNum_phi, matches_done_block);
    237     finalRecordCount_phi->addIncoming(final_record_num, remaining_breaks_block);
    238     finalRecordStart_phi->addIncoming(recordStart_phi, matches_done_block);
    239     finalRecordStart_phi->addIncoming(pendingLineStart, remaining_breaks_block);
    240     Value * retVal = UndefValue::get(returnType);
    241     retVal = iBuilder->CreateInsertValue(retVal, finalRecordStart_phi, 0);
    242     retVal = iBuilder->CreateInsertValue(retVal, finalRecordCount_phi, 1);
    243     iBuilder->CreateRet(retVal);
    244    
    245     return function;
    246 }
    247 
    248 ScanMatchKernel::ScanMatchKernel(IDISA::IDISA_Builder * iBuilder, GrepType grepType)
    249 : BlockOrientedKernel(iBuilder, "scanMatch",
    250     {Binding{iBuilder->getStreamSetTy(1, 1), "matchResult"}, Binding{iBuilder->getStreamSetTy(1, 1), "lineBreak"}},
     82    Value * const matchesPtr = getInputStreamBlockPtr("matchResult", iBuilder->getInt32(0));
     83    Value * const matches = iBuilder->CreateBitCast(iBuilder->CreateBlockAlignedLoad(matchesPtr), scanwordVectorType);
     84
     85    Value * const linebreaksPtr = getInputStreamBlockPtr("lineBreak", iBuilder->getInt32(0));
     86    Value * const linebreaks = iBuilder->CreateBitCast(iBuilder->CreateBlockAlignedLoad(linebreaksPtr), scanwordVectorType);
     87
     88    iBuilder->CreateBr(scanWordIteration);
     89
     90    iBuilder->SetInsertPoint(scanWordIteration);
     91
     92        // while (phiIndex < words per stride)
     93        PHINode * const phiIndex = iBuilder->CreatePHI(iBuilder->getInt32Ty(), 2, "index");
     94        phiIndex->addIncoming(iBuilder->getInt32(0), entryBlock);
     95        PHINode * const phiScanwordPos = iBuilder->CreatePHI(scanwordPos->getType(), 2, "pos");
     96        phiScanwordPos->addIncoming(scanwordPos, entryBlock);
     97        PHINode * const phiLineStart = iBuilder->CreatePHI(lastRecordStart->getType(), 2, "recordstart");
     98        phiLineStart->addIncoming(lastRecordStart, entryBlock);
     99        PHINode * const phiLineNum = iBuilder->CreatePHI(lastRecordNum->getType(), 2, "recordnum");
     100        phiLineNum->addIncoming(lastRecordNum, entryBlock);
     101        Value * const matchWord = iBuilder->CreateExtractElement(matches, phiIndex);
     102        Value * const recordBreaks = iBuilder->CreateExtractElement(linebreaks, phiIndex);
     103
     104        // The match scanner works with a loop involving four variables:
     105        // (a) the bit stream scanword of matches marking the ends of selected records,
     106        // (b) the bit stream scanword of record_breaks marking the ends of all records,
     107        // (c) the integer lastRecordNum indicating the number of records processed so far,
     108        // (d) the index lastRecordStart indicating the file position of the last record.
     109        // We set up a loop structure, in which a set of 4 phi nodes initialize these
     110        // variables from either the input to the scanner or the computed values within
     111        // the loop body.
     112
     113        iBuilder->CreateBr(matches_test_block);
     114
     115        // LOOP Test Block
     116        iBuilder->SetInsertPoint(matches_test_block);
     117        PHINode * phiMatchWord = iBuilder->CreatePHI(sizeTy, 2, "matches");
     118        PHINode * phiRecordBreaks = iBuilder->CreatePHI(sizeTy, 2, "recordbreaks");
     119        PHINode * phiRecordStart = iBuilder->CreatePHI(sizeTy, 2, "recordstart");
     120        PHINode * phiRecordNum = iBuilder->CreatePHI(sizeTy, 2, "recordnum");
     121        phiMatchWord->addIncoming(matchWord, scanWordIteration);
     122        phiRecordBreaks->addIncoming(recordBreaks, scanWordIteration);
     123        phiRecordNum->addIncoming(phiLineNum, scanWordIteration);
     124        phiRecordStart->addIncoming(phiLineStart, scanWordIteration);
     125        Value * anyMatches = iBuilder->CreateICmpNE(phiMatchWord, ConstantInt::getNullValue(sizeTy));
     126        iBuilder->CreateCondBr(anyMatches, processMatchesEntry, processMatchesExit);
     127
     128            // LOOP BODY
     129            // The loop body is entered if we have more matches to process.
     130            iBuilder->SetInsertPoint(processMatchesEntry);
     131            Value * prior_breaks = iBuilder->CreateAnd(generateForwardZeroesMask(iBuilder, phiMatchWord), phiRecordBreaks);
     132            // Within the loop we have a conditional block that is executed if there are any prior record breaks.
     133            Value * prior_breaks_cond = iBuilder->CreateICmpNE(prior_breaks, ConstantInt::getNullValue(sizeTy));
     134            iBuilder->CreateCondBr(prior_breaks_cond, prior_breaks_block, loop_final_block);
     135
     136                // PRIOR_BREAKS_BLOCK
     137                // If there are prior breaks, we count them and compute the record start position.
     138                iBuilder->SetInsertPoint(prior_breaks_block);
     139                Value * matchedRecordNum = iBuilder->CreateAdd(generatePopcount(iBuilder, prior_breaks), phiRecordNum);
     140                Value * reverseDistance = generateCountReverseZeroes(iBuilder, prior_breaks);
     141                Value * width = ConstantInt::get(sizeTy, sizeTy->getBitWidth());
     142                Value * priorRecordStart = iBuilder->CreateAdd(phiScanwordPos, iBuilder->CreateSub(width, reverseDistance));
     143                iBuilder->CreateBr(loop_final_block);
     144
     145            // LOOP FINAL BLOCK
     146            // The prior breaks, if any have been counted.  Set up phi nodes for the recordNum
     147            // and recortStart depending on whether the conditional execution of prior_breaks_block.
     148            iBuilder->SetInsertPoint(loop_final_block);
     149            PHINode * matchRecordNum = iBuilder->CreatePHI(sizeTy, 2, "matchRecordNum");
     150            matchRecordNum->addIncoming(phiRecordNum, processMatchesEntry);
     151            matchRecordNum->addIncoming(matchedRecordNum, prior_breaks_block);
     152            phiRecordNum->addIncoming(matchRecordNum, loop_final_block);
     153
     154            PHINode * matchRecordStart = iBuilder->CreatePHI(sizeTy, 2, "matchRecordStart");
     155            matchRecordStart->addIncoming(phiRecordStart, processMatchesEntry);
     156            matchRecordStart->addIncoming(priorRecordStart, prior_breaks_block);
     157            phiRecordStart->addIncoming(matchRecordStart, loop_final_block);
     158
     159            Value * matchRecordEnd = iBuilder->CreateAdd(phiScanwordPos, generateCountForwardZeroes(iBuilder, phiMatchWord));
     160            switch (mGrepType) {
     161                case GrepType::Normal:
     162                    iBuilder->CreateCall(matchProcessor, {matchRecordNum, matchRecordStart, matchRecordEnd, inputStream, fileSize, fileIdx});
     163                    break;
     164                case GrepType::NameExpression:
     165                case GrepType::PropertyValue:
     166                    iBuilder->CreateCall(matchProcessor, {matchRecordNum, matchRecordStart, matchRecordEnd, inputStream});
     167                    break;
     168                default: break;
     169            }
     170
     171            Value * remaining_matches = generateResetLowestBit(iBuilder, phiMatchWord);
     172            phiMatchWord->addIncoming(remaining_matches, loop_final_block);
     173
     174            Value * remaining_breaks = iBuilder->CreateXor(phiRecordBreaks, prior_breaks);
     175            phiRecordBreaks->addIncoming(remaining_breaks, loop_final_block);
     176
     177            iBuilder->CreateBr(matches_test_block);
     178
     179        // LOOP EXIT/MATCHES_DONE
     180        iBuilder->SetInsertPoint(processMatchesExit);
     181        // When the matches are done, there may be additional record breaks remaining
     182        Value * more_breaks_cond = iBuilder->CreateICmpNE(phiRecordBreaks, ConstantInt::getNullValue(sizeTy));
     183        iBuilder->CreateCondBr(more_breaks_cond, remaining_breaks_block, return_block);
     184
     185            // REMAINING_BREAKS_BLOCK: process remaining record breaks after all matches are processed
     186            iBuilder->SetInsertPoint(remaining_breaks_block);
     187            Value * break_count = generatePopcount(iBuilder, phiRecordBreaks);
     188            Value * final_record_num = iBuilder->CreateAdd(phiRecordNum, break_count);
     189            Value * reverseZeroes = generateCountReverseZeroes(iBuilder, phiRecordBreaks);
     190            Value * pendingLineStart = iBuilder->CreateAdd(phiScanwordPos, iBuilder->CreateSub(width, reverseZeroes));
     191            iBuilder->CreateBr(return_block);
     192
     193        // RETURN block
     194        iBuilder->SetInsertPoint(return_block);
     195        PHINode * phiFinalRecordNum = iBuilder->CreatePHI(sizeTy, 2, "finalRecordCount");
     196        PHINode * phiFinalRecordStart = iBuilder->CreatePHI(sizeTy, 2, "finalRecordStart");
     197
     198        phiFinalRecordNum->addIncoming(phiRecordNum, processMatchesExit);
     199        phiFinalRecordNum->addIncoming(final_record_num, remaining_breaks_block);
     200        phiLineNum->addIncoming(phiFinalRecordNum, return_block);
     201
     202        phiFinalRecordStart->addIncoming(phiRecordStart, processMatchesExit);
     203        phiFinalRecordStart->addIncoming(pendingLineStart, remaining_breaks_block);
     204        phiLineStart->addIncoming(phiFinalRecordStart, return_block);
     205
     206        Value * nextScanwordPos = iBuilder->CreateAdd(phiScanwordPos, ConstantInt::get(sizeTy, sizeTy->getBitWidth()));
     207        phiScanwordPos->addIncoming(nextScanwordPos, return_block);
     208
     209        Value * nextIndex = iBuilder->CreateAdd(phiIndex, iBuilder->getInt32(1));
     210        phiIndex->addIncoming(nextIndex, return_block);
     211        iBuilder->CreateLikelyCondBr(iBuilder->CreateICmpNE(nextIndex, iBuilder->getInt32(fieldCount)), scanWordIteration, scanWordExit);
     212
     213    iBuilder->SetInsertPoint(scanWordExit);
     214    setScalarField("BlockNo", iBuilder->CreateAdd(blockNo, ConstantInt::get(blockNo->getType(), 1)));
     215    setScalarField("LineStart", phiFinalRecordStart);
     216    setScalarField("LineNum", phiFinalRecordNum);
     217}
     218
     219void ScanMatchKernel::generateInitMethod() {
     220    setScalarField("PendingBytes", iBuilder->getSize(iBuilder->getBitBlockWidth() + 2));
     221}
     222
     223void ScanMatchKernel::generateFinalBlockMethod(llvm::Value * remainingItems) {
     224    setScalarField("PendingBytes", remainingItems);
     225    CreateDoBlockMethodCall();
     226}
     227
     228ScanMatchKernel::ScanMatchKernel(IDISA::IDISA_Builder * iBuilder, GrepType grepType, const unsigned codeUnitWidth)
     229: BlockOrientedKernel(iBuilder, "scanMatch" + std::to_string(codeUnitWidth),
     230    {Binding{iBuilder->getStreamSetTy(1, 8), "InputStream"}, Binding{iBuilder->getStreamSetTy(1, 1), "matchResult"}, Binding{iBuilder->getStreamSetTy(1, 1), "lineBreak"}},
    251231    {},
    252     {Binding{iBuilder->getInt8PtrTy(), "FileBuf"}, Binding{iBuilder->getSizeTy(), "FileSize"}, Binding{iBuilder->getSizeTy(), "FileIdx"}},
     232    {Binding{iBuilder->getSizeTy(), "FileIdx"}},
    253233    {},
    254     {Binding{iBuilder->getSizeTy(), "BlockNo"}, Binding{iBuilder->getSizeTy(), "LineStart"}, Binding{iBuilder->getSizeTy(), "LineNum"}})
    255 , mGrepType(grepType) {
    256 }
    257 
    258 }
     234    {Binding{iBuilder->getSizeTy(), "BlockNo"}, Binding{iBuilder->getSizeTy(), "LineStart"}, Binding{iBuilder->getSizeTy(), "LineNum"}, Binding{iBuilder->getSizeTy(), "PendingBytes"}})
     235, mGrepType(grepType)
     236, mCodeUnitWidth(codeUnitWidth) {
     237}
     238
     239}
Note: See TracChangeset for help on using the changeset viewer.