diff --git a/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h b/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h --- a/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h +++ b/llvm/include/llvm/Transforms/Instrumentation/InstrProfiling.h @@ -121,6 +121,9 @@ /// Create a static initializer for our data, on platforms that need it, /// and for any profile output file that was specified. void emitInitialization(); + + // Emit the variable used for runtime counter relocation. + bool emitBiasVar(); }; } // end namespace llvm diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -551,6 +551,10 @@ // Emit the runtime hook even if no counters are present. bool MadeChange = emitRuntimeHook(); + // Emit the bias variable in each module when counter relocation is enabled. + if (isRuntimeCounterRelocationEnabled()) + MadeChange |= emitBiasVar(); + // Improve compile time by avoiding linear scans when there is no work. GlobalVariable *CoverageNamesVar = M.getNamedGlobal(getCoverageUnusedNamesVarName()); @@ -692,23 +696,7 @@ LoadInst *LI = dyn_cast(&I); if (!LI) { IRBuilder<> Builder(&I); - Type *Int64Ty = Type::getInt64Ty(M->getContext()); GlobalVariable *Bias = M->getGlobalVariable(getInstrProfCounterBiasVarName()); - if (!Bias) { - // Compiler must define this variable when runtime counter relocation - // is being used. Runtime has a weak external reference that is used - // to check whether that's the case or not. - Bias = new GlobalVariable(*M, Int64Ty, false, GlobalValue::LinkOnceODRLinkage, - Constant::getNullValue(Int64Ty), - getInstrProfCounterBiasVarName()); - Bias->setVisibility(GlobalVariable::HiddenVisibility); - // A definition that's weak (linkonce_odr) without being in a COMDAT - // section wouldn't lead to link errors, but it would lead to a dead - // data word from every TU but one. Putting it in COMDAT ensures there - // will be exactly one data slot in the link. - if (TT.supportsCOMDAT()) - Bias->setComdat(M->getOrInsertComdat(Bias->getName())); - } LI = Builder.CreateLoad(Int64Ty, Bias); } auto *Add = Builder.CreateAdd(Builder.CreatePtrToInt(Addr, Int64Ty), LI); @@ -1195,3 +1183,26 @@ appendToGlobalCtors(*M, F, 0); } + +bool InstrProfiling::emitBiasVar() { + // Module already provided its own variable, nothin to do. + if (M->getGlobalVariable(getInstrProfCounterBiasVarName())) + return false; + + // Compiler must define this variable when runtime counter relocation + // is being used. Runtime has a weak external reference that is used + // to check whether that's the case or not. + Type *Int64Ty = Type::getInt64Ty(M->getContext()); + auto *Bias = new GlobalVariable(*M, Int64Ty, false, GlobalValue::LinkOnceODRLinkage, + Constant::getNullValue(Int64Ty), + getInstrProfCounterBiasVarName()); + Bias->setVisibility(GlobalVariable::HiddenVisibility); + // A definition that's weak (linkonce_odr) without being in a COMDAT + // section wouldn't lead to link errors, but it would lead to a dead + // data word from every TU but one. Putting it in COMDAT ensures there + // will be exactly one data slot in the link. + if (TT.supportsCOMDAT()) + Bias->setComdat(M->getOrInsertComdat(Bias->getName())); + + return true; +} diff --git a/llvm/test/Instrumentation/InstrProfiling/bias-var.ll b/llvm/test/Instrumentation/InstrProfiling/bias-var.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Instrumentation/InstrProfiling/bias-var.ll @@ -0,0 +1,6 @@ +; RUN: opt < %s -S -instrprof -runtime-counter-relocation | FileCheck -check-prefixes=RELOC %s + +target triple = "x86_64-unknown-linux-gnu" + +; RELOC: $__llvm_profile_counter_bias = comdat any +; RELOC: @__llvm_profile_counter_bias = linkonce_odr hidden global i64 0, comdat