[llvm-commits] [poolalloc] r40505 - in /poolalloc/branches/SVA/lib/DSA: Devirt.cpp Info.cpp
Andrew Lenharth
alenhar2 at cs.uiuc.edu
Wed Jul 25 17:36:59 PDT 2007
Author: alenhar2
Date: Wed Jul 25 19:36:58 2007
New Revision: 40505
URL: http://llvm.org/viewvc/llvm-project?rev=40505&view=rev
Log:
how did I forget these files
Added:
poolalloc/branches/SVA/lib/DSA/Devirt.cpp
poolalloc/branches/SVA/lib/DSA/Info.cpp
Added: poolalloc/branches/SVA/lib/DSA/Devirt.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/SVA/lib/DSA/Devirt.cpp?rev=40505&view=auto
==============================================================================
--- poolalloc/branches/SVA/lib/DSA/Devirt.cpp (added)
+++ poolalloc/branches/SVA/lib/DSA/Devirt.cpp Wed Jul 25 19:36:58 2007
@@ -0,0 +1,176 @@
+//===- Devirt.cpp - Devirtualize using the sig match intrinsic in llva ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/Transforms/IPO.h"
+#include "dsa/CallTargets.h"
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+#include "llvm/Function.h"
+#include "llvm/Instructions.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/ADT/Statistic.h"
+
+#include <iostream>
+#include <map>
+#include <algorithm>
+#include <iterator>
+
+using namespace llvm;
+
+namespace {
+
+ static cl::opt<int>
+ VirtualLimit("devirt-limit", cl::Hidden, cl::init(16),
+ cl::desc("Maximum number of callees to devirtualize at a call site"));
+ Statistic<> FuncAdded("devirt", "Number of bounce functions added");
+ Statistic<> CSConvert("devirt", "Number of call sites converted");
+
+
+ class Devirtualize : public ModulePass {
+
+
+ std::map<std::pair<const Type*, std::vector<Function*> >, Function*> cache;
+ int fnum;
+
+ Function* buildBounce(CallSite cs, std::vector<Function*>& Targets, Module& M) {
+ Value* ptr = cs.getCalledValue();
+ const FunctionType* OrigType =
+ cast<FunctionType>(cast<PointerType>(ptr->getType())->getElementType());;
+ ++FuncAdded;
+
+ std::vector< const Type *> TP(OrigType->param_begin(), OrigType->param_end());
+ TP.insert(TP.begin(), ptr->getType());
+ const FunctionType* NewTy = FunctionType::get(OrigType->getReturnType(), TP, false);
+ Function* F = new Function(NewTy, GlobalValue::InternalLinkage, "devirtbounce", &M);
+ std::map<Function*, BasicBlock*> targets;
+
+ F->arg_begin()->setName("funcPtr");
+ std::vector<Value*> fargs;
+ for(Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end(); ai != ae; ++ai)
+ if (ai != F->arg_begin()) {
+ fargs.push_back(ai);
+ ai->setName("arg");
+ }
+
+ for (std::vector<Function*>::iterator i = Targets.begin(), e = Targets.end();
+ i != e; ++i) {
+ Function* FL = *i;
+ BasicBlock* BL = new BasicBlock(FL->getName(), F);
+ targets[FL] = BL;
+
+ //Make call
+ Value* call = new CallInst(FL, fargs, "", BL);
+
+ //return correctly
+ if (OrigType->getReturnType() == Type::VoidTy)
+ new ReturnInst(0, BL);
+ else
+ new ReturnInst(call, BL);
+ }
+
+ //hookup the test chain
+ BasicBlock* tail = new BasicBlock("fail", F, &F->getEntryBlock());
+ new CallInst(M.getOrInsertFunction("pchk_ind_fail", Type::VoidTy, NULL),
+ "", tail);
+ new UnreachableInst(tail);
+
+ for (std::vector<Function*>::iterator i = Targets.begin(), e = Targets.end();
+ i != e; ++i) {
+ BasicBlock* TB = targets[*i];
+ BasicBlock* newB = new BasicBlock("test." + (*i)->getName(), F, &F->getEntryBlock());
+ Value* p = F->arg_begin();
+ SetCondInst* setcc = new SetCondInst(Instruction::SetEQ, *i, p, "sc", newB);
+ new BranchInst(TB, tail, setcc, newB);
+ tail = newB;
+ }
+ return F;
+ }
+
+ public:
+ virtual bool runOnModule(Module &M) {
+ CallTargetFinder* CTF = &getAnalysis<CallTargetFinder>();
+ bool changed = false;
+
+ Function* ams = M.getNamedFunction("llva_assert_match_sig");
+
+ std::set<Value*> safecalls;
+
+ for (Value::use_iterator ii = ams->use_begin(), ee = ams->use_end();
+ ii != ee; ++ii) {
+ if (CallInst* CI = dyn_cast<CallInst>(*ii)) {
+ std::cerr << "Found safe call site in "
+ << CI->getParent()->getParent()->getName() << "\n";
+ Value* V = CI->getOperand(1);
+ CI->eraseFromParent();
+ do {
+ safecalls.insert(V);
+ if (CastInst* CV = dyn_cast<CastInst>(V))
+ V = CV->getOperand(0);
+ else V = 0;
+ } while (V);
+ }
+ }
+
+ std::vector<Instruction*> toDelete;
+
+ for(std::set<Value*>::iterator i = safecalls.begin(), e = safecalls.end();
+ i != e; ++i) {
+ for (Value::use_iterator ii = (*i)->use_begin(), ie = (*i)->use_end();
+ ii != ie; ++ii) {
+ CallSite cs = CallSite::get(*ii);
+ bool isSafeCall = cs.getInstruction() &&
+ safecalls.find(cs.getCalledValue()) != safecalls.end();
+ if (cs.getInstruction() && !cs.getCalledFunction() &&
+ (isSafeCall || CTF->isComplete(cs))) {
+ std::vector<Function*> Targets;
+ for (std::vector<Function*>::iterator ii = CTF->begin(cs), ee = CTF->end(cs);
+ ii != ee; ++ii)
+ if (!isSafeCall || (*ii)->getType() == cs.getCalledValue()->getType())
+ Targets.push_back(*ii);
+
+ if (Targets.size() > 0) {
+ std::cerr << "Target count: " << Targets.size() << "\n";
+ Function* NF = buildBounce(cs, Targets, M);
+ changed = true;
+ if (CallInst* ci = dyn_cast<CallInst>(cs.getInstruction())) {
+ ++CSConvert;
+ std::vector<Value*> Par(ci->op_begin(), ci->op_end());
+ CallInst* cn = new CallInst(NF, Par,
+ ci->getName() + ".dv", ci);
+ ci->replaceAllUsesWith(cn);
+ toDelete.push_back(ci);
+ } else if (InvokeInst* ci = dyn_cast<InvokeInst>(cs.getInstruction())) {
+ ++CSConvert;
+ std::vector<Value*> Par(ci->op_begin(), ci->op_end());
+ InvokeInst* cn = new InvokeInst(NF, ci->getNormalDest(),
+ ci->getUnwindDest(),
+ Par, ci->getName()+".dv",
+ ci);
+ ci->replaceAllUsesWith(cn);
+ toDelete.push_back(ci);
+ }
+ }
+ }
+ }
+ }
+ for (std::vector<Instruction*>::iterator ii = toDelete.begin(), ee = toDelete.end();
+ ii != ee; ++ii)
+ (*ii)->eraseFromParent();
+ return changed;
+ }
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<CallTargetFinder>();
+ }
+
+ };
+
+ RegisterPass<Devirtualize> X("devirt", "Devirtualization");
+
+}
Added: poolalloc/branches/SVA/lib/DSA/Info.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/branches/SVA/lib/DSA/Info.cpp?rev=40505&view=auto
==============================================================================
--- poolalloc/branches/SVA/lib/DSA/Info.cpp (added)
+++ poolalloc/branches/SVA/lib/DSA/Info.cpp Wed Jul 25 19:36:58 2007
@@ -0,0 +1,28 @@
+#include "llvm/Pass.h"
+#include "llvm/Function.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Instructions.h"
+#include "llvm/ADT/Statistic.h"
+
+using namespace llvm;
+
+Statistic<> Direct("calltarget", "Number of direct calls");
+Statistic<> Indirect("calltarget", "Number of indirect calls");
+
+
+namespace {
+ struct CallInfo : public FunctionPass {
+ virtual bool runOnFunction(Function &F) {
+ for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI)
+ for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); II != IE; ++II)
+ if (CallInst* CI = dyn_cast<CallInst>(&*II))
+ if (CI->getCalledFunction())
+ ++Direct;
+ else
+ ++Indirect;
+ return false;
+ }
+ };
+
+ RegisterPass<CallInfo> X("call-info", "Call Info Pass");
+}
More information about the llvm-commits
mailing list