From 1918888ce1de156b2cb82205456738c3ad64be1e Mon Sep 17 00:00:00 2001 From: theraven Date: Tue, 27 Apr 2010 22:34:15 +0000 Subject: [PATCH] Added LoopIMPCachePass. This pass automatically performs IMP caching on all loops. Microbenchmark that just sends a message that does nothing 1000000000 times in a loop goes from taking 10.2 seconds to taking 4.7 after running the pass. --- opts/Debug/.dir | 1 - opts/Debug/IvarPass.d | 192 -------------------------------------- opts/Debug/TypeFeedback.d | 186 ------------------------------------ opts/IvarPass.cpp | 2 +- opts/LoopIMPCachePass.cpp | 157 +++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 380 deletions(-) delete mode 100644 opts/Debug/.dir delete mode 100644 opts/Debug/IvarPass.d delete mode 100644 opts/Debug/TypeFeedback.d create mode 100644 opts/LoopIMPCachePass.cpp diff --git a/opts/Debug/.dir b/opts/Debug/.dir deleted file mode 100644 index 25bc296..0000000 --- a/opts/Debug/.dir +++ /dev/null @@ -1 +0,0 @@ -Sun 13 Sep 2009 13:29:32 UTC diff --git a/opts/Debug/IvarPass.d b/opts/Debug/IvarPass.d deleted file mode 100644 index 376fe68..0000000 --- a/opts/Debug/IvarPass.d +++ /dev/null @@ -1,192 +0,0 @@ -/usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/IvarPass.o \ - /usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/IvarPass.d \ - /usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/IvarPass.o: \ - IvarPass.cpp /usr/home/theraven/llvm/include/llvm/Pass.h \ - /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ - /usr/home/theraven/llvm/include/llvm/PassSupport.h \ - /usr/home/theraven/llvm/include/llvm/PassAnalysisSupport.h \ - /usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h \ - /usr/home/theraven/llvm/include/llvm/Support/type_traits.h \ - /usr/home/theraven/llvm/include/llvm/Function.h \ - /usr/home/theraven/llvm/include/llvm/GlobalValue.h \ - /usr/home/theraven/llvm/include/llvm/Constant.h \ - /usr/home/theraven/llvm/include/llvm/User.h \ - /usr/home/theraven/llvm/include/llvm/Value.h \ - /usr/home/theraven/llvm/include/llvm/AbstractTypeUser.h \ - /usr/home/theraven/llvm/include/llvm/Use.h \ - /usr/home/theraven/llvm/include/llvm/Support/Casting.h \ - /usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h \ - /usr/home/theraven/llvm/include/llvm/Support/PointerLikeTypeTraits.h \ - /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ - /usr/home/theraven/llvm/include/llvm/ADT/StringRef.h \ - /usr/home/theraven/llvm/include/llvm/ADT/Twine.h \ - /usr/home/theraven/llvm/include/llvm/ADT/StringRef.h \ - /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ - /usr/home/theraven/llvm/include/llvm/CallingConv.h \ - /usr/home/theraven/llvm/include/llvm/BasicBlock.h \ - /usr/home/theraven/llvm/include/llvm/Instruction.h \ - /usr/home/theraven/llvm/include/llvm/ADT/ilist_node.h \ - /usr/home/theraven/llvm/include/llvm/Instruction.def \ - /usr/home/theraven/llvm/include/llvm/SymbolTableListTraits.h \ - /usr/home/theraven/llvm/include/llvm/ADT/ilist.h \ - /usr/home/theraven/llvm/include/llvm/Argument.h \ - /usr/home/theraven/llvm/include/llvm/Attributes.h \ - /usr/home/theraven/llvm/include/llvm/Support/MathExtras.h \ - /usr/home/theraven/llvm/include/llvm/Module.h \ - /usr/home/theraven/llvm/include/llvm/Function.h \ - /usr/home/theraven/llvm/include/llvm/GlobalVariable.h \ - /usr/home/theraven/llvm/include/llvm/OperandTraits.h \ - /usr/home/theraven/llvm/include/llvm/GlobalAlias.h \ - /usr/home/theraven/llvm/include/llvm/Metadata.h \ - /usr/home/theraven/llvm/include/llvm/Type.h \ - /usr/home/theraven/llvm/include/llvm/LLVMContext.h \ - /usr/home/theraven/llvm/include/llvm/System/Atomic.h \ - /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ - /usr/home/theraven/llvm/include/llvm/ADT/GraphTraits.h \ - /usr/home/theraven/llvm/include/llvm/ADT/FoldingSet.h \ - /usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h \ - /usr/home/theraven/llvm/include/llvm/ADT/SmallPtrSet.h \ - /usr/home/theraven/llvm/include/llvm/Support/ErrorHandling.h \ - /usr/home/theraven/llvm/include/llvm/Support/Compiler.h \ - /usr/home/theraven/llvm/include/llvm/Support/ValueHandle.h \ - /usr/home/theraven/llvm/include/llvm/ADT/DenseMapInfo.h \ - /usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h \ - /usr/home/theraven/llvm/include/llvm/Value.h \ - /usr/home/theraven/llvm/include/llvm/Instructions.h \ - /usr/home/theraven/llvm/include/llvm/InstrTypes.h \ - /usr/home/theraven/llvm/include/llvm/Operator.h \ - /usr/home/theraven/llvm/include/llvm/Constants.h \ - /usr/home/theraven/llvm/include/llvm/ADT/APInt.h \ - /usr/home/theraven/llvm/include/llvm/Support/MathExtras.h \ - /usr/home/theraven/llvm/include/llvm/ADT/APFloat.h \ - /usr/home/theraven/llvm/include/llvm/ADT/APInt.h \ - /usr/home/theraven/llvm/include/llvm/DerivedTypes.h \ - /usr/home/theraven/llvm/include/llvm/GlobalAlias.h \ - /usr/home/theraven/llvm/include/llvm/GlobalVariable.h \ - /usr/home/theraven/llvm/include/llvm/Constants.h - -/usr/home/theraven/llvm/include/llvm/Pass.h: - -/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: - -/usr/home/theraven/llvm/include/llvm/PassSupport.h: - -/usr/home/theraven/llvm/include/llvm/PassAnalysisSupport.h: - -/usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h: - -/usr/home/theraven/llvm/include/llvm/Support/type_traits.h: - -/usr/home/theraven/llvm/include/llvm/Function.h: - -/usr/home/theraven/llvm/include/llvm/GlobalValue.h: - -/usr/home/theraven/llvm/include/llvm/Constant.h: - -/usr/home/theraven/llvm/include/llvm/User.h: - -/usr/home/theraven/llvm/include/llvm/Value.h: - -/usr/home/theraven/llvm/include/llvm/AbstractTypeUser.h: - -/usr/home/theraven/llvm/include/llvm/Use.h: - -/usr/home/theraven/llvm/include/llvm/Support/Casting.h: - -/usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h: - -/usr/home/theraven/llvm/include/llvm/Support/PointerLikeTypeTraits.h: - -/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: - -/usr/home/theraven/llvm/include/llvm/ADT/StringRef.h: - -/usr/home/theraven/llvm/include/llvm/ADT/Twine.h: - -/usr/home/theraven/llvm/include/llvm/ADT/StringRef.h: - -/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: - -/usr/home/theraven/llvm/include/llvm/CallingConv.h: - -/usr/home/theraven/llvm/include/llvm/BasicBlock.h: - -/usr/home/theraven/llvm/include/llvm/Instruction.h: - -/usr/home/theraven/llvm/include/llvm/ADT/ilist_node.h: - -/usr/home/theraven/llvm/include/llvm/Instruction.def: - -/usr/home/theraven/llvm/include/llvm/SymbolTableListTraits.h: - -/usr/home/theraven/llvm/include/llvm/ADT/ilist.h: - -/usr/home/theraven/llvm/include/llvm/Argument.h: - -/usr/home/theraven/llvm/include/llvm/Attributes.h: - -/usr/home/theraven/llvm/include/llvm/Support/MathExtras.h: - -/usr/home/theraven/llvm/include/llvm/Module.h: - -/usr/home/theraven/llvm/include/llvm/Function.h: - -/usr/home/theraven/llvm/include/llvm/GlobalVariable.h: - -/usr/home/theraven/llvm/include/llvm/OperandTraits.h: - -/usr/home/theraven/llvm/include/llvm/GlobalAlias.h: - -/usr/home/theraven/llvm/include/llvm/Metadata.h: - -/usr/home/theraven/llvm/include/llvm/Type.h: - -/usr/home/theraven/llvm/include/llvm/LLVMContext.h: - -/usr/home/theraven/llvm/include/llvm/System/Atomic.h: - -/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: - -/usr/home/theraven/llvm/include/llvm/ADT/GraphTraits.h: - -/usr/home/theraven/llvm/include/llvm/ADT/FoldingSet.h: - -/usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h: - -/usr/home/theraven/llvm/include/llvm/ADT/SmallPtrSet.h: - -/usr/home/theraven/llvm/include/llvm/Support/ErrorHandling.h: - -/usr/home/theraven/llvm/include/llvm/Support/Compiler.h: - -/usr/home/theraven/llvm/include/llvm/Support/ValueHandle.h: - -/usr/home/theraven/llvm/include/llvm/ADT/DenseMapInfo.h: - -/usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h: - -/usr/home/theraven/llvm/include/llvm/Value.h: - -/usr/home/theraven/llvm/include/llvm/Instructions.h: - -/usr/home/theraven/llvm/include/llvm/InstrTypes.h: - -/usr/home/theraven/llvm/include/llvm/Operator.h: - -/usr/home/theraven/llvm/include/llvm/Constants.h: - -/usr/home/theraven/llvm/include/llvm/ADT/APInt.h: - -/usr/home/theraven/llvm/include/llvm/Support/MathExtras.h: - -/usr/home/theraven/llvm/include/llvm/ADT/APFloat.h: - -/usr/home/theraven/llvm/include/llvm/ADT/APInt.h: - -/usr/home/theraven/llvm/include/llvm/DerivedTypes.h: - -/usr/home/theraven/llvm/include/llvm/GlobalAlias.h: - -/usr/home/theraven/llvm/include/llvm/GlobalVariable.h: - -/usr/home/theraven/llvm/include/llvm/Constants.h: diff --git a/opts/Debug/TypeFeedback.d b/opts/Debug/TypeFeedback.d deleted file mode 100644 index 5998b41..0000000 --- a/opts/Debug/TypeFeedback.d +++ /dev/null @@ -1,186 +0,0 @@ -/usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/TypeFeedback.o \ - /usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/TypeFeedback.d \ - /usr/home/theraven/llvm/lib/Transforms/GNUObjC/Debug/TypeFeedback.o: \ - TypeFeedback.cpp /usr/home/theraven/llvm/include/llvm/Constants.h \ - /usr/home/theraven/llvm/include/llvm/Constant.h \ - /usr/home/theraven/llvm/include/llvm/User.h \ - /usr/home/theraven/llvm/include/llvm/Value.h \ - /usr/home/theraven/llvm/include/llvm/AbstractTypeUser.h \ - /usr/home/theraven/llvm/include/llvm/Use.h \ - /usr/home/theraven/llvm/include/llvm/Support/Casting.h \ - /usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h \ - /usr/home/theraven/llvm/include/llvm/Support/PointerLikeTypeTraits.h \ - /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ - /usr/home/theraven/llvm/include/llvm/ADT/StringRef.h \ - /usr/home/theraven/llvm/include/llvm/ADT/Twine.h \ - /usr/home/theraven/llvm/include/llvm/ADT/StringRef.h \ - /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ - /usr/home/theraven/llvm/include/llvm/Type.h \ - /usr/home/theraven/llvm/include/llvm/LLVMContext.h \ - /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ - /usr/home/theraven/llvm/include/llvm/System/Atomic.h \ - /usr/home/theraven/llvm/include/llvm/Support/DataTypes.h \ - /usr/home/theraven/llvm/include/llvm/ADT/GraphTraits.h \ - /usr/home/theraven/llvm/include/llvm/OperandTraits.h \ - /usr/home/theraven/llvm/include/llvm/ADT/APInt.h \ - /usr/home/theraven/llvm/include/llvm/Support/MathExtras.h \ - /usr/home/theraven/llvm/include/llvm/ADT/APFloat.h \ - /usr/home/theraven/llvm/include/llvm/ADT/APInt.h \ - /usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h \ - /usr/home/theraven/llvm/include/llvm/Support/type_traits.h \ - /usr/home/theraven/llvm/include/llvm/Pass.h \ - /usr/home/theraven/llvm/include/llvm/PassSupport.h \ - /usr/home/theraven/llvm/include/llvm/PassAnalysisSupport.h \ - /usr/home/theraven/llvm/include/llvm/Module.h \ - /usr/home/theraven/llvm/include/llvm/Function.h \ - /usr/home/theraven/llvm/include/llvm/GlobalValue.h \ - /usr/home/theraven/llvm/include/llvm/CallingConv.h \ - /usr/home/theraven/llvm/include/llvm/BasicBlock.h \ - /usr/home/theraven/llvm/include/llvm/Instruction.h \ - /usr/home/theraven/llvm/include/llvm/ADT/ilist_node.h \ - /usr/home/theraven/llvm/include/llvm/Instruction.def \ - /usr/home/theraven/llvm/include/llvm/SymbolTableListTraits.h \ - /usr/home/theraven/llvm/include/llvm/ADT/ilist.h \ - /usr/home/theraven/llvm/include/llvm/Argument.h \ - /usr/home/theraven/llvm/include/llvm/Attributes.h \ - /usr/home/theraven/llvm/include/llvm/Support/MathExtras.h \ - /usr/home/theraven/llvm/include/llvm/GlobalVariable.h \ - /usr/home/theraven/llvm/include/llvm/GlobalAlias.h \ - /usr/home/theraven/llvm/include/llvm/Metadata.h \ - /usr/home/theraven/llvm/include/llvm/ADT/FoldingSet.h \ - /usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h \ - /usr/home/theraven/llvm/include/llvm/ADT/SmallPtrSet.h \ - /usr/home/theraven/llvm/include/llvm/Support/ErrorHandling.h \ - /usr/home/theraven/llvm/include/llvm/Support/Compiler.h \ - /usr/home/theraven/llvm/include/llvm/Support/ValueHandle.h \ - /usr/home/theraven/llvm/include/llvm/ADT/DenseMapInfo.h \ - /usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h \ - /usr/home/theraven/llvm/include/llvm/Value.h \ - /usr/home/theraven/llvm/include/llvm/Function.h \ - /usr/home/theraven/llvm/include/llvm/Instructions.h \ - /usr/home/theraven/llvm/include/llvm/InstrTypes.h \ - /usr/home/theraven/llvm/include/llvm/Operator.h \ - /usr/home/theraven/llvm/include/llvm/Constants.h \ - /usr/home/theraven/llvm/include/llvm/DerivedTypes.h - -/usr/home/theraven/llvm/include/llvm/Constants.h: - -/usr/home/theraven/llvm/include/llvm/Constant.h: - -/usr/home/theraven/llvm/include/llvm/User.h: - -/usr/home/theraven/llvm/include/llvm/Value.h: - -/usr/home/theraven/llvm/include/llvm/AbstractTypeUser.h: - -/usr/home/theraven/llvm/include/llvm/Use.h: - -/usr/home/theraven/llvm/include/llvm/Support/Casting.h: - -/usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h: - -/usr/home/theraven/llvm/include/llvm/Support/PointerLikeTypeTraits.h: - -/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: - -/usr/home/theraven/llvm/include/llvm/ADT/StringRef.h: - -/usr/home/theraven/llvm/include/llvm/ADT/Twine.h: - -/usr/home/theraven/llvm/include/llvm/ADT/StringRef.h: - -/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: - -/usr/home/theraven/llvm/include/llvm/Type.h: - -/usr/home/theraven/llvm/include/llvm/LLVMContext.h: - -/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: - -/usr/home/theraven/llvm/include/llvm/System/Atomic.h: - -/usr/home/theraven/llvm/include/llvm/Support/DataTypes.h: - -/usr/home/theraven/llvm/include/llvm/ADT/GraphTraits.h: - -/usr/home/theraven/llvm/include/llvm/OperandTraits.h: - -/usr/home/theraven/llvm/include/llvm/ADT/APInt.h: - -/usr/home/theraven/llvm/include/llvm/Support/MathExtras.h: - -/usr/home/theraven/llvm/include/llvm/ADT/APFloat.h: - -/usr/home/theraven/llvm/include/llvm/ADT/APInt.h: - -/usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h: - -/usr/home/theraven/llvm/include/llvm/Support/type_traits.h: - -/usr/home/theraven/llvm/include/llvm/Pass.h: - -/usr/home/theraven/llvm/include/llvm/PassSupport.h: - -/usr/home/theraven/llvm/include/llvm/PassAnalysisSupport.h: - -/usr/home/theraven/llvm/include/llvm/Module.h: - -/usr/home/theraven/llvm/include/llvm/Function.h: - -/usr/home/theraven/llvm/include/llvm/GlobalValue.h: - -/usr/home/theraven/llvm/include/llvm/CallingConv.h: - -/usr/home/theraven/llvm/include/llvm/BasicBlock.h: - -/usr/home/theraven/llvm/include/llvm/Instruction.h: - -/usr/home/theraven/llvm/include/llvm/ADT/ilist_node.h: - -/usr/home/theraven/llvm/include/llvm/Instruction.def: - -/usr/home/theraven/llvm/include/llvm/SymbolTableListTraits.h: - -/usr/home/theraven/llvm/include/llvm/ADT/ilist.h: - -/usr/home/theraven/llvm/include/llvm/Argument.h: - -/usr/home/theraven/llvm/include/llvm/Attributes.h: - -/usr/home/theraven/llvm/include/llvm/Support/MathExtras.h: - -/usr/home/theraven/llvm/include/llvm/GlobalVariable.h: - -/usr/home/theraven/llvm/include/llvm/GlobalAlias.h: - -/usr/home/theraven/llvm/include/llvm/Metadata.h: - -/usr/home/theraven/llvm/include/llvm/ADT/FoldingSet.h: - -/usr/home/theraven/llvm/include/llvm/ADT/SmallVector.h: - -/usr/home/theraven/llvm/include/llvm/ADT/SmallPtrSet.h: - -/usr/home/theraven/llvm/include/llvm/Support/ErrorHandling.h: - -/usr/home/theraven/llvm/include/llvm/Support/Compiler.h: - -/usr/home/theraven/llvm/include/llvm/Support/ValueHandle.h: - -/usr/home/theraven/llvm/include/llvm/ADT/DenseMapInfo.h: - -/usr/home/theraven/llvm/include/llvm/ADT/PointerIntPair.h: - -/usr/home/theraven/llvm/include/llvm/Value.h: - -/usr/home/theraven/llvm/include/llvm/Function.h: - -/usr/home/theraven/llvm/include/llvm/Instructions.h: - -/usr/home/theraven/llvm/include/llvm/InstrTypes.h: - -/usr/home/theraven/llvm/include/llvm/Operator.h: - -/usr/home/theraven/llvm/include/llvm/Constants.h: - -/usr/home/theraven/llvm/include/llvm/DerivedTypes.h: diff --git a/opts/IvarPass.cpp b/opts/IvarPass.cpp index f7de826..22e177f 100644 --- a/opts/IvarPass.cpp +++ b/opts/IvarPass.cpp @@ -60,7 +60,7 @@ namespace int ivarCount = cast(IvarStruct->getOperand(0))->getSExtValue(); Constant *ivars = IvarStruct->getOperand(1); for (int i=0 ; igetOperand(i); + Constant *ivar = cast(ivars->getOperand(i)); GlobalVariable *name = cast(ivar->getOperand(0)->getOperand(0)); std::string ivarNameStr = diff --git a/opts/LoopIMPCachePass.cpp b/opts/LoopIMPCachePass.cpp new file mode 100644 index 0000000..2324eb2 --- /dev/null +++ b/opts/LoopIMPCachePass.cpp @@ -0,0 +1,157 @@ +#include "llvm/Pass.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/GlobalAlias.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Constants.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include + +using namespace llvm; +using std::string; + +namespace +{ + class GNULoopIMPCachePass : public FunctionPass + { + + public: + static char ID; + GNULoopIMPCachePass() : FunctionPass((intptr_t)&ID) {} + + Module *M; + LLVMContext *Context; + const PointerType *PtrTy; + const PointerType *IdTy; + const IntegerType *IntTy; + + virtual bool doInitialization(Module &Mod) { + M = &Mod; + Context = &M->getContext(); + PtrTy = Type::getInt8PtrTy(*Context); + // FIXME: 64-bit. + IntTy = Type::getInt32Ty(*Context); + IdTy = PointerType::getUnqual(PtrTy); + return false; + } + virtual void getAnalysisUsage(AnalysisUsage &Info) const { + Info.addRequired(); + } + + + // TODO: Move this to a helper class. + void CacheLookup(CallInst *lookup, BasicBlock *allocaBlock) { + const Type *SlotPtrTy = lookup->getType(); + + IRBuilder<> B = IRBuilder<>(allocaBlock); + B.SetInsertPoint(allocaBlock, allocaBlock->begin()); + Value *slot = B.CreateAlloca(SlotPtrTy, 0, "slot"); + Value *version = B.CreateAlloca(IntTy, 0, "slot_version"); + + B.SetInsertPoint(allocaBlock, allocaBlock->getTerminator()); + B.CreateStore(Constant::getNullValue(SlotPtrTy), slot); + B.CreateStore(Constant::getNullValue(IntTy), version); + + BasicBlock *beforeLookupBB = lookup->getParent(); + BasicBlock *lookupBB = SplitBlock(beforeLookupBB, lookup, this); + BasicBlock::iterator iter = lookup; + iter++; + BasicBlock *afterLookupBB = SplitBlock(iter->getParent(), iter, this); + + beforeLookupBB->getTerminator()->removeFromParent(); + B.SetInsertPoint(beforeLookupBB); + // Load the slot and check that neither it nor the version is 0. + Value *slotValue = B.CreateLoad(slot); + Value *versionValue = B.CreateLoad(version); + Value *receiver = lookup->getOperand(1); + + Value *isCacheEmpty = + B.CreateOr(versionValue, B.CreatePtrToInt(slotValue, IntTy)); + isCacheEmpty = + B.CreateICmpEQ(isCacheEmpty, Constant::getNullValue(IntTy)); + Value *receiverNotNil = + B.CreateICmpNE(receiver, Constant::getNullValue(receiver->getType())); + isCacheEmpty = B.CreateAnd(isCacheEmpty, receiverNotNil); + + BasicBlock *cacheLookupBB = BasicBlock::Create(*Context, "cache_check", + allocaBlock->getParent()); + + B.CreateCondBr(isCacheEmpty, lookupBB, cacheLookupBB); + + // Check the cache node is current + B.SetInsertPoint(cacheLookupBB); + Value *slotVersion = B.CreateStructGEP(slotValue, 3); + // Note: Volatile load because the slot version might have changed in + // another thread. + slotVersion = B.CreateLoad(slotVersion, true, "slot_version"); + Value *slotCachedFor = B.CreateStructGEP(slotValue, 1); + slotCachedFor = B.CreateLoad(slotCachedFor, true, "slot_owner"); + Value *cls = B.CreateLoad(B.CreateBitCast(receiver, IdTy)); + Value *isVersionCorrect = B.CreateICmpEQ(slotVersion, versionValue); + Value *isOwnerCorrect = B.CreateICmpEQ(slotCachedFor, cls); + Value *isSlotValid = B.CreateAnd(isVersionCorrect, isOwnerCorrect); + // If this slot is still valid, skip the lookup. + B.CreateCondBr(isSlotValid, afterLookupBB, lookupBB); + + // Replace the looked up slot with the loaded one + B.SetInsertPoint(afterLookupBB, afterLookupBB->begin()); + // Not volatile, so a redundant load elimination pass can do some phi + // magic with this later. + lookup->replaceAllUsesWith(B.CreateLoad(slot)); + + // Perform the real lookup and cache the result + lookupBB->getTerminator()->removeFromParent(); + B.SetInsertPoint(lookupBB); + // Store it even if the version is 0, because we always check that the + // version is not 0 at the start and an occasional redundant store is + // probably better than a branch every time. + B.CreateStore(lookup, slot); + B.CreateStore(B.CreateLoad(B.CreateStructGEP(lookup, 3)), version); + cls = B.CreateLoad(B.CreateBitCast(receiver, IdTy)); + B.CreateStore(cls, B.CreateStructGEP(lookup, 1)); + B.CreateBr(afterLookupBB); + } + + virtual bool runOnFunction(Function &F) { + LoopInfo &LI = getAnalysis(); + bool modified = false; + SmallVector Lookups; + BasicBlock *entry = &F.getEntryBlock(); + + for (Function::iterator i=F.begin(), end=F.end() ; + i != end ; ++i) { + // Ignore basic blocks that are not parts of loops. + if (LI.getLoopDepth(i) == 0) { continue; } + 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 (func->getName() == "objc_msg_lookup_sender") { + modified = true; + Lookups.push_back(call); + } + } + } + } + } + for (SmallVectorImpl::iterator i=Lookups.begin(), + e=Lookups.end() ; e!=i ; i++) { + CacheLookup(*i, entry); + } + return modified; + } + }; + + char GNULoopIMPCachePass::ID = 0; + RegisterPass X("gnu-loop-imp-cache", + "Cache IMPs in loops pass"); +} + +FunctionPass *createGNULoopIMPCachePass(void) +{ + return new GNULoopIMPCachePass(); +}