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; }
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"; ); }
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); } }
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; }
/// 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); } }