Ignore:
Timestamp:
May 10, 2017, 4:26:11 PM (2 years ago)
Author:
nmedfort
Message:

Large refactoring step. Removed IR generation code from Kernel (formally KernelBuilder?) and moved it into the new KernelBuilder? class.

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

Legend:

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

    r5435 r5440  
    5252                          '_'};
    5353
    54 bool ParabixObjectCache::loadCachedObjectFile(kernel::Kernel * const kernel) {
     54bool ParabixObjectCache::loadCachedObjectFile(const std::unique_ptr<kernel::KernelBuilder> & idb, kernel::Kernel * const kernel) {
    5555    if (LLVM_LIKELY(kernel->isCachable())) {
    5656
     
    6464            if (f == mKernelSignatureMap.end()) {
    6565                return kernel->moduleIDisSignature();
    66             } else if (kernel->moduleIDisSignature() || (kernel->makeSignature() != f->second)) {
     66            } else if (kernel->moduleIDisSignature() || (kernel->makeSignature(idb) != f->second)) {
    6767                return false;
    6868            }
     
    8383                if (signatureBuffer) {
    8484                    const StringRef loadedSig = signatureBuffer.get()->getBuffer();
    85                     if (!loadedSig.equals(kernel->makeSignature())) {
     85                    if (!loadedSig.equals(kernel->makeSignature(idb))) {
    8686                        return false;
    8787                    }
     
    9696            return true;
    9797        } else if (!kernel->moduleIDisSignature()) {
    98             mKernelSignatureMap.emplace(moduleId, kernel->makeSignature());
     98            mKernelSignatureMap.emplace(moduleId, kernel->makeSignature(idb));
    9999        }
    100100    }
  • icGREP/icgrep-devel/icgrep/toolchain/object_cache.h

    r5435 r5440  
    1818namespace llvm { class MemoryBufferRef; }
    1919namespace kernel { class Kernel; }
     20namespace kernel { class KernelBuilder; }
    2021
    2122// The ParabixObjectCache is a two-level cache compatible with the requirements
     
    4041    ParabixObjectCache();
    4142    ParabixObjectCache(const std::string & dir);
    42     bool loadCachedObjectFile(kernel::Kernel * const kernel);
     43    bool loadCachedObjectFile(const std::unique_ptr<kernel::KernelBuilder> & idb, kernel::Kernel * const kernel);
    4344    void notifyObjectCompiled(const llvm::Module *M, llvm::MemoryBufferRef Obj) override;
    4445    std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module * M) override;
  • icGREP/icgrep-devel/icgrep/toolchain/pipeline.cpp

    r5436 r5440  
    1212#include <boost/container/flat_map.hpp>
    1313#include <kernels/kernel_builder.h>
     14
     15#include <llvm/Support/raw_ostream.h>
    1416
    1517using namespace kernel;
     
    103105        iBuilder->SetInsertPoint(segmentWait);
    104106        const unsigned waitIdx = codegen::DebugOptionIsSet(codegen::SerializeThreads) ? (n - 1) : k;
    105         kernels[waitIdx]->setBuilder(iBuilder);
    106         Value * const processedSegmentCount = kernels[waitIdx]->acquireLogicalSegmentNo();
    107 
     107
     108        iBuilder->setKernel(kernels[waitIdx]);
     109        Value * const processedSegmentCount = iBuilder->acquireLogicalSegmentNo();
     110        iBuilder->setKernel(kernel);
    108111
    109112        assert (processedSegmentCount->getType() == segNo->getType());
     
    118121
    119122            iBuilder->SetInsertPoint(completionTest);
    120 
    121             kernel->setBuilder(iBuilder);
    122             Value * terminationSignal = kernel->getTerminationSignal();
    123 
     123            Value * terminationSignal = iBuilder->getTerminationSignal();
    124124            iBuilder->CreateCondBr(terminationSignal, exitBlock, segmentLoopBody);
    125125            iBuilder->SetInsertPoint(exitBlock);
    126126            // Ensure that the next thread will also exit.
    127             kernel->releaseLogicalSegmentNo(nextSegNo);
     127            iBuilder->releaseLogicalSegmentNo(nextSegNo);
    128128            iBuilder->CreateBr(exitThreadBlock);
    129129        }
     
    139139        }
    140140
    141         kernel->setBuilder(iBuilder);
    142         kernel->createDoSegmentCall(args);       
     141        iBuilder->setKernel(kernel);
     142        iBuilder->createDoSegmentCall(args);
    143143        if (!kernel->hasNoTerminateAttribute()) {
    144             terminated = iBuilder->CreateOr(terminated, kernel->getTerminationSignal());
     144            terminated = iBuilder->CreateOr(terminated, iBuilder->getTerminationSignal());
    145145        }
    146146
    147147        const auto & outputs = kernel->getStreamOutputs();
    148         for (unsigned i = 0; i < outputs.size(); ++i) {
    149             kernel->setBuilder(iBuilder);
    150             Value * const produced = kernel->getProducedItemCount(outputs[i].name, terminated);
     148        for (unsigned i = 0; i < outputs.size(); ++i) {           
     149            Value * const produced = iBuilder->getProducedItemCount(outputs[i].name, terminated);
    151150            const StreamSetBuffer * const buf = kernel->getStreamSetOutputBuffer(i);
    152151            assert (producedPos.count(buf) == 0);
     
    154153        }
    155154        for (unsigned i = 0; i < inputs.size(); ++i) {
    156             kernel->setBuilder(iBuilder);
    157             Value * const processedItemCount = kernel->getProcessedItemCount(inputs[i].name);
     155            Value * const processedItemCount = iBuilder->getProcessedItemCount(inputs[i].name);
    158156            const StreamSetBuffer * const buf = kernel->getStreamSetInputBuffer(i);           
    159157            auto f = consumedPos.find(buf);
     
    165163            }
    166164        }
    167         kernel->setBuilder(iBuilder);
    168         kernel->releaseLogicalSegmentNo(nextSegNo);
     165        iBuilder->releaseLogicalSegmentNo(nextSegNo);
    169166    }
    170167
     
    178175        for (unsigned i = 0; i < outputs.size(); ++i) {
    179176            if (outputs[i] == buf) {
    180                 kernel->setBuilder(iBuilder);
    181                 kernel->setConsumedItemCount(kernel->getStreamOutputs()[i].name, consumed.second);
     177                iBuilder->setKernel(kernel);
     178                iBuilder->setConsumedItemCount(kernel->getStreamOutput(i).name, consumed.second);
    182179                break;
    183180            }
     
    223220
    224221    for (unsigned i = 0; i < n; ++i) {
    225         auto kernel = kernels[i];
    226         kernel->setBuilder(iBuilder);
    227         kernel->releaseLogicalSegmentNo(iBuilder->getSize(0));
     222        iBuilder->setKernel(kernels[i]);
     223        iBuilder->releaseLogicalSegmentNo(iBuilder->getSize(0));
    228224    }
    229225
     
    293289
    294290    for (auto & kernel : kernels) {
    295         kernel->setBuilder(iBuilder);
    296         kernel->releaseLogicalSegmentNo(iBuilder->getSize(0));
     291        iBuilder->setKernel(kernel);
     292        iBuilder->releaseLogicalSegmentNo(iBuilder->getSize(0));
    297293    }
    298294
     
    337333    for (unsigned id = 0; id < n; id++) {
    338334        const auto & kernel = kernels[id];
     335
     336        iBuilder->setKernel(kernel);
     337
    339338        const auto & inputs = kernel->getStreamInputs();
    340339
     
    372371        }
    373372        for (unsigned k : kernelSet) {
    374             Value * consumerSegNo = kernels[k]->acquireLogicalSegmentNo();
     373            iBuilder->setKernel(kernels[k]);
     374            Value * consumerSegNo = iBuilder->acquireLogicalSegmentNo();
    375375            assert (consumerSegNo->getType() == segNo->getType());
    376376            Value * consumedSegNo = iBuilder->CreateAdd(consumerSegNo, bufferSegments);
     
    378378        }
    379379        kernelSet.clear();
     380        iBuilder->setKernel(kernel);
    380381        iBuilder->CreateCondBr(outputWaitCond, inputCheckBlock, outputCheckBlock);
    381382
     
    388389        Value * inputWaitCond = iBuilder->getTrue();
    389390        for (unsigned k : kernelSet) {
    390             Kernel * kernel = kernels[k];
    391             kernel->setBuilder(iBuilder);
    392             producerSegNo[k] = kernel->acquireLogicalSegmentNo();
     391            iBuilder->setKernel(kernels[k]);
     392            producerSegNo[k] = iBuilder->acquireLogicalSegmentNo();
    393393            assert (producerSegNo[k]->getType() == segNo->getType());
    394394            inputWaitCond = iBuilder->CreateAnd(inputWaitCond, iBuilder->CreateICmpULT(segNo, producerSegNo[k]));
    395395        }
     396        iBuilder->setKernel(kernel);
    396397        iBuilder->CreateCondBr(inputWaitCond, doSegmentBlock, inputCheckBlock);
    397398
     
    403404        if (kernelSet.empty()) {
    404405            // if this kernel has no input streams, the kernel itself must decide when it terminates.
    405             terminated = kernel->getTerminationSignal();
     406            terminated = iBuilder->getTerminationSignal();
    406407        } else {
    407408            // ... otherwise the kernel terminates only when it exhausts all of its input streams
    408409            terminated = iBuilder->getTrue();
    409410            for (unsigned k : kernelSet) {
    410                 terminated = iBuilder->CreateAnd(terminated, kernels[k]->getTerminationSignal());
     411                iBuilder->setKernel(kernels[k]);
     412                terminated = iBuilder->CreateAnd(terminated, iBuilder->getTerminationSignal());
    411413                terminated = iBuilder->CreateAnd(terminated, iBuilder->CreateICmpEQ(nextSegNo, producerSegNo[k]));
    412414            }
    413415            kernelSet.clear();
     416            iBuilder->setKernel(kernel);
    414417        }
    415418
     
    417420        args.insert(args.end(), inputs.size(), iBuilder->CreateMul(segmentItems, segNo));
    418421
    419         kernel->createDoSegmentCall(args);
     422        iBuilder->createDoSegmentCall(args);
    420423        segNo->addIncoming(nextSegNo, doSegmentBlock);
    421         kernel->releaseLogicalSegmentNo(nextSegNo);
     424        iBuilder->releaseLogicalSegmentNo(nextSegNo);
    422425
    423426        iBuilder->CreateCondBr(terminated, exitThreadBlock, outputCheckBlock);
     
    480483    Value * terminated = iBuilder->getFalse();
    481484    for (unsigned k = 0; k < kernels.size(); k++) {
     485
    482486        auto & kernel = kernels[k];
    483487
     488        iBuilder->setKernel(kernel);
    484489        const auto & inputs = kernel->getStreamInputs();
    485490        const auto & outputs = kernel->getStreamOutputs();
     
    494499        }
    495500
    496         kernel->setBuilder(iBuilder);
    497         kernel->createDoSegmentCall(args);
     501        iBuilder->createDoSegmentCall(args);
    498502        if (!kernel->hasNoTerminateAttribute()) {
    499             Value * terminatedSignal = kernel->getTerminationSignal();
     503            Value * terminatedSignal = iBuilder->getTerminationSignal();
    500504            terminated = iBuilder->CreateOr(terminated, terminatedSignal);
    501             kernel->setBuilder(iBuilder);
    502505        }
    503506        for (unsigned i = 0; i < outputs.size(); ++i) {
    504             Value * const produced = kernel->getProducedItemCount(outputs[i].name, terminated);
     507            Value * const produced = iBuilder->getProducedItemCount(outputs[i].name, terminated);
    505508            const StreamSetBuffer * const buf = kernel->getStreamSetOutputBuffer(i);
    506509            assert (producedPos.count(buf) == 0);
     
    509512
    510513        for (unsigned i = 0; i < inputs.size(); ++i) {
    511             kernel->setBuilder(iBuilder);
    512             Value * const processedItemCount = kernel->getProcessedItemCount(inputs[i].name);
     514            Value * const processedItemCount = iBuilder->getProcessedItemCount(inputs[i].name);
    513515            const StreamSetBuffer * const buf = kernel->getStreamSetInputBuffer(i);
    514 
    515516            auto f = consumedPos.find(buf);
    516517            if (f == consumedPos.end()) {
     
    528529        }
    529530
    530         kernel->setBuilder(iBuilder);
    531         Value * const segNo = kernel->acquireLogicalSegmentNo();
     531
     532        Value * const segNo = iBuilder->acquireLogicalSegmentNo();
    532533        Value * nextSegNo = iBuilder->CreateAdd(segNo, iBuilder->getSize(1));
    533         kernel->releaseLogicalSegmentNo(nextSegNo);
     534        iBuilder->releaseLogicalSegmentNo(nextSegNo);
    534535    }
    535536
     
    540541        for (unsigned i = 0; i < outputs.size(); ++i) {
    541542            if (outputs[i] == buf) {
    542                 k->setBuilder(iBuilder);
    543                 k->setConsumedItemCount(k->getStreamOutputs()[i].name, consumed.second);
     543                iBuilder->setKernel(k);
     544                iBuilder->setConsumedItemCount(k->getStreamOutput(i).name, consumed.second);
    544545                break;
    545546            }
     
    552553        for (unsigned k = 0; k < kernels.size(); k++) {
    553554            auto & kernel = kernels[k];
     555            iBuilder->setKernel(kernel);
    554556            const auto & inputs = kernel->getStreamInputs();
    555557            const auto & outputs = kernel->getStreamOutputs();
    556             Value * items = inputs.size() > 0 ? kernel->getProcessedItemCount(inputs[0].name) : kernel->getProducedItemCount(outputs[0].name);
     558            Value * items = nullptr;
     559            if (inputs.empty()) {
     560                items = iBuilder->getProducedItemCount(outputs[0].name);
     561            } else {
     562                items = iBuilder->getProcessedItemCount(outputs[0].name);
     563            }
    557564            Value * fItems = iBuilder->CreateUIToFP(items, iBuilder->getDoubleTy());
    558565            Value * cycles = iBuilder->CreateLoad(iBuilder->CreateGEP(mCycleCounts, {iBuilder->getInt32(0), iBuilder->getInt32(k)}));
  • icGREP/icgrep-devel/icgrep/toolchain/toolchain.cpp

    r5436 r5440  
    1515#include <llvm/IR/IRPrintingPasses.h>
    1616#include <llvm/InitializePasses.h>                 // for initializeCodeGen
    17 #ifndef NDEBUG
    18 #include <llvm/IR/Verifier.h>
    19 #include <boost/container/flat_set.hpp>
    20 #endif
    2117#include <llvm/PassRegistry.h>                     // for PassRegistry
    2218#include <llvm/Support/CodeGen.h>                  // for Level, Level::None
     
    3430#include <thread>
    3531#include <boost/lockfree/queue.hpp>
     32#ifndef NDEBUG
     33#include <llvm/IR/Verifier.h>
     34#endif
    3635
    3736using namespace llvm;
     
    151150
    152151    builder.setTargetOptions(opts);
    153     builder.setVerifyModules(IN_DEBUG_MODE);
     152    builder.setVerifyModules(false);
    154153    CodeGenOpt::Level optLevel = CodeGenOpt::Level::None;
    155154    switch (codegen::OptLevel) {
     
    204203    assert ("addKernelCall or makeKernelCall was already run on this kernel." && (kb.getModule() == nullptr));
    205204    mPipeline.emplace_back(&kb);
    206     assert (mMainModule);
    207     kb.setBuilder(iBuilder);
    208     kb.createKernelStub(inputs, outputs);
     205    kb.createKernelStub(iBuilder, inputs, outputs);
    209206}
    210207
     
    212209    assert ("addKernelCall or makeKernelCall was already run on this kernel." && (kb->getModule() == nullptr));
    213210    mPipeline.emplace_back(kb);   
    214     kb->setBuilder(iBuilder);
    215     kb->createKernelStub(inputs, outputs);
     211    kb->createKernelStub(iBuilder, inputs, outputs);
    216212}
    217213
     
    219215    #ifndef NDEBUG
    220216    if (LLVM_UNLIKELY(mPipeline.empty())) {
    221         report_fatal_error("Pipeline must contain at least one kernel");
     217        report_fatal_error("Pipeline cannot be empty");
    222218    } else {
    223         boost::container::flat_set<kernel::Kernel *> K(mPipeline.begin(), mPipeline.end());
    224         if (LLVM_UNLIKELY(K.size() != mPipeline.size())) {
    225             report_fatal_error("Kernel definitions can only occur once in the pipeline");
     219        for (auto i = mPipeline.begin(); i != mPipeline.end(); ++i) {
     220            for (auto j = i; ++j != mPipeline.end(); ) {
     221                if (LLVM_UNLIKELY(*i == *j)) {
     222                    report_fatal_error("Kernel instances cannot occur twice in the pipeline");
     223                }
     224            }
    226225        }
    227226    }
    228227    #endif
    229 
    230228    // note: instantiation of all kernels must occur prior to initialization
    231229    for (const auto & k : mPipeline) {
    232         k->addKernelDeclarations();
     230        k->addKernelDeclarations(iBuilder);
    233231    }
    234232    for (const auto & k : mPipeline) {
    235         k->createInstance();
     233        k->createInstance(iBuilder);
    236234    }
    237235    for (const auto & k : mPipeline) {
    238         k->initializeInstance();
     236        k->initializeInstance(iBuilder);
    239237    }
    240238    if (codegen::pipelineParallel) {
     
    247245    }
    248246    for (const auto & k : mPipeline) {
    249         k->setBuilder(iBuilder);
    250         k->finalizeInstance();
     247        k->finalizeInstance(iBuilder);
    251248    }
    252249}
     
    260257
    261258void ParabixDriver::linkAndFinalize() {
    262     Module * m = mMainModule;
    263     #ifndef NDEBUG
     259    Module * module = nullptr;
    264260    try {
    265     #endif
    266     legacy::PassManager PM;
    267     #ifndef NDEBUG
    268     PM.add(createVerifierPass());
    269     #endif
    270     PM.add(createPromoteMemoryToRegisterPass()); //Force the use of mem2reg to promote stack variables.
    271     PM.add(createReassociatePass());             //Reassociate expressions.
    272     PM.add(createGVNPass());                     //Eliminate common subexpressions.
    273     PM.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
    274     PM.add(createCFGSimplificationPass());
    275 
    276     raw_fd_ostream * IROutputStream = nullptr;
    277     if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowIR))) {
    278         if (codegen::IROutputFilename.empty()) {
    279             IROutputStream = new raw_fd_ostream(STDERR_FILENO, false, false);
    280         } else {
    281             std::error_code error;
    282             IROutputStream = new raw_fd_ostream(codegen::IROutputFilename, error, sys::fs::OpenFlags::F_None);
    283         }
    284         PM.add(createPrintModulePass(*IROutputStream));
    285     }
    286 
    287     #ifndef USE_LLVM_3_6
    288     raw_fd_ostream * ASMOutputStream = nullptr;
    289     if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowASM))) {
    290         if (codegen::ASMOutputFilename.empty()) {
    291             ASMOutputStream = new raw_fd_ostream(STDERR_FILENO, false, false);
    292         } else {
    293             std::error_code error;
    294             ASMOutputStream = new raw_fd_ostream(codegen::ASMOutputFilename, error, sys::fs::OpenFlags::F_None);
    295         }
    296         if (LLVM_UNLIKELY(mTarget->addPassesToEmitFile(PM, *ASMOutputStream, TargetMachine::CGFT_AssemblyFile))) {
    297             report_fatal_error("LLVM error: could not add emit assembly pass");
    298         }
    299     }
    300     #endif
    301 
    302     PM.run(*m);
    303 
    304     for (kernel::Kernel * const k : mPipeline) {
    305         m = k->getModule();
    306         bool uncachedObject = true;
    307         if (mCache && mCache->loadCachedObjectFile(k)) {
    308             uncachedObject = false;
    309         }
    310         if (uncachedObject) {
    311             iBuilder->setModule(m);
    312             k->setBuilder(iBuilder);
    313             k->generateKernel();
    314             PM.run(*m);
    315         }
    316         mEngine->addModule(std::unique_ptr<Module>(m));
    317     }   
    318     mEngine->finalizeObject();
    319 
    320     iBuilder->setModule(mMainModule);
    321 
    322     delete IROutputStream;
    323     #ifndef USE_LLVM_3_6
    324     delete ASMOutputStream;
    325     #endif
    326     #ifndef NDEBUG
    327     } catch (...) { m->dump(); throw; }
    328     #endif
     261
     262        legacy::PassManager PM;
     263        #ifndef NDEBUG
     264        PM.add(createVerifierPass());
     265        #endif
     266        PM.add(createPromoteMemoryToRegisterPass()); //Force the use of mem2reg to promote stack variables.
     267        PM.add(createReassociatePass());             //Reassociate expressions.
     268        PM.add(createGVNPass());                     //Eliminate common subexpressions.
     269        PM.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
     270        PM.add(createCFGSimplificationPass());
     271
     272        std::unique_ptr<raw_fd_ostream> IROutputStream(nullptr);
     273        if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowIR))) {
     274            if (codegen::IROutputFilename.empty()) {
     275                IROutputStream.reset(new raw_fd_ostream(STDERR_FILENO, false, false));
     276            } else {
     277                std::error_code error;
     278                IROutputStream.reset(new raw_fd_ostream(codegen::IROutputFilename, error, sys::fs::OpenFlags::F_None));
     279            }
     280            PM.add(createPrintModulePass(*IROutputStream));
     281        }
     282
     283        #ifndef USE_LLVM_3_6
     284        std::unique_ptr<raw_fd_ostream> ASMOutputStream(nullptr);
     285        if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowASM))) {
     286            if (codegen::ASMOutputFilename.empty()) {
     287                ASMOutputStream.reset(new raw_fd_ostream(STDERR_FILENO, false, false));
     288            } else {
     289                std::error_code error;
     290                ASMOutputStream.reset(new raw_fd_ostream(codegen::ASMOutputFilename, error, sys::fs::OpenFlags::F_None));
     291            }
     292            if (LLVM_UNLIKELY(mTarget->addPassesToEmitFile(PM, *ASMOutputStream, TargetMachine::CGFT_AssemblyFile))) {
     293                report_fatal_error("LLVM error: could not add emit assembly pass");
     294            }
     295        }
     296        #endif
     297
     298        for (kernel::Kernel * const kernel : mPipeline) {
     299            iBuilder->setKernel(kernel);
     300            module = kernel->getModule();
     301            bool uncachedObject = true;
     302            if (mCache && mCache->loadCachedObjectFile(iBuilder, kernel)) {
     303                uncachedObject = false;
     304            }
     305            if (uncachedObject) {
     306                module->setTargetTriple(mMainModule->getTargetTriple());
     307                kernel->generateKernel(iBuilder);
     308                PM.run(*module);
     309            }
     310            mEngine->addModule(std::unique_ptr<Module>(module));
     311        }
     312
     313        iBuilder->setKernel(nullptr);
     314        module = mMainModule;
     315        PM.run(*module);
     316
     317        mEngine->finalizeObject();
     318
     319    } catch (...) {
     320        module->dump();
     321        throw;
     322    }
    329323}
    330324
Note: See TracChangeset for help on using the changeset viewer.