Ignore:
Timestamp:
Sep 7, 2017, 4:56:56 PM (21 months ago)
Author:
nmedfort
Message:

Partial check-in for avoidance of compiling Pablo/LLVM code to determine the Kernel struct type when using a cached object. Inactive RE alternation minimization check in.

Location:
icGREP/icgrep-devel/icgrep/toolchain
Files:
5 edited

Legend:

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

    r5474 r5630  
    5454    mPipeline.emplace_back(kb);
    5555    kb->bindPorts(inputs, outputs);
    56     kb->setModule(iBuilder, mMainModule);
     56    kb->setModule(mMainModule);
    5757}
    5858
  • icGREP/icgrep-devel/icgrep/toolchain/cpudriver.cpp

    r5616 r5630  
    7070        throw std::runtime_error("Could not create ExecutionEngine: " + errMessage);
    7171    }
    72     mTarget = builder.selectTarget();
     72    mTarget = builder.selectTarget();   
    7373    if (LLVM_LIKELY(codegen::EnableObjectCache)) {
    7474        if (codegen::ObjectCacheDir) {
     
    8080    }
    8181    mMainModule->setTargetTriple(mTarget->getTargetTriple().getTriple());
    82 
    8382    iBuilder.reset(IDISA::GetIDISA_Builder(*mContext));
    8483    iBuilder->setDriver(this);
     
    8685}
    8786
    88 void ParabixDriver::makeKernelCall(Kernel * kb, const std::vector<StreamSetBuffer *> & inputs, const std::vector<StreamSetBuffer *> & outputs) {
    89     assert ("addKernelCall or makeKernelCall was already run on this kernel." && (kb->getModule() == nullptr));
    90     mPipeline.emplace_back(kb);
    91     kb->bindPorts(inputs, outputs);
    92     kb->makeModule(iBuilder);
     87void ParabixDriver::makeKernelCall(Kernel * kernel, const std::vector<StreamSetBuffer *> & inputs, const std::vector<StreamSetBuffer *> & outputs) {
     88    assert ("addKernelCall or makeKernelCall was already run on this kernel." && (kernel->getModule() == nullptr));
     89    mPipeline.emplace_back(kernel);
     90    kernel->bindPorts(inputs, outputs);
     91    if (!mCache || !mCache->loadCachedObjectFile(iBuilder, kernel)) {
     92        mUncachedKernel.push_back(kernel);
     93    }
     94    if (kernel->getModule() == nullptr) {
     95        kernel->makeModule(iBuilder);
     96    }
     97    assert (kernel->getModule());
    9398}
    9499
    95100void ParabixDriver::generatePipelineIR() {
    96     #ifndef NDEBUG
     101
    97102    if (LLVM_UNLIKELY(mPipeline.empty())) {
    98103        report_fatal_error("Pipeline cannot be empty");
     
    101106            for (auto j = i; ++j != mPipeline.end(); ) {
    102107                if (LLVM_UNLIKELY(*i == *j)) {
    103                     report_fatal_error("Kernel instances cannot occur twice in the pipeline");
     108                    report_fatal_error("Kernel " + (*i)->getName() + " occurs twice in the pipeline");
    104109                }
    105110            }
    106111        }
    107112    }
    108     #endif
     113
     114    for (Kernel * const kernel : mUncachedKernel) {
     115        kernel->prepareKernel(iBuilder);
     116    }
     117
    109118    // note: instantiation of all kernels must occur prior to initialization
    110119    for (const auto & k : mPipeline) {
     
    130139
    131140Function * ParabixDriver::addLinkFunction(Module * mod, llvm::StringRef name, FunctionType * type, void * functionPtr) const {
    132     assert ("addKernelCall or makeKernelCall must be called before LinkFunction" && (mod != nullptr));
     141    if (LLVM_UNLIKELY(mod == nullptr)) {
     142        report_fatal_error("addLinkFunction(" + name + ") cannot be called until after addKernelCall or makeKernelCall");
     143    }
    133144    Function * f = mod->getFunction(name);
    134145    if (LLVM_UNLIKELY(f == nullptr)) {
    135146        f = Function::Create(type, Function::ExternalLinkage, name, mod);
    136         mEngine->addGlobalMapping(f, functionPtr);
     147        mEngine->updateGlobalMapping(f, functionPtr);
    137148    } else if (LLVM_UNLIKELY(f->getType() != type->getPointerTo())) {
    138149        report_fatal_error("Cannot link " + name + ": a function with a different signature already exists with that name in " + mod->getName());
     
    193204
    194205    Module * module = nullptr;
    195 
    196206    try {
    197 
     207        for (Kernel * const kernel : mUncachedKernel) {
     208            iBuilder->setKernel(kernel);
     209            kernel->generateKernel(iBuilder);
     210            module = kernel->getModule(); assert (module);
     211            module->setTargetTriple(mMainModule->getTargetTriple());
     212            PM.run(*module);
     213        }
     214        module = mMainModule;
     215        iBuilder->setKernel(nullptr);
     216        PM.run(*mMainModule);
    198217        for (Kernel * const kernel : mPipeline) {
    199             iBuilder->setKernel(kernel);
    200             module = kernel->getModule();
    201             assert (module != mMainModule);
    202             bool uncachedObject = true;
    203             if (mCache && mCache->loadCachedObjectFile(iBuilder, kernel)) {
    204                 uncachedObject = false;
    205             }
    206             if (uncachedObject) {
    207                 module->setTargetTriple(mMainModule->getTargetTriple());
    208                 kernel->generateKernel(iBuilder);
    209                 PM.run(*module);
    210             }
    211             mEngine->addModule(std::unique_ptr<Module>(module));
    212         }
    213 
    214         iBuilder->setKernel(nullptr);
    215         module = mMainModule;
    216         PM.run(*mMainModule);
     218            if (LLVM_UNLIKELY(kernel->getModule() == nullptr)) {
     219                report_fatal_error(kernel->getName() + " was neither loaded from cache nor generated prior to finalizeObject");
     220            }
     221            mEngine->addModule(std::unique_ptr<Module>(kernel->getModule()));
     222        }
    217223        mEngine->finalizeObject();
    218 
    219224        if (mCache) mCache->cleanUpObjectCacheFiles();
    220 
    221225    } catch (const std::exception & e) {
    222         report_fatal_error(e.what());
     226        report_fatal_error(module->getName() + ": " + e.what());
    223227    }
    224228
  • icGREP/icgrep-devel/icgrep/toolchain/cpudriver.h

    r5616 r5630  
    3434    llvm::ExecutionEngine *                                 mEngine;
    3535    ParabixObjectCache *                                    mCache;
     36    std::vector<kernel::Kernel *>                           mUncachedKernel;
    3637    // NOTE: when printing the IR/ASM, we cannot assume they're completely finished after finalizeObject is executed. Instead we store a
    3738    // pointer and delete them once the driver (and any processing) is complete. This prevents us from reclaiming the memory early but
  • icGREP/icgrep-devel/icgrep/toolchain/object_cache.cpp

    r5493 r5630  
    1313#include <boost/filesystem.hpp>
    1414#include <boost/range/iterator_range.hpp>
     15#include <boost/container/flat_set.hpp>
     16#include <llvm/Bitcode/ReaderWriter.h>
     17#include <llvm/IR/Verifier.h>
    1518#include <ctime>
    1619
     
    5962const static auto SIGNATURE = "signature";
    6063
    61 const static boost::uintmax_t CACHE_SIZE_LIMIT = 5 * 1024 * 1024;
     64const static boost::uintmax_t CACHE_SIZE_LIMIT = 50 * 1024 * 1024;
    6265
    6366const MDString * getSignature(const llvm::Module * const M) {
     
    7376bool ParabixObjectCache::loadCachedObjectFile(const std::unique_ptr<kernel::KernelBuilder> & idb, kernel::Kernel * const kernel) {
    7477    if (LLVM_LIKELY(kernel->isCachable())) {
    75         Module * const module = kernel->getModule();
    76         assert ("kernel module cannot be null!" && module);
    77         const auto moduleId = module->getModuleIdentifier();
     78        assert (kernel->getModule() == nullptr);
     79        const auto moduleId = kernel->getCacheName(idb);
     80
    7881        // Have we already seen this module before?
    79         if (LLVM_UNLIKELY(mCachedObject.count(moduleId) != 0)) {
     82        const auto f = mCachedObject.find(moduleId);
     83        if (LLVM_UNLIKELY(f != mCachedObject.end())) {
     84            Module * const m = f->second.first; assert (m);
     85            kernel->setModule(m);
    8086            return true;
    8187        }
     
    94100                if (signatureBuffer) {
    95101                    const StringRef loadedSig = signatureBuffer.get()->getBuffer();
    96                     if (!loadedSig.equals(kernel->makeSignature(idb))) {
    97                         return false;
     102                    if (LLVM_UNLIKELY(!loadedSig.equals(kernel->makeSignature(idb)))) {
     103                        goto invalid;
    98104                    }
    99105                } else {
    100106                    report_fatal_error("signature file expected but not found: " + moduleId);
    101                     return false;
     107                }               
     108            }
     109            sys::path::replace_extension(objectName, ".kernel");
     110            auto kernelBuffer = MemoryBuffer::getFile(objectName.c_str(), -1, false);
     111            if (*kernelBuffer) {
     112                //MemoryBuffer * kb = kernelBuffer.get().release();
     113                //auto loadedFile = parseBitcodeFile(kb->getMemBufferRef(), mContext);
     114                auto loadedFile = getLazyBitcodeModule(std::move(kernelBuffer.get()), idb->getContext());
     115                if (*loadedFile) {
     116                    Module * const m = loadedFile.get().release(); assert (m);
     117                    // defaults to <path>/<moduleId>.kernel
     118                    m->setModuleIdentifier(moduleId);
     119                    kernel->setModule(m);
     120                    kernel->prepareCachedKernel(idb);                   
     121                    mCachedObject.emplace(moduleId, std::make_pair(m, std::move(objectBuffer.get())));
     122                    // update the modified time of the object file
     123                    sys::path::replace_extension(objectName, ".o");
     124                    boost::filesystem::last_write_time(objectName.c_str(), time(0));
     125                    return true;
    102126                }
    103127            }
    104             // update the modified time of the file then add it to our cache
    105             boost::filesystem::last_write_time(objectName.c_str(), time(0));
    106             mCachedObject.emplace(moduleId, std::move(objectBuffer.get()));
    107             return true;
    108         } else {
    109             // mark this module as cachable
    110             module->getOrInsertNamedMetadata(CACHEABLE);
    111             // if this module has a signature, add it to the metadata
    112             if (kernel->hasSignature()) {
    113                 NamedMDNode * const md = module->getOrInsertNamedMetadata(SIGNATURE);
    114                 assert (md->getNumOperands() == 0);
    115                 MDString * const sig = MDString::get(module->getContext(), kernel->makeSignature(idb));               
    116                 md->addOperand(MDNode::get(module->getContext(), {sig}));
    117             }
     128        }
     129
     130invalid:
     131
     132        Module * const module = kernel->setModule(new Module(moduleId, idb->getContext()));
     133        // mark this module as cachable
     134        module->getOrInsertNamedMetadata(CACHEABLE);
     135        // if this module has a signature, add it to the metadata
     136        if (kernel->hasSignature()) {
     137            NamedMDNode * const md = module->getOrInsertNamedMetadata(SIGNATURE);
     138            assert (md->getNumOperands() == 0);
     139            MDString * const sig = MDString::get(module->getContext(), kernel->makeSignature(idb));
     140            md->addOperand(MDNode::get(module->getContext(), {sig}));
    118141        }
    119142    }
     
    124147// exists, write it out.
    125148void ParabixObjectCache::notifyObjectCompiled(const Module * M, MemoryBufferRef Obj) {
    126     if (M->getNamedMetadata(CACHEABLE)) {
     149    if (LLVM_LIKELY(M->getNamedMetadata(CACHEABLE))) {
    127150        const auto moduleId = M->getModuleIdentifier();
    128151        Path objectName(mCachePath);
     
    135158        }
    136159
     160        // Write the object code
    137161        std::error_code EC;
    138         raw_fd_ostream outfile(objectName, EC, sys::fs::F_None);
    139         outfile.write(Obj.getBufferStart(), Obj.getBufferSize());
    140         outfile.close();
    141 
    142         // If this module has a signature, write it.
     162        raw_fd_ostream objFile(objectName, EC, sys::fs::F_None);
     163        objFile.write(Obj.getBufferStart(), Obj.getBufferSize());
     164        objFile.close();
     165
     166        // then the signature (if one exists)
    143167        const MDString * const sig = getSignature(M);
    144168        if (sig) {
     
    148172            sigfile.close();
    149173        }
     174
     175        // and finally kernel prototype header.
     176        std::unique_ptr<Module> header(new Module(M->getModuleIdentifier(), M->getContext()));
     177        for (const Function & f : M->getFunctionList()) {
     178            if (f.hasExternalLinkage() && !f.empty()) {
     179                Function::Create(f.getFunctionType(), Function::ExternalLinkage, f.getName(), header.get());
     180            }
     181        }
     182
     183        sys::path::replace_extension(objectName, ".kernel");
     184        raw_fd_ostream kernelFile(objectName.str(), EC, sys::fs::F_None);
     185        WriteBitcodeToFile(header.get(), kernelFile, false, false);
     186        kernelFile.close();
    150187    }
    151188}
     
    178215                    objectPath.replace_extension("sig");
    179216                    remove(objectPath);
     217                    objectPath.replace_extension("kernel");
     218                    remove(objectPath);
    180219                }
    181220            }
     
    185224
    186225std::unique_ptr<MemoryBuffer> ParabixObjectCache::getObject(const Module * module) {
    187     const auto moduleId = module->getModuleIdentifier();
    188     const auto f = mCachedObject.find(moduleId);
     226    const auto f = mCachedObject.find(module->getModuleIdentifier());
    189227    if (f == mCachedObject.end()) {
    190228        return nullptr;
    191229    }
    192230    // Return a copy of the buffer, for MCJIT to modify, if necessary.
    193     return MemoryBuffer::getMemBufferCopy(f->second.get()->getBuffer());
     231    return MemoryBuffer::getMemBufferCopy(f->second.second.get()->getBuffer());
    194232}
    195233
     
    211249}
    212250
    213 ParabixObjectCache::ParabixObjectCache(const std::string & dir)
     251ParabixObjectCache::ParabixObjectCache(const std::string dir)
    214252: mCachePath(dir) {
    215253
  • icGREP/icgrep-devel/icgrep/toolchain/object_cache.h

    r5464 r5630  
    1818namespace llvm { class MemoryBuffer; }
    1919namespace llvm { class MemoryBufferRef; }
     20namespace llvm { class LLVMContext; }
    2021namespace kernel { class Kernel; }
    2122namespace kernel { class KernelBuilder; }
     
    3738    template <typename K, typename V>
    3839    using Map = boost::container::flat_map<K, V>;
    39     using ModuleCache = Map<std::string, std::unique_ptr<llvm::MemoryBuffer>>;
     40    using ModuleCache = Map<std::string, std::pair<llvm::Module *, std::unique_ptr<llvm::MemoryBuffer>>>;
    4041public:
    4142    ParabixObjectCache();
    42     ParabixObjectCache(const std::string & dir);
     43    ParabixObjectCache(const std::string dir);
    4344    bool loadCachedObjectFile(const std::unique_ptr<kernel::KernelBuilder> & idb, kernel::Kernel * const kernel);
    44     void notifyObjectCompiled(const llvm::Module *M, llvm::MemoryBufferRef Obj) override;
     45    void notifyObjectCompiled(const llvm::Module * M, llvm::MemoryBufferRef Obj) override;
    4546    void cleanUpObjectCacheFiles();
    4647    std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module * M) override;
     
    4849    static Path getDefaultPath();
    4950private:
    50     ModuleCache     mCachedObject;
    51     const Path      mCachePath;
     51    ModuleCache         mCachedObject;
     52    const Path          mCachePath;
    5253};
    5354
Note: See TracChangeset for help on using the changeset viewer.