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

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

Bug fix for Mac OS compilation. Partial bug fix for CodeMotionPass?

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