Initial (working) type feedback pass. Records the IMP for every message lookup. Note: This writes 3 words for every single message send, which means that it makes code VERY slow and can fill up the filesystem if you leave it enabled.

The aim of this pass is to identify message send sites which can benefit from speculative inlining and inline caching.  By itself, this pass is useless.  It will later be combined with one that parses this information and then uses the existing caching and inlining infrastructure to optimize hot message send sites.

Now, however, it's time for me to go and dance, so the useful bit will have to wait.
main
theraven 16 years ago
parent 6459292a40
commit c425b1bfdc

@ -3,6 +3,8 @@
#include "llvm/Module.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Linker.h"
#include <vector>
using namespace llvm;
@ -17,22 +19,19 @@ namespace {
const IntegerType *Int32Ty;
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() ;
i != e ; ++i)
{
i != e ; ++i) {
replacementVector replacements;
for (BasicBlock::iterator b=i->begin(), last=i->end() ;
b != last ; ++b)
{
b != last ; ++b) {
Module *M = F.getParent();
if (CallInst *call = dyn_cast<CallInst>(b))
{
if (Function *callee = call->getCalledFunction())
{
if (callee->getName() == "objc_msg_lookup_sender")
{
if (CallInst *call = dyn_cast<CallInst>(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,
@ -51,8 +50,7 @@ namespace {
}
}
for (replacementVector::iterator r=replacements.begin(),
e=replacements.end() ; e!=r ; r++)
{
e=replacements.end() ; e!=r ; r++) {
r->first->replaceAllUsesWith(r->second);
r->second->getParent()->getInstList().erase(r->first);
}
@ -64,17 +62,85 @@ namespace {
{
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<Constant*> functions;
llvm::Constant *Zeros[2];
Zeros[0] = ConstantInt::get(Type::getInt32Ty(VMContext), 0);
Zeros[1] = Zeros[0];
moduleName = ConstantExpr::getGetElementPtr(moduleName, Zeros, 2);
moduleName->dump();
functions.push_back(moduleName);;
functions.push_back(moduleName);;
for (Module::iterator F=M.begin(), e=M.end() ;
F != e ; ++F)
{
F != e ; ++F) {
if (F->isDeclaration()) { continue; }
functions.push_back(ConstantExpr::getBitCast(F, PtrTy));
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));
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<Constant*> ctors;
ConstantArray *CA = cast<ConstantArray>(GCL->getInitializer());
for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) {
ConstantStruct *CS = cast<ConstantStruct>(*i);
ctors.push_back(dyn_cast<Function>(CS->getOperand(1)));
}
// Type of one ctor
const Type *ctorTy =
cast<ArrayType>(GCL->getType()->getElementType())->getElementType();
// Add the
std::vector<Constant*> 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>(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();
M.dump();
return true;
}

Loading…
Cancel
Save