Ignore:
Timestamp:
Nov 6, 2016, 8:37:11 PM (3 years ago)
Author:
nmedfort
Message:

Initial work on adding types to PabloAST and mutable Var objects.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/pablo/pablo_compiler.cpp

    r5199 r5202  
    2323namespace pablo {
    2424
    25 PabloCompiler::PabloCompiler(IDISA::IDISA_Builder * b, PabloKernel * k, PabloFunction * const function)
    26 : mMod(b->getModule())
    27 , iBuilder(b)
    28 , mBitBlockType(b->getBitBlockType())
     25PabloCompiler::PabloCompiler(PabloKernel * k, PabloFunction * const function)
     26: iBuilder(k->getBuilder())
     27, mBitBlockType(iBuilder->getBitBlockType())
    2928, mCarryManager(nullptr)
    3029, mPabloFunction(function)
    31 , mPabloBlock(nullptr)
    3230, mKernelBuilder(k)
    3331, mWhileDepth(0)
     
    3836}
    3937
    40 
    4138Type * PabloCompiler::initializeKernelData() {
    42     Examine(mPabloFunction);
    43    
     39    Examine(mPabloFunction);   
    4440    mCarryManager = std::unique_ptr<CarryManager>(new CarryManager(iBuilder));
    4541    Type * carryDataType = mCarryManager->initializeCarryData(mPabloFunction);
     
    4743}
    4844   
     45void PabloCompiler::verifyParameter(const Var * var, const Value * param) {
     46    if (LLVM_UNLIKELY(&(param->getContext()) != &(iBuilder->getContext()))) {
     47        std::string tmp;
     48        raw_string_ostream out(tmp);
     49        out << "Cannot compile ";
     50        mPabloFunction->print(out);
     51        out << ": LLVM Context for ";
     52        var->print(out);
     53        out << " differs from that of the kernel.";
     54        throw std::runtime_error(out.str());
     55    }
     56}
     57
    4958void PabloCompiler::compile(Function * doBlockFunction) {
    5059
    5160    // Make sure that we generate code into the right module.
    52     mMod = iBuilder->getModule();
    5361    mFunction = doBlockFunction;
    5462    #ifdef PRINT_TIMING_INFORMATION
     
    5967    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", doBlockFunction, 0));
    6068    mSelf = mKernelBuilder->getParameter(doBlockFunction, "self");
     69
    6170    mCarryManager->initializeCodeGen(mKernelBuilder, mSelf);
    6271     
    63     Value * blockNo = mKernelBuilder->getScalarField(mSelf, blockNoScalar);
    64     std::string inputName = mKernelBuilder->mStreamSetInputs[0].ssName;
    65     Value * inputSet_ptr  = mKernelBuilder->getStreamSetBlockPtr(mSelf, inputName, blockNo);
    66 
    67     Value * outputSet_ptr = nullptr;
    68     if (mPabloFunction->getNumOfResults() > 0) {
    69         std::string outputName = mKernelBuilder->mStreamSetOutputs[0].ssName;
    70         outputSet_ptr = mKernelBuilder->getStreamSetBlockPtr(mSelf, outputName, blockNo);
    71     }
    72 
    73     PabloBlock * const entryBlock = mPabloFunction->getEntryBlock();
     72    PabloBlock * const entryBlock = mPabloFunction->getEntryBlock(); assert (entryBlock);
    7473    mMarkerMap.emplace(entryBlock->createZeroes(), iBuilder->allZeroes());
    7574    mMarkerMap.emplace(entryBlock->createOnes(), iBuilder->allOnes());
    76     for (unsigned j = 0; j < mPabloFunction->getNumOfParameters(); ++j) {
    77         Value * inputVal = iBuilder->CreateGEP(inputSet_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(j)});
    78         const Var * const var = mPabloFunction->getParameter(j);
    79         if (DebugOptionIsSet(DumpTrace)) {
    80             iBuilder->CallPrintRegister(var->getName()->to_string(), iBuilder->CreateBlockAlignedLoad(inputVal));
    81         }
    82         mMarkerMap.emplace(var, inputVal);
    83     }
    84    
     75
     76    Value * const blockNo = mKernelBuilder->getScalarField(mSelf, blockNoScalar);
     77
     78    for (unsigned i = 0, j = 0; i < mPabloFunction->getNumOfParameters(); ++i) {
     79        Var * var = mPabloFunction->getParameter(i);
     80        std::string name = var->getName()->to_string();
     81        Value * input = nullptr;
     82        if (var->getType()->isSingleValueType()) {
     83            input = mKernelBuilder->getScalarFieldPtr(mSelf, name);
     84        } else {
     85            input = mKernelBuilder->getStreamSetBlockPtr(mSelf, name, blockNo);
     86            input = iBuilder->CreateGEP(input, {iBuilder->getInt32(0), iBuilder->getInt32(j++)});
     87        }
     88        verifyParameter(var, input);
     89        mMarkerMap.emplace(var, input);
     90    }
     91
     92    for (unsigned i = 0, j = 0; i < mPabloFunction->getNumOfResults(); ++i) {
     93        Var * var = mPabloFunction->getResult(i);
     94        std::string name = var->getName()->to_string();
     95        Value * output = nullptr;
     96        if (var->getType()->isSingleValueType()) {
     97            output = mKernelBuilder->getScalarFieldPtr(mSelf, name);
     98        } else {
     99            output = mKernelBuilder->getStreamSetBlockPtr(mSelf, name, blockNo);
     100            output = iBuilder->CreateGEP(output, {iBuilder->getInt32(0), iBuilder->getInt32(j++)});
     101        }
     102        verifyParameter(var, output);
     103        mMarkerMap.emplace(var, output);
     104    }
     105
    85106    compileBlock(entryBlock);
    86    
    87     for (unsigned j = 0; j < mPabloFunction->getNumOfResults(); ++j) {
    88         const auto f = mMarkerMap.find(mPabloFunction->getResult(j));
    89         if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
    90             throw std::runtime_error("PabloCompiler: result " + std::to_string(j) + " was not assigned a value!");
    91         }
    92         iBuilder->CreateBlockAlignedStore(f->second, outputSet_ptr, {iBuilder->getInt32(0), iBuilder->getInt32(j)});
    93     }
    94    
     107
    95108    #ifdef PRINT_TIMING_INFORMATION
    96109    const timestamp_t pablo_compilation_end = read_cycle_counter();
     
    107120
    108121void PabloCompiler::Examine(const PabloBlock * const block) {
    109     unsigned maxOffset = 0;
    110122    for (const Statement * stmt : *block) {
    111          boost::container::flat_set<unsigned> offsets;
    112123        if (LLVM_UNLIKELY(isa<Lookahead>(stmt))) {
    113124            const Lookahead * const la = cast<Lookahead>(stmt);
    114125            assert (isa<Var>(la->getExpr()));
    115             if (la->getAmount() > maxOffset) maxOffset = la->getAmount();
     126            if (LLVM_LIKELY(la->getAmount() > mKernelBuilder->getLookAhead())) {
     127                mKernelBuilder->setLookAhead(la->getAmount());
     128            }
    116129        } else {
    117130            if (LLVM_UNLIKELY(isa<If>(stmt))) {
     
    123136            }
    124137        }
    125         mKernelBuilder->setLookAhead(maxOffset);
    126     }
    127 }
    128 
    129 void PabloCompiler::compileBlock(const PabloBlock * const block) {
    130     mPabloBlock = block;
     138    }   
     139}
     140
     141inline void PabloCompiler::compileBlock(const PabloBlock * const block) {
    131142    for (const Statement * statement : *block) {
    132143        compileStatement(statement);
    133144    }
    134     mPabloBlock = block->getPredecessor ();
    135 }
    136 
    137 void PabloCompiler::compileIf(const If * ifStatement) {       
     145}
     146
     147static const llvm::StringRef EmptyString;
     148
     149inline const llvm::StringRef & getName(const PabloAST * expr) {
     150    if (expr->getName()) {
     151        return expr->getName()->value();
     152    }
     153    return EmptyString;
     154}
     155
     156void PabloCompiler::compileIf(const If * const ifStatement) {
    138157    //
    139158    //  The If-ElseZero stmt:
     
    154173    //
    155174
     175    Module * const mod = iBuilder->getModule();
    156176    BasicBlock * const ifEntryBlock = iBuilder->GetInsertBlock();
    157     BasicBlock * const ifBodyBlock = BasicBlock::Create(mMod->getContext(), "if.body", mFunction, 0);
    158     BasicBlock * const ifEndBlock = BasicBlock::Create(mMod->getContext(), "if.end", mFunction, 0);
    159    
     177    BasicBlock * const ifBodyBlock = BasicBlock::Create(mod->getContext(), "if.body", mFunction, 0);
     178    BasicBlock * const ifEndBlock = BasicBlock::Create(mod->getContext(), "if.end", mFunction, 0);
     179   
     180    std::vector<std::pair<const Var *, Value *>> incoming;
     181
     182    for (const Var * var : ifStatement->getEscaped()) {
     183        auto f = mMarkerMap.find(var);
     184        if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
     185            std::string tmp;
     186            raw_string_ostream out(tmp);
     187            PabloPrinter::print(var, out);
     188            out << " is uninitialized prior to entering ";
     189            PabloPrinter::print(ifStatement, out);
     190            llvm::report_fatal_error(out.str());
     191        }
     192        incoming.emplace_back(var, f->second);
     193    }
     194
    160195    PabloBlock * ifBody = ifStatement->getBody();
    161196   
     
    169204   
    170205    compileBlock(ifBody);
     206
    171207    BasicBlock * ifExitBlock = iBuilder->GetInsertBlock();
    172208
     
    179215    //End Block
    180216    iBuilder->SetInsertPoint(ifEndBlock);
    181     for (const PabloAST * node : ifStatement->getDefined()) {
    182         const Assign * assign = cast<Assign>(node);
    183         PHINode * phi = iBuilder->CreatePHI(mBitBlockType, 2, assign->getName()->value());
    184         auto f = mMarkerMap.find(assign);
    185         assert (f != mMarkerMap.end());
    186         phi->addIncoming(iBuilder->allZeroes(), ifEntryBlock);
     217    for (const auto i : incoming) {
     218        const Var * var; Value * value;
     219        std::tie(var, value) = i;
     220
     221        auto f = mMarkerMap.find(var);
     222        if (LLVM_UNLIKELY(f == mMarkerMap.end() || f->second == value)) {
     223            std::string tmp;
     224            raw_string_ostream out(tmp);
     225            PabloPrinter::print(var, out);
     226            out << " was not assigned a value.";
     227            llvm::report_fatal_error(out.str());
     228        }
     229
     230        PHINode * phi = iBuilder->CreatePHI(mBitBlockType, 2, getName(var));
     231        phi->addIncoming(value, ifEntryBlock);
    187232        phi->addIncoming(f->second, ifExitBlock);
    188233        f->second = phi;
    189         assert (mMarkerMap[assign] == phi);
     234
     235        assert (mMarkerMap[var] == phi);
    190236    }
    191237    // Create the phi Node for the summary variable, if needed.
     
    194240}
    195241
    196 void PabloCompiler::compileWhile(const While * whileStatement) {
     242void PabloCompiler::compileWhile(const While * const whileStatement) {
    197243
    198244    PabloBlock * const whileBody = whileStatement->getBody();
    199245   
    200246    BasicBlock * whileEntryBlock = iBuilder->GetInsertBlock();
    201     BasicBlock * whileBodyBlock = BasicBlock::Create(mMod->getContext(), "while.body", mFunction, 0);
    202     BasicBlock * whileEndBlock = BasicBlock::Create(mMod->getContext(), "while.end", mFunction, 0);
     247
     248    Module * const mod = iBuilder->getModule();
     249    BasicBlock * whileBodyBlock = BasicBlock::Create(mod->getContext(), "while.body", mFunction, 0);
     250    BasicBlock * whileEndBlock = BasicBlock::Create(mod->getContext(), "while.end", mFunction, 0);
    203251
    204252    mCarryManager->enterScope(whileBody);
    205253    mCarryManager->ensureCarriesLoadedRecursive();
    206254
    207     const auto & nextNodes = whileStatement->getVariants();
    208     std::vector<PHINode *> nextPhis;
    209     nextPhis.reserve(nextNodes.size());
    210255#ifdef ENABLE_BOUNDED_WHILE
    211256    PHINode * bound_phi = nullptr;  // Needed for bounded while loops.
     
    229274    mCarryManager->initializeWhileEntryCarryDataPhis(whileEntryBlock);
    230275
     276    std::vector<std::pair<const Var *, PHINode *>> variants;
     277
    231278    // for any Next nodes in the loop body, initialize to (a) pre-loop value.
    232     for (const Next * n : nextNodes) {
    233         PHINode * phi = iBuilder->CreatePHI(mBitBlockType, 2, n->getName()->value());
    234         auto f = mMarkerMap.find(n->getInitial());       
    235         assert (f != mMarkerMap.end());
     279    for (const auto var : whileStatement->getEscaped()) {
     280        PHINode * phi = iBuilder->CreatePHI(mBitBlockType, 2, getName(var));
     281        auto f = mMarkerMap.find(var);
     282        if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
     283            std::string tmp;
     284            raw_string_ostream out(tmp);
     285            PabloPrinter::print(var, out);
     286            out << " was not assigned a value.";
     287            llvm::report_fatal_error(out.str());
     288        }
    236289        phi->addIncoming(f->second, whileEntryBlock);
    237290        f->second = phi;
    238         assert(mMarkerMap[n->getInitial()] == phi);
    239         nextPhis.push_back(phi);
     291        assert(mMarkerMap[var] == phi);
     292        variants.emplace_back(var, phi);
    240293    }
    241294#ifdef ENABLE_BOUNDED_WHILE
     
    270323    iBuilder->CreateCondBr(cond_expr, whileBodyBlock, whileEndBlock);
    271324
    272     // and for any Next nodes in the loop body
    273     for (unsigned i = 0; i < nextNodes.size(); i++) {
    274         const Next * n = nextNodes[i];
    275         const auto f = mMarkerMap.find(n->getExpr());
    276         if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
    277             throw std::runtime_error("Next node expression was not compiled!");
    278         }
    279         nextPhis[i]->addIncoming(f->second, whileExitBlock);
     325    // and for any variant nodes in the loop body
     326    for (const auto variant : variants) {
     327        const Var * var; PHINode * phi;
     328        std::tie(var, phi) = variant;
     329        const auto f = mMarkerMap.find(var);
     330        if (LLVM_UNLIKELY(f == mMarkerMap.end() || f->second == phi)) {
     331            std::string tmp;
     332            raw_string_ostream out(tmp);
     333            PabloPrinter::print(var, out);
     334            out << " was not assigned a value.";
     335            llvm::report_fatal_error(out.str());
     336        }
     337        phi->addIncoming(f->second, whileExitBlock);
     338        f->second = phi;
    280339    }
    281340
     
    287346}
    288347
    289 
    290348void PabloCompiler::compileStatement(const Statement * stmt) {
    291     Value * expr = nullptr;
    292     if (const Assign * assign = dyn_cast<const Assign>(stmt)) {
    293         expr = compileExpression(assign->getExpression());
    294     } else if (const Next * next = dyn_cast<const Next>(stmt)) {
    295         expr = compileExpression(next->getExpr());
    296     } else if (const If * ifStatement = dyn_cast<const If>(stmt)) {
    297         compileIf(ifStatement);
    298         return;
    299     } else if (const While * whileStatement = dyn_cast<const While>(stmt)) {
    300         compileWhile(whileStatement);
    301         return;
    302 //    } else if (const Call* call = dyn_cast<Call>(stmt)) {
    303 //        // Call the callee once and store the result in the marker map.
    304 //        if (LLVM_UNLIKELY(mMarkerMap.count(call) == 0)) {
    305 //            return;
    306 //        }
    307 
    308 //        const Prototype * proto = call->getPrototype();
    309 //        const String * callee = proto->getName();
    310 
    311 //        Type * inputType = StructType::get(mMod->getContext(), std::vector<Type *>{proto->getNumOfParameters(), mBitBlockType});
    312 //        Type * outputType = StructType::get(mMod->getContext(), std::vector<Type *>{proto->getNumOfResults(), mBitBlockType});
    313 //        FunctionType * functionType = FunctionType::get(Type::getVoidTy(mMod->getContext()), std::vector<Type *>{PointerType::get(inputType, 0), PointerType::get(outputType, 0)}, false);
    314 
    315 //        //Starts on process_block
    316 //        SmallVector<AttributeSet, 3> Attrs;
    317 //        Attrs.push_back(AttributeSet::get(mMod->getContext(), 1U, std::vector<Attribute::AttrKind>({ Attribute::ReadOnly, Attribute::NoCapture })));
    318 //        Attrs.push_back(AttributeSet::get(mMod->getContext(), 2U, std::vector<Attribute::AttrKind>({ Attribute::ReadNone, Attribute::NoCapture })));
    319 //        AttributeSet AttrSet = AttributeSet::get(mMod->getContext(), Attrs);
    320 
    321 //        Function * externalFunction = cast<Function>(mMod->getOrInsertFunction(callee->value(), functionType, AttrSet));
    322 //        if (LLVM_UNLIKELY(externalFunction == nullptr)) {
    323 //            throw std::runtime_error("Could not create static method call for external function \"" + callee->to_string() + "\"");
    324 //        }
    325 //        externalFunction->setCallingConv(llvm::CallingConv::C);
    326 
    327 //        AllocaInst * outputStruct = iBuilder->CreateAlloca(outputType);
    328 //        iBuilder->CreateCall2(externalFunction, mInputAddressPtr, outputStruct);
    329 //        Value * outputPtr = iBuilder->CreateGEP(outputStruct, std::vector<Value *>({ iBuilder->getInt32(0), iBuilder->getInt32(0) }));
    330 
    331 //        expr = iBuilder->CreateBlockAlignedLoad(outputPtr);
    332     } else if (const And * pablo_and = dyn_cast<And>(stmt)) {
    333         expr = iBuilder->simd_and(compileExpression(pablo_and->getOperand(0)), compileExpression(pablo_and->getOperand(1)));
    334     } else if (const Or * pablo_or = dyn_cast<Or>(stmt)) {
    335         expr = iBuilder->simd_or(compileExpression(pablo_or->getOperand(0)), compileExpression(pablo_or->getOperand(1)));
    336     } else if (const Xor * pablo_xor = dyn_cast<Xor>(stmt)) {
    337         expr = iBuilder->simd_xor(compileExpression(pablo_xor->getOperand(0)), compileExpression(pablo_xor->getOperand(1)));
    338     } else if (const Sel * sel = dyn_cast<Sel>(stmt)) {
    339         Value* ifMask = compileExpression(sel->getCondition());
    340         Value* ifTrue = iBuilder->simd_and(ifMask, compileExpression(sel->getTrueExpr()));
    341         Value* ifFalse = iBuilder->simd_and(iBuilder->simd_not(ifMask), compileExpression(sel->getFalseExpr()));
    342         expr = iBuilder->simd_or(ifTrue, ifFalse);
    343     } else if (const Not * pablo_not = dyn_cast<Not>(stmt)) {
    344         expr = iBuilder->simd_not(compileExpression(pablo_not->getExpr()));
    345     } else if (const Advance * adv = dyn_cast<Advance>(stmt)) {
    346         Value * const strm_value = compileExpression(adv->getExpr());
    347         expr = mCarryManager->advanceCarryInCarryOut(adv->getLocalIndex(), adv->getAmount(), strm_value);
    348     } else if (const MatchStar * mstar = dyn_cast<MatchStar>(stmt)) {
    349         Value * const marker = compileExpression(mstar->getMarker());
    350         Value * const cc = compileExpression(mstar->getCharClass());
    351         Value * const marker_and_cc = iBuilder->simd_and(marker, cc);
    352         Value * const sum = mCarryManager->addCarryInCarryOut(mstar->getLocalCarryIndex(), marker_and_cc, cc);
    353         expr = iBuilder->simd_or(iBuilder->simd_xor(sum, cc), marker);
    354     } else if (const ScanThru * sthru = dyn_cast<ScanThru>(stmt)) {
    355         Value * const  marker_expr = compileExpression(sthru->getScanFrom());
    356         Value * const  cc_expr = compileExpression(sthru->getScanThru());
    357         Value * const  sum = mCarryManager->addCarryInCarryOut(sthru->getLocalCarryIndex(), marker_expr, cc_expr);
    358         expr = iBuilder->simd_and(sum, iBuilder->simd_not(cc_expr));
    359     } else if (const InFile * e = dyn_cast<InFile>(stmt)) {
    360         Value * EOFmask = mKernelBuilder->getScalarField(mSelf, "EOFmask");
    361         expr = iBuilder->simd_xor(compileExpression(e->getExpr()), EOFmask);
    362     } else if (const AtEOF * e = dyn_cast<AtEOF>(stmt)) {
    363         Value * EOFbit = mKernelBuilder->getScalarField(mSelf, "EOFbit");
    364                 expr = iBuilder->simd_and(compileExpression(e->getExpr()), EOFbit);
    365     } else if (const Count * c = dyn_cast<Count>(stmt)) {
    366         Value * const to_count = compileExpression(c->getExpr());
    367         std::string counter = c->getName()->to_string();
    368         Value * countSoFar = mKernelBuilder->getScalarField(mSelf, counter);
    369         unsigned counterSize = countSoFar->getType()->getIntegerBitWidth();
    370         Value * fieldCounts = iBuilder->simd_popcount(counterSize, to_count);
    371         for (unsigned i = 0; i < iBuilder->getBitBlockWidth()/counterSize; ++i) {
    372             countSoFar = iBuilder->CreateAdd(countSoFar, iBuilder->mvmd_extract(counterSize, fieldCounts, i));
    373         }
    374         mKernelBuilder->setScalarField(mSelf, counter, countSoFar);
    375         expr = iBuilder->bitCast(iBuilder->CreateZExt(countSoFar, iBuilder->getIntNTy(iBuilder->getBitBlockWidth())));
    376     } else if (const Lookahead * l = dyn_cast<Lookahead>(stmt)) {
    377         PabloAST * const var = l->getExpr();
    378         if (LLVM_UNLIKELY(!isa<Var>(var))) {
    379             throw std::runtime_error("Lookahead operations may only be applied to input streams");
    380         }
    381         unsigned index = 0;
    382         for (; index < mPabloFunction->getNumOfParameters(); ++index) {
    383             if (mPabloFunction->getParameter(index) == var) {
    384                 break;
    385             }
    386         }
    387         if (LLVM_UNLIKELY(index >= mPabloFunction->getNumOfParameters())) {
    388             throw std::runtime_error("Lookahead has an illegal Var operand");
    389         }
    390         const unsigned bit_shift = (l->getAmount() % iBuilder->getBitBlockWidth());
    391         const unsigned block_shift = (l->getAmount() / iBuilder->getBitBlockWidth());
    392         std::string inputName = mKernelBuilder->mStreamSetInputs[0].ssName;
    393         Value * blockNo = mKernelBuilder->getScalarField(mSelf, blockNoScalar);
    394         Value * lookAhead_blockPtr  = mKernelBuilder->getStreamSetBlockPtr(mSelf, inputName, iBuilder->CreateAdd(blockNo, ConstantInt::get(iBuilder->getSizeTy(), block_shift)));
    395         Value * lookAhead_inputPtr = iBuilder->CreateGEP(lookAhead_blockPtr, {iBuilder->getInt32(0), iBuilder->getInt32(index)});
    396         Value * lookAhead = iBuilder->CreateBlockAlignedLoad(lookAhead_inputPtr);
    397         if (bit_shift == 0) {  // Simple case with no intra-block shifting.
    398             expr = lookAhead; 
    399         }
    400         else { // Need to form shift result from two adjacent blocks.
    401             Value * lookAhead_blockPtr1  = mKernelBuilder->getStreamSetBlockPtr(mSelf, inputName, iBuilder->CreateAdd(blockNo, ConstantInt::get(iBuilder->getSizeTy(), block_shift + 1)));
    402             Value * lookAhead_inputPtr1 = iBuilder->CreateGEP(lookAhead_blockPtr1, {iBuilder->getInt32(0), iBuilder->getInt32(index)});
    403             Value * lookAhead1 = iBuilder->CreateBlockAlignedLoad(lookAhead_inputPtr1);
    404             if (LLVM_UNLIKELY((bit_shift % 8) == 0)) { // Use a single whole-byte shift, if possible.
    405                 expr = iBuilder->mvmd_dslli(8, lookAhead1, lookAhead, (bit_shift / 8));
    406             }
    407             else {
    408                 Type  * const streamType = iBuilder->getIntNTy(iBuilder->getBitBlockWidth());
    409                 Value * b1 = iBuilder->CreateBitCast(lookAhead1, streamType);
    410                 Value * b0 = iBuilder->CreateBitCast(lookAhead, streamType);
    411                 Value * result = iBuilder->CreateOr(iBuilder->CreateShl(b1, iBuilder->getBitBlockWidth() - bit_shift), iBuilder->CreateLShr(b0, bit_shift));
    412                 expr = iBuilder->CreateBitCast(result, mBitBlockType);
    413             }
    414         }
     349
     350    if (LLVM_UNLIKELY(isa<If>(stmt))) {
     351        compileIf(cast<If>(stmt));
     352    } else if (LLVM_UNLIKELY(isa<While>(stmt))) {
     353        compileWhile(cast<While>(stmt));
    415354    } else {
    416         std::string tmp;
    417         llvm::raw_string_ostream msg(tmp);
    418         msg << "Internal error: ";
    419         PabloPrinter::print(stmt, msg);
    420         msg << " is not a recognized statement in the Pablo compiler.";
    421         throw std::runtime_error(msg.str());
    422     }
    423     mMarkerMap.emplace(stmt, expr);
    424     if (DebugOptionIsSet(DumpTrace)) {
    425         iBuilder->CallPrintRegister(stmt->getName()->to_string(), expr);
    426     }
    427    
    428 }
    429 
    430 Value * PabloCompiler::compileExpression(const PabloAST * expr) {
     355        const PabloAST * expr = stmt;
     356        Value * value = nullptr;
     357        if (LLVM_UNLIKELY(isa<Assign>(stmt))) {
     358
     359            expr = cast<Assign>(stmt)->getVariable();
     360            value = compileExpression(cast<Assign>(stmt)->getValue());
     361
     362            bool storeInstRequired = false;
     363            if (LLVM_LIKELY(isa<Var>(expr))) {
     364                for (unsigned i = 0; i < mPabloFunction->getNumOfResults(); ++i) {
     365                    if (expr == mPabloFunction->getResult(i)) {
     366                        storeInstRequired = true;
     367                        break;
     368                    }
     369                }
     370            }
     371
     372            if (LLVM_UNLIKELY(storeInstRequired || isa<Extract>(expr))) {
     373
     374                const auto f = mMarkerMap.find(expr);
     375                if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
     376                    std::string tmp;
     377                    raw_string_ostream out(tmp);
     378                    PabloPrinter::print(expr, out);
     379                    out << " was not defined prior to ";
     380                    PabloPrinter::print(stmt, out);
     381                    throw std::runtime_error(out.str());
     382                }
     383                Value * const ptr = f->second;
     384
     385                assert (&(value->getContext()) == &(ptr->getContext()));
     386
     387                if (isa<Count>(cast<Assign>(stmt)->getValue())) {
     388                    Value * count = iBuilder->CreateLoad(ptr);
     389                    Value * accum = iBuilder->CreateAdd(value, count);
     390                    iBuilder->CreateStore(accum, ptr);
     391                } else {
     392                    iBuilder->CreateBlockAlignedStore(value, ptr);
     393                }
     394            }
     395
     396        } else if (const Extract * extract = dyn_cast<Extract>(stmt)) {
     397            Value * array = compileExpression(extract->getArray(), false);
     398            Value * index = compileExpression(extract->getIndex());
     399            value = iBuilder->CreateGEP(array, index, getName(stmt));
     400        } else if (const And * pablo_and = dyn_cast<And>(stmt)) {
     401            value = iBuilder->simd_and(compileExpression(pablo_and->getOperand(0)), compileExpression(pablo_and->getOperand(1)));
     402        } else if (const Or * pablo_or = dyn_cast<Or>(stmt)) {
     403            value = iBuilder->simd_or(compileExpression(pablo_or->getOperand(0)), compileExpression(pablo_or->getOperand(1)));
     404        } else if (const Xor * pablo_xor = dyn_cast<Xor>(stmt)) {
     405            value = iBuilder->simd_xor(compileExpression(pablo_xor->getOperand(0)), compileExpression(pablo_xor->getOperand(1)));
     406        } else if (const Sel * sel = dyn_cast<Sel>(stmt)) {
     407            Value* ifMask = compileExpression(sel->getCondition());
     408            Value* ifTrue = iBuilder->simd_and(ifMask, compileExpression(sel->getTrueExpr()));
     409            Value* ifFalse = iBuilder->simd_and(iBuilder->simd_not(ifMask), compileExpression(sel->getFalseExpr()));
     410            value = iBuilder->simd_or(ifTrue, ifFalse);
     411        } else if (const Not * pablo_not = dyn_cast<Not>(stmt)) {
     412            value = iBuilder->simd_not(compileExpression(pablo_not->getExpr()));
     413        } else if (const Advance * adv = dyn_cast<Advance>(stmt)) {
     414            Value * const strm_value = compileExpression(adv->getExpr());
     415            value = mCarryManager->advanceCarryInCarryOut(adv->getLocalIndex(), adv->getAmount(), strm_value);
     416        } else if (const MatchStar * mstar = dyn_cast<MatchStar>(stmt)) {
     417            Value * const marker = compileExpression(mstar->getMarker());
     418            Value * const cc = compileExpression(mstar->getCharClass());
     419            Value * const marker_and_cc = iBuilder->simd_and(marker, cc);
     420            Value * const sum = mCarryManager->addCarryInCarryOut(mstar->getLocalCarryIndex(), marker_and_cc, cc);
     421            value = iBuilder->simd_or(iBuilder->simd_xor(sum, cc), marker);
     422        } else if (const ScanThru * sthru = dyn_cast<ScanThru>(stmt)) {
     423            Value * const  marker_expr = compileExpression(sthru->getScanFrom());
     424            Value * const  cc_expr = compileExpression(sthru->getScanThru());
     425            Value * const  sum = mCarryManager->addCarryInCarryOut(sthru->getLocalCarryIndex(), marker_expr, cc_expr);
     426            value = iBuilder->simd_and(sum, iBuilder->simd_not(cc_expr));
     427        } else if (const InFile * e = dyn_cast<InFile>(stmt)) {
     428            Value * EOFmask = mKernelBuilder->getScalarField(mSelf, "EOFmask");
     429            value = iBuilder->simd_xor(compileExpression(e->getExpr()), EOFmask);
     430        } else if (const AtEOF * e = dyn_cast<AtEOF>(stmt)) {
     431            Value * EOFbit = mKernelBuilder->getScalarField(mSelf, "EOFbit");
     432            value = iBuilder->simd_and(compileExpression(e->getExpr()), EOFbit);
     433        } else if (const Count * c = dyn_cast<Count>(stmt)) {
     434            Value * const to_count = compileExpression(c->getExpr());
     435            const unsigned counterSize = 64;
     436            Value * fieldCounts = iBuilder->simd_popcount(counterSize, to_count);
     437            value = iBuilder->mvmd_extract(counterSize, fieldCounts, 0);
     438            for (unsigned i = 1; i < (iBuilder->getBitBlockWidth() / counterSize); ++i) {
     439                Value * temp = iBuilder->mvmd_extract(counterSize, fieldCounts, i);
     440                value = iBuilder->CreateAdd(value, temp);
     441            }
     442        } else if (const Lookahead * l = dyn_cast<Lookahead>(stmt)) {
     443            PabloAST * const var = l->getExpr();
     444            if (LLVM_UNLIKELY(!isa<Var>(var))) {
     445                throw std::runtime_error("Lookahead operations may only be applied to input streams");
     446            }
     447            unsigned index = 0;
     448            for (; index < mPabloFunction->getNumOfParameters(); ++index) {
     449                if (mPabloFunction->getParameter(index) == var) {
     450                    break;
     451                }
     452            }
     453            if (LLVM_UNLIKELY(index >= mPabloFunction->getNumOfParameters())) {
     454                throw std::runtime_error("Lookahead has an illegal Var operand");
     455            }
     456            const unsigned bit_shift = (l->getAmount() % iBuilder->getBitBlockWidth());
     457            const unsigned block_shift = (l->getAmount() / iBuilder->getBitBlockWidth());
     458            std::string inputName = var->getName()->to_string();;
     459            Value * blockNo = mKernelBuilder->getScalarField(mSelf, blockNoScalar);
     460            Value * lookAhead_blockPtr  = mKernelBuilder->getStreamSetBlockPtr(mSelf, inputName, iBuilder->CreateAdd(blockNo, ConstantInt::get(iBuilder->getSizeTy(), block_shift)));
     461            Value * lookAhead_inputPtr = iBuilder->CreateGEP(lookAhead_blockPtr, {iBuilder->getInt32(0), iBuilder->getInt32(index)});
     462            Value * lookAhead = iBuilder->CreateBlockAlignedLoad(lookAhead_inputPtr);
     463            if (bit_shift == 0) {  // Simple case with no intra-block shifting.
     464                value = lookAhead;
     465            } else { // Need to form shift result from two adjacent blocks.
     466                Value * lookAhead_blockPtr1  = mKernelBuilder->getStreamSetBlockPtr(mSelf, inputName, iBuilder->CreateAdd(blockNo, ConstantInt::get(iBuilder->getSizeTy(), block_shift + 1)));
     467                Value * lookAhead_inputPtr1 = iBuilder->CreateGEP(lookAhead_blockPtr1, {iBuilder->getInt32(0), iBuilder->getInt32(index)});
     468                Value * lookAhead1 = iBuilder->CreateBlockAlignedLoad(lookAhead_inputPtr1);
     469                if (LLVM_UNLIKELY((bit_shift % 8) == 0)) { // Use a single whole-byte shift, if possible.
     470                    value = iBuilder->mvmd_dslli(8, lookAhead1, lookAhead, (bit_shift / 8));
     471                } else {
     472                    Type  * const streamType = iBuilder->getIntNTy(iBuilder->getBitBlockWidth());
     473                    Value * b1 = iBuilder->CreateBitCast(lookAhead1, streamType);
     474                    Value * b0 = iBuilder->CreateBitCast(lookAhead, streamType);
     475                    Value * result = iBuilder->CreateOr(iBuilder->CreateShl(b1, iBuilder->getBitBlockWidth() - bit_shift), iBuilder->CreateLShr(b0, bit_shift));
     476                    value = iBuilder->CreateBitCast(result, mBitBlockType);
     477                }
     478            }
     479
     480        } else {
     481            std::string tmp;
     482            llvm::raw_string_ostream msg(tmp);
     483            msg << "Internal error: ";
     484            PabloPrinter::print(stmt, msg);
     485            msg << " is not a recognized statement in the Pablo compiler.";
     486            throw std::runtime_error(msg.str());
     487        }
     488
     489        mMarkerMap[expr] = value;
     490
     491        if (DebugOptionIsSet(DumpTrace)) {
     492            iBuilder->CallPrintRegister(stmt->getName()->to_string(), value);
     493        }
     494    }
     495}
     496
     497Value * PabloCompiler::compileExpression(const PabloAST * expr, const bool ensureLoaded) const {
    431498    if (LLVM_UNLIKELY(isa<Ones>(expr))) {
    432499        return iBuilder->allOnes();
    433500    } else if (LLVM_UNLIKELY(isa<Zeroes>(expr))) {
    434501        return iBuilder->allZeroes();
    435     }
    436     auto f = mMarkerMap.find(expr);
     502    } else if (LLVM_UNLIKELY(isa<Integer>(expr))) {
     503        return iBuilder->getInt64(cast<Integer>(expr)->value());
     504    }
     505    const auto f = mMarkerMap.find(expr);
    437506    if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
    438507        std::string tmp;
    439508        llvm::raw_string_ostream out(tmp);
    440         out << "\"";
    441509        PabloPrinter::print(expr, out);
    442         out << "\" was used before definition!";
     510        out << " was used before definition!";
    443511        throw std::runtime_error(out.str());
    444512    }
    445     Value * result = f->second;
    446     if (LLVM_UNLIKELY(isa<Var>(expr))) {
    447         assert (isa<GetElementPtrInst>(result));
    448         result = iBuilder->CreateBlockAlignedLoad(result);
    449     }
    450     return result;
    451 }
    452 
    453 }
     513    Value * value = f->second;
     514    if (LLVM_UNLIKELY(isa<GetElementPtrInst>(value) && ensureLoaded)) {
     515        value = iBuilder->CreateBlockAlignedLoad(value);
     516    }
     517    return value;
     518}
     519
     520}
Note: See TracChangeset for help on using the changeset viewer.