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

Last change on this file since 5142 was 5141, checked in by cameron, 3 years ago

pablo.Lookahead support updated for stream set access/kernel system

File size: 5.9 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
10#include <IDISA/idisa_builder.h>
11
12#include <kernels/interface.h>
13#include <kernels/kernel.h>
14#include <kernels/s2p_kernel.h>
15
16#include <llvm/IR/TypeBuilder.h>
17
18using namespace kernel;
19
20void generatePipelineParallel(IDISA::IDISA_Builder * iBuilder, std::vector<KernelBuilder *> kernels, std::vector<Value *> instances) {
21 
22    Module * m = iBuilder->getModule();
23
24    Type * pthreadTy = iBuilder->getSizeTy(); //Pthread Type for 64-bit machine.     
25    Type * const voidPtrTy = TypeBuilder<void *, false>::get(m->getContext());
26    Type * const int8PtrTy = iBuilder->getInt8PtrTy();
27
28    Type * const pthreadsTy = ArrayType::get(pthreadTy, kernels.size());
29    AllocaInst * const pthreads = iBuilder->CreateAlloca(pthreadsTy);
30    std::vector<Value *> pthreadsPtrs;
31    for (unsigned i = 0; i < kernels.size(); i++) {
32        pthreadsPtrs.push_back(iBuilder->CreateGEP(pthreads, {iBuilder->getInt32(0), iBuilder->getInt32(i)}));
33    }
34    Value * nullVal = Constant::getNullValue(voidPtrTy);
35    AllocaInst * const status = iBuilder->CreateAlloca(int8PtrTy);
36
37    std::vector<Function *> kernel_functions;
38    const auto ip = iBuilder->saveIP();
39    for (unsigned i = 0; i < kernels.size(); i++) {
40        kernel_functions.push_back(kernels[i]->generateThreadFunction("k_"+std::to_string(i)));
41    }
42    iBuilder->restoreIP(ip);
43
44    Function * pthreadCreateFunc = m->getFunction("pthread_create");
45    Function * pthreadJoinFunc = m->getFunction("pthread_join");
46
47    for (unsigned i = 0; i < kernels.size(); i++) {
48        iBuilder->CreateCall(pthreadCreateFunc, std::vector<Value *>({pthreadsPtrs[i], nullVal, kernel_functions[i], iBuilder->CreateBitCast(instances[i], int8PtrTy)}));
49    }
50
51    std::vector<Value *> threadIDs;
52    for (unsigned i = 0; i < kernels.size(); i++) { 
53        threadIDs.push_back(iBuilder->CreateLoad(pthreadsPtrs[i]));
54    }
55   
56    for (unsigned i = 0; i < kernels.size(); i++) { 
57        iBuilder->CreateCall(pthreadJoinFunc, std::vector<Value *>({threadIDs[i], status}));
58    }
59}
60
61
62void generatePipelineLoop(IDISA::IDISA_Builder * iBuilder, std::vector<KernelBuilder *> kernels, std::vector<Value *> instances, Value * fileSize) {
63   
64    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
65    Function * main = entryBlock->getParent();
66       
67    const unsigned segmentSize = codegen::SegmentSize;
68    Type * const size_ty = iBuilder->getSizeTy();
69
70    // Create the basic blocks for the loop.
71    BasicBlock * segmentCondBlock = nullptr;
72    BasicBlock * segmentBodyBlock = nullptr;
73    if (segmentSize > 1) {
74        segmentCondBlock = BasicBlock::Create(iBuilder->getContext(), "segmentCond", main, 0);
75        segmentBodyBlock = BasicBlock::Create(iBuilder->getContext(), "segmentBody", main, 0);
76    }
77    BasicBlock * fullCondBlock = BasicBlock::Create(iBuilder->getContext(), "fullCond", main, 0);
78    BasicBlock * fullBodyBlock = BasicBlock::Create(iBuilder->getContext(), "fullBody", main, 0);
79    BasicBlock * finalBlock = BasicBlock::Create(iBuilder->getContext(), "final", main, 0);
80   
81   
82    Value * initialBufferSize = nullptr;
83    Value * initialBlockNo = nullptr;
84    BasicBlock * initialBlock = nullptr;
85   
86    if (segmentSize > 1) {
87        iBuilder->CreateBr(segmentCondBlock);
88        iBuilder->SetInsertPoint(segmentCondBlock);
89        PHINode * remainingBytes = iBuilder->CreatePHI(size_ty, 2, "remainingBytes");
90        remainingBytes->addIncoming(fileSize, entryBlock);
91        PHINode * blockNo = iBuilder->CreatePHI(size_ty, 2, "blockNo");
92        blockNo->addIncoming(ConstantInt::get(size_ty, 0), entryBlock);
93       
94        Constant * const step = ConstantInt::get(size_ty, iBuilder->getStride() * segmentSize);
95        Value * segmentCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
96        iBuilder->CreateCondBr(segmentCondTest, fullCondBlock, segmentBodyBlock);
97       
98        iBuilder->SetInsertPoint(segmentBodyBlock);
99        Value * segBlocks = ConstantInt::get(size_ty, segmentSize);
100        for (unsigned i = 0; i < kernels.size(); i++) {
101            kernels[i]->createDoSegmentCall(instances[i], segBlocks);
102        }
103        remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), segmentBodyBlock);
104        blockNo->addIncoming(iBuilder->CreateAdd(blockNo, segBlocks), segmentBodyBlock);
105       
106        iBuilder->CreateBr(segmentCondBlock);
107        initialBufferSize = remainingBytes;
108        initialBlockNo = blockNo;
109        initialBlock = segmentCondBlock;
110    } else {
111        initialBufferSize = fileSize;
112        initialBlockNo = ConstantInt::get(size_ty, 0);
113        initialBlock = entryBlock;
114        iBuilder->CreateBr(fullCondBlock);
115    }
116   
117    iBuilder->SetInsertPoint(fullCondBlock);
118    PHINode * remainingBytes = iBuilder->CreatePHI(size_ty, 2, "remainingBytes");
119    remainingBytes->addIncoming(initialBufferSize, initialBlock);
120    PHINode * blockNo = iBuilder->CreatePHI(size_ty, 2, "blockNo");
121    blockNo->addIncoming(initialBlockNo, initialBlock);
122   
123    Constant * const step = ConstantInt::get(size_ty, iBuilder->getStride());
124    Value * fullCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
125    iBuilder->CreateCondBr(fullCondTest, finalBlock, fullBodyBlock);
126   
127    // Full Block Pipeline loop
128    iBuilder->SetInsertPoint(fullBodyBlock);
129    for (unsigned i = 0; i < kernels.size(); i++) {
130        kernels[i]->createDoSegmentCall(instances[i], ConstantInt::get(size_ty, 1));
131    }
132   
133    remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), fullBodyBlock);
134    blockNo->addIncoming(iBuilder->CreateAdd(blockNo, ConstantInt::get(size_ty, 1)), fullBodyBlock);
135    iBuilder->CreateBr(fullCondBlock);
136   
137    iBuilder->SetInsertPoint(finalBlock);
138    for (unsigned i = 0; i < kernels.size(); i++) {
139        kernels[i]->createFinalBlockCall(instances[i], remainingBytes);
140    }
141}
Note: See TracBrowser for help on using the repository browser.