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.
main
theraven 15 years ago
parent 52381f163b
commit 9d5452b147

@ -22,7 +22,7 @@ namespace
public: public:
static char ID; static char ID;
ClassIMPCachePass() : ModulePass((intptr_t)&ID) {} ClassIMPCachePass() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) { virtual bool runOnModule(Module &M) {
GNUstep::IMPCacher cacher = GNUstep::IMPCacher(M.getContext(), this); GNUstep::IMPCacher cacher = GNUstep::IMPCacher(M.getContext(), this);
@ -44,7 +44,7 @@ namespace
i != end ; ++i) { i != end ; ++i) {
for (BasicBlock::iterator b=i->begin(), last=i->end() ; for (BasicBlock::iterator b=i->begin(), last=i->end() ;
b != last ; ++b) { b != last ; ++b) {
CallSite call = CallSite::get(b); CallSite call(b);
if (call.getInstruction()) { if (call.getInstruction()) {
Value *callee = call.getCalledValue()->stripPointerCasts(); Value *callee = call.getCalledValue()->stripPointerCasts();
if (Function *func = dyn_cast<Function>(callee)) { if (Function *func = dyn_cast<Function>(callee)) {

@ -5,45 +5,53 @@
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/GlobalVariable.h" #include "llvm/GlobalVariable.h"
#include "llvm/Support/IRBuilder.h" #include "llvm/Support/IRBuilder.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopInfo.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include <string> #include <string>
#include "IMPCacher.h"
using namespace llvm; using namespace llvm;
using namespace GNUstep;
using std::string; using std::string;
using std::pair; using std::pair;
namespace namespace
{ {
class ClassLookupCachePass : public FunctionPass class ClassLookupCachePass : public ModulePass {
{ /// Module that we're currently optimising
Module *M; 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<GlobalVariable*> statics;
typedef std::pair<CallInst*,std::string> ClassLookup; typedef std::pair<CallInst*,std::string> ClassLookup;
public: public:
static char ID; static char ID;
ClassLookupCachePass() : FunctionPass((intptr_t)&ID) {} ClassLookupCachePass() : ModulePass(ID) {}
virtual bool doInitialization(Module &Mod) { virtual bool doInitialization(Module &Mod) {
M = &Mod; M = &Mod;
return false; return false;
} }
virtual bool runOnFunction(Function &F) { bool runOnFunction(Function &F) {
bool modified = false; bool modified = false;
SmallVector<ClassLookup, 16> Lookups; SmallVector<ClassLookup, 16> Lookups;
BasicBlock *entry = &F.getEntryBlock();
for (Function::iterator i=F.begin(), end=F.end() ; for (Function::iterator i=F.begin(), end=F.end() ;
i != end ; ++i) { i != end ; ++i) {
for (BasicBlock::iterator b=i->begin(), last=i->end() ; for (BasicBlock::iterator b=i->begin(), last=i->end() ;
b != last ; ++b) { b != last ; ++b) {
if (CallInst *call = dyn_cast<CallInst>(b)) { if (CallInst *call = dyn_cast<CallInst>(b)) {
Value *callee = call->getCalledValue()->stripPointerCasts(); if (Function *func = call->getCalledFunction()) {
if (Function *func = dyn_cast<Function>(callee)) {
if (func->getName() == "objc_lookup_class") { if (func->getName() == "objc_lookup_class") {
ClassLookup lookup; ClassLookup lookup;
GlobalVariable *classNameVar = dyn_cast<GlobalVariable>( GlobalVariable *classNameVar = dyn_cast<GlobalVariable>(
call->getOperand(1)->stripPointerCasts()); call->getOperand(0)->stripPointerCasts());
if (0 == classNameVar) { continue; } if (0 == classNameVar) { continue; }
ConstantArray *init = dyn_cast<ConstantArray>( ConstantArray *init = dyn_cast<ConstantArray>(
classNameVar->getInitializer()); classNameVar->getInitializer());
@ -57,18 +65,81 @@ namespace
} }
} }
} }
IRBuilder<> B = IRBuilder<>(entry);
for (SmallVectorImpl<ClassLookup>::iterator i=Lookups.begin(), for (SmallVectorImpl<ClassLookup>::iterator i=Lookups.begin(),
e=Lookups.end() ; e!=i ; i++) { 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); 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) { if (global) {
Value *cls = new BitCastInst(global, i->first->getType(), "class", i->first); // Insert a bitcast of the class to the required type where the
i->first->replaceAllUsesWith(cls); // lookup is and then replace all references to the lookup with it.
i->first->removeFromParent(); 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; 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; char ClassLookupCachePass::ID = 0;
@ -76,7 +147,7 @@ namespace
"Cache class lookups"); "Cache class lookups");
} }
FunctionPass *createClassLookupCachePass(void) ModulePass *createClassLookupCachePass(void)
{ {
return new ClassLookupCachePass(); return new ClassLookupCachePass();
} }

@ -36,7 +36,7 @@ namespace
public: public:
static char ID; static char ID;
ClassMethodInliner() : ModulePass((intptr_t)&ID) {} ClassMethodInliner() : ModulePass(ID) {}
virtual bool runOnModule(Module &M) { virtual bool runOnModule(Module &M) {
unsigned MessageSendMDKind = M.getContext().getMDKindID("GNUObjCMessageSend"); unsigned MessageSendMDKind = M.getContext().getMDKindID("GNUObjCMessageSend");
@ -59,7 +59,7 @@ namespace
i != end ; ++i) { i != end ; ++i) {
for (BasicBlock::iterator b=i->begin(), last=i->end() ; for (BasicBlock::iterator b=i->begin(), last=i->end() ;
b != last ; ++b) { b != last ; ++b) {
CallSite call = CallSite::get(b); CallSite call(b);
if (call.getInstruction() && !call.getCalledFunction()) { if (call.getInstruction() && !call.getCalledFunction()) {
MDNode *messageType = call->getMetadata(MessageSendMDKind); MDNode *messageType = call->getMetadata(MessageSendMDKind);
if (0 == messageType) { continue; } if (0 == messageType) { continue; }

@ -172,7 +172,7 @@ void GNUstep::IMPCacher::SpeculativelyInline(Instruction *call, Function
// Unify the return values // Unify the return values
if (call->getType() != Type::getVoidTy(Context)) { if (call->getType() != Type::getVoidTy(Context)) {
B.SetInsertPoint(afterCallBB, afterCallBB->begin()); B.SetInsertPoint(afterCallBB, afterCallBB->begin());
PHINode *phi = B.CreatePHI(call->getType()); PHINode *phi = B.CreatePHI(call->getType(), 2);
call->replaceAllUsesWith(phi); call->replaceAllUsesWith(phi);
phi->addIncoming(call, callBB); phi->addIncoming(call, callBB);
phi->addIncoming(inlineResult, inlineBB); phi->addIncoming(inlineResult, inlineBB);

@ -17,7 +17,7 @@ namespace
public: public:
static char ID; static char ID;
GNUNonfragileIvarPass() : FunctionPass((intptr_t)&ID) {} GNUNonfragileIvarPass() : FunctionPass(ID) {}
Module *M; Module *M;
size_t PointerSize; size_t PointerSize;
@ -31,7 +31,8 @@ namespace
std::string getSuperName(Constant *ClsStruct) { std::string getSuperName(Constant *ClsStruct) {
GlobalVariable *name = GlobalVariable *name =
cast<GlobalVariable>(ClsStruct->getOperand(1)->getOperand(0)); cast<GlobalVariable>(
cast<Instruction>(ClsStruct->getOperand(1))->getOperand(0));
return cast<ConstantArray>(name->getInitializer())->getAsString(); return cast<ConstantArray>(name->getInitializer())->getAsString();
} }
@ -62,7 +63,8 @@ namespace
for (int i=0 ; i<ivarCount ; i++) { for (int i=0 ; i<ivarCount ; i++) {
Constant *ivar = cast<Constant>(ivars->getOperand(i)); Constant *ivar = cast<Constant>(ivars->getOperand(i));
GlobalVariable *name = GlobalVariable *name =
cast<GlobalVariable>(ivar->getOperand(0)->getOperand(0)); cast<GlobalVariable>(
cast<Instruction>(ivar->getOperand(0))->getOperand(0));
std::string ivarNameStr = std::string ivarNameStr =
cast<ConstantArray>(name->getInitializer())->getAsString(); cast<ConstantArray>(name->getInitializer())->getAsString();
if (ivarNameStr.compare(0, ivarName.size(), ivarName.str()) == 0) if (ivarNameStr.compare(0, ivarName.size(), ivarName.str()) == 0)

@ -20,7 +20,7 @@ namespace
public: public:
static char ID; static char ID;
GNULoopIMPCachePass() : FunctionPass((intptr_t)&ID) {} GNULoopIMPCachePass() : FunctionPass(ID) {}
~GNULoopIMPCachePass() { delete cacher; } ~GNULoopIMPCachePass() { delete cacher; }
virtual bool doInitialization(Module &Mod) { virtual bool doInitialization(Module &Mod) {

@ -18,7 +18,7 @@ namespace {
static char ID; static char ID;
uint32_t callsiteCount; uint32_t callsiteCount;
const IntegerType *Int32Ty; const IntegerType *Int32Ty;
GNUObjCTypeFeedback() : ModulePass(&ID), callsiteCount(0) {} GNUObjCTypeFeedback() : ModulePass(ID), callsiteCount(0) {}
void profileFunction(Function &F, Constant *ModuleID) { void profileFunction(Function &F, Constant *ModuleID) {
for (Function::iterator i=F.begin(), e=F.end() ; for (Function::iterator i=F.begin(), e=F.end() ;
@ -29,7 +29,7 @@ namespace {
for (BasicBlock::iterator b=i->begin(), last=i->end() ; for (BasicBlock::iterator b=i->begin(), last=i->end() ;
b != last ; ++b) { b != last ; ++b) {
CallSite call = CallSite::get(b); CallSite call(b);
if (call.getInstruction() && !call.getCalledFunction()) { if (call.getInstruction() && !call.getCalledFunction()) {
llvm::Value *args[] = { call->getOperand(1), call->getOperand(0), llvm::Value *args[] = { call->getOperand(1), call->getOperand(0),
ModuleID, ConstantInt::get(Int32Ty, callsiteCount++) }; ModuleID, ConstantInt::get(Int32Ty, callsiteCount++) };

@ -25,7 +25,7 @@ namespace {
public: public:
GNUObjCTypeFeedbackDrivenInliner() : ModulePass(&ID), callsiteCount(0) {} GNUObjCTypeFeedbackDrivenInliner() : ModulePass(ID), callsiteCount(0) {}
virtual bool runOnModule(Module &M) virtual bool runOnModule(Module &M)
{ {
@ -51,7 +51,7 @@ namespace {
i != end ; ++i) { i != end ; ++i) {
for (BasicBlock::iterator b=i->begin(), last=i->end() ; for (BasicBlock::iterator b=i->begin(), last=i->end() ;
b != last ; ++b) { b != last ; ++b) {
CallSite call = CallSite::get(b); CallSite call(b);
if (call.getInstruction() && !call.getCalledFunction()) { if (call.getInstruction() && !call.getCalledFunction()) {
messages.push_back(call); messages.push_back(call);
} }

Loading…
Cancel
Save