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.
This commit is contained in:
theraven 2011-04-22 11:06:33 +00:00
parent 52381f163b
commit 9d5452b147
8 changed files with 99 additions and 26 deletions

View File

@ -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<Function>(callee)) {

View File

@ -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 <string>
#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<GlobalVariable*> statics;
typedef std::pair<CallInst*,std::string> 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<ClassLookup, 16> 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<CallInst>(b)) {
Value *callee = call->getCalledValue()->stripPointerCasts();
if (Function *func = dyn_cast<Function>(callee)) {
if (Function *func = call->getCalledFunction()) {
if (func->getName() == "objc_lookup_class") {
ClassLookup lookup;
GlobalVariable *classNameVar = dyn_cast<GlobalVariable>(
call->getOperand(1)->stripPointerCasts());
call->getOperand(0)->stripPointerCasts());
if (0 == classNameVar) { continue; }
ConstantArray *init = dyn_cast<ConstantArray>(
classNameVar->getInitializer());
@ -57,18 +65,81 @@ namespace
}
}
}
IRBuilder<> B = IRBuilder<>(entry);
for (SmallVectorImpl<ClassLookup>::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();
}

View File

@ -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; }

View File

@ -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);

View File

@ -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<GlobalVariable>(ClsStruct->getOperand(1)->getOperand(0));
cast<GlobalVariable>(
cast<Instruction>(ClsStruct->getOperand(1))->getOperand(0));
return cast<ConstantArray>(name->getInitializer())->getAsString();
}
@ -62,7 +63,8 @@ namespace
for (int i=0 ; i<ivarCount ; i++) {
Constant *ivar = cast<Constant>(ivars->getOperand(i));
GlobalVariable *name =
cast<GlobalVariable>(ivar->getOperand(0)->getOperand(0));
cast<GlobalVariable>(
cast<Instruction>(ivar->getOperand(0))->getOperand(0));
std::string ivarNameStr =
cast<ConstantArray>(name->getInitializer())->getAsString();
if (ivarNameStr.compare(0, ivarName.size(), ivarName.str()) == 0)

View File

@ -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) {

View File

@ -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++) };

View File

@ -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);
}