aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp')
-rw-r--r--llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp106
1 files changed, 97 insertions, 9 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
index c0409206216e..a7b1953ce81c 100644
--- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -16,7 +16,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
@@ -47,6 +46,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"
#include <algorithm>
@@ -421,6 +421,9 @@ bool InstrProfiling::lowerIntrinsics(Function *F) {
} else if (auto *IPI = dyn_cast<InstrProfIncrementInst>(&Instr)) {
lowerIncrement(IPI);
MadeChange = true;
+ } else if (auto *IPC = dyn_cast<InstrProfTimestampInst>(&Instr)) {
+ lowerTimestamp(IPC);
+ MadeChange = true;
} else if (auto *IPC = dyn_cast<InstrProfCoverInst>(&Instr)) {
lowerCover(IPC);
MadeChange = true;
@@ -510,6 +513,7 @@ static bool containsProfilingIntrinsics(Module &M) {
return containsIntrinsic(llvm::Intrinsic::instrprof_cover) ||
containsIntrinsic(llvm::Intrinsic::instrprof_increment) ||
containsIntrinsic(llvm::Intrinsic::instrprof_increment_step) ||
+ containsIntrinsic(llvm::Intrinsic::instrprof_timestamp) ||
containsIntrinsic(llvm::Intrinsic::instrprof_value_profile);
}
@@ -540,18 +544,19 @@ bool InstrProfiling::run(
// the instrumented function. This is counting the number of instrumented
// target value sites to enter it as field in the profile data variable.
for (Function &F : M) {
- InstrProfIncrementInst *FirstProfIncInst = nullptr;
+ InstrProfInstBase *FirstProfInst = nullptr;
for (BasicBlock &BB : F)
for (auto I = BB.begin(), E = BB.end(); I != E; I++)
if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(I))
computeNumValueSiteCounts(Ind);
- else if (FirstProfIncInst == nullptr)
- FirstProfIncInst = dyn_cast<InstrProfIncrementInst>(I);
+ else if (FirstProfInst == nullptr &&
+ (isa<InstrProfIncrementInst>(I) || isa<InstrProfCoverInst>(I)))
+ FirstProfInst = dyn_cast<InstrProfInstBase>(I);
// Value profiling intrinsic lowering requires per-function profile data
// variable to be created first.
- if (FirstProfIncInst != nullptr)
- static_cast<void>(getOrCreateRegionCounters(FirstProfIncInst));
+ if (FirstProfInst != nullptr)
+ static_cast<void>(getOrCreateRegionCounters(FirstProfInst));
}
for (Function &F : M)
@@ -669,6 +674,9 @@ Value *InstrProfiling::getCounterAddress(InstrProfInstBase *I) {
auto *Counters = getOrCreateRegionCounters(I);
IRBuilder<> Builder(I);
+ if (isa<InstrProfTimestampInst>(I))
+ Counters->setAlignment(Align(8));
+
auto *Addr = Builder.CreateConstInBoundsGEP2_32(
Counters->getValueType(), Counters, 0, I->getIndex()->getZExtValue());
@@ -710,6 +718,21 @@ void InstrProfiling::lowerCover(InstrProfCoverInst *CoverInstruction) {
CoverInstruction->eraseFromParent();
}
+void InstrProfiling::lowerTimestamp(
+ InstrProfTimestampInst *TimestampInstruction) {
+ assert(TimestampInstruction->getIndex()->isZeroValue() &&
+ "timestamp probes are always the first probe for a function");
+ auto &Ctx = M->getContext();
+ auto *TimestampAddr = getCounterAddress(TimestampInstruction);
+ IRBuilder<> Builder(TimestampInstruction);
+ auto *CalleeTy =
+ FunctionType::get(Type::getVoidTy(Ctx), TimestampAddr->getType(), false);
+ auto Callee = M->getOrInsertFunction(
+ INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_SET_TIMESTAMP), CalleeTy);
+ Builder.CreateCall(Callee, {TimestampAddr});
+ TimestampInstruction->eraseFromParent();
+}
+
void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) {
auto *Addr = getCounterAddress(Inc);
@@ -823,6 +846,72 @@ static inline bool shouldRecordFunctionAddr(Function *F) {
return F->hasAddressTaken() || F->hasLinkOnceLinkage();
}
+static inline bool shouldUsePublicSymbol(Function *Fn) {
+ // It isn't legal to make an alias of this function at all
+ if (Fn->isDeclarationForLinker())
+ return true;
+
+ // Symbols with local linkage can just use the symbol directly without
+ // introducing relocations
+ if (Fn->hasLocalLinkage())
+ return true;
+
+ // PGO + ThinLTO + CFI cause duplicate symbols to be introduced due to some
+ // unfavorable interaction between the new alias and the alias renaming done
+ // in LowerTypeTests under ThinLTO. For comdat functions that would normally
+ // be deduplicated, but the renaming scheme ends up preventing renaming, since
+ // it creates unique names for each alias, resulting in duplicated symbols. In
+ // the future, we should update the CFI related passes to migrate these
+ // aliases to the same module as the jump-table they refer to will be defined.
+ if (Fn->hasMetadata(LLVMContext::MD_type))
+ return true;
+
+ // For comdat functions, an alias would need the same linkage as the original
+ // function and hidden visibility. There is no point in adding an alias with
+ // identical linkage an visibility to avoid introducing symbolic relocations.
+ if (Fn->hasComdat() &&
+ (Fn->getVisibility() == GlobalValue::VisibilityTypes::HiddenVisibility))
+ return true;
+
+ // its OK to use an alias
+ return false;
+}
+
+static inline Constant *getFuncAddrForProfData(Function *Fn) {
+ auto *Int8PtrTy = Type::getInt8PtrTy(Fn->getContext());
+ // Store a nullptr in __llvm_profd, if we shouldn't use a real address
+ if (!shouldRecordFunctionAddr(Fn))
+ return ConstantPointerNull::get(Int8PtrTy);
+
+ // If we can't use an alias, we must use the public symbol, even though this
+ // may require a symbolic relocation.
+ if (shouldUsePublicSymbol(Fn))
+ return ConstantExpr::getBitCast(Fn, Int8PtrTy);
+
+ // When possible use a private alias to avoid symbolic relocations.
+ auto *GA = GlobalAlias::create(GlobalValue::LinkageTypes::PrivateLinkage,
+ Fn->getName() + ".local", Fn);
+
+ // When the instrumented function is a COMDAT function, we cannot use a
+ // private alias. If we did, we would create reference to a local label in
+ // this function's section. If this version of the function isn't selected by
+ // the linker, then the metadata would introduce a reference to a discarded
+ // section. So, for COMDAT functions, we need to adjust the linkage of the
+ // alias. Using hidden visibility avoids a dynamic relocation and an entry in
+ // the dynamic symbol table.
+ //
+ // Note that this handles COMDAT functions with visibility other than Hidden,
+ // since that case is covered in shouldUsePublicSymbol()
+ if (Fn->hasComdat()) {
+ GA->setLinkage(Fn->getLinkage());
+ GA->setVisibility(GlobalValue::VisibilityTypes::HiddenVisibility);
+ }
+
+ // appendToCompilerUsed(*Fn->getParent(), {GA});
+
+ return ConstantExpr::getBitCast(GA, Int8PtrTy);
+}
+
static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) {
// Don't do this for Darwin. compiler-rt uses linker magic.
if (TT.isOSDarwin())
@@ -1014,9 +1103,7 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfInstBase *Inc) {
};
auto *DataTy = StructType::get(Ctx, ArrayRef(DataTypes));
- Constant *FunctionAddr = shouldRecordFunctionAddr(Fn)
- ? ConstantExpr::getBitCast(Fn, Int8PtrTy)
- : ConstantPointerNull::get(Int8PtrTy);
+ Constant *FunctionAddr = getFuncAddrForProfData(Fn);
Constant *Int16ArrayVals[IPVK_Last + 1];
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
@@ -1116,6 +1203,7 @@ void InstrProfiling::emitVNodes() {
Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName());
VNodesVar->setSection(
getInstrProfSectionName(IPSK_vnodes, TT.getObjectFormat()));
+ VNodesVar->setAlignment(M->getDataLayout().getABITypeAlign(VNodesTy));
// VNodesVar is used by runtime but not referenced via relocation by other
// sections. Conservatively make it linker retained.
UsedVars.push_back(VNodesVar);