aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-05-25 23:55:00 +0000
committerBill Wendling <isanbard@gmail.com>2012-05-25 23:55:00 +0000
commitc7a884040e4ec7795515978a94803894ad08c4ca (patch)
tree0c9689fd8c604156dfdd31fd850469bc76c84e36 /lib
parent3ad21bef923159491ebf98024b4d066b1c30eeb4 (diff)
The llvm_gcda_increment_indirect_counter function writes to the arguments that
are passed in. However, those arguments may be in a write-protected area, as far as the runtime library is concerned. For instance, the data could be placed into a 'linkedit' section, which isn't writable. Emit the code from llvm_gcda_increment_indirect_counter directly into the function instead. Note: The code for this is ugly, and can lead to bloat. We should look into simplifying this code instead of having all of these branches. <rdar://problem/11181370> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157505 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/Instrumentation/GCOVProfiling.cpp74
1 files changed, 57 insertions, 17 deletions
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index 96e5d5b311..1b0cc00bce 100644
--- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -70,7 +70,9 @@ namespace {
// Get pointers to the functions in the runtime library.
Constant *getStartFileFunc();
- Constant *getIncrementIndirectCounterFunc();
+ void incrementIndirectCounter(IRBuilder<> &Builder, BasicBlock *Exit,
+ GlobalVariable *EdgeState,
+ Value *CounterPtrArray);
Constant *getEmitFunctionFunc();
Constant *getEmitArcsFunc();
Constant *getEndFileFunc();
@@ -501,16 +503,17 @@ bool GCOVProfiler::emitProfileArcs() {
}
for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) {
// call runtime to perform increment
- BasicBlock::iterator InsertPt =
- ComplexEdgeSuccs[i+1]->getFirstInsertionPt();
+ BasicBlock *BB = ComplexEdgeSuccs[i+1];
+ BasicBlock::iterator InsertPt = BB->getFirstInsertionPt();
+ BasicBlock *Split = BB->splitBasicBlock(InsertPt);
+ InsertPt = BB->getFirstInsertionPt();
IRBuilder<> Builder(InsertPt);
Value *CounterPtrArray =
Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0,
i * ComplexEdgePreds.size());
- Builder.CreateCall2(getIncrementIndirectCounterFunc(),
- EdgeState, CounterPtrArray);
- // clear the predecessor number
- Builder.CreateStore(ConstantInt::get(Int32Ty, 0xffffffff), EdgeState);
+
+ // Build code to increment the counter.
+ incrementIndirectCounter(Builder, Split, EdgeState, CounterPtrArray);
}
}
}
@@ -573,14 +576,52 @@ Constant *GCOVProfiler::getStartFileFunc() {
return M->getOrInsertFunction("llvm_gcda_start_file", FTy);
}
-Constant *GCOVProfiler::getIncrementIndirectCounterFunc() {
- Type *Args[] = {
- Type::getInt32PtrTy(*Ctx), // uint32_t *predecessor
- Type::getInt64PtrTy(*Ctx)->getPointerTo(), // uint64_t **state_table_row
- };
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
- Args, false);
- return M->getOrInsertFunction("llvm_gcda_increment_indirect_counter", FTy);
+/// incrementIndirectCounter - Emit code that increments the indirect
+/// counter. The code is meant to copy the llvm_gcda_increment_indirect_counter
+/// 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);
+ ConstantInt *NegOne = ConstantInt::get(Type::getInt32Ty(*Ctx), 0xffffffff);
+
+ // Create exiting blocks.
+ BasicBlock *InsBB = Builder.GetInsertBlock();
+ Function *Fn = InsBB->getParent();
+ BasicBlock *PredNotNegOne = BasicBlock::Create(*Ctx, "", Fn, Exit);
+ 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() {
@@ -588,8 +629,7 @@ Constant *GCOVProfiler::getEmitFunctionFunc() {
Type::getInt32Ty(*Ctx), // uint32_t ident
Type::getInt8PtrTy(*Ctx), // const char *function_name
};
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
- Args, false);
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), Args, false);
return M->getOrInsertFunction("llvm_gcda_emit_function", FTy);
}