From 9d5452b147a3bd0361c439b0832b49f2c7f4a657 Mon Sep 17 00:00:00 2001 From: theraven Date: Fri, 22 Apr 2011 11:06:33 +0000 Subject: [PATCH] Fixed LLVM passes to compile with recent LLVM. Made class caching pass cache classes in a static variable if the original class is not available. --- opts/ClassIMPCache.cpp | 4 +- opts/ClassLookupCache.cpp | 97 ++++++++++++++++++++++++++---- opts/ClassMethodInliner.cpp | 4 +- opts/IMPCacher.cpp | 2 +- opts/IvarPass.cpp | 8 ++- opts/LoopIMPCachePass.cpp | 2 +- opts/TypeFeedback.cpp | 4 +- opts/TypeFeedbackDrivenInliner.cpp | 4 +- 8 files changed, 99 insertions(+), 26 deletions(-) diff --git a/opts/ClassIMPCache.cpp b/opts/ClassIMPCache.cpp index bb9807c..f0beb45 100644 --- a/opts/ClassIMPCache.cpp +++ b/opts/ClassIMPCache.cpp @@ -22,7 +22,7 @@ namespace public: static char ID; - ClassIMPCachePass() : ModulePass((intptr_t)&ID) {} + ClassIMPCachePass() : ModulePass(ID) {} virtual bool runOnModule(Module &M) { GNUstep::IMPCacher cacher = GNUstep::IMPCacher(M.getContext(), this); @@ -44,7 +44,7 @@ namespace i != end ; ++i) { for (BasicBlock::iterator b=i->begin(), last=i->end() ; b != last ; ++b) { - CallSite call = CallSite::get(b); + CallSite call(b); if (call.getInstruction()) { Value *callee = call.getCalledValue()->stripPointerCasts(); if (Function *func = dyn_cast(callee)) { diff --git a/opts/ClassLookupCache.cpp b/opts/ClassLookupCache.cpp index 5a3df1d..19ef41f 100644 --- a/opts/ClassLookupCache.cpp +++ b/opts/ClassLookupCache.cpp @@ -5,45 +5,53 @@ #include "llvm/Constants.h" #include "llvm/GlobalVariable.h" #include "llvm/Support/IRBuilder.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include +#include "IMPCacher.h" + using namespace llvm; +using namespace GNUstep; using std::string; using std::pair; namespace { - class ClassLookupCachePass : public FunctionPass - { + class ClassLookupCachePass : public ModulePass { + /// Module that we're currently optimising Module *M; + /// Static cache. If we're not using the non-fragile ABI, then we cache + /// all class lookups in static variables to avoid the overhead of the + /// lookup. With the non-fragile ABI, we don't need to do this. + llvm::StringMap statics; + typedef std::pair ClassLookup; public: static char ID; - ClassLookupCachePass() : FunctionPass((intptr_t)&ID) {} + ClassLookupCachePass() : ModulePass(ID) {} virtual bool doInitialization(Module &Mod) { M = &Mod; return false; } - virtual bool runOnFunction(Function &F) { + bool runOnFunction(Function &F) { bool modified = false; SmallVector Lookups; - BasicBlock *entry = &F.getEntryBlock(); for (Function::iterator i=F.begin(), end=F.end() ; i != end ; ++i) { for (BasicBlock::iterator b=i->begin(), last=i->end() ; b != last ; ++b) { if (CallInst *call = dyn_cast(b)) { - Value *callee = call->getCalledValue()->stripPointerCasts(); - if (Function *func = dyn_cast(callee)) { + if (Function *func = call->getCalledFunction()) { if (func->getName() == "objc_lookup_class") { ClassLookup lookup; GlobalVariable *classNameVar = dyn_cast( - call->getOperand(1)->stripPointerCasts()); + call->getOperand(0)->stripPointerCasts()); if (0 == classNameVar) { continue; } ConstantArray *init = dyn_cast( classNameVar->getInitializer()); @@ -57,18 +65,81 @@ namespace } } } - IRBuilder<> B = IRBuilder<>(entry); for (SmallVectorImpl::iterator i=Lookups.begin(), e=Lookups.end() ; e!=i ; i++) { + llvm::Instruction *lookup = i->first; + std::string &cls = i->second; + const llvm::Type *clsTy = lookup->getType(); Value *global = M->getGlobalVariable(("_OBJC_CLASS_" + i->second).c_str(), true); + global = 0; + // If we can see the class reference for this, then reference it + // directly. If not, then do the lookup and cache it. if (global) { - Value *cls = new BitCastInst(global, i->first->getType(), "class", i->first); - i->first->replaceAllUsesWith(cls); - i->first->removeFromParent(); + // Insert a bitcast of the class to the required type where the + // lookup is and then replace all references to the lookup with it. + Value *cls = new BitCastInst(global, clsTy, "class", lookup); + lookup->replaceAllUsesWith(cls); + lookup->removeFromParent(); + } else { + GlobalVariable *cache = statics[cls]; + if (!cache) { + cache = new GlobalVariable(*M, clsTy, false, + GlobalVariable::PrivateLinkage, Constant::getNullValue(clsTy), + ".class_cache"); + statics[cls] = cache; + } + BasicBlock *beforeLookupBB = lookup->getParent(); + BasicBlock *lookupBB = SplitBlock(beforeLookupBB, lookup, this); + BasicBlock::iterator iter = lookup; + iter++; + BasicBlock *afterLookupBB = SplitBlock(iter->getParent(), iter, this); + // SplitBlock() adds an unconditional branch, which we don't want. + // Remove it. + removeTerminator(beforeLookupBB); + removeTerminator(lookupBB); + + PHINode *phi = + PHINode::Create(clsTy, 2, cls, afterLookupBB->begin()); + // We replace all of the existing uses with the PHI node now, because + // we're going to add some more uses later that we don't want + // replaced. + lookup->replaceAllUsesWith(phi); + + // In the original basic block, we test whether the cache is NULL, + // and skip the lookup if it isn't. + IRBuilder<> B(beforeLookupBB); + llvm::Value *cachedClass = + B.CreateBitCast(B.CreateLoad(cache), clsTy); + llvm::Value *needsLookup = B.CreateIsNull(cachedClass); + B.CreateCondBr(needsLookup, lookupBB, afterLookupBB); + // In the lookup basic block, we just do the lookup, store it in the + // cache, and then jump to the continue block + B.SetInsertPoint(lookupBB); + B.CreateStore(lookup, cache); + B.CreateBr(afterLookupBB); + // Now we just need to set the PHI node to use the cache or the + // lookup result + phi->addIncoming(cachedClass, beforeLookupBB); + phi->addIncoming(lookup, lookupBB); } } return modified; } + virtual bool runOnModule(Module &Mod) { + statics.empty(); + M = &Mod; + bool modified; + + for (Module::iterator F=Mod.begin(), fend=Mod.end() ; + F != fend ; ++F) { + + if (F->isDeclaration()) { continue; } + + modified |= runOnFunction(*F); + } + + return modified; + }; }; char ClassLookupCachePass::ID = 0; @@ -76,7 +147,7 @@ namespace "Cache class lookups"); } -FunctionPass *createClassLookupCachePass(void) +ModulePass *createClassLookupCachePass(void) { return new ClassLookupCachePass(); } diff --git a/opts/ClassMethodInliner.cpp b/opts/ClassMethodInliner.cpp index 0806eb9..f5e33ef 100644 --- a/opts/ClassMethodInliner.cpp +++ b/opts/ClassMethodInliner.cpp @@ -36,7 +36,7 @@ namespace public: static char ID; - ClassMethodInliner() : ModulePass((intptr_t)&ID) {} + ClassMethodInliner() : ModulePass(ID) {} virtual bool runOnModule(Module &M) { unsigned MessageSendMDKind = M.getContext().getMDKindID("GNUObjCMessageSend"); @@ -59,7 +59,7 @@ namespace i != end ; ++i) { for (BasicBlock::iterator b=i->begin(), last=i->end() ; b != last ; ++b) { - CallSite call = CallSite::get(b); + CallSite call(b); if (call.getInstruction() && !call.getCalledFunction()) { MDNode *messageType = call->getMetadata(MessageSendMDKind); if (0 == messageType) { continue; } diff --git a/opts/IMPCacher.cpp b/opts/IMPCacher.cpp index 352ebb9..bcc48a3 100644 --- a/opts/IMPCacher.cpp +++ b/opts/IMPCacher.cpp @@ -172,7 +172,7 @@ void GNUstep::IMPCacher::SpeculativelyInline(Instruction *call, Function // Unify the return values if (call->getType() != Type::getVoidTy(Context)) { B.SetInsertPoint(afterCallBB, afterCallBB->begin()); - PHINode *phi = B.CreatePHI(call->getType()); + PHINode *phi = B.CreatePHI(call->getType(), 2); call->replaceAllUsesWith(phi); phi->addIncoming(call, callBB); phi->addIncoming(inlineResult, inlineBB); diff --git a/opts/IvarPass.cpp b/opts/IvarPass.cpp index 22e177f..8d0c694 100644 --- a/opts/IvarPass.cpp +++ b/opts/IvarPass.cpp @@ -17,7 +17,7 @@ namespace public: static char ID; - GNUNonfragileIvarPass() : FunctionPass((intptr_t)&ID) {} + GNUNonfragileIvarPass() : FunctionPass(ID) {} Module *M; size_t PointerSize; @@ -31,7 +31,8 @@ namespace std::string getSuperName(Constant *ClsStruct) { GlobalVariable *name = - cast(ClsStruct->getOperand(1)->getOperand(0)); + cast( + cast(ClsStruct->getOperand(1))->getOperand(0)); return cast(name->getInitializer())->getAsString(); } @@ -62,7 +63,8 @@ namespace for (int i=0 ; i(ivars->getOperand(i)); GlobalVariable *name = - cast(ivar->getOperand(0)->getOperand(0)); + cast( + cast(ivar->getOperand(0))->getOperand(0)); std::string ivarNameStr = cast(name->getInitializer())->getAsString(); if (ivarNameStr.compare(0, ivarName.size(), ivarName.str()) == 0) diff --git a/opts/LoopIMPCachePass.cpp b/opts/LoopIMPCachePass.cpp index 6ada618..3d4cfa0 100644 --- a/opts/LoopIMPCachePass.cpp +++ b/opts/LoopIMPCachePass.cpp @@ -20,7 +20,7 @@ namespace public: static char ID; - GNULoopIMPCachePass() : FunctionPass((intptr_t)&ID) {} + GNULoopIMPCachePass() : FunctionPass(ID) {} ~GNULoopIMPCachePass() { delete cacher; } virtual bool doInitialization(Module &Mod) { diff --git a/opts/TypeFeedback.cpp b/opts/TypeFeedback.cpp index 6da8502..90fe6eb 100644 --- a/opts/TypeFeedback.cpp +++ b/opts/TypeFeedback.cpp @@ -18,7 +18,7 @@ namespace { static char ID; uint32_t callsiteCount; const IntegerType *Int32Ty; - GNUObjCTypeFeedback() : ModulePass(&ID), callsiteCount(0) {} + GNUObjCTypeFeedback() : ModulePass(ID), callsiteCount(0) {} void profileFunction(Function &F, Constant *ModuleID) { for (Function::iterator i=F.begin(), e=F.end() ; @@ -29,7 +29,7 @@ namespace { for (BasicBlock::iterator b=i->begin(), last=i->end() ; b != last ; ++b) { - CallSite call = CallSite::get(b); + CallSite call(b); if (call.getInstruction() && !call.getCalledFunction()) { llvm::Value *args[] = { call->getOperand(1), call->getOperand(0), ModuleID, ConstantInt::get(Int32Ty, callsiteCount++) }; diff --git a/opts/TypeFeedbackDrivenInliner.cpp b/opts/TypeFeedbackDrivenInliner.cpp index f0a5f09..77702b5 100644 --- a/opts/TypeFeedbackDrivenInliner.cpp +++ b/opts/TypeFeedbackDrivenInliner.cpp @@ -25,7 +25,7 @@ namespace { public: - GNUObjCTypeFeedbackDrivenInliner() : ModulePass(&ID), callsiteCount(0) {} + GNUObjCTypeFeedbackDrivenInliner() : ModulePass(ID), callsiteCount(0) {} virtual bool runOnModule(Module &M) { @@ -51,7 +51,7 @@ namespace { i != end ; ++i) { for (BasicBlock::iterator b=i->begin(), last=i->end() ; b != last ; ++b) { - CallSite call = CallSite::get(b); + CallSite call(b); if (call.getInstruction() && !call.getCalledFunction()) { messages.push_back(call); }