source: icGREP/icgrep-devel/icgrep/pablo/pablo_compiler.cpp @ 5234

Last change on this file since 5234 was 5234, checked in by nmedfort, 2 years ago

Modified memory alignment mechanism for GetPropertyValueGrepString? + misc. changes.

File size: 23.1 KB
RevLine 
[3850]1/*
[5043]2 *  Copyright (c) 2014-16 International Characters.
[3850]3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
[4237]7#include <pablo/pablo_compiler.h>
[5031]8#include <pablo/pablo_toolchain.h>
[4237]9#include <pablo/codegenstate.h>
[4647]10#include <pablo/carry_manager.h>
[4237]11#include <pablo/printer_pablos.h>
[5217]12#include <pablo/prototype.h>
[4249]13#include <re/re_name.h>
[4237]14#include <stdexcept>
[4416]15#include <sstream>
[4663]16#include <IDISA/idisa_builder.h>
[4274]17#include <llvm/IR/Module.h>
18#include <llvm/IR/IRBuilder.h>
[4438]19#include <iostream>
[4919]20#include <hrtime.h>
[5063]21#include <llvm/Support/Debug.h>
[4919]22
[4237]23namespace pablo {
24
[5227]25using TypeId = PabloAST::ClassTypeId;
[4237]26
[5227]27void PabloCompiler::initializeKernelData() {
[5217]28    Examine();
[5227]29    mCarryManager->initializeCarryData(mKernel);
[5063]30}
31   
[5227]32void PabloCompiler::compile(Value * const self, Function * function) {
[5202]33
[5063]34    // Make sure that we generate code into the right module.
[5217]35    mSelf = self;
[5227]36    mFunction = function;
[5217]37
[5063]38    //Generate Kernel//
[5227]39    iBuilder->SetInsertPoint(BasicBlock::Create(iBuilder->getContext(), "entry", function, 0));
[5202]40
[5227]41    mCarryManager->initializeCodeGen(self, function);
[5063]42     
[5217]43    PabloBlock * const entryBlock = mKernel->getEntryBlock(); assert (entryBlock);
[5202]44    mMarkerMap.emplace(entryBlock->createZeroes(), iBuilder->allZeroes());
45    mMarkerMap.emplace(entryBlock->createOnes(), iBuilder->allOnes());
[5102]46
[5217]47    Value * const blockNo = mKernel->getScalarField(mSelf, blockNoScalar);
[5202]48
[5217]49    for (unsigned i = 0; i < mKernel->getNumOfInputs(); ++i) {
50        Var * var = mKernel->getInput(i);
[5202]51        std::string name = var->getName()->to_string();
52        Value * input = nullptr;
53        if (var->getType()->isSingleValueType()) {
[5217]54            input = mKernel->getScalarFieldPtr(mSelf, name);
[5202]55        } else {
[5217]56            input = mKernel->getStreamSetBlockPtr(mSelf, name, blockNo);
[5202]57        }
58        mMarkerMap.emplace(var, input);
[4939]59    }
[5156]60
[5217]61    for (unsigned i = 0; i < mKernel->getNumOfOutputs(); ++i) {
62        Var * var = mKernel->getOutput(i);
[5202]63        std::string name = var->getName()->to_string();
64        Value * output = nullptr;
65        if (var->getType()->isSingleValueType()) {
[5217]66            output = mKernel->getScalarFieldPtr(mSelf, name);
[5202]67        } else {
[5217]68            output = mKernel->getStreamSetBlockPtr(mSelf, name, blockNo);
[4986]69        }
[5202]70        mMarkerMap.emplace(var, output);
[4974]71    }
[5202]72
[5160]73    compileBlock(entryBlock);
[5202]74
[5063]75    #ifdef PRINT_TIMING_INFORMATION
76    const timestamp_t pablo_compilation_end = read_cycle_counter();
77    std::cerr << "PABLO COMPILATION TIME: " << (pablo_compilation_end - pablo_compilation_start) << std::endl;
78    #endif
[4237]79}
[4659]80
[5217]81inline void PabloCompiler::Examine() {
82    Examine(mKernel->getEntryBlock());
[4659]83}
[4665]84
[5141]85void PabloCompiler::Examine(const PabloBlock * const block) {
[5000]86    for (const Statement * stmt : *block) {
87        if (LLVM_UNLIKELY(isa<Lookahead>(stmt))) {
88            const Lookahead * const la = cast<Lookahead>(stmt);
89            assert (isa<Var>(la->getExpr()));
[5217]90            if (LLVM_LIKELY(la->getAmount() > mKernel->getLookAhead())) {
91                mKernel->setLookAhead(la->getAmount());
[5202]92            }
[5227]93        } else if (LLVM_UNLIKELY(isa<Branch>(stmt))) {
94            Examine(cast<Branch>(stmt)->getBody());
[4237]95        }
[5202]96    }   
[4237]97}
98
[5202]99inline void PabloCompiler::compileBlock(const PabloBlock * const block) {
[4870]100    for (const Statement * statement : *block) {
[4343]101        compileStatement(statement);
[4237]102    }
103}
104
[5202]105static const llvm::StringRef EmptyString;
106
107inline const llvm::StringRef & getName(const PabloAST * expr) {
108    if (expr->getName()) {
109        return expr->getName()->value();
110    }
111    return EmptyString;
112}
113
114void PabloCompiler::compileIf(const If * const ifStatement) {
[4647]115    //
116    //  The If-ElseZero stmt:
117    //  if <predicate:expr> then <body:stmt>* elsezero <defined:var>* endif
118    //  If the value of the predicate is nonzero, then determine the values of variables
119    //  <var>* by executing the given statements.  Otherwise, the value of the
120    //  variables are all zero.  Requirements: (a) no variable that is defined within
121    //  the body of the if may be accessed outside unless it is explicitly
122    //  listed in the variable list, (b) every variable in the defined list receives
123    //  a value within the body, and (c) the logical consequence of executing
124    //  the statements in the event that the predicate is zero is that the
125    //  values of all defined variables indeed work out to be 0.
126    //
127    //  Simple Implementation with Phi nodes:  a phi node in the if exit block
128    //  is inserted for each variable in the defined variable list.  It receives
129    //  a zero value from the ifentry block and the defined value from the if
130    //  body.
131    //
[4665]132
[4925]133    BasicBlock * const ifEntryBlock = iBuilder->GetInsertBlock();
[5227]134    BasicBlock * const ifBodyBlock = BasicBlock::Create(mFunction->getContext(), "if.body", mFunction);
135    BasicBlock * const ifEndBlock = BasicBlock::Create(mFunction->getContext(), "if.end", mFunction);
[4541]136   
[5202]137    std::vector<std::pair<const Var *, Value *>> incoming;
138
139    for (const Var * var : ifStatement->getEscaped()) {
140        auto f = mMarkerMap.find(var);
141        if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
142            std::string tmp;
143            raw_string_ostream out(tmp);
144            PabloPrinter::print(var, out);
145            out << " is uninitialized prior to entering ";
146            PabloPrinter::print(ifStatement, out);
147            llvm::report_fatal_error(out.str());
148        }
149        incoming.emplace_back(var, f->second);
150    }
151
[4870]152    PabloBlock * ifBody = ifStatement->getBody();
[4628]153   
[5227]154    mCarryManager->enterIfScope(ifBody);
155
156    Value * condition = compileExpression(ifStatement->getCondition());
157    if (condition->getType() == iBuilder->getBitBlockType()) {
158        condition = iBuilder->bitblock_any(mCarryManager->generateSummaryTest(condition));
159    }
[4670]160   
[5227]161    iBuilder->CreateCondBr(condition, ifBodyBlock, ifEndBlock);
[4838]162   
[4647]163    // Entry processing is complete, now handle the body of the if.
[4898]164    iBuilder->SetInsertPoint(ifBodyBlock);
[5227]165
166    mCarryManager->enterIfBody(ifEntryBlock);
167
[4647]168    compileBlock(ifBody);
[5202]169
[5227]170    BasicBlock * ifExitBlock = iBuilder->GetInsertBlock();   
[4922]171
[5227]172    mCarryManager->leaveIfBody(ifExitBlock);
[4922]173
[4898]174    iBuilder->CreateBr(ifEndBlock);
[4647]175    //End Block
[4898]176    iBuilder->SetInsertPoint(ifEndBlock);
[5227]177
178    mCarryManager->leaveIfScope(ifEntryBlock, ifExitBlock);
179
[5202]180    for (const auto i : incoming) {
181        const Var * var; Value * value;
182        std::tie(var, value) = i;
183
184        auto f = mMarkerMap.find(var);
185        if (LLVM_UNLIKELY(f == mMarkerMap.end() || f->second == value)) {
186            std::string tmp;
187            raw_string_ostream out(tmp);
188            PabloPrinter::print(var, out);
189            out << " was not assigned a value.";
190            llvm::report_fatal_error(out.str());
191        }
192
[5227]193        Value * const next = f->second;
194
195        assert (value->getType() == next->getType());
196
197        PHINode * phi = iBuilder->CreatePHI(value->getType(), 2, getName(var));
[5202]198        phi->addIncoming(value, ifEntryBlock);
[5227]199        phi->addIncoming(next, ifExitBlock);
[5160]200        f->second = phi;
[5202]201
202        assert (mMarkerMap[var] == phi);
[5227]203    }   
[4535]204}
205
[5202]206void PabloCompiler::compileWhile(const While * const whileStatement) {
[4595]207
[4870]208    PabloBlock * const whileBody = whileStatement->getBody();
[4647]209   
[4898]210    BasicBlock * whileEntryBlock = iBuilder->GetInsertBlock();
[4640]211
[5227]212    BasicBlock * whileBodyBlock = BasicBlock::Create(iBuilder->getContext(), "while.body", mFunction);
[5202]213
[5227]214    BasicBlock * whileEndBlock = BasicBlock::Create(iBuilder->getContext(), "while.end", mFunction);
[4640]215
[5227]216    const auto escaped = whileStatement->getEscaped();
217
[5169]218#ifdef ENABLE_BOUNDED_WHILE
219    PHINode * bound_phi = nullptr;  // Needed for bounded while loops.
220#endif
[4647]221    // On entry to the while structure, proceed to execute the first iteration
222    // of the loop body unconditionally.   The while condition is tested at the end of
223    // the loop.
[4640]224
[5227]225    mCarryManager->enterLoopScope(whileBody);
226
[4898]227    iBuilder->CreateBr(whileBodyBlock);
[5227]228
[4898]229    iBuilder->SetInsertPoint(whileBodyBlock);
[4640]230
[4647]231    //
232    // There are 3 sets of Phi nodes for the while loop.
233    // (1) Carry-ins: (a) incoming carry data first iterations, (b) zero thereafter
234    // (2) Carry-out accumulators: (a) zero first iteration, (b) |= carry-out of each iteration
235    // (3) Next nodes: (a) values set up before loop, (b) modified values calculated in loop.
[5169]236#ifdef ENABLE_BOUNDED_WHILE
237    // (4) The loop bound, if any.
238#endif
[4640]239
[5202]240    std::vector<std::pair<const Var *, PHINode *>> variants;
241
[4647]242    // for any Next nodes in the loop body, initialize to (a) pre-loop value.
[5227]243    for (const auto var : escaped) {
[5202]244        auto f = mMarkerMap.find(var);
245        if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
246            std::string tmp;
247            raw_string_ostream out(tmp);
248            PabloPrinter::print(var, out);
[5217]249            out << " is uninitialized prior to entering ";
250            PabloPrinter::print(whileStatement, out);
[5202]251            llvm::report_fatal_error(out.str());
252        }
[5227]253        Value * entryValue = f->second;
254        PHINode * phi = iBuilder->CreatePHI(entryValue->getType(), 2, getName(var));
255        phi->addIncoming(entryValue, whileEntryBlock);
[5160]256        f->second = phi;
[5202]257        assert(mMarkerMap[var] == phi);
258        variants.emplace_back(var, phi);
[4647]259    }
[5169]260#ifdef ENABLE_BOUNDED_WHILE
261    if (whileStatement->getBound()) {
[5170]262        bound_phi = iBuilder->CreatePHI(iBuilder->getSizeTy(), 2, "while_bound");
263        bound_phi->addIncoming(ConstantInt::get(iBuilder->getSizeTy(), whileStatement->getBound()), whileEntryBlock);
[5169]264    }
265#endif
[5227]266
267    mCarryManager->enterLoopBody(whileEntryBlock);
268
[4647]269    //
270    // Now compile the loop body proper.  Carry-out accumulated values
271    // and iterated values of Next nodes will be computed.
272    compileBlock(whileBody);
[4640]273
[5169]274    // After the whileBody has been compiled, we may be in a different basic block.
[4925]275    BasicBlock * whileExitBlock = iBuilder->GetInsertBlock();
[4640]276
[5227]277    mCarryManager->leaveLoopBody(whileExitBlock);
[4264]278
[4647]279    // Terminate the while loop body with a conditional branch back.
[5227]280    Value * condition = compileExpression(whileStatement->getCondition());
281    if (condition->getType() == iBuilder->getBitBlockType()) {
282        condition = iBuilder->bitblock_any(condition);
283    }
[5169]284#ifdef ENABLE_BOUNDED_WHILE
285    if (whileStatement->getBound()) {
[5234]286        Value * new_bound = iBuilder->CreateSub(bound_phi, iBuilder->getSize(1));
[5170]287        bound_phi->addIncoming(new_bound, whileExitBlock);
[5227]288        condition = iBuilder->CreateAnd(condition, iBuilder->CreateICmpUGT(new_bound, ConstantInt::getNullValue(iBuilder->getSizeTy())));
[5169]289    }
[5227]290#endif
[4576]291
[5202]292    // and for any variant nodes in the loop body
293    for (const auto variant : variants) {
294        const Var * var; PHINode * phi;
295        std::tie(var, phi) = variant;
296        const auto f = mMarkerMap.find(var);
297        if (LLVM_UNLIKELY(f == mMarkerMap.end() || f->second == phi)) {
298            std::string tmp;
299            raw_string_ostream out(tmp);
300            PabloPrinter::print(var, out);
301            out << " was not assigned a value.";
302            llvm::report_fatal_error(out.str());
[4264]303        }
[5227]304        Value * exitValue = f->second;
305        assert (phi->getType() == exitValue->getType());
306        phi->addIncoming(exitValue, whileExitBlock);
[5202]307        f->second = phi;
[4647]308    }
[4237]309
[5227]310    iBuilder->CreateCondBr(condition, whileBodyBlock, whileEndBlock);
311
[4898]312    iBuilder->SetInsertPoint(whileEndBlock);
[4640]313
[5227]314    mCarryManager->leaveLoopScope(whileEntryBlock, whileExitBlock);
315
[4535]316}
317
[4643]318void PabloCompiler::compileStatement(const Statement * stmt) {
[4674]319
[5202]320    if (LLVM_UNLIKELY(isa<If>(stmt))) {
321        compileIf(cast<If>(stmt));
322    } else if (LLVM_UNLIKELY(isa<While>(stmt))) {
323        compileWhile(cast<While>(stmt));
324    } else {
325        const PabloAST * expr = stmt;
326        Value * value = nullptr;
327        if (LLVM_UNLIKELY(isa<Assign>(stmt))) {
[4684]328
[5202]329            expr = cast<Assign>(stmt)->getVariable();
330            value = compileExpression(cast<Assign>(stmt)->getValue());
[4684]331
[5202]332            bool storeInstRequired = false;
333            if (LLVM_LIKELY(isa<Var>(expr))) {
[5217]334                for (unsigned i = 0; i < mKernel->getNumOfOutputs(); ++i) {
335                    if (expr == mKernel->getOutput(i)) {
[5202]336                        storeInstRequired = true;
337                        break;
338                    }
339                }
340            }
[4684]341
[5202]342            if (LLVM_UNLIKELY(storeInstRequired || isa<Extract>(expr))) {
343                const auto f = mMarkerMap.find(expr);
344                if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
345                    std::string tmp;
346                    raw_string_ostream out(tmp);
[5227]347                    out << "PabloCompiler: use-before-definition error: ";
[5217]348                    expr->print(out);
349                    out << " does not dominate ";
350                    stmt->print(out);
[5227]351                    llvm::report_fatal_error(out.str());
[5202]352                }
353                Value * const ptr = f->second;
[4684]354
[5202]355                assert (&(value->getContext()) == &(ptr->getContext()));
356
357                if (isa<Count>(cast<Assign>(stmt)->getValue())) {
358                    Value * count = iBuilder->CreateLoad(ptr);
[5204]359                    value = iBuilder->CreateTruncOrBitCast(value, count->getType());
360                    value = iBuilder->CreateAdd(value, count);
[5217]361                }
362
363                const Type * const type = value->getType();
364                if (isa<VectorType>(type) || isa<IntegerType>(type)) {
365                    const auto bitWidth = isa<VectorType>(type)
366                            ? cast<VectorType>(type)->getBitWidth()
367                            : cast<IntegerType>(type)->getBitWidth();
368                    iBuilder->CreateAlignedStore(value, ptr, bitWidth / 8);
369                } else {
[5204]370                    iBuilder->CreateStore(value, ptr);
[5202]371                }
[4959]372            }
[5202]373
374        } else if (const Extract * extract = dyn_cast<Extract>(stmt)) {
375            Value * array = compileExpression(extract->getArray(), false);
376            Value * index = compileExpression(extract->getIndex());
[5217]377            value = iBuilder->CreateGEP(array, {ConstantInt::getNullValue(index->getType()), index}, getName(stmt));
[5227]378        } else if (isa<And>(stmt)) {
379            value = compileExpression(stmt->getOperand(0));
380            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
381                value = iBuilder->simd_and(value, compileExpression(stmt->getOperand(1)));
382            }
383        } else if (isa<Or>(stmt)) {
384            value = compileExpression(stmt->getOperand(0));
385            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
386                value = iBuilder->simd_or(value, compileExpression(stmt->getOperand(1)));
387            }
388        } else if (isa<Xor>(stmt)) {
389            value = compileExpression(stmt->getOperand(0));
390            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
391                value = iBuilder->simd_xor(value, compileExpression(stmt->getOperand(1)));
392            }
[5202]393        } else if (const Sel * sel = dyn_cast<Sel>(stmt)) {
394            Value* ifMask = compileExpression(sel->getCondition());
395            Value* ifTrue = iBuilder->simd_and(ifMask, compileExpression(sel->getTrueExpr()));
396            Value* ifFalse = iBuilder->simd_and(iBuilder->simd_not(ifMask), compileExpression(sel->getFalseExpr()));
397            value = iBuilder->simd_or(ifTrue, ifFalse);
[5227]398        } else if (isa<Not>(stmt)) {
399            value = iBuilder->simd_not(compileExpression(stmt->getOperand(0)));
400        } else if (isa<Advance>(stmt)) {
401            const Advance * const adv = cast<Advance>(stmt);
402            // If our expr is an Extract op on a mutable Var then we need to pass the index value to the carry
403            // manager so that it properly selects the correct carry bit.
404            value = mCarryManager->advanceCarryInCarryOut(adv, compileExpression(adv->getExpression()));
[5202]405        } else if (const MatchStar * mstar = dyn_cast<MatchStar>(stmt)) {
406            Value * const marker = compileExpression(mstar->getMarker());
407            Value * const cc = compileExpression(mstar->getCharClass());
408            Value * const marker_and_cc = iBuilder->simd_and(marker, cc);
[5227]409            Value * const sum = mCarryManager->addCarryInCarryOut(mstar, marker_and_cc, cc);
[5202]410            value = iBuilder->simd_or(iBuilder->simd_xor(sum, cc), marker);
411        } else if (const ScanThru * sthru = dyn_cast<ScanThru>(stmt)) {
[5227]412            Value * const marker_expr = compileExpression(sthru->getScanFrom());
413            Value * const cc_expr = compileExpression(sthru->getScanThru());
414            Value * const sum = mCarryManager->addCarryInCarryOut(sthru, marker_expr, cc_expr);
[5202]415            value = iBuilder->simd_and(sum, iBuilder->simd_not(cc_expr));
416        } else if (const InFile * e = dyn_cast<InFile>(stmt)) {
[5217]417            Value * EOFmask = mKernel->getScalarField(mSelf, "EOFmask");
[5202]418            value = iBuilder->simd_xor(compileExpression(e->getExpr()), EOFmask);
419        } else if (const AtEOF * e = dyn_cast<AtEOF>(stmt)) {
[5217]420            Value * EOFbit = mKernel->getScalarField(mSelf, "EOFbit");
[5202]421            value = iBuilder->simd_and(compileExpression(e->getExpr()), EOFbit);
422        } else if (const Count * c = dyn_cast<Count>(stmt)) {
423            Value * const to_count = compileExpression(c->getExpr());
[5217]424            const unsigned counterSize = iBuilder->getSizeTy()->getBitWidth();
425            Value * const partial = iBuilder->simd_popcount(counterSize, to_count);
426            if (LLVM_UNLIKELY(counterSize <= 1)) {
427                value = partial;
428            } else {
429                value = iBuilder->mvmd_extract(counterSize, partial, 0);
430                const auto fields = (iBuilder->getBitBlockWidth() / counterSize);
431                for (unsigned i = 1; i < fields; ++i) {
432                    Value * temp = iBuilder->mvmd_extract(counterSize, partial, i);
433                    value = iBuilder->CreateAdd(value, temp);
434                }
[5141]435            }
[5202]436        } else if (const Lookahead * l = dyn_cast<Lookahead>(stmt)) {
437            PabloAST * const var = l->getExpr();
438            if (LLVM_UNLIKELY(!isa<Var>(var))) {
439                throw std::runtime_error("Lookahead operations may only be applied to input streams");
[5141]440            }
[5202]441            unsigned index = 0;
[5217]442            for (; index < mKernel->getNumOfInputs(); ++index) {
443                if (mKernel->getInput(index) == var) {
[5202]444                    break;
445                }
446            }
[5217]447            if (LLVM_UNLIKELY(index >= mKernel->getNumOfInputs())) {
[5202]448                throw std::runtime_error("Lookahead has an illegal Var operand");
449            }
450            const unsigned bit_shift = (l->getAmount() % iBuilder->getBitBlockWidth());
451            const unsigned block_shift = (l->getAmount() / iBuilder->getBitBlockWidth());
452            std::string inputName = var->getName()->to_string();;
[5217]453            Value * blockNo = mKernel->getScalarField(mSelf, blockNoScalar);
454            Value * lookAhead_blockPtr  = mKernel->getStreamSetBlockPtr(mSelf, inputName, iBuilder->CreateAdd(blockNo, ConstantInt::get(iBuilder->getSizeTy(), block_shift)));
[5202]455            Value * lookAhead_inputPtr = iBuilder->CreateGEP(lookAhead_blockPtr, {iBuilder->getInt32(0), iBuilder->getInt32(index)});
456            Value * lookAhead = iBuilder->CreateBlockAlignedLoad(lookAhead_inputPtr);
457            if (bit_shift == 0) {  // Simple case with no intra-block shifting.
458                value = lookAhead;
459            } else { // Need to form shift result from two adjacent blocks.
[5217]460                Value * lookAhead_blockPtr1  = mKernel->getStreamSetBlockPtr(mSelf, inputName, iBuilder->CreateAdd(blockNo, ConstantInt::get(iBuilder->getSizeTy(), block_shift + 1)));
[5202]461                Value * lookAhead_inputPtr1 = iBuilder->CreateGEP(lookAhead_blockPtr1, {iBuilder->getInt32(0), iBuilder->getInt32(index)});
462                Value * lookAhead1 = iBuilder->CreateBlockAlignedLoad(lookAhead_inputPtr1);
463                if (LLVM_UNLIKELY((bit_shift % 8) == 0)) { // Use a single whole-byte shift, if possible.
464                    value = iBuilder->mvmd_dslli(8, lookAhead1, lookAhead, (bit_shift / 8));
465                } else {
466                    Type  * const streamType = iBuilder->getIntNTy(iBuilder->getBitBlockWidth());
467                    Value * b1 = iBuilder->CreateBitCast(lookAhead1, streamType);
468                    Value * b0 = iBuilder->CreateBitCast(lookAhead, streamType);
469                    Value * result = iBuilder->CreateOr(iBuilder->CreateShl(b1, iBuilder->getBitBlockWidth() - bit_shift), iBuilder->CreateLShr(b0, bit_shift));
[5227]470                    value = iBuilder->CreateBitCast(result, iBuilder->getBitBlockType());
[5202]471                }
472            }
473
474        } else {
475            std::string tmp;
476            llvm::raw_string_ostream msg(tmp);
477            msg << "Internal error: ";
478            PabloPrinter::print(stmt, msg);
479            msg << " is not a recognized statement in the Pablo compiler.";
480            throw std::runtime_error(msg.str());
[5141]481        }
[5202]482
483        mMarkerMap[expr] = value;
484        if (DebugOptionIsSet(DumpTrace)) {
[5204]485            assert (expr->getName());
486            iBuilder->CallPrintRegister(expr->getName()->to_string(), value);
[5202]487        }
[4720]488    }
[4410]489}
490
[5202]491Value * PabloCompiler::compileExpression(const PabloAST * expr, const bool ensureLoaded) const {
[4959]492    if (LLVM_UNLIKELY(isa<Ones>(expr))) {
[4892]493        return iBuilder->allOnes();
[4959]494    } else if (LLVM_UNLIKELY(isa<Zeroes>(expr))) {
[4892]495        return iBuilder->allZeroes();
[5202]496    } else if (LLVM_UNLIKELY(isa<Integer>(expr))) {
497        return iBuilder->getInt64(cast<Integer>(expr)->value());
[5227]498    } else if (LLVM_UNLIKELY(isa<Operator>(expr))) {
499        const Operator * op = cast<Operator>(expr);
500        Value * lh = compileExpression(op->getLH());
501        Value * rh = compileExpression(op->getRH());
502        assert (lh->getType() == rh->getType());
503        switch (op->getClassTypeId()) {
504            case TypeId::Add:
505                return iBuilder->CreateAdd(lh, rh);
506            case TypeId::Subtract:
507                return iBuilder->CreateSub(lh, rh);
508            case TypeId::LessThan:
509                return iBuilder->CreateICmpSLT(lh, rh);
510            case TypeId::LessThanEquals:
511                return iBuilder->CreateICmpSLE(lh, rh);
512            case TypeId::Equals:
513                return iBuilder->CreateICmpEQ(lh, rh);
514            case TypeId::GreaterThanEquals:
515                return iBuilder->CreateICmpSGE(lh, rh);
516            case TypeId::GreaterThan:
517                return iBuilder->CreateICmpSGT(lh, rh);
518            case TypeId::NotEquals:
519                return iBuilder->CreateICmpNE(lh, rh);
520            default:
521                break;
522        }
523        std::string tmp;
524        raw_string_ostream out(tmp);
525        expr->print(out);
526        out << " is not a valid Operator";
527        llvm::report_fatal_error(out.str());
[4410]528    }
[5202]529    const auto f = mMarkerMap.find(expr);
[4643]530    if (LLVM_UNLIKELY(f == mMarkerMap.end())) {
[5160]531        std::string tmp;
532        llvm::raw_string_ostream out(tmp);
533        PabloPrinter::print(expr, out);
[5202]534        out << " was used before definition!";
[5160]535        throw std::runtime_error(out.str());
[4359]536    }
[5202]537    Value * value = f->second;
538    if (LLVM_UNLIKELY(isa<GetElementPtrInst>(value) && ensureLoaded)) {
539        value = iBuilder->CreateBlockAlignedLoad(value);
[4684]540    }
[5202]541    return value;
[4237]542}
[4268]543
[5227]544PabloCompiler::PabloCompiler(PabloKernel * kernel)
545: iBuilder(kernel->getBuilder())
546, mCarryManager(new CarryManager(iBuilder))
547, mKernel(kernel)
548, mFunction(nullptr) {
549
[4268]550}
[5227]551
552PabloCompiler::~PabloCompiler() {
553    delete mCarryManager;
554}
555
556}
Note: See TracBrowser for help on using the repository browser.