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

Last change on this file since 5400 was 5385, checked in by cameron, 2 years ago

Disable lookahead CRLF - further work needed

File size: 27.8 KB
Line 
1/*
2 *  Copyright (c) 2014-16 International Characters.
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
7#include "pablo_compiler.h"
8#include <pablo/pablo_kernel.h>
9#include <pablo/pablo_toolchain.h>
10#include <pablo/codegenstate.h>
11#include <pablo/boolean.h>
12#include <pablo/arithmetic.h>
13#include <pablo/branch.h>
14#include <pablo/pe_advance.h>
15#include <pablo/pe_lookahead.h>
16#include <pablo/pe_matchstar.h>
17#include <pablo/pe_scanthru.h>
18#include <pablo/pe_infile.h>
19#include <pablo/pe_count.h>
20#include <pablo/pe_integer.h>
21#include <pablo/pe_string.h>
22#include <pablo/pe_zeroes.h>
23#include <pablo/pe_ones.h>
24#include <pablo/pe_var.h>
25#include <pablo/ps_assign.h>
26#include <pablo/carry_manager.h>
27#include <IR_Gen/idisa_builder.h>
28#include <kernels/streamset.h>
29#include <llvm/IR/Module.h>
30#include <llvm/Support/raw_os_ostream.h>
31
32using namespace llvm;
33
34namespace pablo {
35
36using TypeId = PabloAST::ClassTypeId;
37
38inline static unsigned getAlignment(const Value * const ptr) {
39    return ptr->getType()->getPrimitiveSizeInBits() / 8;
40}
41
42inline static unsigned getPointerElementAlignment(const Value * const ptr) {
43    return ptr->getType()->getPointerElementType()->getPrimitiveSizeInBits() / 8;
44}
45
46void PabloCompiler::compile() {
47    mCarryManager->initializeCodeGen();     
48    PabloBlock * const entryBlock = mKernel->getEntryBlock(); assert (entryBlock);
49    mMarker.emplace(entryBlock->createZeroes(), iBuilder->allZeroes());
50    mMarker.emplace(entryBlock->createOnes(), iBuilder->allOnes());
51    compileBlock(entryBlock);
52    mCarryManager->finalizeCodeGen();
53}
54
55void PabloCompiler::initializeKernelData() {
56    examineBlock(mKernel->getEntryBlock());
57    mCarryManager->initializeCarryData(mKernel);
58}
59
60void PabloCompiler::examineBlock(const PabloBlock * const block) {
61    for (const Statement * stmt : *block) {
62        if (LLVM_UNLIKELY(isa<Lookahead>(stmt))) {
63            const Lookahead * const la = cast<Lookahead>(stmt);
64            //assert ((isa<Var>(la->getExpr()) || isa<Extract>(la->getExpr())));
65            if (LLVM_LIKELY(la->getAmount() > mKernel->getLookAhead())) {
66                mKernel->setLookAhead(la->getAmount());
67            }
68        } else if (LLVM_UNLIKELY(isa<Branch>(stmt))) {
69            examineBlock(cast<Branch>(stmt)->getBody());
70        } else if (LLVM_UNLIKELY(isa<Count>(stmt))) {
71            mAccumulator.insert(std::make_pair(stmt, iBuilder->getInt32(mKernel->addUnnamedScalar(stmt->getType()))));
72        }
73    }   
74}
75
76inline void PabloCompiler::compileBlock(const PabloBlock * const block) {
77    for (const Statement * statement : *block) {
78        compileStatement(statement);
79    }
80}
81
82void PabloCompiler::compileIf(const If * const ifStatement) {
83    //
84    //  The If-ElseZero stmt:
85    //  if <predicate:expr> then <body:stmt>* elsezero <defined:var>* endif
86    //  If the value of the predicate is nonzero, then determine the values of variables
87    //  <var>* by executing the given statements.  Otherwise, the value of the
88    //  variables are all zero.  Requirements: (a) no variable that is defined within
89    //  the body of the if may be accessed outside unless it is explicitly
90    //  listed in the variable list, (b) every variable in the defined list receives
91    //  a value within the body, and (c) the logical consequence of executing
92    //  the statements in the event that the predicate is zero is that the
93    //  values of all defined variables indeed work out to be 0.
94    //
95    //  Simple Implementation with Phi nodes:  a phi node in the if exit block
96    //  is inserted for each variable in the defined variable list.  It receives
97    //  a zero value from the ifentry block and the defined value from the if
98    //  body.
99    //
100
101    BasicBlock * const ifEntryBlock = iBuilder->GetInsertBlock();
102    BasicBlock * const ifBodyBlock = mKernel->CreateBasicBlock("if.body");
103    BasicBlock * const ifEndBlock = mKernel->CreateBasicBlock("if.end");
104   
105    std::vector<std::pair<const Var *, Value *>> incoming;
106
107    for (const Var * var : ifStatement->getEscaped()) {
108        if (LLVM_UNLIKELY(var->isKernelParameter())) {
109            Value * marker = nullptr;
110            if (var->isScalar()) {
111                marker = mKernel->getScalarFieldPtr(var->getName());
112            } else if (var->isReadOnly()) {
113                marker = mKernel->getInputStreamBlockPtr(var->getName(), iBuilder->getInt32(0));
114            } else if (var->isReadNone()) {
115                marker = mKernel->getOutputStreamBlockPtr(var->getName(), iBuilder->getInt32(0));
116            }
117            mMarker[var] = marker;
118        } else {
119            auto f = mMarker.find(var);
120            if (LLVM_UNLIKELY(f == mMarker.end())) {
121                std::string tmp;
122                raw_string_ostream out(tmp);
123                var->print(out);
124                out << " is uninitialized prior to entering ";
125                ifStatement->print(out);
126                report_fatal_error(out.str());
127            }
128            incoming.emplace_back(var, f->second);
129        }
130    }
131
132    const PabloBlock * ifBody = ifStatement->getBody();
133   
134    mCarryManager->enterIfScope(ifBody);
135
136    Value * condition = compileExpression(ifStatement->getCondition());
137    if (condition->getType() == iBuilder->getBitBlockType()) {
138        condition = iBuilder->bitblock_any(mCarryManager->generateSummaryTest(condition));
139    }
140   
141    iBuilder->CreateCondBr(condition, ifBodyBlock, ifEndBlock);
142   
143    // Entry processing is complete, now handle the body of the if.
144    iBuilder->SetInsertPoint(ifBodyBlock);
145
146    mCarryManager->enterIfBody(ifEntryBlock);
147
148    compileBlock(ifBody);
149
150    mCarryManager->leaveIfBody(iBuilder->GetInsertBlock());
151
152    BasicBlock * ifExitBlock = iBuilder->GetInsertBlock();
153
154    iBuilder->CreateBr(ifEndBlock);
155
156    ifEndBlock->moveAfter(ifExitBlock);
157
158    //End Block
159    iBuilder->SetInsertPoint(ifEndBlock);
160
161    mCarryManager->leaveIfScope(ifEntryBlock, ifExitBlock);
162
163    for (const auto i : incoming) {
164        const Var * var; Value * incoming;
165        std::tie(var, incoming) = i;
166
167        auto f = mMarker.find(var);
168        if (LLVM_UNLIKELY(f == mMarker.end())) {
169            std::string tmp;
170            raw_string_ostream out(tmp);
171            out << "PHINode creation error: ";
172            var->print(out);
173            out << " was not assigned an outgoing value.";
174            report_fatal_error(out.str());
175        }
176
177        Value * const outgoing = f->second;
178        if (LLVM_UNLIKELY(incoming == outgoing)) {
179            continue;
180        }
181
182        if (LLVM_UNLIKELY(incoming->getType() != outgoing->getType())) {
183            std::string tmp;
184            raw_string_ostream out(tmp);
185            out << "PHINode creation error: incoming type of ";
186            var->print(out);
187            out << " (";
188            incoming->getType()->print(out);
189            out << ") differs from the outgoing type (";
190            outgoing->getType()->print(out);
191            out << ") within ";
192            ifStatement->print(out);
193            report_fatal_error(out.str());
194        }
195
196        PHINode * phi = iBuilder->CreatePHI(incoming->getType(), 2, var->getName());
197        phi->addIncoming(incoming, ifEntryBlock);
198        phi->addIncoming(outgoing, ifExitBlock);
199        f->second = phi;
200    }   
201}
202
203void PabloCompiler::compileWhile(const While * const whileStatement) {
204
205    const PabloBlock * const whileBody = whileStatement->getBody();
206
207    BasicBlock * whileEntryBlock = iBuilder->GetInsertBlock();
208
209    const auto escaped = whileStatement->getEscaped();
210
211#ifdef ENABLE_BOUNDED_WHILE
212    PHINode * bound_phi = nullptr;  // Needed for bounded while loops.
213#endif
214    // On entry to the while structure, proceed to execute the first iteration
215    // of the loop body unconditionally. The while condition is tested at the end of
216    // the loop.
217
218    for (const Var * var : escaped) {
219        if (LLVM_UNLIKELY(var->isKernelParameter())) {
220            Value * marker = nullptr;
221            if (var->isScalar()) {
222                marker = mKernel->getScalarFieldPtr(var->getName());
223            } else if (var->isReadOnly()) {
224                marker = mKernel->getInputStreamBlockPtr(var->getName(), iBuilder->getInt32(0));
225            } else if (var->isReadNone()) {
226                marker = mKernel->getOutputStreamBlockPtr(var->getName(), iBuilder->getInt32(0));
227            }
228            mMarker[var] = marker;
229        }
230    }
231
232    mCarryManager->enterLoopScope(whileBody);
233
234    BasicBlock * whileBodyBlock = mKernel->CreateBasicBlock("while.body");
235
236    iBuilder->CreateBr(whileBodyBlock);
237
238    iBuilder->SetInsertPoint(whileBodyBlock);
239
240    //
241    // There are 3 sets of Phi nodes for the while loop.
242    // (1) Carry-ins: (a) incoming carry data first iterations, (b) zero thereafter
243    // (2) Carry-out accumulators: (a) zero first iteration, (b) |= carry-out of each iteration
244    // (3) Next nodes: (a) values set up before loop, (b) modified values calculated in loop.
245#ifdef ENABLE_BOUNDED_WHILE
246    // (4) The loop bound, if any.
247#endif
248
249    std::vector<std::pair<const Var *, PHINode *>> variants;
250
251    // for any Next nodes in the loop body, initialize to (a) pre-loop value.
252    for (const auto var : escaped) {
253        auto f = mMarker.find(var);
254        if (LLVM_UNLIKELY(f == mMarker.end())) {
255            std::string tmp;
256            raw_string_ostream out(tmp);
257            out << "PHINode creation error: ";
258            var->print(out);
259            out << " is uninitialized prior to entering ";
260            whileStatement->print(out);
261            report_fatal_error(out.str());
262        }
263        Value * entryValue = f->second;
264        PHINode * phi = iBuilder->CreatePHI(entryValue->getType(), 2, var->getName());
265        phi->addIncoming(entryValue, whileEntryBlock);
266        f->second = phi;
267        assert(mMarker[var] == phi);
268        variants.emplace_back(var, phi);
269    }
270#ifdef ENABLE_BOUNDED_WHILE
271    if (whileStatement->getBound()) {
272        bound_phi = iBuilder->CreatePHI(iBuilder->getSizeTy(), 2, "while_bound");
273        bound_phi->addIncoming(iBuilder->getSize(whileStatement->getBound()), whileEntryBlock);
274    }
275#endif
276
277    mCarryManager->enterLoopBody(whileEntryBlock);
278
279    compileBlock(whileBody);
280
281    // After the whileBody has been compiled, we may be in a different basic block.
282
283    mCarryManager->leaveLoopBody(iBuilder->GetInsertBlock());
284
285
286#ifdef ENABLE_BOUNDED_WHILE
287    if (whileStatement->getBound()) {
288        Value * new_bound = iBuilder->CreateSub(bound_phi, iBuilder->getSize(1));
289        bound_phi->addIncoming(new_bound, whileExitBlock);
290        condition = iBuilder->CreateAnd(condition, iBuilder->CreateICmpUGT(new_bound, ConstantInt::getNullValue(iBuilder->getSizeTy())));
291    }
292#endif
293
294    BasicBlock * const whileExitBlock = iBuilder->GetInsertBlock();
295
296    // and for any variant nodes in the loop body
297    for (const auto variant : variants) {
298        const Var * var; PHINode * incomingPhi;
299        std::tie(var, incomingPhi) = variant;
300        const auto f = mMarker.find(var);
301        if (LLVM_UNLIKELY(f == mMarker.end())) {
302            std::string tmp;
303            raw_string_ostream out(tmp);
304            out << "PHINode creation error: ";
305            var->print(out);
306            out << " is no longer assigned a value.";
307            report_fatal_error(out.str());
308        }
309
310        Value * const outgoingValue = f->second;
311
312        if (LLVM_UNLIKELY(incomingPhi->getType() != outgoingValue->getType())) {
313            std::string tmp;
314            raw_string_ostream out(tmp);
315            out << "PHINode creation error: incoming type of ";
316            var->print(out);
317            out << " (";
318            incomingPhi->getType()->print(out);
319            out << ") differs from the outgoing type (";
320            outgoingValue->getType()->print(out);
321            out << ") within ";
322            whileStatement->print(out);
323            report_fatal_error(out.str());
324        }
325
326        incomingPhi->addIncoming(outgoingValue, whileExitBlock);
327    }
328
329    BasicBlock * whileEndBlock = mKernel->CreateBasicBlock("while.end");
330
331    // Terminate the while loop body with a conditional branch back.
332    Value * condition = compileExpression(whileStatement->getCondition());
333    if (condition->getType() == iBuilder->getBitBlockType()) {
334        condition = iBuilder->bitblock_any(mCarryManager->generateSummaryTest(condition));
335    }
336
337    iBuilder->CreateCondBr(condition, whileBodyBlock, whileEndBlock);
338
339    iBuilder->SetInsertPoint(whileEndBlock);
340
341    mCarryManager->leaveLoopScope(whileEntryBlock, whileExitBlock);
342
343}
344
345void PabloCompiler::compileStatement(const Statement * const stmt) {
346
347    if (LLVM_UNLIKELY(isa<If>(stmt))) {
348        compileIf(cast<If>(stmt));
349    } else if (LLVM_UNLIKELY(isa<While>(stmt))) {
350        compileWhile(cast<While>(stmt));
351    } else {
352        const PabloAST * expr = stmt;
353        Value * value = nullptr;
354        if (LLVM_UNLIKELY(isa<Assign>(stmt))) {
355            value = compileExpression(cast<Assign>(stmt)->getValue());
356            expr = cast<Assign>(stmt)->getVariable();
357            Value * ptr = nullptr;
358            if (LLVM_LIKELY(isa<Var>(expr))) {
359                const Var * var = cast<Var>(expr);
360                if (LLVM_UNLIKELY(var->isReadOnly())) {
361                    std::string tmp;
362                    raw_string_ostream out(tmp);
363                    out << mKernel->getName();
364                    out << " cannot assign value to ";
365                    var->print(out);
366                    out << ": ";
367                    var->print(out);
368                    out << " is read only";
369                    report_fatal_error(out.str());
370                }
371                if (var->isKernelParameter()) {
372                    if (var->isScalar()) {
373                        ptr = mKernel->getScalarFieldPtr(var->getName());
374                    } else {
375                        ptr = mKernel->getOutputStreamBlockPtr(var->getName(), iBuilder->getInt32(0));
376                    }
377                }
378            } else if (isa<Extract>(expr)) {
379                const auto f = mMarker.find(expr);
380                if (LLVM_UNLIKELY(f == mMarker.end())) {
381                    std::string tmp;
382                    raw_string_ostream out(tmp);
383                    out << mKernel->getName();
384                    out << " cannot assign value to ";
385                    expr->print(out);
386                    out << ": ";
387                    expr->print(out);
388                    out << " does not dominate ";
389                    stmt->print(out);
390                    report_fatal_error(out.str());
391                }
392                ptr = f->second;
393                assert (ptr);
394            }
395            if (ptr) {
396                iBuilder->CreateAlignedStore(value, ptr, getAlignment(value));
397                value = ptr;
398            }
399        } else if (const Extract * extract = dyn_cast<Extract>(stmt)) {
400            Value * index = compileExpression(extract->getIndex());
401            Var * const array = dyn_cast<Var>(extract->getArray());
402            if (LLVM_LIKELY(array && array->isKernelParameter())) {
403                if (array->isReadOnly()) {
404                    value = mKernel->getInputStreamBlockPtr(array->getName(), index);
405                } else if (array->isReadNone()) {
406                    value = mKernel->getOutputStreamBlockPtr(array->getName(), index);
407                } else {
408                    std::string tmp;
409                    raw_string_ostream out(tmp);
410                    out << mKernel->getName();
411                    out << " stream ";
412                    expr->print(out);
413                    out << " cannot be read or written to";
414                    report_fatal_error(out.str());
415                }
416            } else {
417                Value * ptr = compileExpression(extract->getArray(), false);
418                value = iBuilder->CreateGEP(ptr, {ConstantInt::getNullValue(index->getType()), index}, "extract");
419            }
420        } else if (isa<And>(stmt)) {
421            value = compileExpression(stmt->getOperand(0));
422            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
423                value = iBuilder->simd_and(value, compileExpression(stmt->getOperand(1)));
424            }
425        } else if (isa<Or>(stmt)) {
426            value = compileExpression(stmt->getOperand(0));
427            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
428                value = iBuilder->simd_or(value, compileExpression(stmt->getOperand(1)));
429            }
430        } else if (isa<Xor>(stmt)) {
431            value = compileExpression(stmt->getOperand(0));
432            for (unsigned i = 1; i < stmt->getNumOperands(); ++i) {
433                value = iBuilder->simd_xor(value, compileExpression(stmt->getOperand(1)));
434            }
435        } else if (const Sel * sel = dyn_cast<Sel>(stmt)) {
436            Value* ifMask = compileExpression(sel->getCondition());
437            Value* ifTrue = iBuilder->simd_and(ifMask, compileExpression(sel->getTrueExpr()));
438            Value* ifFalse = iBuilder->simd_and(iBuilder->simd_not(ifMask), compileExpression(sel->getFalseExpr()));
439            value = iBuilder->simd_or(ifTrue, ifFalse);
440        } else if (isa<Not>(stmt)) {
441            value = iBuilder->simd_not(compileExpression(stmt->getOperand(0)));
442        } else if (isa<Advance>(stmt)) {
443            const Advance * const adv = cast<Advance>(stmt);
444            // If our expr is an Extract op on a mutable Var then we need to pass the index value to the carry
445            // manager so that it properly selects the correct carry bit.
446            value = mCarryManager->advanceCarryInCarryOut(adv, compileExpression(adv->getExpression()));
447        } else if (const MatchStar * mstar = dyn_cast<MatchStar>(stmt)) {
448            Value * const marker = compileExpression(mstar->getMarker());
449            Value * const cc = compileExpression(mstar->getCharClass());
450            Value * const marker_and_cc = iBuilder->simd_and(marker, cc);
451            Value * const sum = mCarryManager->addCarryInCarryOut(mstar, marker_and_cc, cc);
452            value = iBuilder->simd_or(iBuilder->simd_xor(sum, cc), marker);
453        } else if (const ScanThru * sthru = dyn_cast<ScanThru>(stmt)) {
454            Value * const from = compileExpression(sthru->getScanFrom());
455            Value * const thru = compileExpression(sthru->getScanThru());
456            Value * const sum = mCarryManager->addCarryInCarryOut(sthru, from, thru);
457            value = iBuilder->simd_and(sum, iBuilder->simd_not(thru));
458        } else if (const ScanTo * sthru = dyn_cast<ScanTo>(stmt)) {
459            Value * const marker_expr = compileExpression(sthru->getScanFrom());
460            Value * const to = iBuilder->simd_xor(compileExpression(sthru->getScanTo()), mKernel->getScalarField("EOFmask"));
461            Value * const sum = mCarryManager->addCarryInCarryOut(sthru, marker_expr, iBuilder->simd_not(to));
462            value = iBuilder->simd_and(sum, to);
463        } else if (const AdvanceThenScanThru * sthru = dyn_cast<AdvanceThenScanThru>(stmt)) {
464            Value * const from = compileExpression(sthru->getScanFrom());
465            Value * const thru = compileExpression(sthru->getScanThru());
466            Value * const sum = mCarryManager->addCarryInCarryOut(sthru, from, iBuilder->simd_or(from, thru));
467            value = iBuilder->simd_and(sum, iBuilder->simd_not(thru));
468        } else if (const AdvanceThenScanTo * sthru = dyn_cast<AdvanceThenScanTo>(stmt)) {
469            Value * const from = compileExpression(sthru->getScanFrom());
470            Value * const to = iBuilder->simd_xor(compileExpression(sthru->getScanTo()), mKernel->getScalarField("EOFmask"));
471            Value * const sum = mCarryManager->addCarryInCarryOut(sthru, from, iBuilder->simd_or(from, iBuilder->simd_not(to)));
472            value = iBuilder->simd_and(sum, to);
473        } else if (const InFile * e = dyn_cast<InFile>(stmt)) {
474            Value * EOFmask = mKernel->getScalarField("EOFmask");
475            value = iBuilder->simd_and(compileExpression(e->getExpr()), iBuilder->simd_not(EOFmask));
476        } else if (const AtEOF * e = dyn_cast<AtEOF>(stmt)) {
477            Value * EOFbit = mKernel->getScalarField("EOFbit");
478            value = iBuilder->simd_and(compileExpression(e->getExpr()), EOFbit);
479        } else if (const Count * c = dyn_cast<Count>(stmt)) {
480            Value * EOFbit = mKernel->getScalarField("EOFbit");
481            Value * EOFmask = mKernel->getScalarField("EOFmask");
482            Value * const to_count = iBuilder->simd_and(iBuilder->simd_or(iBuilder->simd_not(EOFmask), EOFbit), compileExpression(c->getExpr()));
483            const unsigned counterSize = iBuilder->getSizeTy()->getBitWidth();
484            const auto f = mAccumulator.find(c);
485            if (LLVM_UNLIKELY(f == mAccumulator.end())) {
486                report_fatal_error("Unknown accumulator: " + c->getName().str());
487            }
488            Value * ptr = mKernel->getScalarFieldPtr(f->second);
489            const auto alignment = getPointerElementAlignment(ptr);
490            Value * count = iBuilder->CreateAlignedLoad(ptr, alignment, c->getName() + "_accumulator");
491            Value * const partial = iBuilder->simd_popcount(counterSize, to_count);
492            if (LLVM_UNLIKELY(counterSize <= 1)) {
493                value = partial;
494            } else {
495                value = iBuilder->mvmd_extract(counterSize, partial, 0);
496                const auto fields = (iBuilder->getBitBlockWidth() / counterSize);
497                for (unsigned i = 1; i < fields; ++i) {
498                    Value * temp = iBuilder->mvmd_extract(counterSize, partial, i);
499                    value = iBuilder->CreateAdd(value, temp);
500                }
501            }
502            value = iBuilder->CreateAdd(value, count);
503            iBuilder->CreateAlignedStore(value, ptr, alignment);
504        } else if (const Lookahead * l = dyn_cast<Lookahead>(stmt)) {
505            Var * var = nullptr;
506            PabloAST * stream = l->getExpr();
507            Value * index = iBuilder->getInt32(0);
508            if (LLVM_UNLIKELY(isa<Extract>(stream))) {
509                var = dyn_cast<Var>(cast<Extract>(stream)->getArray());
510                index = compileExpression(cast<Extract>(stream)->getIndex());
511                if (!var->isKernelParameter() || var->isReadNone()) {
512                    std::string tmp;
513                    raw_string_ostream out(tmp);
514                    out << "Lookahead operation cannot be applied to ";
515                    stmt->print(out);
516                    out << " - not an input stream";
517                    report_fatal_error(out.str());
518                }
519            }
520            if (LLVM_LIKELY(isa<Var>(stream))) {
521                var = cast<Var>(stream);
522                if (!var->isKernelParameter() || var->isReadNone()) {
523                    std::string tmp;
524                    raw_string_ostream out(tmp);
525                    out << "Lookahead operation cannot be applied to ";
526                    stmt->print(out);
527                    out << ": ";
528                    var->print(out);
529                    out << " is not an input stream";
530                    report_fatal_error(out.str());
531                }
532            }
533            const auto bit_shift = (l->getAmount() % iBuilder->getBitBlockWidth());
534            const auto block_shift = (l->getAmount() / iBuilder->getBitBlockWidth());
535
536            Value * ptr = mKernel->getAdjustedInputStreamBlockPtr(iBuilder->getSize(block_shift), var->getName(), index);
537            Value * lookAhead = iBuilder->CreateBlockAlignedLoad(ptr);
538            if (bit_shift == 0) {  // Simple case with no intra-block shifting.
539                value = lookAhead;
540            } else { // Need to form shift result from two adjacent blocks.
541                Value * ptr = mKernel->getAdjustedInputStreamBlockPtr(iBuilder->getSize(block_shift + 1), var->getName(), index);
542                Value * lookAhead1 = iBuilder->CreateBlockAlignedLoad(ptr);
543                if (LLVM_UNLIKELY((bit_shift % 8) == 0)) { // Use a single whole-byte shift, if possible.
544                    value = iBuilder->mvmd_dslli(8, lookAhead1, lookAhead, (bit_shift / 8));
545                } else {
546                    Type  * const streamType = iBuilder->getIntNTy(iBuilder->getBitBlockWidth());
547                    Value * b1 = iBuilder->CreateBitCast(lookAhead1, streamType);
548                    Value * b0 = iBuilder->CreateBitCast(lookAhead, streamType);
549                    Value * result = iBuilder->CreateOr(iBuilder->CreateShl(b1, iBuilder->getBitBlockWidth() - bit_shift), iBuilder->CreateLShr(b0, bit_shift));
550                    value = iBuilder->CreateBitCast(result, iBuilder->getBitBlockType());
551                }
552            }
553
554        } else {
555            std::string tmp;
556            raw_string_ostream out(tmp);
557            out << "PabloCompiler: ";
558            stmt->print(out);
559            out << " was not recognized by the compiler";
560            report_fatal_error(out.str());
561        }
562
563        mMarker[expr] = value;
564        if (DebugOptionIsSet(DumpTrace)) {
565            const String & name = isa<Var>(expr) ? cast<Var>(expr)->getName() : cast<Statement>(expr)->getName();
566            if (value->getType()->isPointerTy()) {
567                value = iBuilder->CreateLoad(value);
568            }
569            if (value->getType()->isVectorTy()) {
570                iBuilder->CallPrintRegister(name.str(), value);
571            } else if (value->getType()->isIntegerTy()) {
572                iBuilder->CallPrintInt(name.str(), value);
573            }
574        }
575    }
576}
577
578Value * PabloCompiler::compileExpression(const PabloAST * expr, const bool ensureLoaded) const {
579    if (LLVM_UNLIKELY(isa<Ones>(expr))) {
580        return iBuilder->allOnes();
581    } else if (LLVM_UNLIKELY(isa<Zeroes>(expr))) {
582        return iBuilder->allZeroes();
583    } else if (LLVM_UNLIKELY(isa<Integer>(expr))) {
584        return ConstantInt::get(cast<Integer>(expr)->getType(), cast<Integer>(expr)->value());
585    } else if (LLVM_UNLIKELY(isa<Operator>(expr))) {
586        const Operator * op = cast<Operator>(expr);
587        Value * lh = compileExpression(op->getLH());
588        Value * rh = compileExpression(op->getRH());
589        if (LLVM_UNLIKELY(lh->getType() != rh->getType())) {
590            std::string tmp;
591            raw_string_ostream out(tmp);
592            out << "Operator creation error: left hand type of ";
593            expr->print(out);
594            out << " (";
595            lh->getType()->print(out);
596            out << ") differs from right hand type (";
597            rh->getType()->print(out);
598            out << ")";
599            report_fatal_error(out.str());
600        }
601        switch (op->getClassTypeId()) {
602            case TypeId::Add:
603                return iBuilder->CreateAdd(lh, rh);
604            case TypeId::Subtract:
605                return iBuilder->CreateSub(lh, rh);
606            case TypeId::LessThan:
607                return iBuilder->CreateICmpSLT(lh, rh);
608            case TypeId::LessThanEquals:
609                return iBuilder->CreateICmpSLE(lh, rh);
610            case TypeId::Equals:
611                return iBuilder->CreateICmpEQ(lh, rh);
612            case TypeId::GreaterThanEquals:
613                return iBuilder->CreateICmpSGE(lh, rh);
614            case TypeId::GreaterThan:
615                return iBuilder->CreateICmpSGT(lh, rh);
616            case TypeId::NotEquals:
617                return iBuilder->CreateICmpNE(lh, rh);
618            default: break;
619        }
620        std::string tmp;
621        raw_string_ostream out(tmp);
622        out << "PabloCompiler: ";
623        expr->print(out);
624        out << " is not a valid Operator";
625        report_fatal_error(out.str());
626    }
627    const auto f = mMarker.find(expr);
628    if (LLVM_UNLIKELY(f == mMarker.end())) {
629        std::string tmp;
630        raw_string_ostream out(tmp);
631        out << "PabloCompiler: ";
632        expr->print(out);
633        out << " was used before definition!";
634        report_fatal_error(out.str());
635    }
636    Value * value = f->second;
637    if (LLVM_UNLIKELY(isa<GetElementPtrInst>(value) && ensureLoaded)) {
638        value = iBuilder->CreateAlignedLoad(value, getPointerElementAlignment(value));
639    }
640    return value;
641}
642
643PabloCompiler::PabloCompiler(PabloKernel * kernel)
644: iBuilder(kernel->getBuilder())
645, mKernel(kernel)
646, mCarryManager(new CarryManager(iBuilder)) {
647
648}
649
650PabloCompiler::~PabloCompiler() {
651    delete mCarryManager;
652}
653
654}
Note: See TracBrowser for help on using the repository browser.