source: icGREP/icgrep-devel/icgrep/kernels/sequential_kernel.cpp @ 5941

Last change on this file since 5941 was 5905, checked in by xwa163, 16 months ago
  1. Fix some bugs in match copy kernel
  2. Remove some legacy codes from match copy kernel and sequential kernel
File size: 25.3 KB
Line 
1
2#include "sequential_kernel.h"
3#include <kernels/kernel_builder.h>
4#include <kernels/streamset.h>
5#include <iostream>
6#include <string>
7#include <llvm/Support/raw_ostream.h>
8
9
10using namespace llvm;
11using namespace kernel;
12using namespace parabix;
13using namespace std;
14
15#define SequentialSegmentStateKey ("SequentialSegment_State")
16#define CountForwardMaxPosTempKey ("CountForwardMaxPosTempKey")
17
18
19namespace kernel {
20    SequentialKernel::SequentialKernel(
21            const std::unique_ptr<kernel::KernelBuilder> &iBuilder,
22            std::string &&kernelName,
23            std::vector<Binding> &&stream_inputs,
24            std::vector<Binding> &&stream_outputs,
25            std::vector<Binding> &&scalar_parameters,
26            std::vector<Binding> &&scalar_outputs,
27            std::vector<Binding> &&internal_scalars) :
28            MultiBlockKernel(std::move(kernelName), std::move(stream_inputs), std::move(stream_outputs),
29                             std::move(scalar_parameters), std::move(scalar_outputs), std::move(internal_scalars)) {
30        addScalar(iBuilder->getSizeTy(), SequentialSegmentStateKey);
31        addScalar(iBuilder->getSizeTy(), CountForwardMaxPosTempKey);
32        addScalar(iBuilder->getSizeTy(), "tempClear");
33
34    }
35
36
37    void SequentialKernel::recordCountForwardTempMaxPos(const std::unique_ptr<KernelBuilder> &iBuilder, Value *maxPos) {
38        if (maxPos) {
39            iBuilder->setScalarField(CountForwardMaxPosTempKey, maxPos);
40        }
41    }
42
43    Value *SequentialKernel::restoreCountForwardTempMaxPos(const std::unique_ptr<KernelBuilder> &iBuilder,
44                                                           Value *currentMaxPos) {
45        if (currentMaxPos) {
46            return iBuilder->getScalarField(CountForwardMaxPosTempKey);
47        }
48        return NULL;
49    }
50
51    void SequentialKernel::generateMultiBlockLogic(const std::unique_ptr<KernelBuilder> &iBuilder,
52                                                   Value *const numOfStrides) {
53        BasicBlock *entryBlock = iBuilder->GetInsertBlock();
54//        iBuilder->CallPrintInt("entry", iBuilder->getSize(1));
55//        iBuilder->CallPrintInt("available", iBuilder->getAvailableItemCount("byteStream"));
56
57        // AfterEntryBlock will be the entry block of subclass if it is initial state
58        BasicBlock *afterEntryBlock = iBuilder->CreateBasicBlock("afterEntryBlock");
59        this->exitBlock = iBuilder->CreateBasicBlock("exitBlock");
60
61        this->stateBlocks.push_back(afterEntryBlock); // index 0 will be initial state
62        iBuilder->SetInsertPoint(afterEntryBlock);
63        this->generateDoSequentialSegmentMethod(iBuilder);
64
65        iBuilder->CreateBr(this->exitBlock);
66        iBuilder->SetInsertPoint(this->exitBlock);
67
68
69        iBuilder->SetInsertPoint(entryBlock);
70
71
72        // Create Indirect Branch
73        std::vector<Constant *> blockAddressVector = std::vector<Constant *>();
74        for (BasicBlock *bb : this->stateBlocks) {
75            blockAddressVector.push_back(BlockAddress::get(bb));
76        }
77        Constant *labels = ConstantVector::get(blockAddressVector);
78
79        Value *target = iBuilder->CreateExtractElement(labels, iBuilder->getScalarField(SequentialSegmentStateKey));
80        IndirectBrInst *indirectBr = iBuilder->CreateIndirectBr(target);
81        for (BasicBlock *bb : this->stateBlocks) {
82            indirectBr->addDestination(bb);
83        }
84
85        iBuilder->SetInsertPoint(this->exitBlock);
86    }
87
88    void SequentialKernel::generateDoSequentialSegmentMethod(const std::unique_ptr<KernelBuilder> &iBuilder) {
89        // Will be override by subclass
90    }
91
92    // Cursor
93    std::string SequentialKernel::generateCursorFullname(std::string cursorName) {
94        return "Cursor_" + cursorName;
95    }
96
97    void SequentialKernel::initBufferCursor(const std::unique_ptr<KernelBuilder> &iBuilder,
98                                            std::vector<std::string> cursorNames) {
99        for (std::string name : cursorNames) {
100            addScalar(iBuilder->getSizeTy(), this->generateCursorFullname(name));
101        }
102    }
103
104    Value *SequentialKernel::getCursorValue(const std::unique_ptr<KernelBuilder> &iBuilder, std::string cursorName) {
105        return iBuilder->getScalarField(this->generateCursorFullname(cursorName));
106    }
107
108    void SequentialKernel::setCursorValue(const std::unique_ptr<KernelBuilder> &iBuilder, std::string cursorName,
109                                          Value *value) {
110        iBuilder->setScalarField(this->generateCursorFullname(cursorName), value);
111    }
112
113    void SequentialKernel::advanceCursor(const std::unique_ptr<KernelBuilder> &iBuilder, std::string cursorName,
114                                         llvm::Value *nums) {
115        std::string fullname = this->generateCursorFullname(cursorName);
116        Value *cursorValue = iBuilder->getScalarField(fullname);
117        cursorValue = iBuilder->CreateAdd(cursorValue, nums);
118        iBuilder->setScalarField(fullname, cursorValue);
119    }
120
121    void SequentialKernel::advanceCursorUntilPos(const std::unique_ptr<KernelBuilder> &iBuilder, std::string cursorName,
122                                                 llvm::Value *position) {
123        std::string fullname = this->generateCursorFullname(cursorName);
124        Value *cursorValue = iBuilder->getScalarField(fullname);
125        iBuilder->CreateAssert(iBuilder->CreateICmpSLE(cursorValue, position),
126                               cursorName + " Cursor can only move forward");
127        iBuilder->setScalarField(fullname, position);
128    }
129
130
131    // forwardBits, packEnd, exceedAvailable
132    std::pair<llvm::Value *, std::pair<llvm::Value *, llvm::Value *>>
133    SequentialKernel::genereateCountForwardBitsOnePack(
134            const std::unique_ptr<KernelBuilder> &iBuilder,
135            std::string inputStreamBufferName,
136            llvm::Value *cursorValue,
137            bool isZero
138    ) {
139        size_t bufferSize = this->getInputBufferSize(iBuilder, inputStreamBufferName);
140        Value *bufferOffsetMask = iBuilder->getSize(bufferSize - 1);
141
142        Value *actualBufferOffset = iBuilder->CreateAnd(bufferOffsetMask, cursorValue);
143
144        Value *packIndex = iBuilder->CreateLShr(actualBufferOffset, iBuilder->getSize(std::log2(64)));
145
146        Value *countStartBitIndex = iBuilder->CreateAnd(actualBufferOffset, iBuilder->getSize(64 - 1));
147
148        Value *inputStreamPtr = iBuilder->getInputStreamBlockPtr(inputStreamBufferName, iBuilder->getInt32(0));
149        inputStreamPtr = iBuilder->CreatePointerCast(inputStreamPtr, iBuilder->getInt64Ty()->getPointerTo());
150        Value *packData = iBuilder->CreateLoad(iBuilder->CreateGEP(inputStreamPtr, packIndex));
151
152
153        packData = iBuilder->CreateLShr(packData, countStartBitIndex);
154
155        if (!isZero) {
156            packData = iBuilder->CreateNot(packData);
157        }
158        Value *forwardZeroCount = iBuilder->CreateCountForwardZeroes(packData);
159
160
161        Value *isEndOfPack = iBuilder->CreateICmpUGE(iBuilder->CreateAdd(countStartBitIndex, forwardZeroCount),
162                                                     iBuilder->getSize(64));
163        forwardZeroCount = iBuilder->CreateSelect(
164                isEndOfPack,
165                iBuilder->CreateSub(iBuilder->getSize(64), countStartBitIndex),
166                forwardZeroCount
167        );
168
169        Value *newCursorValue = iBuilder->CreateAdd(cursorValue, forwardZeroCount);
170        Value *itemTotal = iBuilder->CreateAdd(iBuilder->getAvailableItemCount(inputStreamBufferName),
171                                               iBuilder->getProcessedItemCount(inputStreamBufferName));
172
173        Value *isExceedAvailable = iBuilder->CreateICmpUGE(newCursorValue, itemTotal);
174
175        newCursorValue = iBuilder->CreateSelect(isExceedAvailable, itemTotal, newCursorValue);
176
177//        Value* isNotFinished = iBuilder->CreateOr(isEndOfPack, isExceedAvailable);
178//        Value* isFinished = iBuilder->CreateNot(isNotFinished);
179        return std::make_pair(iBuilder->CreateSub(newCursorValue, cursorValue),
180                              make_pair(isEndOfPack, isExceedAvailable));
181    };
182
183    // pair<forwardZeros, isFinished>
184    std::pair<llvm::Value *, llvm::Value *> SequentialKernel::generateCountForwardBits(
185            const std::unique_ptr<KernelBuilder> &iBuilder,
186            std::string inputStreamBufferName,
187            llvm::Value *cursorValue,
188            bool isZero,
189            llvm::Value *maxPos
190    ) {
191        BasicBlock *entryBlock = iBuilder->CreateBasicBlock("count_forward_bit_entry");
192        iBuilder->CreateBr(entryBlock);
193        iBuilder->SetInsertPoint(entryBlock);
194
195        BasicBlock *exitBlock = iBuilder->CreateBasicBlock("count_forward_bit_exit");
196
197
198        auto onePackResult = genereateCountForwardBitsOnePack(iBuilder, inputStreamBufferName, cursorValue, isZero);
199
200        Value *forwardCount = onePackResult.first;
201        Value *isEndOfPack = onePackResult.second.first;
202        Value *isExceedAvailable = onePackResult.second.second;
203        Value *newCursorValue = iBuilder->CreateAdd(cursorValue, forwardCount);
204
205        Value *isNotFinished = iBuilder->CreateOr(isEndOfPack, isExceedAvailable);
206        Value *isFinished = iBuilder->CreateNot(isNotFinished);
207
208        if (maxPos) {
209            Value *reachMaxPos = iBuilder->CreateICmpUGE(newCursorValue, maxPos);
210            isFinished = iBuilder->CreateSelect(
211                    reachMaxPos,
212                    iBuilder->getInt1(true),
213                    isFinished
214            );
215            newCursorValue = iBuilder->CreateSelect(
216                    reachMaxPos,
217                    maxPos,
218                    newCursorValue
219            );
220
221        }
222
223        iBuilder->CreateBr(exitBlock);
224        iBuilder->SetInsertPoint(exitBlock);
225
226        return std::make_pair(iBuilder->CreateSub(newCursorValue, cursorValue), isFinished);
227
228    };
229
230    std::pair<llvm::Value *, llvm::Value *>
231    SequentialKernel::generateCountForwardOnes(const unique_ptr<KernelBuilder> &iBuilder, string inputStreamBufferName,
232                                               Value *beginOffset, Value *maxPos) {
233        return this->generateCountForwardBits(iBuilder, inputStreamBufferName, beginOffset, false, maxPos);
234    };
235
236    std::pair<llvm::Value *, llvm::Value *>
237    SequentialKernel::generateCountForwardZeros(const unique_ptr<KernelBuilder> &iBuilder, string inputStreamBufferName,
238                                                Value *beginOffset, Value *maxPos) {
239        return this->generateCountForwardBits(iBuilder, inputStreamBufferName, beginOffset, true, maxPos);
240    }
241
242
243    BasicBlock *
244    SequentialKernel::advanceCursorUntilNextOne(const std::unique_ptr<KernelBuilder> &iBuilder, std::string cursorName,
245                                                std::string inputStreamBufferName, Value *maxPos) {
246        BasicBlock *entryBlock = iBuilder->CreateBasicBlock("advance_cursor_until_next_one_entry");
247
248        this->recordCountForwardTempMaxPos(iBuilder, maxPos);
249
250        iBuilder->CreateBr(entryBlock);
251        iBuilder->SetInsertPoint(entryBlock);
252
253
254        // StateIndex will be increased in waitCursorUntilInputAvailable
255        this->waitCursorUntilInputAvailable(iBuilder, cursorName, inputStreamBufferName);
256
257        BasicBlock *countForwareZeroBlock = iBuilder->CreateBasicBlock("advance_cursor_until_next_one_count_block");
258        BasicBlock *exitBlock = iBuilder->CreateBasicBlock("advance_cursor_until_next_one_exit_block");
259
260        iBuilder->CreateBr(countForwareZeroBlock);
261        iBuilder->SetInsertPoint(countForwareZeroBlock);
262
263        Value *cursorValue = this->getCursorValue(iBuilder, cursorName);
264
265        maxPos = this->restoreCountForwardTempMaxPos(iBuilder, maxPos);
266
267        auto retValue = this->generateCountForwardZeros(iBuilder, inputStreamBufferName, cursorValue, maxPos);
268
269        cursorValue = iBuilder->CreateAdd(cursorValue, retValue.first);
270        Value *isFinished = retValue.second;
271
272
273        //TODO Add additional handle for isFinish (is isFinish === false, the next pack will always start from index 0), avoid using waitCursorUntilInputAvailable in the second loop
274
275        this->setCursorValue(iBuilder, cursorName, cursorValue);
276
277        iBuilder->CreateCondBr(isFinished, exitBlock, entryBlock);
278        //TODO add index bits for count forward zeros and ones
279        iBuilder->SetInsertPoint(exitBlock);
280        return exitBlock;
281    }
282
283
284    BasicBlock *SequentialKernel::advanceCursorUntilNextZero(
285            const std::unique_ptr<KernelBuilder> &iBuilder, std::string cursorName, std::string inputStreamBufferName,
286            Value *maxPos) {
287        BasicBlock *entryBlock = iBuilder->CreateBasicBlock("advance_cursor_until_next_zero_entry");
288
289        this->recordCountForwardTempMaxPos(iBuilder, maxPos);
290
291        iBuilder->CreateBr(entryBlock);
292        iBuilder->SetInsertPoint(entryBlock);
293
294        this->waitCursorUntilInputAvailable(iBuilder, cursorName, inputStreamBufferName);
295
296        BasicBlock *countForwareOneBlock = iBuilder->CreateBasicBlock("advance_cursor_until_next_zero_count_block");
297        BasicBlock *exitBlock = iBuilder->CreateBasicBlock("advance_cursor_until_next_zero_exit_block");
298
299        iBuilder->CreateBr(countForwareOneBlock);
300        iBuilder->SetInsertPoint(countForwareOneBlock);
301
302        Value *cursorValue = this->getCursorValue(iBuilder, cursorName);
303
304        maxPos = this->restoreCountForwardTempMaxPos(iBuilder, maxPos);
305
306        auto retValue = this->generateCountForwardOnes(iBuilder, inputStreamBufferName, cursorValue, maxPos);
307
308        this->advanceCursor(iBuilder, cursorName, retValue.first);
309
310        Value *isFinished = retValue.second;
311
312        iBuilder->CreateCondBr(isFinished, exitBlock, entryBlock);
313        //TODO add index bits for count forward zeros and ones
314        iBuilder->SetInsertPoint(exitBlock);
315        return exitBlock;
316    }
317
318
319    BasicBlock *SequentialKernel::waitCursorUntilInputAvailable(const std::unique_ptr<KernelBuilder> &iBuilder,
320                                                                std::string cursorName,
321                                                                std::string inputStreamBufferName) {
322//        BasicBlock* entryBlock = iBuilder->GetInsertBlock();
323        Value *nextStateValue = iBuilder->getSize(this->stateBlocks.size());
324
325        BasicBlock *restoreBlock = iBuilder->CreateBasicBlock("wait_cursor_until_input_available_restore");
326        BasicBlock *continueBlock = iBuilder->CreateBasicBlock("wait_cursor_until_input_available_continue");
327
328        this->stateBlocks.push_back(restoreBlock);
329
330        iBuilder->CreateBr(restoreBlock);
331
332        iBuilder->SetInsertPoint(restoreBlock);
333
334        Value *cursorValue = this->getCursorValue(iBuilder, cursorName);
335        Value *itemTotal = iBuilder->CreateAdd(iBuilder->getAvailableItemCount(inputStreamBufferName),
336                                               iBuilder->getProcessedItemCount(inputStreamBufferName));
337        Value *isAvailable = iBuilder->CreateICmpULT(cursorValue, itemTotal);
338
339        Value *nextState = iBuilder->CreateSelect(isAvailable, iBuilder->getSize(0), nextStateValue);
340        iBuilder->setScalarField(SequentialSegmentStateKey, nextState);
341
342        iBuilder->CreateCondBr(isAvailable, continueBlock, this->exitBlock);
343
344        iBuilder->SetInsertPoint(continueBlock);
345
346        return continueBlock;
347
348    }
349
350    size_t SequentialKernel::getInputBufferSize(const unique_ptr<KernelBuilder> &iBuilder, string bufferName) {
351        //TODO codegen::BlockSize == iBuilder->getStride() ?
352        return this->getInputStreamSetBuffer(bufferName)->getBufferBlocks() * iBuilder->getStride();
353    }
354
355    size_t SequentialKernel::getOutputBufferSize(const unique_ptr<KernelBuilder> &iBuilder, string bufferName) {
356        return this->getOutputStreamSetBuffer(bufferName)->getBufferBlocks() * iBuilder->getStride();
357    }
358
359    Value *SequentialKernel::offsetToPackBaseOffset(const unique_ptr<KernelBuilder> &iBuilder, Value *offset) {
360        return iBuilder->CreateShl(
361                this->offsetToPackIndex(iBuilder, offset),
362                iBuilder->getSize(std::log2(64))
363        );
364    }
365
366    Value *SequentialKernel::offsetToPackIndex(const unique_ptr<KernelBuilder> &iBuilder, Value *offset) {
367        return iBuilder->CreateLShr(offset, iBuilder->getSize(std::log2(64)));
368    }
369
370    Value *SequentialKernel::offsetToPackOffset(const unique_ptr<KernelBuilder> &iBuilder, Value *offset) {
371        return iBuilder->CreateAnd(offset, iBuilder->getSize(64 - 1));
372    }
373
374    Value *
375    SequentialKernel::offsetToActualBufferOffset(const unique_ptr<KernelBuilder> &iBuilder, string inputBufferName,
376                                                 Value *offset) {
377        size_t bufferSize = this->getInputBufferSize(iBuilder, inputBufferName);
378        Value *bufferOffsetMask = iBuilder->getSize(bufferSize - 1);
379        return iBuilder->CreateAnd(bufferOffsetMask, offset);
380    }
381
382    Value *
383    SequentialKernel::generateLoadCircularInputPack(const unique_ptr<KernelBuilder> &iBuilder, string inputBufferName,
384                                                    Value *offset) {
385        Value *actualBufferOffset = this->offsetToActualBufferOffset(iBuilder, inputBufferName, offset);
386        Value *packIndex = this->offsetToPackIndex(iBuilder, actualBufferOffset);
387//        Value* countStartBitIndex = this->offsetToPackOffset(iBuilder, actualBufferOffset);
388
389
390        Value *inputStreamPtr = iBuilder->getInputStreamBlockPtr(inputBufferName, iBuilder->getInt32(0));
391        inputStreamPtr = iBuilder->CreatePointerCast(inputStreamPtr, iBuilder->getInt64Ty()->getPointerTo());
392        return iBuilder->CreateLoad(iBuilder->CreateGEP(inputStreamPtr, packIndex));
393
394//        packData = iBuilder->CreateLShr(packData, countStartBitIndex);
395
396    }
397
398    Value *
399    SequentialKernel::generateLoadCircularInput(const unique_ptr<KernelBuilder> &iBuilder, string inputBufferName,
400                                                Value *offset, Type *pointerType) {
401        size_t inputSize = this->getInputBufferSize(iBuilder, inputBufferName);
402        Value *offsetMask = iBuilder->getSize(inputSize - 1);
403        Value *maskedOffset = iBuilder->CreateAnd(offsetMask, offset);
404
405        Value *inputBufferPtr = iBuilder->getRawInputPointer(inputBufferName, iBuilder->getSize(0));
406
407        inputBufferPtr = iBuilder->CreatePointerCast(inputBufferPtr, pointerType);
408        return iBuilder->CreateLoad(iBuilder->CreateGEP(inputBufferPtr, maskedOffset));
409    }
410
411    Value *SequentialKernel::generateLoadSourceInputByte(const std::unique_ptr<KernelBuilder> &iBuilder,
412                                                         string sourceBufferName, Value *offset) {
413        Value *blockStartPtr = iBuilder->CreatePointerCast(
414                iBuilder->getInputStreamBlockPtr(sourceBufferName, iBuilder->getInt32(0)),
415                iBuilder->getInt8PtrTy()
416        );
417        Value *ptr = iBuilder->CreateGEP(blockStartPtr, offset);
418
419
420        return iBuilder->CreateLoad(ptr);
421    }
422
423
424    void
425    SequentialKernel::generateStoreCircularOutput(const unique_ptr<KernelBuilder> &iBuilder, string outputBufferName,
426                                                  Type *pointerType, Value *value) {
427        Value *offset = iBuilder->getProducedItemCount(outputBufferName);
428
429        size_t inputSize = this->getOutputBufferSize(iBuilder, outputBufferName);
430        Value *offsetMask = iBuilder->getSize(inputSize - 1);
431        Value *maskedOffset = iBuilder->CreateAnd(offsetMask, offset);
432
433        Value *outputBufferPtr = iBuilder->getRawOutputPointer(outputBufferName, iBuilder->getSize(0));
434
435        outputBufferPtr = iBuilder->CreatePointerCast(outputBufferPtr, pointerType);
436        iBuilder->CreateStore(value, iBuilder->CreateGEP(outputBufferPtr, maskedOffset));
437
438        offset = iBuilder->CreateAdd(offset, iBuilder->getSize(1));
439        iBuilder->setProducedItemCount(outputBufferName, offset);
440    }
441
442    void
443    SequentialKernel::increaseScalarField(const std::unique_ptr<KernelBuilder> &iBuilder, const std::string &fieldName,
444                                          llvm::Value *value) {
445        Value *fieldValue = iBuilder->getScalarField(fieldName);
446        fieldValue = iBuilder->CreateAdd(fieldValue, value);
447        iBuilder->setScalarField(fieldName, fieldValue);
448    }
449
450
451    void SequentialKernel::markCircularOutputBitstreamOnePack(const std::unique_ptr<KernelBuilder> &iBuilder,
452                                                              const std::string &bitstreamName, llvm::Value *start,
453                                                              llvm::Value *end, bool isOne) {
454        Value *outputBasePtr = iBuilder->getRawOutputPointer(bitstreamName, iBuilder->getSize(0));
455
456        outputBasePtr = iBuilder->CreatePointerCast(outputBasePtr, iBuilder->getInt64Ty()->getPointerTo());
457
458        size_t outputBufferSize = this->getOutputBufferSize(iBuilder, bitstreamName);
459        Value *outputMask = iBuilder->getSize(outputBufferSize / 64 - 1);
460
461
462        Value *startOffset = iBuilder->CreateLShr(start, iBuilder->getSize(std::log2(64)), "startOffset");
463        Value *curOffset = startOffset;
464
465
466        Value *outputLowestBitValue = iBuilder->CreateSelect(
467                iBuilder->CreateICmpULE(
468                        iBuilder->CreateShl(curOffset, std::log2(64)),
469                        start
470                ),
471                iBuilder->CreateShl(iBuilder->getSize(1), iBuilder->CreateAnd(start, iBuilder->getSize(64 - 1))),
472                iBuilder->getSize(1)
473        );
474
475        Value *outputHighestBitValue = iBuilder->CreateShl(
476                iBuilder->getSize(1),
477                iBuilder->CreateAnd(end, iBuilder->getSize(64 - 1))
478        );
479
480
481        Value *bitMask = iBuilder->CreateSub(
482                outputHighestBitValue,
483                outputLowestBitValue
484        );
485
486        if (!isOne) {
487            bitMask = iBuilder->CreateNot(bitMask);
488        }
489    }
490
491    // Assume we have enough output buffer
492    llvm::BasicBlock *SequentialKernel::markCircularOutputBitstream(const std::unique_ptr<KernelBuilder> &iBuilder,
493                                                                    const std::string &bitstreamName,
494                                                                    llvm::Value *start, llvm::Value *end, bool isOne,
495                                                                    bool setProduced) {
496        BasicBlock *entryBlock = iBuilder->GetInsertBlock();
497
498        Value *outputBasePtr = iBuilder->getRawOutputPointer(bitstreamName, iBuilder->getSize(0));
499
500        outputBasePtr = iBuilder->CreatePointerCast(outputBasePtr, iBuilder->getInt64Ty()->getPointerTo());
501
502        size_t outputBufferSize = this->getOutputBufferSize(iBuilder, bitstreamName);
503        Value *outputMask = iBuilder->getSize(outputBufferSize / 64 - 1);
504
505        BasicBlock *conBlock = iBuilder->CreateBasicBlock("mark_bit_one_con");
506        BasicBlock *bodyBlock = iBuilder->CreateBasicBlock("mark_bit_one_body");
507        BasicBlock *exitBlock = iBuilder->CreateBasicBlock("mark_bit_one_exit");
508
509        Value *startOffset = iBuilder->CreateLShr(start, iBuilder->getSize(std::log2(64)), "startOffset");
510
511        iBuilder->CreateBr(conBlock);
512
513        // Con
514        iBuilder->SetInsertPoint(conBlock);
515
516
517        PHINode *curOffset = iBuilder->CreatePHI(iBuilder->getSizeTy(), 2);
518        curOffset->addIncoming(startOffset, entryBlock);
519
520        iBuilder->CreateCondBr(
521                iBuilder->CreateICmpULT(iBuilder->CreateShl(curOffset, std::log2(64)), end),
522                bodyBlock,
523                exitBlock
524        );
525
526        // Body
527        iBuilder->SetInsertPoint(bodyBlock);
528        Value *maskedOffset = iBuilder->CreateAnd(curOffset, outputMask);
529
530        Value *outputLowestBitValue = iBuilder->CreateSelect(
531                iBuilder->CreateICmpULE(
532                        iBuilder->CreateShl(curOffset, std::log2(64)),
533                        start
534                ),
535                iBuilder->CreateShl(iBuilder->getSize(1), iBuilder->CreateAnd(start, iBuilder->getSize(64 - 1))),
536                iBuilder->getSize(1)
537        );
538
539        Value *hasNotReachEnd = iBuilder->CreateICmpULE(
540                iBuilder->CreateShl(iBuilder->CreateAdd(curOffset, iBuilder->getSize(1)), std::log2(64)),
541                end
542        );
543        Value *producedItemsCount = iBuilder->CreateSelect(
544                hasNotReachEnd,
545                iBuilder->CreateShl(iBuilder->CreateAdd(curOffset, iBuilder->getSize(1)), std::log2(64)),
546                end
547        );
548
549        Value *outputHighestBitValue = iBuilder->CreateSelect(
550                hasNotReachEnd,
551                iBuilder->getSize(0),
552                iBuilder->CreateShl(
553                        iBuilder->getSize(1),
554                        iBuilder->CreateAnd(end, iBuilder->getSize(64 - 1))
555                )
556        );
557
558
559        Value *bitMask = iBuilder->CreateSub(
560                outputHighestBitValue,
561                outputLowestBitValue
562        );
563
564        if (!isOne) {
565            bitMask = iBuilder->CreateNot(bitMask);
566        }
567
568        Value *targetPtr = iBuilder->CreateGEP(outputBasePtr, maskedOffset);
569        Value *oldValue = iBuilder->CreateLoad(targetPtr);
570        Value *newValue = NULL;
571        if (isOne) {
572            newValue = iBuilder->CreateOr(oldValue, bitMask);
573        } else {
574            newValue = iBuilder->CreateAnd(oldValue, bitMask);
575        }
576        iBuilder->CreateStore(
577                newValue,
578                targetPtr
579        );
580        if (setProduced) {
581            iBuilder->setProducedItemCount(bitstreamName, producedItemsCount);
582        }
583
584        curOffset->addIncoming(iBuilder->CreateAdd(curOffset, iBuilder->getSize(1)), bodyBlock);
585        iBuilder->CreateBr(conBlock);
586
587        // Exit
588        iBuilder->SetInsertPoint(exitBlock);
589        return exitBlock;
590    }
591}
Note: See TracBrowser for help on using the repository browser.