Implement the indirect counter increment code in a better way. Instead of
replicating the code for every place it's needed, we instead generate a function that does that for us. This function is local to the executable, so there shouldn't be any writing violations. llvm-svn: 157564
This commit is contained in:
parent
2137c928b0
commit
1560517ec3
|
@ -70,9 +70,7 @@ namespace {
|
||||||
|
|
||||||
// Get pointers to the functions in the runtime library.
|
// Get pointers to the functions in the runtime library.
|
||||||
Constant *getStartFileFunc();
|
Constant *getStartFileFunc();
|
||||||
void incrementIndirectCounter(IRBuilder<> &Builder, BasicBlock *Exit,
|
Constant *getIncrementIndirectCounterFunc();
|
||||||
GlobalVariable *EdgeState,
|
|
||||||
Value *CounterPtrArray);
|
|
||||||
Constant *getEmitFunctionFunc();
|
Constant *getEmitFunctionFunc();
|
||||||
Constant *getEmitArcsFunc();
|
Constant *getEmitArcsFunc();
|
||||||
Constant *getEndFileFunc();
|
Constant *getEndFileFunc();
|
||||||
|
@ -92,6 +90,7 @@ namespace {
|
||||||
// list.
|
// list.
|
||||||
void insertCounterWriteout(SmallVector<std::pair<GlobalVariable *,
|
void insertCounterWriteout(SmallVector<std::pair<GlobalVariable *,
|
||||||
MDNode *>, 8> &);
|
MDNode *>, 8> &);
|
||||||
|
void insertIndirectCounterIncrement();
|
||||||
|
|
||||||
std::string mangleName(DICompileUnit CU, std::string NewStem);
|
std::string mangleName(DICompileUnit CU, std::string NewStem);
|
||||||
|
|
||||||
|
@ -423,6 +422,7 @@ bool GCOVProfiler::emitProfileArcs() {
|
||||||
if (!CU_Nodes) return false;
|
if (!CU_Nodes) return false;
|
||||||
|
|
||||||
bool Result = false;
|
bool Result = false;
|
||||||
|
bool InsertIndCounterIncrCode = false;
|
||||||
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
|
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
|
||||||
DICompileUnit CU(CU_Nodes->getOperand(i));
|
DICompileUnit CU(CU_Nodes->getOperand(i));
|
||||||
DIArray SPs = CU.getSubprograms();
|
DIArray SPs = CU.getSubprograms();
|
||||||
|
@ -503,22 +503,26 @@ bool GCOVProfiler::emitProfileArcs() {
|
||||||
}
|
}
|
||||||
for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
|
for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
|
||||||
// call runtime to perform increment
|
// call runtime to perform increment
|
||||||
BasicBlock *BB = ComplexEdgeSuccs[i+1];
|
BasicBlock::iterator InsertPt =
|
||||||
BasicBlock::iterator InsertPt = BB->getFirstInsertionPt();
|
ComplexEdgeSuccs[i+1]->getFirstInsertionPt();
|
||||||
BasicBlock *Split = BB->splitBasicBlock(InsertPt);
|
|
||||||
InsertPt = BB->getFirstInsertionPt();
|
|
||||||
IRBuilder<> Builder(InsertPt);
|
IRBuilder<> Builder(InsertPt);
|
||||||
Value *CounterPtrArray =
|
Value *CounterPtrArray =
|
||||||
Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
|
Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
|
||||||
i * ComplexEdgePreds.size());
|
i * ComplexEdgePreds.size());
|
||||||
|
|
||||||
// Build code to increment the counter.
|
// Build code to increment the counter.
|
||||||
incrementIndirectCounter(Builder, Split, EdgeState, CounterPtrArray);
|
InsertIndCounterIncrCode = true;
|
||||||
|
Builder.CreateCall2(getIncrementIndirectCounterFunc(),
|
||||||
|
EdgeState, CounterPtrArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
insertCounterWriteout(CountersBySP);
|
insertCounterWriteout(CountersBySP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (InsertIndCounterIncrCode)
|
||||||
|
insertIndirectCounterIncrement();
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,52 +580,15 @@ Constant *GCOVProfiler::getStartFileFunc() {
|
||||||
return M->getOrInsertFunction("llvm_gcda_start_file", FTy);
|
return M->getOrInsertFunction("llvm_gcda_start_file", FTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// incrementIndirectCounter - Emit code that increments the indirect
|
Constant *GCOVProfiler::getIncrementIndirectCounterFunc() {
|
||||||
/// counter. The code is meant to copy the llvm_gcda_increment_indirect_counter
|
Type *Int32Ty = Type::getInt32Ty(*Ctx);
|
||||||
/// function, but because it's inlined into the function, we don't have to worry
|
|
||||||
/// about the runtime library possibly writing into a protected area.
|
|
||||||
void GCOVProfiler::incrementIndirectCounter(IRBuilder<> &Builder,
|
|
||||||
BasicBlock *Exit,
|
|
||||||
GlobalVariable *EdgeState,
|
|
||||||
Value *CounterPtrArray) {
|
|
||||||
Type *Int64Ty = Type::getInt64Ty(*Ctx);
|
Type *Int64Ty = Type::getInt64Ty(*Ctx);
|
||||||
ConstantInt *NegOne = ConstantInt::get(Type::getInt32Ty(*Ctx), 0xffffffff);
|
Type *Args[] = {
|
||||||
|
Int32Ty->getPointerTo(), // uint32_t *predecessor
|
||||||
// Create exiting blocks.
|
Int64Ty->getPointerTo()->getPointerTo() // uint64_t **counters
|
||||||
BasicBlock *InsBB = Builder.GetInsertBlock();
|
};
|
||||||
Function *Fn = InsBB->getParent();
|
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
|
||||||
BasicBlock *PredNotNegOne = BasicBlock::Create(*Ctx, "", Fn, Exit);
|
return M->getOrInsertFunction("__llvm_gcov_indirect_counter_increment", FTy);
|
||||||
BasicBlock *CounterEnd = BasicBlock::Create(*Ctx, "", Fn, Exit);
|
|
||||||
|
|
||||||
// uint32_t pred = *EdgeState;
|
|
||||||
// if (pred == 0xffffffff) return;
|
|
||||||
Value *Pred = Builder.CreateLoad(EdgeState, "predecessor");
|
|
||||||
Value *Cond = Builder.CreateICmpEQ(Pred, NegOne);
|
|
||||||
InsBB->getTerminator()->eraseFromParent();
|
|
||||||
BranchInst::Create(Exit, PredNotNegOne, Cond, InsBB);
|
|
||||||
|
|
||||||
Builder.SetInsertPoint(PredNotNegOne);
|
|
||||||
|
|
||||||
// uint64_t *counter = CounterPtrArray[pred];
|
|
||||||
// if (!counter) return;
|
|
||||||
Value *ZExtPred = Builder.CreateZExt(Pred, Int64Ty);
|
|
||||||
Value *GEP = Builder.CreateGEP(CounterPtrArray, ZExtPred);
|
|
||||||
Value *Counter = Builder.CreateLoad(GEP, "counter");
|
|
||||||
Cond = Builder.CreateICmpEQ(Counter,
|
|
||||||
Constant::getNullValue(Type::getInt64PtrTy(*Ctx, 0)));
|
|
||||||
Builder.CreateCondBr(Cond, Exit, CounterEnd);
|
|
||||||
|
|
||||||
Builder.SetInsertPoint(CounterEnd);
|
|
||||||
|
|
||||||
// ++*counter;
|
|
||||||
Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter),
|
|
||||||
ConstantInt::get(Int64Ty, 1));
|
|
||||||
Builder.CreateStore(Add, Counter);
|
|
||||||
Builder.CreateBr(Exit);
|
|
||||||
|
|
||||||
// Clear the predecessor number
|
|
||||||
Builder.SetInsertPoint(Exit->getFirstInsertionPt());
|
|
||||||
Builder.CreateStore(NegOne, EdgeState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Constant *GCOVProfiler::getEmitFunctionFunc() {
|
Constant *GCOVProfiler::getEmitFunctionFunc() {
|
||||||
|
@ -707,3 +674,55 @@ void GCOVProfiler::insertCounterWriteout(
|
||||||
|
|
||||||
InsertProfilingShutdownCall(WriteoutF, M);
|
InsertProfilingShutdownCall(WriteoutF, M);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GCOVProfiler::insertIndirectCounterIncrement() {
|
||||||
|
Function *Fn =
|
||||||
|
cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
|
||||||
|
Fn->setUnnamedAddr(true);
|
||||||
|
Fn->setLinkage(GlobalValue::InternalLinkage);
|
||||||
|
Fn->addFnAttr(Attribute::NoInline);
|
||||||
|
|
||||||
|
Type *Int32Ty = Type::getInt32Ty(*Ctx);
|
||||||
|
Type *Int64Ty = Type::getInt64Ty(*Ctx);
|
||||||
|
Constant *NegOne = ConstantInt::get(Int32Ty, 0xffffffff);
|
||||||
|
|
||||||
|
// Create basic blocks for function.
|
||||||
|
BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", Fn);
|
||||||
|
IRBuilder<> Builder(BB);
|
||||||
|
|
||||||
|
BasicBlock *PredNotNegOne = BasicBlock::Create(*Ctx, "", Fn);
|
||||||
|
BasicBlock *CounterEnd = BasicBlock::Create(*Ctx, "", Fn);
|
||||||
|
BasicBlock *Exit = BasicBlock::Create(*Ctx, "exit", Fn);
|
||||||
|
|
||||||
|
// uint32_t pred = *predecessor;
|
||||||
|
// if (pred == 0xffffffff) return;
|
||||||
|
Argument *Arg = Fn->arg_begin();
|
||||||
|
Arg->setName("predecessor");
|
||||||
|
Value *Pred = Builder.CreateLoad(Arg, "pred");
|
||||||
|
Value *Cond = Builder.CreateICmpEQ(Pred, NegOne);
|
||||||
|
BranchInst::Create(Exit, PredNotNegOne, Cond, BB);
|
||||||
|
|
||||||
|
Builder.SetInsertPoint(PredNotNegOne);
|
||||||
|
|
||||||
|
// uint64_t *counter = counters[pred];
|
||||||
|
// if (!counter) return;
|
||||||
|
Value *ZExtPred = Builder.CreateZExt(Pred, Int64Ty);
|
||||||
|
Arg = llvm::next(Fn->arg_begin());
|
||||||
|
Arg->setName("counters");
|
||||||
|
Value *GEP = Builder.CreateGEP(Arg, ZExtPred);
|
||||||
|
Value *Counter = Builder.CreateLoad(GEP, "counter");
|
||||||
|
Cond = Builder.CreateICmpEQ(Counter,
|
||||||
|
Constant::getNullValue(Int64Ty->getPointerTo()));
|
||||||
|
Builder.CreateCondBr(Cond, Exit, CounterEnd);
|
||||||
|
|
||||||
|
// ++*counter;
|
||||||
|
Builder.SetInsertPoint(CounterEnd);
|
||||||
|
Value *Add = Builder.CreateAdd(Builder.CreateLoad(Counter),
|
||||||
|
ConstantInt::get(Int64Ty, 1));
|
||||||
|
Builder.CreateStore(Add, Counter);
|
||||||
|
Builder.CreateBr(Exit);
|
||||||
|
|
||||||
|
// Fill in the exit block.
|
||||||
|
Builder.SetInsertPoint(Exit);
|
||||||
|
Builder.CreateRetVoid();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue