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
shouldInstrumentEntryBB()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.
isValueProfilingDisabled()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:
getBranchCondString(Instruction * TI)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.
createIRLevelProfileFlagVar(Module & M,bool IsCS)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
SelectInstVisitor__anon0925556b0111::SelectInstVisitor44606c3fb27SDimitry Andric SelectInstVisitor(Function &Func, bool HasSingleByteCoverage)
44706c3fb27SDimitry Andric : F(Func), HasSingleByteCoverage(HasSingleByteCoverage) {}
4480b57cec5SDimitry Andric
countSelects__anon0925556b0111::SelectInstVisitor44906c3fb27SDimitry 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.
instrumentSelects__anon0925556b0111::SelectInstVisitor45906c3fb27SDimitry 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.
annotateSelects__anon0925556b0111::SelectInstVisitor47006c3fb27SDimitry 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().
getNumOfSelectInsts__anon0925556b0111::SelectInstVisitor4850b57cec5SDimitry 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
PGOEdge__anon0925556b0111::PGOEdge50006c3fb27SDimitry 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.
infoString__anon0925556b0111::PGOEdge504fe6060f1SDimitry 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
PGOBBInfo__anon0925556b0111::PGOBBInfo51706c3fb27SDimitry Andric PGOBBInfo(unsigned IX) : Group(this), Index(IX) {}
5180b57cec5SDimitry Andric
51906c3fb27SDimitry Andric /// Return the information string of this object.
infoString__anon0925556b0111::PGOBBInfo520fe6060f1SDimitry 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>
constructBCI(Function & Func,bool HasSingleByteCoverage,bool InstrumentFuncEntry)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.
getBBInfo(const BasicBlock * BB) const5740b57cec5SDimitry Andric BBInfo &getBBInfo(const BasicBlock *BB) const { return MST.getBBInfo(BB); }
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andric // Return the auxiliary BB information if available.
findBBInfo(const BasicBlock * BB) const5770b57cec5SDimitry Andric BBInfo *findBBInfo(const BasicBlock *BB) const { return MST.findBBInfo(BB); }
5780b57cec5SDimitry Andric
5790b57cec5SDimitry Andric // Dump edges and BB information.
dumpInfo(StringRef Str="") const58006c3fb27SDimitry 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
FuncPGOInstrumentation(Function & Func,TargetLibraryInfo & TLI,std::unordered_multimap<Comdat *,GlobalValue * > & ComdatMembers,bool CreateGlobalVar=false,BranchProbabilityInfo * BPI=nullptr,BlockFrequencyInfo * BFI=nullptr,bool IsCS=false,bool InstrumentFuncEntry=true,bool HasSingleByteCoverage=false)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>
computeCFGHash()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.
canRenameComdat(Function & F,std::unordered_multimap<Comdat *,GlobalValue * > & ComdatMembers)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>
renameComdatFunction()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>
getInstrumentBBs(std::vector<BasicBlock * > & InstrumentBBs)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>
getInstrBB(Edge * E)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
populateEHOperandBundle(VPCandidateInfo & Cand,DenseMap<BasicBlock *,ColorVector> & BlockColors,SmallVectorImpl<OperandBundleDef> & OpBundles)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.
instrumentOneFunc(Function & F,Module * M,TargetLibraryInfo & TLI,BranchProbabilityInfo * BPI,BlockFrequencyInfo * BFI,std::unordered_multimap<Comdat *,GlobalValue * > & ComdatMembers,bool IsCS)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
setEdgeCount__anon0925556b0711::PGOUseEdge10280fca6ea1SDimitry Andric void setEdgeCount(uint64_t Value) { Count = Value; }
10290b57cec5SDimitry Andric
10300b57cec5SDimitry Andric // Return the information string for this object.
infoString__anon0925556b0711::PGOUseEdge1031fe6060f1SDimitry 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
PGOUseBBInfo__anon0925556b0711::PGOUseBBInfo10480fca6ea1SDimitry Andric PGOUseBBInfo(unsigned IX) : PGOBBInfo(IX) {}
10490b57cec5SDimitry Andric
10500b57cec5SDimitry Andric // Set the profile count value for this BB.
setBBInfoCount__anon0925556b0711::PGOUseBBInfo10510fca6ea1SDimitry Andric void setBBInfoCount(uint64_t Value) { Count = Value; }
10520b57cec5SDimitry Andric
10530b57cec5SDimitry Andric // Return the information string of this object.
infoString__anon0925556b0711::PGOUseBBInfo1054fe6060f1SDimitry 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.
addOutEdge__anon0925556b0711::PGOUseBBInfo10610b57cec5SDimitry 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.
addInEdge__anon0925556b0711::PGOUseBBInfo10670b57cec5SDimitry 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.
sumEdgeCount(const ArrayRef<PGOUseEdge * > 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:
PGOUseFunc(Function & Func,Module * Modu,TargetLibraryInfo & TLI,std::unordered_multimap<Comdat *,GlobalValue * > & ComdatMembers,BranchProbabilityInfo * BPI,BlockFrequencyInfo * BFIin,ProfileSummaryInfo * PSI,bool IsCS,bool InstrumentFuncEntry,bool HasSingleByteCoverage)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.
getFuncFreqAttr() const11290b57cec5SDimitry Andric FuncFreqAttr getFuncFreqAttr() const { return FreqAttr; }
11300b57cec5SDimitry Andric
11310b57cec5SDimitry Andric // Return the function hash.
getFuncHash() const11320b57cec5SDimitry Andric uint64_t getFuncHash() const { return FuncInfo.FunctionHash; }
11330b57cec5SDimitry Andric
11340b57cec5SDimitry Andric // Return the profile record for this function;
getProfileRecord()11350b57cec5SDimitry Andric InstrProfRecord &getProfileRecord() { return ProfileRecord; }
11360b57cec5SDimitry Andric
11370b57cec5SDimitry Andric // Return the auxiliary BB information.
getBBInfo(const BasicBlock * BB) const113806c3fb27SDimitry 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.
findBBInfo(const BasicBlock * BB) const114306c3fb27SDimitry Andric PGOUseBBInfo *findBBInfo(const BasicBlock *BB) const {
11440b57cec5SDimitry Andric return FuncInfo.findBBInfo(BB);
11450b57cec5SDimitry Andric }
11460b57cec5SDimitry Andric
getFunc() const11470b57cec5SDimitry Andric Function &getFunc() const { return F; }
11480b57cec5SDimitry Andric
dumpInfo(StringRef Str="") const114906c3fb27SDimitry Andric void dumpInfo(StringRef Str = "") const { FuncInfo.dumpInfo(Str); }
11500b57cec5SDimitry Andric
getProgramMaxCount() const11510b57cec5SDimitry 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.
markFunctionAttributes(uint64_t EntryCount,uint64_t MaxCount)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.
setupBBInfoEdges(const FuncPGOInstrumentation<PGOUseEdge,PGOUseBBInfo> & FuncInfo)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.
setInstrumentedCounts(const std::vector<uint64_t> & CountFromProfile)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.
setEdgeCount(DirectEdges & Edges,uint64_t Value)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.
annotateFunctionWithHashMismatch(Function & F,LLVMContext & ctx)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
handleInstrProfError(Error Err,uint64_t MismatchedFuncSum)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.
readCounters(IndexedInstrProfReader * PGOReader,bool & AllZeros,InstrProfRecord::CountPseudoKind & PseudoKind)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
populateCoverage(IndexedInstrProfReader * PGOReader)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.
populateCounters()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.
setBranchWeights()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
isIndirectBrTarget(BasicBlock * BB)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
annotateIrrLoopHeaderWeights()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
instrumentOneSelectInst(SelectInst & SI)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
annotateOneSelectInst(SelectInst & SI)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
visitSelectInst(SelectInst & SI)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
getMaxNumAnnotations(InstrProfValueKind ValueProfKind)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.
annotateValueSites()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.
annotateValueSites(uint32_t 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.
collectComdatMembers(Module & M,std::unordered_multimap<Comdat *,GlobalValue * > & 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
skipPGOUse(const Function & F)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
skipPGOGen(const Function & F)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
InstrumentAllFunctions(Module & M,function_ref<TargetLibraryInfo & (Function &)> LookupTLI,function_ref<BranchProbabilityInfo * (Function &)> LookupBPI,function_ref<BlockFrequencyInfo * (Function &)> LookupBFI,bool IsCS)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
run(Module & M,ModuleAnalysisManager & MAM)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
run(Module & M,ModuleAnalysisManager & MAM)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.
fixFuncEntryCount(PGOUseFunc & Func,LoopInfo & LI,BranchProbabilityInfo & NBPI)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.
verifyFuncBFI(PGOUseFunc & Func,LoopInfo & LI,BranchProbabilityInfo & NBPI,uint64_t HotCountThreshold,uint64_t ColdCountThreshold)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
annotateAllFunctions(Module & M,StringRef ProfileFileName,StringRef ProfileRemappingFileName,vfs::FileSystem & FS,function_ref<TargetLibraryInfo & (Function &)> LookupTLI,function_ref<BranchProbabilityInfo * (Function &)> LookupBPI,function_ref<BlockFrequencyInfo * (Function &)> LookupBFI,ProfileSummaryInfo * PSI,bool IsCS)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
PGOInstrumentationUse(std::string Filename,std::string RemappingFilename,bool IsCS,IntrusiveRefCntPtr<vfs::FileSystem> VFS)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
run(Module & M,ModuleAnalysisManager & MAM)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
getSimpleNodeName(const BasicBlock * Node)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
setProfMetadata(Module * M,Instruction * TI,ArrayRef<uint64_t> EdgeCounts,uint64_t MaxCount)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
setIrrLoopHeaderMetadata(Module * M,Instruction * TI,uint64_t Count)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
getEntryNodellvm::GraphTraits23520b57cec5SDimitry Andric static NodeRef getEntryNode(const PGOUseFunc *G) {
23530b57cec5SDimitry Andric return &G->getFunc().front();
23540b57cec5SDimitry Andric }
23550b57cec5SDimitry Andric
child_beginllvm::GraphTraits23560b57cec5SDimitry Andric static ChildIteratorType child_begin(const NodeRef N) {
23570b57cec5SDimitry Andric return succ_begin(N);
23580b57cec5SDimitry Andric }
23590b57cec5SDimitry Andric
child_endllvm::GraphTraits23600b57cec5SDimitry Andric static ChildIteratorType child_end(const NodeRef N) { return succ_end(N); }
23610b57cec5SDimitry Andric
nodes_beginllvm::GraphTraits23620b57cec5SDimitry Andric static nodes_iterator nodes_begin(const PGOUseFunc *G) {
23630b57cec5SDimitry Andric return nodes_iterator(G->getFunc().begin());
23640b57cec5SDimitry Andric }
23650b57cec5SDimitry Andric
nodes_endllvm::GraphTraits23660b57cec5SDimitry 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 {
DOTGraphTraitsllvm::DOTGraphTraits23720b57cec5SDimitry Andric explicit DOTGraphTraits(bool isSimple = false)
23730b57cec5SDimitry Andric : DefaultDOTGraphTraits(isSimple) {}
23740b57cec5SDimitry Andric
getGraphNamellvm::DOTGraphTraits23750b57cec5SDimitry Andric static std::string getGraphName(const PGOUseFunc *G) {
23765ffd83dbSDimitry Andric return std::string(G->getFunc().getName());
23770b57cec5SDimitry Andric }
23780b57cec5SDimitry Andric
getNodeLabelllvm::DOTGraphTraits23790b57cec5SDimitry 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