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

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

Merged PabloFunction? and PabloKernel? classes. Updated projects where necessary.

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