diff --git a/opts/ClassMethodInliner.cpp b/opts/ClassMethodInliner.cpp index 9741fb9..0806eb9 100644 --- a/opts/ClassMethodInliner.cpp +++ b/opts/ClassMethodInliner.cpp @@ -60,7 +60,7 @@ namespace for (BasicBlock::iterator b=i->begin(), last=i->end() ; b != last ; ++b) { CallSite call = CallSite::get(b); - if (call.getInstruction()) { + if (call.getInstruction() && !call.getCalledFunction()) { MDNode *messageType = call->getMetadata(MessageSendMDKind); if (0 == messageType) { continue; } messages.push_back(call); @@ -97,7 +97,7 @@ namespace char ClassMethodInliner::ID = 0; RegisterPass X("gnu-class-method-inline", - "Inline class methods"); + "Inline class methods and message sends to super"); } ModulePass *createClassMethodInliner(void) diff --git a/opts/IMPCacher.cpp b/opts/IMPCacher.cpp index 9d3dec0..352ebb9 100644 --- a/opts/IMPCacher.cpp +++ b/opts/IMPCacher.cpp @@ -158,7 +158,12 @@ void GNUstep::IMPCacher::SpeculativelyInline(Instruction *call, Function } } if (FTy->getReturnType() != calleeTy->getReturnType()) { - inlineResult = new BitCastInst(inlineCall, calleeTy->getReturnType(), "", inlineBB); + if (FTy->getReturnType() == Type::getVoidTy(Context)) { + inlineResult = Constant::getNullValue(calleeTy->getReturnType()); + } else { + inlineResult = + new BitCastInst(inlineCall, calleeTy->getReturnType(), "", inlineBB); + } } } diff --git a/opts/TypeFeedback.cpp b/opts/TypeFeedback.cpp index bc958e4..4638b41 100644 --- a/opts/TypeFeedback.cpp +++ b/opts/TypeFeedback.cpp @@ -3,6 +3,7 @@ #include "llvm/Module.h" #include "llvm/Function.h" #include "llvm/Instructions.h" +#include "llvm/Support/CallSite.h" #include "llvm/Support/IRBuilder.h" #include "llvm/Linker.h" #include @@ -23,37 +24,23 @@ namespace { for (Function::iterator i=F.begin(), e=F.end() ; i != e ; ++i) { + Module *M = F.getParent(); replacementVector replacements; for (BasicBlock::iterator b=i->begin(), last=i->end() ; b != last ; ++b) { - Module *M = F.getParent(); - if (CallInst *call = dyn_cast(b)) { - if (Function *callee = call->getCalledFunction()) { - if (callee->getName() == "objc_msg_lookup_sender") { - - llvm::Value *args[] = { call->getOperand(1), - call->getOperand(2), call->getOperand(3), - ModuleID, ConstantInt::get(Int32Ty, - callsiteCount++) }; - Function *profile = cast( - M->getOrInsertFunction("objc_msg_lookup_profile", - callee->getFunctionType()->getReturnType(), - args[0]->getType(), args[1]->getType(), - args[2]->getType(), - ModuleID->getType(), Int32Ty, NULL)); - llvm::CallInst *profileCall = - CallInst::Create(profile, args, args+5, "", call); - replacements.push_back(callPair(call, profileCall)); - } - } + CallSite call = CallSite::get(b); + if (call.getInstruction() && !call.getCalledFunction()) { + llvm::Value *args[] = { call->getOperand(1), call->getOperand(0), + ModuleID, ConstantInt::get(Int32Ty, callsiteCount++) }; + Constant *profile = + M->getOrInsertFunction("objc_msg_profile", + Type::getVoidTy(M->getContext()), + args[0]->getType(), args[1]->getType(), + args[2]->getType(), args[3]->getType(), NULL); + CallInst::Create(profile, args, args+4, "", call.getInstruction()); } } - for (replacementVector::iterator r=replacements.begin(), - e=replacements.end() ; e!=r ; r++) { - r->first->replaceAllUsesWith(r->second); - r->second->getParent()->getInstList().erase(r->first); - } } } diff --git a/opts/TypeFeedbackDrivenInliner.cpp b/opts/TypeFeedbackDrivenInliner.cpp index 5ed8ac6..83fda80 100644 --- a/opts/TypeFeedbackDrivenInliner.cpp +++ b/opts/TypeFeedbackDrivenInliner.cpp @@ -4,10 +4,14 @@ #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Support/IRBuilder.h" +#include "llvm/Analysis/InlineCost.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Linker.h" #include +#include "TypeInfoProvider.h" using namespace llvm; +using namespace GNUstep; namespace { struct GNUObjCTypeFeedbackDrivenInliner : public ModulePass { @@ -17,127 +21,65 @@ namespace { static char ID; uint32_t callsiteCount; const IntegerType *Int32Ty; - GNUObjCTypeFeedbackDrivenInliner() : ModulePass(&ID), callsiteCount(0) {} - - void profileFunction(Function &F, Constant *ModuleID) { - for (Function::iterator i=F.begin(), e=F.end() ; - i != e ; ++i) { - - replacementVector replacements; - for (BasicBlock::iterator b=i->begin(), last=i->end() ; - b != last ; ++b) { - - Module *M = F.getParent(); - if (CallInst *call = dyn_cast(b)) { - if (Function *callee = call->getCalledFunction()) { - if (callee->getName() == "objc_msg_lookup_sender") { - llvm::Value *args[] = { call->getOperand(1), - call->getOperand(2), call->getOperand(3), - ModuleID, ConstantInt::get(Int32Ty, - callsiteCount++) }; - Function *profile = cast( - M->getOrInsertFunction("objc_msg_lookup_profile", - callee->getFunctionType()->getReturnType(), - args[0]->getType(), args[1]->getType(), - args[2]->getType(), - ModuleID->getType(), Int32Ty, NULL)); - llvm::CallInst *profileCall = - CallInst::Create(profile, args, args+5, "", call); - replacements.push_back(callPair(call, profileCall)); - } - } - } - } - for (replacementVector::iterator r=replacements.begin(), - e=replacements.end() ; e!=r ; r++) { - r->first->replaceAllUsesWith(r->second); - r->second->getParent()->getInstList().erase(r->first); - } - } - } + public: + + GNUObjCTypeFeedbackDrivenInliner() : ModulePass(&ID), callsiteCount(0) {} + virtual bool runOnModule(Module &M) { + bool modified = false; LLVMContext &VMContext = M.getContext(); Int32Ty = IntegerType::get(VMContext, 32); - const PointerType *PtrTy = Type::getInt8PtrTy(VMContext); - Constant *moduleName = - ConstantArray::get(VMContext, M.getModuleIdentifier(), true); - moduleName = new GlobalVariable(M, moduleName->getType(), true, - GlobalValue::InternalLinkage, moduleName, - ".objc_profile_module_name"); - std::vector functions; - - llvm::Constant *Zeros[2]; - Zeros[0] = ConstantInt::get(Type::getInt32Ty(VMContext), 0); - Zeros[1] = Zeros[0]; - - moduleName = ConstantExpr::getGetElementPtr(moduleName, Zeros, 2); - functions.push_back(moduleName);; - functions.push_back(moduleName);; - - for (Module::iterator F=M.begin(), e=M.end() ; - F != e ; ++F) { - if (F->isDeclaration()) { continue; } - functions.push_back(ConstantExpr::getBitCast(F, PtrTy)); + TypeInfoProvider::CallSiteMap *SiteMap = + TypeInfoProvider::SharedTypeInfoProvider()->getCallSitesForModule(M); + SmallPtrSet NeverInline; - Constant * ConstStr = - llvm::ConstantArray::get(VMContext, F->getName()); - ConstStr = new GlobalVariable(M, ConstStr->getType(), true, - GlobalValue::PrivateLinkage, ConstStr, "str"); - functions.push_back( - ConstantExpr::getGetElementPtr(ConstStr, Zeros, 2)); + //TypeInfoProvider::SharedTypeInfoProvider()->PrintStatistics(); + GNUstep::IMPCacher cacher = GNUstep::IMPCacher(M.getContext(), this); + InlineCostAnalyzer CA; + SmallVector messages; - profileFunction(*F, moduleName); - } - functions.push_back(ConstantPointerNull::get(PtrTy)); - Constant *symtab = ConstantArray::get(ArrayType::get(PtrTy, - functions.size()), functions); - Value *symbolTable = new GlobalVariable(M, symtab->getType(), true, - GlobalValue::InternalLinkage, symtab, "symtab"); - - Function *init = - Function::Create(FunctionType::get(Type::getVoidTy(VMContext), false), - GlobalValue::PrivateLinkage, "load_symbol_table", &M); - BasicBlock * EntryBB = BasicBlock::Create(VMContext, "entry", init); - IRBuilder<> B = IRBuilder<>(EntryBB); - Value *syms = B.CreateStructGEP(symbolTable, 0); - B.CreateCall(M.getOrInsertFunction("objc_profile_write_symbols", - Type::getVoidTy(VMContext), syms->getType(), NULL), - syms); - B.CreateRetVoid(); - - GlobalVariable *GCL = M.getGlobalVariable("llvm.global_ctors"); - - std::vector ctors; - - ConstantArray *CA = cast(GCL->getInitializer()); - - for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) { - ctors.push_back(cast(*i)); + for (Module::iterator F=M.begin(), fend=M.end() ; + F != fend ; ++F) { + + + if (F->isDeclaration()) { continue; } + + for (Function::iterator i=F->begin(), end=F->end() ; + i != end ; ++i) { + for (BasicBlock::iterator b=i->begin(), last=i->end() ; + b != last ; ++b) { + CallSite call = CallSite::get(b); + if (call.getInstruction() && !call.getCalledFunction()) { + messages.push_back(call); + } + } + } } + TypeInfoProvider::CallSiteMap::iterator Entry = SiteMap->begin(); - // Type of one ctor - const Type *ctorTy = - cast(GCL->getType()->getElementType())->getElementType(); - // Add the - std::vector CSVals; - CSVals.push_back(ConstantInt::get(Type::getInt32Ty(VMContext),65535)); - CSVals.push_back(init); - ctors.push_back(ConstantStruct::get(GCL->getContext(), CSVals, false)); - // Create the array initializer. - CA = cast(ConstantArray::get(ArrayType::get(ctorTy, - ctors.size()), ctors)); - // Create the new global and replace the old one - GlobalVariable *NGV = new GlobalVariable(CA->getType(), - GCL->isConstant(), GCL->getLinkage(), CA, "", GCL->isThreadLocal()); - GCL->getParent()->getGlobalList().insert(GCL, NGV); - NGV->takeName(GCL); - GCL->replaceAllUsesWith(NGV); - GCL->eraseFromParent(); - - return true; + for (SmallVectorImpl::iterator i=messages.begin(), + e=messages.end() ; e!=i ; ++i, ++Entry) { + + if (Entry->size() == 1) { + + TypeInfoProvider::CallSiteEntry::iterator iterator = Entry->begin(); + Function *method = M.getFunction(Entry->begin()->getKey()); + if (0 == method || method->isDeclaration()) { continue; } + + InlineCost IC = CA.getInlineCost((*i), method, NeverInline); + // FIXME: 200 is a random number. Pick a better one! + if (IC.isAlways() || (IC.isVariable() && IC.getValue() < 200)) { + cacher.SpeculativelyInline((*i).getInstruction(), method); + modified = true; + } + } + // FIXME: Inline the most popular call if one is much more popular + // than the others. + } + return modified; } };