Ignore:
Timestamp:
Nov 2, 2018, 7:18:31 PM (11 months ago)
Author:
nmedfort
Message:

Initial version of PipelineKernel? + revised StreamSet? model.

Location:
icGREP/icgrep-devel/icgrep/toolchain
Files:
2 added
3 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/toolchain/NVPTXDriver.cpp

    r5841 r6184  
    1212#include <llvm/Transforms/Utils/Local.h>
    1313#include <toolchain/toolchain.h>
    14 #include <toolchain/pipeline.h>
    1514#include <llvm/Analysis/TargetLibraryInfo.h>
    1615#include <llvm/CodeGen/MIRParser/MIRParser.h>
     
    2827using namespace llvm;
    2928
    30 using StreamSetBuffer = parabix::StreamSetBuffer;
     29using StreamSetBuffer = kernel::StreamSetBuffer;
    3130
    3231NVPTXDriver::NVPTXDriver(std::string && moduleName)
    33 : Driver(std::move(moduleName)) {
     32: BaseDriver(std::move(moduleName)) {
    3433
    3534    InitializeAllTargets();
     
    5554    iBuilder->setModule(mMainModule);
    5655    iBuilder->CreateBaseFunctions();
    57 }
    58 
    59 void NVPTXDriver::makeKernelCall(kernel::Kernel * kb, const std::vector<parabix::StreamSetBuffer *> & inputs, const std::vector<parabix::StreamSetBuffer *> & outputs) {
    60     assert ("addKernelCall or makeKernelCall was already run on this kernel." && (kb->getModule() == nullptr));
    61     mPipeline.emplace_back(kb);
    62     kb->bindPorts(inputs, outputs);
    63     kb->setModule(mMainModule);
    64 }
    65 
    66 void NVPTXDriver::generatePipelineIR() {
    67     // note: instantiation of all kernels must occur prior to initialization
    68     for (const auto & k : mPipeline) {
    69         k->addKernelDeclarations(iBuilder);
    70     }
    71     for (const auto & k : mPipeline) {
    72         k->createInstance(iBuilder);
    73     }
    74     for (const auto & k : mPipeline) {
    75         k->initializeInstance(iBuilder);
    76     }
    77    
    78     generatePipelineLoop(iBuilder, mPipeline);
    79    
    80     for (const auto & k : mPipeline) {
    81         k->finalizeInstance(iBuilder);
    82     }
    8356}
    8457
     
    158131}
    159132
    160 void NVPTXDriver::finalizeObject() {
     133void * NVPTXDriver::finalizeObject(Function * mainMethod) {
    161134
    162135    legacy::PassManager PM;
     
    190163
    191164    llvm2ptx(mMainModule, PTXFilename);
    192 }
    193165
    194 void * NVPTXDriver::getMain() {
    195     report_fatal_error("NVPTX must be executed by calling RunPTX");
     166    return nullptr;
    196167}
    197168
    198169NVPTXDriver::~NVPTXDriver() {
     170
    199171}
  • icGREP/icgrep-devel/icgrep/toolchain/NVPTXDriver.h

    r5493 r6184  
    88#define NVPTXDRIVER_H
    99
    10 #include "driver.h"
     10#include <toolchain/driver.h>
     11#include <toolchain/object_cache_manager.h>
    1112
    12 class NVPTXDriver final : public Driver {
     13class NVPTXDriver final : public BaseDriver {
    1314    friend class CBuilder;
    1415public:
     
    1718    ~NVPTXDriver();
    1819
    19     void generatePipelineIR() override;
    20    
    21     void makeKernelCall(kernel::Kernel * kb, const std::vector<parabix::StreamSetBuffer *> & inputs, const std::vector<parabix::StreamSetBuffer *> & outputs) override;
     20    void addKernel(Kernel * const kernel) override { }
    2221
    23     void finalizeObject() override;
     22    void generateUncachedKernels() { }
     23
     24    void * finalizeObject(llvm::Function * mainMethod) override;
    2425
    2526    bool hasExternalFunction(const llvm::StringRef /* functionName */) const override { return false; }
    2627
    27     void * getMain() override; // "main" exists until the driver is deleted
     28protected:
     29
     30    NVPTXDriver(std::string && moduleName);
    2831
    2932private:
  • icGREP/icgrep-devel/icgrep/toolchain/cpudriver.cpp

    r6030 r6184  
    2323#include <llvm/Transforms/Utils/Local.h>
    2424#include <toolchain/object_cache.h>
    25 #include <toolchain/pipeline.h>
    2625#include <kernels/kernel_builder.h>
    27 #include <kernels/kernel.h>
     26#include <kernels/pipeline_builder.h>
    2827#include <llvm/IR/Verifier.h>
    2928#include "llvm/IR/Mangler.h"
     
    5554
    5655using namespace llvm;
    57 using Kernel = kernel::Kernel;
    58 using StreamSetBuffer = parabix::StreamSetBuffer;
    59 using KernelBuilder = kernel::KernelBuilder;
    60 
    61 ParabixDriver::ParabixDriver(std::string && moduleName)
    62 : Driver(std::move(moduleName))
     56using kernel::Kernel;
     57using kernel::PipelineKernel;
     58using kernel::StreamSetBuffer;
     59using kernel::StreamSetBuffers;
     60using kernel::KernelBuilder;
     61
     62CPUDriver::CPUDriver(std::string && moduleName)
     63: BaseDriver(std::move(moduleName))
    6364, mTarget(nullptr)
    6465#ifndef ORCJIT
    6566, mEngine(nullptr)
    6667#endif
    67 , mCache(nullptr)
    6868, mUnoptimizedIROutputStream(nullptr)
    6969, mIROutputStream(nullptr)
     
    7676   
    7777
    78 #ifdef ORCJIT
     78    #ifdef ORCJIT
    7979    EngineBuilder builder;
    80 #else
     80    #else
    8181    std::string errMessage;
    8282    EngineBuilder builder{std::unique_ptr<Module>(mMainModule)};
     
    8585    builder.setVerifyModules(false);
    8686    builder.setEngineKind(EngineKind::JIT);
    87 #endif
     87    #endif
    8888    builder.setTargetOptions(codegen::target_Options);
    8989    builder.setOptLevel(codegen::OptLevel);
     
    107107    preparePassManager();
    108108
    109 #ifdef ORCJIT
     109    #ifdef ORCJIT
    110110    mCompileLayer = make_unique<CompileLayerT>(mObjectLayer, orc::SimpleCompiler(*mTarget));
    111 #else
     111    #else
    112112    mEngine = builder.create();
    113113    if (mEngine == nullptr) {
    114114        throw std::runtime_error("Could not create ExecutionEngine: " + errMessage);
    115115    }
    116 #endif
    117     if (LLVM_LIKELY(codegen::EnableObjectCache)) {
    118         if (codegen::ObjectCacheDir) {
    119             mCache = new ParabixObjectCache(codegen::ObjectCacheDir);
    120         } else {
    121             mCache = new ParabixObjectCache();
    122         }
    123 #ifdef ORCJIT
    124 #if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
    125         mCompileLayer->setObjectCache(mCache);
    126 #else
    127         mCompileLayer->getCompiler().setObjectCache(mCache);
    128 #endif
    129 #else
    130         mEngine->setObjectCache(mCache);
    131 #endif
     116    #endif
     117    auto cache = ObjectCacheManager::getObjectCache();
     118    if (cache) {
     119        #ifdef ORCJIT
     120        #if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(5, 0, 0)
     121        mCompileLayer->setObjectCache(cache);
     122        #else
     123        mCompileLayer->getCompiler().setObjectCache(cache);
     124        #endif
     125        #else
     126        mEngine->setObjectCache(cache);
     127        #endif
    132128    }
    133129    auto triple = mTarget->getTargetTriple().getTriple();
     
    140136}
    141137
    142 void ParabixDriver::makeKernelCall(Kernel * kernel, const std::vector<StreamSetBuffer *> & inputs, const std::vector<StreamSetBuffer *> & outputs) {
    143     assert ("makeKernelCall was already run on this kernel." && (kernel->getModule() == nullptr));
    144     mPipeline.emplace_back(kernel);
    145     kernel->bindPorts(inputs, outputs);
    146     if (!mCache || !mCache->loadCachedObjectFile(iBuilder, kernel)) {
    147         mUncachedKernel.push_back(kernel);
    148     }
    149     if (kernel->getModule() == nullptr) {
    150         kernel->makeModule(iBuilder);
    151     }
    152     assert (kernel->getModule());
    153 }
    154 
    155 void ParabixDriver::generatePipelineIR() {
    156 
    157     for (Kernel * const kernel : mUncachedKernel) {
    158         kernel->prepareKernel(iBuilder);
    159     }
    160     // note: instantiation of all kernels must occur prior to initialization
    161     for (Kernel * const k : mPipeline) {
    162         k->addKernelDeclarations(iBuilder);
    163     }
    164     for (Kernel * const k : mPipeline) {
    165         k->createInstance(iBuilder);
    166     }
    167     for (Kernel * const k : mPipeline) {
    168         k->initializeInstance(iBuilder);
    169     }
    170     if (codegen::SegmentPipelineParallel) {
    171         generateSegmentParallelPipeline(iBuilder, mPipeline);
    172     } else {
    173         generatePipelineLoop(iBuilder, mPipeline);
    174     }
    175     for (const auto & k : mPipeline) {
    176         k->finalizeInstance(iBuilder);
    177     }
    178 }
    179 
    180 
    181 Function * ParabixDriver::addLinkFunction(Module * mod, llvm::StringRef name, FunctionType * type, void * functionPtr) const {
     138Function * CPUDriver::addLinkFunction(Module * mod, llvm::StringRef name, FunctionType * type, void * functionPtr) const {
    182139    if (LLVM_UNLIKELY(mod == nullptr)) {
    183140        report_fatal_error("addLinkFunction(" + name + ") cannot be called until after addKernelCall or makeKernelCall");
     
    186143    if (LLVM_UNLIKELY(f == nullptr)) {
    187144        f = Function::Create(type, Function::ExternalLinkage, name, mod);
    188 #ifdef ORCJIT
    189 #else
     145        #ifndef ORCJIT
    190146        mEngine->updateGlobalMapping(f, functionPtr);
    191 #endif
     147        #endif
    192148    } else if (LLVM_UNLIKELY(f->getType() != type->getPointerTo())) {
    193149        report_fatal_error("Cannot link " + name + ": a function with a different signature already exists with that name in " + mod->getName());
     
    196152}
    197153
    198 std::string ParabixDriver::getMangledName(std::string s) {
     154std::string CPUDriver::getMangledName(std::string s) {
    199155    #if LLVM_VERSION_INTEGER >= LLVM_VERSION_CODE(3, 9, 0)
    200156    DataLayout DL(mTarget->createDataLayout());   
     
    208164}
    209165
    210 void ParabixDriver::preparePassManager() {
     166void CPUDriver::preparePassManager() {
    211167    PassRegistry * Registry = PassRegistry::getPassRegistry();
    212168    initializeCore(*Registry);
     
    228184        mPassManager.add(createVerifierPass());
    229185    }
     186
     187    mPassManager.add(createDeadCodeEliminationPass());        // Eliminate any trivially dead code
    230188    mPassManager.add(createPromoteMemoryToRegisterPass());    // Promote stack variables to constants or PHI nodes
    231189    mPassManager.add(createCFGSimplificationPass());          // Remove dead basic blocks and unnecessary branch statements / phi nodes
     
    235193    mPassManager.add(createGVNPass());                        // Global value numbering redundant expression elimination pass
    236194    mPassManager.add(createCFGSimplificationPass());          // Repeat CFG Simplification to "clean up" any newly found redundant phi nodes
    237    
     195    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::EnableAsserts))) {
     196        mPassManager.add(createRemoveRedundantAssertionsPass());
     197        mPassManager.add(createDeadCodeEliminationPass());
     198        mPassManager.add(createCFGSimplificationPass());
     199    }
     200
    238201    if (LLVM_UNLIKELY(codegen::ShowIROption != codegen::OmittedOption)) {
    239202        if (LLVM_LIKELY(mIROutputStream == nullptr)) {
     
    263226}
    264227
    265 void ParabixDriver::finalizeObject() {
    266 #ifdef ORCJIT
     228void CPUDriver::generateUncachedKernels() {
     229    for (auto & kernel : mUncachedKernel) {
     230        kernel->prepareKernel(iBuilder);
     231    }
     232    mCachedKernel.reserve(mUncachedKernel.size());
     233    for (auto & kernel : mUncachedKernel) {
     234        kernel->generateKernel(iBuilder);
     235        Module * const module = kernel->getModule(); assert (module);
     236        module->setTargetTriple(mMainModule->getTargetTriple());
     237        mPassManager.run(*module);
     238        mCachedKernel.emplace_back(kernel.release());
     239    }
     240    mUncachedKernel.clear();
     241}
     242
     243void * CPUDriver::finalizeObject(llvm::Function * mainMethod) {
     244
     245    #ifdef ORCJIT
     246    auto Resolver = llvm::orc::createLambdaResolver(
     247        [&](const std::string &Name) {
     248            auto Sym = mCompileLayer->findSymbol(Name, false);
     249            if (!Sym) Sym = mCompileLayer->findSymbol(getMangledName(Name), false);
     250            #if LLVM_VERSION_INTEGER <= LLVM_VERSION_CODE(3, 9, 1)
     251            if (Sym) return Sym.toRuntimeDyldSymbol();
     252            return RuntimeDyld::SymbolInfo(nullptr);
     253            #else
     254            if (Sym) return Sym;
     255            return JITSymbol(nullptr);
     256            #endif
     257        },
     258        [&](const std::string &Name) {
     259            auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name);
     260            if (!SymAddr) SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(getMangledName(Name));
     261            #if LLVM_VERSION_INTEGER <= LLVM_VERSION_CODE(3, 9, 1)
     262            if (SymAddr) return RuntimeDyld::SymbolInfo(SymAddr, JITSymbolFlags::Exported);
     263            return RuntimeDyld::SymbolInfo(nullptr);
     264            #else
     265            if (SymAddr) return JITSymbol(SymAddr, JITSymbolFlags::Exported);
     266            return JITSymbol(nullptr);
     267            #endif
     268        });
     269    #endif
     270
     271    iBuilder->setModule(mMainModule);
     272    mPassManager.run(*mMainModule);
     273    #ifdef ORCJIT
    267274    std::vector<std::unique_ptr<Module>> moduleSet;
    268     auto Resolver = llvm::orc::createLambdaResolver(
    269             [&](const std::string &Name) {
    270                 auto Sym = mCompileLayer->findSymbol(Name, false);
    271                 if (!Sym) Sym = mCompileLayer->findSymbol(getMangledName(Name), false);
    272 #if LLVM_VERSION_INTEGER <= LLVM_VERSION_CODE(3, 9, 1)
    273                 if (Sym) return Sym.toRuntimeDyldSymbol();
    274                 return RuntimeDyld::SymbolInfo(nullptr);
    275 #else
    276                 if (Sym) return Sym;
    277                 return JITSymbol(nullptr);
    278 #endif
    279             },
    280             [&](const std::string &Name) {
    281                 auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(Name);
    282                 if (!SymAddr) SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(getMangledName(Name));
    283 #if LLVM_VERSION_INTEGER <= LLVM_VERSION_CODE(3, 9, 1)
    284                 if (SymAddr) return RuntimeDyld::SymbolInfo(SymAddr, JITSymbolFlags::Exported);
    285                 return RuntimeDyld::SymbolInfo(nullptr);
    286 #else
    287                 if (SymAddr) return JITSymbol(SymAddr, JITSymbolFlags::Exported);
    288                 return JITSymbol(nullptr);
    289 #endif
    290             });
    291 #endif
    292    
    293     Module * module = nullptr;
    294     try {
    295         for (Kernel * const kernel : mUncachedKernel) {
    296             iBuilder->setKernel(kernel);
    297             kernel->generateKernel(iBuilder);
    298             module = kernel->getModule(); assert (module);
    299             module->setTargetTriple(mMainModule->getTargetTriple());
    300             mPassManager.run(*module);
    301         }
    302         module = mMainModule;
    303         iBuilder->setKernel(nullptr);
    304         mPassManager.run(*mMainModule);
    305         for (Kernel * const kernel : mPipeline) {
    306             if (LLVM_UNLIKELY(kernel->getModule() == nullptr)) {
    307                 report_fatal_error(kernel->getName() + " was neither loaded from cache nor generated prior to finalizeObject");
    308             }
    309 #ifndef ORCJIT
    310             mEngine->addModule(std::unique_ptr<Module>(kernel->getModule()));
    311 #else
    312             moduleSet.push_back(std::unique_ptr<Module>(kernel->getModule()));
    313 #endif
    314         }
    315 #ifndef ORCJIT
    316             mEngine->finalizeObject();
    317 #else
    318             moduleSet.push_back(std::unique_ptr<Module>(mMainModule));
    319             auto handle = mCompileLayer->addModuleSet(std::move(moduleSet), make_unique<SectionMemoryManager>(), std::move(Resolver));
    320 #endif
    321     } catch (const std::exception & e) {
    322         report_fatal_error(module->getName() + ": " + e.what());
    323     }
    324 
    325 }
    326 
    327 bool ParabixDriver::hasExternalFunction(llvm::StringRef functionName) const {
     275    moduleSet.reserve(mCachedKernel.size());
     276    #endif
     277    for (const auto & kernel : mCachedKernel) {
     278        if (LLVM_UNLIKELY(kernel->getModule() == nullptr)) {
     279            report_fatal_error(kernel->getName() + " was neither loaded from cache nor generated prior to finalizeObject");
     280        }
     281        #ifndef ORCJIT
     282        mEngine->addModule(std::unique_ptr<Module>(kernel->getModule()));
     283        #else
     284        moduleSet.push_back(std::unique_ptr<Module>(kernel->getModule()));
     285        #endif
     286    }
     287    mCachedKernel.clear();
     288    // compile any uncompiled kernel/method
     289    #ifndef ORCJIT
     290    mEngine->finalizeObject();
     291    #else
     292    moduleSet.push_back(std::unique_ptr<Module>(mMainModule);
     293    mCompileLayer->addModuleSet(std::move(moduleSet), make_unique<SectionMemoryManager>(), std::move(Resolver));
     294    #endif
     295
     296    // return the compiled main method
     297    #ifndef ORCJIT
     298    return mEngine->getPointerToFunction(mainMethod);
     299    #else
     300    auto MainSym = mCompileLayer->findSymbol(getMangledName(mMainMethod->getName()), false);
     301    assert (MainSym && "Main not found");
     302    return (void *)MainSym.getAddress();
     303    #endif
     304}
     305
     306bool CPUDriver::hasExternalFunction(llvm::StringRef functionName) const {
    328307    return RTDyldMemoryManager::getSymbolAddressInProcess(functionName);
    329308}
    330309
    331 void * ParabixDriver::getMain() {
    332 #ifndef ORCJIT
    333     return mEngine->getPointerToNamedFunction("Main");
    334 #else
    335     auto MainSym = mCompileLayer->findSymbol(getMangledName("Main"), false);
    336     assert (MainSym && "Main not found");
    337    
    338     intptr_t main = (intptr_t) MainSym.getAddress();
    339     return (void *) main;
    340 #endif
    341 }
    342 
    343 void ParabixDriver::performIncrementalCacheCleanupStep() {
    344     if (mCache) mCache->performIncrementalCacheCleanupStep();
    345 }
    346 
    347 ParabixDriver::~ParabixDriver() {
    348 #ifndef ORCJIT
     310CPUDriver::~CPUDriver() {
     311    #ifndef ORCJIT
    349312    delete mEngine;
    350 #endif
    351     delete mCache;
     313    #endif
    352314    delete mTarget;
    353  }
     315}
  • icGREP/icgrep-devel/icgrep/toolchain/cpudriver.h

    r5932 r6184  
    3333#endif
    3434
    35 class ParabixObjectCache;
     35class ObjectCacheManager;
    3636
    37 class ParabixDriver final : public Driver {
    38     friend class CBuilder;
     37class CPUDriver final : public BaseDriver {
    3938public:
    40     ParabixDriver(std::string && moduleName);
    4139
    42     ~ParabixDriver();
     40    CPUDriver(std::string && moduleName);
    4341
    44     void generatePipelineIR() override;
     42    ~CPUDriver();
    4543
    46     void makeKernelCall(kernel::Kernel * kb, const std::vector<parabix::StreamSetBuffer *> & inputs, const std::vector<parabix::StreamSetBuffer *> & outputs) override;
     44    void generateUncachedKernels() override;
    4745
    48     void finalizeObject() override;
     46    void * finalizeObject(llvm::Function * mainMethod) override;
    4947
    5048    bool hasExternalFunction(const llvm::StringRef functionName) const override;
    5149
    52     void * getMain() override; // "main" exists until the driver is deleted
    53    
    54     void performIncrementalCacheCleanupStep() override;
     50private:
    5551
    56 private:
    5752    std::string getMangledName(std::string s);
    5853   
     
    6156    llvm::Function * addLinkFunction(llvm::Module * mod, llvm::StringRef name, llvm::FunctionType * type, void * functionPtr) const override;
    6257
     58private:
    6359    llvm::TargetMachine *                                   mTarget;
    64 
    65 #ifdef ORCJIT
    66     ObjectLayerT mObjectLayer;
    67     std::unique_ptr<CompileLayerT> mCompileLayer;
    68 
    69 #else
     60    #ifdef ORCJIT
     61    ObjectLayerT                                            mObjectLayer;
     62    std::unique_ptr<CompileLayerT>                          mCompileLayer;
     63    #else
    7064    llvm::ExecutionEngine *                                 mEngine;
    71 #endif
    72     ParabixObjectCache *                                    mCache;
    73     std::vector<kernel::Kernel *>                           mUncachedKernel;
     65    #endif
    7466    std::unique_ptr<llvm::raw_fd_ostream>                   mUnoptimizedIROutputStream;
    7567    std::unique_ptr<llvm::raw_fd_ostream>                   mIROutputStream;
  • icGREP/icgrep-devel/icgrep/toolchain/driver.cpp

    r5998 r6184  
    11#include "driver.h"
    22#include <kernels/kernel_builder.h>
    3 #include <kernels/streamset.h>
    4 #include <kernels/kernel.h>
     3#include <kernels/pipeline_builder.h>
    54#include <llvm/IR/Module.h>
     5#include <toolchain/toolchain.h>
     6#include <toolchain/object_cache.h>
     7#include <llvm/Support/raw_ostream.h>
    68
    7 using namespace llvm;
    8 using namespace parabix;
     9using namespace kernel;
    910
    10 using Kernel = kernel::Kernel;
    11 using KernelBuilder = kernel::KernelBuilder;
     11using RelationshipAllocator = Relationship::Allocator;
    1212
    13 Driver::Driver(std::string && moduleName)
    14 : mContext(new llvm::LLVMContext())
    15 , mMainModule(new Module(moduleName, *mContext))
    16 , iBuilder(nullptr) {
    17 
     13/** ------------------------------------------------------------------------------------------------------------- *
     14 * @brief makePipelineWithIO
     15 ** ------------------------------------------------------------------------------------------------------------- */
     16std::unique_ptr<PipelineBuilder> BaseDriver::makePipelineWithIO(Bindings stream_inputs, Bindings stream_outputs, Bindings scalar_inputs, Bindings scalar_outputs) {
     17    return llvm::make_unique<PipelineBuilder>(*this, std::move(stream_inputs), std::move(stream_outputs), std::move(scalar_inputs), std::move(scalar_outputs));
    1818}
    1919
    20 void Driver::deallocateBuffers() {
    21     for (const auto & b : mOwnedBuffers) {
    22         b->releaseBuffer(iBuilder);
     20/** ------------------------------------------------------------------------------------------------------------- *
     21 * @brief makePipeline
     22 ** ------------------------------------------------------------------------------------------------------------- */
     23std::unique_ptr<kernel::PipelineBuilder> BaseDriver::makePipeline(Bindings scalar_inputs, Bindings scalar_outputs) {
     24    return llvm::make_unique<PipelineBuilder>(*this, Bindings{}, Bindings{}, std::move(scalar_inputs), std::move(scalar_outputs));
     25}
     26
     27/** ------------------------------------------------------------------------------------------------------------- *
     28 * @brief CreateStreamSet
     29 ** ------------------------------------------------------------------------------------------------------------- */
     30StreamSet * BaseDriver::CreateStreamSet(const unsigned NumElements, const unsigned FieldWidth) {
     31    RelationshipAllocator A(mAllocator);
     32    return new (A) StreamSet(getContext(), NumElements, FieldWidth);
     33}
     34
     35/** ------------------------------------------------------------------------------------------------------------- *
     36 * @brief CreateConstant
     37 ** ------------------------------------------------------------------------------------------------------------- */
     38Scalar * BaseDriver::CreateScalar(llvm::Type * scalarType) {
     39    RelationshipAllocator A(mAllocator);
     40    return new (A) Scalar(scalarType);
     41}
     42
     43/** ------------------------------------------------------------------------------------------------------------- *
     44 * @brief CreateConstant
     45 ** ------------------------------------------------------------------------------------------------------------- */
     46Scalar * BaseDriver::CreateConstant(llvm::Constant * const value) {
     47    RelationshipAllocator A(mAllocator);
     48    return new (A) ScalarConstant(value);
     49}
     50
     51/** ------------------------------------------------------------------------------------------------------------- *
     52 * @brief makeCache
     53 ** ------------------------------------------------------------------------------------------------------------- */
     54void BaseDriver::addKernel(Kernel * const kernel) {
     55    if (ObjectCacheManager::checkForCachedKernel(iBuilder, kernel)) {
     56        assert (kernel->getModule());
     57        mCachedKernel.emplace_back(kernel);
     58    } else {
     59        if (kernel->getModule() == nullptr) {
     60            kernel->makeModule(iBuilder);
     61        }
     62        mUncachedKernel.emplace_back(kernel);
    2363    }
    2464}
    2565
    26 Driver::~Driver() {}
     66/** ------------------------------------------------------------------------------------------------------------- *
     67 * @brief constructor
     68 ** ------------------------------------------------------------------------------------------------------------- */
     69BaseDriver::BaseDriver(std::string && moduleName)
     70: mContext(new llvm::LLVMContext())
     71, mMainModule(new llvm::Module(moduleName, *mContext))
     72, iBuilder(nullptr) {
     73    ObjectCacheManager::initializeCacheSystems();
     74}
     75
     76/** ------------------------------------------------------------------------------------------------------------- *
     77 * @brief deconstructor
     78 ** ------------------------------------------------------------------------------------------------------------- */
     79BaseDriver::~BaseDriver() {
     80
     81}
  • icGREP/icgrep-devel/icgrep/toolchain/driver.h

    r6047 r6184  
    44#include <IR_Gen/FunctionTypeBuilder.h>
    55#include <llvm/ExecutionEngine/GenericValue.h>
     6#include <kernels/kernel.h>
    67#include <kernels/streamset.h>
    7 #include <kernels/kernel.h>
     8#include <kernels/relationship.h>
     9#include <toolchain/object_cache_manager.h>
     10#include <util/slab_allocator.h>
    811#include <string>
    912#include <vector>
     
    1215namespace llvm { class Function; }
    1316namespace kernel { class KernelBuilder; }
     17namespace kernel { class PipelineBuilder; }
     18class CBuilder;
    1419
    15 class Driver {
     20class ObjectCacheManager;
     21
     22class BaseDriver {
    1623    friend class CBuilder;
     24    friend class kernel::PipelineBuilder;
     25    using Kernel = kernel::Kernel;
     26    using Relationship = kernel::Relationship;
     27    using Bindings = kernel::Bindings;
     28    using OwnedKernels = std::vector<std::unique_ptr<Kernel>>;
     29
    1730public:
    18     Driver(std::string && moduleName);
     31
     32    std::unique_ptr<kernel::PipelineBuilder> makePipelineWithIO(Bindings stream_inputs = {}, Bindings stream_outputs = {}, Bindings scalar_inputs = {}, Bindings scalar_outputs = {});
     33
     34    std::unique_ptr<kernel::PipelineBuilder> makePipeline(Bindings scalar_inputs = {}, Bindings scalar_outputs = {});
    1935
    2036    const std::unique_ptr<kernel::KernelBuilder> & getBuilder() {
     
    2238    }
    2339
    24     template<typename BufferType, typename... Args>
    25     parabix::StreamSetBuffer * addBuffer(Args &&... args) {
    26         BufferType * const b = new BufferType(std::forward<Args>(args) ...);
    27         mOwnedBuffers.emplace_back(b);
    28         mOwnedBuffers.back()->allocateBuffer(iBuilder);
    29         return b;
    30     }
     40    kernel::StreamSet * CreateStreamSet(const unsigned NumElements = 1, const unsigned FieldWidth = 1);
    3141
    32     template<typename KernelType, typename... Args>
    33     kernel::Kernel * addKernelInstance(Args &&... args) {
    34         KernelType * const k = new KernelType(std::forward<Args>(args) ...);
    35         mOwnedKernels.emplace_back(k);
    36         return k;
    37     }
     42    kernel::Scalar * CreateScalar(llvm::Type * scalarType);
    3843
    39     virtual void makeKernelCall(kernel::Kernel * kb, const std::vector<parabix::StreamSetBuffer *> & inputs, const std::vector<parabix::StreamSetBuffer *> & outputs) = 0;
     44    kernel::Scalar * CreateConstant(llvm::Constant * value);
    4045
    41     virtual void generatePipelineIR() = 0;
     46    void addKernel(Kernel * const kernel);
    4247
    4348    template <typename ExternalFunctionType>
    44     llvm::Function * LinkFunction(kernel::Kernel & kb, llvm::StringRef name, ExternalFunctionType * functionPtr) const;
     49    llvm::Function * LinkFunction(not_null<Kernel *> kb, llvm::StringRef name, ExternalFunctionType & functionPtr) const;
    4550
    4651    virtual bool hasExternalFunction(const llvm::StringRef functionName) const = 0;
    4752
    48     void deallocateBuffers();
     53    virtual void generateUncachedKernels() = 0;
     54
     55    virtual void * finalizeObject(llvm::Function * mainMethod) = 0;
    4956   
    50     virtual void finalizeObject() = 0;
    51    
    52     virtual void * getMain() = 0; // "main" exists until the driver is deleted
    53    
    54     virtual void performIncrementalCacheCleanupStep() = 0;
     57    virtual ~BaseDriver();
    5558
    56     virtual ~Driver() = 0;
     59    llvm::LLVMContext & getContext() const {
     60        return *mContext.get();
     61    }
     62
     63    llvm::Module * getMainModule() const {
     64        return mMainModule;
     65    }
    5766
    5867protected:
     68
     69    BaseDriver(std::string && moduleName);
    5970
    6071    virtual llvm::Function * addLinkFunction(llvm::Module * mod, llvm::StringRef name, llvm::FunctionType * type, void * functionPtr) const = 0;
    6172
    6273protected:
     74
    6375    std::unique_ptr<llvm::LLVMContext>                      mContext;
    6476    llvm::Module * const                                    mMainModule;
    6577    std::unique_ptr<kernel::KernelBuilder>                  iBuilder;
    66     std::vector<std::unique_ptr<kernel::Kernel>>            mOwnedKernels;
    67     std::vector<std::unique_ptr<parabix::StreamSetBuffer>>  mOwnedBuffers;
    68     std::vector<kernel::Kernel *>                           mPipeline;
     78    OwnedKernels                                            mUncachedKernel;
     79    OwnedKernels                                            mCachedKernel;
     80    SlabAllocator<>                                         mAllocator;
    6981};
    7082
    7183template <typename ExternalFunctionType>
    72 llvm::Function * Driver::LinkFunction(kernel::Kernel & kb, llvm::StringRef name, ExternalFunctionType * functionPtr) const {
    73     llvm::FunctionType * const type = FunctionTypeBuilder<ExternalFunctionType>::get(*mContext.get());
     84llvm::Function * BaseDriver::LinkFunction(not_null<Kernel *> kb, llvm::StringRef name, ExternalFunctionType & functionPtr) const {
     85    llvm::FunctionType * const type = FunctionTypeBuilder<ExternalFunctionType>::get(getContext());
    7486    assert ("FunctionTypeBuilder did not resolve a function type." && type);
    75     return addLinkFunction(kb.getModule(), name, type, reinterpret_cast<void *>(functionPtr));
     87    return addLinkFunction(kb->getModule(), name, type, reinterpret_cast<void *>(functionPtr));
    7688}
    7789
  • icGREP/icgrep-devel/icgrep/toolchain/object_cache.cpp

    r5841 r6184  
    9292        const auto moduleId = kernel->getCacheName(idb);
    9393
    94         // Have we already seen this module before?
    95         const auto f = mCachedObject.find(moduleId);
    96         if (LLVM_UNLIKELY(f != mCachedObject.end())) {
    97             Module * const m = f->second.first; assert (m);
    98             kernel->setModule(m);
    99             kernel->prepareCachedKernel(idb);
    100             return true;
    101         }
     94        // TODO: To enable the quick lookup of previously cached objects, I need to reclaim ownership
     95        // of the modules from the JIT engine before it destroys them.
     96
     97//        // Have we already seen this module before?
     98//        const auto f = mCachedObject.find(moduleId);
     99//        if (LLVM_UNLIKELY(f != mCachedObject.end())) {
     100//            Module * const m = f->second.first; assert (m);
     101//            kernel->setModule(m);
     102//            kernel->prepareCachedKernel(idb);
     103//            return true;
     104//        }
    102105
    103106        // No, check for an existing cache file.
     
    163166void ParabixObjectCache::notifyObjectCompiled(const Module * M, MemoryBufferRef Obj) {
    164167    if (LLVM_LIKELY(M->getNamedMetadata(CACHEABLE))) {
     168
    165169        const auto moduleId = M->getModuleIdentifier();
    166170        Path objectName(mCachePath);
     
    200204
    201205void ParabixObjectCache::performIncrementalCacheCleanupStep() {
    202     mCleanupMutex.lock();
    203     if (LLVM_UNLIKELY(mCleanupIterator == fs::directory_iterator())) {
     206    if (LLVM_LIKELY(mCleanupMutex.try_lock())) {
     207        try {
     208
     209            // Simple clean-up policy: files that haven't been touched by the
     210            // driver in MaxCacheEntryHours are deleted.
     211
     212            // TODO: possibly incrementally manage by size and/or total file count.
     213            // TODO: possibly determine total filecount and set items per clean up step based on
     214            // filecount
     215
     216            const auto now = std::time(nullptr);
     217            while (LLVM_LIKELY(mCleanupIterator != fs::directory_iterator())) {
     218                const auto i = mCleanupIterator;
     219                ++mCleanupIterator;
     220                const auto & e = i->path();
     221                if (LLVM_LIKELY(fs::is_regular_file(e))) {
     222                    const auto expiry = fs::last_write_time(e) + (CACHE_ENTRY_MAX_HOURS * SECONDS_PER_HOUR);
     223                    if (now > expiry) {
     224                        fs::remove(e);
     225                        break;
     226                    }
     227                }
     228            }
     229        } catch (...) {
     230            fs::path p(mCachePath.str());
     231            mCleanupIterator = fs::directory_iterator(p);
     232        }
    204233        mCleanupMutex.unlock();
    205     } else {
    206         const auto e = mCleanupIterator->path();
    207         mCleanupIterator++;
    208         mCleanupMutex.unlock();
    209 
    210         // Simple clean-up policy: files that haven't been touched by the
    211         // driver in MaxCacheEntryHours are deleted.
    212         // TODO: possibly incrementally manage by size and/or total file count.
    213         // TODO: possibly determine total filecount and set items per clean up step based on
    214         // filecount
    215         if (fs::is_regular_file(e)) {
    216             const auto age = std::time(nullptr) - fs::last_write_time(e);
    217             if (age > (CACHE_ENTRY_MAX_HOURS * SECONDS_PER_HOUR)) {
    218                 fs::remove(e);
    219             }
    220         }
    221234    }
    222235}
     
    256269
    257270}
    258 
    259 
  • icGREP/icgrep-devel/icgrep/toolchain/object_cache.h

    r5771 r6184  
    2727// of the LLVM ExecutionEngine as well as the Parabix Kernel builder infrastructure.
    2828//
    29 // The ParabixObjectCache allows the ParabixDriver to look up cached modules based on a
     29// The ParabixObjectCache allows the CPUEngineInstance to look up cached modules based on a
    3030// module stub that contains only the necessary Module ID and signature (loadCachedObjectFile).
    3131// If found, the module object file is immediately loaded into the cachedObjectMap,
    3232// and later made available to the ExecutionEngine as needed.  Otherwise, false is
    33 // return to signal that a cached File is not found.  The ParabixDriver can then
     33// return to signal that a cached File is not found.  The CPUEngineInstance can then
    3434// apply the necessary kernel builder to build the full module IR before passing
    3535// it to the ExecutionEngine.
  • icGREP/icgrep-devel/icgrep/toolchain/toolchain.cpp

    r6030 r6184  
    1010#include <llvm/Support/CommandLine.h>
    1111#include <llvm/Support/raw_ostream.h>
     12#include <boost/interprocess/mapped_region.hpp>
    1213
    1314using namespace llvm;
     
    2021
    2122namespace codegen {
     23   
     24inline unsigned getPageSize() {
     25    return boost::interprocess::mapped_region::get_page_size();
     26}
    2227
    23 const unsigned DEFAULT_SEGMENT_SIZE = 64;
    24    
    2528static cl::OptionCategory CodeGenOptions("Code Generation Options", "These options control code generation.");
    2629
     
    3134                        clEnumVal(TraceDynamicBuffers, "Show dynamic buffer allocations and deallocations."),
    3235                        clEnumVal(EnableAsserts, "Enable built-in Parabix framework asserts in generated IR."),
     36                        clEnumVal(EnableMProtect, "Use mprotect to cause a write fault when erroneously overwriting kernel state / stream space.\n"
     37                                                  "NOTE: this requires memory to be page-aligned, which may still hide errors."),
    3338                        clEnumVal(EnableCycleCounter, "Count and report CPU cycles per kernel."),
    3439                        clEnumVal(DisableIndirectBranch, "Disable use of indirect branches in kernel code.")
     
    6873
    6974
    70 static cl::opt<unsigned, true> SegmentSizeOption("segment-size", cl::location(SegmentSize), cl::init(DEFAULT_SEGMENT_SIZE),
    71                                             cl::desc("Segment Size"), cl::value_desc("positive integer"));
     75static cl::opt<unsigned, true> SegmentSizeOption("segment-size", cl::location(SegmentSize),
     76                                               cl::init(getPageSize()),
     77                                               cl::desc("Expected amount of input data to process per segment"), cl::value_desc("positive integer"), cl::cat(CodeGenOptions));
    7278
    7379static cl::opt<unsigned, true> BufferSegmentsOption("buffer-segments", cl::location(BufferSegments), cl::init(1),
     
    7985
    8086
    81 static cl::opt<bool, true> segmentPipelineParallelOption("enable-segment-pipeline-parallel", cl::location(SegmentPipelineParallel),
     87static cl::opt<bool, true> segmentPipelineParallelOption("enable-segment-pipeline-parallel", cl::location(SegmentPipelineParallel), cl::init(false),
    8288                                                         cl::desc("Enable multithreading with segment pipeline parallelism."), cl::cat(CodeGenOptions));
    8389
     
    161167}
    162168
    163 }
    164169#if LLVM_VERSION_INTEGER < LLVM_VERSION_CODE(6, 0, 0)
    165170void printParabixVersion () {
     
    177182    cl::AddExtraVersionPrinter(&printParabixVersion);
    178183}
     184
     185}
  • icGREP/icgrep-devel/icgrep/toolchain/toolchain.h

    r6105 r6184  
    3737    TraceDynamicBuffers,
    3838    EnableAsserts,
     39    EnableMProtect,
    3940    EnableCycleCounter,
    4041    DisableIndirectBranch,
     
    5859const unsigned LaneWidth = 64;
    5960extern unsigned BlockSize;  // set from command line
    60 extern unsigned SegmentSize;  // set from command line
     61extern unsigned SegmentSize; // set from command line
    6162extern unsigned BufferSegments;
    6263extern unsigned ThreadNum;
     
    6970void ParseCommandLineOptions(int argc, const char *const *argv, std::initializer_list<const llvm::cl::OptionCategory *> hiding = {});
    7071
     72void AddParabixVersionPrinter();
     73
    7174}
    7275
    73 void AddParabixVersionPrinter();
    74 
    7576#endif
Note: See TracChangeset for help on using the changeset viewer.