diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp | 123 |
1 files changed, 88 insertions, 35 deletions
diff --git a/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp b/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp index e38855c92b1a..bd3964ce127f 100644 --- a/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp +++ b/contrib/llvm-project/llvm/lib/ProfileData/InstrProf.cpp @@ -27,6 +27,7 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ProfDataUtils.h" #include "llvm/IR/Type.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/Casting.h" @@ -42,6 +43,7 @@ #include "llvm/Support/Path.h" #include "llvm/Support/SwapByteOrder.h" #include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" #include <algorithm> #include <cassert> @@ -258,6 +260,46 @@ std::string InstrProfError::message() const { char InstrProfError::ID = 0; +ProfOStream::ProfOStream(raw_fd_ostream &FD) + : IsFDOStream(true), OS(FD), LE(FD, llvm::endianness::little) {} + +ProfOStream::ProfOStream(raw_string_ostream &STR) + : IsFDOStream(false), OS(STR), LE(STR, llvm::endianness::little) {} + +uint64_t ProfOStream::tell() const { return OS.tell(); } +void ProfOStream::write(uint64_t V) { LE.write<uint64_t>(V); } +void ProfOStream::write32(uint32_t V) { LE.write<uint32_t>(V); } +void ProfOStream::writeByte(uint8_t V) { LE.write<uint8_t>(V); } + +void ProfOStream::patch(ArrayRef<PatchItem> P) { + using namespace support; + + if (IsFDOStream) { + raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS); + const uint64_t LastPos = FDOStream.tell(); + for (const auto &K : P) { + FDOStream.seek(K.Pos); + for (uint64_t Elem : K.D) + write(Elem); + } + // Reset the stream to the last position after patching so that users + // don't accidentally overwrite data. This makes it consistent with + // the string stream below which replaces the data directly. + FDOStream.seek(LastPos); + } else { + raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS); + std::string &Data = SOStream.str(); // with flush + for (const auto &K : P) { + for (int I = 0, E = K.D.size(); I != E; I++) { + uint64_t Bytes = + endian::byte_swap<uint64_t, llvm::endianness::little>(K.D[I]); + Data.replace(K.Pos + I * sizeof(uint64_t), sizeof(uint64_t), + (const char *)&Bytes, sizeof(uint64_t)); + } + } + } +} + std::string getPGOFuncName(StringRef Name, GlobalValue::LinkageTypes Linkage, StringRef FileName, uint64_t Version LLVM_ATTRIBUTE_UNUSED) { @@ -437,13 +479,31 @@ std::string getPGOFuncNameVarName(StringRef FuncName, return VarName; } +bool isGPUProfTarget(const Module &M) { + const Triple &T = M.getTargetTriple(); + return T.isGPU(); +} + +void setPGOFuncVisibility(Module &M, GlobalVariable *FuncNameVar) { + // If the target is a GPU, make the symbol protected so it can + // be read from the host device + if (isGPUProfTarget(M)) + FuncNameVar->setVisibility(GlobalValue::ProtectedVisibility); + // Hide the symbol so that we correctly get a copy for each executable. + else if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage())) + FuncNameVar->setVisibility(GlobalValue::HiddenVisibility); +} + GlobalVariable *createPGOFuncNameVar(Module &M, GlobalValue::LinkageTypes Linkage, StringRef PGOFuncName) { + // Ensure profiling variables on GPU are visible to be read from host + if (isGPUProfTarget(M)) + Linkage = GlobalValue::ExternalLinkage; // We generally want to match the function's linkage, but available_externally // and extern_weak both have the wrong semantics, and anything that doesn't // need to link across compilation units doesn't need to be visible at all. - if (Linkage == GlobalValue::ExternalWeakLinkage) + else if (Linkage == GlobalValue::ExternalWeakLinkage) Linkage = GlobalValue::LinkOnceAnyLinkage; else if (Linkage == GlobalValue::AvailableExternallyLinkage) Linkage = GlobalValue::LinkOnceODRLinkage; @@ -457,10 +517,7 @@ GlobalVariable *createPGOFuncNameVar(Module &M, new GlobalVariable(M, Value->getType(), true, Linkage, Value, getPGOFuncNameVarName(PGOFuncName, Linkage)); - // Hide the symbol so that we correctly get a copy for each executable. - if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage())) - FuncNameVar->setVisibility(GlobalValue::HiddenVisibility); - + setPGOFuncVisibility(M, FuncNameVar); return FuncNameVar; } @@ -468,20 +525,19 @@ GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName) { return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), PGOFuncName); } -Error InstrProfSymtab::create(Module &M, bool InLTO) { +Error InstrProfSymtab::create(Module &M, bool InLTO, bool AddCanonical) { for (Function &F : M) { // Function may not have a name: like using asm("") to overwrite the name. // Ignore in this case. if (!F.hasName()) continue; - if (Error E = addFuncWithName(F, getIRPGOFuncName(F, InLTO))) + if (Error E = addFuncWithName(F, getIRPGOFuncName(F, InLTO), AddCanonical)) return E; // Also use getPGOFuncName() so that we can find records from older profiles - if (Error E = addFuncWithName(F, getPGOFuncName(F, InLTO))) + if (Error E = addFuncWithName(F, getPGOFuncName(F, InLTO), AddCanonical)) return E; } - SmallVector<MDNode *, 2> Types; for (GlobalVariable &G : M.globals()) { if (!G.hasName() || !G.hasMetadata(LLVMContext::MD_type)) continue; @@ -501,8 +557,8 @@ Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable, return E; bool Inserted = true; - std::tie(std::ignore, Inserted) = - MD5VTableMap.try_emplace(GlobalValue::getGUID(Name), &VTable); + std::tie(std::ignore, Inserted) = MD5VTableMap.try_emplace( + GlobalValue::getGUIDAssumingExternalLinkage(Name), &VTable); if (!Inserted) LLVM_DEBUG(dbgs() << "GUID conflict within one module"); return Error::success(); @@ -517,12 +573,8 @@ Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable, return Error::success(); } -/// \c NameStrings is a string composed of one of more possibly encoded -/// sub-strings. The substrings are separated by 0 or more zero bytes. This -/// method decodes the string and calls `NameCallback` for each substring. -static Error -readAndDecodeStrings(StringRef NameStrings, - std::function<Error(StringRef)> NameCallback) { +Error readAndDecodeStrings(StringRef NameStrings, + std::function<Error(StringRef)> NameCallback) { const uint8_t *P = NameStrings.bytes_begin(); const uint8_t *EndP = NameStrings.bytes_end(); while (P < EndP) { @@ -565,28 +617,24 @@ readAndDecodeStrings(StringRef NameStrings, } Error InstrProfSymtab::create(StringRef NameStrings) { - return readAndDecodeStrings( - NameStrings, - std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1)); + return readAndDecodeStrings(NameStrings, + [&](StringRef S) { return addFuncName(S); }); } Error InstrProfSymtab::create(StringRef FuncNameStrings, StringRef VTableNameStrings) { - if (Error E = readAndDecodeStrings(FuncNameStrings, - std::bind(&InstrProfSymtab::addFuncName, - this, std::placeholders::_1))) + if (Error E = readAndDecodeStrings( + FuncNameStrings, [&](StringRef S) { return addFuncName(S); })) return E; - return readAndDecodeStrings( - VTableNameStrings, - std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1)); + return readAndDecodeStrings(VTableNameStrings, + [&](StringRef S) { return addVTableName(S); }); } Error InstrProfSymtab::initVTableNamesFromCompressedStrings( StringRef CompressedVTableStrings) { - return readAndDecodeStrings( - CompressedVTableStrings, - std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1)); + return readAndDecodeStrings(CompressedVTableStrings, + [&](StringRef S) { return addVTableName(S); }); } StringRef InstrProfSymtab::getCanonicalName(StringRef PGOName) { @@ -615,16 +663,20 @@ StringRef InstrProfSymtab::getCanonicalName(StringRef PGOName) { return PGOName; } -Error InstrProfSymtab::addFuncWithName(Function &F, StringRef PGOFuncName) { +Error InstrProfSymtab::addFuncWithName(Function &F, StringRef PGOFuncName, + bool AddCanonical) { auto NameToGUIDMap = [&](StringRef Name) -> Error { if (Error E = addFuncName(Name)) return E; - MD5FuncMap.emplace_back(Function::getGUID(Name), &F); + MD5FuncMap.emplace_back(Function::getGUIDAssumingExternalLinkage(Name), &F); return Error::success(); }; if (Error E = NameToGUIDMap(PGOFuncName)) return E; + if (!AddCanonical) + return Error::success(); + StringRef CanonicalFuncName = getCanonicalName(PGOFuncName); if (CanonicalFuncName != PGOFuncName) return NameToGUIDMap(CanonicalFuncName); @@ -1057,7 +1109,8 @@ void TemporalProfTraceTy::createBPFunctionNodes( // BalancedPartitioning more effective. for (auto &[Id, UNs] : IdToUNs) llvm::erase_if(UNs, [&](auto &UN) { - return UNFrequency[UN] <= 1 || 2 * UNFrequency[UN] > IdToUNs.size(); + unsigned Freq = UNFrequency[UN]; + return Freq <= 1 || 2 * Freq > IdToUNs.size(); }); } @@ -1302,7 +1355,7 @@ void annotateValueSite(Module &M, Instruction &Inst, MDBuilder MDHelper(Ctx); SmallVector<Metadata *, 3> Vals; // Tag - Vals.push_back(MDHelper.createString("VP")); + Vals.push_back(MDHelper.createString(MDProfLabels::ValueProfile)); // Value Kind Vals.push_back(MDHelper.createConstant( ConstantInt::get(Type::getInt32Ty(Ctx), ValueKind))); @@ -1333,7 +1386,7 @@ MDNode *mayHaveValueProfileOfKind(const Instruction &Inst, return nullptr; MDString *Tag = cast<MDString>(MD->getOperand(0)); - if (!Tag || Tag->getString() != "VP") + if (!Tag || Tag->getString() != MDProfLabels::ValueProfile) return nullptr; // Now check kind: @@ -1417,7 +1470,7 @@ bool needsComdatForCounter(const GlobalObject &GO, const Module &M) { if (GO.hasComdat()) return true; - if (!Triple(M.getTargetTriple()).supportsCOMDAT()) + if (!M.getTargetTriple().supportsCOMDAT()) return false; // See createPGOFuncNameVar for more details. To avoid link errors, profile |
