1480093f4SDimitry Andric/*===-- InstrProfData.inc - instr profiling runtime structures -*- C++ -*-=== *\ 2480093f4SDimitry Andric|* 3480093f4SDimitry Andric|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4480093f4SDimitry Andric|* See https://llvm.org/LICENSE.txt for license information. 5480093f4SDimitry Andric|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6480093f4SDimitry Andric|* 7480093f4SDimitry Andric\*===----------------------------------------------------------------------===*/ 8480093f4SDimitry Andric/* 9fe6060f1SDimitry Andric * This is the main file that defines all the data structure, signature, 10480093f4SDimitry Andric * constant literals that are shared across profiling runtime library, 11480093f4SDimitry Andric * compiler (instrumentation), and host tools (reader/writer). The entities 12480093f4SDimitry Andric * defined in this file affect the profile runtime ABI, the raw profile format, 13480093f4SDimitry Andric * or both. 14480093f4SDimitry Andric * 15fe6060f1SDimitry Andric * The file has two identical copies. The primary copy lives in LLVM and 16480093f4SDimitry Andric * the other one sits in compiler-rt/lib/profile directory. To make changes 17fe6060f1SDimitry Andric * in this file, first modify the primary copy and copy it over to compiler-rt. 18480093f4SDimitry Andric * Testing of any change in this file can start only after the two copies are 19480093f4SDimitry Andric * synced up. 20480093f4SDimitry Andric * 21480093f4SDimitry Andric * The first part of the file includes macros that defines types, names, and 22480093f4SDimitry Andric * initializers for the member fields of the core data structures. The field 23480093f4SDimitry Andric * declarations for one structure is enabled by defining the field activation 24480093f4SDimitry Andric * macro associated with that structure. Only one field activation record 25480093f4SDimitry Andric * can be defined at one time and the rest definitions will be filtered out by 26480093f4SDimitry Andric * the preprocessor. 27480093f4SDimitry Andric * 28480093f4SDimitry Andric * Examples of how the template is used to instantiate structure definition: 29480093f4SDimitry Andric * 1. To declare a structure: 30480093f4SDimitry Andric * 31480093f4SDimitry Andric * struct ProfData { 32480093f4SDimitry Andric * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ 33480093f4SDimitry Andric * Type Name; 34480093f4SDimitry Andric * #include "llvm/ProfileData/InstrProfData.inc" 35480093f4SDimitry Andric * }; 36480093f4SDimitry Andric * 37480093f4SDimitry Andric * 2. To construct LLVM type arrays for the struct type: 38480093f4SDimitry Andric * 39480093f4SDimitry Andric * Type *DataTypes[] = { 40480093f4SDimitry Andric * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ 41480093f4SDimitry Andric * LLVMType, 42480093f4SDimitry Andric * #include "llvm/ProfileData/InstrProfData.inc" 43480093f4SDimitry Andric * }; 44480093f4SDimitry Andric * 45480093f4SDimitry Andric * 4. To construct constant array for the initializers: 46480093f4SDimitry Andric * #define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) \ 47480093f4SDimitry Andric * Initializer, 48480093f4SDimitry Andric * Constant *ConstantVals[] = { 49480093f4SDimitry Andric * #include "llvm/ProfileData/InstrProfData.inc" 50480093f4SDimitry Andric * }; 51480093f4SDimitry Andric * 52480093f4SDimitry Andric * 53480093f4SDimitry Andric * The second part of the file includes definitions all other entities that 54480093f4SDimitry Andric * are related to runtime ABI and format. When no field activation macro is 55480093f4SDimitry Andric * defined, this file can be included to introduce the definitions. 56480093f4SDimitry Andric * 57480093f4SDimitry Andric\*===----------------------------------------------------------------------===*/ 58480093f4SDimitry Andric 59480093f4SDimitry Andric/* Functions marked with INSTR_PROF_VISIBILITY must have hidden visibility in 60480093f4SDimitry Andric * the compiler runtime. */ 61480093f4SDimitry Andric#ifndef INSTR_PROF_VISIBILITY 62480093f4SDimitry Andric#define INSTR_PROF_VISIBILITY 63480093f4SDimitry Andric#endif 64480093f4SDimitry Andric 65*0fca6ea1SDimitry Andric// clang-format off:consider re-enabling clang-format if auto-formatted C macros 66*0fca6ea1SDimitry Andric// are readable (e.g., after `issue #82426` is fixed) 67480093f4SDimitry Andric/* INSTR_PROF_DATA start. */ 68480093f4SDimitry Andric/* Definition of member fields of the per-function control structure. */ 69480093f4SDimitry Andric#ifndef INSTR_PROF_DATA 70480093f4SDimitry Andric#define INSTR_PROF_DATA(Type, LLVMType, Name, Initializer) 71480093f4SDimitry Andric#else 72480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 73480093f4SDimitry Andric#endif 74480093f4SDimitry AndricINSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \ 75480093f4SDimitry Andric ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ 76480093f4SDimitry Andric IndexedInstrProf::ComputeHash(getPGOFuncNameVarInitializer(Inc->getName())))) 77480093f4SDimitry AndricINSTR_PROF_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ 78480093f4SDimitry Andric ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ 79480093f4SDimitry Andric Inc->getHash()->getZExtValue())) 80349cc55cSDimitry AndricINSTR_PROF_DATA(const IntPtrT, IntPtrTy, CounterPtr, RelativeCounterPtr) 815f757f3fSDimitry AndricINSTR_PROF_DATA(const IntPtrT, IntPtrTy, BitmapPtr, RelativeBitmapPtr) 82480093f4SDimitry Andric/* This is used to map function pointers for the indirect call targets to 83480093f4SDimitry Andric * function name hashes during the conversion from raw to merged profile 84480093f4SDimitry Andric * data. 85480093f4SDimitry Andric */ 865f757f3fSDimitry AndricINSTR_PROF_DATA(const IntPtrT, llvm::PointerType::getUnqual(Ctx), FunctionPointer, \ 87480093f4SDimitry Andric FunctionAddr) 885f757f3fSDimitry AndricINSTR_PROF_DATA(IntPtrT, llvm::PointerType::getUnqual(Ctx), Values, \ 89480093f4SDimitry Andric ValuesPtrExpr) 90480093f4SDimitry AndricINSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumCounters, \ 91480093f4SDimitry Andric ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumCounters)) 92480093f4SDimitry AndricINSTR_PROF_DATA(const uint16_t, Int16ArrayTy, NumValueSites[IPVK_Last+1], \ 935f757f3fSDimitry Andric ConstantArray::get(Int16ArrayTy, Int16ArrayVals)) \ 945f757f3fSDimitry AndricINSTR_PROF_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), NumBitmapBytes, \ 955f757f3fSDimitry Andric ConstantInt::get(llvm::Type::getInt32Ty(Ctx), NumBitmapBytes)) 96480093f4SDimitry Andric#undef INSTR_PROF_DATA 97480093f4SDimitry Andric/* INSTR_PROF_DATA end. */ 98480093f4SDimitry Andric 99*0fca6ea1SDimitry Andric/* For a virtual table object, record the name hash to associate profiled 100*0fca6ea1SDimitry Andric * addresses with global variables, and record {starting address, size in bytes} 101*0fca6ea1SDimitry Andric * to map the profiled virtual table (which usually have an offset from the 102*0fca6ea1SDimitry Andric * starting address) back to a virtual table object. */ 103*0fca6ea1SDimitry Andric#ifndef INSTR_PROF_VTABLE_DATA 104*0fca6ea1SDimitry Andric#define INSTR_PROF_VTABLE_DATA(Type, LLVMType, Name, Initializer) 105*0fca6ea1SDimitry Andric#else 106*0fca6ea1SDimitry Andric#define INSTR_PROF_VTABLE_DATA_DEFINED 107*0fca6ea1SDimitry Andric#endif 108*0fca6ea1SDimitry AndricINSTR_PROF_VTABLE_DATA(const uint64_t, llvm::Type::getInt64Ty(Ctx), \ 109*0fca6ea1SDimitry Andric VTableNameHash, ConstantInt::get(llvm::Type::getInt64Ty(Ctx), \ 110*0fca6ea1SDimitry Andric IndexedInstrProf::ComputeHash(PGOVTableName))) 111*0fca6ea1SDimitry AndricINSTR_PROF_VTABLE_DATA(const IntPtrT, llvm::PointerType::getUnqual(Ctx), \ 112*0fca6ea1SDimitry Andric VTablePointer, VTableAddr) 113*0fca6ea1SDimitry AndricINSTR_PROF_VTABLE_DATA(const uint32_t, llvm::Type::getInt32Ty(Ctx), VTableSize, \ 114*0fca6ea1SDimitry Andric ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \ 115*0fca6ea1SDimitry Andric VTableSizeVal)) 116*0fca6ea1SDimitry Andric#undef INSTR_PROF_VTABLE_DATA 117*0fca6ea1SDimitry Andric/* INSTR_PROF_VTABLE_DATA end. */ 118480093f4SDimitry Andric 119480093f4SDimitry Andric/* This is an internal data structure used by value profiler. It 120480093f4SDimitry Andric * is defined here to allow serialization code sharing by LLVM 121480093f4SDimitry Andric * to be used in unit test. 122480093f4SDimitry Andric * 123480093f4SDimitry Andric * typedef struct ValueProfNode { 124480093f4SDimitry Andric * // InstrProfValueData VData; 125480093f4SDimitry Andric * uint64_t Value; 126480093f4SDimitry Andric * uint64_t Count; 127480093f4SDimitry Andric * struct ValueProfNode *Next; 128480093f4SDimitry Andric * } ValueProfNode; 129480093f4SDimitry Andric */ 130480093f4SDimitry Andric/* INSTR_PROF_VALUE_NODE start. */ 131480093f4SDimitry Andric#ifndef INSTR_PROF_VALUE_NODE 132480093f4SDimitry Andric#define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Initializer) 133480093f4SDimitry Andric#else 134480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 135480093f4SDimitry Andric#endif 136480093f4SDimitry AndricINSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Value, \ 137480093f4SDimitry Andric ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0)) 138480093f4SDimitry AndricINSTR_PROF_VALUE_NODE(uint64_t, llvm::Type::getInt64Ty(Ctx), Count, \ 139480093f4SDimitry Andric ConstantInt::get(llvm::Type::GetInt64Ty(Ctx), 0)) 1405f757f3fSDimitry AndricINSTR_PROF_VALUE_NODE(PtrToNodeT, llvm::PointerType::getUnqual(Ctx), Next, \ 141*0fca6ea1SDimitry Andric ConstantInt::get(llvm::PointerType::getUnqual(Ctx), 0)) 142480093f4SDimitry Andric#undef INSTR_PROF_VALUE_NODE 143480093f4SDimitry Andric/* INSTR_PROF_VALUE_NODE end. */ 144480093f4SDimitry Andric 145480093f4SDimitry Andric/* INSTR_PROF_RAW_HEADER start */ 146480093f4SDimitry Andric/* Definition of member fields of the raw profile header data structure. */ 147297eecfbSDimitry Andric/* Please update llvm/docs/InstrProfileFormat.rst as appropriate when updating 148297eecfbSDimitry Andric raw profile format. */ 149480093f4SDimitry Andric#ifndef INSTR_PROF_RAW_HEADER 150480093f4SDimitry Andric#define INSTR_PROF_RAW_HEADER(Type, Name, Initializer) 151480093f4SDimitry Andric#else 152480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 153480093f4SDimitry Andric#endif 154480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, Magic, __llvm_profile_get_magic()) 155480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, Version, __llvm_profile_get_version()) 1566e75b2fbSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL)) 1575f757f3fSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, NumData, NumData) 158480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesBeforeCounters, PaddingBytesBeforeCounters) 1595f757f3fSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, NumCounters, NumCounters) 160480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterCounters, PaddingBytesAfterCounters) 1615f757f3fSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, NumBitmapBytes, NumBitmapBytes) 1625f757f3fSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, PaddingBytesAfterBitmapBytes, PaddingBytesAfterBitmapBytes) 163480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize) 164349cc55cSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, 165349cc55cSDimitry Andric (uintptr_t)CountersBegin - (uintptr_t)DataBegin) 1665f757f3fSDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, BitmapDelta, 1675f757f3fSDimitry Andric (uintptr_t)BitmapBegin - (uintptr_t)DataBegin) 168480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) 169*0fca6ea1SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, NumVTables, NumVTables) 170*0fca6ea1SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, VNamesSize, VNamesSize) 171480093f4SDimitry AndricINSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) 172480093f4SDimitry Andric#undef INSTR_PROF_RAW_HEADER 173480093f4SDimitry Andric/* INSTR_PROF_RAW_HEADER end */ 174480093f4SDimitry Andric 175480093f4SDimitry Andric/* VALUE_PROF_FUNC_PARAM start */ 176480093f4SDimitry Andric/* Definition of parameter types of the runtime API used to do value profiling 177480093f4SDimitry Andric * for a given value site. 178480093f4SDimitry Andric */ 179480093f4SDimitry Andric#ifndef VALUE_PROF_FUNC_PARAM 180480093f4SDimitry Andric#define VALUE_PROF_FUNC_PARAM(ArgType, ArgName, ArgLLVMType) 181480093f4SDimitry Andric#define INSTR_PROF_COMMA 182480093f4SDimitry Andric#else 183480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 184480093f4SDimitry Andric#define INSTR_PROF_COMMA , 185480093f4SDimitry Andric#endif 186480093f4SDimitry AndricVALUE_PROF_FUNC_PARAM(uint64_t, TargetValue, Type::getInt64Ty(Ctx)) \ 187480093f4SDimitry Andric INSTR_PROF_COMMA 1885f757f3fSDimitry AndricVALUE_PROF_FUNC_PARAM(void *, Data, PointerType::getUnqual(Ctx)) INSTR_PROF_COMMA 189480093f4SDimitry AndricVALUE_PROF_FUNC_PARAM(uint32_t, CounterIndex, Type::getInt32Ty(Ctx)) 190480093f4SDimitry Andric#undef VALUE_PROF_FUNC_PARAM 191480093f4SDimitry Andric#undef INSTR_PROF_COMMA 192480093f4SDimitry Andric/* VALUE_PROF_FUNC_PARAM end */ 193480093f4SDimitry Andric 194480093f4SDimitry Andric/* VALUE_PROF_KIND start */ 195480093f4SDimitry Andric#ifndef VALUE_PROF_KIND 196480093f4SDimitry Andric#define VALUE_PROF_KIND(Enumerator, Value, Descr) 197480093f4SDimitry Andric#else 198480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 199480093f4SDimitry Andric#endif 200480093f4SDimitry Andric/* For indirect function call value profiling, the addresses of the target 201480093f4SDimitry Andric * functions are profiled by the instrumented code. The target addresses are 202480093f4SDimitry Andric * written in the raw profile data and converted to target function name's MD5 203480093f4SDimitry Andric * hash by the profile reader during deserialization. Typically, this happens 204480093f4SDimitry Andric * when the raw profile data is read during profile merging. 205480093f4SDimitry Andric * 206480093f4SDimitry Andric * For this remapping the ProfData is used. ProfData contains both the function 207480093f4SDimitry Andric * name hash and the function address. 208480093f4SDimitry Andric */ 209480093f4SDimitry AndricVALUE_PROF_KIND(IPVK_IndirectCallTarget, 0, "indirect call target") 210480093f4SDimitry Andric/* For memory intrinsic functions size profiling. */ 211480093f4SDimitry AndricVALUE_PROF_KIND(IPVK_MemOPSize, 1, "memory intrinsic functions size") 212*0fca6ea1SDimitry Andric/* For virtual table address profiling, the address point of the virtual table 213*0fca6ea1SDimitry Andric * (i.e., the address contained in objects pointing to a virtual table) are 214*0fca6ea1SDimitry Andric * profiled. Note this may not be the address of the per C++ class virtual table 215*0fca6ea1SDimitry Andric * object (e.g., there might be an offset). 216*0fca6ea1SDimitry Andric * 217*0fca6ea1SDimitry Andric * The profiled addresses are stored in raw profile, together with the following 218*0fca6ea1SDimitry Andric * two types of information. 219*0fca6ea1SDimitry Andric * 1. The (starting and ending) addresses of per C++ class virtual table objects. 220*0fca6ea1SDimitry Andric * 2. The (compressed) virtual table object names. 221*0fca6ea1SDimitry Andric * RawInstrProfReader converts profiled virtual table addresses to virtual table 222*0fca6ea1SDimitry Andric * objects' MD5 hash. 223*0fca6ea1SDimitry Andric */ 224*0fca6ea1SDimitry AndricVALUE_PROF_KIND(IPVK_VTableTarget, 2, "The profiled address point of the vtable") 225480093f4SDimitry Andric/* These two kinds must be the last to be 226480093f4SDimitry Andric * declared. This is to make sure the string 227480093f4SDimitry Andric * array created with the template can be 228480093f4SDimitry Andric * indexed with the kind value. 229480093f4SDimitry Andric */ 230480093f4SDimitry AndricVALUE_PROF_KIND(IPVK_First, IPVK_IndirectCallTarget, "first") 231*0fca6ea1SDimitry AndricVALUE_PROF_KIND(IPVK_Last, IPVK_VTableTarget, "last") 232480093f4SDimitry Andric 233480093f4SDimitry Andric#undef VALUE_PROF_KIND 234480093f4SDimitry Andric/* VALUE_PROF_KIND end */ 235480093f4SDimitry Andric 2365ffd83dbSDimitry Andric#undef COVMAP_V2_OR_V3 2375ffd83dbSDimitry Andric#ifdef COVMAP_V2 2385ffd83dbSDimitry Andric#define COVMAP_V2_OR_V3 2395ffd83dbSDimitry Andric#endif 2405ffd83dbSDimitry Andric#ifdef COVMAP_V3 2415ffd83dbSDimitry Andric#define COVMAP_V2_OR_V3 2425ffd83dbSDimitry Andric#endif 2435ffd83dbSDimitry Andric 244480093f4SDimitry Andric/* COVMAP_FUNC_RECORD start */ 245480093f4SDimitry Andric/* Definition of member fields of the function record structure in coverage 246480093f4SDimitry Andric * map. 247480093f4SDimitry Andric */ 248480093f4SDimitry Andric#ifndef COVMAP_FUNC_RECORD 249480093f4SDimitry Andric#define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Initializer) 250480093f4SDimitry Andric#else 251480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 252480093f4SDimitry Andric#endif 253480093f4SDimitry Andric#ifdef COVMAP_V1 2545f757f3fSDimitry AndricCOVMAP_FUNC_RECORD(const IntPtrT, llvm::PointerType::getUnqual(Ctx), \ 255480093f4SDimitry Andric NamePtr, llvm::ConstantExpr::getBitCast(NamePtr, \ 2565f757f3fSDimitry Andric llvm::PointerType::getUnqual(Ctx))) 257480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), NameSize, \ 258480093f4SDimitry Andric llvm::ConstantInt::get(llvm::Type::getInt32Ty(Ctx), \ 259480093f4SDimitry Andric NameValue.size())) 2605ffd83dbSDimitry Andric#endif 2615ffd83dbSDimitry Andric#ifdef COVMAP_V2_OR_V3 262480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const int64_t, llvm::Type::getInt64Ty(Ctx), NameRef, \ 2635ffd83dbSDimitry Andric llvm::ConstantInt::get( \ 2645ffd83dbSDimitry Andric llvm::Type::getInt64Ty(Ctx), NameHash)) 265480093f4SDimitry Andric#endif 266480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const uint32_t, llvm::Type::getInt32Ty(Ctx), DataSize, \ 2675ffd83dbSDimitry Andric llvm::ConstantInt::get( \ 2685ffd83dbSDimitry Andric llvm::Type::getInt32Ty(Ctx), CoverageMapping.size())) 269480093f4SDimitry AndricCOVMAP_FUNC_RECORD(const uint64_t, llvm::Type::getInt64Ty(Ctx), FuncHash, \ 2705ffd83dbSDimitry Andric llvm::ConstantInt::get( \ 2715ffd83dbSDimitry Andric llvm::Type::getInt64Ty(Ctx), FuncHash)) 2725ffd83dbSDimitry Andric#ifdef COVMAP_V3 2735ffd83dbSDimitry AndricCOVMAP_FUNC_RECORD(const uint64_t, llvm::Type::getInt64Ty(Ctx), FilenamesRef, \ 2745ffd83dbSDimitry Andric llvm::ConstantInt::get( \ 2755ffd83dbSDimitry Andric llvm::Type::getInt64Ty(Ctx), FilenamesRef)) 2765ffd83dbSDimitry AndricCOVMAP_FUNC_RECORD(const char, \ 2775ffd83dbSDimitry Andric llvm::ArrayType::get(llvm::Type::getInt8Ty(Ctx), \ 2785ffd83dbSDimitry Andric CoverageMapping.size()), \ 2795ffd83dbSDimitry Andric CoverageMapping, 2805ffd83dbSDimitry Andric llvm::ConstantDataArray::getRaw( \ 2815ffd83dbSDimitry Andric CoverageMapping, CoverageMapping.size(), \ 2825ffd83dbSDimitry Andric llvm::Type::getInt8Ty(Ctx))) 2835ffd83dbSDimitry Andric#endif 284480093f4SDimitry Andric#undef COVMAP_FUNC_RECORD 285480093f4SDimitry Andric/* COVMAP_FUNC_RECORD end. */ 286480093f4SDimitry Andric 287480093f4SDimitry Andric/* COVMAP_HEADER start */ 288480093f4SDimitry Andric/* Definition of member fields of coverage map header. 289480093f4SDimitry Andric */ 290480093f4SDimitry Andric#ifndef COVMAP_HEADER 291480093f4SDimitry Andric#define COVMAP_HEADER(Type, LLVMType, Name, Initializer) 292480093f4SDimitry Andric#else 293480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 294480093f4SDimitry Andric#endif 295480093f4SDimitry AndricCOVMAP_HEADER(uint32_t, Int32Ty, NRecords, \ 2965ffd83dbSDimitry Andric llvm::ConstantInt::get(Int32Ty, NRecords)) 297480093f4SDimitry AndricCOVMAP_HEADER(uint32_t, Int32Ty, FilenamesSize, \ 298480093f4SDimitry Andric llvm::ConstantInt::get(Int32Ty, FilenamesSize)) 299480093f4SDimitry AndricCOVMAP_HEADER(uint32_t, Int32Ty, CoverageSize, \ 300480093f4SDimitry Andric llvm::ConstantInt::get(Int32Ty, CoverageMappingSize)) 301480093f4SDimitry AndricCOVMAP_HEADER(uint32_t, Int32Ty, Version, \ 302480093f4SDimitry Andric llvm::ConstantInt::get(Int32Ty, CovMapVersion::CurrentVersion)) 303480093f4SDimitry Andric#undef COVMAP_HEADER 304480093f4SDimitry Andric/* COVMAP_HEADER end. */ 305480093f4SDimitry Andric 306480093f4SDimitry Andric 307480093f4SDimitry Andric#ifdef INSTR_PROF_SECT_ENTRY 308480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 309480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_data, \ 310480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON), \ 311480093f4SDimitry Andric INSTR_PROF_DATA_COFF, "__DATA,") 312480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_cnts, \ 313480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON), \ 314480093f4SDimitry Andric INSTR_PROF_CNTS_COFF, "__DATA,") 3155f757f3fSDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_bitmap, \ 3165f757f3fSDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_BITS_COMMON), \ 3175f757f3fSDimitry Andric INSTR_PROF_BITS_COFF, "__DATA,") 318480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_name, \ 319480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON), \ 320480093f4SDimitry Andric INSTR_PROF_NAME_COFF, "__DATA,") 321*0fca6ea1SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_vname, \ 322*0fca6ea1SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VNAME_COMMON), \ 323*0fca6ea1SDimitry Andric INSTR_PROF_VNAME_COFF, "__DATA,") 324480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_vals, \ 325480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON), \ 326480093f4SDimitry Andric INSTR_PROF_VALS_COFF, "__DATA,") 327480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_vnodes, \ 328480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON), \ 329480093f4SDimitry Andric INSTR_PROF_VNODES_COFF, "__DATA,") 330*0fca6ea1SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_vtab, \ 331*0fca6ea1SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VTAB_COMMON), \ 332*0fca6ea1SDimitry Andric INSTR_PROF_VTAB_COFF, "__DATA,") 333480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_covmap, \ 334480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON), \ 335480093f4SDimitry Andric INSTR_PROF_COVMAP_COFF, "__LLVM_COV,") 3365ffd83dbSDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_covfun, \ 3375ffd83dbSDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_COVFUN_COMMON), \ 3385ffd83dbSDimitry Andric INSTR_PROF_COVFUN_COFF, "__LLVM_COV,") 339480093f4SDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_orderfile, \ 340480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON), \ 341480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COFF), "__DATA,") 3425f757f3fSDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_covdata, \ 3435f757f3fSDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_COVDATA_COMMON), \ 3445f757f3fSDimitry Andric INSTR_PROF_COVDATA_COFF, "__LLVM_COV,") 3455f757f3fSDimitry AndricINSTR_PROF_SECT_ENTRY(IPSK_covname, \ 3465f757f3fSDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_COVNAME_COMMON), \ 3475f757f3fSDimitry Andric INSTR_PROF_COVNAME_COFF, "__LLVM_COV,") 348480093f4SDimitry Andric 349480093f4SDimitry Andric#undef INSTR_PROF_SECT_ENTRY 350480093f4SDimitry Andric#endif 351480093f4SDimitry Andric 352480093f4SDimitry Andric 353480093f4SDimitry Andric#ifdef INSTR_PROF_VALUE_PROF_DATA 354480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 355480093f4SDimitry Andric 356480093f4SDimitry Andric#define INSTR_PROF_MAX_NUM_VAL_PER_SITE 255 357480093f4SDimitry Andric/*! 358480093f4SDimitry Andric * This is the header of the data structure that defines the on-disk 359480093f4SDimitry Andric * layout of the value profile data of a particular kind for one function. 360480093f4SDimitry Andric */ 361480093f4SDimitry Andrictypedef struct ValueProfRecord { 362480093f4SDimitry Andric /* The kind of the value profile record. */ 363480093f4SDimitry Andric uint32_t Kind; 364480093f4SDimitry Andric /* 365480093f4SDimitry Andric * The number of value profile sites. It is guaranteed to be non-zero; 366480093f4SDimitry Andric * otherwise the record for this kind won't be emitted. 367480093f4SDimitry Andric */ 368480093f4SDimitry Andric uint32_t NumValueSites; 369480093f4SDimitry Andric /* 370480093f4SDimitry Andric * The first element of the array that stores the number of profiled 371480093f4SDimitry Andric * values for each value site. The size of the array is NumValueSites. 372480093f4SDimitry Andric * Since NumValueSites is greater than zero, there is at least one 373480093f4SDimitry Andric * element in the array. 374480093f4SDimitry Andric */ 375480093f4SDimitry Andric uint8_t SiteCountArray[1]; 376480093f4SDimitry Andric 377480093f4SDimitry Andric /* 378480093f4SDimitry Andric * The fake declaration is for documentation purpose only. 379480093f4SDimitry Andric * Align the start of next field to be on 8 byte boundaries. 380480093f4SDimitry Andric uint8_t Padding[X]; 381480093f4SDimitry Andric */ 382480093f4SDimitry Andric 383480093f4SDimitry Andric /* The array of value profile data. The size of the array is the sum 384480093f4SDimitry Andric * of all elements in SiteCountArray[]. 385480093f4SDimitry Andric InstrProfValueData ValueData[]; 386480093f4SDimitry Andric */ 387480093f4SDimitry Andric 388480093f4SDimitry Andric#ifdef __cplusplus 389480093f4SDimitry Andric /*! 390480093f4SDimitry Andric * Return the number of value sites. 391480093f4SDimitry Andric */ 392480093f4SDimitry Andric uint32_t getNumValueSites() const { return NumValueSites; } 393480093f4SDimitry Andric /*! 394480093f4SDimitry Andric * Read data from this record and save it to Record. 395480093f4SDimitry Andric */ 396480093f4SDimitry Andric void deserializeTo(InstrProfRecord &Record, 397480093f4SDimitry Andric InstrProfSymtab *SymTab); 398480093f4SDimitry Andric /* 399480093f4SDimitry Andric * In-place byte swap: 400480093f4SDimitry Andric * Do byte swap for this instance. \c Old is the original order before 401480093f4SDimitry Andric * the swap, and \c New is the New byte order. 402480093f4SDimitry Andric */ 4035f757f3fSDimitry Andric void swapBytes(llvm::endianness Old, llvm::endianness New); 404480093f4SDimitry Andric#endif 405480093f4SDimitry Andric} ValueProfRecord; 406480093f4SDimitry Andric 407480093f4SDimitry Andric/*! 408480093f4SDimitry Andric * Per-function header/control data structure for value profiling 409480093f4SDimitry Andric * data in indexed format. 410480093f4SDimitry Andric */ 411480093f4SDimitry Andrictypedef struct ValueProfData { 412480093f4SDimitry Andric /* 413480093f4SDimitry Andric * Total size in bytes including this field. It must be a multiple 414480093f4SDimitry Andric * of sizeof(uint64_t). 415480093f4SDimitry Andric */ 416480093f4SDimitry Andric uint32_t TotalSize; 417480093f4SDimitry Andric /* 418480093f4SDimitry Andric *The number of value profile kinds that has value profile data. 419480093f4SDimitry Andric * In this implementation, a value profile kind is considered to 420480093f4SDimitry Andric * have profile data if the number of value profile sites for the 421480093f4SDimitry Andric * kind is not zero. More aggressively, the implementation can 422480093f4SDimitry Andric * choose to check the actual data value: if none of the value sites 423480093f4SDimitry Andric * has any profiled values, the kind can be skipped. 424480093f4SDimitry Andric */ 425480093f4SDimitry Andric uint32_t NumValueKinds; 426480093f4SDimitry Andric 427480093f4SDimitry Andric /* 428480093f4SDimitry Andric * Following are a sequence of variable length records. The prefix/header 429480093f4SDimitry Andric * of each record is defined by ValueProfRecord type. The number of 430480093f4SDimitry Andric * records is NumValueKinds. 431480093f4SDimitry Andric * ValueProfRecord Record_1; 432480093f4SDimitry Andric * ValueProfRecord Record_N; 433480093f4SDimitry Andric */ 434480093f4SDimitry Andric 435480093f4SDimitry Andric#if __cplusplus 436480093f4SDimitry Andric /*! 437480093f4SDimitry Andric * Return the total size in bytes of the on-disk value profile data 438480093f4SDimitry Andric * given the data stored in Record. 439480093f4SDimitry Andric */ 440480093f4SDimitry Andric static uint32_t getSize(const InstrProfRecord &Record); 441480093f4SDimitry Andric /*! 442480093f4SDimitry Andric * Return a pointer to \c ValueProfData instance ready to be streamed. 443480093f4SDimitry Andric */ 444480093f4SDimitry Andric static std::unique_ptr<ValueProfData> 445480093f4SDimitry Andric serializeFrom(const InstrProfRecord &Record); 446480093f4SDimitry Andric /*! 447480093f4SDimitry Andric * Check the integrity of the record. 448480093f4SDimitry Andric */ 449480093f4SDimitry Andric Error checkIntegrity(); 450480093f4SDimitry Andric /*! 451480093f4SDimitry Andric * Return a pointer to \c ValueProfileData instance ready to be read. 452480093f4SDimitry Andric * All data in the instance are properly byte swapped. The input 453480093f4SDimitry Andric * data is assumed to be in little endian order. 454480093f4SDimitry Andric */ 455480093f4SDimitry Andric static Expected<std::unique_ptr<ValueProfData>> 456480093f4SDimitry Andric getValueProfData(const unsigned char *SrcBuffer, 457480093f4SDimitry Andric const unsigned char *const SrcBufferEnd, 4585f757f3fSDimitry Andric llvm::endianness SrcDataEndianness); 459480093f4SDimitry Andric /*! 460480093f4SDimitry Andric * Swap byte order from \c Endianness order to host byte order. 461480093f4SDimitry Andric */ 4625f757f3fSDimitry Andric void swapBytesToHost(llvm::endianness Endianness); 463480093f4SDimitry Andric /*! 464480093f4SDimitry Andric * Swap byte order from host byte order to \c Endianness order. 465480093f4SDimitry Andric */ 4665f757f3fSDimitry Andric void swapBytesFromHost(llvm::endianness Endianness); 467480093f4SDimitry Andric /*! 468480093f4SDimitry Andric * Return the total size of \c ValueProfileData. 469480093f4SDimitry Andric */ 470480093f4SDimitry Andric uint32_t getSize() const { return TotalSize; } 471480093f4SDimitry Andric /*! 472480093f4SDimitry Andric * Read data from this data and save it to \c Record. 473480093f4SDimitry Andric */ 474480093f4SDimitry Andric void deserializeTo(InstrProfRecord &Record, 475480093f4SDimitry Andric InstrProfSymtab *SymTab); 476480093f4SDimitry Andric void operator delete(void *ptr) { ::operator delete(ptr); } 477480093f4SDimitry Andric#endif 478480093f4SDimitry Andric} ValueProfData; 479480093f4SDimitry Andric 480480093f4SDimitry Andric/* 481480093f4SDimitry Andric * The closure is designed to abstact away two types of value profile data: 482480093f4SDimitry Andric * - InstrProfRecord which is the primary data structure used to 483480093f4SDimitry Andric * represent profile data in host tools (reader, writer, and profile-use) 484480093f4SDimitry Andric * - value profile runtime data structure suitable to be used by C 485480093f4SDimitry Andric * runtime library. 486480093f4SDimitry Andric * 487480093f4SDimitry Andric * Both sources of data need to serialize to disk/memory-buffer in common 488480093f4SDimitry Andric * format: ValueProfData. The abstraction allows compiler-rt's raw profiler 489480093f4SDimitry Andric * writer to share the same format and code with indexed profile writer. 490480093f4SDimitry Andric * 491480093f4SDimitry Andric * For documentation of the member methods below, refer to corresponding methods 492480093f4SDimitry Andric * in class InstrProfRecord. 493480093f4SDimitry Andric */ 494480093f4SDimitry Andrictypedef struct ValueProfRecordClosure { 495480093f4SDimitry Andric const void *Record; 496480093f4SDimitry Andric uint32_t (*GetNumValueKinds)(const void *Record); 497480093f4SDimitry Andric uint32_t (*GetNumValueSites)(const void *Record, uint32_t VKind); 498480093f4SDimitry Andric uint32_t (*GetNumValueData)(const void *Record, uint32_t VKind); 499480093f4SDimitry Andric uint32_t (*GetNumValueDataForSite)(const void *R, uint32_t VK, uint32_t S); 500480093f4SDimitry Andric 501480093f4SDimitry Andric /* 502480093f4SDimitry Andric * After extracting the value profile data from the value profile record, 503480093f4SDimitry Andric * this method is used to map the in-memory value to on-disk value. If 504480093f4SDimitry Andric * the method is null, value will be written out untranslated. 505480093f4SDimitry Andric */ 506480093f4SDimitry Andric uint64_t (*RemapValueData)(uint32_t, uint64_t Value); 507480093f4SDimitry Andric void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K, 508480093f4SDimitry Andric uint32_t S); 509480093f4SDimitry Andric ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes); 510480093f4SDimitry Andric} ValueProfRecordClosure; 511480093f4SDimitry Andric 512480093f4SDimitry AndricINSTR_PROF_VISIBILITY ValueProfRecord * 513480093f4SDimitry AndricgetFirstValueProfRecord(ValueProfData *VPD); 514480093f4SDimitry AndricINSTR_PROF_VISIBILITY ValueProfRecord * 515480093f4SDimitry AndricgetValueProfRecordNext(ValueProfRecord *VPR); 516480093f4SDimitry AndricINSTR_PROF_VISIBILITY InstrProfValueData * 517480093f4SDimitry AndricgetValueProfRecordValueData(ValueProfRecord *VPR); 518480093f4SDimitry AndricINSTR_PROF_VISIBILITY uint32_t 519480093f4SDimitry AndricgetValueProfRecordHeaderSize(uint32_t NumValueSites); 520480093f4SDimitry Andric 521480093f4SDimitry Andric#undef INSTR_PROF_VALUE_PROF_DATA 522480093f4SDimitry Andric#endif /* INSTR_PROF_VALUE_PROF_DATA */ 523480093f4SDimitry Andric 524480093f4SDimitry Andric 525480093f4SDimitry Andric#ifdef INSTR_PROF_COMMON_API_IMPL 526480093f4SDimitry Andric#define INSTR_PROF_DATA_DEFINED 527480093f4SDimitry Andric#ifdef __cplusplus 528480093f4SDimitry Andric#define INSTR_PROF_INLINE inline 529480093f4SDimitry Andric#define INSTR_PROF_NULLPTR nullptr 530480093f4SDimitry Andric#else 531480093f4SDimitry Andric#define INSTR_PROF_INLINE 532480093f4SDimitry Andric#define INSTR_PROF_NULLPTR NULL 533480093f4SDimitry Andric#endif 534480093f4SDimitry Andric 535480093f4SDimitry Andric#ifndef offsetof 536480093f4SDimitry Andric#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 537480093f4SDimitry Andric#endif 538480093f4SDimitry Andric 539*0fca6ea1SDimitry Andric// clang-format on 540*0fca6ea1SDimitry Andric 541480093f4SDimitry Andric/*! 542480093f4SDimitry Andric * Return the \c ValueProfRecord header size including the 543480093f4SDimitry Andric * padding bytes. 544480093f4SDimitry Andric */ 545*0fca6ea1SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE uint32_t 546*0fca6ea1SDimitry AndricgetValueProfRecordHeaderSize(uint32_t NumValueSites) { 547480093f4SDimitry Andric uint32_t Size = offsetof(ValueProfRecord, SiteCountArray) + 548480093f4SDimitry Andric sizeof(uint8_t) * NumValueSites; 549480093f4SDimitry Andric /* Round the size to multiple of 8 bytes. */ 550480093f4SDimitry Andric Size = (Size + 7) & ~7; 551480093f4SDimitry Andric return Size; 552480093f4SDimitry Andric} 553480093f4SDimitry Andric 554480093f4SDimitry Andric/*! 555480093f4SDimitry Andric * Return the total size of the value profile record including the 556480093f4SDimitry Andric * header and the value data. 557480093f4SDimitry Andric */ 558*0fca6ea1SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE uint32_t 559*0fca6ea1SDimitry AndricgetValueProfRecordSize(uint32_t NumValueSites, uint32_t NumValueData) { 560480093f4SDimitry Andric return getValueProfRecordHeaderSize(NumValueSites) + 561480093f4SDimitry Andric sizeof(InstrProfValueData) * NumValueData; 562480093f4SDimitry Andric} 563480093f4SDimitry Andric 564480093f4SDimitry Andric/*! 565480093f4SDimitry Andric * Return the pointer to the start of value data array. 566480093f4SDimitry Andric */ 567*0fca6ea1SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE InstrProfValueData * 568*0fca6ea1SDimitry AndricgetValueProfRecordValueData(ValueProfRecord *This) { 569480093f4SDimitry Andric return (InstrProfValueData *)((char *)This + getValueProfRecordHeaderSize( 570480093f4SDimitry Andric This->NumValueSites)); 571480093f4SDimitry Andric} 572480093f4SDimitry Andric 573480093f4SDimitry Andric/*! 574480093f4SDimitry Andric * Return the total number of value data for \c This record. 575480093f4SDimitry Andric */ 576*0fca6ea1SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE uint32_t 577*0fca6ea1SDimitry AndricgetValueProfRecordNumValueData(ValueProfRecord *This) { 578480093f4SDimitry Andric uint32_t NumValueData = 0; 579480093f4SDimitry Andric uint32_t I; 580480093f4SDimitry Andric for (I = 0; I < This->NumValueSites; I++) 581480093f4SDimitry Andric NumValueData += This->SiteCountArray[I]; 582480093f4SDimitry Andric return NumValueData; 583480093f4SDimitry Andric} 584480093f4SDimitry Andric 585480093f4SDimitry Andric/*! 586480093f4SDimitry Andric * Use this method to advance to the next \c This \c ValueProfRecord. 587480093f4SDimitry Andric */ 588*0fca6ea1SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE ValueProfRecord * 589*0fca6ea1SDimitry AndricgetValueProfRecordNext(ValueProfRecord *This) { 590480093f4SDimitry Andric uint32_t NumValueData = getValueProfRecordNumValueData(This); 591480093f4SDimitry Andric return (ValueProfRecord *)((char *)This + 592480093f4SDimitry Andric getValueProfRecordSize(This->NumValueSites, 593480093f4SDimitry Andric NumValueData)); 594480093f4SDimitry Andric} 595480093f4SDimitry Andric 596480093f4SDimitry Andric/*! 597480093f4SDimitry Andric * Return the first \c ValueProfRecord instance. 598480093f4SDimitry Andric */ 599*0fca6ea1SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE ValueProfRecord * 600*0fca6ea1SDimitry AndricgetFirstValueProfRecord(ValueProfData *This) { 601480093f4SDimitry Andric return (ValueProfRecord *)((char *)This + sizeof(ValueProfData)); 602480093f4SDimitry Andric} 603480093f4SDimitry Andric 604480093f4SDimitry Andric/* Closure based interfaces. */ 605480093f4SDimitry Andric 606480093f4SDimitry Andric/*! 607480093f4SDimitry Andric * Return the total size in bytes of the on-disk value profile data 608480093f4SDimitry Andric * given the data stored in Record. 609480093f4SDimitry Andric */ 610480093f4SDimitry AndricINSTR_PROF_VISIBILITY uint32_t 611480093f4SDimitry AndricgetValueProfDataSize(ValueProfRecordClosure *Closure) { 612480093f4SDimitry Andric uint32_t Kind; 613480093f4SDimitry Andric uint32_t TotalSize = sizeof(ValueProfData); 614480093f4SDimitry Andric const void *Record = Closure->Record; 615480093f4SDimitry Andric 616480093f4SDimitry Andric for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { 617480093f4SDimitry Andric uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind); 618480093f4SDimitry Andric if (!NumValueSites) 619480093f4SDimitry Andric continue; 620480093f4SDimitry Andric TotalSize += getValueProfRecordSize(NumValueSites, 621480093f4SDimitry Andric Closure->GetNumValueData(Record, Kind)); 622480093f4SDimitry Andric } 623480093f4SDimitry Andric return TotalSize; 624480093f4SDimitry Andric} 625480093f4SDimitry Andric 626480093f4SDimitry Andric/*! 627480093f4SDimitry Andric * Extract value profile data of a function for the profile kind \c ValueKind 628480093f4SDimitry Andric * from the \c Closure and serialize the data into \c This record instance. 629480093f4SDimitry Andric */ 630480093f4SDimitry AndricINSTR_PROF_VISIBILITY void 631480093f4SDimitry AndricserializeValueProfRecordFrom(ValueProfRecord *This, 632480093f4SDimitry Andric ValueProfRecordClosure *Closure, 633480093f4SDimitry Andric uint32_t ValueKind, uint32_t NumValueSites) { 634480093f4SDimitry Andric uint32_t S; 635480093f4SDimitry Andric const void *Record = Closure->Record; 636480093f4SDimitry Andric This->Kind = ValueKind; 637480093f4SDimitry Andric This->NumValueSites = NumValueSites; 638480093f4SDimitry Andric InstrProfValueData *DstVD = getValueProfRecordValueData(This); 639480093f4SDimitry Andric 640480093f4SDimitry Andric for (S = 0; S < NumValueSites; S++) { 641480093f4SDimitry Andric uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S); 642480093f4SDimitry Andric This->SiteCountArray[S] = ND; 643480093f4SDimitry Andric Closure->GetValueForSite(Record, DstVD, ValueKind, S); 644480093f4SDimitry Andric DstVD += ND; 645480093f4SDimitry Andric } 646480093f4SDimitry Andric} 647480093f4SDimitry Andric 648480093f4SDimitry Andric/*! 649480093f4SDimitry Andric * Extract value profile data of a function from the \c Closure 650480093f4SDimitry Andric * and serialize the data into \c DstData if it is not NULL or heap 651480093f4SDimitry Andric * memory allocated by the \c Closure's allocator method. If \c 652480093f4SDimitry Andric * DstData is not null, the caller is expected to set the TotalSize 653480093f4SDimitry Andric * in DstData. 654480093f4SDimitry Andric */ 655480093f4SDimitry AndricINSTR_PROF_VISIBILITY ValueProfData * 656480093f4SDimitry AndricserializeValueProfDataFrom(ValueProfRecordClosure *Closure, 657480093f4SDimitry Andric ValueProfData *DstData) { 658480093f4SDimitry Andric uint32_t Kind; 659480093f4SDimitry Andric uint32_t TotalSize = 660480093f4SDimitry Andric DstData ? DstData->TotalSize : getValueProfDataSize(Closure); 661480093f4SDimitry Andric 662480093f4SDimitry Andric ValueProfData *VPD = 663480093f4SDimitry Andric DstData ? DstData : Closure->AllocValueProfData(TotalSize); 664480093f4SDimitry Andric 665480093f4SDimitry Andric VPD->TotalSize = TotalSize; 666480093f4SDimitry Andric VPD->NumValueKinds = Closure->GetNumValueKinds(Closure->Record); 667480093f4SDimitry Andric ValueProfRecord *VR = getFirstValueProfRecord(VPD); 668480093f4SDimitry Andric for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) { 669480093f4SDimitry Andric uint32_t NumValueSites = Closure->GetNumValueSites(Closure->Record, Kind); 670480093f4SDimitry Andric if (!NumValueSites) 671480093f4SDimitry Andric continue; 672480093f4SDimitry Andric serializeValueProfRecordFrom(VR, Closure, Kind, NumValueSites); 673480093f4SDimitry Andric VR = getValueProfRecordNext(VR); 674480093f4SDimitry Andric } 675480093f4SDimitry Andric return VPD; 676480093f4SDimitry Andric} 677480093f4SDimitry Andric 678480093f4SDimitry Andric#undef INSTR_PROF_COMMON_API_IMPL 679480093f4SDimitry Andric#endif /* INSTR_PROF_COMMON_API_IMPL */ 680480093f4SDimitry Andric 681480093f4SDimitry Andric/*============================================================================*/ 682480093f4SDimitry Andric 683*0fca6ea1SDimitry Andric// clang-format off:consider re-enabling clang-format if auto-formatted C macros 684*0fca6ea1SDimitry Andric// are readable (e.g., after `issue #82426` is fixed) 685480093f4SDimitry Andric#ifndef INSTR_PROF_DATA_DEFINED 686480093f4SDimitry Andric 687480093f4SDimitry Andric#ifndef INSTR_PROF_DATA_INC 688480093f4SDimitry Andric#define INSTR_PROF_DATA_INC 689480093f4SDimitry Andric 690480093f4SDimitry Andric/* Helper macros. */ 691480093f4SDimitry Andric#define INSTR_PROF_SIMPLE_QUOTE(x) #x 692480093f4SDimitry Andric#define INSTR_PROF_QUOTE(x) INSTR_PROF_SIMPLE_QUOTE(x) 693480093f4SDimitry Andric#define INSTR_PROF_SIMPLE_CONCAT(x,y) x ## y 694480093f4SDimitry Andric#define INSTR_PROF_CONCAT(x,y) INSTR_PROF_SIMPLE_CONCAT(x,y) 695480093f4SDimitry Andric 696480093f4SDimitry Andric/* Magic number to detect file format and endianness. 697480093f4SDimitry Andric * Use 255 at one end, since no UTF-8 file can use that character. Avoid 0, 698480093f4SDimitry Andric * so that utilities, like strings, don't grab it as a string. 129 is also 699480093f4SDimitry Andric * invalid UTF-8, and high enough to be interesting. 700480093f4SDimitry Andric * Use "lprofr" in the centre to stand for "LLVM Profile Raw", or "lprofR" 701480093f4SDimitry Andric * for 32-bit platforms. 702480093f4SDimitry Andric */ 703480093f4SDimitry Andric#define INSTR_PROF_RAW_MAGIC_64 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \ 704480093f4SDimitry Andric (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ 705480093f4SDimitry Andric (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129 706480093f4SDimitry Andric#define INSTR_PROF_RAW_MAGIC_32 (uint64_t)255 << 56 | (uint64_t)'l' << 48 | \ 707480093f4SDimitry Andric (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | (uint64_t)'o' << 24 | \ 708480093f4SDimitry Andric (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129 709480093f4SDimitry Andric 710480093f4SDimitry Andric/* Raw profile format version (start from 1). */ 711*0fca6ea1SDimitry Andric#define INSTR_PROF_RAW_VERSION 10 712480093f4SDimitry Andric/* Indexed profile format version (start from 1). */ 713*0fca6ea1SDimitry Andric#define INSTR_PROF_INDEX_VERSION 12 7145ffd83dbSDimitry Andric/* Coverage mapping format version (start from 0). */ 7155f757f3fSDimitry Andric#define INSTR_PROF_COVMAP_VERSION 6 716480093f4SDimitry Andric 7175f757f3fSDimitry Andric/* Profile version is always of type uint64_t. Reserve the upper 32 bits in the 7185f757f3fSDimitry Andric * version for other variants of profile. We set the 8th most significant bit 7195f757f3fSDimitry Andric * (i.e. bit 56) to 1 to indicate if this is an IR-level instrumentation 720480093f4SDimitry Andric * generated profile, and 0 if this is a Clang FE generated profile. 721480093f4SDimitry Andric * 1 in bit 57 indicates there are context-sensitive records in the profile. 7220eae32dcSDimitry Andric * The 59th bit indicates whether to use debug info to correlate profiles. 7231fd87a68SDimitry Andric * The 60th bit indicates single byte coverage instrumentation. 7241fd87a68SDimitry Andric * The 61st bit indicates function entry instrumentation only. 72581ad6265SDimitry Andric * The 62nd bit indicates whether memory profile information is present. 72606c3fb27SDimitry Andric * The 63rd bit indicates if this is a temporal profile. 727480093f4SDimitry Andric */ 7285f757f3fSDimitry Andric#define VARIANT_MASKS_ALL 0xffffffff00000000ULL 729480093f4SDimitry Andric#define GET_VERSION(V) ((V) & ~VARIANT_MASKS_ALL) 730480093f4SDimitry Andric#define VARIANT_MASK_IR_PROF (0x1ULL << 56) 731480093f4SDimitry Andric#define VARIANT_MASK_CSIR_PROF (0x1ULL << 57) 732e8d8bef9SDimitry Andric#define VARIANT_MASK_INSTR_ENTRY (0x1ULL << 58) 7330eae32dcSDimitry Andric#define VARIANT_MASK_DBG_CORRELATE (0x1ULL << 59) 7341fd87a68SDimitry Andric#define VARIANT_MASK_BYTE_COVERAGE (0x1ULL << 60) 7351fd87a68SDimitry Andric#define VARIANT_MASK_FUNCTION_ENTRY_ONLY (0x1ULL << 61) 73681ad6265SDimitry Andric#define VARIANT_MASK_MEMPROF (0x1ULL << 62) 73706c3fb27SDimitry Andric#define VARIANT_MASK_TEMPORAL_PROF (0x1ULL << 63) 738480093f4SDimitry Andric#define INSTR_PROF_RAW_VERSION_VAR __llvm_profile_raw_version 739480093f4SDimitry Andric#define INSTR_PROF_PROFILE_RUNTIME_VAR __llvm_profile_runtime 740fe6060f1SDimitry Andric#define INSTR_PROF_PROFILE_COUNTER_BIAS_VAR __llvm_profile_counter_bias 74106c3fb27SDimitry Andric#define INSTR_PROF_PROFILE_SET_TIMESTAMP __llvm_profile_set_timestamp 742*0fca6ea1SDimitry Andric#define INSTR_PROF_PROFILE_SAMPLING_VAR __llvm_profile_sampling 743480093f4SDimitry Andric 744480093f4SDimitry Andric/* The variable that holds the name of the profile data 745480093f4SDimitry Andric * specified via command line. */ 746480093f4SDimitry Andric#define INSTR_PROF_PROFILE_NAME_VAR __llvm_profile_filename 747480093f4SDimitry Andric 748480093f4SDimitry Andric/* section name strings common to all targets other 749480093f4SDimitry Andric than WIN32 */ 750480093f4SDimitry Andric#define INSTR_PROF_DATA_COMMON __llvm_prf_data 751480093f4SDimitry Andric#define INSTR_PROF_NAME_COMMON __llvm_prf_names 752*0fca6ea1SDimitry Andric#define INSTR_PROF_VNAME_COMMON __llvm_prf_vns 753480093f4SDimitry Andric#define INSTR_PROF_CNTS_COMMON __llvm_prf_cnts 7545f757f3fSDimitry Andric#define INSTR_PROF_BITS_COMMON __llvm_prf_bits 755480093f4SDimitry Andric#define INSTR_PROF_VALS_COMMON __llvm_prf_vals 756480093f4SDimitry Andric#define INSTR_PROF_VNODES_COMMON __llvm_prf_vnds 757*0fca6ea1SDimitry Andric#define INSTR_PROF_VTAB_COMMON __llvm_prf_vtab 758480093f4SDimitry Andric#define INSTR_PROF_COVMAP_COMMON __llvm_covmap 7595ffd83dbSDimitry Andric#define INSTR_PROF_COVFUN_COMMON __llvm_covfun 7605f757f3fSDimitry Andric#define INSTR_PROF_COVDATA_COMMON __llvm_covdata 7615f757f3fSDimitry Andric#define INSTR_PROF_COVNAME_COMMON __llvm_covnames 762480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_COMMON __llvm_orderfile 763480093f4SDimitry Andric/* Windows section names. Because these section names contain dollar characters, 764480093f4SDimitry Andric * they must be quoted. 765480093f4SDimitry Andric */ 766480093f4SDimitry Andric#define INSTR_PROF_DATA_COFF ".lprfd$M" 767480093f4SDimitry Andric#define INSTR_PROF_NAME_COFF ".lprfn$M" 768*0fca6ea1SDimitry Andric#define INSTR_PROF_VNAME_COFF ".lprfvn$M" 769480093f4SDimitry Andric#define INSTR_PROF_CNTS_COFF ".lprfc$M" 7705f757f3fSDimitry Andric#define INSTR_PROF_BITS_COFF ".lprfb$M" 771480093f4SDimitry Andric#define INSTR_PROF_VALS_COFF ".lprfv$M" 772480093f4SDimitry Andric#define INSTR_PROF_VNODES_COFF ".lprfnd$M" 773*0fca6ea1SDimitry Andric#define INSTR_PROF_VTAB_COFF ".lprfvt$M" 774480093f4SDimitry Andric#define INSTR_PROF_COVMAP_COFF ".lcovmap$M" 7755ffd83dbSDimitry Andric#define INSTR_PROF_COVFUN_COFF ".lcovfun$M" 7765f757f3fSDimitry Andric/* Since cov data and cov names sections are not allocated, we don't need to 7775f757f3fSDimitry Andric * access them at runtime. 7785f757f3fSDimitry Andric */ 7795f757f3fSDimitry Andric#define INSTR_PROF_COVDATA_COFF ".lcovd" 7805f757f3fSDimitry Andric#define INSTR_PROF_COVNAME_COFF ".lcovn" 781480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_COFF ".lorderfile$M" 782480093f4SDimitry Andric 783480093f4SDimitry Andric#ifdef _WIN32 784480093f4SDimitry Andric/* Runtime section names and name strings. */ 785480093f4SDimitry Andric#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_DATA_COFF 786480093f4SDimitry Andric#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_NAME_COFF 787480093f4SDimitry Andric#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_CNTS_COFF 7885f757f3fSDimitry Andric#define INSTR_PROF_BITS_SECT_NAME INSTR_PROF_BITS_COFF 789*0fca6ea1SDimitry Andric#define INSTR_PROF_VTAB_SECT_NAME INSTR_PROF_VTAB_COFF 790*0fca6ea1SDimitry Andric#define INSTR_PROF_VNAME_SECT_NAME INSTR_PROF_VNAME_COFF 791480093f4SDimitry Andric/* Array of pointers. Each pointer points to a list 792480093f4SDimitry Andric * of value nodes associated with one value site. 793480093f4SDimitry Andric */ 794480093f4SDimitry Andric#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_VALS_COFF 795480093f4SDimitry Andric/* Value profile nodes section. */ 796480093f4SDimitry Andric#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_VNODES_COFF 797480093f4SDimitry Andric#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_COVMAP_COFF 7985ffd83dbSDimitry Andric#define INSTR_PROF_COVFUN_SECT_NAME INSTR_PROF_COVFUN_COFF 7995f757f3fSDimitry Andric#define INSTR_PROF_COVDATA_SECT_NAME INSTR_PROF_COVDATA_COFF 8005f757f3fSDimitry Andric#define INSTR_PROF_COVNAME_SECT_NAME INSTR_PROF_COVNAME_COFF 801480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_SECT_NAME INSTR_PROF_ORDERFILE_COFF 802480093f4SDimitry Andric#else 803480093f4SDimitry Andric/* Runtime section names and name strings. */ 804480093f4SDimitry Andric#define INSTR_PROF_DATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_DATA_COMMON) 805480093f4SDimitry Andric#define INSTR_PROF_NAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_NAME_COMMON) 806480093f4SDimitry Andric#define INSTR_PROF_CNTS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_CNTS_COMMON) 8075f757f3fSDimitry Andric#define INSTR_PROF_BITS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_BITS_COMMON) 808*0fca6ea1SDimitry Andric#define INSTR_PROF_VTAB_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VTAB_COMMON) 809*0fca6ea1SDimitry Andric#define INSTR_PROF_VNAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VNAME_COMMON) 810480093f4SDimitry Andric/* Array of pointers. Each pointer points to a list 811480093f4SDimitry Andric * of value nodes associated with one value site. 812480093f4SDimitry Andric */ 813480093f4SDimitry Andric#define INSTR_PROF_VALS_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VALS_COMMON) 814480093f4SDimitry Andric/* Value profile nodes section. */ 815480093f4SDimitry Andric#define INSTR_PROF_VNODES_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_VNODES_COMMON) 816480093f4SDimitry Andric#define INSTR_PROF_COVMAP_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVMAP_COMMON) 8175ffd83dbSDimitry Andric#define INSTR_PROF_COVFUN_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVFUN_COMMON) 8185f757f3fSDimitry Andric#define INSTR_PROF_COVDATA_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVDATA_COMMON) 8195f757f3fSDimitry Andric#define INSTR_PROF_COVNAME_SECT_NAME INSTR_PROF_QUOTE(INSTR_PROF_COVNAME_COMMON) 820480093f4SDimitry Andric/* Order file instrumentation. */ 821480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_SECT_NAME \ 822480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_COMMON) 823480093f4SDimitry Andric#endif 824480093f4SDimitry Andric 825480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_BUFFER_NAME _llvm_order_file_buffer 826480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_BUFFER_NAME_STR \ 827480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_NAME) 828480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME _llvm_order_file_buffer_idx 829480093f4SDimitry Andric#define INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME_STR \ 830480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_ORDERFILE_BUFFER_IDX_NAME) 831480093f4SDimitry Andric 832480093f4SDimitry Andric/* Macros to define start/stop section symbol for a given 833480093f4SDimitry Andric * section on Linux. For instance 834480093f4SDimitry Andric * INSTR_PROF_SECT_START(INSTR_PROF_DATA_SECT_NAME) will 835480093f4SDimitry Andric * expand to __start___llvm_prof_data 836480093f4SDimitry Andric */ 837480093f4SDimitry Andric#define INSTR_PROF_SECT_START(Sect) \ 838480093f4SDimitry Andric INSTR_PROF_CONCAT(__start_,Sect) 839480093f4SDimitry Andric#define INSTR_PROF_SECT_STOP(Sect) \ 840480093f4SDimitry Andric INSTR_PROF_CONCAT(__stop_,Sect) 841480093f4SDimitry Andric 842480093f4SDimitry Andric/* Value Profiling API linkage name. */ 843480093f4SDimitry Andric#define INSTR_PROF_VALUE_PROF_FUNC __llvm_profile_instrument_target 844480093f4SDimitry Andric#define INSTR_PROF_VALUE_PROF_FUNC_STR \ 845480093f4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_FUNC) 846e8d8bef9SDimitry Andric#define INSTR_PROF_VALUE_PROF_MEMOP_FUNC __llvm_profile_instrument_memop 847e8d8bef9SDimitry Andric#define INSTR_PROF_VALUE_PROF_MEMOP_FUNC_STR \ 848e8d8bef9SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_VALUE_PROF_MEMOP_FUNC) 849480093f4SDimitry Andric 850480093f4SDimitry Andric/* InstrProfile per-function control data alignment. */ 851480093f4SDimitry Andric#define INSTR_PROF_DATA_ALIGNMENT 8 852480093f4SDimitry Andric 853480093f4SDimitry Andric/* The data structure that represents a tracked value by the 854480093f4SDimitry Andric * value profiler. 855480093f4SDimitry Andric */ 856480093f4SDimitry Andrictypedef struct InstrProfValueData { 857480093f4SDimitry Andric /* Profiled value. */ 858480093f4SDimitry Andric uint64_t Value; 859480093f4SDimitry Andric /* Number of times the value appears in the training run. */ 860480093f4SDimitry Andric uint64_t Count; 861480093f4SDimitry Andric} InstrProfValueData; 862480093f4SDimitry Andric 863480093f4SDimitry Andric#endif /* INSTR_PROF_DATA_INC */ 864480093f4SDimitry Andric 865480093f4SDimitry Andric#ifndef INSTR_ORDER_FILE_INC 866480093f4SDimitry Andric/* The maximal # of functions: 128*1024 (the buffer size will be 128*4 KB). */ 867480093f4SDimitry Andric#define INSTR_ORDER_FILE_BUFFER_SIZE 131072 868480093f4SDimitry Andric#define INSTR_ORDER_FILE_BUFFER_BITS 17 869480093f4SDimitry Andric#define INSTR_ORDER_FILE_BUFFER_MASK 0x1ffff 870480093f4SDimitry Andric#endif /* INSTR_ORDER_FILE_INC */ 871480093f4SDimitry Andric#else 872480093f4SDimitry Andric#undef INSTR_PROF_DATA_DEFINED 873480093f4SDimitry Andric#endif 8745ffd83dbSDimitry Andric 8755ffd83dbSDimitry Andric#undef COVMAP_V2_OR_V3 876e8d8bef9SDimitry Andric 877e8d8bef9SDimitry Andric#ifdef INSTR_PROF_VALUE_PROF_MEMOP_API 878e8d8bef9SDimitry Andric 879e8d8bef9SDimitry Andric#ifdef __cplusplus 880e8d8bef9SDimitry Andric#define INSTR_PROF_INLINE inline 881e8d8bef9SDimitry Andric#else 882e8d8bef9SDimitry Andric#define INSTR_PROF_INLINE 883e8d8bef9SDimitry Andric#endif 884e8d8bef9SDimitry Andric 885e8d8bef9SDimitry Andric/* The value range buckets (22 buckets) for the memop size value profiling looks 886e8d8bef9SDimitry Andric * like: 887e8d8bef9SDimitry Andric * 888e8d8bef9SDimitry Andric * [0, 0] 889e8d8bef9SDimitry Andric * [1, 1] 890e8d8bef9SDimitry Andric * [2, 2] 891e8d8bef9SDimitry Andric * [3, 3] 892e8d8bef9SDimitry Andric * [4, 4] 893e8d8bef9SDimitry Andric * [5, 5] 894e8d8bef9SDimitry Andric * [6, 6] 895e8d8bef9SDimitry Andric * [7, 7] 896e8d8bef9SDimitry Andric * [8, 8] 897e8d8bef9SDimitry Andric * [9, 15] 898e8d8bef9SDimitry Andric * [16, 16] 899e8d8bef9SDimitry Andric * [17, 31] 900e8d8bef9SDimitry Andric * [32, 32] 901e8d8bef9SDimitry Andric * [33, 63] 902e8d8bef9SDimitry Andric * [64, 64] 903e8d8bef9SDimitry Andric * [65, 127] 904e8d8bef9SDimitry Andric * [128, 128] 905e8d8bef9SDimitry Andric * [129, 255] 906e8d8bef9SDimitry Andric * [256, 256] 907e8d8bef9SDimitry Andric * [257, 511] 908e8d8bef9SDimitry Andric * [512, 512] 909e8d8bef9SDimitry Andric * [513, UINT64_MAX] 910e8d8bef9SDimitry Andric * 911e8d8bef9SDimitry Andric * Each range has a 'representative value' which is the lower end value of the 912e8d8bef9SDimitry Andric * range and used to store in the runtime profile data records and the VP 913e8d8bef9SDimitry Andric * metadata. For example, it's 2 for [2, 2] and 64 for [65, 127]. 914e8d8bef9SDimitry Andric */ 915fe6060f1SDimitry Andric#define INSTR_PROF_NUM_BUCKETS 22 916e8d8bef9SDimitry Andric 917e8d8bef9SDimitry Andric/* 918e8d8bef9SDimitry Andric * Clz and Popcount. This code was copied from 919e8d8bef9SDimitry Andric * compiler-rt/lib/fuzzer/{FuzzerBuiltins.h,FuzzerBuiltinsMsvc.h} and 920e8d8bef9SDimitry Andric * llvm/include/llvm/Support/MathExtras.h. 921e8d8bef9SDimitry Andric */ 922e8d8bef9SDimitry Andric#if defined(_MSC_VER) && !defined(__clang__) 923e8d8bef9SDimitry Andric 924e8d8bef9SDimitry Andric#include <intrin.h> 925e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 926e8d8bef9SDimitry Andricint InstProfClzll(unsigned long long X) { 927e8d8bef9SDimitry Andric unsigned long LeadZeroIdx = 0; 928e8d8bef9SDimitry Andric#if !defined(_M_ARM64) && !defined(_M_X64) 929e8d8bef9SDimitry Andric // Scan the high 32 bits. 930e8d8bef9SDimitry Andric if (_BitScanReverse(&LeadZeroIdx, (unsigned long)(X >> 32))) 931e8d8bef9SDimitry Andric return (int)(63 - (LeadZeroIdx + 32)); // Create a bit offset 932e8d8bef9SDimitry Andric // from the MSB. 933e8d8bef9SDimitry Andric // Scan the low 32 bits. 934e8d8bef9SDimitry Andric if (_BitScanReverse(&LeadZeroIdx, (unsigned long)(X))) 935e8d8bef9SDimitry Andric return (int)(63 - LeadZeroIdx); 936e8d8bef9SDimitry Andric#else 937e8d8bef9SDimitry Andric if (_BitScanReverse64(&LeadZeroIdx, X)) return 63 - LeadZeroIdx; 938e8d8bef9SDimitry Andric#endif 939e8d8bef9SDimitry Andric return 64; 940e8d8bef9SDimitry Andric} 941e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 942e8d8bef9SDimitry Andricint InstProfPopcountll(unsigned long long X) { 943e8d8bef9SDimitry Andric // This code originates from https://reviews.llvm.org/rG30626254510f. 944e8d8bef9SDimitry Andric unsigned long long v = X; 945e8d8bef9SDimitry Andric v = v - ((v >> 1) & 0x5555555555555555ULL); 946e8d8bef9SDimitry Andric v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); 947e8d8bef9SDimitry Andric v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; 948e8d8bef9SDimitry Andric return (int)((unsigned long long)(v * 0x0101010101010101ULL) >> 56); 949e8d8bef9SDimitry Andric} 950e8d8bef9SDimitry Andric 951e8d8bef9SDimitry Andric#else 952e8d8bef9SDimitry Andric 953e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 954e8d8bef9SDimitry Andricint InstProfClzll(unsigned long long X) { return __builtin_clzll(X); } 955e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE 956e8d8bef9SDimitry Andricint InstProfPopcountll(unsigned long long X) { return __builtin_popcountll(X); } 957e8d8bef9SDimitry Andric 958e8d8bef9SDimitry Andric#endif /* defined(_MSC_VER) && !defined(__clang__) */ 959e8d8bef9SDimitry Andric 960*0fca6ea1SDimitry Andric// clang-format on 961*0fca6ea1SDimitry Andric 962e8d8bef9SDimitry Andric/* Map an (observed) memop size value to the representative value of its range. 963e8d8bef9SDimitry Andric * For example, 5 -> 5, 22 -> 17, 99 -> 65, 256 -> 256, 1001 -> 513. */ 964e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE uint64_t 965e8d8bef9SDimitry AndricInstrProfGetRangeRepValue(uint64_t Value) { 966e8d8bef9SDimitry Andric if (Value <= 8) 967e8d8bef9SDimitry Andric // The first ranges are individually tracked. Use the value as is. 968e8d8bef9SDimitry Andric return Value; 969e8d8bef9SDimitry Andric else if (Value >= 513) 970e8d8bef9SDimitry Andric // The last range is mapped to its lowest value. 971e8d8bef9SDimitry Andric return 513; 972e8d8bef9SDimitry Andric else if (InstProfPopcountll(Value) == 1) 973e8d8bef9SDimitry Andric // If it's a power of two, use it as is. 974e8d8bef9SDimitry Andric return Value; 975e8d8bef9SDimitry Andric else 976e8d8bef9SDimitry Andric // Otherwise, take to the previous power of two + 1. 977fe6060f1SDimitry Andric return (UINT64_C(1) << (64 - InstProfClzll(Value) - 1)) + 1; 978e8d8bef9SDimitry Andric} 979e8d8bef9SDimitry Andric 980e8d8bef9SDimitry Andric/* Return true if the range that an (observed) memop size value belongs to has 981e8d8bef9SDimitry Andric * only a single value in the range. For example, 0 -> true, 8 -> true, 10 -> 982e8d8bef9SDimitry Andric * false, 64 -> true, 100 -> false, 513 -> false. */ 983e8d8bef9SDimitry AndricINSTR_PROF_VISIBILITY INSTR_PROF_INLINE unsigned 984e8d8bef9SDimitry AndricInstrProfIsSingleValRange(uint64_t Value) { 985e8d8bef9SDimitry Andric if (Value <= 8) 986e8d8bef9SDimitry Andric // The first ranges are individually tracked. 987e8d8bef9SDimitry Andric return 1; 988e8d8bef9SDimitry Andric else if (InstProfPopcountll(Value) == 1) 989e8d8bef9SDimitry Andric // If it's a power of two, there's only one value. 990e8d8bef9SDimitry Andric return 1; 991e8d8bef9SDimitry Andric else 992e8d8bef9SDimitry Andric // Otherwise, there's more than one value in the range. 993e8d8bef9SDimitry Andric return 0; 994e8d8bef9SDimitry Andric} 995e8d8bef9SDimitry Andric 996e8d8bef9SDimitry Andric#endif /* INSTR_PROF_VALUE_PROF_MEMOP_API */ 997