Example #1
0
void* MCJITHelper::identityGeneratorForOpenOSR(Function* F1, Instruction* OSRSrc, void* extra, void* profDataAddr) {
    MCJITHelper* TheHelper = (MCJITHelper*) extra;
    bool verbose = TheHelper->verbose;

    assert(OSRSrc->getParent()->getParent() == F1 && "MCJIT messed up the objects");

    if (verbose) {
        std::cerr << "Value for F1 is " << F1 << std::endl;
        std::cerr << "Value for OSRSrc is " << OSRSrc << std::endl;
        std::cerr << "Value for extra is " << extra << std::endl;
        std::cerr << "Value for profDataAddr is " << profDataAddr << std::endl;
    }

    std::pair<Function*, StateMap*> identityPair = StateMap::generateIdentityMapping(F1);

    Function* F2 = identityPair.first;
    StateMap* M = identityPair.second;

    Instruction* OSRSrcInF2 = cast<Instruction>(M->getCorrespondingOneToOneValue(OSRSrc));
    if (OSRLibrary::removeOSRPoint(*OSRSrcInF2) && verbose) {
        std::cerr << "OSR point removed after cloning F1" << std::endl;
    }

    Instruction* LPad = M->getLandingPad(OSRSrc);

    LivenessAnalysis LA(F1);
    std::vector<Value*>* valuesToPass = OSRLibrary::getLiveValsVecAtInstr(OSRSrc, LA);
    std::string OSRDestFunName = (F2->getName().str()).append("OSRCont");
    Function* OSRDestFun = OSRLibrary::genContinuationFunc(TheHelper->Context,
            *F1, *F2, *OSRSrc, *LPad, *valuesToPass, *M, &OSRDestFunName, verbose);
    delete valuesToPass;
    delete F2;
    delete M;

    // put the generated code into a module
    std::string modForJITName = "OpenOSRClone";
    modForJITName.append(OSRDestFunName);
    std::unique_ptr<Module> modForJIT = llvm::make_unique<Module>(modForJITName, TheHelper->Context);
    Module* modForJIT_ptr = modForJIT.get();
    modForJIT_ptr->getFunctionList().push_back(OSRDestFun);
    verifyFunction(*OSRDestFun, &outs());

    // remove dead code
    FunctionPassManager FPM(modForJIT_ptr);
    FPM.add(createCFGSimplificationPass());
    FPM.doInitialization();
    FPM.run(*OSRDestFun);

    // compile code
    TheHelper->addModule(std::move(modForJIT));
    return (void*)TheHelper->JIT->getFunctionAddress(OSRDestFunName);
}
Example #2
0
void* MCJITHelper::dynamicInlinerForOpenOSR(Function* F1, Instruction* OSRSrc, void* extra, void* profDataAddr) {
    DynamicInlinerInfo* inlineInfo = (DynamicInlinerInfo*) extra;
    MCJITHelper* TheHelper = inlineInfo->TheHelper;
    bool verbose = TheHelper->verbose;

    assert(OSRSrc->getParent()->getParent() == F1 && "MCJIT messed up the objects");

    if (verbose) {
        std::cerr << "Value for F1 is " << F1 << std::endl;
        std::cerr << "Value for OSRSrc is " << OSRSrc << std::endl;
        std::cerr << "Value for extra is " << extra << std::endl;
        std::cerr << "Value for profDataAddr is " << profDataAddr << std::endl;
    }

    std::pair<Function*, StateMap*> identityPair = StateMap::generateIdentityMapping(F1);

    Function* F2 = identityPair.first;
    StateMap* M = identityPair.second;

    Value* valToInlineInF2 = M->getCorrespondingOneToOneValue(inlineInfo->valToInline);

    Instruction* OSRSrcInF2 = cast<Instruction>(M->getCorrespondingOneToOneValue(OSRSrc));
    assert (OSRSrcInF2 != nullptr && "TODO cannot find corresponding OSRSrc in temporary F2");
    if (OSRLibrary::removeOSRPoint(*OSRSrcInF2) && verbose) {
        std::cerr << "OSR point removed after cloning F1" << std::endl;
    }

    Instruction* LPad = M->getLandingPad(OSRSrc);

    StateMap* M_F2toOSRContFun;
    LivenessAnalysis LA(F1);
    std::vector<Value*>* valuesToPass = OSRLibrary::getLiveValsVecAtInstr(OSRSrc, LA);
    std::string OSRDestFunName = (F2->getName().str()).append("OSRCont");
    Function* OSRContFun = OSRLibrary::genContinuationFunc(TheHelper->Context,
            *F1, *F2, *OSRSrc, *LPad, *valuesToPass, *M, &OSRDestFunName, verbose, &M_F2toOSRContFun);

    Value* valToInline = M_F2toOSRContFun->getCorrespondingOneToOneValue(valToInlineInF2);
    assert (valToInline != nullptr && "broken state map for continuation function");

    delete valuesToPass;
    delete F2;
    delete M;
    delete M_F2toOSRContFun;

    // create a module for generated code
    std::string modForJITName = "OpenOSRDynInline";
    modForJITName.append(OSRDestFunName);
    std::unique_ptr<Module> modForJIT = llvm::make_unique<Module>(modForJITName, TheHelper->Context);
    Module* modForJIT_ptr = modForJIT.get();

    // determine which function is called
    uint64_t calledFun = (uint64_t)profDataAddr;

    std::cerr << "Address of invoked function: " << calledFun << std::endl;
    Function* funToInline = nullptr;
    for (AddrSymPair &pair: TheHelper->CompiledFunAddrTable) {
        if (pair.first == calledFun) {
            std::string &FunName = pair.second;
            funToInline = TheHelper->getFunction(FunName);
            break;
        }
    }

    Function* myFunToInline = nullptr;
    if (funToInline == nullptr) {
        std::cerr << "Sorry, I could not determine which function was called!" << std::endl;
    } else {
        std::cerr << "Function being inlined: " << funToInline->getName().str() << std::endl;
        ValueToValueMapTy VMap;
        myFunToInline = CloneFunction(funToInline, VMap, false, nullptr);
        myFunToInline->addFnAttr(Attribute::AlwaysInline);
        myFunToInline->setLinkage(Function::LinkageTypes::PrivateLinkage);
        modForJIT_ptr->getFunctionList().push_back(myFunToInline);
        OSRLibrary::fixUsesOfFunctionsAndGlobals(funToInline, myFunToInline);
        for (Value::use_iterator UI = valToInline->use_begin(),
                UE = valToInline->use_end(); UI != UE; ) {
            Use &U = *(UI++);
            if (CallInst* CI = dyn_cast<CallInst>(U.getUser())) {
                if (CI->getParent()->getParent() != OSRContFun) continue;
                if (verbose) {
                    raw_os_ostream errStream(std::cerr);
                    std::cerr << "Updating instruction ";
                    CI->print(errStream);
                    std::cerr << std::endl;
                }
                U.set(myFunToInline);
            }
        }
    }

    modForJIT_ptr->getFunctionList().push_back(OSRContFun);
    verifyFunction(*OSRContFun, &outs());

    // remove dead code & inline when possible
    FunctionPassManager FPM(modForJIT_ptr);
    FPM.add(createCFGSimplificationPass());
    FPM.doInitialization();
    FPM.run(*OSRContFun);

    if (funToInline != nullptr) {
        PassManager PM;
        PM.add(llvm::createAlwaysInlinerPass());
        PM.run(*modForJIT_ptr);
    }

    // compile code
    TheHelper->addModule(std::move(modForJIT));
    return (void*)TheHelper->JIT->getFunctionAddress(OSRDestFunName);
}