//
// 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.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// backedges. At each connection point a choice is made as to whether to jump
// to the profiled code (take a sample) or execute the unprofiled code.
//
-// It is highly recommeneded that after this pass one runs mem2reg and adce
+// It is highly recommended that after this pass one runs mem2reg and adce
// (instcombine load-vn gdce dse also are good to run afterwards)
//
// This design is intended to make the profiling passes independent of the RS
#include "llvm/Instructions.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/Intrinsics.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Transforms/Instrumentation.h"
#include "RSProfiling.h"
#include <set>
#include <map>
#include <queue>
-#include <list>
using namespace llvm;
namespace {
enum RandomMeth {
GBV, GBVO, HOSTCC
};
+}
- cl::opt<RandomMeth> RandomMethod("profile-randomness",
- cl::desc("How to randomly choose to profile:"),
- cl::values(
- clEnumValN(GBV, "global", "global counter"),
- clEnumValN(GBVO, "ra_global",
- "register allocated global counter"),
- clEnumValN(HOSTCC, "rdcc", "cycle counter"),
- clEnumValEnd));
+static cl::opt<RandomMeth> RandomMethod("profile-randomness",
+ cl::desc("How to randomly choose to profile:"),
+ cl::values(
+ clEnumValN(GBV, "global", "global counter"),
+ clEnumValN(GBVO, "ra_global",
+ "register allocated global counter"),
+ clEnumValN(HOSTCC, "rdcc", "cycle counter"),
+ clEnumValEnd));
+namespace {
/// NullProfilerRS - The basic profiler that does nothing. It is the default
/// profiler and thus terminates RSProfiler chains. It is useful for
/// measuring framework overhead
- class NullProfilerRS : public RSProfilers {
+ class VISIBILITY_HIDDEN NullProfilerRS : public RSProfilers {
public:
+ static char ID; // Pass identification, replacement for typeid
bool isProfiling(Value* v) {
return false;
}
AU.setPreservesAll();
}
};
+}
- static RegisterAnalysisGroup<RSProfilers> A("Profiling passes");
- static RegisterPass<NullProfilerRS> NP("insert-null-profiling-rs",
- "Measure profiling framework overhead");
- static RegisterAnalysisGroup<RSProfilers, true> NPT(NP);
+static RegisterAnalysisGroup<RSProfilers> A("Profiling passes");
+static RegisterPass<NullProfilerRS> NP("insert-null-profiling-rs",
+ "Measure profiling framework overhead");
+static RegisterAnalysisGroup<RSProfilers, true> NPT(NP);
+namespace {
/// Chooser - Something that chooses when to make a sample of the profiled code
- class Chooser {
+ class VISIBILITY_HIDDEN Chooser {
public:
/// ProcessChoicePoint - is called for each basic block inserted to choose
/// between normal and sample code
//Things that implement sampling policies
//A global value that is read-mod-stored to choose when to sample.
//A sample is taken when the global counter hits 0
- class GlobalRandomCounter : public Chooser {
+ class VISIBILITY_HIDDEN GlobalRandomCounter : public Chooser {
GlobalVariable* Counter;
Value* ResetValue;
- const Type* T;
+ const IntegerType* T;
public:
- GlobalRandomCounter(Module& M, const Type* t, uint64_t resetval);
+ GlobalRandomCounter(Module& M, const IntegerType* t, uint64_t resetval);
virtual ~GlobalRandomCounter();
virtual void PrepFunction(Function* F);
virtual void ProcessChoicePoint(BasicBlock* bb);
};
//Same is GRC, but allow register allocation of the global counter
- class GlobalRandomCounterOpt : public Chooser {
+ class VISIBILITY_HIDDEN GlobalRandomCounterOpt : public Chooser {
GlobalVariable* Counter;
Value* ResetValue;
AllocaInst* AI;
- const Type* T;
+ const IntegerType* T;
public:
- GlobalRandomCounterOpt(Module& M, const Type* t, uint64_t resetval);
+ GlobalRandomCounterOpt(Module& M, const IntegerType* t, uint64_t resetval);
virtual ~GlobalRandomCounterOpt();
virtual void PrepFunction(Function* F);
virtual void ProcessChoicePoint(BasicBlock* bb);
//Use the cycle counter intrinsic as a source of pseudo randomness when
//deciding when to sample.
- class CycleCounter : public Chooser {
+ class VISIBILITY_HIDDEN CycleCounter : public Chooser {
uint64_t rm;
- Function* F;
+ Constant *F;
public:
CycleCounter(Module& m, uint64_t resetmask);
virtual ~CycleCounter();
};
/// ProfilerRS - Insert the random sampling framework
- struct ProfilerRS : public FunctionPass {
+ struct VISIBILITY_HIDDEN ProfilerRS : public FunctionPass {
+ static char ID; // Pass identification, replacement for typeid
+ ProfilerRS() : FunctionPass(&ID) {}
+
std::map<Value*, Value*> TransCache;
std::set<BasicBlock*> ChoicePoints;
Chooser* c;
bool doInitialization(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
};
-
- RegisterPass<ProfilerRS> X("insert-rs-profiling-framework",
- "Insert random sampling instrumentation framework");
}
+static RegisterPass<ProfilerRS>
+X("insert-rs-profiling-framework",
+ "Insert random sampling instrumentation framework");
+
+char RSProfilers::ID = 0;
+char NullProfilerRS::ID = 0;
+char ProfilerRS::ID = 0;
+
//Local utilities
static void ReplacePhiPred(BasicBlock* btarget,
BasicBlock* bold, BasicBlock* bnew);
// Methods of choosing when to profile
///////////////////////////////////////
-GlobalRandomCounter::GlobalRandomCounter(Module& M, const Type* t,
+GlobalRandomCounter::GlobalRandomCounter(Module& M, const IntegerType* t,
uint64_t resetval) : T(t) {
ConstantInt* Init = ConstantInt::get(T, resetval);
ResetValue = Init;
//decrement counter
LoadInst* l = new LoadInst(Counter, "counter", t);
- SetCondInst* s = new SetCondInst(Instruction::SetEQ, l,
- ConstantInt::get(T, 0),
- "countercc", t);
- Value* nv = BinaryOperator::createSub(l, ConstantInt::get(T, 1),
- "counternew", t);
+ ICmpInst* s = new ICmpInst(ICmpInst::ICMP_EQ, l, ConstantInt::get(T, 0),
+ "countercc", t);
+
+ Value* nv = BinaryOperator::CreateSub(l, ConstantInt::get(T, 1),
+ "counternew", t);
new StoreInst(nv, Counter, t);
t->setCondition(s);
//reset counter
BasicBlock* oldnext = t->getSuccessor(0);
- BasicBlock* resetblock = new BasicBlock("reset", oldnext->getParent(),
- oldnext);
- TerminatorInst* t2 = new BranchInst(oldnext, resetblock);
+ BasicBlock* resetblock = BasicBlock::Create("reset", oldnext->getParent(),
+ oldnext);
+ TerminatorInst* t2 = BranchInst::Create(oldnext, resetblock);
t->setSuccessor(0, resetblock);
new StoreInst(ResetValue, Counter, t2);
ReplacePhiPred(oldnext, bb, resetblock);
}
-GlobalRandomCounterOpt::GlobalRandomCounterOpt(Module& M, const Type* t,
+GlobalRandomCounterOpt::GlobalRandomCounterOpt(Module& M, const IntegerType* t,
uint64_t resetval)
: AI(0), T(t) {
ConstantInt* Init = ConstantInt::get(T, resetval);
void GlobalRandomCounterOpt::PrepFunction(Function* F) {
//make a local temporary to cache the global
BasicBlock& bb = F->getEntryBlock();
- AI = new AllocaInst(T, 0, "localcounter", bb.begin());
- LoadInst* l = new LoadInst(Counter, "counterload", AI->getNext());
- new StoreInst(l, AI, l->getNext());
+ BasicBlock::iterator InsertPt = bb.begin();
+ AI = new AllocaInst(T, 0, "localcounter", InsertPt);
+ LoadInst* l = new LoadInst(Counter, "counterload", InsertPt);
+ new StoreInst(l, AI, InsertPt);
//modify all functions and return values to restore the local variable to/from
//the global variable
fib != fie; ++fib)
for(BasicBlock::iterator bib = fib->begin(), bie = fib->end();
bib != bie; ++bib)
- if (isa<CallInst>(&*bib)) {
+ if (isa<CallInst>(bib)) {
LoadInst* l = new LoadInst(AI, "counter", bib);
new StoreInst(l, Counter, bib);
- l = new LoadInst(Counter, "counter", bib->getNext());
- new StoreInst(l, AI, l->getNext());
- } else if (isa<InvokeInst>(&*bib)) {
+ l = new LoadInst(Counter, "counter", ++bib);
+ new StoreInst(l, AI, bib--);
+ } else if (isa<InvokeInst>(bib)) {
LoadInst* l = new LoadInst(AI, "counter", bib);
new StoreInst(l, Counter, bib);
- BasicBlock* bb = cast<InvokeInst>(&*bib)->getNormalDest();
- Instruction* i = bb->begin();
- while (isa<PHINode>(i)) i = i->getNext();
+ BasicBlock* bb = cast<InvokeInst>(bib)->getNormalDest();
+ BasicBlock::iterator i = bb->getFirstNonPHI();
l = new LoadInst(Counter, "counter", i);
- bb = cast<InvokeInst>(&*bib)->getUnwindDest();
- i = bb->begin();
- while (isa<PHINode>(i)) i = i->getNext();
+ bb = cast<InvokeInst>(bib)->getUnwindDest();
+ i = bb->getFirstNonPHI();
l = new LoadInst(Counter, "counter", i);
- new StoreInst(l, AI, l->getNext());
+ new StoreInst(l, AI, i);
} else if (isa<UnwindInst>(&*bib) || isa<ReturnInst>(&*bib)) {
LoadInst* l = new LoadInst(AI, "counter", bib);
new StoreInst(l, Counter, bib);
//decrement counter
LoadInst* l = new LoadInst(AI, "counter", t);
- SetCondInst* s = new SetCondInst(Instruction::SetEQ, l,
- ConstantInt::get(T, 0),
- "countercc", t);
- Value* nv = BinaryOperator::createSub(l, ConstantInt::get(T, 1),
- "counternew", t);
+ ICmpInst* s = new ICmpInst(ICmpInst::ICMP_EQ, l, ConstantInt::get(T, 0),
+ "countercc", t);
+
+ Value* nv = BinaryOperator::CreateSub(l, ConstantInt::get(T, 1),
+ "counternew", t);
new StoreInst(nv, AI, t);
t->setCondition(s);
//reset counter
BasicBlock* oldnext = t->getSuccessor(0);
- BasicBlock* resetblock = new BasicBlock("reset", oldnext->getParent(),
- oldnext);
- TerminatorInst* t2 = new BranchInst(oldnext, resetblock);
+ BasicBlock* resetblock = BasicBlock::Create("reset", oldnext->getParent(),
+ oldnext);
+ TerminatorInst* t2 = BranchInst::Create(oldnext, resetblock);
t->setSuccessor(0, resetblock);
new StoreInst(ResetValue, AI, t2);
ReplacePhiPred(oldnext, bb, resetblock);
CycleCounter::CycleCounter(Module& m, uint64_t resetmask) : rm(resetmask) {
- F = m.getOrInsertFunction("llvm.readcyclecounter", Type::ULongTy, NULL);
+ F = Intrinsic::getDeclaration(&m, Intrinsic::readcyclecounter);
}
CycleCounter::~CycleCounter() {}
void CycleCounter::ProcessChoicePoint(BasicBlock* bb) {
BranchInst* t = cast<BranchInst>(bb->getTerminator());
- CallInst* c = new CallInst(F, "rdcc", t);
+ CallInst* c = CallInst::Create(F, "rdcc", t);
BinaryOperator* b =
- BinaryOperator::createAnd(c, ConstantInt::get(Type::ULongTy, rm),
- "mrdcc", t);
+ BinaryOperator::CreateAnd(c, ConstantInt::get(Type::Int64Ty, rm),
+ "mrdcc", t);
- SetCondInst* s = new SetCondInst(Instruction::SetEQ, b,
- ConstantInt::get(Type::ULongTy, 0),
- "mrdccc", t);
+ ICmpInst *s = new ICmpInst(ICmpInst::ICMP_EQ, b,
+ ConstantInt::get(Type::Int64Ty, 0),
+ "mrdccc", t);
+
t->setCondition(s);
}
void RSProfilers_std::IncrementCounterInBlock(BasicBlock *BB, unsigned CounterNum,
GlobalValue *CounterArray) {
// Insert the increment after any alloca or PHI instructions...
- BasicBlock::iterator InsertPos = BB->begin();
- while (isa<AllocaInst>(InsertPos) || isa<PHINode>(InsertPos))
+ BasicBlock::iterator InsertPos = BB->getFirstNonPHI();
+ while (isa<AllocaInst>(InsertPos))
++InsertPos;
// Create the getelementptr constant expression
std::vector<Constant*> Indices(2);
- Indices[0] = Constant::getNullValue(Type::IntTy);
- Indices[1] = ConstantInt::get(Type::IntTy, CounterNum);
- Constant *ElementPtr = ConstantExpr::getGetElementPtr(CounterArray, Indices);
+ Indices[0] = Constant::getNullValue(Type::Int32Ty);
+ Indices[1] = ConstantInt::get(Type::Int32Ty, CounterNum);
+ Constant *ElementPtr = ConstantExpr::getGetElementPtr(CounterArray,
+ &Indices[0], 2);
// Load, increment and store the value back.
Value *OldVal = new LoadInst(ElementPtr, "OldCounter", InsertPos);
profcode.insert(OldVal);
- Value *NewVal = BinaryOperator::createAdd(OldVal,
- ConstantInt::get(Type::UIntTy, 1),
- "NewCounter", InsertPos);
+ Value *NewVal = BinaryOperator::CreateAdd(OldVal,
+ ConstantInt::get(Type::Int32Ty, 1),
+ "NewCounter", InsertPos);
profcode.insert(NewVal);
profcode.insert(new StoreInst(NewVal, ElementPtr, InsertPos));
}
if (bb == &bb->getParent()->getEntryBlock())
TransCache[bb] = bb; //don't translate entry block
else
- TransCache[bb] = new BasicBlock("dup_" + bb->getName(), bb->getParent(),
- NULL);
+ TransCache[bb] = BasicBlock::Create("dup_" + bb->getName(),
+ bb->getParent(), NULL);
return TransCache[bb];
} else if (Instruction* i = dyn_cast<Instruction>(v)) {
//we have already translated this
// add in edge from C using x in A'
//a:
- BasicBlock* bbC = new BasicBlock("choice", &F, src->getNext() );
+ Function::iterator BBN = src; ++BBN;
+ BasicBlock* bbC = BasicBlock::Create("choice", &F, BBN);
//ChoicePoints.insert(bbC);
- BasicBlock* bbCp =
- new BasicBlock("choice", &F, cast<BasicBlock>(Translate(src))->getNext() );
+ BBN = cast<BasicBlock>(Translate(src));
+ BasicBlock* bbCp = BasicBlock::Create("choice", &F, ++BBN);
ChoicePoints.insert(bbCp);
//b:
- new BranchInst(cast<BasicBlock>(Translate(dst)), bbC);
- new BranchInst(dst, cast<BasicBlock>(Translate(dst)),
- ConstantBool::get(true), bbCp);
+ BranchInst::Create(cast<BasicBlock>(Translate(dst)), bbC);
+ BranchInst::Create(dst, cast<BasicBlock>(Translate(dst)),
+ ConstantInt::get(Type::Int1Ty, true), bbCp);
//c:
{
TerminatorInst* iB = src->getTerminator();
CollapsePhi(dst, bbC);
//f:
ReplacePhiPred(cast<BasicBlock>(Translate(dst)),
- cast<BasicBlock>(Translate(src)),bbCp);
+ cast<BasicBlock>(Translate(src)),bbCp);
CollapsePhi(cast<BasicBlock>(Translate(dst)), bbCp);
//g:
for(BasicBlock::iterator ib = dst->begin(), ie = dst->end(); ib != ie;
if(bbC == phi->getIncomingBlock(x)) {
phi->addIncoming(Translate(phi->getIncomingValue(x)), bbCp);
cast<PHINode>(Translate(phi))->addIncoming(phi->getIncomingValue(x),
- bbC);
+ bbC);
}
phi->removeIncomingValue(bbC);
}
}
bool ProfilerRS::runOnFunction(Function& F) {
- if (!F.isExternal()) {
+ if (!F.isDeclaration()) {
std::set<std::pair<BasicBlock*, BasicBlock*> > BackEdges;
RSProfilers& LI = getAnalysis<RSProfilers>();
//assume that stuff worked. now connect the duplicated basic blocks
//with the originals in such a way as to preserve ssa. yuk!
for (std::set<std::pair<BasicBlock*, BasicBlock*> >::iterator
- ib = BackEdges.begin(), ie = BackEdges.end(); ib != ie; ++ib)
+ ib = BackEdges.begin(), ie = BackEdges.end(); ib != ie; ++ib)
ProcessBackEdge(ib->first, ib->second, F);
//oh, and add the edge from the reg2mem created entry node to the
//duplicated second node
TerminatorInst* T = F.getEntryBlock().getTerminator();
- ReplaceInstWithInst(T, new BranchInst(T->getSuccessor(0),
- cast<BasicBlock>(Translate(T->getSuccessor(0))),
- ConstantBool::get(true)));
+ ReplaceInstWithInst(T, BranchInst::Create(T->getSuccessor(0),
+ cast<BasicBlock>(
+ Translate(T->getSuccessor(0))),
+ ConstantInt::get(Type::Int1Ty,
+ true)));
//do whatever is needed now that the function is duplicated
c->PrepFunction(&F);
ChoicePoints.insert(&F.getEntryBlock());
for (std::set<BasicBlock*>::iterator
- ii = ChoicePoints.begin(), ie = ChoicePoints.end(); ii != ie; ++ii)
+ ii = ChoicePoints.begin(), ie = ChoicePoints.end(); ii != ie; ++ii)
c->ProcessChoicePoint(*ii);
ChoicePoints.clear();
bool ProfilerRS::doInitialization(Module &M) {
switch (RandomMethod) {
case GBV:
- c = new GlobalRandomCounter(M, Type::UIntTy, (1 << 14) - 1);
+ c = new GlobalRandomCounter(M, Type::Int32Ty, (1 << 14) - 1);
break;
case GBVO:
- c = new GlobalRandomCounterOpt(M, Type::UIntTy, (1 << 14) - 1);
+ c = new GlobalRandomCounterOpt(M, Type::Int32Ty, (1 << 14) - 1);
break;
case HOSTCC:
c = new CycleCounter(M, (1 << 14) - 1);