Esempio n. 1
0
bool InlineMalloc::runOnFunction(Function& F) {
  Function* Malloc = F.getParent()->getFunction("gcmalloc");
  if (!Malloc || Malloc->isDeclaration()) return false;
  bool Changed = false;
  for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; BI++) { 
    BasicBlock *Cur = BI; 
    for (BasicBlock::iterator II = Cur->begin(), IE = Cur->end(); II != IE;) {
      Instruction *I = II;
      II++;
      CallSite Call = CallSite::get(I);
      Instruction* CI = Call.getInstruction();
      if (CI) {
        Function* Temp = Call.getCalledFunction();
        if (Temp == Malloc) {
          if (dyn_cast<Constant>(Call.getArgument(0))) {
            InlineFunctionInfo IFI(NULL, mvm::MvmModule::TheTargetData);
            Changed |= InlineFunction(Call, IFI);
            break;
          }
        }
      }
    }
  }
  return Changed;
}
Esempio n. 2
0
void inlineFunctionCalls(Function* f, TargetData* targetData) {
    //WFVOPENCL_DEBUG( outs() << "  inlining function calls... "; );
    bool functionChanged = true;
    while (functionChanged) {
        functionChanged = false;
        for (Function::iterator BB=f->begin(); BB!=f->end(); ++BB) {
            bool blockChanged = false;
            for (BasicBlock::iterator I=BB->begin(); !blockChanged && I!=BB->end();) {
                if (!isa<CallInst>(I)) { ++I; continue; }
                CallInst* call = cast<CallInst>(I++);
                Function* callee = call->getCalledFunction();
                if (!callee) {
                    //errs() << "ERROR: could not inline function call: " << *call;
                    continue;
                }
                if (callee->getAttributes().hasAttrSomewhere(Attribute::NoInline)) {
                    //WFVOPENCL_DEBUG( outs() << "    function '" << callee->getNameStr() << "' has attribute 'no inline', ignored call!\n"; );
                    continue;
                }

                const std::string calleeName = callee->getNameStr(); //possibly deleted by InlineFunction()

                InlineFunctionInfo IFI(NULL, targetData);
                blockChanged = InlineFunction(call, IFI);
                //WFVOPENCL_DEBUG(
                    //if (blockChanged) outs() << "  inlined call to function '" << calleeName << "'\n";
                    //else errs() << "  inlining of call to function '" << calleeName << "' FAILED!\n";
                //);
                functionChanged |= blockChanged;
            }
        }
    }
    //WFVOPENCL_DEBUG( outs() << "done.\n"; );
}
Esempio n. 3
0
void GNUstep::IMPCacher::SpeculativelyInline(Instruction *call, Function
        *function) {
    BasicBlock *beforeCallBB = call->getParent();
    BasicBlock *callBB = SplitBlock(beforeCallBB, call, Owner);
    BasicBlock *inlineBB = BasicBlock::Create(Context, "inline",
                           callBB->getParent());


    BasicBlock::iterator iter = call;
    iter++;

    BasicBlock *afterCallBB = SplitBlock(iter->getParent(), iter, Owner);

    removeTerminator(beforeCallBB);

    // Put a branch before the call, testing whether the callee really is the
    // function
    IRBuilder<> B = IRBuilder<>(beforeCallBB);
    Value *callee = isa<CallInst>(call) ? cast<CallInst>(call)->getCalledValue()
                    : cast<InvokeInst>(call)->getCalledValue();

    const FunctionType *FTy = function->getFunctionType();
    const FunctionType *calleeTy = cast<FunctionType>(
                                       cast<PointerType>(callee->getType())->getElementType());
    if (calleeTy != FTy) {
        callee = B.CreateBitCast(callee, function->getType());
    }

    Value *isInlineValid = B.CreateICmpEQ(callee, function);
    B.CreateCondBr(isInlineValid, inlineBB, callBB);

    // In the inline BB, add a copy of the call, but this time calling the real
    // version.
    Instruction *inlineCall = call->clone();
    Value *inlineResult= inlineCall;
    inlineBB->getInstList().push_back(inlineCall);

    B.SetInsertPoint(inlineBB);

    if (calleeTy != FTy) {
        for (unsigned i=0 ; i<FTy->getNumParams() ; i++) {
            LLVMType *callType = calleeTy->getParamType(i);
            LLVMType *argType = FTy->getParamType(i);
            if (callType != argType) {
                inlineCall->setOperand(i, new
                                       BitCastInst(inlineCall->getOperand(i), argType, "", inlineCall));
            }
        }
        if (FTy->getReturnType() != calleeTy->getReturnType()) {
            if (FTy->getReturnType() == Type::getVoidTy(Context)) {
                inlineResult = Constant::getNullValue(calleeTy->getReturnType());
            } else {
                inlineResult =
                    new BitCastInst(inlineCall, calleeTy->getReturnType(), "", inlineBB);
            }
        }
    }

    B.CreateBr(afterCallBB);

    // Unify the return values
    if (call->getType() != Type::getVoidTy(Context)) {
        PHINode *phi = CreatePHI(call->getType(), 2, "", afterCallBB->begin());
        call->replaceAllUsesWith(phi);
        phi->addIncoming(call, callBB);
        phi->addIncoming(inlineResult, inlineBB);
    }

    // Really do the real inlining
    InlineFunctionInfo IFI(0, 0);
    if (CallInst *c = dyn_cast<CallInst>(inlineCall)) {
        c->setCalledFunction(function);
        InlineFunction(c, IFI);
    } else if (InvokeInst *c = dyn_cast<InvokeInst>(inlineCall)) {
        c->setCalledFunction(function);
        InlineFunction(c, IFI);
    }
}
Esempio n. 4
0
Function* generateFunctionWrapperWithParams(const std::string& wrapper_name, Function* f, Module* mod, std::vector<const Type*>& additionalParams, const bool inlineCall) {
    assert (f && mod);
    assert (f->getParent());

    if (f->getParent() != mod) {
        errs() << "WARNING: generateFunctionWrapper(): module '"
                << mod->getModuleIdentifier()
                << "' is not the parent of function '"
                << f->getNameStr() << "' (parent: '"
                << f->getParent()->getModuleIdentifier() << "')!\n";
    }

    // first make sure there is no function with that name in mod
    // TODO: Implement logic from LLVM tutorial that checks for matching extern
    //       declaration without body and, in this case, goes on.
    if (mod->getFunction(wrapper_name)) {
        errs() << "ERROR: generateFunctionWrapper(): Function with name '"
                << wrapper_name << "' already exists in module '"
                << mod->getModuleIdentifier() << "'!\n";
        return NULL;
    }

    // warn if f has a return value
    if (!f->getReturnType()->isVoidTy()) {
        errs() << "WARNING: generateFunctionWrapper(): target function '"
                << f->getNameStr() << "' must not have a return type (ignored)!\n";
    }

    LLVMContext& context = mod->getContext();

    IRBuilder<> builder(context);

    // determine all arguments of f
    std::vector<const Argument*> oldArgs;
    std::vector<const Type*> oldArgTypes;
    for (Function::const_arg_iterator A=f->arg_begin(), AE=f->arg_end(); A!=AE; ++A) {
        oldArgs.push_back(A);
        oldArgTypes.push_back(A->getType());
    }

    // create a struct type with a member for each argument
    const StructType* argStructType = StructType::get(context, oldArgTypes, false);


    // create function
    //const FunctionType* fType = TypeBuilder<void(void*), true>::get(context);
    std::vector<const Type*> params;
    params.push_back(PointerType::getUnqual(argStructType));

    for (std::vector<const Type*>::const_iterator it=additionalParams.begin(), E=additionalParams.end(); it!=E; ++it) {
        params.push_back(*it);
    }

    const FunctionType* fType = FunctionType::get(Type::getVoidTy(context), params, false);
    Function* wrapper = Function::Create(fType, Function::ExternalLinkage, wrapper_name, mod);

    // set name of argument
    Argument* arg_str = wrapper->arg_begin();
    arg_str->setName("arg_struct");

    // create entry block
    BasicBlock* entryBB = BasicBlock::Create(context, "entry", wrapper);
    builder.SetInsertPoint(entryBB);

    // create extractions of arguments out of the struct
    SmallVector<Value*, 8> extractedArgs;
    for (unsigned i=0, e=oldArgTypes.size(); i<e; ++i) {
        // create GEP
        std::vector<Value*> indices;
        indices.push_back(Constant::getNullValue(Type::getInt32Ty(context))); // step through pointer
        indices.push_back(ConstantInt::get(context, APInt(32, i))); // index of argument
        Value* gep = builder.CreateGEP(arg_str, indices.begin(), indices.end(), "");

        // create load
        LoadInst* load = builder.CreateLoad(gep, false, "");

        // store as argument for call to f
        extractedArgs.push_back(load);
    }

    // create the call to f
    CallInst* call = builder.CreateCall(f, extractedArgs.begin(), extractedArgs.end(), "");

    // the function returns void
    builder.CreateRetVoid();


    //wrapper->addAttribute(0, Attribute::NoUnwind); // function does not unwind stack -> why is there an index required ???
    wrapper->setDoesNotCapture(1, true); // arg ptr does not capture
    wrapper->setDoesNotAlias(1, true);   // arg ptr does not alias

    // inline call if required
    if (inlineCall) {
        InlineFunctionInfo IFI(NULL, new TargetData(mod));
        const bool success = InlineFunction(call, IFI);
        if (!success) {
            errs() << "WARNING: could not inline function call inside wrapper: " << *call << "\n";
        }
        assert (success);
    }

    //verifyFunction(*wrapper, NULL);

    return wrapper;
}
Esempio n. 5
0
/// inlineFuctions - Walk all call sites in all functions supplied by
/// client. Inline as many call sites as possible. Delete completely
/// inlined functions.
void BasicInlinerImpl::inlineFunctions() {

    // Scan through and identify all call sites ahead of time so that we only
    // inline call sites in the original functions, not call sites that result
    // from inlining other functions.
    std::vector<CallSite> CallSites;

    for (std::vector<Function *>::iterator FI = Functions.begin(),
            FE = Functions.end(); FI != FE; ++FI) {
        Function *F = *FI;
        for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
            for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
                CallSite CS(cast<Value>(I));
                if (CS && CS.getCalledFunction()
                        && !CS.getCalledFunction()->isDeclaration())
                    CallSites.push_back(CS);
            }
    }

    DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n");

    // Inline call sites.
    bool Changed = false;
    do {
        Changed = false;
        for (unsigned index = 0; index != CallSites.size() && !CallSites.empty();
                ++index) {
            CallSite CS = CallSites[index];
            if (Function *Callee = CS.getCalledFunction()) {

                // Eliminate calls that are never inlinable.
                if (Callee->isDeclaration() ||
                        CS.getInstruction()->getParent()->getParent() == Callee) {
                    CallSites.erase(CallSites.begin() + index);
                    --index;
                    continue;
                }
                InlineCost IC = CA.getInlineCost(CS, NeverInline);
                if (IC.isAlways()) {
                    DEBUG(dbgs() << "  Inlining: cost=always"
                          <<", call: " << *CS.getInstruction());
                } else if (IC.isNever()) {
                    DEBUG(dbgs() << "  NOT Inlining: cost=never"
                          <<", call: " << *CS.getInstruction());
                    continue;
                } else {
                    int Cost = IC.getValue();

                    if (Cost >= (int) BasicInlineThreshold) {
                        DEBUG(dbgs() << "  NOT Inlining: cost = " << Cost
                              << ", call: " <<  *CS.getInstruction());
                        continue;
                    } else {
                        DEBUG(dbgs() << "  Inlining: cost = " << Cost
                              << ", call: " <<  *CS.getInstruction());
                    }
                }

                // Inline
                InlineFunctionInfo IFI(0, TD);
                if (InlineFunction(CS, IFI)) {
                    Callee->removeDeadConstantUsers();
                    if (Callee->isDefTriviallyDead())
                        DeadFunctions.insert(Callee);
                    Changed = true;
                    CallSites.erase(CallSites.begin() + index);
                    --index;
                }
            }
        }
    } while (Changed);

    // Remove completely inlined functions from module.
    for(SmallPtrSet<Function *, 8>::iterator I = DeadFunctions.begin(),
            E = DeadFunctions.end(); I != E; ++I) {
        Function *D = *I;
        Module *M = D->getParent();
        M->getFunctionList().remove(D);
    }
}