From a5be9e3cfba9cc841f37881a60bf5337aac5a704 Mon Sep 17 00:00:00 2001 From: Betul Buyukkurt Date: Wed, 18 Nov 2015 18:14:55 +0000 Subject: [PATCH] [PGO] Value profiling support This change introduces an instrumentation intrinsic instruction for value profiling purposes, the lowering of the instrumentation intrinsic and raw reader updates. The raw profile data files for llvm-profdata testing are updated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253484 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LangRef.rst | 49 ++++++ include/llvm/IR/IntrinsicInst.h | 35 ++++- include/llvm/IR/Intrinsics.td | 10 +- include/llvm/ProfileData/InstrProf.h | 23 ++- include/llvm/ProfileData/InstrProfData.inc | 6 + include/llvm/ProfileData/InstrProfReader.h | 25 ++- .../SelectionDAG/SelectionDAGBuilder.cpp | 3 +- lib/ProfileData/InstrProfReader.cpp | 83 +++++++++- .../Instrumentation/InstrProfiling.cpp | 143 +++++++++++++++--- .../Instrumentation/InstrProfiling/PR23499.ll | 2 +- .../Instrumentation/InstrProfiling/linkage.ll | 8 +- .../InstrProfiling/platform.ll | 9 +- .../InstrProfiling/profiling.ll | 6 +- .../llvm-profdata/Inputs/c-general.profraw | Bin 1384 -> 1776 bytes test/tools/llvm-profdata/c-general.test | 6 +- test/tools/llvm-profdata/raw-32-bits-be.test | 13 +- test/tools/llvm-profdata/raw-32-bits-le.test | 13 +- test/tools/llvm-profdata/raw-64-bits-be.test | 13 +- test/tools/llvm-profdata/raw-64-bits-le.test | 13 +- .../tools/llvm-profdata/raw-two-profiles.test | 31 ++-- 20 files changed, 414 insertions(+), 77 deletions(-) diff --git a/docs/LangRef.rst b/docs/LangRef.rst index cafc208ba8d..709b154e3da 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -9514,6 +9514,55 @@ structures and the code to increment the appropriate value, in a format that can be written out by a compiler runtime and consumed via the ``llvm-profdata`` tool. +'``llvm.instrprof_value_profile``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.instrprof_value_profile(i8* , i64 , + i64 , i32 , + i32 ) + +Overview: +""""""""" + +The '``llvm.instrprof_value_profile``' intrinsic can be emitted by a +frontend for use with instrumentation based profiling. This will be +lowered by the ``-instrprof`` pass to find out the target values, +instrumented expressions take in a program at runtime. + +Arguments: +"""""""""" + +The first argument is a pointer to a global variable containing the +name of the entity being instrumented. ``name`` should generally be the +(mangled) function name for a set of counters. + +The second argument is a hash value that can be used by the consumer +of the profile data to detect changes to the instrumented source. It +is an error if ``hash`` differs between two instances of +``llvm.instrprof_*`` that refer to the same name. + +The third argument is the value of the expression being profiled. The profiled +expression's value should be representable as an unsigned 64-bit value. The +fourth argument represents the kind of value profiling that is being done. The +supported value profiling kinds are enumerated through the +``InstrProfValueKind`` type declared in the +```` header file. The last argument is the +index of the instrumented expression within ``name``. It should be >= 0. + +Semantics: +"""""""""" + +This intrinsic represents the point where a call to a runtime routine +should be inserted for value profiling of target expressions. ``-instrprof`` +pass will generate the appropriate data structures and replace the +``llvm.instrprof_value_profile`` intrinsic with the call to the profile +runtime library with proper arguments. + Standard C Library Intrinsics ----------------------------- diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index 2c8b6eb6f39..169bcc02198 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -372,6 +372,39 @@ namespace llvm { return cast(const_cast(getArgOperand(3))); } }; -} + + /// This represents the llvm.instrprof_value_profile intrinsic. + class InstrProfValueProfileInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::instrprof_value_profile; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + GlobalVariable *getName() const { + return cast( + const_cast(getArgOperand(0))->stripPointerCasts()); + } + + ConstantInt *getHash() const { + return cast(const_cast(getArgOperand(1))); + } + + Value *getTargetValue() const { + return cast(const_cast(getArgOperand(2))); + } + + ConstantInt *getValueKind() const { + return cast(const_cast(getArgOperand(3))); + } + + // Returns the value site index. + ConstantInt *getIndex() const { + return cast(const_cast(getArgOperand(4))); + } + }; +} // namespace llvm #endif diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 66ef6fb1e5e..e7b60ef3d41 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -319,7 +319,15 @@ def int_instrprof_increment : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty], []>; - + +// A call to profile runtime for value profiling of target expressions +// through instrumentation based profiling. +def int_instrprof_value_profile : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i64_ty, llvm_i32_ty, + llvm_i32_ty], + []>; + //===------------------- Standard C Library Intrinsics --------------------===// // diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index aa100a796f2..59d0e1877a6 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -265,7 +265,7 @@ struct InstrProfRecord { inline void addValueData(uint32_t ValueKind, uint32_t Site, InstrProfValueData *VData, uint32_t N, ValueMapType *HashKeys); - /// Merge Value Profile ddata from Src record to this record for ValueKind. + /// Merge Value Profile data from Src record to this record for ValueKind. inline instrprof_error mergeValueProfData(uint32_t ValueKind, InstrProfRecord &Src); @@ -273,6 +273,12 @@ struct InstrProfRecord { /// the writer instance. inline void updateStrings(InstrProfStringTable *StrTab); + /// Clear value data entries + inline void clearValueData() { + for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) + getValueSitesForKind(Kind).clear(); + } + private: std::vector IndirectCallSites; const std::vector & @@ -292,6 +298,7 @@ private: const_cast(this) ->getValueSitesForKind(ValueKind)); } + // Map indirect call target name hash to name string. uint64_t remapValue(uint64_t Value, uint32_t ValueKind, ValueMapType *HashKeys) { @@ -303,9 +310,8 @@ private: std::lower_bound(HashKeys->begin(), HashKeys->end(), Value, [](const std::pair &LHS, uint64_t RHS) { return LHS.first < RHS; }); - assert(Result != HashKeys->end() && - "Hash does not match any known keys\n"); - Value = (uint64_t)Result->second; + if (Result != HashKeys->end()) + Value = (uint64_t)Result->second; break; } } @@ -464,7 +470,7 @@ struct ValueProfData { // The number of value profile kinds that has value profile data. // In this implementation, a value profile kind is considered to // have profile data if the number of value profile sites for the - // kind is not zero. More aggressively, the implemnetation can + // kind is not zero. More aggressively, the implementation can // choose to check the actual data value: if none of the value sites // has any profiled values, the kind can be skipped. uint32_t NumValueKinds; @@ -545,7 +551,7 @@ struct Header { namespace RawInstrProf { -const uint64_t Version = 1; +const uint64_t Version = 2; // Magic number to detect file format and endianness. // Use 255 at one end, since no UTF-8 file can use that character. Avoid 0, @@ -577,7 +583,7 @@ inline uint64_t getMagic() { // compiler-rt/lib/profile/InstrProfiling.h. // It should also match the synthesized type in // Transforms/Instrumentation/InstrProfiling.cpp:getOrCreateRegionCounters. -template struct ProfileData { +template struct LLVM_ALIGNAS(8) ProfileData { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Type Name; #include "llvm/ProfileData/InstrProfData.inc" }; @@ -594,6 +600,9 @@ struct Header { const uint64_t NamesSize; const uint64_t CountersDelta; const uint64_t NamesDelta; + const uint64_t ValueKindLast; + const uint64_t ValueDataSize; + const uint64_t ValueDataDelta; }; } // end namespace RawInstrProf diff --git a/include/llvm/ProfileData/InstrProfData.inc b/include/llvm/ProfileData/InstrProfData.inc index 0747ada40ae..b66df7696ae 100644 --- a/include/llvm/ProfileData/InstrProfData.inc +++ b/include/llvm/ProfileData/InstrProfData.inc @@ -56,6 +56,12 @@ INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), NamePtr, \ INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt64PtrTy(Ctx), CounterPtr, \ ConstantExpr::getBitCast(CounterPtr, \ llvm::Type::getInt64PtrTy(Ctx))) +INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), FunctionPointer, \ + FunctionAddr) +INSTR_PROF_DATA(const IntPtrT, llvm::Type::getInt8PtrTy(Ctx), Values, \ + ConstantPointerNull::get(Int8PtrTy)) +INSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \ + ConstantArray::get(Int16ArrayTy, Int16ArrayVals)) // INSTR_PROF_DATA_END #ifdef INSTR_PROF_DATA diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 3d4777a853e..c1d17c27158 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -20,10 +20,12 @@ #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/OnDiskHashTable.h" #include +#include namespace llvm { @@ -132,15 +134,21 @@ class RawInstrProfReader : public InstrProfReader { private: /// The profile data file contents. std::unique_ptr DataBuffer; - bool ShouldSwapBytes; uint64_t CountersDelta; uint64_t NamesDelta; + uint64_t ValueDataDelta; const RawInstrProf::ProfileData *Data; const RawInstrProf::ProfileData *DataEnd; const uint64_t *CountersStart; const char *NamesStart; + const uint8_t *ValueDataStart; const char *ProfileEnd; + uint32_t ValueKindLast; + + // String table for holding a unique copy of all the strings in the profile. + InstrProfStringTable StringTable; + InstrProfRecord::ValueMapType FunctionPtrToNameMap; RawInstrProfReader(const RawInstrProfReader &) = delete; RawInstrProfReader &operator=(const RawInstrProfReader &) = delete; @@ -159,10 +167,13 @@ private: IntT swap(IntT Int) const { return ShouldSwapBytes ? sys::getSwappedBytes(Int) : Int; } - + inline uint8_t getNumPaddingBytes(uint64_t SizeInBytes) { + return 7 & (sizeof(uint64_t) - SizeInBytes % sizeof(uint64_t)); + } std::error_code readName(InstrProfRecord &Record); std::error_code readFuncHash(InstrProfRecord &Record); std::error_code readRawCounts(InstrProfRecord &Record); + std::error_code readValueData(InstrProfRecord &Record); bool atEnd() const { return Data == DataEnd; } void advanceData() { Data++; } @@ -174,6 +185,15 @@ private: ptrdiff_t Offset = (swap(NamePtr) - NamesDelta) / sizeof(char); return NamesStart + Offset; } + const uint8_t *getValueDataCounts(IntPtrT ValueCountsPtr) const { + ptrdiff_t Offset = (swap(ValueCountsPtr) - ValueDataDelta) / sizeof(uint8_t); + return ValueDataStart + Offset; + } + // This accepts an already byte-swapped ValueDataPtr argument. + const InstrProfValueData *getValueData(IntPtrT ValueDataPtr) const { + ptrdiff_t Offset = (ValueDataPtr - ValueDataDelta) / sizeof(uint8_t); + return reinterpret_cast(ValueDataStart + Offset); + } }; typedef RawInstrProfReader RawInstrProfReader32; @@ -303,6 +323,7 @@ private: /// Fill Counts with the profile data for the given function name. std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector &Counts); + /// Return the maximum of all known function counts. uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 50a4f247efb..de0c0fba5f7 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5211,7 +5211,8 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { } case Intrinsic::instrprof_increment: llvm_unreachable("instrprof failed to lower an increment"); - + case Intrinsic::instrprof_value_profile: + llvm_unreachable("instrprof failed to lower a value profiling call"); case Intrinsic::localescape: { MachineFunction &MF = DAG.getMachineFunction(); const TargetInstrInfo *TII = DAG.getSubtarget().getInstrInfo(); diff --git a/lib/ProfileData/InstrProfReader.cpp b/lib/ProfileData/InstrProfReader.cpp index 479b6bc61d9..8a0354dc98c 100644 --- a/lib/ProfileData/InstrProfReader.cpp +++ b/lib/ProfileData/InstrProfReader.cpp @@ -206,15 +206,21 @@ std::error_code RawInstrProfReader::readHeader( CountersDelta = swap(Header.CountersDelta); NamesDelta = swap(Header.NamesDelta); + ValueDataDelta = swap(Header.ValueDataDelta); auto DataSize = swap(Header.DataSize); auto CountersSize = swap(Header.CountersSize); auto NamesSize = swap(Header.NamesSize); + auto ValueDataSize = swap(Header.ValueDataSize); + ValueKindLast = swap(Header.ValueKindLast); + + auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData); + auto PaddingSize = getNumPaddingBytes(NamesSize); ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); - ptrdiff_t CountersOffset = - DataOffset + sizeof(RawInstrProf::ProfileData) * DataSize; + ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes; ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize; - size_t ProfileSize = NamesOffset + sizeof(char) * NamesSize; + ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize; + size_t ProfileSize = ValueDataOffset + ValueDataSize; auto *Start = reinterpret_cast(&Header); if (Start + ProfileSize > DataBuffer->getBufferEnd()) @@ -225,8 +231,23 @@ std::error_code RawInstrProfReader::readHeader( DataEnd = Data + DataSize; CountersStart = reinterpret_cast(Start + CountersOffset); NamesStart = Start + NamesOffset; + ValueDataStart = reinterpret_cast(Start + ValueDataOffset); ProfileEnd = Start + ProfileSize; + FunctionPtrToNameMap.clear(); + for (const RawInstrProf::ProfileData *I = Data; I != DataEnd; ++I) { + const IntPtrT FPtr = swap(I->FunctionPointer); + if (!FPtr) + continue; + StringRef FunctionName(getName(I->NamePtr), swap(I->NameSize)); + const char* NameEntryPtr = StringTable.insertString(FunctionName); + FunctionPtrToNameMap.push_back(std::pair + (FPtr, NameEntryPtr)); + } + std::sort(FunctionPtrToNameMap.begin(), FunctionPtrToNameMap.end(), less_first()); + FunctionPtrToNameMap.erase(std::unique(FunctionPtrToNameMap.begin(), + FunctionPtrToNameMap.end()), + FunctionPtrToNameMap.end()); return success(); } @@ -234,9 +255,8 @@ template std::error_code RawInstrProfReader::readName(InstrProfRecord &Record) { Record.Name = StringRef(getName(Data->NamePtr), swap(Data->NameSize)); if (Record.Name.data() < NamesStart || - Record.Name.data() + Record.Name.size() > DataBuffer->getBufferEnd()) + Record.Name.data() + Record.Name.size() > (char*)ValueDataStart) return error(instrprof_error::malformed); - return success(); } @@ -275,8 +295,54 @@ std::error_code RawInstrProfReader::readRawCounts( } template -std::error_code -RawInstrProfReader::readNextRecord(InstrProfRecord &Record) { +std::error_code RawInstrProfReader::readValueData( + InstrProfRecord &Record) { + + Record.clearValueData(); + if (!Data->Values || (ValueDataDelta == 0)) + return success(); + + // Read value data. + uint64_t NumVSites = 0; + for (uint32_t Kind = IPVK_First; Kind <= ValueKindLast; ++Kind) + NumVSites += swap(Data->NumValueSites[Kind]); + NumVSites += getNumPaddingBytes(NumVSites); + + auto VDataCounts = makeArrayRef(getValueDataCounts(Data->Values), NumVSites); + // Check bounds. + if (VDataCounts.data() < ValueDataStart || + VDataCounts.data() + VDataCounts.size() > (const uint8_t *)ProfileEnd) + return error(instrprof_error::malformed); + + const InstrProfValueData *VDataPtr = + getValueData(swap(Data->Values) + NumVSites); + for (uint32_t Kind = IPVK_First; Kind <= ValueKindLast; ++Kind) { + NumVSites = swap(Data->NumValueSites[Kind]); + Record.reserveSites(Kind, NumVSites); + for (uint32_t VSite = 0; VSite < NumVSites; ++VSite) { + + uint32_t VDataCount = VDataCounts[VSite]; + if ((const char *)(VDataPtr + VDataCount) > ProfileEnd) + return error(instrprof_error::malformed); + + std::vector CurrentValues; + CurrentValues.reserve(VDataCount); + for (uint32_t VIndex = 0; VIndex < VDataCount; ++VIndex) { + uint64_t TargetValue = swap(VDataPtr->Value); + uint64_t Count = swap(VDataPtr->Count); + CurrentValues.push_back({TargetValue, Count}); + ++VDataPtr; + } + Record.addValueData(Kind, VSite, CurrentValues.data(), + VDataCount, &FunctionPtrToNameMap); + } + } + return success(); +} + +template +std::error_code RawInstrProfReader::readNextRecord( + InstrProfRecord &Record) { if (atEnd()) if (std::error_code EC = readNextHeader(ProfileEnd)) return EC; @@ -293,6 +359,9 @@ RawInstrProfReader::readNextRecord(InstrProfRecord &Record) { if (std::error_code EC = readRawCounts(Record)) return EC; + // Read value data and set Record. + if (std::error_code EC = readValueData(Record)) return EC; + // Iterate. advanceData(); return success(); diff --git a/lib/Transforms/Instrumentation/InstrProfiling.cpp b/lib/Transforms/Instrumentation/InstrProfiling.cpp index 5f0ae54df23..334c41f3abc 100644 --- a/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -7,19 +7,18 @@ // //===----------------------------------------------------------------------===// // -// This pass lowers instrprof_increment intrinsics emitted by a frontend for -// profiling. It also builds the data structures and initialization code needed -// for updating execution counts and emitting the profile at runtime. +// This pass lowers instrprof_* intrinsics emitted by a frontend for profiling. +// It also builds the data structures and initialization code needed for +// updating execution counts and emitting the profile at runtime. // //===----------------------------------------------------------------------===// -#include "llvm/ProfileData/InstrProf.h" -#include "llvm/Transforms/Instrumentation.h" - #include "llvm/ADT/Triple.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; @@ -50,7 +49,15 @@ public: private: InstrProfOptions Options; Module *M; - DenseMap RegionCounters; + typedef struct PerFunctionProfileData { + uint32_t NumValueSites[IPVK_Last+1]; + GlobalVariable* RegionCounters; + GlobalVariable* DataVar; + PerFunctionProfileData() : RegionCounters(nullptr), DataVar(nullptr) { + memset(NumValueSites, 0, sizeof(uint32_t) * (IPVK_Last+1)); + } + } PerFunctionProfileData; + DenseMap ProfileDataMap; std::vector UsedVars; bool isMachO() const { @@ -77,6 +84,12 @@ private: return getInstrProfCoverageSectionName(isMachO()); } + /// Count the number of instrumented value sites for the function. + void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins); + + /// Replace instrprof_value_profile with a call to runtime library. + void lowerValueProfileInst(InstrProfValueProfileInst *Ins); + /// Replace instrprof_increment with an increment of the appropriate value. void lowerIncrement(InstrProfIncrementInst *Inc); @@ -118,21 +131,37 @@ bool InstrProfiling::runOnModule(Module &M) { bool MadeChange = false; this->M = &M; - RegionCounters.clear(); + ProfileDataMap.clear(); UsedVars.clear(); + // We did not know how many value sites there would be inside + // 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) for (BasicBlock &BB : F) for (auto I = BB.begin(), E = BB.end(); I != E;) - if (auto *Inc = dyn_cast(I++)) { + if (auto *Ind = dyn_cast(I++)) + computeNumValueSiteCounts(Ind); + + for (Function &F : M) + for (BasicBlock &BB : F) + for (auto I = BB.begin(), E = BB.end(); I != E;) { + auto Instr = I++; + if (auto *Inc = dyn_cast(Instr)) { lowerIncrement(Inc); MadeChange = true; + } else if (auto *Ind = dyn_cast(Instr)) { + lowerValueProfileInst(Ind); + MadeChange = true; } + } + if (GlobalVariable *Coverage = M.getNamedGlobal(getCoverageMappingVarName())) { lowerCoverageData(Coverage); MadeChange = true; } + if (!MadeChange) return false; @@ -143,6 +172,54 @@ bool InstrProfiling::runOnModule(Module &M) { return true; } +static Constant *getOrInsertValueProfilingCall(Module &M) { + auto *VoidTy = Type::getVoidTy(M.getContext()); + auto *VoidPtrTy = Type::getInt8PtrTy(M.getContext()); + auto *Int32Ty = Type::getInt32Ty(M.getContext()); + auto *Int64Ty = Type::getInt64Ty(M.getContext()); + Type *ArgTypes[] = {Int64Ty, VoidPtrTy, Int32Ty}; + auto *ValueProfilingCallTy = + FunctionType::get(VoidTy, makeArrayRef(ArgTypes), false); + return M.getOrInsertFunction("__llvm_profile_instrument_target", + ValueProfilingCallTy); +} + +void InstrProfiling::computeNumValueSiteCounts(InstrProfValueProfileInst *Ind) { + + GlobalVariable *Name = Ind->getName(); + uint64_t ValueKind = Ind->getValueKind()->getZExtValue(); + uint64_t Index = Ind->getIndex()->getZExtValue(); + auto It = ProfileDataMap.find(Name); + if (It == ProfileDataMap.end()) { + PerFunctionProfileData PD; + PD.NumValueSites[ValueKind] = Index + 1; + ProfileDataMap[Name] = PD; + } else if (It->second.NumValueSites[ValueKind] <= Index) + It->second.NumValueSites[ValueKind] = Index + 1; +} + +void InstrProfiling::lowerValueProfileInst(InstrProfValueProfileInst *Ind) { + + GlobalVariable *Name = Ind->getName(); + auto It = ProfileDataMap.find(Name); + assert(It != ProfileDataMap.end() && It->second.DataVar && + "value profiling detected in function with no counter incerement"); + + GlobalVariable *DataVar = It->second.DataVar; + uint64_t ValueKind = Ind->getValueKind()->getZExtValue(); + uint64_t Index = Ind->getIndex()->getZExtValue(); + for (uint32_t Kind = IPVK_First; Kind < ValueKind; ++Kind) + Index += It->second.NumValueSites[Kind]; + + IRBuilder<> Builder(Ind); + Value* Args[3] = {Ind->getTargetValue(), + Builder.CreateBitCast(DataVar, Builder.getInt8PtrTy()), + Builder.getInt32(Index)}; + Ind->replaceAllUsesWith( + Builder.CreateCall(getOrInsertValueProfilingCall(*M), Args)); + Ind->eraseFromParent(); +} + void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) { GlobalVariable *Counters = getOrCreateRegionCounters(Inc); @@ -174,9 +251,10 @@ void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageData) { GlobalVariable *Name = cast(V); // If we have region counters for this name, we've already handled it. - auto It = RegionCounters.find(Name); - if (It != RegionCounters.end()) - continue; + auto It = ProfileDataMap.find(Name); + if (It != ProfileDataMap.end()) + if (It->second.RegionCounters) + continue; // Move the name variable to the right section. Name->setSection(getNameSection()); @@ -191,12 +269,25 @@ static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) { return (Prefix + Name).str(); } +static inline bool shouldRecordFunctionAddr(Function *F) { + // Check the linkage + if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() && + !F->hasAvailableExternallyLinkage()) + return true; + // Check uses of this function for other than direct calls or invokes to it. + return F->hasAddressTaken(); +} + GlobalVariable * InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { GlobalVariable *NamePtr = Inc->getName(); - auto It = RegionCounters.find(NamePtr); - if (It != RegionCounters.end()) - return It->second; + auto It = ProfileDataMap.find(NamePtr); + PerFunctionProfileData PD; + if (It != ProfileDataMap.end()) { + if (It->second.RegionCounters) + return It->second.RegionCounters; + PD = It->second; + } // Move the name variable to the right section. Place them in a COMDAT group // if the associated function is a COMDAT. This will make sure that @@ -225,22 +316,29 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { CounterPtr->setAlignment(8); CounterPtr->setComdat(ProfileVarsComdat); - RegionCounters[Inc->getName()] = CounterPtr; - // Create data variable. - + auto *Int8PtrTy = Type::getInt8PtrTy(Ctx); + auto *Int16Ty = Type::getInt16Ty(Ctx); + auto *Int16ArrayTy = ArrayType::get(Int16Ty, IPVK_Last+1); Type *DataTypes[] = { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) LLVMType, #include "llvm/ProfileData/InstrProfData.inc" }; auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes)); + Constant *FunctionAddr = shouldRecordFunctionAddr(Fn) ? + ConstantExpr::getBitCast(Fn, Int8PtrTy) : + ConstantPointerNull::get(Int8PtrTy); + + Constant *Int16ArrayVals[IPVK_Last+1]; + for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) + Int16ArrayVals[Kind] = ConstantInt::get(Int16Ty, PD.NumValueSites[Kind]); + Constant *DataVals[] = { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init, #include "llvm/ProfileData/InstrProfData.inc" }; - - auto *Data = new GlobalVariable(*M, DataTy, true, NamePtr->getLinkage(), + auto *Data = new GlobalVariable(*M, DataTy, false, NamePtr->getLinkage(), ConstantStruct::get(DataTy, DataVals), getVarName(Inc, getInstrProfDataVarPrefix())); Data->setVisibility(NamePtr->getVisibility()); @@ -248,6 +346,10 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { Data->setAlignment(8); Data->setComdat(ProfileVarsComdat); + PD.RegionCounters = CounterPtr; + PD.DataVar = Data; + ProfileDataMap[NamePtr] = PD; + // Mark the data variable as used so that it isn't stripped out. UsedVars.push_back(Data); @@ -341,7 +443,6 @@ void InstrProfiling::emitUses() { LLVMUsed = new GlobalVariable(*M, ATy, false, GlobalValue::AppendingLinkage, ConstantArray::get(ATy, MergedVars), "llvm.used"); - LLVMUsed->setSection("llvm.metadata"); } diff --git a/test/Instrumentation/InstrProfiling/PR23499.ll b/test/Instrumentation/InstrProfiling/PR23499.ll index 8988a9aa3be..a7dc36dde67 100644 --- a/test/Instrumentation/InstrProfiling/PR23499.ll +++ b/test/Instrumentation/InstrProfiling/PR23499.ll @@ -10,7 +10,7 @@ $_Z3barIvEvv = comdat any ; CHECK: @__llvm_profile_name__Z3barIvEvv = linkonce_odr hidden constant [11 x i8] c"_Z3barIvEvv", section "{{.*}}__llvm_prf_names", comdat($__llvm_profile_vars__Z3barIvEvv), align 1 ; CHECK: @__llvm_profile_counters__Z3barIvEvv = linkonce_odr hidden global [1 x i64] zeroinitializer, section "{{.*}}__llvm_prf_cnts", comdat($__llvm_profile_vars__Z3barIvEvv), align 8 -; CHECK: @__llvm_profile_data__Z3barIvEvv = linkonce_odr hidden constant { i32, i32, i64, i8*, i64* } { i32 11, i32 1, i64 0, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @__llvm_profile_name__Z3barIvEvv, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__llvm_profile_counters__Z3barIvEvv, i32 0, i32 0) }, section "{{.*}}__llvm_prf_data", comdat($__llvm_profile_vars__Z3barIvEvv), align 8 +; CHECK: @__llvm_profile_data__Z3barIvEvv = linkonce_odr hidden global { i32, i32, i64, i8*, i64*, i8*, i8*, [1 x i16] } { i32 11, i32 1, i64 0, i8* getelementptr inbounds ([11 x i8], [11 x i8]* @__llvm_profile_name__Z3barIvEvv, i32 0, i32 0), i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__llvm_profile_counters__Z3barIvEvv, i32 0, i32 0), i8* null, i8* null, [1 x i16] zeroinitializer }, section "{{.*}}__llvm_prf_data", comdat($__llvm_profile_vars__Z3barIvEvv), align 8 declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #1 diff --git a/test/Instrumentation/InstrProfiling/linkage.ll b/test/Instrumentation/InstrProfiling/linkage.ll index 2c9e97becec..caa5aa4edd4 100644 --- a/test/Instrumentation/InstrProfiling/linkage.ll +++ b/test/Instrumentation/InstrProfiling/linkage.ll @@ -9,28 +9,28 @@ @__llvm_profile_name_foo_inline = linkonce_odr hidden constant [10 x i8] c"foo_inline" ; COMMON: @__llvm_profile_counters_foo = hidden global -; COMMON: @__llvm_profile_data_foo = hidden constant +; COMMON: @__llvm_profile_data_foo = hidden global define void @foo() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64 0, i32 1, i32 0) ret void } ; COMMON: @__llvm_profile_counters_foo_weak = weak hidden global -; COMMON: @__llvm_profile_data_foo_weak = weak hidden constant +; COMMON: @__llvm_profile_data_foo_weak = weak hidden global define weak void @foo_weak() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([8 x i8], [8 x i8]* @__llvm_profile_name_foo_weak, i32 0, i32 0), i64 0, i32 1, i32 0) ret void } ; COMMON: @"__llvm_profile_counters_linkage.ll:foo_internal" = internal global -; COMMON: @"__llvm_profile_data_linkage.ll:foo_internal" = internal constant +; COMMON: @"__llvm_profile_data_linkage.ll:foo_internal" = internal global define internal void @foo_internal() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([23 x i8], [23 x i8]* @"__llvm_profile_name_linkage.ll:foo_internal", i32 0, i32 0), i64 0, i32 1, i32 0) ret void } ; COMMON: @__llvm_profile_counters_foo_inline = linkonce_odr hidden global -; COMMON: @__llvm_profile_data_foo_inline = linkonce_odr hidden constant +; COMMON: @__llvm_profile_data_foo_inline = linkonce_odr hidden global define linkonce_odr void @foo_inline() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @__llvm_profile_name_foo_inline, i32 0, i32 0), i64 0, i32 1, i32 0) ret void diff --git a/test/Instrumentation/InstrProfiling/platform.ll b/test/Instrumentation/InstrProfiling/platform.ll index 9fe84b043e2..6ae10f19c0e 100644 --- a/test/Instrumentation/InstrProfiling/platform.ll +++ b/test/Instrumentation/InstrProfiling/platform.ll @@ -12,10 +12,11 @@ ; MACHO: @__llvm_profile_counters_foo = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 ; ELF: @__llvm_profile_counters_foo = hidden global [1 x i64] zeroinitializer, section "__llvm_prf_cnts", align 8 -; MACHO: @__llvm_profile_data_foo = hidden constant {{.*}}, section "__DATA,__llvm_prf_data", align 8 -; LINUX: @__llvm_profile_data_foo = hidden constant {{.*}}, section "__llvm_prf_data", align 8 -; FREEBSD: @__llvm_profile_data_foo = hidden constant {{.*}}, section "__llvm_prf_data", align 8 -; SOLARIS: @__llvm_profile_data_foo = hidden constant {{.*}}, section "__llvm_prf_data", align 8 +; MACHO: @__llvm_profile_data_foo = hidden {{.*}}, section "__DATA,__llvm_prf_data", align 8 +; LINUX: @__llvm_profile_data_foo = hidden {{.*}}, section "__llvm_prf_data", align 8 +; FREEBSD: @__llvm_profile_data_foo = hidden {{.*}}, section "__llvm_prf_data", align 8 +; SOLARIS: @__llvm_profile_data_foo = hidden {{.*}}, section "__llvm_prf_data", align 8 + define void @foo() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64 0, i32 1, i32 0) ret void diff --git a/test/Instrumentation/InstrProfiling/profiling.ll b/test/Instrumentation/InstrProfiling/profiling.ll index 52a6eadbff0..cae103ab667 100644 --- a/test/Instrumentation/InstrProfiling/profiling.ll +++ b/test/Instrumentation/InstrProfiling/profiling.ll @@ -10,21 +10,21 @@ target triple = "x86_64-apple-macosx10.10.0" ; CHECK: @baz_prof_name = hidden constant [3 x i8] c"baz", section "__DATA,__llvm_prf_names", align 1 ; CHECK: @__llvm_profile_counters_foo = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 -; CHECK: @__llvm_profile_data_foo = hidden constant {{.*}}, section "__DATA,__llvm_prf_data", align 8 +; CHECK: @__llvm_profile_data_foo = hidden {{.*}}, section "__DATA,__llvm_prf_data", align 8 define void @foo() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), i64 0, i32 1, i32 0) ret void } ; CHECK: @__llvm_profile_counters_bar = hidden global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 -; CHECK: @__llvm_profile_data_bar = hidden constant {{.*}}, section "__DATA,__llvm_prf_data", align 8 +; CHECK: @__llvm_profile_data_bar = hidden {{.*}}, section "__DATA,__llvm_prf_data", align 8 define void @bar() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @__llvm_profile_name_bar, i32 0, i32 0), i64 0, i32 1, i32 0) ret void } ; CHECK: @__llvm_profile_counters_baz = hidden global [3 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 -; CHECK: @__llvm_profile_data_baz = hidden constant {{.*}}, section "__DATA,__llvm_prf_data", align 8 +; CHECK: @__llvm_profile_data_baz = hidden {{.*}}, section "__DATA,__llvm_prf_data", align 8 define void @baz() { call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @baz_prof_name, i32 0, i32 0), i64 0, i32 3, i32 0) call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @baz_prof_name, i32 0, i32 0), i64 0, i32 3, i32 1) diff --git a/test/tools/llvm-profdata/Inputs/c-general.profraw b/test/tools/llvm-profdata/Inputs/c-general.profraw index e8cef21de5f258c5e08a1089280f282be0a77455..a4d94858a9e7cecbec88d7bb7de76f51152a4587 100644 GIT binary patch delta 599 zcmaFC^?}#8u_!ISs37M*69WYBKLylAa7zClL*CqXj=i9S2a2Fc7cm)wBQfL_%!_RNV=v zx-EhbbzDF-fGc13&~29EYkafT@#$sN)05fx`Ke1CRiM z+fa2KP<1}i5Op9mj9?WI;w4nw3aGk2P<7%!X;6HF)PulVsJabMbty7n^ClNCaZEnI y$gz0^qX6^d049ma4_JT#EcGJE`FSasC7Jnoi8=B41*t`eCHX~@?O8R!1_A&O*>n2< literal 1384 zcmah|yGjE=6dg69QSk}BDx}*gw?JWHSOFzTX-o_8` z11tp#otrr)gaz@!aORwI@7h~{IiGyN+iD6(9dx*!@;bS$3KEH|BPYszmnioq-x|0|5vfBS)=}rXBT^@F zUqtFe?uSUdi4SfA>p*!=64Yy+D&9xdlk;AYZb>a57GaS@L93rezx<17yZ`_I diff --git a/test/tools/llvm-profdata/c-general.test b/test/tools/llvm-profdata/c-general.test index 01435303d44..efa9bfa18d7 100644 --- a/test/tools/llvm-profdata/c-general.test +++ b/test/tools/llvm-profdata/c-general.test @@ -6,7 +6,7 @@ REGENERATE: $ SRC=path/to/llvm REGENERATE: $ CFE=$SRC/tools/clang REGENERATE: $ TESTDIR=$SRC/test/tools/llvm-profdata REGENERATE: $ CFE_TESTDIR=$CFE/test/Profile -REGENERATE: $ clang -o a.out -fprofile-instr-generate $CFE_TESTDIR/test/Profile/c-general.c +REGENERATE: $ clang -o a.out -fprofile-instr-generate $CFE_TESTDIR/c-general.c REGENERATE: $ LLVM_PROFILE_FILE=$TESTDIR/Inputs/c-general.profraw ./a.out RUN: llvm-profdata show %p/Inputs/c-general.profraw -o - | FileCheck %s -check-prefix=CHECK @@ -14,11 +14,11 @@ RUN: llvm-profdata show %p/Inputs/c-general.profraw -o - --function=switches | F SWITCHES-LABEL: Counters: SWITCHES-NEXT: switches: -SWITCHES-NEXT: Hash: 0x0000000000000013 +SWITCHES-NEXT: Hash: 0x2618e4f23f2e8daa SWITCHES-NEXT: Counters: 19 SWITCHES-NEXT: Function count: 1 SWITCHES-LABEL: Functions shown: 1 -CHECK-LABEL: Total functions: 11 +CHECK-LABEL: Total functions: 12 CHECK-NEXT: Maximum function count: 1 CHECK-NEXT: Maximum internal block count: 100 diff --git a/test/tools/llvm-profdata/raw-32-bits-be.test b/test/tools/llvm-profdata/raw-32-bits-be.test index 86ac56d39f2..d20c36022fa 100644 --- a/test/tools/llvm-profdata/raw-32-bits-be.test +++ b/test/tools/llvm-profdata/raw-32-bits-be.test @@ -1,27 +1,36 @@ RUN: printf '\377lprofR\201' > %t -RUN: printf '\0\0\0\0\0\0\0\1' >> %t +RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\3' >> %t RUN: printf '\0\0\0\0\0\0\0\6' >> %t RUN: printf '\0\0\0\0\1\0\0\0' >> %t RUN: printf '\0\0\0\0\2\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\3' >> %t RUN: printf '\0\0\0\1' >> %t RUN: printf '\0\0\0\0\0\0\0\1' >> %t RUN: printf '\2\0\0\0' >> %t RUN: printf '\1\0\0\0' >> %t +RUN: printf '\0\0\0\0' >> %t +RUN: printf '\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\3' >> %t RUN: printf '\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\2\0\0\03' >> %t RUN: printf '\1\0\0\10' >> %t +RUN: printf '\0\0\0\0' >> %t +RUN: printf '\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\023' >> %t RUN: printf '\0\0\0\0\0\0\0\067' >> %t RUN: printf '\0\0\0\0\0\0\0\101' >> %t -RUN: printf 'foobar' >> %t +RUN: printf 'foobar\0\0' >> %t RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s diff --git a/test/tools/llvm-profdata/raw-32-bits-le.test b/test/tools/llvm-profdata/raw-32-bits-le.test index 9325e7eb0f5..1bd81a87fba 100644 --- a/test/tools/llvm-profdata/raw-32-bits-le.test +++ b/test/tools/llvm-profdata/raw-32-bits-le.test @@ -1,27 +1,36 @@ RUN: printf '\201Rforpl\377' > %t -RUN: printf '\1\0\0\0\0\0\0\0' >> %t +RUN: printf '\2\0\0\0\0\0\0\0' >> %t RUN: printf '\2\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0\0\0\0\0' >> %t RUN: printf '\6\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\1\0\0\0\0' >> %t RUN: printf '\0\0\0\2\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0' >> %t RUN: printf '\1\0\0\0' >> %t RUN: printf '\1\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\2' >> %t RUN: printf '\0\0\0\1' >> %t +RUN: printf '\0\0\0\0' >> %t +RUN: printf '\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0' >> %t RUN: printf '\2\0\0\0' >> %t RUN: printf '\02\0\0\0\0\0\0\0' >> %t RUN: printf '\03\0\0\2' >> %t RUN: printf '\10\0\0\1' >> %t +RUN: printf '\0\0\0\0' >> %t +RUN: printf '\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\023\0\0\0\0\0\0\0' >> %t RUN: printf '\067\0\0\0\0\0\0\0' >> %t RUN: printf '\101\0\0\0\0\0\0\0' >> %t -RUN: printf 'foobar' >> %t +RUN: printf 'foobar\0\0' >> %t RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s diff --git a/test/tools/llvm-profdata/raw-64-bits-be.test b/test/tools/llvm-profdata/raw-64-bits-be.test index b97d8b5dac6..902cedd476a 100644 --- a/test/tools/llvm-profdata/raw-64-bits-be.test +++ b/test/tools/llvm-profdata/raw-64-bits-be.test @@ -1,27 +1,36 @@ RUN: printf '\377lprofr\201' > %t -RUN: printf '\0\0\0\0\0\0\0\1' >> %t +RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\3' >> %t RUN: printf '\0\0\0\0\0\0\0\6' >> %t RUN: printf '\0\0\0\1\0\4\0\0' >> %t RUN: printf '\0\0\0\2\0\4\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\3' >> %t RUN: printf '\0\0\0\1' >> %t RUN: printf '\0\0\0\0\0\0\0\1' >> %t RUN: printf '\0\0\0\2\0\4\0\0' >> %t RUN: printf '\0\0\0\1\0\4\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\3' >> %t RUN: printf '\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\02' >> %t RUN: printf '\0\0\0\2\0\4\0\03' >> %t RUN: printf '\0\0\0\1\0\4\0\10' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\023' >> %t RUN: printf '\0\0\0\0\0\0\0\067' >> %t RUN: printf '\0\0\0\0\0\0\0\101' >> %t -RUN: printf 'foobar' >> %t +RUN: printf 'foobar\0\0' >> %t RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s diff --git a/test/tools/llvm-profdata/raw-64-bits-le.test b/test/tools/llvm-profdata/raw-64-bits-le.test index 0e6853811ec..d2f410a6bb9 100644 --- a/test/tools/llvm-profdata/raw-64-bits-le.test +++ b/test/tools/llvm-profdata/raw-64-bits-le.test @@ -1,27 +1,36 @@ RUN: printf '\201rforpl\377' > %t -RUN: printf '\1\0\0\0\0\0\0\0' >> %t +RUN: printf '\2\0\0\0\0\0\0\0' >> %t RUN: printf '\2\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0\0\0\0\0' >> %t RUN: printf '\6\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\4\0\1\0\0\0' >> %t RUN: printf '\0\0\4\0\2\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0' >> %t RUN: printf '\1\0\0\0' >> %t RUN: printf '\1\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\4\0\2\0\0\0' >> %t RUN: printf '\0\0\4\0\1\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\03\0\0\0' >> %t RUN: printf '\02\0\0\0' >> %t RUN: printf '\02\0\0\0\0\0\0\0' >> %t RUN: printf '\03\0\4\0\2\0\0\0' >> %t RUN: printf '\10\0\4\0\1\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\023\0\0\0\0\0\0\0' >> %t RUN: printf '\067\0\0\0\0\0\0\0' >> %t RUN: printf '\101\0\0\0\0\0\0\0' >> %t -RUN: printf 'foobar' >> %t +RUN: printf 'foobar\0\0' >> %t RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s diff --git a/test/tools/llvm-profdata/raw-two-profiles.test b/test/tools/llvm-profdata/raw-two-profiles.test index be78793215e..09eb121adf3 100644 --- a/test/tools/llvm-profdata/raw-two-profiles.test +++ b/test/tools/llvm-profdata/raw-two-profiles.test @@ -1,48 +1,51 @@ RUN: printf '\201rforpl\377' > %t-foo.profraw -RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\2\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\3\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\4\0\1\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\4\0\2\0\0\0' >> %t-foo.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\3\0\0\0' >> %t-foo.profraw RUN: printf '\1\0\0\0' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\4\0\2\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\4\0\1\0\0\0' >> %t-foo.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\023\0\0\0\0\0\0\0' >> %t-foo.profraw -RUN: printf 'foo' >> %t-foo.profraw +RUN: printf 'foo\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\201rforpl\377' > %t-bar.profraw -RUN: printf '\1\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\2\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\2\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\3\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\6\0\1\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\6\0\2\0\0\0' >> %t-bar.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\3\0\0\0' >> %t-bar.profraw RUN: printf '\2\0\0\0' >> %t-bar.profraw RUN: printf '\2\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\6\0\2\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\6\0\1\0\0\0' >> %t-bar.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\067\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\101\0\0\0\0\0\0\0' >> %t-bar.profraw -RUN: printf 'bar' >> %t-bar.profraw - -Versions of the profiles that are padded to eight byte alignment. -RUN: cat %t-foo.profraw > %t-foo-padded.profraw -RUN: printf '\0\0\0\0\0' >> %t-foo-padded.profraw -RUN: cat %t-bar.profraw > %t-bar-padded.profraw -RUN: printf '\0\0\0\0\0' >> %t-bar-padded.profraw - -RUN: cat %t-foo-padded.profraw %t-bar.profraw > %t-pad-between.profraw -RUN: cat %t-foo-padded.profraw %t-bar-padded.profraw > %t-pad.profraw +RUN: printf 'bar\0\0\0\0\0' >> %t-bar.profraw -RUN: llvm-profdata show %t-pad-between.profraw -all-functions -counts | FileCheck %s +RUN: cat %t-foo.profraw %t-bar.profraw > %t-pad.profraw RUN: llvm-profdata show %t-pad.profraw -all-functions -counts | FileCheck %s CHECK: Counters: -- 2.34.1