source: icGREP/icgrep-devel/icgrep/kernels/pipeline.cpp @ 5100

Last change on this file since 5100 was 5099, checked in by cameron, 3 years ago

Pipeline generation for kernels with non-void DoBlock? return

File size: 4.5 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
6
7#include <toolchain.h>
8#include "pipeline.h"
9#include "utf_encoding.h"
10
11#include <IDISA/idisa_builder.h>
12
13#include <kernels/interface.h>
14#include <kernels/kernel.h>
15#include <kernels/s2p_kernel.h>
16
17
18using namespace kernel;
19
20
21void generatePipelineLoop(IDISA::IDISA_Builder * iBuilder, std::vector<KernelBuilder *> kernels, std::vector<Value *> instances, Value * fileSize) {
22   
23    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
24    Function * main = entryBlock->getParent();
25       
26    const unsigned segmentSize = codegen::SegmentSize;
27    Type * const int64ty = iBuilder->getInt64Ty();
28
29    // Create the basic blocks for the loop.
30    BasicBlock * segmentCondBlock = nullptr;
31    BasicBlock * segmentBodyBlock = nullptr;
32    if (segmentSize > 1) {
33        segmentCondBlock = BasicBlock::Create(iBuilder->getContext(), "segmentCond", main, 0);
34        segmentBodyBlock = BasicBlock::Create(iBuilder->getContext(), "segmentBody", main, 0);
35    }
36    BasicBlock * fullCondBlock = BasicBlock::Create(iBuilder->getContext(), "fullCond", main, 0);
37    BasicBlock * fullBodyBlock = BasicBlock::Create(iBuilder->getContext(), "fullBody", main, 0);
38    BasicBlock * finalBlock = BasicBlock::Create(iBuilder->getContext(), "final", main, 0);
39   
40   
41    Value * initialBufferSize = nullptr;
42    Value * initialBlockNo = nullptr;
43    BasicBlock * initialBlock = nullptr;
44    Value * rslt = nullptr;
45   
46    if (segmentSize > 1) {
47        iBuilder->CreateBr(segmentCondBlock);
48        iBuilder->SetInsertPoint(segmentCondBlock);
49        PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
50        remainingBytes->addIncoming(fileSize, entryBlock);
51        PHINode * blockNo = iBuilder->CreatePHI(int64ty, 2, "blockNo");
52        blockNo->addIncoming(iBuilder->getInt64(0), entryBlock);
53       
54        Constant * const step = ConstantInt::get(int64ty, iBuilder->getBitBlockWidth() * segmentSize);
55        Value * segmentCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
56        iBuilder->CreateCondBr(segmentCondTest, fullCondBlock, segmentBodyBlock);
57       
58        iBuilder->SetInsertPoint(segmentBodyBlock);
59        Value * segBlocks = ConstantInt::get(int64ty, segmentSize);
60        Value * rslt = kernels[0]->createDoSegmentCall(instances[0], segBlocks);
61        for (unsigned i = 1; i < kernels.size(); i++) {
62            rslt = kernels[i]->createDoSegmentCall(instances[i], rslt->getType()->isVoidTy() ? segBlocks : rslt);
63        }
64        remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), segmentBodyBlock);
65        blockNo->addIncoming(iBuilder->CreateAdd(blockNo, segBlocks), segmentBodyBlock);
66       
67        iBuilder->CreateBr(segmentCondBlock);
68        initialBufferSize = remainingBytes;
69        initialBlockNo = blockNo;
70        initialBlock = segmentCondBlock;
71    } else {
72        initialBufferSize = fileSize;
73        initialBlockNo = ConstantInt::get(int64ty, 0);
74        initialBlock = entryBlock;
75        iBuilder->CreateBr(fullCondBlock);
76    }
77   
78    iBuilder->SetInsertPoint(fullCondBlock);
79    PHINode * remainingBytes = iBuilder->CreatePHI(int64ty, 2, "remainingBytes");
80    remainingBytes->addIncoming(initialBufferSize, initialBlock);
81    PHINode * blockNo = iBuilder->CreatePHI(int64ty, 2, "blockNo");
82    blockNo->addIncoming(initialBlockNo, initialBlock);
83   
84    Constant * const step = ConstantInt::get(int64ty, iBuilder->getBitBlockWidth());
85    Value * fullCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
86    iBuilder->CreateCondBr(fullCondTest, finalBlock, fullBodyBlock);
87   
88    // Full Block Pipeline loop
89    iBuilder->SetInsertPoint(fullBodyBlock);
90    rslt = kernels[0]->createDoSegmentCall(instances[0], ConstantInt::get(int64ty, 1));
91    for (unsigned i = 1; i < kernels.size(); i++) {
92        rslt = kernels[i]->createDoSegmentCall(instances[i], rslt->getType()->isVoidTy() ? ConstantInt::get(int64ty, 1) : rslt);
93    }
94   
95    remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), fullBodyBlock);
96    blockNo->addIncoming(iBuilder->CreateAdd(blockNo, iBuilder->getInt64(1)), fullBodyBlock);
97    iBuilder->CreateBr(fullCondBlock);
98   
99    iBuilder->SetInsertPoint(finalBlock);
100    rslt = kernels[0]-> createFinalBlockCall(instances[0], remainingBytes);
101    for (unsigned i = 1; i < kernels.size(); i++) {
102        kernels[i]->createFinalBlockCall(instances[i], rslt->getType()->isVoidTy() ? remainingBytes : rslt);
103    }
104}
Note: See TracBrowser for help on using the repository browser.