10b57cec5SDimitry Andric //===- PGOInstrumentation.cpp - MST-based PGO Instrumentation -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements PGO instrumentation using a minimum spanning tree based 100b57cec5SDimitry Andric // on the following paper: 110b57cec5SDimitry Andric // [1] Donald E. Knuth, Francis R. Stevenson. Optimal measurement of points 120b57cec5SDimitry Andric // for program frequency counts. BIT Numerical Mathematics 1973, Volume 13, 130b57cec5SDimitry Andric // Issue 3, pp 313-322 140b57cec5SDimitry Andric // The idea of the algorithm based on the fact that for each node (except for 150b57cec5SDimitry Andric // the entry and exit), the sum of incoming edge counts equals the sum of 160b57cec5SDimitry Andric // outgoing edge counts. The count of edge on spanning tree can be derived from 170b57cec5SDimitry Andric // those edges not on the spanning tree. Knuth proves this method instruments 180b57cec5SDimitry Andric // the minimum number of edges. 190b57cec5SDimitry Andric // 200b57cec5SDimitry Andric // The minimal spanning tree here is actually a maximum weight tree -- on-tree 210b57cec5SDimitry Andric // edges have higher frequencies (more likely to execute). The idea is to 220b57cec5SDimitry Andric // instrument those less frequently executed edges to reduce the runtime 230b57cec5SDimitry Andric // overhead of instrumented binaries. 240b57cec5SDimitry Andric // 250b57cec5SDimitry Andric // This file contains two passes: 260b57cec5SDimitry Andric // (1) Pass PGOInstrumentationGen which instruments the IR to generate edge 270b57cec5SDimitry Andric // count profile, and generates the instrumentation for indirect call 280b57cec5SDimitry Andric // profiling. 290b57cec5SDimitry Andric // (2) Pass PGOInstrumentationUse which reads the edge count profile and 300b57cec5SDimitry Andric // annotates the branch weights. It also reads the indirect call value 310b57cec5SDimitry Andric // profiling records and annotate the indirect call instructions. 320b57cec5SDimitry Andric // 330b57cec5SDimitry Andric // To get the precise counter information, These two passes need to invoke at 340b57cec5SDimitry Andric // the same compilation point (so they see the same IR). For pass 350b57cec5SDimitry Andric // PGOInstrumentationGen, the real work is done in instrumentOneFunc(). For 360b57cec5SDimitry Andric // pass PGOInstrumentationUse, the real work in done in class PGOUseFunc and 370b57cec5SDimitry Andric // the profile is opened in module level and passed to each PGOUseFunc instance. 380b57cec5SDimitry Andric // The shared code for PGOInstrumentationGen and PGOInstrumentationUse is put 390b57cec5SDimitry Andric // in class FuncPGOInstrumentation. 400b57cec5SDimitry Andric // 410b57cec5SDimitry Andric // Class PGOEdge represents a CFG edge and some auxiliary information. Class 420b57cec5SDimitry Andric // BBInfo contains auxiliary information for each BB. These two classes are used 430b57cec5SDimitry Andric // in pass PGOInstrumentationGen. Class PGOUseEdge and UseBBInfo are the derived 440b57cec5SDimitry Andric // class of PGOEdge and BBInfo, respectively. They contains extra data structure 450b57cec5SDimitry Andric // used in populating profile counters. 460b57cec5SDimitry Andric // The MST implementation is in Class CFGMST (CFGMST.h). 470b57cec5SDimitry Andric // 480b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 490b57cec5SDimitry Andric 50480093f4SDimitry Andric #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" 518bcb0991SDimitry Andric #include "ValueProfileCollector.h" 520b57cec5SDimitry Andric #include "llvm/ADT/APInt.h" 530b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 540b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 550b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 560b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 570b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 580b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 590b57cec5SDimitry Andric #include "llvm/ADT/iterator.h" 600b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 610b57cec5SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h" 620b57cec5SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h" 630b57cec5SDimitry Andric #include "llvm/Analysis/CFG.h" 640b57cec5SDimitry Andric #include "llvm/Analysis/LoopInfo.h" 650b57cec5SDimitry Andric #include "llvm/Analysis/OptimizationRemarkEmitter.h" 660b57cec5SDimitry Andric #include "llvm/Analysis/ProfileSummaryInfo.h" 6781ad6265SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 680b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 690b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 700b57cec5SDimitry Andric #include "llvm/IR/CFG.h" 710b57cec5SDimitry Andric #include "llvm/IR/Comdat.h" 720b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 730b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 740b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 750b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 7606c3fb27SDimitry Andric #include "llvm/IR/EHPersonalities.h" 770b57cec5SDimitry Andric #include "llvm/IR/Function.h" 780b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h" 790b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 800b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 810b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 820b57cec5SDimitry Andric #include "llvm/IR/InstVisitor.h" 830b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 840b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 850b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 860b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 870b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 880b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 890b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h" 900b57cec5SDimitry Andric #include "llvm/IR/Module.h" 910b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 92bdd1243dSDimitry Andric #include "llvm/IR/ProfDataUtils.h" 930b57cec5SDimitry Andric #include "llvm/IR/ProfileSummary.h" 940b57cec5SDimitry Andric #include "llvm/IR/Type.h" 950b57cec5SDimitry Andric #include "llvm/IR/Value.h" 960b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h" 970b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h" 980b57cec5SDimitry Andric #include "llvm/Support/BranchProbability.h" 998bcb0991SDimitry Andric #include "llvm/Support/CRC.h" 1000b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 1010b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 1020b57cec5SDimitry Andric #include "llvm/Support/DOTGraphTraits.h" 1030b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 1040b57cec5SDimitry Andric #include "llvm/Support/Error.h" 1050b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 1060b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h" 10706c3fb27SDimitry Andric #include "llvm/Support/VirtualFileSystem.h" 1080b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 10906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 1100b57cec5SDimitry Andric #include "llvm/Transforms/Instrumentation.h" 11106c3fb27SDimitry Andric #include "llvm/Transforms/Instrumentation/BlockCoverageInference.h" 11206c3fb27SDimitry Andric #include "llvm/Transforms/Instrumentation/CFGMST.h" 1130fca6ea1SDimitry Andric #include "llvm/Transforms/Instrumentation/PGOCtxProfLowering.h" 1140b57cec5SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h" 11581ad6265SDimitry Andric #include "llvm/Transforms/Utils/MisExpect.h" 116349cc55cSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h" 1170b57cec5SDimitry Andric #include <algorithm> 1180b57cec5SDimitry Andric #include <cassert> 1190b57cec5SDimitry Andric #include <cstdint> 1200b57cec5SDimitry Andric #include <memory> 1210b57cec5SDimitry Andric #include <numeric> 122bdd1243dSDimitry Andric #include <optional> 1230fca6ea1SDimitry Andric #include <stack> 1240b57cec5SDimitry Andric #include <string> 1250b57cec5SDimitry Andric #include <unordered_map> 1260b57cec5SDimitry Andric #include <utility> 1270b57cec5SDimitry Andric #include <vector> 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric using namespace llvm; 1300b57cec5SDimitry Andric using ProfileCount = Function::ProfileCount; 1318bcb0991SDimitry Andric using VPCandidateInfo = ValueProfileCollector::CandidateInfo; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric #define DEBUG_TYPE "pgo-instrumentation" 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric STATISTIC(NumOfPGOInstrument, "Number of edges instrumented."); 1360b57cec5SDimitry Andric STATISTIC(NumOfPGOSelectInsts, "Number of select instruction instrumented."); 1370b57cec5SDimitry Andric STATISTIC(NumOfPGOMemIntrinsics, "Number of mem intrinsics instrumented."); 1380b57cec5SDimitry Andric STATISTIC(NumOfPGOEdge, "Number of edges."); 1390b57cec5SDimitry Andric STATISTIC(NumOfPGOBB, "Number of basic-blocks."); 1400b57cec5SDimitry Andric STATISTIC(NumOfPGOSplit, "Number of critical edge splits."); 1410b57cec5SDimitry Andric STATISTIC(NumOfPGOFunc, "Number of functions having valid profile counts."); 1420b57cec5SDimitry Andric STATISTIC(NumOfPGOMismatch, "Number of functions having mismatch profile."); 1430b57cec5SDimitry Andric STATISTIC(NumOfPGOMissing, "Number of functions without profile."); 1440b57cec5SDimitry Andric STATISTIC(NumOfPGOICall, "Number of indirect call value instrumentations."); 1450b57cec5SDimitry Andric STATISTIC(NumOfCSPGOInstrument, "Number of edges instrumented in CSPGO."); 1460b57cec5SDimitry Andric STATISTIC(NumOfCSPGOSelectInsts, 1470b57cec5SDimitry Andric "Number of select instruction instrumented in CSPGO."); 1480b57cec5SDimitry Andric STATISTIC(NumOfCSPGOMemIntrinsics, 1490b57cec5SDimitry Andric "Number of mem intrinsics instrumented in CSPGO."); 1500b57cec5SDimitry Andric STATISTIC(NumOfCSPGOEdge, "Number of edges in CSPGO."); 1510b57cec5SDimitry Andric STATISTIC(NumOfCSPGOBB, "Number of basic-blocks in CSPGO."); 1520b57cec5SDimitry Andric STATISTIC(NumOfCSPGOSplit, "Number of critical edge splits in CSPGO."); 1530b57cec5SDimitry Andric STATISTIC(NumOfCSPGOFunc, 1540b57cec5SDimitry Andric "Number of functions having valid profile counts in CSPGO."); 1550b57cec5SDimitry Andric STATISTIC(NumOfCSPGOMismatch, 1560b57cec5SDimitry Andric "Number of functions having mismatch profile in CSPGO."); 1570b57cec5SDimitry Andric STATISTIC(NumOfCSPGOMissing, "Number of functions without profile in CSPGO."); 15806c3fb27SDimitry Andric STATISTIC(NumCoveredBlocks, "Number of basic blocks that were executed"); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // Command line option to specify the file to read profile from. This is 1610b57cec5SDimitry Andric // mainly used for testing. 1620b57cec5SDimitry Andric static cl::opt<std::string> 1630b57cec5SDimitry Andric PGOTestProfileFile("pgo-test-profile-file", cl::init(""), cl::Hidden, 1640b57cec5SDimitry Andric cl::value_desc("filename"), 1650b57cec5SDimitry Andric cl::desc("Specify the path of profile data file. This is" 1660b57cec5SDimitry Andric "mainly for test purpose.")); 1670b57cec5SDimitry Andric static cl::opt<std::string> PGOTestProfileRemappingFile( 1680b57cec5SDimitry Andric "pgo-test-profile-remapping-file", cl::init(""), cl::Hidden, 1690b57cec5SDimitry Andric cl::value_desc("filename"), 1700b57cec5SDimitry Andric cl::desc("Specify the path of profile remapping file. This is mainly for " 1710b57cec5SDimitry Andric "test purpose.")); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric // Command line option to disable value profiling. The default is false: 1740b57cec5SDimitry Andric // i.e. value profiling is enabled by default. This is for debug purpose. 1750b57cec5SDimitry Andric static cl::opt<bool> DisableValueProfiling("disable-vp", cl::init(false), 1760b57cec5SDimitry Andric cl::Hidden, 1770b57cec5SDimitry Andric cl::desc("Disable Value Profiling")); 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric // Command line option to set the maximum number of VP annotations to write to 1800b57cec5SDimitry Andric // the metadata for a single indirect call callsite. 1810b57cec5SDimitry Andric static cl::opt<unsigned> MaxNumAnnotations( 18281ad6265SDimitry Andric "icp-max-annotations", cl::init(3), cl::Hidden, 1830b57cec5SDimitry Andric cl::desc("Max number of annotations for a single indirect " 1840b57cec5SDimitry Andric "call callsite")); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // Command line option to set the maximum number of value annotations 1870b57cec5SDimitry Andric // to write to the metadata for a single memop intrinsic. 1880b57cec5SDimitry Andric static cl::opt<unsigned> MaxNumMemOPAnnotations( 18981ad6265SDimitry Andric "memop-max-annotations", cl::init(4), cl::Hidden, 1900b57cec5SDimitry Andric cl::desc("Max number of preicise value annotations for a single memop" 1910b57cec5SDimitry Andric "intrinsic")); 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric // Command line option to control appending FunctionHash to the name of a COMDAT 1940b57cec5SDimitry Andric // function. This is to avoid the hash mismatch caused by the preinliner. 1950b57cec5SDimitry Andric static cl::opt<bool> DoComdatRenaming( 1960b57cec5SDimitry Andric "do-comdat-renaming", cl::init(false), cl::Hidden, 1970b57cec5SDimitry Andric cl::desc("Append function hash to the name of COMDAT function to avoid " 1980b57cec5SDimitry Andric "function hash mismatch due to the preinliner")); 1990b57cec5SDimitry Andric 20006c3fb27SDimitry Andric namespace llvm { 2010b57cec5SDimitry Andric // Command line option to enable/disable the warning about missing profile 2020b57cec5SDimitry Andric // information. 20306c3fb27SDimitry Andric cl::opt<bool> PGOWarnMissing("pgo-warn-missing-function", cl::init(false), 20406c3fb27SDimitry Andric cl::Hidden, 2050b57cec5SDimitry Andric cl::desc("Use this option to turn on/off " 2060b57cec5SDimitry Andric "warnings about missing profile data for " 2070b57cec5SDimitry Andric "functions.")); 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric // Command line option to enable/disable the warning about a hash mismatch in 2100b57cec5SDimitry Andric // the profile data. 211349cc55cSDimitry Andric cl::opt<bool> 2120b57cec5SDimitry Andric NoPGOWarnMismatch("no-pgo-warn-mismatch", cl::init(false), cl::Hidden, 2130b57cec5SDimitry Andric cl::desc("Use this option to turn off/on " 2140b57cec5SDimitry Andric "warnings about profile cfg mismatch.")); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // Command line option to enable/disable the warning about a hash mismatch in 2170b57cec5SDimitry Andric // the profile data for Comdat functions, which often turns out to be false 2180b57cec5SDimitry Andric // positive due to the pre-instrumentation inline. 21906c3fb27SDimitry Andric cl::opt<bool> NoPGOWarnMismatchComdatWeak( 220fcaf7f86SDimitry Andric "no-pgo-warn-mismatch-comdat-weak", cl::init(true), cl::Hidden, 2210b57cec5SDimitry Andric cl::desc("The option is used to turn on/off " 2220b57cec5SDimitry Andric "warnings about hash mismatch for comdat " 223fcaf7f86SDimitry Andric "or weak functions.")); 22406c3fb27SDimitry Andric } // namespace llvm 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric // Command line option to enable/disable select instruction instrumentation. 2270b57cec5SDimitry Andric static cl::opt<bool> 2280b57cec5SDimitry Andric PGOInstrSelect("pgo-instr-select", cl::init(true), cl::Hidden, 2290b57cec5SDimitry Andric cl::desc("Use this option to turn on/off SELECT " 2300b57cec5SDimitry Andric "instruction instrumentation. ")); 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric // Command line option to turn on CFG dot or text dump of raw profile counts 2330b57cec5SDimitry Andric static cl::opt<PGOViewCountsType> PGOViewRawCounts( 2340b57cec5SDimitry Andric "pgo-view-raw-counts", cl::Hidden, 2350b57cec5SDimitry Andric cl::desc("A boolean option to show CFG dag or text " 2360b57cec5SDimitry Andric "with raw profile counts from " 2370b57cec5SDimitry Andric "profile data. See also option " 2380b57cec5SDimitry Andric "-pgo-view-counts. To limit graph " 2390b57cec5SDimitry Andric "display to only one function, use " 2400b57cec5SDimitry Andric "filtering option -view-bfi-func-name."), 2410b57cec5SDimitry Andric cl::values(clEnumValN(PGOVCT_None, "none", "do not show."), 2420b57cec5SDimitry Andric clEnumValN(PGOVCT_Graph, "graph", "show a graph."), 2430b57cec5SDimitry Andric clEnumValN(PGOVCT_Text, "text", "show in text."))); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric // Command line option to enable/disable memop intrinsic call.size profiling. 2460b57cec5SDimitry Andric static cl::opt<bool> 2470b57cec5SDimitry Andric PGOInstrMemOP("pgo-instr-memop", cl::init(true), cl::Hidden, 2480b57cec5SDimitry Andric cl::desc("Use this option to turn on/off " 2490b57cec5SDimitry Andric "memory intrinsic size profiling.")); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric // Emit branch probability as optimization remarks. 2520b57cec5SDimitry Andric static cl::opt<bool> 2530b57cec5SDimitry Andric EmitBranchProbability("pgo-emit-branch-prob", cl::init(false), cl::Hidden, 2540b57cec5SDimitry Andric cl::desc("When this option is on, the annotated " 2550b57cec5SDimitry Andric "branch probability will be emitted as " 2560b57cec5SDimitry Andric "optimization remarks: -{Rpass|" 2570b57cec5SDimitry Andric "pass-remarks}=pgo-instrumentation")); 2580b57cec5SDimitry Andric 259e8d8bef9SDimitry Andric static cl::opt<bool> PGOInstrumentEntry( 260e8d8bef9SDimitry Andric "pgo-instrument-entry", cl::init(false), cl::Hidden, 261e8d8bef9SDimitry Andric cl::desc("Force to instrument function entry basicblock.")); 262e8d8bef9SDimitry Andric 2631fd87a68SDimitry Andric static cl::opt<bool> PGOFunctionEntryCoverage( 26481ad6265SDimitry Andric "pgo-function-entry-coverage", cl::Hidden, 2651fd87a68SDimitry Andric cl::desc( 2661fd87a68SDimitry Andric "Use this option to enable function entry coverage instrumentation.")); 2671fd87a68SDimitry Andric 26806c3fb27SDimitry Andric static cl::opt<bool> PGOBlockCoverage( 26906c3fb27SDimitry Andric "pgo-block-coverage", 27006c3fb27SDimitry Andric cl::desc("Use this option to enable basic block coverage instrumentation")); 27106c3fb27SDimitry Andric 27206c3fb27SDimitry Andric static cl::opt<bool> 27306c3fb27SDimitry Andric PGOViewBlockCoverageGraph("pgo-view-block-coverage-graph", 27406c3fb27SDimitry Andric cl::desc("Create a dot file of CFGs with block " 27506c3fb27SDimitry Andric "coverage inference information")); 27606c3fb27SDimitry Andric 27706c3fb27SDimitry Andric static cl::opt<bool> PGOTemporalInstrumentation( 27806c3fb27SDimitry Andric "pgo-temporal-instrumentation", 27906c3fb27SDimitry Andric cl::desc("Use this option to enable temporal instrumentation")); 28006c3fb27SDimitry Andric 281e8d8bef9SDimitry Andric static cl::opt<bool> 282e8d8bef9SDimitry Andric PGOFixEntryCount("pgo-fix-entry-count", cl::init(true), cl::Hidden, 283e8d8bef9SDimitry Andric cl::desc("Fix function entry count in profile use.")); 284e8d8bef9SDimitry Andric 285e8d8bef9SDimitry Andric static cl::opt<bool> PGOVerifyHotBFI( 286e8d8bef9SDimitry Andric "pgo-verify-hot-bfi", cl::init(false), cl::Hidden, 287e8d8bef9SDimitry Andric cl::desc("Print out the non-match BFI count if a hot raw profile count " 288e8d8bef9SDimitry Andric "becomes non-hot, or a cold raw profile count becomes hot. " 289e8d8bef9SDimitry Andric "The print is enabled under -Rpass-analysis=pgo, or " 290e8d8bef9SDimitry Andric "internal option -pass-remakrs-analysis=pgo.")); 291e8d8bef9SDimitry Andric 292e8d8bef9SDimitry Andric static cl::opt<bool> PGOVerifyBFI( 293e8d8bef9SDimitry Andric "pgo-verify-bfi", cl::init(false), cl::Hidden, 294e8d8bef9SDimitry Andric cl::desc("Print out mismatched BFI counts after setting profile metadata " 295e8d8bef9SDimitry Andric "The print is enabled under -Rpass-analysis=pgo, or " 296e8d8bef9SDimitry Andric "internal option -pass-remakrs-analysis=pgo.")); 297e8d8bef9SDimitry Andric 298e8d8bef9SDimitry Andric static cl::opt<unsigned> PGOVerifyBFIRatio( 2990eae32dcSDimitry Andric "pgo-verify-bfi-ratio", cl::init(2), cl::Hidden, 3000eae32dcSDimitry Andric cl::desc("Set the threshold for pgo-verify-bfi: only print out " 301e8d8bef9SDimitry Andric "mismatched BFI if the difference percentage is greater than " 302e8d8bef9SDimitry Andric "this value (in percentage).")); 303e8d8bef9SDimitry Andric 304e8d8bef9SDimitry Andric static cl::opt<unsigned> PGOVerifyBFICutoff( 3050eae32dcSDimitry Andric "pgo-verify-bfi-cutoff", cl::init(5), cl::Hidden, 3060eae32dcSDimitry Andric cl::desc("Set the threshold for pgo-verify-bfi: skip the counts whose " 307e8d8bef9SDimitry Andric "profile count value is below.")); 308e8d8bef9SDimitry Andric 309fcaf7f86SDimitry Andric static cl::opt<std::string> PGOTraceFuncHash( 310fcaf7f86SDimitry Andric "pgo-trace-func-hash", cl::init("-"), cl::Hidden, 311fcaf7f86SDimitry Andric cl::value_desc("function name"), 312fcaf7f86SDimitry Andric cl::desc("Trace the hash of the function with this name.")); 313fcaf7f86SDimitry Andric 314bdd1243dSDimitry Andric static cl::opt<unsigned> PGOFunctionSizeThreshold( 315bdd1243dSDimitry Andric "pgo-function-size-threshold", cl::Hidden, 316bdd1243dSDimitry Andric cl::desc("Do not instrument functions smaller than this threshold.")); 317bdd1243dSDimitry Andric 318bdd1243dSDimitry Andric static cl::opt<unsigned> PGOFunctionCriticalEdgeThreshold( 319bdd1243dSDimitry Andric "pgo-critical-edge-threshold", cl::init(20000), cl::Hidden, 320bdd1243dSDimitry Andric cl::desc("Do not instrument functions with the number of critical edges " 321bdd1243dSDimitry Andric " greater than this threshold.")); 322bdd1243dSDimitry Andric 3230fca6ea1SDimitry Andric extern cl::opt<unsigned> MaxNumVTableAnnotations; 3240fca6ea1SDimitry Andric 325fe6060f1SDimitry Andric namespace llvm { 3260b57cec5SDimitry Andric // Command line option to turn on CFG dot dump after profile annotation. 3270b57cec5SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp: -pgo-view-counts 3280b57cec5SDimitry Andric extern cl::opt<PGOViewCountsType> PGOViewCounts; 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Command line option to specify the name of the function for CFG dump 3310b57cec5SDimitry Andric // Defined in Analysis/BlockFrequencyInfo.cpp: -view-bfi-func-name= 3320b57cec5SDimitry Andric extern cl::opt<std::string> ViewBlockFreqFuncName; 3330eae32dcSDimitry Andric 3340fca6ea1SDimitry Andric // Command line option to enable vtable value profiling. Defined in 3350fca6ea1SDimitry Andric // ProfileData/InstrProf.cpp: -enable-vtable-value-profiling= 3360fca6ea1SDimitry Andric extern cl::opt<bool> EnableVTableValueProfiling; 3370fca6ea1SDimitry Andric extern cl::opt<bool> EnableVTableProfileUse; 3385f757f3fSDimitry Andric extern cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate; 339fe6060f1SDimitry Andric } // namespace llvm 3400b57cec5SDimitry Andric 3410fca6ea1SDimitry Andric bool shouldInstrumentEntryBB() { 3420fca6ea1SDimitry Andric return PGOInstrumentEntry || 3430fca6ea1SDimitry Andric PGOCtxProfLoweringPass::isContextualIRPGOEnabled(); 3440fca6ea1SDimitry Andric } 3450fca6ea1SDimitry Andric 3460fca6ea1SDimitry Andric // FIXME(mtrofin): re-enable this for ctx profiling, for non-indirect calls. Ctx 3470fca6ea1SDimitry Andric // profiling implicitly captures indirect call cases, but not other values. 3480fca6ea1SDimitry Andric // Supporting other values is relatively straight-forward - just another counter 3490fca6ea1SDimitry Andric // range within the context. 3500fca6ea1SDimitry Andric bool isValueProfilingDisabled() { 3510fca6ea1SDimitry Andric return DisableValueProfiling || 3520fca6ea1SDimitry Andric PGOCtxProfLoweringPass::isContextualIRPGOEnabled(); 3530fca6ea1SDimitry Andric } 3540fca6ea1SDimitry Andric 3550b57cec5SDimitry Andric // Return a string describing the branch condition that can be 3560b57cec5SDimitry Andric // used in static branch probability heuristics: 3570b57cec5SDimitry Andric static std::string getBranchCondString(Instruction *TI) { 3580b57cec5SDimitry Andric BranchInst *BI = dyn_cast<BranchInst>(TI); 3590b57cec5SDimitry Andric if (!BI || !BI->isConditional()) 3600b57cec5SDimitry Andric return std::string(); 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric Value *Cond = BI->getCondition(); 3630b57cec5SDimitry Andric ICmpInst *CI = dyn_cast<ICmpInst>(Cond); 3640b57cec5SDimitry Andric if (!CI) 3650b57cec5SDimitry Andric return std::string(); 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric std::string result; 3680b57cec5SDimitry Andric raw_string_ostream OS(result); 36906c3fb27SDimitry Andric OS << CI->getPredicate() << "_"; 3700b57cec5SDimitry Andric CI->getOperand(0)->getType()->print(OS, true); 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric Value *RHS = CI->getOperand(1); 3730b57cec5SDimitry Andric ConstantInt *CV = dyn_cast<ConstantInt>(RHS); 3740b57cec5SDimitry Andric if (CV) { 3750b57cec5SDimitry Andric if (CV->isZero()) 3760b57cec5SDimitry Andric OS << "_Zero"; 3770b57cec5SDimitry Andric else if (CV->isOne()) 3780b57cec5SDimitry Andric OS << "_One"; 3790b57cec5SDimitry Andric else if (CV->isMinusOne()) 3800b57cec5SDimitry Andric OS << "_MinusOne"; 3810b57cec5SDimitry Andric else 3820b57cec5SDimitry Andric OS << "_Const"; 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric OS.flush(); 3850b57cec5SDimitry Andric return result; 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric 3888bcb0991SDimitry Andric static const char *ValueProfKindDescr[] = { 3898bcb0991SDimitry Andric #define VALUE_PROF_KIND(Enumerator, Value, Descr) Descr, 3908bcb0991SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc" 3918bcb0991SDimitry Andric }; 3928bcb0991SDimitry Andric 3931fd87a68SDimitry Andric // Create a COMDAT variable INSTR_PROF_RAW_VERSION_VAR to make the runtime 3941fd87a68SDimitry Andric // aware this is an ir_level profile so it can set the version flag. 3951fd87a68SDimitry Andric static GlobalVariable *createIRLevelProfileFlagVar(Module &M, bool IsCS) { 3961fd87a68SDimitry Andric const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_RAW_VERSION_VAR)); 3971fd87a68SDimitry Andric Type *IntTy64 = Type::getInt64Ty(M.getContext()); 3981fd87a68SDimitry Andric uint64_t ProfileVersion = (INSTR_PROF_RAW_VERSION | VARIANT_MASK_IR_PROF); 3991fd87a68SDimitry Andric if (IsCS) 4001fd87a68SDimitry Andric ProfileVersion |= VARIANT_MASK_CSIR_PROF; 4010fca6ea1SDimitry Andric if (shouldInstrumentEntryBB()) 4021fd87a68SDimitry Andric ProfileVersion |= VARIANT_MASK_INSTR_ENTRY; 4035f757f3fSDimitry Andric if (DebugInfoCorrelate || ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO) 4041fd87a68SDimitry Andric ProfileVersion |= VARIANT_MASK_DBG_CORRELATE; 4051fd87a68SDimitry Andric if (PGOFunctionEntryCoverage) 4061fd87a68SDimitry Andric ProfileVersion |= 4071fd87a68SDimitry Andric VARIANT_MASK_BYTE_COVERAGE | VARIANT_MASK_FUNCTION_ENTRY_ONLY; 40806c3fb27SDimitry Andric if (PGOBlockCoverage) 40906c3fb27SDimitry Andric ProfileVersion |= VARIANT_MASK_BYTE_COVERAGE; 41006c3fb27SDimitry Andric if (PGOTemporalInstrumentation) 41106c3fb27SDimitry Andric ProfileVersion |= VARIANT_MASK_TEMPORAL_PROF; 4121fd87a68SDimitry Andric auto IRLevelVersionVariable = new GlobalVariable( 4131fd87a68SDimitry Andric M, IntTy64, true, GlobalValue::WeakAnyLinkage, 4141fd87a68SDimitry Andric Constant::getIntegerValue(IntTy64, APInt(64, ProfileVersion)), VarName); 415bdd1243dSDimitry Andric IRLevelVersionVariable->setVisibility(GlobalValue::HiddenVisibility); 4161fd87a68SDimitry Andric Triple TT(M.getTargetTriple()); 4171fd87a68SDimitry Andric if (TT.supportsCOMDAT()) { 4181fd87a68SDimitry Andric IRLevelVersionVariable->setLinkage(GlobalValue::ExternalLinkage); 4191fd87a68SDimitry Andric IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName)); 4201fd87a68SDimitry Andric } 4211fd87a68SDimitry Andric return IRLevelVersionVariable; 4221fd87a68SDimitry Andric } 4231fd87a68SDimitry Andric 4240b57cec5SDimitry Andric namespace { 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric /// The select instruction visitor plays three roles specified 4270b57cec5SDimitry Andric /// by the mode. In \c VM_counting mode, it simply counts the number of 4280b57cec5SDimitry Andric /// select instructions. In \c VM_instrument mode, it inserts code to count 4290b57cec5SDimitry Andric /// the number times TrueValue of select is taken. In \c VM_annotate mode, 4300b57cec5SDimitry Andric /// it reads the profile data and annotate the select instruction with metadata. 4310b57cec5SDimitry Andric enum VisitMode { VM_counting, VM_instrument, VM_annotate }; 4320b57cec5SDimitry Andric class PGOUseFunc; 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric /// Instruction Visitor class to visit select instructions. 4350b57cec5SDimitry Andric struct SelectInstVisitor : public InstVisitor<SelectInstVisitor> { 4360b57cec5SDimitry Andric Function &F; 4370b57cec5SDimitry Andric unsigned NSIs = 0; // Number of select instructions instrumented. 4380b57cec5SDimitry Andric VisitMode Mode = VM_counting; // Visiting mode. 4390b57cec5SDimitry Andric unsigned *CurCtrIdx = nullptr; // Pointer to current counter index. 4400b57cec5SDimitry Andric unsigned TotalNumCtrs = 0; // Total number of counters 4410b57cec5SDimitry Andric GlobalVariable *FuncNameVar = nullptr; 4420b57cec5SDimitry Andric uint64_t FuncHash = 0; 4430b57cec5SDimitry Andric PGOUseFunc *UseFunc = nullptr; 44406c3fb27SDimitry Andric bool HasSingleByteCoverage; 4450b57cec5SDimitry Andric 44606c3fb27SDimitry Andric SelectInstVisitor(Function &Func, bool HasSingleByteCoverage) 44706c3fb27SDimitry Andric : F(Func), HasSingleByteCoverage(HasSingleByteCoverage) {} 4480b57cec5SDimitry Andric 44906c3fb27SDimitry Andric void countSelects() { 4500b57cec5SDimitry Andric NSIs = 0; 4510b57cec5SDimitry Andric Mode = VM_counting; 45206c3fb27SDimitry Andric visit(F); 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric // Visit the IR stream and instrument all select instructions. \p 4560b57cec5SDimitry Andric // Ind is a pointer to the counter index variable; \p TotalNC 4570b57cec5SDimitry Andric // is the total number of counters; \p FNV is the pointer to the 4580b57cec5SDimitry Andric // PGO function name var; \p FHash is the function hash. 45906c3fb27SDimitry Andric void instrumentSelects(unsigned *Ind, unsigned TotalNC, GlobalVariable *FNV, 46006c3fb27SDimitry Andric uint64_t FHash) { 4610b57cec5SDimitry Andric Mode = VM_instrument; 4620b57cec5SDimitry Andric CurCtrIdx = Ind; 4630b57cec5SDimitry Andric TotalNumCtrs = TotalNC; 4640b57cec5SDimitry Andric FuncHash = FHash; 4650b57cec5SDimitry Andric FuncNameVar = FNV; 46606c3fb27SDimitry Andric visit(F); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric // Visit the IR stream and annotate all select instructions. 47006c3fb27SDimitry Andric void annotateSelects(PGOUseFunc *UF, unsigned *Ind) { 4710b57cec5SDimitry Andric Mode = VM_annotate; 4720b57cec5SDimitry Andric UseFunc = UF; 4730b57cec5SDimitry Andric CurCtrIdx = Ind; 47406c3fb27SDimitry Andric visit(F); 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric void instrumentOneSelectInst(SelectInst &SI); 4780b57cec5SDimitry Andric void annotateOneSelectInst(SelectInst &SI); 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric // Visit \p SI instruction and perform tasks according to visit mode. 4810b57cec5SDimitry Andric void visitSelectInst(SelectInst &SI); 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric // Return the number of select instructions. This needs be called after 4840b57cec5SDimitry Andric // countSelects(). 4850b57cec5SDimitry Andric unsigned getNumOfSelectInsts() const { return NSIs; } 4860b57cec5SDimitry Andric }; 4870b57cec5SDimitry Andric 48806c3fb27SDimitry Andric /// This class implements the CFG edges for the Minimum Spanning Tree (MST) 48906c3fb27SDimitry Andric /// based instrumentation. 49006c3fb27SDimitry Andric /// Note that the CFG can be a multi-graph. So there might be multiple edges 49106c3fb27SDimitry Andric /// with the same SrcBB and DestBB. 4920b57cec5SDimitry Andric struct PGOEdge { 49306c3fb27SDimitry Andric BasicBlock *SrcBB; 49406c3fb27SDimitry Andric BasicBlock *DestBB; 4950b57cec5SDimitry Andric uint64_t Weight; 4960b57cec5SDimitry Andric bool InMST = false; 4970b57cec5SDimitry Andric bool Removed = false; 4980b57cec5SDimitry Andric bool IsCritical = false; 4990b57cec5SDimitry Andric 50006c3fb27SDimitry Andric PGOEdge(BasicBlock *Src, BasicBlock *Dest, uint64_t W = 1) 5010b57cec5SDimitry Andric : SrcBB(Src), DestBB(Dest), Weight(W) {} 5020b57cec5SDimitry Andric 50306c3fb27SDimitry Andric /// Return the information string of an edge. 504fe6060f1SDimitry Andric std::string infoString() const { 5050b57cec5SDimitry Andric return (Twine(Removed ? "-" : " ") + (InMST ? " " : "*") + 50606c3fb27SDimitry Andric (IsCritical ? "c" : " ") + " W=" + Twine(Weight)) 50706c3fb27SDimitry Andric .str(); 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric }; 5100b57cec5SDimitry Andric 51106c3fb27SDimitry Andric /// This class stores the auxiliary information for each BB in the MST. 51206c3fb27SDimitry Andric struct PGOBBInfo { 51306c3fb27SDimitry Andric PGOBBInfo *Group; 5140b57cec5SDimitry Andric uint32_t Index; 5150b57cec5SDimitry Andric uint32_t Rank = 0; 5160b57cec5SDimitry Andric 51706c3fb27SDimitry Andric PGOBBInfo(unsigned IX) : Group(this), Index(IX) {} 5180b57cec5SDimitry Andric 51906c3fb27SDimitry Andric /// Return the information string of this object. 520fe6060f1SDimitry Andric std::string infoString() const { 5210b57cec5SDimitry Andric return (Twine("Index=") + Twine(Index)).str(); 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric }; 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric // This class implements the CFG edges. Note the CFG can be a multi-graph. 5260b57cec5SDimitry Andric template <class Edge, class BBInfo> class FuncPGOInstrumentation { 5270b57cec5SDimitry Andric private: 5280b57cec5SDimitry Andric Function &F; 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric // Is this is context-sensitive instrumentation. 5310b57cec5SDimitry Andric bool IsCS; 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric // A map that stores the Comdat group in function F. 5340b57cec5SDimitry Andric std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers; 5350b57cec5SDimitry Andric 5368bcb0991SDimitry Andric ValueProfileCollector VPC; 5378bcb0991SDimitry Andric 5380b57cec5SDimitry Andric void computeCFGHash(); 5390b57cec5SDimitry Andric void renameComdatFunction(); 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric public: 542bdd1243dSDimitry Andric const TargetLibraryInfo &TLI; 5438bcb0991SDimitry Andric std::vector<std::vector<VPCandidateInfo>> ValueSites; 5440b57cec5SDimitry Andric SelectInstVisitor SIVisitor; 5450b57cec5SDimitry Andric std::string FuncName; 5465f757f3fSDimitry Andric std::string DeprecatedFuncName; 5470b57cec5SDimitry Andric GlobalVariable *FuncNameVar; 5480b57cec5SDimitry Andric 5490b57cec5SDimitry Andric // CFG hash value for this function. 5500b57cec5SDimitry Andric uint64_t FunctionHash = 0; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric // The Minimum Spanning Tree of function CFG. 5530b57cec5SDimitry Andric CFGMST<Edge, BBInfo> MST; 5540b57cec5SDimitry Andric 55506c3fb27SDimitry Andric const std::optional<BlockCoverageInference> BCI; 55606c3fb27SDimitry Andric 55706c3fb27SDimitry Andric static std::optional<BlockCoverageInference> 55806c3fb27SDimitry Andric constructBCI(Function &Func, bool HasSingleByteCoverage, 55906c3fb27SDimitry Andric bool InstrumentFuncEntry) { 56006c3fb27SDimitry Andric if (HasSingleByteCoverage) 56106c3fb27SDimitry Andric return BlockCoverageInference(Func, InstrumentFuncEntry); 56206c3fb27SDimitry Andric return {}; 56306c3fb27SDimitry Andric } 56406c3fb27SDimitry Andric 5650b57cec5SDimitry Andric // Collect all the BBs that will be instrumented, and store them in 5660b57cec5SDimitry Andric // InstrumentBBs. 5670b57cec5SDimitry Andric void getInstrumentBBs(std::vector<BasicBlock *> &InstrumentBBs); 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric // Give an edge, find the BB that will be instrumented. 5700b57cec5SDimitry Andric // Return nullptr if there is no BB to be instrumented. 5710b57cec5SDimitry Andric BasicBlock *getInstrBB(Edge *E); 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric // Return the auxiliary BB information. 5740b57cec5SDimitry Andric BBInfo &getBBInfo(const BasicBlock *BB) const { return MST.getBBInfo(BB); } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric // Return the auxiliary BB information if available. 5770b57cec5SDimitry Andric BBInfo *findBBInfo(const BasicBlock *BB) const { return MST.findBBInfo(BB); } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric // Dump edges and BB information. 58006c3fb27SDimitry Andric void dumpInfo(StringRef Str = "") const { 58106c3fb27SDimitry Andric MST.dumpEdges(dbgs(), Twine("Dump Function ") + FuncName + 58206c3fb27SDimitry Andric " Hash: " + Twine(FunctionHash) + "\t" + Str); 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric FuncPGOInstrumentation( 5865ffd83dbSDimitry Andric Function &Func, TargetLibraryInfo &TLI, 5870b57cec5SDimitry Andric std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers, 5880b57cec5SDimitry Andric bool CreateGlobalVar = false, BranchProbabilityInfo *BPI = nullptr, 589e8d8bef9SDimitry Andric BlockFrequencyInfo *BFI = nullptr, bool IsCS = false, 59006c3fb27SDimitry Andric bool InstrumentFuncEntry = true, bool HasSingleByteCoverage = false) 5915ffd83dbSDimitry Andric : F(Func), IsCS(IsCS), ComdatMembers(ComdatMembers), VPC(Func, TLI), 59206c3fb27SDimitry Andric TLI(TLI), ValueSites(IPVK_Last + 1), 59306c3fb27SDimitry Andric SIVisitor(Func, HasSingleByteCoverage), 59406c3fb27SDimitry Andric MST(F, InstrumentFuncEntry, BPI, BFI), 59506c3fb27SDimitry Andric BCI(constructBCI(Func, HasSingleByteCoverage, InstrumentFuncEntry)) { 59606c3fb27SDimitry Andric if (BCI && PGOViewBlockCoverageGraph) 59706c3fb27SDimitry Andric BCI->viewBlockCoverageGraph(); 5980b57cec5SDimitry Andric // This should be done before CFG hash computation. 59906c3fb27SDimitry Andric SIVisitor.countSelects(); 6008bcb0991SDimitry Andric ValueSites[IPVK_MemOPSize] = VPC.get(IPVK_MemOPSize); 6010b57cec5SDimitry Andric if (!IsCS) { 6020b57cec5SDimitry Andric NumOfPGOSelectInsts += SIVisitor.getNumOfSelectInsts(); 6038bcb0991SDimitry Andric NumOfPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size(); 6045f757f3fSDimitry Andric NumOfPGOBB += MST.bbInfoSize(); 6058bcb0991SDimitry Andric ValueSites[IPVK_IndirectCallTarget] = VPC.get(IPVK_IndirectCallTarget); 6060fca6ea1SDimitry Andric if (EnableVTableValueProfiling) 6070fca6ea1SDimitry Andric ValueSites[IPVK_VTableTarget] = VPC.get(IPVK_VTableTarget); 6080b57cec5SDimitry Andric } else { 6090b57cec5SDimitry Andric NumOfCSPGOSelectInsts += SIVisitor.getNumOfSelectInsts(); 6108bcb0991SDimitry Andric NumOfCSPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size(); 6115f757f3fSDimitry Andric NumOfCSPGOBB += MST.bbInfoSize(); 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric 6145f757f3fSDimitry Andric FuncName = getIRPGOFuncName(F); 6155f757f3fSDimitry Andric DeprecatedFuncName = getPGOFuncName(F); 6160b57cec5SDimitry Andric computeCFGHash(); 6170b57cec5SDimitry Andric if (!ComdatMembers.empty()) 6180b57cec5SDimitry Andric renameComdatFunction(); 6190b57cec5SDimitry Andric LLVM_DEBUG(dumpInfo("after CFGMST")); 6200b57cec5SDimitry Andric 6215f757f3fSDimitry Andric for (const auto &E : MST.allEdges()) { 6220b57cec5SDimitry Andric if (E->Removed) 6230b57cec5SDimitry Andric continue; 6240b57cec5SDimitry Andric IsCS ? NumOfCSPGOEdge++ : NumOfPGOEdge++; 6250b57cec5SDimitry Andric if (!E->InMST) 6260b57cec5SDimitry Andric IsCS ? NumOfCSPGOInstrument++ : NumOfPGOInstrument++; 6270b57cec5SDimitry Andric } 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric if (CreateGlobalVar) 6300b57cec5SDimitry Andric FuncNameVar = createPGOFuncNameVar(F, FuncName); 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric }; 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric } // end anonymous namespace 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric // Compute Hash value for the CFG: the lower 32 bits are CRC32 of the index 637e8d8bef9SDimitry Andric // value of each BB in the CFG. The higher 32 bits are the CRC32 of the numbers 638e8d8bef9SDimitry Andric // of selects, indirect calls, mem ops and edges. 6390b57cec5SDimitry Andric template <class Edge, class BBInfo> 6400b57cec5SDimitry Andric void FuncPGOInstrumentation<Edge, BBInfo>::computeCFGHash() { 6418bcb0991SDimitry Andric std::vector<uint8_t> Indexes; 6420b57cec5SDimitry Andric JamCRC JC; 6430b57cec5SDimitry Andric for (auto &BB : F) { 644297eecfbSDimitry Andric for (BasicBlock *Succ : successors(&BB)) { 6450b57cec5SDimitry Andric auto BI = findBBInfo(Succ); 6460b57cec5SDimitry Andric if (BI == nullptr) 6470b57cec5SDimitry Andric continue; 6480b57cec5SDimitry Andric uint32_t Index = BI->Index; 6490b57cec5SDimitry Andric for (int J = 0; J < 4; J++) 6508bcb0991SDimitry Andric Indexes.push_back((uint8_t)(Index >> (J * 8))); 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric JC.update(Indexes); 6540b57cec5SDimitry Andric 655e8d8bef9SDimitry Andric JamCRC JCH; 656e8d8bef9SDimitry Andric // The higher 32 bits. 657e8d8bef9SDimitry Andric auto updateJCH = [&JCH](uint64_t Num) { 658e8d8bef9SDimitry Andric uint8_t Data[8]; 659e8d8bef9SDimitry Andric support::endian::write64le(Data, Num); 660e8d8bef9SDimitry Andric JCH.update(Data); 661e8d8bef9SDimitry Andric }; 662e8d8bef9SDimitry Andric updateJCH((uint64_t)SIVisitor.getNumOfSelectInsts()); 663e8d8bef9SDimitry Andric updateJCH((uint64_t)ValueSites[IPVK_IndirectCallTarget].size()); 664e8d8bef9SDimitry Andric updateJCH((uint64_t)ValueSites[IPVK_MemOPSize].size()); 66506c3fb27SDimitry Andric if (BCI) { 66606c3fb27SDimitry Andric updateJCH(BCI->getInstrumentedBlocksHash()); 66706c3fb27SDimitry Andric } else { 6685f757f3fSDimitry Andric updateJCH((uint64_t)MST.numEdges()); 66906c3fb27SDimitry Andric } 670e8d8bef9SDimitry Andric 671e8d8bef9SDimitry Andric // Hash format for context sensitive profile. Reserve 4 bits for other 672e8d8bef9SDimitry Andric // information. 673e8d8bef9SDimitry Andric FunctionHash = (((uint64_t)JCH.getCRC()) << 28) + JC.getCRC(); 674e8d8bef9SDimitry Andric 6750b57cec5SDimitry Andric // Reserve bit 60-63 for other information purpose. 6760b57cec5SDimitry Andric FunctionHash &= 0x0FFFFFFFFFFFFFFF; 6770b57cec5SDimitry Andric if (IsCS) 6780b57cec5SDimitry Andric NamedInstrProfRecord::setCSFlagInHash(FunctionHash); 6790b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Function Hash Computation for " << F.getName() << ":\n" 6800b57cec5SDimitry Andric << " CRC = " << JC.getCRC() 6810b57cec5SDimitry Andric << ", Selects = " << SIVisitor.getNumOfSelectInsts() 6825f757f3fSDimitry Andric << ", Edges = " << MST.numEdges() << ", ICSites = " 683297eecfbSDimitry Andric << ValueSites[IPVK_IndirectCallTarget].size() 684297eecfbSDimitry Andric << ", Memops = " << ValueSites[IPVK_MemOPSize].size() 685297eecfbSDimitry Andric << ", High32 CRC = " << JCH.getCRC() 686297eecfbSDimitry Andric << ", Hash = " << FunctionHash << "\n";); 687fcaf7f86SDimitry Andric 688fcaf7f86SDimitry Andric if (PGOTraceFuncHash != "-" && F.getName().contains(PGOTraceFuncHash)) 689fcaf7f86SDimitry Andric dbgs() << "Funcname=" << F.getName() << ", Hash=" << FunctionHash 690fcaf7f86SDimitry Andric << " in building " << F.getParent()->getSourceFileName() << "\n"; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // Check if we can safely rename this Comdat function. 6940b57cec5SDimitry Andric static bool canRenameComdat( 6950b57cec5SDimitry Andric Function &F, 6960b57cec5SDimitry Andric std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers) { 6970b57cec5SDimitry Andric if (!DoComdatRenaming || !canRenameComdatFunc(F, true)) 6980b57cec5SDimitry Andric return false; 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric // FIXME: Current only handle those Comdat groups that only containing one 701e8d8bef9SDimitry Andric // function. 7020b57cec5SDimitry Andric // (1) For a Comdat group containing multiple functions, we need to have a 7030b57cec5SDimitry Andric // unique postfix based on the hashes for each function. There is a 7040b57cec5SDimitry Andric // non-trivial code refactoring to do this efficiently. 7050b57cec5SDimitry Andric // (2) Variables can not be renamed, so we can not rename Comdat function in a 7060b57cec5SDimitry Andric // group including global vars. 7070b57cec5SDimitry Andric Comdat *C = F.getComdat(); 7080b57cec5SDimitry Andric for (auto &&CM : make_range(ComdatMembers.equal_range(C))) { 709e8d8bef9SDimitry Andric assert(!isa<GlobalAlias>(CM.second)); 7100b57cec5SDimitry Andric Function *FM = dyn_cast<Function>(CM.second); 7110b57cec5SDimitry Andric if (FM != &F) 7120b57cec5SDimitry Andric return false; 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric return true; 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric // Append the CFGHash to the Comdat function name. 7180b57cec5SDimitry Andric template <class Edge, class BBInfo> 7190b57cec5SDimitry Andric void FuncPGOInstrumentation<Edge, BBInfo>::renameComdatFunction() { 7200b57cec5SDimitry Andric if (!canRenameComdat(F, ComdatMembers)) 7210b57cec5SDimitry Andric return; 7220b57cec5SDimitry Andric std::string OrigName = F.getName().str(); 7230b57cec5SDimitry Andric std::string NewFuncName = 7240b57cec5SDimitry Andric Twine(F.getName() + "." + Twine(FunctionHash)).str(); 7250b57cec5SDimitry Andric F.setName(Twine(NewFuncName)); 7260b57cec5SDimitry Andric GlobalAlias::create(GlobalValue::WeakAnyLinkage, OrigName, &F); 7270b57cec5SDimitry Andric FuncName = Twine(FuncName + "." + Twine(FunctionHash)).str(); 7280b57cec5SDimitry Andric Comdat *NewComdat; 7290b57cec5SDimitry Andric Module *M = F.getParent(); 7300b57cec5SDimitry Andric // For AvailableExternallyLinkage functions, change the linkage to 7310b57cec5SDimitry Andric // LinkOnceODR and put them into comdat. This is because after renaming, there 7320b57cec5SDimitry Andric // is no backup external copy available for the function. 7330b57cec5SDimitry Andric if (!F.hasComdat()) { 7340b57cec5SDimitry Andric assert(F.getLinkage() == GlobalValue::AvailableExternallyLinkage); 7350b57cec5SDimitry Andric NewComdat = M->getOrInsertComdat(StringRef(NewFuncName)); 7360b57cec5SDimitry Andric F.setLinkage(GlobalValue::LinkOnceODRLinkage); 7370b57cec5SDimitry Andric F.setComdat(NewComdat); 7380b57cec5SDimitry Andric return; 7390b57cec5SDimitry Andric } 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric // This function belongs to a single function Comdat group. 7420b57cec5SDimitry Andric Comdat *OrigComdat = F.getComdat(); 7430b57cec5SDimitry Andric std::string NewComdatName = 7440b57cec5SDimitry Andric Twine(OrigComdat->getName() + "." + Twine(FunctionHash)).str(); 7450b57cec5SDimitry Andric NewComdat = M->getOrInsertComdat(StringRef(NewComdatName)); 7460b57cec5SDimitry Andric NewComdat->setSelectionKind(OrigComdat->getSelectionKind()); 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric for (auto &&CM : make_range(ComdatMembers.equal_range(OrigComdat))) { 7490b57cec5SDimitry Andric // Must be a function. 750e8d8bef9SDimitry Andric cast<Function>(CM.second)->setComdat(NewComdat); 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric 75406c3fb27SDimitry Andric /// Collect all the BBs that will be instruments and add them to 75506c3fb27SDimitry Andric /// `InstrumentBBs`. 7560b57cec5SDimitry Andric template <class Edge, class BBInfo> 7570b57cec5SDimitry Andric void FuncPGOInstrumentation<Edge, BBInfo>::getInstrumentBBs( 7580b57cec5SDimitry Andric std::vector<BasicBlock *> &InstrumentBBs) { 75906c3fb27SDimitry Andric if (BCI) { 76006c3fb27SDimitry Andric for (auto &BB : F) 76106c3fb27SDimitry Andric if (BCI->shouldInstrumentBlock(BB)) 76206c3fb27SDimitry Andric InstrumentBBs.push_back(&BB); 76306c3fb27SDimitry Andric return; 76406c3fb27SDimitry Andric } 76506c3fb27SDimitry Andric 7660b57cec5SDimitry Andric // Use a worklist as we will update the vector during the iteration. 7670b57cec5SDimitry Andric std::vector<Edge *> EdgeList; 7685f757f3fSDimitry Andric EdgeList.reserve(MST.numEdges()); 7695f757f3fSDimitry Andric for (const auto &E : MST.allEdges()) 7700b57cec5SDimitry Andric EdgeList.push_back(E.get()); 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric for (auto &E : EdgeList) { 7730b57cec5SDimitry Andric BasicBlock *InstrBB = getInstrBB(E); 7740b57cec5SDimitry Andric if (InstrBB) 7750b57cec5SDimitry Andric InstrumentBBs.push_back(InstrBB); 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric // Given a CFG E to be instrumented, find which BB to place the instrumented 7800b57cec5SDimitry Andric // code. The function will split the critical edge if necessary. 7810b57cec5SDimitry Andric template <class Edge, class BBInfo> 7820b57cec5SDimitry Andric BasicBlock *FuncPGOInstrumentation<Edge, BBInfo>::getInstrBB(Edge *E) { 7830b57cec5SDimitry Andric if (E->InMST || E->Removed) 7840b57cec5SDimitry Andric return nullptr; 7850b57cec5SDimitry Andric 78606c3fb27SDimitry Andric BasicBlock *SrcBB = E->SrcBB; 78706c3fb27SDimitry Andric BasicBlock *DestBB = E->DestBB; 7880b57cec5SDimitry Andric // For a fake edge, instrument the real BB. 7890b57cec5SDimitry Andric if (SrcBB == nullptr) 7900b57cec5SDimitry Andric return DestBB; 7910b57cec5SDimitry Andric if (DestBB == nullptr) 7920b57cec5SDimitry Andric return SrcBB; 7930b57cec5SDimitry Andric 7940b57cec5SDimitry Andric auto canInstrument = [](BasicBlock *BB) -> BasicBlock * { 7950b57cec5SDimitry Andric // There are basic blocks (such as catchswitch) cannot be instrumented. 7960b57cec5SDimitry Andric // If the returned first insertion point is the end of BB, skip this BB. 7970b57cec5SDimitry Andric if (BB->getFirstInsertionPt() == BB->end()) 7980b57cec5SDimitry Andric return nullptr; 7990b57cec5SDimitry Andric return BB; 8000b57cec5SDimitry Andric }; 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric // Instrument the SrcBB if it has a single successor, 8030b57cec5SDimitry Andric // otherwise, the DestBB if this is not a critical edge. 8040b57cec5SDimitry Andric Instruction *TI = SrcBB->getTerminator(); 8050b57cec5SDimitry Andric if (TI->getNumSuccessors() <= 1) 8060b57cec5SDimitry Andric return canInstrument(SrcBB); 8070b57cec5SDimitry Andric if (!E->IsCritical) 8080b57cec5SDimitry Andric return canInstrument(DestBB); 8090b57cec5SDimitry Andric 810e8d8bef9SDimitry Andric // Some IndirectBr critical edges cannot be split by the previous 811e8d8bef9SDimitry Andric // SplitIndirectBrCriticalEdges call. Bail out. 8120b57cec5SDimitry Andric unsigned SuccNum = GetSuccessorNumber(SrcBB, DestBB); 813e8d8bef9SDimitry Andric BasicBlock *InstrBB = 814e8d8bef9SDimitry Andric isa<IndirectBrInst>(TI) ? nullptr : SplitCriticalEdge(TI, SuccNum); 8150b57cec5SDimitry Andric if (!InstrBB) { 8160b57cec5SDimitry Andric LLVM_DEBUG( 8170b57cec5SDimitry Andric dbgs() << "Fail to split critical edge: not instrument this edge.\n"); 8180b57cec5SDimitry Andric return nullptr; 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric // For a critical edge, we have to split. Instrument the newly 8210b57cec5SDimitry Andric // created BB. 8220b57cec5SDimitry Andric IsCS ? NumOfCSPGOSplit++ : NumOfPGOSplit++; 8230b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Split critical edge: " << getBBInfo(SrcBB).Index 8240b57cec5SDimitry Andric << " --> " << getBBInfo(DestBB).Index << "\n"); 8250b57cec5SDimitry Andric // Need to add two new edges. First one: Add new edge of SrcBB->InstrBB. 8260b57cec5SDimitry Andric MST.addEdge(SrcBB, InstrBB, 0); 8270b57cec5SDimitry Andric // Second one: Add new edge of InstrBB->DestBB. 8280b57cec5SDimitry Andric Edge &NewEdge1 = MST.addEdge(InstrBB, DestBB, 0); 8290b57cec5SDimitry Andric NewEdge1.InMST = true; 8300b57cec5SDimitry Andric E->Removed = true; 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric return canInstrument(InstrBB); 8330b57cec5SDimitry Andric } 8340b57cec5SDimitry Andric 8355ffd83dbSDimitry Andric // When generating value profiling calls on Windows routines that make use of 8365ffd83dbSDimitry Andric // handler funclets for exception processing an operand bundle needs to attached 8375ffd83dbSDimitry Andric // to the called function. This routine will set \p OpBundles to contain the 8385ffd83dbSDimitry Andric // funclet information, if any is needed, that should be placed on the generated 8395ffd83dbSDimitry Andric // value profiling call for the value profile candidate call. 8405ffd83dbSDimitry Andric static void 8415ffd83dbSDimitry Andric populateEHOperandBundle(VPCandidateInfo &Cand, 8425ffd83dbSDimitry Andric DenseMap<BasicBlock *, ColorVector> &BlockColors, 8435ffd83dbSDimitry Andric SmallVectorImpl<OperandBundleDef> &OpBundles) { 8445ffd83dbSDimitry Andric auto *OrigCall = dyn_cast<CallBase>(Cand.AnnotatedInst); 84504eeddc0SDimitry Andric if (!OrigCall) 84604eeddc0SDimitry Andric return; 84704eeddc0SDimitry Andric 84804eeddc0SDimitry Andric if (!isa<IntrinsicInst>(OrigCall)) { 8495ffd83dbSDimitry Andric // The instrumentation call should belong to the same funclet as a 8505ffd83dbSDimitry Andric // non-intrinsic call, so just copy the operand bundle, if any exists. 851bdd1243dSDimitry Andric std::optional<OperandBundleUse> ParentFunclet = 8525ffd83dbSDimitry Andric OrigCall->getOperandBundle(LLVMContext::OB_funclet); 8535ffd83dbSDimitry Andric if (ParentFunclet) 8545ffd83dbSDimitry Andric OpBundles.emplace_back(OperandBundleDef(*ParentFunclet)); 8555ffd83dbSDimitry Andric } else { 8565ffd83dbSDimitry Andric // Intrinsics or other instructions do not get funclet information from the 8575ffd83dbSDimitry Andric // front-end. Need to use the BlockColors that was computed by the routine 8585ffd83dbSDimitry Andric // colorEHFunclets to determine whether a funclet is needed. 8595ffd83dbSDimitry Andric if (!BlockColors.empty()) { 8605ffd83dbSDimitry Andric const ColorVector &CV = BlockColors.find(OrigCall->getParent())->second; 8615ffd83dbSDimitry Andric assert(CV.size() == 1 && "non-unique color for block!"); 8625ffd83dbSDimitry Andric Instruction *EHPad = CV.front()->getFirstNonPHI(); 8635ffd83dbSDimitry Andric if (EHPad->isEHPad()) 8645ffd83dbSDimitry Andric OpBundles.emplace_back("funclet", EHPad); 8655ffd83dbSDimitry Andric } 8665ffd83dbSDimitry Andric } 8675ffd83dbSDimitry Andric } 8685ffd83dbSDimitry Andric 8690b57cec5SDimitry Andric // Visit all edge and instrument the edges not in MST, and do value profiling. 8700b57cec5SDimitry Andric // Critical edges will be split. 8710b57cec5SDimitry Andric static void instrumentOneFunc( 8725ffd83dbSDimitry Andric Function &F, Module *M, TargetLibraryInfo &TLI, BranchProbabilityInfo *BPI, 8735ffd83dbSDimitry Andric BlockFrequencyInfo *BFI, 8740b57cec5SDimitry Andric std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers, 8750b57cec5SDimitry Andric bool IsCS) { 87606c3fb27SDimitry Andric if (!PGOBlockCoverage) { 8770b57cec5SDimitry Andric // Split indirectbr critical edges here before computing the MST rather than 8780b57cec5SDimitry Andric // later in getInstrBB() to avoid invalidating it. 87981ad6265SDimitry Andric SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI, BFI); 88006c3fb27SDimitry Andric } 8810b57cec5SDimitry Andric 88206c3fb27SDimitry Andric FuncPGOInstrumentation<PGOEdge, PGOBBInfo> FuncInfo( 8830fca6ea1SDimitry Andric F, TLI, ComdatMembers, true, BPI, BFI, IsCS, shouldInstrumentEntryBB(), 88406c3fb27SDimitry Andric PGOBlockCoverage); 8851fd87a68SDimitry Andric 8865f757f3fSDimitry Andric auto Name = FuncInfo.FuncNameVar; 8871fd87a68SDimitry Andric auto CFGHash = ConstantInt::get(Type::getInt64Ty(M->getContext()), 8881fd87a68SDimitry Andric FuncInfo.FunctionHash); 8891fd87a68SDimitry Andric if (PGOFunctionEntryCoverage) { 8901fd87a68SDimitry Andric auto &EntryBB = F.getEntryBlock(); 8911fd87a68SDimitry Andric IRBuilder<> Builder(&EntryBB, EntryBB.getFirstInsertionPt()); 8921fd87a68SDimitry Andric // llvm.instrprof.cover(i8* <name>, i64 <hash>, i32 <num-counters>, 8931fd87a68SDimitry Andric // i32 <index>) 8941fd87a68SDimitry Andric Builder.CreateCall( 8951fd87a68SDimitry Andric Intrinsic::getDeclaration(M, Intrinsic::instrprof_cover), 8961fd87a68SDimitry Andric {Name, CFGHash, Builder.getInt32(1), Builder.getInt32(0)}); 8971fd87a68SDimitry Andric return; 8981fd87a68SDimitry Andric } 8991fd87a68SDimitry Andric 9000b57cec5SDimitry Andric std::vector<BasicBlock *> InstrumentBBs; 9010b57cec5SDimitry Andric FuncInfo.getInstrumentBBs(InstrumentBBs); 9020b57cec5SDimitry Andric unsigned NumCounters = 9030b57cec5SDimitry Andric InstrumentBBs.size() + FuncInfo.SIVisitor.getNumOfSelectInsts(); 9040b57cec5SDimitry Andric 9050fca6ea1SDimitry Andric if (PGOCtxProfLoweringPass::isContextualIRPGOEnabled()) { 9060fca6ea1SDimitry Andric auto *CSIntrinsic = 9070fca6ea1SDimitry Andric Intrinsic::getDeclaration(M, Intrinsic::instrprof_callsite); 9080fca6ea1SDimitry Andric // We want to count the instrumentable callsites, then instrument them. This 9090fca6ea1SDimitry Andric // is because the llvm.instrprof.callsite intrinsic has an argument (like 9100fca6ea1SDimitry Andric // the other instrprof intrinsics) capturing the total number of 9110fca6ea1SDimitry Andric // instrumented objects (counters, or callsites, in this case). In this 9120fca6ea1SDimitry Andric // case, we want that value so we can readily pass it to the compiler-rt 9130fca6ea1SDimitry Andric // APIs that may have to allocate memory based on the nr of callsites. 9140fca6ea1SDimitry Andric // The traversal logic is the same for both counting and instrumentation, 9150fca6ea1SDimitry Andric // just needs to be done in succession. 9160fca6ea1SDimitry Andric auto Visit = [&](llvm::function_ref<void(CallBase * CB)> Visitor) { 9170fca6ea1SDimitry Andric for (auto &BB : F) 9180fca6ea1SDimitry Andric for (auto &Instr : BB) 9190fca6ea1SDimitry Andric if (auto *CS = dyn_cast<CallBase>(&Instr)) { 9200fca6ea1SDimitry Andric if ((CS->getCalledFunction() && 9210fca6ea1SDimitry Andric CS->getCalledFunction()->isIntrinsic()) || 9220fca6ea1SDimitry Andric dyn_cast<InlineAsm>(CS->getCalledOperand())) 9230fca6ea1SDimitry Andric continue; 9240fca6ea1SDimitry Andric Visitor(CS); 9250fca6ea1SDimitry Andric } 9260fca6ea1SDimitry Andric }; 9270fca6ea1SDimitry Andric // First, count callsites. 9280fca6ea1SDimitry Andric uint32_t TotalNrCallsites = 0; 9290fca6ea1SDimitry Andric Visit([&TotalNrCallsites](auto *) { ++TotalNrCallsites; }); 9300fca6ea1SDimitry Andric 9310fca6ea1SDimitry Andric // Now instrument. 9320fca6ea1SDimitry Andric uint32_t CallsiteIndex = 0; 9330fca6ea1SDimitry Andric Visit([&](auto *CB) { 9340fca6ea1SDimitry Andric IRBuilder<> Builder(CB); 9350fca6ea1SDimitry Andric Builder.CreateCall(CSIntrinsic, 9360fca6ea1SDimitry Andric {Name, CFGHash, Builder.getInt32(TotalNrCallsites), 9370fca6ea1SDimitry Andric Builder.getInt32(CallsiteIndex++), 9380fca6ea1SDimitry Andric CB->getCalledOperand()}); 9390fca6ea1SDimitry Andric }); 9400fca6ea1SDimitry Andric } 9410fca6ea1SDimitry Andric 9420b57cec5SDimitry Andric uint32_t I = 0; 94306c3fb27SDimitry Andric if (PGOTemporalInstrumentation) { 94406c3fb27SDimitry Andric NumCounters += PGOBlockCoverage ? 8 : 1; 94506c3fb27SDimitry Andric auto &EntryBB = F.getEntryBlock(); 94606c3fb27SDimitry Andric IRBuilder<> Builder(&EntryBB, EntryBB.getFirstInsertionPt()); 94706c3fb27SDimitry Andric // llvm.instrprof.timestamp(i8* <name>, i64 <hash>, i32 <num-counters>, 94806c3fb27SDimitry Andric // i32 <index>) 94906c3fb27SDimitry Andric Builder.CreateCall( 95006c3fb27SDimitry Andric Intrinsic::getDeclaration(M, Intrinsic::instrprof_timestamp), 95106c3fb27SDimitry Andric {Name, CFGHash, Builder.getInt32(NumCounters), Builder.getInt32(I)}); 95206c3fb27SDimitry Andric I += PGOBlockCoverage ? 8 : 1; 95306c3fb27SDimitry Andric } 95406c3fb27SDimitry Andric 9550b57cec5SDimitry Andric for (auto *InstrBB : InstrumentBBs) { 9560b57cec5SDimitry Andric IRBuilder<> Builder(InstrBB, InstrBB->getFirstInsertionPt()); 9570b57cec5SDimitry Andric assert(Builder.GetInsertPoint() != InstrBB->end() && 9580b57cec5SDimitry Andric "Cannot get the Instrumentation point"); 9591fd87a68SDimitry Andric // llvm.instrprof.increment(i8* <name>, i64 <hash>, i32 <num-counters>, 9601fd87a68SDimitry Andric // i32 <index>) 9610b57cec5SDimitry Andric Builder.CreateCall( 96206c3fb27SDimitry Andric Intrinsic::getDeclaration(M, PGOBlockCoverage 96306c3fb27SDimitry Andric ? Intrinsic::instrprof_cover 96406c3fb27SDimitry Andric : Intrinsic::instrprof_increment), 9651fd87a68SDimitry Andric {Name, CFGHash, Builder.getInt32(NumCounters), Builder.getInt32(I++)}); 9660b57cec5SDimitry Andric } 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric // Now instrument select instructions: 96906c3fb27SDimitry Andric FuncInfo.SIVisitor.instrumentSelects(&I, NumCounters, FuncInfo.FuncNameVar, 9700b57cec5SDimitry Andric FuncInfo.FunctionHash); 9710b57cec5SDimitry Andric assert(I == NumCounters); 9720b57cec5SDimitry Andric 9730fca6ea1SDimitry Andric if (isValueProfilingDisabled()) 9740b57cec5SDimitry Andric return; 9750b57cec5SDimitry Andric 9768bcb0991SDimitry Andric NumOfPGOICall += FuncInfo.ValueSites[IPVK_IndirectCallTarget].size(); 9778bcb0991SDimitry Andric 9785ffd83dbSDimitry Andric // Intrinsic function calls do not have funclet operand bundles needed for 9795ffd83dbSDimitry Andric // Windows exception handling attached to them. However, if value profiling is 9805ffd83dbSDimitry Andric // inserted for one of these calls, then a funclet value will need to be set 9815ffd83dbSDimitry Andric // on the instrumentation call based on the funclet coloring. 9825ffd83dbSDimitry Andric DenseMap<BasicBlock *, ColorVector> BlockColors; 9835ffd83dbSDimitry Andric if (F.hasPersonalityFn() && 9840fca6ea1SDimitry Andric isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) 9855ffd83dbSDimitry Andric BlockColors = colorEHFunclets(F); 9865ffd83dbSDimitry Andric 9878bcb0991SDimitry Andric // For each VP Kind, walk the VP candidates and instrument each one. 9888bcb0991SDimitry Andric for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) { 9898bcb0991SDimitry Andric unsigned SiteIndex = 0; 9908bcb0991SDimitry Andric if (Kind == IPVK_MemOPSize && !PGOInstrMemOP) 9918bcb0991SDimitry Andric continue; 9928bcb0991SDimitry Andric 9938bcb0991SDimitry Andric for (VPCandidateInfo Cand : FuncInfo.ValueSites[Kind]) { 9948bcb0991SDimitry Andric LLVM_DEBUG(dbgs() << "Instrument one VP " << ValueProfKindDescr[Kind] 9958bcb0991SDimitry Andric << " site: CallSite Index = " << SiteIndex << "\n"); 9968bcb0991SDimitry Andric 9978bcb0991SDimitry Andric IRBuilder<> Builder(Cand.InsertPt); 9988bcb0991SDimitry Andric assert(Builder.GetInsertPoint() != Cand.InsertPt->getParent()->end() && 9990b57cec5SDimitry Andric "Cannot get the Instrumentation point"); 10008bcb0991SDimitry Andric 10018bcb0991SDimitry Andric Value *ToProfile = nullptr; 10028bcb0991SDimitry Andric if (Cand.V->getType()->isIntegerTy()) 10038bcb0991SDimitry Andric ToProfile = Builder.CreateZExtOrTrunc(Cand.V, Builder.getInt64Ty()); 10048bcb0991SDimitry Andric else if (Cand.V->getType()->isPointerTy()) 10058bcb0991SDimitry Andric ToProfile = Builder.CreatePtrToInt(Cand.V, Builder.getInt64Ty()); 10068bcb0991SDimitry Andric assert(ToProfile && "value profiling Value is of unexpected type"); 10078bcb0991SDimitry Andric 10085ffd83dbSDimitry Andric SmallVector<OperandBundleDef, 1> OpBundles; 10095ffd83dbSDimitry Andric populateEHOperandBundle(Cand, BlockColors, OpBundles); 10100b57cec5SDimitry Andric Builder.CreateCall( 10110b57cec5SDimitry Andric Intrinsic::getDeclaration(M, Intrinsic::instrprof_value_profile), 10125f757f3fSDimitry Andric {FuncInfo.FuncNameVar, Builder.getInt64(FuncInfo.FunctionHash), 10135f757f3fSDimitry Andric ToProfile, Builder.getInt32(Kind), Builder.getInt32(SiteIndex++)}, 10145ffd83dbSDimitry Andric OpBundles); 10150b57cec5SDimitry Andric } 10168bcb0991SDimitry Andric } // IPVK_First <= Kind <= IPVK_Last 10170b57cec5SDimitry Andric } 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric namespace { 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric // This class represents a CFG edge in profile use compilation. 10220b57cec5SDimitry Andric struct PGOUseEdge : public PGOEdge { 102306c3fb27SDimitry Andric using PGOEdge::PGOEdge; 102406c3fb27SDimitry Andric 10250fca6ea1SDimitry Andric std::optional<uint64_t> Count; 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric // Set edge count value 10280fca6ea1SDimitry Andric void setEdgeCount(uint64_t Value) { Count = Value; } 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric // Return the information string for this object. 1031fe6060f1SDimitry Andric std::string infoString() const { 10320fca6ea1SDimitry Andric if (!Count) 10330b57cec5SDimitry Andric return PGOEdge::infoString(); 10340fca6ea1SDimitry Andric return (Twine(PGOEdge::infoString()) + " Count=" + Twine(*Count)).str(); 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric }; 10370b57cec5SDimitry Andric 10380b57cec5SDimitry Andric using DirectEdges = SmallVector<PGOUseEdge *, 2>; 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric // This class stores the auxiliary information for each BB. 104106c3fb27SDimitry Andric struct PGOUseBBInfo : public PGOBBInfo { 10420fca6ea1SDimitry Andric std::optional<uint64_t> Count; 10430b57cec5SDimitry Andric int32_t UnknownCountInEdge = 0; 10440b57cec5SDimitry Andric int32_t UnknownCountOutEdge = 0; 10450b57cec5SDimitry Andric DirectEdges InEdges; 10460b57cec5SDimitry Andric DirectEdges OutEdges; 10470b57cec5SDimitry Andric 10480fca6ea1SDimitry Andric PGOUseBBInfo(unsigned IX) : PGOBBInfo(IX) {} 10490b57cec5SDimitry Andric 10500b57cec5SDimitry Andric // Set the profile count value for this BB. 10510fca6ea1SDimitry Andric void setBBInfoCount(uint64_t Value) { Count = Value; } 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric // Return the information string of this object. 1054fe6060f1SDimitry Andric std::string infoString() const { 10550fca6ea1SDimitry Andric if (!Count) 105606c3fb27SDimitry Andric return PGOBBInfo::infoString(); 10570fca6ea1SDimitry Andric return (Twine(PGOBBInfo::infoString()) + " Count=" + Twine(*Count)).str(); 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric // Add an OutEdge and update the edge count. 10610b57cec5SDimitry Andric void addOutEdge(PGOUseEdge *E) { 10620b57cec5SDimitry Andric OutEdges.push_back(E); 10630b57cec5SDimitry Andric UnknownCountOutEdge++; 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric // Add an InEdge and update the edge count. 10670b57cec5SDimitry Andric void addInEdge(PGOUseEdge *E) { 10680b57cec5SDimitry Andric InEdges.push_back(E); 10690b57cec5SDimitry Andric UnknownCountInEdge++; 10700b57cec5SDimitry Andric } 10710b57cec5SDimitry Andric }; 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andric } // end anonymous namespace 10740b57cec5SDimitry Andric 10750b57cec5SDimitry Andric // Sum up the count values for all the edges. 10760b57cec5SDimitry Andric static uint64_t sumEdgeCount(const ArrayRef<PGOUseEdge *> Edges) { 10770b57cec5SDimitry Andric uint64_t Total = 0; 1078bdd1243dSDimitry Andric for (const auto &E : Edges) { 10790b57cec5SDimitry Andric if (E->Removed) 10800b57cec5SDimitry Andric continue; 10810fca6ea1SDimitry Andric if (E->Count) 10820fca6ea1SDimitry Andric Total += *E->Count; 10830b57cec5SDimitry Andric } 10840b57cec5SDimitry Andric return Total; 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric namespace { 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric class PGOUseFunc { 10900b57cec5SDimitry Andric public: 10915ffd83dbSDimitry Andric PGOUseFunc(Function &Func, Module *Modu, TargetLibraryInfo &TLI, 10920b57cec5SDimitry Andric std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers, 10938bcb0991SDimitry Andric BranchProbabilityInfo *BPI, BlockFrequencyInfo *BFIin, 109406c3fb27SDimitry Andric ProfileSummaryInfo *PSI, bool IsCS, bool InstrumentFuncEntry, 109506c3fb27SDimitry Andric bool HasSingleByteCoverage) 10968bcb0991SDimitry Andric : F(Func), M(Modu), BFI(BFIin), PSI(PSI), 1097e8d8bef9SDimitry Andric FuncInfo(Func, TLI, ComdatMembers, false, BPI, BFIin, IsCS, 109806c3fb27SDimitry Andric InstrumentFuncEntry, HasSingleByteCoverage), 10990fca6ea1SDimitry Andric FreqAttr(FFA_Normal), IsCS(IsCS), VPC(Func, TLI) {} 11000b57cec5SDimitry Andric 110106c3fb27SDimitry Andric void handleInstrProfError(Error Err, uint64_t MismatchedFuncSum); 110206c3fb27SDimitry Andric 11030b57cec5SDimitry Andric // Read counts for the instrumented BB from profile. 1104e8d8bef9SDimitry Andric bool readCounters(IndexedInstrProfReader *PGOReader, bool &AllZeros, 1105bdd1243dSDimitry Andric InstrProfRecord::CountPseudoKind &PseudoKind); 1106bdd1243dSDimitry Andric 11070b57cec5SDimitry Andric // Populate the counts for all BBs. 11080b57cec5SDimitry Andric void populateCounters(); 11090b57cec5SDimitry Andric 111006c3fb27SDimitry Andric // Set block coverage based on profile coverage values. 111106c3fb27SDimitry Andric void populateCoverage(IndexedInstrProfReader *PGOReader); 111206c3fb27SDimitry Andric 11130b57cec5SDimitry Andric // Set the branch weights based on the count values. 11140b57cec5SDimitry Andric void setBranchWeights(); 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andric // Annotate the value profile call sites for all value kind. 11170b57cec5SDimitry Andric void annotateValueSites(); 11180b57cec5SDimitry Andric 11190b57cec5SDimitry Andric // Annotate the value profile call sites for one value kind. 11200b57cec5SDimitry Andric void annotateValueSites(uint32_t Kind); 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric // Annotate the irreducible loop header weights. 11230b57cec5SDimitry Andric void annotateIrrLoopHeaderWeights(); 11240b57cec5SDimitry Andric 11250b57cec5SDimitry Andric // The hotness of the function from the profile count. 11260b57cec5SDimitry Andric enum FuncFreqAttr { FFA_Normal, FFA_Cold, FFA_Hot }; 11270b57cec5SDimitry Andric 11280b57cec5SDimitry Andric // Return the function hotness from the profile. 11290b57cec5SDimitry Andric FuncFreqAttr getFuncFreqAttr() const { return FreqAttr; } 11300b57cec5SDimitry Andric 11310b57cec5SDimitry Andric // Return the function hash. 11320b57cec5SDimitry Andric uint64_t getFuncHash() const { return FuncInfo.FunctionHash; } 11330b57cec5SDimitry Andric 11340b57cec5SDimitry Andric // Return the profile record for this function; 11350b57cec5SDimitry Andric InstrProfRecord &getProfileRecord() { return ProfileRecord; } 11360b57cec5SDimitry Andric 11370b57cec5SDimitry Andric // Return the auxiliary BB information. 113806c3fb27SDimitry Andric PGOUseBBInfo &getBBInfo(const BasicBlock *BB) const { 11390b57cec5SDimitry Andric return FuncInfo.getBBInfo(BB); 11400b57cec5SDimitry Andric } 11410b57cec5SDimitry Andric 11420b57cec5SDimitry Andric // Return the auxiliary BB information if available. 114306c3fb27SDimitry Andric PGOUseBBInfo *findBBInfo(const BasicBlock *BB) const { 11440b57cec5SDimitry Andric return FuncInfo.findBBInfo(BB); 11450b57cec5SDimitry Andric } 11460b57cec5SDimitry Andric 11470b57cec5SDimitry Andric Function &getFunc() const { return F; } 11480b57cec5SDimitry Andric 114906c3fb27SDimitry Andric void dumpInfo(StringRef Str = "") const { FuncInfo.dumpInfo(Str); } 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andric uint64_t getProgramMaxCount() const { return ProgramMaxCount; } 115206c3fb27SDimitry Andric 11530b57cec5SDimitry Andric private: 11540b57cec5SDimitry Andric Function &F; 11550b57cec5SDimitry Andric Module *M; 11560b57cec5SDimitry Andric BlockFrequencyInfo *BFI; 11578bcb0991SDimitry Andric ProfileSummaryInfo *PSI; 11580b57cec5SDimitry Andric 11590b57cec5SDimitry Andric // This member stores the shared information with class PGOGenFunc. 116006c3fb27SDimitry Andric FuncPGOInstrumentation<PGOUseEdge, PGOUseBBInfo> FuncInfo; 11610b57cec5SDimitry Andric 11620b57cec5SDimitry Andric // The maximum count value in the profile. This is only used in PGO use 11630b57cec5SDimitry Andric // compilation. 11640b57cec5SDimitry Andric uint64_t ProgramMaxCount; 11650b57cec5SDimitry Andric 11660b57cec5SDimitry Andric // Position of counter that remains to be read. 11670b57cec5SDimitry Andric uint32_t CountPosition = 0; 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric // Total size of the profile count for this function. 11700b57cec5SDimitry Andric uint32_t ProfileCountSize = 0; 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric // ProfileRecord for this function. 11730b57cec5SDimitry Andric InstrProfRecord ProfileRecord; 11740b57cec5SDimitry Andric 11750b57cec5SDimitry Andric // Function hotness info derived from profile. 11760b57cec5SDimitry Andric FuncFreqAttr FreqAttr; 11770b57cec5SDimitry Andric 11780b57cec5SDimitry Andric // Is to use the context sensitive profile. 11790b57cec5SDimitry Andric bool IsCS; 11800b57cec5SDimitry Andric 11810fca6ea1SDimitry Andric ValueProfileCollector VPC; 11820fca6ea1SDimitry Andric 11830b57cec5SDimitry Andric // Find the Instrumented BB and set the value. Return false on error. 11840b57cec5SDimitry Andric bool setInstrumentedCounts(const std::vector<uint64_t> &CountFromProfile); 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric // Set the edge counter value for the unknown edge -- there should be only 11870b57cec5SDimitry Andric // one unknown edge. 11880b57cec5SDimitry Andric void setEdgeCount(DirectEdges &Edges, uint64_t Value); 11890b57cec5SDimitry Andric 11900b57cec5SDimitry Andric // Set the hot/cold inline hints based on the count values. 11910b57cec5SDimitry Andric // FIXME: This function should be removed once the functionality in 11920b57cec5SDimitry Andric // the inliner is implemented. 11930b57cec5SDimitry Andric void markFunctionAttributes(uint64_t EntryCount, uint64_t MaxCount) { 11948bcb0991SDimitry Andric if (PSI->isHotCount(EntryCount)) 11950b57cec5SDimitry Andric FreqAttr = FFA_Hot; 11968bcb0991SDimitry Andric else if (PSI->isColdCount(MaxCount)) 11970b57cec5SDimitry Andric FreqAttr = FFA_Cold; 11980b57cec5SDimitry Andric } 11990b57cec5SDimitry Andric }; 12000b57cec5SDimitry Andric 12010b57cec5SDimitry Andric } // end anonymous namespace 12020b57cec5SDimitry Andric 120306c3fb27SDimitry Andric /// Set up InEdges/OutEdges for all BBs in the MST. 12045f757f3fSDimitry Andric static void setupBBInfoEdges( 12055f757f3fSDimitry Andric const FuncPGOInstrumentation<PGOUseEdge, PGOUseBBInfo> &FuncInfo) { 120606c3fb27SDimitry Andric // This is not required when there is block coverage inference. 120706c3fb27SDimitry Andric if (FuncInfo.BCI) 120806c3fb27SDimitry Andric return; 12095f757f3fSDimitry Andric for (const auto &E : FuncInfo.MST.allEdges()) { 121006c3fb27SDimitry Andric if (E->Removed) 121106c3fb27SDimitry Andric continue; 121206c3fb27SDimitry Andric const BasicBlock *SrcBB = E->SrcBB; 121306c3fb27SDimitry Andric const BasicBlock *DestBB = E->DestBB; 121406c3fb27SDimitry Andric PGOUseBBInfo &SrcInfo = FuncInfo.getBBInfo(SrcBB); 121506c3fb27SDimitry Andric PGOUseBBInfo &DestInfo = FuncInfo.getBBInfo(DestBB); 121606c3fb27SDimitry Andric SrcInfo.addOutEdge(E.get()); 121706c3fb27SDimitry Andric DestInfo.addInEdge(E.get()); 121806c3fb27SDimitry Andric } 121906c3fb27SDimitry Andric } 122006c3fb27SDimitry Andric 12210b57cec5SDimitry Andric // Visit all the edges and assign the count value for the instrumented 12220b57cec5SDimitry Andric // edges and the BB. Return false on error. 12230b57cec5SDimitry Andric bool PGOUseFunc::setInstrumentedCounts( 12240b57cec5SDimitry Andric const std::vector<uint64_t> &CountFromProfile) { 12250b57cec5SDimitry Andric 12260b57cec5SDimitry Andric std::vector<BasicBlock *> InstrumentBBs; 12270b57cec5SDimitry Andric FuncInfo.getInstrumentBBs(InstrumentBBs); 122806c3fb27SDimitry Andric 122906c3fb27SDimitry Andric setupBBInfoEdges(FuncInfo); 123006c3fb27SDimitry Andric 12310b57cec5SDimitry Andric unsigned NumCounters = 12320b57cec5SDimitry Andric InstrumentBBs.size() + FuncInfo.SIVisitor.getNumOfSelectInsts(); 12330b57cec5SDimitry Andric // The number of counters here should match the number of counters 12340b57cec5SDimitry Andric // in profile. Return if they mismatch. 12350b57cec5SDimitry Andric if (NumCounters != CountFromProfile.size()) { 12360b57cec5SDimitry Andric return false; 12370b57cec5SDimitry Andric } 1238e8d8bef9SDimitry Andric auto *FuncEntry = &*F.begin(); 1239e8d8bef9SDimitry Andric 12400b57cec5SDimitry Andric // Set the profile count to the Instrumented BBs. 12410b57cec5SDimitry Andric uint32_t I = 0; 12420b57cec5SDimitry Andric for (BasicBlock *InstrBB : InstrumentBBs) { 12430b57cec5SDimitry Andric uint64_t CountValue = CountFromProfile[I++]; 124406c3fb27SDimitry Andric PGOUseBBInfo &Info = getBBInfo(InstrBB); 1245e8d8bef9SDimitry Andric // If we reach here, we know that we have some nonzero count 1246e8d8bef9SDimitry Andric // values in this function. The entry count should not be 0. 1247e8d8bef9SDimitry Andric // Fix it if necessary. 1248e8d8bef9SDimitry Andric if (InstrBB == FuncEntry && CountValue == 0) 1249e8d8bef9SDimitry Andric CountValue = 1; 12500b57cec5SDimitry Andric Info.setBBInfoCount(CountValue); 12510b57cec5SDimitry Andric } 12520b57cec5SDimitry Andric ProfileCountSize = CountFromProfile.size(); 12530b57cec5SDimitry Andric CountPosition = I; 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andric // Set the edge count and update the count of unknown edges for BBs. 12560b57cec5SDimitry Andric auto setEdgeCount = [this](PGOUseEdge *E, uint64_t Value) -> void { 12570b57cec5SDimitry Andric E->setEdgeCount(Value); 12580b57cec5SDimitry Andric this->getBBInfo(E->SrcBB).UnknownCountOutEdge--; 12590b57cec5SDimitry Andric this->getBBInfo(E->DestBB).UnknownCountInEdge--; 12600b57cec5SDimitry Andric }; 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric // Set the profile count the Instrumented edges. There are BBs that not in 12630b57cec5SDimitry Andric // MST but not instrumented. Need to set the edge count value so that we can 12640b57cec5SDimitry Andric // populate the profile counts later. 12655f757f3fSDimitry Andric for (const auto &E : FuncInfo.MST.allEdges()) { 12660b57cec5SDimitry Andric if (E->Removed || E->InMST) 12670b57cec5SDimitry Andric continue; 12680b57cec5SDimitry Andric const BasicBlock *SrcBB = E->SrcBB; 126906c3fb27SDimitry Andric PGOUseBBInfo &SrcInfo = getBBInfo(SrcBB); 12700b57cec5SDimitry Andric 12710b57cec5SDimitry Andric // If only one out-edge, the edge profile count should be the same as BB 12720b57cec5SDimitry Andric // profile count. 12730fca6ea1SDimitry Andric if (SrcInfo.Count && SrcInfo.OutEdges.size() == 1) 12740fca6ea1SDimitry Andric setEdgeCount(E.get(), *SrcInfo.Count); 12750b57cec5SDimitry Andric else { 12760b57cec5SDimitry Andric const BasicBlock *DestBB = E->DestBB; 127706c3fb27SDimitry Andric PGOUseBBInfo &DestInfo = getBBInfo(DestBB); 12780b57cec5SDimitry Andric // If only one in-edge, the edge profile count should be the same as BB 12790b57cec5SDimitry Andric // profile count. 12800fca6ea1SDimitry Andric if (DestInfo.Count && DestInfo.InEdges.size() == 1) 12810fca6ea1SDimitry Andric setEdgeCount(E.get(), *DestInfo.Count); 12820b57cec5SDimitry Andric } 12830fca6ea1SDimitry Andric if (E->Count) 12840b57cec5SDimitry Andric continue; 12850b57cec5SDimitry Andric // E's count should have been set from profile. If not, this meenas E skips 12860b57cec5SDimitry Andric // the instrumentation. We set the count to 0. 12870b57cec5SDimitry Andric setEdgeCount(E.get(), 0); 12880b57cec5SDimitry Andric } 12890b57cec5SDimitry Andric return true; 12900b57cec5SDimitry Andric } 12910b57cec5SDimitry Andric 12920b57cec5SDimitry Andric // Set the count value for the unknown edge. There should be one and only one 12930b57cec5SDimitry Andric // unknown edge in Edges vector. 12940b57cec5SDimitry Andric void PGOUseFunc::setEdgeCount(DirectEdges &Edges, uint64_t Value) { 12950b57cec5SDimitry Andric for (auto &E : Edges) { 12960fca6ea1SDimitry Andric if (E->Count) 12970b57cec5SDimitry Andric continue; 12980b57cec5SDimitry Andric E->setEdgeCount(Value); 12990b57cec5SDimitry Andric 13000b57cec5SDimitry Andric getBBInfo(E->SrcBB).UnknownCountOutEdge--; 13010b57cec5SDimitry Andric getBBInfo(E->DestBB).UnknownCountInEdge--; 13020b57cec5SDimitry Andric return; 13030b57cec5SDimitry Andric } 13040b57cec5SDimitry Andric llvm_unreachable("Cannot find the unknown count edge"); 13050b57cec5SDimitry Andric } 13060b57cec5SDimitry Andric 1307fe6060f1SDimitry Andric // Emit function metadata indicating PGO profile mismatch. 130806c3fb27SDimitry Andric static void annotateFunctionWithHashMismatch(Function &F, LLVMContext &ctx) { 1309fe6060f1SDimitry Andric const char MetadataName[] = "instr_prof_hash_mismatch"; 1310fe6060f1SDimitry Andric SmallVector<Metadata *, 2> Names; 1311fe6060f1SDimitry Andric // If this metadata already exists, ignore. 1312fe6060f1SDimitry Andric auto *Existing = F.getMetadata(LLVMContext::MD_annotation); 1313fe6060f1SDimitry Andric if (Existing) { 1314fe6060f1SDimitry Andric MDTuple *Tuple = cast<MDTuple>(Existing); 1315bdd1243dSDimitry Andric for (const auto &N : Tuple->operands()) { 131606c3fb27SDimitry Andric if (N.equalsStr(MetadataName)) 1317fe6060f1SDimitry Andric return; 1318fe6060f1SDimitry Andric Names.push_back(N.get()); 1319fe6060f1SDimitry Andric } 1320fe6060f1SDimitry Andric } 1321fe6060f1SDimitry Andric 1322fe6060f1SDimitry Andric MDBuilder MDB(ctx); 1323fe6060f1SDimitry Andric Names.push_back(MDB.createString(MetadataName)); 1324fe6060f1SDimitry Andric MDNode *MD = MDTuple::get(ctx, Names); 1325fe6060f1SDimitry Andric F.setMetadata(LLVMContext::MD_annotation, MD); 1326fe6060f1SDimitry Andric } 1327fe6060f1SDimitry Andric 132806c3fb27SDimitry Andric void PGOUseFunc::handleInstrProfError(Error Err, uint64_t MismatchedFuncSum) { 132906c3fb27SDimitry Andric handleAllErrors(std::move(Err), [&](const InstrProfError &IPE) { 1330bdd1243dSDimitry Andric auto &Ctx = M->getContext(); 13310b57cec5SDimitry Andric auto Err = IPE.get(); 13320b57cec5SDimitry Andric bool SkipWarning = false; 13330b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Error in reading profile for Func " 13340b57cec5SDimitry Andric << FuncInfo.FuncName << ": "); 13350b57cec5SDimitry Andric if (Err == instrprof_error::unknown_function) { 13360b57cec5SDimitry Andric IsCS ? NumOfCSPGOMissing++ : NumOfPGOMissing++; 13370b57cec5SDimitry Andric SkipWarning = !PGOWarnMissing; 13380b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "unknown function"); 13390b57cec5SDimitry Andric } else if (Err == instrprof_error::hash_mismatch || 13400b57cec5SDimitry Andric Err == instrprof_error::malformed) { 13410b57cec5SDimitry Andric IsCS ? NumOfCSPGOMismatch++ : NumOfPGOMismatch++; 13420b57cec5SDimitry Andric SkipWarning = 13430b57cec5SDimitry Andric NoPGOWarnMismatch || 1344fcaf7f86SDimitry Andric (NoPGOWarnMismatchComdatWeak && 1345fcaf7f86SDimitry Andric (F.hasComdat() || F.getLinkage() == GlobalValue::WeakAnyLinkage || 13460b57cec5SDimitry Andric F.getLinkage() == GlobalValue::AvailableExternallyLinkage)); 1347fcaf7f86SDimitry Andric LLVM_DEBUG(dbgs() << "hash mismatch (hash= " << FuncInfo.FunctionHash 1348fcaf7f86SDimitry Andric << " skip=" << SkipWarning << ")"); 1349fe6060f1SDimitry Andric // Emit function metadata indicating PGO profile mismatch. 1350fe6060f1SDimitry Andric annotateFunctionWithHashMismatch(F, M->getContext()); 13510b57cec5SDimitry Andric } 13520b57cec5SDimitry Andric 13530b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " IsCS=" << IsCS << "\n"); 13540b57cec5SDimitry Andric if (SkipWarning) 13550b57cec5SDimitry Andric return; 13560b57cec5SDimitry Andric 1357fcaf7f86SDimitry Andric std::string Msg = 1358fcaf7f86SDimitry Andric IPE.message() + std::string(" ") + F.getName().str() + 1359fcaf7f86SDimitry Andric std::string(" Hash = ") + std::to_string(FuncInfo.FunctionHash) + 1360fcaf7f86SDimitry Andric std::string(" up to ") + std::to_string(MismatchedFuncSum) + 1361fcaf7f86SDimitry Andric std::string(" count discarded"); 13620b57cec5SDimitry Andric 13630b57cec5SDimitry Andric Ctx.diagnose( 13640b57cec5SDimitry Andric DiagnosticInfoPGOProfile(M->getName().data(), Msg, DS_Warning)); 13650b57cec5SDimitry Andric }); 136606c3fb27SDimitry Andric } 136706c3fb27SDimitry Andric 136806c3fb27SDimitry Andric // Read the profile from ProfileFileName and assign the value to the 136906c3fb27SDimitry Andric // instrumented BB and the edges. This function also updates ProgramMaxCount. 137006c3fb27SDimitry Andric // Return true if the profile are successfully read, and false on errors. 137106c3fb27SDimitry Andric bool PGOUseFunc::readCounters(IndexedInstrProfReader *PGOReader, bool &AllZeros, 137206c3fb27SDimitry Andric InstrProfRecord::CountPseudoKind &PseudoKind) { 137306c3fb27SDimitry Andric auto &Ctx = M->getContext(); 137406c3fb27SDimitry Andric uint64_t MismatchedFuncSum = 0; 137506c3fb27SDimitry Andric Expected<InstrProfRecord> Result = PGOReader->getInstrProfRecord( 13765f757f3fSDimitry Andric FuncInfo.FuncName, FuncInfo.FunctionHash, FuncInfo.DeprecatedFuncName, 13775f757f3fSDimitry Andric &MismatchedFuncSum); 137806c3fb27SDimitry Andric if (Error E = Result.takeError()) { 137906c3fb27SDimitry Andric handleInstrProfError(std::move(E), MismatchedFuncSum); 13800b57cec5SDimitry Andric return false; 13810b57cec5SDimitry Andric } 13820b57cec5SDimitry Andric ProfileRecord = std::move(Result.get()); 1383bdd1243dSDimitry Andric PseudoKind = ProfileRecord.getCountPseudoKind(); 1384bdd1243dSDimitry Andric if (PseudoKind != InstrProfRecord::NotPseudo) { 1385bdd1243dSDimitry Andric return true; 1386bdd1243dSDimitry Andric } 13870b57cec5SDimitry Andric std::vector<uint64_t> &CountFromProfile = ProfileRecord.Counts; 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric IsCS ? NumOfCSPGOFunc++ : NumOfPGOFunc++; 13900b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << CountFromProfile.size() << " counts\n"); 1391bdd1243dSDimitry Andric 13920b57cec5SDimitry Andric uint64_t ValueSum = 0; 13930b57cec5SDimitry Andric for (unsigned I = 0, S = CountFromProfile.size(); I < S; I++) { 13940b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " " << I << ": " << CountFromProfile[I] << "\n"); 13950b57cec5SDimitry Andric ValueSum += CountFromProfile[I]; 13960b57cec5SDimitry Andric } 13970b57cec5SDimitry Andric AllZeros = (ValueSum == 0); 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "SUM = " << ValueSum << "\n"); 14000b57cec5SDimitry Andric 14010b57cec5SDimitry Andric getBBInfo(nullptr).UnknownCountOutEdge = 2; 14020b57cec5SDimitry Andric getBBInfo(nullptr).UnknownCountInEdge = 2; 14030b57cec5SDimitry Andric 14040b57cec5SDimitry Andric if (!setInstrumentedCounts(CountFromProfile)) { 14050b57cec5SDimitry Andric LLVM_DEBUG( 14060b57cec5SDimitry Andric dbgs() << "Inconsistent number of counts, skipping this function"); 14070b57cec5SDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile( 14080b57cec5SDimitry Andric M->getName().data(), 140906c3fb27SDimitry Andric Twine("Inconsistent number of counts in ") + F.getName().str() + 141006c3fb27SDimitry Andric Twine(": the profile may be stale or there is a function name " 141106c3fb27SDimitry Andric "collision."), 14120b57cec5SDimitry Andric DS_Warning)); 14130b57cec5SDimitry Andric return false; 14140b57cec5SDimitry Andric } 14150b57cec5SDimitry Andric ProgramMaxCount = PGOReader->getMaximumFunctionCount(IsCS); 14160b57cec5SDimitry Andric return true; 14170b57cec5SDimitry Andric } 14180b57cec5SDimitry Andric 141906c3fb27SDimitry Andric void PGOUseFunc::populateCoverage(IndexedInstrProfReader *PGOReader) { 142006c3fb27SDimitry Andric uint64_t MismatchedFuncSum = 0; 142106c3fb27SDimitry Andric Expected<InstrProfRecord> Result = PGOReader->getInstrProfRecord( 14225f757f3fSDimitry Andric FuncInfo.FuncName, FuncInfo.FunctionHash, FuncInfo.DeprecatedFuncName, 14235f757f3fSDimitry Andric &MismatchedFuncSum); 142406c3fb27SDimitry Andric if (auto Err = Result.takeError()) { 142506c3fb27SDimitry Andric handleInstrProfError(std::move(Err), MismatchedFuncSum); 142606c3fb27SDimitry Andric return; 142706c3fb27SDimitry Andric } 14280fca6ea1SDimitry Andric IsCS ? NumOfCSPGOFunc++ : NumOfPGOFunc++; 142906c3fb27SDimitry Andric 143006c3fb27SDimitry Andric std::vector<uint64_t> &CountsFromProfile = Result.get().Counts; 143106c3fb27SDimitry Andric DenseMap<const BasicBlock *, bool> Coverage; 143206c3fb27SDimitry Andric unsigned Index = 0; 143306c3fb27SDimitry Andric for (auto &BB : F) 143406c3fb27SDimitry Andric if (FuncInfo.BCI->shouldInstrumentBlock(BB)) 143506c3fb27SDimitry Andric Coverage[&BB] = (CountsFromProfile[Index++] != 0); 143606c3fb27SDimitry Andric assert(Index == CountsFromProfile.size()); 143706c3fb27SDimitry Andric 143806c3fb27SDimitry Andric // For each B in InverseDependencies[A], if A is covered then B is covered. 143906c3fb27SDimitry Andric DenseMap<const BasicBlock *, DenseSet<const BasicBlock *>> 144006c3fb27SDimitry Andric InverseDependencies; 144106c3fb27SDimitry Andric for (auto &BB : F) { 144206c3fb27SDimitry Andric for (auto *Dep : FuncInfo.BCI->getDependencies(BB)) { 144306c3fb27SDimitry Andric // If Dep is covered then BB is covered. 144406c3fb27SDimitry Andric InverseDependencies[Dep].insert(&BB); 144506c3fb27SDimitry Andric } 144606c3fb27SDimitry Andric } 144706c3fb27SDimitry Andric 144806c3fb27SDimitry Andric // Infer coverage of the non-instrumented blocks using a flood-fill algorithm. 144906c3fb27SDimitry Andric std::stack<const BasicBlock *> CoveredBlocksToProcess; 145006c3fb27SDimitry Andric for (auto &[BB, IsCovered] : Coverage) 145106c3fb27SDimitry Andric if (IsCovered) 145206c3fb27SDimitry Andric CoveredBlocksToProcess.push(BB); 145306c3fb27SDimitry Andric 145406c3fb27SDimitry Andric while (!CoveredBlocksToProcess.empty()) { 145506c3fb27SDimitry Andric auto *CoveredBlock = CoveredBlocksToProcess.top(); 145606c3fb27SDimitry Andric assert(Coverage[CoveredBlock]); 145706c3fb27SDimitry Andric CoveredBlocksToProcess.pop(); 145806c3fb27SDimitry Andric for (auto *BB : InverseDependencies[CoveredBlock]) { 145906c3fb27SDimitry Andric // If CoveredBlock is covered then BB is covered. 146006c3fb27SDimitry Andric if (Coverage[BB]) 146106c3fb27SDimitry Andric continue; 146206c3fb27SDimitry Andric Coverage[BB] = true; 146306c3fb27SDimitry Andric CoveredBlocksToProcess.push(BB); 146406c3fb27SDimitry Andric } 146506c3fb27SDimitry Andric } 146606c3fb27SDimitry Andric 146706c3fb27SDimitry Andric // Annotate block coverage. 146806c3fb27SDimitry Andric MDBuilder MDB(F.getContext()); 146906c3fb27SDimitry Andric // We set the entry count to 10000 if the entry block is covered so that BFI 147006c3fb27SDimitry Andric // can propagate a fraction of this count to the other covered blocks. 147106c3fb27SDimitry Andric F.setEntryCount(Coverage[&F.getEntryBlock()] ? 10000 : 0); 147206c3fb27SDimitry Andric for (auto &BB : F) { 147306c3fb27SDimitry Andric // For a block A and its successor B, we set the edge weight as follows: 147406c3fb27SDimitry Andric // If A is covered and B is covered, set weight=1. 147506c3fb27SDimitry Andric // If A is covered and B is uncovered, set weight=0. 147606c3fb27SDimitry Andric // If A is uncovered, set weight=1. 147706c3fb27SDimitry Andric // This setup will allow BFI to give nonzero profile counts to only covered 147806c3fb27SDimitry Andric // blocks. 14795f757f3fSDimitry Andric SmallVector<uint32_t, 4> Weights; 148006c3fb27SDimitry Andric for (auto *Succ : successors(&BB)) 148106c3fb27SDimitry Andric Weights.push_back((Coverage[Succ] || !Coverage[&BB]) ? 1 : 0); 148206c3fb27SDimitry Andric if (Weights.size() >= 2) 14830fca6ea1SDimitry Andric llvm::setBranchWeights(*BB.getTerminator(), Weights, 14840fca6ea1SDimitry Andric /*IsExpected=*/false); 148506c3fb27SDimitry Andric } 148606c3fb27SDimitry Andric 148706c3fb27SDimitry Andric unsigned NumCorruptCoverage = 0; 148806c3fb27SDimitry Andric DominatorTree DT(F); 148906c3fb27SDimitry Andric LoopInfo LI(DT); 149006c3fb27SDimitry Andric BranchProbabilityInfo BPI(F, LI); 149106c3fb27SDimitry Andric BlockFrequencyInfo BFI(F, BPI, LI); 149206c3fb27SDimitry Andric auto IsBlockDead = [&](const BasicBlock &BB) -> std::optional<bool> { 149306c3fb27SDimitry Andric if (auto C = BFI.getBlockProfileCount(&BB)) 149406c3fb27SDimitry Andric return C == 0; 149506c3fb27SDimitry Andric return {}; 149606c3fb27SDimitry Andric }; 149706c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << "Block Coverage: (Instrumented=*, Covered=X)\n"); 149806c3fb27SDimitry Andric for (auto &BB : F) { 149906c3fb27SDimitry Andric LLVM_DEBUG(dbgs() << (FuncInfo.BCI->shouldInstrumentBlock(BB) ? "* " : " ") 150006c3fb27SDimitry Andric << (Coverage[&BB] ? "X " : " ") << " " << BB.getName() 150106c3fb27SDimitry Andric << "\n"); 150206c3fb27SDimitry Andric // In some cases it is possible to find a covered block that has no covered 150306c3fb27SDimitry Andric // successors, e.g., when a block calls a function that may call exit(). In 150406c3fb27SDimitry Andric // those cases, BFI could find its successor to be covered while BCI could 150506c3fb27SDimitry Andric // find its successor to be dead. 150606c3fb27SDimitry Andric if (Coverage[&BB] == IsBlockDead(BB).value_or(false)) { 150706c3fb27SDimitry Andric LLVM_DEBUG( 150806c3fb27SDimitry Andric dbgs() << "Found inconsistent block covearge for " << BB.getName() 150906c3fb27SDimitry Andric << ": BCI=" << (Coverage[&BB] ? "Covered" : "Dead") << " BFI=" 151006c3fb27SDimitry Andric << (IsBlockDead(BB).value() ? "Dead" : "Covered") << "\n"); 151106c3fb27SDimitry Andric ++NumCorruptCoverage; 151206c3fb27SDimitry Andric } 151306c3fb27SDimitry Andric if (Coverage[&BB]) 151406c3fb27SDimitry Andric ++NumCoveredBlocks; 151506c3fb27SDimitry Andric } 151606c3fb27SDimitry Andric if (PGOVerifyBFI && NumCorruptCoverage) { 151706c3fb27SDimitry Andric auto &Ctx = M->getContext(); 151806c3fb27SDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile( 151906c3fb27SDimitry Andric M->getName().data(), 152006c3fb27SDimitry Andric Twine("Found inconsistent block coverage for function ") + F.getName() + 152106c3fb27SDimitry Andric " in " + Twine(NumCorruptCoverage) + " blocks.", 152206c3fb27SDimitry Andric DS_Warning)); 152306c3fb27SDimitry Andric } 152406c3fb27SDimitry Andric if (PGOViewBlockCoverageGraph) 152506c3fb27SDimitry Andric FuncInfo.BCI->viewBlockCoverageGraph(&Coverage); 152606c3fb27SDimitry Andric } 152706c3fb27SDimitry Andric 15280b57cec5SDimitry Andric // Populate the counters from instrumented BBs to all BBs. 15290b57cec5SDimitry Andric // In the end of this operation, all BBs should have a valid count value. 15300b57cec5SDimitry Andric void PGOUseFunc::populateCounters() { 15310b57cec5SDimitry Andric bool Changes = true; 15320b57cec5SDimitry Andric unsigned NumPasses = 0; 15330b57cec5SDimitry Andric while (Changes) { 15340b57cec5SDimitry Andric NumPasses++; 15350b57cec5SDimitry Andric Changes = false; 15360b57cec5SDimitry Andric 15370b57cec5SDimitry Andric // For efficient traversal, it's better to start from the end as most 15380b57cec5SDimitry Andric // of the instrumented edges are at the end. 15390b57cec5SDimitry Andric for (auto &BB : reverse(F)) { 15400fca6ea1SDimitry Andric PGOUseBBInfo *UseBBInfo = findBBInfo(&BB); 15410fca6ea1SDimitry Andric if (UseBBInfo == nullptr) 15420b57cec5SDimitry Andric continue; 15430fca6ea1SDimitry Andric if (!UseBBInfo->Count) { 15440fca6ea1SDimitry Andric if (UseBBInfo->UnknownCountOutEdge == 0) { 15450fca6ea1SDimitry Andric UseBBInfo->Count = sumEdgeCount(UseBBInfo->OutEdges); 15460b57cec5SDimitry Andric Changes = true; 15470fca6ea1SDimitry Andric } else if (UseBBInfo->UnknownCountInEdge == 0) { 15480fca6ea1SDimitry Andric UseBBInfo->Count = sumEdgeCount(UseBBInfo->InEdges); 15490b57cec5SDimitry Andric Changes = true; 15500b57cec5SDimitry Andric } 15510b57cec5SDimitry Andric } 15520fca6ea1SDimitry Andric if (UseBBInfo->Count) { 15530fca6ea1SDimitry Andric if (UseBBInfo->UnknownCountOutEdge == 1) { 15540b57cec5SDimitry Andric uint64_t Total = 0; 15550fca6ea1SDimitry Andric uint64_t OutSum = sumEdgeCount(UseBBInfo->OutEdges); 15560b57cec5SDimitry Andric // If the one of the successor block can early terminate (no-return), 15570b57cec5SDimitry Andric // we can end up with situation where out edge sum count is larger as 15580b57cec5SDimitry Andric // the source BB's count is collected by a post-dominated block. 15590fca6ea1SDimitry Andric if (*UseBBInfo->Count > OutSum) 15600fca6ea1SDimitry Andric Total = *UseBBInfo->Count - OutSum; 15610fca6ea1SDimitry Andric setEdgeCount(UseBBInfo->OutEdges, Total); 15620b57cec5SDimitry Andric Changes = true; 15630b57cec5SDimitry Andric } 15640fca6ea1SDimitry Andric if (UseBBInfo->UnknownCountInEdge == 1) { 15650b57cec5SDimitry Andric uint64_t Total = 0; 15660fca6ea1SDimitry Andric uint64_t InSum = sumEdgeCount(UseBBInfo->InEdges); 15670fca6ea1SDimitry Andric if (*UseBBInfo->Count > InSum) 15680fca6ea1SDimitry Andric Total = *UseBBInfo->Count - InSum; 15690fca6ea1SDimitry Andric setEdgeCount(UseBBInfo->InEdges, Total); 15700b57cec5SDimitry Andric Changes = true; 15710b57cec5SDimitry Andric } 15720b57cec5SDimitry Andric } 15730b57cec5SDimitry Andric } 15740b57cec5SDimitry Andric } 15750b57cec5SDimitry Andric 15760b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Populate counts in " << NumPasses << " passes.\n"); 157781ad6265SDimitry Andric (void)NumPasses; 15780b57cec5SDimitry Andric #ifndef NDEBUG 15790b57cec5SDimitry Andric // Assert every BB has a valid counter. 15800b57cec5SDimitry Andric for (auto &BB : F) { 15810b57cec5SDimitry Andric auto BI = findBBInfo(&BB); 15820b57cec5SDimitry Andric if (BI == nullptr) 15830b57cec5SDimitry Andric continue; 15840fca6ea1SDimitry Andric assert(BI->Count && "BB count is not valid"); 15850b57cec5SDimitry Andric } 15860b57cec5SDimitry Andric #endif 15870fca6ea1SDimitry Andric uint64_t FuncEntryCount = *getBBInfo(&*F.begin()).Count; 15880b57cec5SDimitry Andric uint64_t FuncMaxCount = FuncEntryCount; 15890b57cec5SDimitry Andric for (auto &BB : F) { 15900b57cec5SDimitry Andric auto BI = findBBInfo(&BB); 15910b57cec5SDimitry Andric if (BI == nullptr) 15920b57cec5SDimitry Andric continue; 15930fca6ea1SDimitry Andric FuncMaxCount = std::max(FuncMaxCount, *BI->Count); 15940b57cec5SDimitry Andric } 1595e8d8bef9SDimitry Andric 1596e8d8bef9SDimitry Andric // Fix the obviously inconsistent entry count. 1597e8d8bef9SDimitry Andric if (FuncMaxCount > 0 && FuncEntryCount == 0) 1598e8d8bef9SDimitry Andric FuncEntryCount = 1; 1599e8d8bef9SDimitry Andric F.setEntryCount(ProfileCount(FuncEntryCount, Function::PCT_Real)); 16000b57cec5SDimitry Andric markFunctionAttributes(FuncEntryCount, FuncMaxCount); 16010b57cec5SDimitry Andric 16020b57cec5SDimitry Andric // Now annotate select instructions 160306c3fb27SDimitry Andric FuncInfo.SIVisitor.annotateSelects(this, &CountPosition); 16040b57cec5SDimitry Andric assert(CountPosition == ProfileCountSize); 16050b57cec5SDimitry Andric 16060b57cec5SDimitry Andric LLVM_DEBUG(FuncInfo.dumpInfo("after reading profile.")); 16070b57cec5SDimitry Andric } 16080b57cec5SDimitry Andric 16090b57cec5SDimitry Andric // Assign the scaled count values to the BB with multiple out edges. 16100b57cec5SDimitry Andric void PGOUseFunc::setBranchWeights() { 16110b57cec5SDimitry Andric // Generate MD_prof metadata for every branch instruction. 16120b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nSetting branch weights for func " << F.getName() 16130b57cec5SDimitry Andric << " IsCS=" << IsCS << "\n"); 16140b57cec5SDimitry Andric for (auto &BB : F) { 16150b57cec5SDimitry Andric Instruction *TI = BB.getTerminator(); 16160b57cec5SDimitry Andric if (TI->getNumSuccessors() < 2) 16170b57cec5SDimitry Andric continue; 16180b57cec5SDimitry Andric if (!(isa<BranchInst>(TI) || isa<SwitchInst>(TI) || 1619bdd1243dSDimitry Andric isa<IndirectBrInst>(TI) || isa<InvokeInst>(TI) || 1620bdd1243dSDimitry Andric isa<CallBrInst>(TI))) 16210b57cec5SDimitry Andric continue; 16220b57cec5SDimitry Andric 16230fca6ea1SDimitry Andric const PGOUseBBInfo &BBCountInfo = getBBInfo(&BB); 16240fca6ea1SDimitry Andric if (!*BBCountInfo.Count) 16250b57cec5SDimitry Andric continue; 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric // We have a non-zero Branch BB. 1628*6c4b055cSDimitry Andric 1629*6c4b055cSDimitry Andric // SuccessorCount can be greater than OutEdgesCount, because 1630*6c4b055cSDimitry Andric // removed edges don't appear in OutEdges. 1631*6c4b055cSDimitry Andric unsigned OutEdgesCount = BBCountInfo.OutEdges.size(); 1632*6c4b055cSDimitry Andric unsigned SuccessorCount = BB.getTerminator()->getNumSuccessors(); 1633*6c4b055cSDimitry Andric assert(OutEdgesCount <= SuccessorCount); 1634*6c4b055cSDimitry Andric 1635*6c4b055cSDimitry Andric SmallVector<uint64_t, 2> EdgeCounts(SuccessorCount, 0); 16360b57cec5SDimitry Andric uint64_t MaxCount = 0; 1637*6c4b055cSDimitry Andric for (unsigned It = 0; It < OutEdgesCount; It++) { 1638*6c4b055cSDimitry Andric const PGOUseEdge *E = BBCountInfo.OutEdges[It]; 16390b57cec5SDimitry Andric const BasicBlock *SrcBB = E->SrcBB; 16400b57cec5SDimitry Andric const BasicBlock *DestBB = E->DestBB; 16410b57cec5SDimitry Andric if (DestBB == nullptr) 16420b57cec5SDimitry Andric continue; 16430b57cec5SDimitry Andric unsigned SuccNum = GetSuccessorNumber(SrcBB, DestBB); 16440fca6ea1SDimitry Andric uint64_t EdgeCount = *E->Count; 16450b57cec5SDimitry Andric if (EdgeCount > MaxCount) 16460b57cec5SDimitry Andric MaxCount = EdgeCount; 16470b57cec5SDimitry Andric EdgeCounts[SuccNum] = EdgeCount; 16480b57cec5SDimitry Andric } 1649bdd1243dSDimitry Andric 1650bdd1243dSDimitry Andric if (MaxCount) 16510b57cec5SDimitry Andric setProfMetadata(M, TI, EdgeCounts, MaxCount); 1652bdd1243dSDimitry Andric else { 1653bdd1243dSDimitry Andric // A zero MaxCount can come about when we have a BB with a positive 1654bdd1243dSDimitry Andric // count, and whose successor blocks all have 0 count. This can happen 1655bdd1243dSDimitry Andric // when there is no exit block and the code exits via a noreturn function. 1656bdd1243dSDimitry Andric auto &Ctx = M->getContext(); 1657bdd1243dSDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile( 1658bdd1243dSDimitry Andric M->getName().data(), 1659bdd1243dSDimitry Andric Twine("Profile in ") + F.getName().str() + 1660bdd1243dSDimitry Andric Twine(" partially ignored") + 1661bdd1243dSDimitry Andric Twine(", possibly due to the lack of a return path."), 1662bdd1243dSDimitry Andric DS_Warning)); 1663bdd1243dSDimitry Andric } 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric } 16660b57cec5SDimitry Andric 16670b57cec5SDimitry Andric static bool isIndirectBrTarget(BasicBlock *BB) { 1668fe6060f1SDimitry Andric for (BasicBlock *Pred : predecessors(BB)) { 1669fe6060f1SDimitry Andric if (isa<IndirectBrInst>(Pred->getTerminator())) 16700b57cec5SDimitry Andric return true; 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric return false; 16730b57cec5SDimitry Andric } 16740b57cec5SDimitry Andric 16750b57cec5SDimitry Andric void PGOUseFunc::annotateIrrLoopHeaderWeights() { 16760b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nAnnotating irreducible loop header weights.\n"); 16770b57cec5SDimitry Andric // Find irr loop headers 16780b57cec5SDimitry Andric for (auto &BB : F) { 16790b57cec5SDimitry Andric // As a heuristic also annotate indrectbr targets as they have a high chance 16800b57cec5SDimitry Andric // to become an irreducible loop header after the indirectbr tail 16810b57cec5SDimitry Andric // duplication. 16820b57cec5SDimitry Andric if (BFI->isIrrLoopHeader(&BB) || isIndirectBrTarget(&BB)) { 16830b57cec5SDimitry Andric Instruction *TI = BB.getTerminator(); 168406c3fb27SDimitry Andric const PGOUseBBInfo &BBCountInfo = getBBInfo(&BB); 16850fca6ea1SDimitry Andric setIrrLoopHeaderMetadata(M, TI, *BBCountInfo.Count); 16860b57cec5SDimitry Andric } 16870b57cec5SDimitry Andric } 16880b57cec5SDimitry Andric } 16890b57cec5SDimitry Andric 16900b57cec5SDimitry Andric void SelectInstVisitor::instrumentOneSelectInst(SelectInst &SI) { 16910b57cec5SDimitry Andric Module *M = F.getParent(); 16920b57cec5SDimitry Andric IRBuilder<> Builder(&SI); 16930b57cec5SDimitry Andric Type *Int64Ty = Builder.getInt64Ty(); 16940b57cec5SDimitry Andric auto *Step = Builder.CreateZExt(SI.getCondition(), Int64Ty); 16950b57cec5SDimitry Andric Builder.CreateCall( 16960b57cec5SDimitry Andric Intrinsic::getDeclaration(M, Intrinsic::instrprof_increment_step), 16975f757f3fSDimitry Andric {FuncNameVar, Builder.getInt64(FuncHash), Builder.getInt32(TotalNumCtrs), 16980b57cec5SDimitry Andric Builder.getInt32(*CurCtrIdx), Step}); 16990b57cec5SDimitry Andric ++(*CurCtrIdx); 17000b57cec5SDimitry Andric } 17010b57cec5SDimitry Andric 17020b57cec5SDimitry Andric void SelectInstVisitor::annotateOneSelectInst(SelectInst &SI) { 17030b57cec5SDimitry Andric std::vector<uint64_t> &CountFromProfile = UseFunc->getProfileRecord().Counts; 17040b57cec5SDimitry Andric assert(*CurCtrIdx < CountFromProfile.size() && 17050b57cec5SDimitry Andric "Out of bound access of counters"); 17060b57cec5SDimitry Andric uint64_t SCounts[2]; 17070b57cec5SDimitry Andric SCounts[0] = CountFromProfile[*CurCtrIdx]; // True count 17080b57cec5SDimitry Andric ++(*CurCtrIdx); 17090b57cec5SDimitry Andric uint64_t TotalCount = 0; 17100b57cec5SDimitry Andric auto BI = UseFunc->findBBInfo(SI.getParent()); 17110b57cec5SDimitry Andric if (BI != nullptr) 17120fca6ea1SDimitry Andric TotalCount = *BI->Count; 17130b57cec5SDimitry Andric // False Count 17140b57cec5SDimitry Andric SCounts[1] = (TotalCount > SCounts[0] ? TotalCount - SCounts[0] : 0); 17150b57cec5SDimitry Andric uint64_t MaxCount = std::max(SCounts[0], SCounts[1]); 17160b57cec5SDimitry Andric if (MaxCount) 17170b57cec5SDimitry Andric setProfMetadata(F.getParent(), &SI, SCounts, MaxCount); 17180b57cec5SDimitry Andric } 17190b57cec5SDimitry Andric 17200b57cec5SDimitry Andric void SelectInstVisitor::visitSelectInst(SelectInst &SI) { 172106c3fb27SDimitry Andric if (!PGOInstrSelect || PGOFunctionEntryCoverage || HasSingleByteCoverage) 17220b57cec5SDimitry Andric return; 17230b57cec5SDimitry Andric // FIXME: do not handle this yet. 17240b57cec5SDimitry Andric if (SI.getCondition()->getType()->isVectorTy()) 17250b57cec5SDimitry Andric return; 17260b57cec5SDimitry Andric 17270b57cec5SDimitry Andric switch (Mode) { 17280b57cec5SDimitry Andric case VM_counting: 17290b57cec5SDimitry Andric NSIs++; 17300b57cec5SDimitry Andric return; 17310b57cec5SDimitry Andric case VM_instrument: 17320b57cec5SDimitry Andric instrumentOneSelectInst(SI); 17330b57cec5SDimitry Andric return; 17340b57cec5SDimitry Andric case VM_annotate: 17350b57cec5SDimitry Andric annotateOneSelectInst(SI); 17360b57cec5SDimitry Andric return; 17370b57cec5SDimitry Andric } 17380b57cec5SDimitry Andric 17390b57cec5SDimitry Andric llvm_unreachable("Unknown visiting mode"); 17400b57cec5SDimitry Andric } 17410b57cec5SDimitry Andric 17420fca6ea1SDimitry Andric static uint32_t getMaxNumAnnotations(InstrProfValueKind ValueProfKind) { 17430fca6ea1SDimitry Andric if (ValueProfKind == IPVK_MemOPSize) 17440fca6ea1SDimitry Andric return MaxNumMemOPAnnotations; 17450fca6ea1SDimitry Andric if (ValueProfKind == llvm::IPVK_VTableTarget) 17460fca6ea1SDimitry Andric return MaxNumVTableAnnotations; 17470fca6ea1SDimitry Andric return MaxNumAnnotations; 17480fca6ea1SDimitry Andric } 17490fca6ea1SDimitry Andric 17500b57cec5SDimitry Andric // Traverse all valuesites and annotate the instructions for all value kind. 17510b57cec5SDimitry Andric void PGOUseFunc::annotateValueSites() { 17520fca6ea1SDimitry Andric if (isValueProfilingDisabled()) 17530b57cec5SDimitry Andric return; 17540b57cec5SDimitry Andric 17550b57cec5SDimitry Andric // Create the PGOFuncName meta data. 17560b57cec5SDimitry Andric createPGOFuncNameMetadata(F, FuncInfo.FuncName); 17570b57cec5SDimitry Andric 17580b57cec5SDimitry Andric for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) 17590b57cec5SDimitry Andric annotateValueSites(Kind); 17600b57cec5SDimitry Andric } 17610b57cec5SDimitry Andric 17620b57cec5SDimitry Andric // Annotate the instructions for a specific value kind. 17630b57cec5SDimitry Andric void PGOUseFunc::annotateValueSites(uint32_t Kind) { 17640b57cec5SDimitry Andric assert(Kind <= IPVK_Last); 17650b57cec5SDimitry Andric unsigned ValueSiteIndex = 0; 17660fca6ea1SDimitry Andric 17670b57cec5SDimitry Andric unsigned NumValueSites = ProfileRecord.getNumValueSites(Kind); 17680fca6ea1SDimitry Andric 17690fca6ea1SDimitry Andric // Since there isn't a reliable or fast way for profile reader to tell if a 17700fca6ea1SDimitry Andric // profile is generated with `-enable-vtable-value-profiling` on, we run the 17710fca6ea1SDimitry Andric // value profile collector over the function IR to find the instrumented sites 17720fca6ea1SDimitry Andric // iff function profile records shows the number of instrumented vtable sites 17730fca6ea1SDimitry Andric // is not zero. Function cfg already takes the number of instrumented 17740fca6ea1SDimitry Andric // indirect call sites into account so it doesn't hash the number of 17750fca6ea1SDimitry Andric // instrumented vtables; as a side effect it makes it easier to enable 17760fca6ea1SDimitry Andric // profiling and profile use in two steps if needed. 17770fca6ea1SDimitry Andric // TODO: Remove this if/when -enable-vtable-value-profiling is on by default. 17780fca6ea1SDimitry Andric if (NumValueSites > 0 && Kind == IPVK_VTableTarget && 17790fca6ea1SDimitry Andric NumValueSites != FuncInfo.ValueSites[IPVK_VTableTarget].size() && 17800fca6ea1SDimitry Andric MaxNumVTableAnnotations != 0) 17810fca6ea1SDimitry Andric FuncInfo.ValueSites[IPVK_VTableTarget] = VPC.get(IPVK_VTableTarget); 17820fca6ea1SDimitry Andric auto &ValueSites = FuncInfo.ValueSites[Kind]; 17830b57cec5SDimitry Andric if (NumValueSites != ValueSites.size()) { 17840b57cec5SDimitry Andric auto &Ctx = M->getContext(); 17850b57cec5SDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile( 17860b57cec5SDimitry Andric M->getName().data(), 17870b57cec5SDimitry Andric Twine("Inconsistent number of value sites for ") + 178806c3fb27SDimitry Andric Twine(ValueProfKindDescr[Kind]) + Twine(" profiling in \"") + 178906c3fb27SDimitry Andric F.getName().str() + 17900b57cec5SDimitry Andric Twine("\", possibly due to the use of a stale profile."), 17910b57cec5SDimitry Andric DS_Warning)); 17920b57cec5SDimitry Andric return; 17930b57cec5SDimitry Andric } 17940b57cec5SDimitry Andric 17958bcb0991SDimitry Andric for (VPCandidateInfo &I : ValueSites) { 17960b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Read one value site profile (kind = " << Kind 17970b57cec5SDimitry Andric << "): Index = " << ValueSiteIndex << " out of " 17980b57cec5SDimitry Andric << NumValueSites << "\n"); 17990fca6ea1SDimitry Andric annotateValueSite( 18000fca6ea1SDimitry Andric *M, *I.AnnotatedInst, ProfileRecord, 18010b57cec5SDimitry Andric static_cast<InstrProfValueKind>(Kind), ValueSiteIndex, 18020fca6ea1SDimitry Andric getMaxNumAnnotations(static_cast<InstrProfValueKind>(Kind))); 18030b57cec5SDimitry Andric ValueSiteIndex++; 18040b57cec5SDimitry Andric } 18050b57cec5SDimitry Andric } 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric // Collect the set of members for each Comdat in module M and store 18080b57cec5SDimitry Andric // in ComdatMembers. 18090b57cec5SDimitry Andric static void collectComdatMembers( 18100b57cec5SDimitry Andric Module &M, 18110b57cec5SDimitry Andric std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers) { 18120b57cec5SDimitry Andric if (!DoComdatRenaming) 18130b57cec5SDimitry Andric return; 18140b57cec5SDimitry Andric for (Function &F : M) 18150b57cec5SDimitry Andric if (Comdat *C = F.getComdat()) 18160b57cec5SDimitry Andric ComdatMembers.insert(std::make_pair(C, &F)); 18170b57cec5SDimitry Andric for (GlobalVariable &GV : M.globals()) 18180b57cec5SDimitry Andric if (Comdat *C = GV.getComdat()) 18190b57cec5SDimitry Andric ComdatMembers.insert(std::make_pair(C, &GV)); 18200b57cec5SDimitry Andric for (GlobalAlias &GA : M.aliases()) 18210b57cec5SDimitry Andric if (Comdat *C = GA.getComdat()) 18220b57cec5SDimitry Andric ComdatMembers.insert(std::make_pair(C, &GA)); 18230b57cec5SDimitry Andric } 18240b57cec5SDimitry Andric 18255f757f3fSDimitry Andric // Return true if we should not find instrumentation data for this function 18265f757f3fSDimitry Andric static bool skipPGOUse(const Function &F) { 1827bdd1243dSDimitry Andric if (F.isDeclaration()) 1828bdd1243dSDimitry Andric return true; 1829bdd1243dSDimitry Andric // If there are too many critical edges, PGO might cause 1830bdd1243dSDimitry Andric // compiler time problem. Skip PGO if the number of 1831bdd1243dSDimitry Andric // critical edges execeed the threshold. 1832bdd1243dSDimitry Andric unsigned NumCriticalEdges = 0; 1833bdd1243dSDimitry Andric for (auto &BB : F) { 1834bdd1243dSDimitry Andric const Instruction *TI = BB.getTerminator(); 1835bdd1243dSDimitry Andric for (unsigned I = 0, E = TI->getNumSuccessors(); I != E; ++I) { 1836bdd1243dSDimitry Andric if (isCriticalEdge(TI, I)) 1837bdd1243dSDimitry Andric NumCriticalEdges++; 1838bdd1243dSDimitry Andric } 1839bdd1243dSDimitry Andric } 1840bdd1243dSDimitry Andric if (NumCriticalEdges > PGOFunctionCriticalEdgeThreshold) { 1841bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "In func " << F.getName() 1842bdd1243dSDimitry Andric << ", NumCriticalEdges=" << NumCriticalEdges 1843bdd1243dSDimitry Andric << " exceed the threshold. Skip PGO.\n"); 1844bdd1243dSDimitry Andric return true; 1845bdd1243dSDimitry Andric } 18465f757f3fSDimitry Andric return false; 18475f757f3fSDimitry Andric } 1848bdd1243dSDimitry Andric 18495f757f3fSDimitry Andric // Return true if we should not instrument this function 18505f757f3fSDimitry Andric static bool skipPGOGen(const Function &F) { 18515f757f3fSDimitry Andric if (skipPGOUse(F)) 18525f757f3fSDimitry Andric return true; 18535f757f3fSDimitry Andric if (F.hasFnAttribute(llvm::Attribute::Naked)) 18545f757f3fSDimitry Andric return true; 18555f757f3fSDimitry Andric if (F.hasFnAttribute(llvm::Attribute::NoProfile)) 18565f757f3fSDimitry Andric return true; 18575f757f3fSDimitry Andric if (F.hasFnAttribute(llvm::Attribute::SkipProfile)) 18585f757f3fSDimitry Andric return true; 18595f757f3fSDimitry Andric if (F.getInstructionCount() < PGOFunctionSizeThreshold) 18605f757f3fSDimitry Andric return true; 1861bdd1243dSDimitry Andric return false; 1862bdd1243dSDimitry Andric } 1863bdd1243dSDimitry Andric 18640b57cec5SDimitry Andric static bool InstrumentAllFunctions( 18655ffd83dbSDimitry Andric Module &M, function_ref<TargetLibraryInfo &(Function &)> LookupTLI, 18665ffd83dbSDimitry Andric function_ref<BranchProbabilityInfo *(Function &)> LookupBPI, 18670b57cec5SDimitry Andric function_ref<BlockFrequencyInfo *(Function &)> LookupBFI, bool IsCS) { 18680b57cec5SDimitry Andric // For the context-sensitve instrumentation, we should have a separated pass 18690b57cec5SDimitry Andric // (before LTO/ThinLTO linking) to create these variables. 18700fca6ea1SDimitry Andric if (!IsCS && !PGOCtxProfLoweringPass::isContextualIRPGOEnabled()) 18711fd87a68SDimitry Andric createIRLevelProfileFlagVar(M, /*IsCS=*/false); 18720fca6ea1SDimitry Andric 18730fca6ea1SDimitry Andric Triple TT(M.getTargetTriple()); 18740fca6ea1SDimitry Andric LLVMContext &Ctx = M.getContext(); 18750fca6ea1SDimitry Andric if (!TT.isOSBinFormatELF() && EnableVTableValueProfiling) 18760fca6ea1SDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile( 18770fca6ea1SDimitry Andric M.getName().data(), 18780fca6ea1SDimitry Andric Twine("VTable value profiling is presently not " 18790fca6ea1SDimitry Andric "supported for non-ELF object formats"), 18800fca6ea1SDimitry Andric DS_Warning)); 18810b57cec5SDimitry Andric std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers; 18820b57cec5SDimitry Andric collectComdatMembers(M, ComdatMembers); 18830b57cec5SDimitry Andric 18840b57cec5SDimitry Andric for (auto &F : M) { 18855f757f3fSDimitry Andric if (skipPGOGen(F)) 1886e8d8bef9SDimitry Andric continue; 18875ffd83dbSDimitry Andric auto &TLI = LookupTLI(F); 18880b57cec5SDimitry Andric auto *BPI = LookupBPI(F); 18890b57cec5SDimitry Andric auto *BFI = LookupBFI(F); 18905ffd83dbSDimitry Andric instrumentOneFunc(F, &M, TLI, BPI, BFI, ComdatMembers, IsCS); 18910b57cec5SDimitry Andric } 18920b57cec5SDimitry Andric return true; 18930b57cec5SDimitry Andric } 18940b57cec5SDimitry Andric 18950b57cec5SDimitry Andric PreservedAnalyses 189606c3fb27SDimitry Andric PGOInstrumentationGenCreateVar::run(Module &M, ModuleAnalysisManager &MAM) { 18970b57cec5SDimitry Andric createProfileFileNameVar(M, CSInstrName); 1898349cc55cSDimitry Andric // The variable in a comdat may be discarded by LTO. Ensure the declaration 1899349cc55cSDimitry Andric // will be retained. 19001fd87a68SDimitry Andric appendToCompilerUsed(M, createIRLevelProfileFlagVar(M, /*IsCS=*/true)); 19010fca6ea1SDimitry Andric if (ProfileSampling) 19020fca6ea1SDimitry Andric createProfileSamplingVar(M); 190306c3fb27SDimitry Andric PreservedAnalyses PA; 190406c3fb27SDimitry Andric PA.preserve<FunctionAnalysisManagerModuleProxy>(); 190506c3fb27SDimitry Andric PA.preserveSet<AllAnalysesOn<Function>>(); 190606c3fb27SDimitry Andric return PA; 19070b57cec5SDimitry Andric } 19080b57cec5SDimitry Andric 19090b57cec5SDimitry Andric PreservedAnalyses PGOInstrumentationGen::run(Module &M, 191006c3fb27SDimitry Andric ModuleAnalysisManager &MAM) { 191106c3fb27SDimitry Andric auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 19125ffd83dbSDimitry Andric auto LookupTLI = [&FAM](Function &F) -> TargetLibraryInfo & { 19135ffd83dbSDimitry Andric return FAM.getResult<TargetLibraryAnalysis>(F); 19145ffd83dbSDimitry Andric }; 19150b57cec5SDimitry Andric auto LookupBPI = [&FAM](Function &F) { 19160b57cec5SDimitry Andric return &FAM.getResult<BranchProbabilityAnalysis>(F); 19170b57cec5SDimitry Andric }; 19180b57cec5SDimitry Andric auto LookupBFI = [&FAM](Function &F) { 19190b57cec5SDimitry Andric return &FAM.getResult<BlockFrequencyAnalysis>(F); 19200b57cec5SDimitry Andric }; 19210b57cec5SDimitry Andric 19225ffd83dbSDimitry Andric if (!InstrumentAllFunctions(M, LookupTLI, LookupBPI, LookupBFI, IsCS)) 19230b57cec5SDimitry Andric return PreservedAnalyses::all(); 19240b57cec5SDimitry Andric 19250b57cec5SDimitry Andric return PreservedAnalyses::none(); 19260b57cec5SDimitry Andric } 19270b57cec5SDimitry Andric 1928e8d8bef9SDimitry Andric // Using the ratio b/w sums of profile count values and BFI count values to 1929e8d8bef9SDimitry Andric // adjust the func entry count. 1930e8d8bef9SDimitry Andric static void fixFuncEntryCount(PGOUseFunc &Func, LoopInfo &LI, 1931e8d8bef9SDimitry Andric BranchProbabilityInfo &NBPI) { 1932e8d8bef9SDimitry Andric Function &F = Func.getFunc(); 1933e8d8bef9SDimitry Andric BlockFrequencyInfo NBFI(F, NBPI, LI); 1934e8d8bef9SDimitry Andric #ifndef NDEBUG 1935e8d8bef9SDimitry Andric auto BFIEntryCount = F.getEntryCount(); 193681ad6265SDimitry Andric assert(BFIEntryCount && (BFIEntryCount->getCount() > 0) && 1937e8d8bef9SDimitry Andric "Invalid BFI Entrycount"); 1938e8d8bef9SDimitry Andric #endif 1939e8d8bef9SDimitry Andric auto SumCount = APFloat::getZero(APFloat::IEEEdouble()); 1940e8d8bef9SDimitry Andric auto SumBFICount = APFloat::getZero(APFloat::IEEEdouble()); 1941e8d8bef9SDimitry Andric for (auto &BBI : F) { 1942e8d8bef9SDimitry Andric uint64_t CountValue = 0; 1943e8d8bef9SDimitry Andric uint64_t BFICountValue = 0; 1944e8d8bef9SDimitry Andric if (!Func.findBBInfo(&BBI)) 1945e8d8bef9SDimitry Andric continue; 1946e8d8bef9SDimitry Andric auto BFICount = NBFI.getBlockProfileCount(&BBI); 19470fca6ea1SDimitry Andric CountValue = *Func.getBBInfo(&BBI).Count; 194881ad6265SDimitry Andric BFICountValue = *BFICount; 1949e8d8bef9SDimitry Andric SumCount.add(APFloat(CountValue * 1.0), APFloat::rmNearestTiesToEven); 1950e8d8bef9SDimitry Andric SumBFICount.add(APFloat(BFICountValue * 1.0), APFloat::rmNearestTiesToEven); 1951e8d8bef9SDimitry Andric } 1952e8d8bef9SDimitry Andric if (SumCount.isZero()) 1953e8d8bef9SDimitry Andric return; 1954e8d8bef9SDimitry Andric 1955e8d8bef9SDimitry Andric assert(SumBFICount.compare(APFloat(0.0)) == APFloat::cmpGreaterThan && 1956e8d8bef9SDimitry Andric "Incorrect sum of BFI counts"); 1957e8d8bef9SDimitry Andric if (SumBFICount.compare(SumCount) == APFloat::cmpEqual) 1958e8d8bef9SDimitry Andric return; 1959e8d8bef9SDimitry Andric double Scale = (SumCount / SumBFICount).convertToDouble(); 1960e8d8bef9SDimitry Andric if (Scale < 1.001 && Scale > 0.999) 1961e8d8bef9SDimitry Andric return; 1962e8d8bef9SDimitry Andric 19630fca6ea1SDimitry Andric uint64_t FuncEntryCount = *Func.getBBInfo(&*F.begin()).Count; 1964e8d8bef9SDimitry Andric uint64_t NewEntryCount = 0.5 + FuncEntryCount * Scale; 1965e8d8bef9SDimitry Andric if (NewEntryCount == 0) 1966e8d8bef9SDimitry Andric NewEntryCount = 1; 1967e8d8bef9SDimitry Andric if (NewEntryCount != FuncEntryCount) { 1968e8d8bef9SDimitry Andric F.setEntryCount(ProfileCount(NewEntryCount, Function::PCT_Real)); 1969e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "FixFuncEntryCount: in " << F.getName() 1970e8d8bef9SDimitry Andric << ", entry_count " << FuncEntryCount << " --> " 1971e8d8bef9SDimitry Andric << NewEntryCount << "\n"); 1972e8d8bef9SDimitry Andric } 1973e8d8bef9SDimitry Andric } 1974e8d8bef9SDimitry Andric 1975e8d8bef9SDimitry Andric // Compare the profile count values with BFI count values, and print out 1976e8d8bef9SDimitry Andric // the non-matching ones. 1977e8d8bef9SDimitry Andric static void verifyFuncBFI(PGOUseFunc &Func, LoopInfo &LI, 1978e8d8bef9SDimitry Andric BranchProbabilityInfo &NBPI, 1979e8d8bef9SDimitry Andric uint64_t HotCountThreshold, 1980e8d8bef9SDimitry Andric uint64_t ColdCountThreshold) { 1981e8d8bef9SDimitry Andric Function &F = Func.getFunc(); 1982e8d8bef9SDimitry Andric BlockFrequencyInfo NBFI(F, NBPI, LI); 1983e8d8bef9SDimitry Andric // bool PrintFunc = false; 1984e8d8bef9SDimitry Andric bool HotBBOnly = PGOVerifyHotBFI; 198506c3fb27SDimitry Andric StringRef Msg; 1986e8d8bef9SDimitry Andric OptimizationRemarkEmitter ORE(&F); 1987e8d8bef9SDimitry Andric 1988e8d8bef9SDimitry Andric unsigned BBNum = 0, BBMisMatchNum = 0, NonZeroBBNum = 0; 1989e8d8bef9SDimitry Andric for (auto &BBI : F) { 1990e8d8bef9SDimitry Andric uint64_t CountValue = 0; 1991e8d8bef9SDimitry Andric uint64_t BFICountValue = 0; 1992e8d8bef9SDimitry Andric 19930fca6ea1SDimitry Andric CountValue = Func.getBBInfo(&BBI).Count.value_or(CountValue); 1994e8d8bef9SDimitry Andric 1995e8d8bef9SDimitry Andric BBNum++; 1996e8d8bef9SDimitry Andric if (CountValue) 1997e8d8bef9SDimitry Andric NonZeroBBNum++; 1998e8d8bef9SDimitry Andric auto BFICount = NBFI.getBlockProfileCount(&BBI); 1999e8d8bef9SDimitry Andric if (BFICount) 200081ad6265SDimitry Andric BFICountValue = *BFICount; 2001e8d8bef9SDimitry Andric 2002e8d8bef9SDimitry Andric if (HotBBOnly) { 2003e8d8bef9SDimitry Andric bool rawIsHot = CountValue >= HotCountThreshold; 2004e8d8bef9SDimitry Andric bool BFIIsHot = BFICountValue >= HotCountThreshold; 2005e8d8bef9SDimitry Andric bool rawIsCold = CountValue <= ColdCountThreshold; 2006e8d8bef9SDimitry Andric bool ShowCount = false; 2007e8d8bef9SDimitry Andric if (rawIsHot && !BFIIsHot) { 2008e8d8bef9SDimitry Andric Msg = "raw-Hot to BFI-nonHot"; 2009e8d8bef9SDimitry Andric ShowCount = true; 2010e8d8bef9SDimitry Andric } else if (rawIsCold && BFIIsHot) { 2011e8d8bef9SDimitry Andric Msg = "raw-Cold to BFI-Hot"; 2012e8d8bef9SDimitry Andric ShowCount = true; 2013e8d8bef9SDimitry Andric } 2014e8d8bef9SDimitry Andric if (!ShowCount) 2015e8d8bef9SDimitry Andric continue; 2016e8d8bef9SDimitry Andric } else { 2017e8d8bef9SDimitry Andric if ((CountValue < PGOVerifyBFICutoff) && 2018e8d8bef9SDimitry Andric (BFICountValue < PGOVerifyBFICutoff)) 2019e8d8bef9SDimitry Andric continue; 2020e8d8bef9SDimitry Andric uint64_t Diff = (BFICountValue >= CountValue) 2021e8d8bef9SDimitry Andric ? BFICountValue - CountValue 2022e8d8bef9SDimitry Andric : CountValue - BFICountValue; 20230eae32dcSDimitry Andric if (Diff <= CountValue / 100 * PGOVerifyBFIRatio) 2024e8d8bef9SDimitry Andric continue; 2025e8d8bef9SDimitry Andric } 2026e8d8bef9SDimitry Andric BBMisMatchNum++; 2027e8d8bef9SDimitry Andric 2028e8d8bef9SDimitry Andric ORE.emit([&]() { 2029e8d8bef9SDimitry Andric OptimizationRemarkAnalysis Remark(DEBUG_TYPE, "bfi-verify", 2030e8d8bef9SDimitry Andric F.getSubprogram(), &BBI); 2031e8d8bef9SDimitry Andric Remark << "BB " << ore::NV("Block", BBI.getName()) 2032e8d8bef9SDimitry Andric << " Count=" << ore::NV("Count", CountValue) 2033e8d8bef9SDimitry Andric << " BFI_Count=" << ore::NV("Count", BFICountValue); 2034e8d8bef9SDimitry Andric if (!Msg.empty()) 2035e8d8bef9SDimitry Andric Remark << " (" << Msg << ")"; 2036e8d8bef9SDimitry Andric return Remark; 2037e8d8bef9SDimitry Andric }); 2038e8d8bef9SDimitry Andric } 2039e8d8bef9SDimitry Andric if (BBMisMatchNum) 2040e8d8bef9SDimitry Andric ORE.emit([&]() { 2041e8d8bef9SDimitry Andric return OptimizationRemarkAnalysis(DEBUG_TYPE, "bfi-verify", 2042e8d8bef9SDimitry Andric F.getSubprogram(), &F.getEntryBlock()) 2043e8d8bef9SDimitry Andric << "In Func " << ore::NV("Function", F.getName()) 2044e8d8bef9SDimitry Andric << ": Num_of_BB=" << ore::NV("Count", BBNum) 2045e8d8bef9SDimitry Andric << ", Num_of_non_zerovalue_BB=" << ore::NV("Count", NonZeroBBNum) 2046e8d8bef9SDimitry Andric << ", Num_of_mis_matching_BB=" << ore::NV("Count", BBMisMatchNum); 2047e8d8bef9SDimitry Andric }); 2048e8d8bef9SDimitry Andric } 2049e8d8bef9SDimitry Andric 20500b57cec5SDimitry Andric static bool annotateAllFunctions( 20510b57cec5SDimitry Andric Module &M, StringRef ProfileFileName, StringRef ProfileRemappingFileName, 205206c3fb27SDimitry Andric vfs::FileSystem &FS, 20535ffd83dbSDimitry Andric function_ref<TargetLibraryInfo &(Function &)> LookupTLI, 20540b57cec5SDimitry Andric function_ref<BranchProbabilityInfo *(Function &)> LookupBPI, 20558bcb0991SDimitry Andric function_ref<BlockFrequencyInfo *(Function &)> LookupBFI, 20568bcb0991SDimitry Andric ProfileSummaryInfo *PSI, bool IsCS) { 20570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Read in profile counters: "); 20580b57cec5SDimitry Andric auto &Ctx = M.getContext(); 20590b57cec5SDimitry Andric // Read the counter array from file. 206006c3fb27SDimitry Andric auto ReaderOrErr = IndexedInstrProfReader::create(ProfileFileName, FS, 206106c3fb27SDimitry Andric ProfileRemappingFileName); 20620b57cec5SDimitry Andric if (Error E = ReaderOrErr.takeError()) { 20630b57cec5SDimitry Andric handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) { 20640b57cec5SDimitry Andric Ctx.diagnose( 20650b57cec5SDimitry Andric DiagnosticInfoPGOProfile(ProfileFileName.data(), EI.message())); 20660b57cec5SDimitry Andric }); 20670b57cec5SDimitry Andric return false; 20680b57cec5SDimitry Andric } 20690b57cec5SDimitry Andric 20700b57cec5SDimitry Andric std::unique_ptr<IndexedInstrProfReader> PGOReader = 20710b57cec5SDimitry Andric std::move(ReaderOrErr.get()); 20720b57cec5SDimitry Andric if (!PGOReader) { 20730b57cec5SDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile(ProfileFileName.data(), 20740b57cec5SDimitry Andric StringRef("Cannot get PGOReader"))); 20750b57cec5SDimitry Andric return false; 20760b57cec5SDimitry Andric } 20770b57cec5SDimitry Andric if (!PGOReader->hasCSIRLevelProfile() && IsCS) 20780b57cec5SDimitry Andric return false; 20790b57cec5SDimitry Andric 20800b57cec5SDimitry Andric // TODO: might need to change the warning once the clang option is finalized. 208106c3fb27SDimitry Andric if (!PGOReader->isIRLevelProfile()) { 20820b57cec5SDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile( 20830b57cec5SDimitry Andric ProfileFileName.data(), "Not an IR level instrumentation profile")); 20840b57cec5SDimitry Andric return false; 20850b57cec5SDimitry Andric } 20861fd87a68SDimitry Andric if (PGOReader->functionEntryOnly()) { 20871fd87a68SDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile( 20881fd87a68SDimitry Andric ProfileFileName.data(), 20891fd87a68SDimitry Andric "Function entry profiles are not yet supported for optimization")); 20901fd87a68SDimitry Andric return false; 20911fd87a68SDimitry Andric } 20920b57cec5SDimitry Andric 20930fca6ea1SDimitry Andric if (EnableVTableProfileUse) { 20940fca6ea1SDimitry Andric for (GlobalVariable &G : M.globals()) { 20950fca6ea1SDimitry Andric if (!G.hasName() || !G.hasMetadata(LLVMContext::MD_type)) 20960fca6ea1SDimitry Andric continue; 20970fca6ea1SDimitry Andric 20980fca6ea1SDimitry Andric // Create the PGOFuncName meta data. 20990fca6ea1SDimitry Andric createPGONameMetadata(G, getPGOName(G, false /* InLTO*/)); 21000fca6ea1SDimitry Andric } 21010fca6ea1SDimitry Andric } 21020fca6ea1SDimitry Andric 21038bcb0991SDimitry Andric // Add the profile summary (read from the header of the indexed summary) here 21048bcb0991SDimitry Andric // so that we can use it below when reading counters (which checks if the 21058bcb0991SDimitry Andric // function should be marked with a cold or inlinehint attribute). 21068bcb0991SDimitry Andric M.setProfileSummary(PGOReader->getSummary(IsCS).getMD(M.getContext()), 21078bcb0991SDimitry Andric IsCS ? ProfileSummary::PSK_CSInstr 21088bcb0991SDimitry Andric : ProfileSummary::PSK_Instr); 21095ffd83dbSDimitry Andric PSI->refresh(); 21108bcb0991SDimitry Andric 21110b57cec5SDimitry Andric std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers; 21120b57cec5SDimitry Andric collectComdatMembers(M, ComdatMembers); 21130b57cec5SDimitry Andric std::vector<Function *> HotFunctions; 21140b57cec5SDimitry Andric std::vector<Function *> ColdFunctions; 2115e8d8bef9SDimitry Andric 2116e8d8bef9SDimitry Andric // If the profile marked as always instrument the entry BB, do the 2117e8d8bef9SDimitry Andric // same. Note this can be overwritten by the internal option in CFGMST.h 2118e8d8bef9SDimitry Andric bool InstrumentFuncEntry = PGOReader->instrEntryBBEnabled(); 2119e8d8bef9SDimitry Andric if (PGOInstrumentEntry.getNumOccurrences() > 0) 2120e8d8bef9SDimitry Andric InstrumentFuncEntry = PGOInstrumentEntry; 21210fca6ea1SDimitry Andric InstrumentFuncEntry |= PGOCtxProfLoweringPass::isContextualIRPGOEnabled(); 21220fca6ea1SDimitry Andric 212306c3fb27SDimitry Andric bool HasSingleByteCoverage = PGOReader->hasSingleByteCoverage(); 21240b57cec5SDimitry Andric for (auto &F : M) { 21255f757f3fSDimitry Andric if (skipPGOUse(F)) 21260b57cec5SDimitry Andric continue; 21275ffd83dbSDimitry Andric auto &TLI = LookupTLI(F); 21280b57cec5SDimitry Andric auto *BPI = LookupBPI(F); 21290b57cec5SDimitry Andric auto *BFI = LookupBFI(F); 213006c3fb27SDimitry Andric if (!HasSingleByteCoverage) { 213106c3fb27SDimitry Andric // Split indirectbr critical edges here before computing the MST rather 213206c3fb27SDimitry Andric // than later in getInstrBB() to avoid invalidating it. 213306c3fb27SDimitry Andric SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI, 213406c3fb27SDimitry Andric BFI); 213506c3fb27SDimitry Andric } 2136e8d8bef9SDimitry Andric PGOUseFunc Func(F, &M, TLI, ComdatMembers, BPI, BFI, PSI, IsCS, 213706c3fb27SDimitry Andric InstrumentFuncEntry, HasSingleByteCoverage); 213806c3fb27SDimitry Andric if (HasSingleByteCoverage) { 213906c3fb27SDimitry Andric Func.populateCoverage(PGOReader.get()); 2140bdd1243dSDimitry Andric continue; 214106c3fb27SDimitry Andric } 2142bdd1243dSDimitry Andric // When PseudoKind is set to a vaule other than InstrProfRecord::NotPseudo, 2143bdd1243dSDimitry Andric // it means the profile for the function is unrepresentative and this 2144bdd1243dSDimitry Andric // function is actually hot / warm. We will reset the function hot / cold 2145bdd1243dSDimitry Andric // attribute and drop all the profile counters. 2146bdd1243dSDimitry Andric InstrProfRecord::CountPseudoKind PseudoKind = InstrProfRecord::NotPseudo; 21470b57cec5SDimitry Andric bool AllZeros = false; 2148bdd1243dSDimitry Andric if (!Func.readCounters(PGOReader.get(), AllZeros, PseudoKind)) 21490b57cec5SDimitry Andric continue; 21500b57cec5SDimitry Andric if (AllZeros) { 21510b57cec5SDimitry Andric F.setEntryCount(ProfileCount(0, Function::PCT_Real)); 21520b57cec5SDimitry Andric if (Func.getProgramMaxCount() != 0) 21530b57cec5SDimitry Andric ColdFunctions.push_back(&F); 21540b57cec5SDimitry Andric continue; 21550b57cec5SDimitry Andric } 2156bdd1243dSDimitry Andric if (PseudoKind != InstrProfRecord::NotPseudo) { 2157bdd1243dSDimitry Andric // Clear function attribute cold. 2158bdd1243dSDimitry Andric if (F.hasFnAttribute(Attribute::Cold)) 2159bdd1243dSDimitry Andric F.removeFnAttr(Attribute::Cold); 2160bdd1243dSDimitry Andric // Set function attribute as hot. 2161bdd1243dSDimitry Andric if (PseudoKind == InstrProfRecord::PseudoHot) 2162bdd1243dSDimitry Andric F.addFnAttr(Attribute::Hot); 2163e8d8bef9SDimitry Andric continue; 2164e8d8bef9SDimitry Andric } 21650b57cec5SDimitry Andric Func.populateCounters(); 21660b57cec5SDimitry Andric Func.setBranchWeights(); 21670b57cec5SDimitry Andric Func.annotateValueSites(); 21680b57cec5SDimitry Andric Func.annotateIrrLoopHeaderWeights(); 21690b57cec5SDimitry Andric PGOUseFunc::FuncFreqAttr FreqAttr = Func.getFuncFreqAttr(); 21700b57cec5SDimitry Andric if (FreqAttr == PGOUseFunc::FFA_Cold) 21710b57cec5SDimitry Andric ColdFunctions.push_back(&F); 21720b57cec5SDimitry Andric else if (FreqAttr == PGOUseFunc::FFA_Hot) 21730b57cec5SDimitry Andric HotFunctions.push_back(&F); 21740b57cec5SDimitry Andric if (PGOViewCounts != PGOVCT_None && 21750b57cec5SDimitry Andric (ViewBlockFreqFuncName.empty() || 21760fca6ea1SDimitry Andric F.getName() == ViewBlockFreqFuncName)) { 21770b57cec5SDimitry Andric LoopInfo LI{DominatorTree(F)}; 21780b57cec5SDimitry Andric std::unique_ptr<BranchProbabilityInfo> NewBPI = 21798bcb0991SDimitry Andric std::make_unique<BranchProbabilityInfo>(F, LI); 21800b57cec5SDimitry Andric std::unique_ptr<BlockFrequencyInfo> NewBFI = 21818bcb0991SDimitry Andric std::make_unique<BlockFrequencyInfo>(F, *NewBPI, LI); 21820b57cec5SDimitry Andric if (PGOViewCounts == PGOVCT_Graph) 21830b57cec5SDimitry Andric NewBFI->view(); 21840b57cec5SDimitry Andric else if (PGOViewCounts == PGOVCT_Text) { 21850b57cec5SDimitry Andric dbgs() << "pgo-view-counts: " << Func.getFunc().getName() << "\n"; 21860b57cec5SDimitry Andric NewBFI->print(dbgs()); 21870b57cec5SDimitry Andric } 21880b57cec5SDimitry Andric } 21890b57cec5SDimitry Andric if (PGOViewRawCounts != PGOVCT_None && 21900b57cec5SDimitry Andric (ViewBlockFreqFuncName.empty() || 21910fca6ea1SDimitry Andric F.getName() == ViewBlockFreqFuncName)) { 21920b57cec5SDimitry Andric if (PGOViewRawCounts == PGOVCT_Graph) 21930b57cec5SDimitry Andric if (ViewBlockFreqFuncName.empty()) 21940b57cec5SDimitry Andric WriteGraph(&Func, Twine("PGORawCounts_") + Func.getFunc().getName()); 21950b57cec5SDimitry Andric else 21960b57cec5SDimitry Andric ViewGraph(&Func, Twine("PGORawCounts_") + Func.getFunc().getName()); 21970b57cec5SDimitry Andric else if (PGOViewRawCounts == PGOVCT_Text) { 21980b57cec5SDimitry Andric dbgs() << "pgo-view-raw-counts: " << Func.getFunc().getName() << "\n"; 21990b57cec5SDimitry Andric Func.dumpInfo(); 22000b57cec5SDimitry Andric } 22010b57cec5SDimitry Andric } 2202e8d8bef9SDimitry Andric 2203e8d8bef9SDimitry Andric if (PGOVerifyBFI || PGOVerifyHotBFI || PGOFixEntryCount) { 2204e8d8bef9SDimitry Andric LoopInfo LI{DominatorTree(F)}; 2205e8d8bef9SDimitry Andric BranchProbabilityInfo NBPI(F, LI); 2206e8d8bef9SDimitry Andric 2207e8d8bef9SDimitry Andric // Fix func entry count. 2208e8d8bef9SDimitry Andric if (PGOFixEntryCount) 2209e8d8bef9SDimitry Andric fixFuncEntryCount(Func, LI, NBPI); 2210e8d8bef9SDimitry Andric 2211e8d8bef9SDimitry Andric // Verify BlockFrequency information. 2212e8d8bef9SDimitry Andric uint64_t HotCountThreshold = 0, ColdCountThreshold = 0; 2213e8d8bef9SDimitry Andric if (PGOVerifyHotBFI) { 2214e8d8bef9SDimitry Andric HotCountThreshold = PSI->getOrCompHotCountThreshold(); 2215e8d8bef9SDimitry Andric ColdCountThreshold = PSI->getOrCompColdCountThreshold(); 2216e8d8bef9SDimitry Andric } 2217e8d8bef9SDimitry Andric verifyFuncBFI(Func, LI, NBPI, HotCountThreshold, ColdCountThreshold); 2218e8d8bef9SDimitry Andric } 22190b57cec5SDimitry Andric } 22200b57cec5SDimitry Andric 22210b57cec5SDimitry Andric // Set function hotness attribute from the profile. 22220b57cec5SDimitry Andric // We have to apply these attributes at the end because their presence 22230b57cec5SDimitry Andric // can affect the BranchProbabilityInfo of any callers, resulting in an 22240b57cec5SDimitry Andric // inconsistent MST between prof-gen and prof-use. 22250b57cec5SDimitry Andric for (auto &F : HotFunctions) { 22260b57cec5SDimitry Andric F->addFnAttr(Attribute::InlineHint); 22270b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Set inline attribute to function: " << F->getName() 22280b57cec5SDimitry Andric << "\n"); 22290b57cec5SDimitry Andric } 22300b57cec5SDimitry Andric for (auto &F : ColdFunctions) { 2231e8d8bef9SDimitry Andric // Only set when there is no Attribute::Hot set by the user. For Hot 2232e8d8bef9SDimitry Andric // attribute, user's annotation has the precedence over the profile. 2233e8d8bef9SDimitry Andric if (F->hasFnAttribute(Attribute::Hot)) { 2234e8d8bef9SDimitry Andric auto &Ctx = M.getContext(); 2235e8d8bef9SDimitry Andric std::string Msg = std::string("Function ") + F->getName().str() + 2236e8d8bef9SDimitry Andric std::string(" is annotated as a hot function but" 2237e8d8bef9SDimitry Andric " the profile is cold"); 2238e8d8bef9SDimitry Andric Ctx.diagnose( 2239e8d8bef9SDimitry Andric DiagnosticInfoPGOProfile(M.getName().data(), Msg, DS_Warning)); 2240e8d8bef9SDimitry Andric continue; 2241e8d8bef9SDimitry Andric } 22420b57cec5SDimitry Andric F->addFnAttr(Attribute::Cold); 22430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Set cold attribute to function: " << F->getName() 22440b57cec5SDimitry Andric << "\n"); 22450b57cec5SDimitry Andric } 22460b57cec5SDimitry Andric return true; 22470b57cec5SDimitry Andric } 22480b57cec5SDimitry Andric 224906c3fb27SDimitry Andric PGOInstrumentationUse::PGOInstrumentationUse( 225006c3fb27SDimitry Andric std::string Filename, std::string RemappingFilename, bool IsCS, 225106c3fb27SDimitry Andric IntrusiveRefCntPtr<vfs::FileSystem> VFS) 22520b57cec5SDimitry Andric : ProfileFileName(std::move(Filename)), 225306c3fb27SDimitry Andric ProfileRemappingFileName(std::move(RemappingFilename)), IsCS(IsCS), 225406c3fb27SDimitry Andric FS(std::move(VFS)) { 22550b57cec5SDimitry Andric if (!PGOTestProfileFile.empty()) 22560b57cec5SDimitry Andric ProfileFileName = PGOTestProfileFile; 22570b57cec5SDimitry Andric if (!PGOTestProfileRemappingFile.empty()) 22580b57cec5SDimitry Andric ProfileRemappingFileName = PGOTestProfileRemappingFile; 225906c3fb27SDimitry Andric if (!FS) 226006c3fb27SDimitry Andric FS = vfs::getRealFileSystem(); 22610b57cec5SDimitry Andric } 22620b57cec5SDimitry Andric 22630b57cec5SDimitry Andric PreservedAnalyses PGOInstrumentationUse::run(Module &M, 226406c3fb27SDimitry Andric ModuleAnalysisManager &MAM) { 22650b57cec5SDimitry Andric 226606c3fb27SDimitry Andric auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 22675ffd83dbSDimitry Andric auto LookupTLI = [&FAM](Function &F) -> TargetLibraryInfo & { 22685ffd83dbSDimitry Andric return FAM.getResult<TargetLibraryAnalysis>(F); 22695ffd83dbSDimitry Andric }; 22700b57cec5SDimitry Andric auto LookupBPI = [&FAM](Function &F) { 22710b57cec5SDimitry Andric return &FAM.getResult<BranchProbabilityAnalysis>(F); 22720b57cec5SDimitry Andric }; 22730b57cec5SDimitry Andric auto LookupBFI = [&FAM](Function &F) { 22740b57cec5SDimitry Andric return &FAM.getResult<BlockFrequencyAnalysis>(F); 22750b57cec5SDimitry Andric }; 22760b57cec5SDimitry Andric 227706c3fb27SDimitry Andric auto *PSI = &MAM.getResult<ProfileSummaryAnalysis>(M); 227806c3fb27SDimitry Andric if (!annotateAllFunctions(M, ProfileFileName, ProfileRemappingFileName, *FS, 22795ffd83dbSDimitry Andric LookupTLI, LookupBPI, LookupBFI, PSI, IsCS)) 22800b57cec5SDimitry Andric return PreservedAnalyses::all(); 22810b57cec5SDimitry Andric 22820b57cec5SDimitry Andric return PreservedAnalyses::none(); 22830b57cec5SDimitry Andric } 22840b57cec5SDimitry Andric 22850b57cec5SDimitry Andric static std::string getSimpleNodeName(const BasicBlock *Node) { 22860b57cec5SDimitry Andric if (!Node->getName().empty()) 228706c3fb27SDimitry Andric return Node->getName().str(); 22880b57cec5SDimitry Andric 22890b57cec5SDimitry Andric std::string SimpleNodeName; 22900b57cec5SDimitry Andric raw_string_ostream OS(SimpleNodeName); 22910b57cec5SDimitry Andric Node->printAsOperand(OS, false); 22920fca6ea1SDimitry Andric return SimpleNodeName; 22930b57cec5SDimitry Andric } 22940b57cec5SDimitry Andric 22950b57cec5SDimitry Andric void llvm::setProfMetadata(Module *M, Instruction *TI, 229606c3fb27SDimitry Andric ArrayRef<uint64_t> EdgeCounts, uint64_t MaxCount) { 22970b57cec5SDimitry Andric assert(MaxCount > 0 && "Bad max count"); 22980b57cec5SDimitry Andric uint64_t Scale = calculateCountScale(MaxCount); 22990b57cec5SDimitry Andric SmallVector<unsigned, 4> Weights; 23000b57cec5SDimitry Andric for (const auto &ECI : EdgeCounts) 23010b57cec5SDimitry Andric Weights.push_back(scaleBranchCount(ECI, Scale)); 23020b57cec5SDimitry Andric 23030b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Weight is: "; for (const auto &W 23040b57cec5SDimitry Andric : Weights) { 23050b57cec5SDimitry Andric dbgs() << W << " "; 23060b57cec5SDimitry Andric } dbgs() << "\n";); 23078bcb0991SDimitry Andric 230881ad6265SDimitry Andric misexpect::checkExpectAnnotations(*TI, Weights, /*IsFrontend=*/false); 230981ad6265SDimitry Andric 23100fca6ea1SDimitry Andric setBranchWeights(*TI, Weights, /*IsExpected=*/false); 23110b57cec5SDimitry Andric if (EmitBranchProbability) { 23120b57cec5SDimitry Andric std::string BrCondStr = getBranchCondString(TI); 23130b57cec5SDimitry Andric if (BrCondStr.empty()) 23140b57cec5SDimitry Andric return; 23150b57cec5SDimitry Andric 23160b57cec5SDimitry Andric uint64_t WSum = 23170b57cec5SDimitry Andric std::accumulate(Weights.begin(), Weights.end(), (uint64_t)0, 23180b57cec5SDimitry Andric [](uint64_t w1, uint64_t w2) { return w1 + w2; }); 23190b57cec5SDimitry Andric uint64_t TotalCount = 23200b57cec5SDimitry Andric std::accumulate(EdgeCounts.begin(), EdgeCounts.end(), (uint64_t)0, 23210b57cec5SDimitry Andric [](uint64_t c1, uint64_t c2) { return c1 + c2; }); 23220b57cec5SDimitry Andric Scale = calculateCountScale(WSum); 23230b57cec5SDimitry Andric BranchProbability BP(scaleBranchCount(Weights[0], Scale), 23240b57cec5SDimitry Andric scaleBranchCount(WSum, Scale)); 23250b57cec5SDimitry Andric std::string BranchProbStr; 23260b57cec5SDimitry Andric raw_string_ostream OS(BranchProbStr); 23270b57cec5SDimitry Andric OS << BP; 23280b57cec5SDimitry Andric OS << " (total count : " << TotalCount << ")"; 23290b57cec5SDimitry Andric OS.flush(); 23300b57cec5SDimitry Andric Function *F = TI->getParent()->getParent(); 23310b57cec5SDimitry Andric OptimizationRemarkEmitter ORE(F); 23320b57cec5SDimitry Andric ORE.emit([&]() { 23330b57cec5SDimitry Andric return OptimizationRemark(DEBUG_TYPE, "pgo-instrumentation", TI) 23340b57cec5SDimitry Andric << BrCondStr << " is true with probability : " << BranchProbStr; 23350b57cec5SDimitry Andric }); 23360b57cec5SDimitry Andric } 23370b57cec5SDimitry Andric } 23380b57cec5SDimitry Andric 23390b57cec5SDimitry Andric namespace llvm { 23400b57cec5SDimitry Andric 23410b57cec5SDimitry Andric void setIrrLoopHeaderMetadata(Module *M, Instruction *TI, uint64_t Count) { 23420b57cec5SDimitry Andric MDBuilder MDB(M->getContext()); 23430b57cec5SDimitry Andric TI->setMetadata(llvm::LLVMContext::MD_irr_loop, 23440b57cec5SDimitry Andric MDB.createIrrLoopHeaderWeight(Count)); 23450b57cec5SDimitry Andric } 23460b57cec5SDimitry Andric 23470b57cec5SDimitry Andric template <> struct GraphTraits<PGOUseFunc *> { 23480b57cec5SDimitry Andric using NodeRef = const BasicBlock *; 23495ffd83dbSDimitry Andric using ChildIteratorType = const_succ_iterator; 23500b57cec5SDimitry Andric using nodes_iterator = pointer_iterator<Function::const_iterator>; 23510b57cec5SDimitry Andric 23520b57cec5SDimitry Andric static NodeRef getEntryNode(const PGOUseFunc *G) { 23530b57cec5SDimitry Andric return &G->getFunc().front(); 23540b57cec5SDimitry Andric } 23550b57cec5SDimitry Andric 23560b57cec5SDimitry Andric static ChildIteratorType child_begin(const NodeRef N) { 23570b57cec5SDimitry Andric return succ_begin(N); 23580b57cec5SDimitry Andric } 23590b57cec5SDimitry Andric 23600b57cec5SDimitry Andric static ChildIteratorType child_end(const NodeRef N) { return succ_end(N); } 23610b57cec5SDimitry Andric 23620b57cec5SDimitry Andric static nodes_iterator nodes_begin(const PGOUseFunc *G) { 23630b57cec5SDimitry Andric return nodes_iterator(G->getFunc().begin()); 23640b57cec5SDimitry Andric } 23650b57cec5SDimitry Andric 23660b57cec5SDimitry Andric static nodes_iterator nodes_end(const PGOUseFunc *G) { 23670b57cec5SDimitry Andric return nodes_iterator(G->getFunc().end()); 23680b57cec5SDimitry Andric } 23690b57cec5SDimitry Andric }; 23700b57cec5SDimitry Andric 23710b57cec5SDimitry Andric template <> struct DOTGraphTraits<PGOUseFunc *> : DefaultDOTGraphTraits { 23720b57cec5SDimitry Andric explicit DOTGraphTraits(bool isSimple = false) 23730b57cec5SDimitry Andric : DefaultDOTGraphTraits(isSimple) {} 23740b57cec5SDimitry Andric 23750b57cec5SDimitry Andric static std::string getGraphName(const PGOUseFunc *G) { 23765ffd83dbSDimitry Andric return std::string(G->getFunc().getName()); 23770b57cec5SDimitry Andric } 23780b57cec5SDimitry Andric 23790b57cec5SDimitry Andric std::string getNodeLabel(const BasicBlock *Node, const PGOUseFunc *Graph) { 23800b57cec5SDimitry Andric std::string Result; 23810b57cec5SDimitry Andric raw_string_ostream OS(Result); 23820b57cec5SDimitry Andric 23830b57cec5SDimitry Andric OS << getSimpleNodeName(Node) << ":\\l"; 238406c3fb27SDimitry Andric PGOUseBBInfo *BI = Graph->findBBInfo(Node); 23850b57cec5SDimitry Andric OS << "Count : "; 23860fca6ea1SDimitry Andric if (BI && BI->Count) 23870fca6ea1SDimitry Andric OS << *BI->Count << "\\l"; 23880b57cec5SDimitry Andric else 23890b57cec5SDimitry Andric OS << "Unknown\\l"; 23900b57cec5SDimitry Andric 23910b57cec5SDimitry Andric if (!PGOInstrSelect) 23920b57cec5SDimitry Andric return Result; 23930b57cec5SDimitry Andric 2394fe6060f1SDimitry Andric for (const Instruction &I : *Node) { 2395fe6060f1SDimitry Andric if (!isa<SelectInst>(&I)) 23960b57cec5SDimitry Andric continue; 23970b57cec5SDimitry Andric // Display scaled counts for SELECT instruction: 23980b57cec5SDimitry Andric OS << "SELECT : { T = "; 23990b57cec5SDimitry Andric uint64_t TC, FC; 2400bdd1243dSDimitry Andric bool HasProf = extractBranchWeights(I, TC, FC); 24010b57cec5SDimitry Andric if (!HasProf) 24020b57cec5SDimitry Andric OS << "Unknown, F = Unknown }\\l"; 24030b57cec5SDimitry Andric else 24040b57cec5SDimitry Andric OS << TC << ", F = " << FC << " }\\l"; 24050b57cec5SDimitry Andric } 24060b57cec5SDimitry Andric return Result; 24070b57cec5SDimitry Andric } 24080b57cec5SDimitry Andric }; 24090b57cec5SDimitry Andric 24100b57cec5SDimitry Andric } // end namespace llvm 2411