Ignore:
Timestamp:
Apr 9, 2017, 3:59:17 PM (2 years ago)
Author:
nmedfort
Message:

Updated all projects to use ParabixDriver?. Deprecated original pipeline generation methods. Enabled LLVM optimizations, IR and ASM printing for Kernel modules. Enabled object cache by default. Begun work on moving consumed position information back to producing kernels.

File:
1 edited

Legend:

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

    r5399 r5401  
    1111#include <llvm/Support/TargetSelect.h>             // for InitializeNativeTa...
    1212#include <llvm/Support/raw_ostream.h>              // for errs, raw_ostream
     13#include <llvm/Support/FormattedStream.h>
    1314#include <llvm/ADT/SmallString.h>                  // for SmallString
    1415#include <llvm/IR/LegacyPassManager.h>             // for PassManager
     16#include <llvm/IR/IRPrintingPasses.h>
    1517#include <llvm/IR/Verifier.h>
    1618#include <llvm/InitializePasses.h>                 // for initializeCodeGen
     
    4143static cl::bits<DebugFlags>
    4244DebugOptions(cl::values(clEnumVal(ShowIR, "Print generated LLVM IR."),
    43 #if LLVM_VERSION_MINOR > 6
     45#ifndef USE_LLVM_3_6
    4446                        clEnumVal(ShowASM, "Print assembly code."),
    4547#endif
     
    4850
    4951static cl::opt<std::string> IROutputFilename("dump-generated-IR-output", cl::init(""), cl::desc("output IR filename"), cl::cat(CodeGenOptions));
    50 #if LLVM_VERSION_MINOR > 6
     52#ifndef USE_LLVM_3_6
    5153static cl::opt<std::string> ASMOutputFilename("asm-output", cl::init(""), cl::desc("output ASM filename"), cl::cat(CodeGenOptions));
    5254static cl::opt<bool> AsmVerbose("asm-verbose",
     
    6062
    6163
    62 static cl::opt<bool> EnableObjectCache("enable-object-cache", cl::init(false), cl::desc("Enable object caching"), cl::cat(CodeGenOptions));
     64static cl::opt<bool> EnableObjectCache("enable-object-cache", cl::init(true), cl::desc("Enable object caching"), cl::cat(CodeGenOptions));
    6365
    6466static cl::opt<std::string> ObjectCacheDir("object-cache-dir", cl::init(""), cl::desc("Path to the object cache diretory"), cl::cat(CodeGenOptions));
     
    8991   
    9092static cl::opt<bool> segmentPipelineParallel("enable-segment-pipeline-parallel", cl::desc("Enable multithreading with segment pipeline parallelism."), cl::cat(CodeGenOptions));
    91 
    92 
    9393   
    9494#ifdef CUDA_ENABLED
     
    101101}
    102102
    103 
    104103#ifdef CUDA_ENABLED
    105104void setNVPTXOption(){
     
    139138    cl::AddExtraVersionPrinter(&printParabixVersion);
    140139}
    141 
    142 
    143140
    144141void setAllFeatures(EngineBuilder &builder) {
     
    163160}
    164161
    165 #ifndef USE_LLVM_3_6
    166 void WriteAssembly (TargetMachine *TM, Module * m) {
    167     legacy::PassManager PM;
    168 
    169     SmallString<128> Str;
    170     raw_svector_ostream dest(Str);
    171 
    172     if (TM->addPassesToEmitFile(PM, dest, TargetMachine::CGFT_AssemblyFile ) ) {
    173         throw std::runtime_error("LLVM error: addPassesToEmitFile failed.");
    174     }
    175     PM.run(*m);
    176 
    177     if (codegen::ASMOutputFilename.empty()) {
    178         errs() << Str;
    179     } else {
    180         std::error_code error;
    181         raw_fd_ostream out(codegen::ASMOutputFilename, error, sys::fs::OpenFlags::F_None);
    182         out << Str;
    183     }
    184 }
    185 #endif
    186 
    187 ExecutionEngine * JIT_to_ExecutionEngine (Module * m) {
    188 
    189     // Use the pass manager to optimize the function.
    190     #ifndef NDEBUG
    191     try {
    192     #endif
    193     legacy::PassManager PM;
    194     #ifndef NDEBUG
    195     PM.add(createVerifierPass());
    196     #endif
    197     PM.add(createReassociatePass());             //Reassociate expressions.
    198     PM.add(createGVNPass());                     //Eliminate common subexpressions.
    199     PM.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
    200     PM.add(createCFGSimplificationPass());   
    201     PM.run(*m);
    202     #ifndef NDEBUG
    203     } catch (...) { m->dump(); throw; }
    204     #endif
     162ParabixDriver::ParabixDriver(IDISA::IDISA_Builder * iBuilder)
     163: iBuilder(iBuilder)
     164, mMainModule(iBuilder->getModule())
     165, mTarget(nullptr)
     166, mEngine(nullptr)
     167{
    205168    InitializeNativeTarget();
    206169    InitializeNativeTargetAsmPrinter();
     
    213176
    214177    std::string errMessage;
    215     EngineBuilder builder{std::unique_ptr<Module>(m)};
     178    EngineBuilder builder{std::unique_ptr<Module>(mMainModule)};
    216179    builder.setErrorStr(&errMessage);
    217180    TargetOptions opts = InitTargetOptionsFromCodeGenFlags();
     
    232195    setAllFeatures(builder);
    233196
    234     if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowIR))) {
    235         if (codegen::IROutputFilename.empty()) {
    236             m->dump();
    237         } else {
    238             std::error_code error;
    239             raw_fd_ostream out(codegen::IROutputFilename, error, sys::fs::OpenFlags::F_None);
    240             m->print(out, nullptr);
    241         }
    242     }
    243 #if LLVM_VERSION_MINOR > 6
    244     if (codegen::DebugOptionIsSet(codegen::ShowASM)) {
    245         WriteAssembly(builder.selectTarget(), m);
    246     }
    247 #endif
    248     ExecutionEngine * engine = builder.create();
    249     if (engine == nullptr) {
    250         throw std::runtime_error("Could not create ExecutionEngine: " + errMessage);
    251     }
    252     return engine;
    253 }
    254 
    255 void ApplyObjectCache(ExecutionEngine * e) {
    256     ParabixObjectCache * cache = nullptr;
    257     if (codegen::EnableObjectCache) {
    258         if (codegen::ObjectCacheDir.empty())
    259             // Default is $HOME/.cache/icgrep
    260             cache = new ParabixObjectCache();
    261         else
    262             cache = new ParabixObjectCache(codegen::ObjectCacheDir);
    263         e->setObjectCache(cache);
    264     }
    265 }
    266 
    267 void generatePipeline(IDISA::IDISA_Builder * iBuilder, const std::vector<kernel::KernelBuilder *> & kernels) {
    268     if (codegen::pipelineParallel) {
    269         generateParallelPipeline(iBuilder, kernels);
    270     } else if (codegen::segmentPipelineParallel) {
    271         generateSegmentParallelPipeline(iBuilder, kernels);
    272     } else {
    273         codegen::ThreadNum = 1;
    274         generatePipelineLoop(iBuilder, kernels);
    275     }
    276 }
    277 
    278 ParabixDriver::ParabixDriver(IDISA::IDISA_Builder * iBuilder)
    279 : iBuilder(iBuilder)
    280 , mMainModule(iBuilder->getModule())
    281 , mTarget(nullptr)
    282 , mEngine(nullptr)
    283 {
    284     InitializeNativeTarget();
    285     InitializeNativeTargetAsmPrinter();
    286     InitializeNativeTargetAsmParser();
    287 
    288     PassRegistry * Registry = PassRegistry::getPassRegistry();
    289     initializeCore(*Registry);
    290     initializeCodeGen(*Registry);
    291     initializeLowerIntrinsicsPass(*Registry);
    292 
    293     std::string errMessage;
    294     EngineBuilder builder{std::unique_ptr<Module>(mMainModule)};
    295     builder.setErrorStr(&errMessage);
    296     TargetOptions opts = InitTargetOptionsFromCodeGenFlags();
    297     opts.MCOptions.AsmVerbose = codegen::AsmVerbose;
    298 
    299     builder.setTargetOptions(opts);
    300     builder.setVerifyModules(true);
    301     CodeGenOpt::Level optLevel = CodeGenOpt::Level::None;
    302     switch (codegen::OptLevel) {
    303         case '0': optLevel = CodeGenOpt::None; break;
    304         case '1': optLevel = CodeGenOpt::Less; break;
    305         case '2': optLevel = CodeGenOpt::Default; break;
    306         case '3': optLevel = CodeGenOpt::Aggressive; break;
    307         default: errs() << codegen::OptLevel << " is an invalid optimization level.\n";
    308     }
    309     builder.setOptLevel(optLevel);
    310 
    311     setAllFeatures(builder);
    312 
    313197    mEngine = builder.create();
    314198    if (mEngine == nullptr) {
     
    316200    }
    317201    mTarget = builder.selectTarget();
    318     if (codegen::EnableObjectCache) {
     202    if (LLVM_LIKELY(codegen::EnableObjectCache && codegen::DebugOptions.getBits() == 0)) {
    319203        if (codegen::ObjectCacheDir.empty()) {
    320204            mCache = llvm::make_unique<ParabixObjectCache>();
     
    327211}
    328212
    329 void ParabixDriver::JITcompileMain () {
    330     // Use the pass manager to optimize the function.
    331     #ifndef NDEBUG
    332     try {
    333     #endif
    334     legacy::PassManager PM;
    335     #ifndef NDEBUG
    336     PM.add(createVerifierPass());
    337     #endif
    338     PM.add(createReassociatePass());             //Reassociate expressions.
    339     PM.add(createGVNPass());                     //Eliminate common subexpressions.
    340     PM.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
    341     PM.add(createCFGSimplificationPass());   
    342     PM.run(*mMainModule);
    343     #ifndef NDEBUG
    344     } catch (...) { mMainModule->dump(); throw; }
    345     #endif
    346 
    347     if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowIR))) {
    348         if (codegen::IROutputFilename.empty()) {
    349             mMainModule->dump();
    350         } else {
    351             std::error_code error;
    352             raw_fd_ostream out(codegen::IROutputFilename, error, sys::fs::OpenFlags::F_None);
    353             mMainModule->print(out, nullptr);
    354         }
    355     }
    356     #if LLVM_VERSION_MINOR > 6
    357     if (codegen::DebugOptionIsSet(codegen::ShowASM)) {
    358         WriteAssembly(mTarget, mMainModule);
    359     }
    360     #endif
    361 }
    362 
    363213void ParabixDriver::addKernelCall(kernel::KernelBuilder & kb, const std::vector<parabix::StreamSetBuffer *> & inputs, const std::vector<parabix::StreamSetBuffer *> & outputs) {
    364214    assert (mModuleMap.count(&kb) == 0);
    365215    mKernelList.push_back(&kb);
    366     mModuleMap.emplace(&kb, std::move(kb.createKernelStub(inputs, outputs)));
     216    mModuleMap.emplace(&kb, kb.createKernelStub(inputs, outputs));
    367217}
    368218
     
    384234    const auto f = mModuleMap.find(&kb);
    385235    assert ("addKernelCall(kb, ...) must be called before addExternalLink(kb, ...)" && f != mModuleMap.end());
    386     llvm::Module * const m = f->second.get();
    387     mEngine->addGlobalMapping(cast<Function>(m->getOrInsertFunction(name, type)), functionPtr);
     236    mEngine->addGlobalMapping(cast<Function>(f->second->getOrInsertFunction(name, type)), functionPtr);
    388237}
    389238
    390239void ParabixDriver::linkAndFinalize() {
    391     for (kernel::KernelBuilder * kb : mKernelList) {
    392         const auto f = mModuleMap.find(kb);
    393         if (LLVM_UNLIKELY(f == mModuleMap.end())) {
    394             report_fatal_error("linkAndFinalize was called twice!");
    395         }
    396         std::unique_ptr<Module> km(std::move(f->second));
     240    Module * m = mMainModule;
     241    #ifndef NDEBUG
     242    try {
     243    #endif
     244    legacy::PassManager PM;
     245    #ifndef NDEBUG
     246    PM.add(createVerifierPass());
     247    #endif
     248    PM.add(createReassociatePass());             //Reassociate expressions.
     249    PM.add(createGVNPass());                     //Eliminate common subexpressions.
     250    PM.add(createInstructionCombiningPass());    //Simple peephole optimizations and bit-twiddling.
     251    PM.add(createCFGSimplificationPass());
     252
     253    raw_fd_ostream * IROutputStream = nullptr;
     254    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowIR))) {
     255        if (codegen::IROutputFilename.empty()) {
     256            IROutputStream = new raw_fd_ostream(STDERR_FILENO, false, false);
     257        } else {
     258            std::error_code error;
     259            IROutputStream = new raw_fd_ostream(codegen::IROutputFilename, error, sys::fs::OpenFlags::F_None);
     260        }
     261        PM.add(createPrintModulePass(*IROutputStream));
     262    }
     263
     264    #ifndef USE_LLVM_3_6
     265    raw_fd_ostream * ASMOutputStream = nullptr;
     266    if (LLVM_UNLIKELY(codegen::DebugOptionIsSet(codegen::ShowASM))) {
     267        if (codegen::ASMOutputFilename.empty()) {
     268            ASMOutputStream = new raw_fd_ostream(STDERR_FILENO, false, false);
     269        } else {
     270            std::error_code error;
     271            ASMOutputStream = new raw_fd_ostream(codegen::ASMOutputFilename, error, sys::fs::OpenFlags::F_None);
     272        }
     273        if (LLVM_UNLIKELY(mTarget->addPassesToEmitFile(PM, *ASMOutputStream, TargetMachine::CGFT_AssemblyFile))) {
     274            report_fatal_error("LLVM error: could not add emit assembly pass");
     275        }
     276    }
     277    #endif
     278
     279    PM.run(*m);
     280    for (auto pair : mModuleMap) {
     281        kernel::KernelBuilder * const kb = std::get<0>(pair);
     282        m = std::get<1>(pair);
    397283        bool uncachedObject = true;
    398284        if (mCache) {
    399             std::string moduleID = km->getModuleIdentifier();
    400             std::string signature;
    401             if (kb->moduleIDisSignature()) {
    402                 signature = moduleID;
    403             } else {
    404                 kb->generateKernelSignature(signature);
    405             }
     285            const std::string moduleID = m->getModuleIdentifier();
     286            const std::string signature = kb->generateKernelSignature(moduleID);
    406287            if (mCache->loadCachedObjectFile(moduleID, signature)) {
    407288                uncachedObject = false;
     
    409290        }
    410291        if (uncachedObject) {
    411             Module * const saveM = iBuilder->getModule();
    412             iBuilder->setModule(km.get());
     292            Module * const cm = iBuilder->getModule();
     293            iBuilder->setModule(m);
    413294            kb->generateKernel();
    414             iBuilder->setModule(saveM);
     295            PM.run(*m);
     296            iBuilder->setModule(cm);
    415297        }       
    416         mEngine->addModule(std::move(km));
    417     }
     298        mEngine->addModule(std::unique_ptr<Module>(m));
     299    }   
    418300    mEngine->finalizeObject();
     301
     302    delete IROutputStream;
     303    #ifndef USE_LLVM_3_6
     304    delete ASMOutputStream;
     305    #endif
     306    #ifndef NDEBUG
     307    } catch (...) { m->dump(); throw; }
     308    #endif
    419309    mModuleMap.clear();
    420310}
Note: See TracChangeset for help on using the changeset viewer.