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

Last change on this file since 5139 was 5139, checked in by lindanl, 3 years ago

change getInt64Ty to getSizeTy.

File size: 5.9 KB
RevLine 
[4929]1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5
[5033]6
7#include <toolchain.h>
[4929]8#include "pipeline.h"
9
[5086]10#include <IDISA/idisa_builder.h>
11
12#include <kernels/interface.h>
13#include <kernels/kernel.h>
[4929]14#include <kernels/s2p_kernel.h>
15
[5135]16#include <llvm/IR/TypeBuilder.h>
[4929]17
[4974]18using namespace kernel;
[4929]19
[5135]20void generatePipelineParallel(IDISA::IDISA_Builder * iBuilder, std::vector<KernelBuilder *> kernels, std::vector<Value *> instances) {
21 
22    Module * m = iBuilder->getModule();
[4929]23
[5139]24    Type * pthreadTy = iBuilder->getSizeTy(); //Pthread Type for 64-bit machine.     
[5135]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
[5086]62void generatePipelineLoop(IDISA::IDISA_Builder * iBuilder, std::vector<KernelBuilder *> kernels, std::vector<Value *> instances, Value * fileSize) {
[5063]63   
[5086]64    BasicBlock * entryBlock = iBuilder->GetInsertBlock();
65    Function * main = entryBlock->getParent();
66       
67    const unsigned segmentSize = codegen::SegmentSize;
[5106]68    Type * const size_ty = iBuilder->getSizeTy();
[4929]69
[5086]70    // Create the basic blocks for the loop.
[5075]71    BasicBlock * segmentCondBlock = nullptr;
72    BasicBlock * segmentBodyBlock = nullptr;
73    if (segmentSize > 1) {
[5086]74        segmentCondBlock = BasicBlock::Create(iBuilder->getContext(), "segmentCond", main, 0);
75        segmentBodyBlock = BasicBlock::Create(iBuilder->getContext(), "segmentBody", main, 0);
[5075]76    }
[5086]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);
[5063]80   
81   
[5075]82    Value * initialBufferSize = nullptr;
83    Value * initialBlockNo = nullptr;
84    BasicBlock * initialBlock = nullptr;
[5099]85    Value * rslt = nullptr;
[5086]86   
[5075]87    if (segmentSize > 1) {
88        iBuilder->CreateBr(segmentCondBlock);
89        iBuilder->SetInsertPoint(segmentCondBlock);
[5106]90        PHINode * remainingBytes = iBuilder->CreatePHI(size_ty, 2, "remainingBytes");
[5086]91        remainingBytes->addIncoming(fileSize, entryBlock);
[5106]92        PHINode * blockNo = iBuilder->CreatePHI(size_ty, 2, "blockNo");
93        blockNo->addIncoming(ConstantInt::get(size_ty, 0), entryBlock);
[5086]94       
[5126]95        Constant * const step = ConstantInt::get(size_ty, iBuilder->getStride() * segmentSize);
[5075]96        Value * segmentCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
97        iBuilder->CreateCondBr(segmentCondTest, fullCondBlock, segmentBodyBlock);
[5086]98       
[5075]99        iBuilder->SetInsertPoint(segmentBodyBlock);
[5106]100        Value * segBlocks = ConstantInt::get(size_ty, segmentSize);
[5111]101        for (unsigned i = 0; i < kernels.size(); i++) {
102            kernels[i]->createDoSegmentCall(instances[i], segBlocks);
[5075]103        }
104        remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), segmentBodyBlock);
[5086]105        blockNo->addIncoming(iBuilder->CreateAdd(blockNo, segBlocks), segmentBodyBlock);
106       
[5075]107        iBuilder->CreateBr(segmentCondBlock);
108        initialBufferSize = remainingBytes;
109        initialBlockNo = blockNo;
110        initialBlock = segmentCondBlock;
111    } else {
[5086]112        initialBufferSize = fileSize;
[5106]113        initialBlockNo = ConstantInt::get(size_ty, 0);
[5075]114        initialBlock = entryBlock;
115        iBuilder->CreateBr(fullCondBlock);
116    }
[5086]117   
[4986]118    iBuilder->SetInsertPoint(fullCondBlock);
[5106]119    PHINode * remainingBytes = iBuilder->CreatePHI(size_ty, 2, "remainingBytes");
[4986]120    remainingBytes->addIncoming(initialBufferSize, initialBlock);
[5106]121    PHINode * blockNo = iBuilder->CreatePHI(size_ty, 2, "blockNo");
[5063]122    blockNo->addIncoming(initialBlockNo, initialBlock);
123   
[5126]124    Constant * const step = ConstantInt::get(size_ty, iBuilder->getStride());
[4986]125    Value * fullCondTest = iBuilder->CreateICmpULT(remainingBytes, step);
126    iBuilder->CreateCondBr(fullCondTest, finalBlock, fullBodyBlock);
[5086]127   
[5063]128    // Full Block Pipeline loop
[4986]129    iBuilder->SetInsertPoint(fullBodyBlock);
[5111]130    for (unsigned i = 0; i < kernels.size(); i++) {
131        kernels[i]->createDoSegmentCall(instances[i], ConstantInt::get(size_ty, 1));
[5025]132    }
[5086]133   
[4986]134    remainingBytes->addIncoming(iBuilder->CreateSub(remainingBytes, step), fullBodyBlock);
[5106]135    blockNo->addIncoming(iBuilder->CreateAdd(blockNo, ConstantInt::get(size_ty, 1)), fullBodyBlock);
[4986]136    iBuilder->CreateBr(fullCondBlock);
[5086]137   
[4986]138    iBuilder->SetInsertPoint(finalBlock);
[5126]139    for (unsigned i = 0; i < kernels.size(); i++) {
140        kernels[i]->createFinalBlockCall(instances[i], remainingBytes);
[5063]141    }
[4929]142}
Note: See TracBrowser for help on using the repository browser.