167c32a98SDimitry Andric //===-- InstrProfiling.cpp - Frontend instrumentation based profiling -----===//
267c32a98SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
667c32a98SDimitry Andric //
767c32a98SDimitry Andric //===----------------------------------------------------------------------===//
867c32a98SDimitry Andric //
9b1c73532SDimitry Andric // This pass lowers instrprof_* intrinsics emitted by an instrumentor.
10dd58ef01SDimitry Andric // It also builds the data structures and initialization code needed for
11dd58ef01SDimitry Andric // updating execution counts and emitting the profile at runtime.
1267c32a98SDimitry Andric //
1367c32a98SDimitry Andric //===----------------------------------------------------------------------===//
1467c32a98SDimitry Andric
15eb11fae6SDimitry Andric #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
1671d5a254SDimitry Andric #include "llvm/ADT/ArrayRef.h"
17b1c73532SDimitry Andric #include "llvm/ADT/STLExtras.h"
1871d5a254SDimitry Andric #include "llvm/ADT/SmallVector.h"
1971d5a254SDimitry Andric #include "llvm/ADT/StringRef.h"
2071d5a254SDimitry Andric #include "llvm/ADT/Twine.h"
21e6d15924SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h"
22e6d15924SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
2308bbd35aSDimitry Andric #include "llvm/Analysis/LoopInfo.h"
24b915e9e0SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
2571d5a254SDimitry Andric #include "llvm/IR/Attributes.h"
2671d5a254SDimitry Andric #include "llvm/IR/BasicBlock.h"
27b1c73532SDimitry Andric #include "llvm/IR/CFG.h"
2871d5a254SDimitry Andric #include "llvm/IR/Constant.h"
2971d5a254SDimitry Andric #include "llvm/IR/Constants.h"
3077fc4c14SDimitry Andric #include "llvm/IR/DIBuilder.h"
3171d5a254SDimitry Andric #include "llvm/IR/DerivedTypes.h"
3277fc4c14SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
3308bbd35aSDimitry Andric #include "llvm/IR/Dominators.h"
3471d5a254SDimitry Andric #include "llvm/IR/Function.h"
3571d5a254SDimitry Andric #include "llvm/IR/GlobalValue.h"
3671d5a254SDimitry Andric #include "llvm/IR/GlobalVariable.h"
377ab83427SDimitry Andric #include "llvm/IR/IRBuilder.h"
3871d5a254SDimitry Andric #include "llvm/IR/Instruction.h"
3971d5a254SDimitry Andric #include "llvm/IR/Instructions.h"
4067c32a98SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
41ac9a064cSDimitry Andric #include "llvm/IR/MDBuilder.h"
4267c32a98SDimitry Andric #include "llvm/IR/Module.h"
4371d5a254SDimitry Andric #include "llvm/IR/Type.h"
44706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
4571d5a254SDimitry Andric #include "llvm/Pass.h"
46dd58ef01SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
4777fc4c14SDimitry Andric #include "llvm/ProfileData/InstrProfCorrelator.h"
4871d5a254SDimitry Andric #include "llvm/Support/Casting.h"
4971d5a254SDimitry Andric #include "llvm/Support/CommandLine.h"
5071d5a254SDimitry Andric #include "llvm/Support/Error.h"
5171d5a254SDimitry Andric #include "llvm/Support/ErrorHandling.h"
527fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
53b1c73532SDimitry Andric #include "llvm/Transforms/Instrumentation.h"
54b1c73532SDimitry Andric #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
55b1c73532SDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
5667c32a98SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
5708bbd35aSDimitry Andric #include "llvm/Transforms/Utils/SSAUpdater.h"
5871d5a254SDimitry Andric #include <algorithm>
5971d5a254SDimitry Andric #include <cassert>
6071d5a254SDimitry Andric #include <cstdint>
6171d5a254SDimitry Andric #include <string>
6267c32a98SDimitry Andric
6367c32a98SDimitry Andric using namespace llvm;
6467c32a98SDimitry Andric
6567c32a98SDimitry Andric #define DEBUG_TYPE "instrprof"
6667c32a98SDimitry Andric
6777fc4c14SDimitry Andric namespace llvm {
68ac9a064cSDimitry Andric // Command line option to enable vtable value profiling. Defined in
69ac9a064cSDimitry Andric // ProfileData/InstrProf.cpp: -enable-vtable-value-profiling=
70ac9a064cSDimitry Andric extern cl::opt<bool> EnableVTableValueProfiling;
71312c0ed1SDimitry Andric // TODO: Remove -debug-info-correlate in next LLVM release, in favor of
72312c0ed1SDimitry Andric // -profile-correlate=debug-info.
73312c0ed1SDimitry Andric cl::opt<bool> DebugInfoCorrelate(
74312c0ed1SDimitry Andric "debug-info-correlate",
75312c0ed1SDimitry Andric cl::desc("Use debug info to correlate profiles. (Deprecated, use "
76312c0ed1SDimitry Andric "-profile-correlate=debug-info)"),
7777fc4c14SDimitry Andric cl::init(false));
78312c0ed1SDimitry Andric
79312c0ed1SDimitry Andric cl::opt<InstrProfCorrelator::ProfCorrelatorKind> ProfileCorrelate(
80312c0ed1SDimitry Andric "profile-correlate",
81312c0ed1SDimitry Andric cl::desc("Use debug info or binary file to correlate profiles."),
82312c0ed1SDimitry Andric cl::init(InstrProfCorrelator::NONE),
83312c0ed1SDimitry Andric cl::values(clEnumValN(InstrProfCorrelator::NONE, "",
84312c0ed1SDimitry Andric "No profile correlation"),
85312c0ed1SDimitry Andric clEnumValN(InstrProfCorrelator::DEBUG_INFO, "debug-info",
86312c0ed1SDimitry Andric "Use debug info to correlate"),
87312c0ed1SDimitry Andric clEnumValN(InstrProfCorrelator::BINARY, "binary",
88312c0ed1SDimitry Andric "Use binary to correlate")));
8977fc4c14SDimitry Andric } // namespace llvm
9077fc4c14SDimitry Andric
9167c32a98SDimitry Andric namespace {
9267c32a98SDimitry Andric
93581a6d85SDimitry Andric cl::opt<bool> DoHashBasedCounterSplit(
94581a6d85SDimitry Andric "hash-based-counter-split",
95581a6d85SDimitry Andric cl::desc("Rename counter variable of a comdat function based on cfg hash"),
96581a6d85SDimitry Andric cl::init(true));
97581a6d85SDimitry Andric
98f65dcba8SDimitry Andric cl::opt<bool>
99f65dcba8SDimitry Andric RuntimeCounterRelocation("runtime-counter-relocation",
100cfca06d7SDimitry Andric cl::desc("Enable relocating counters at runtime."),
101cfca06d7SDimitry Andric cl::init(false));
102cfca06d7SDimitry Andric
10301095a5dSDimitry Andric cl::opt<bool> ValueProfileStaticAlloc(
10401095a5dSDimitry Andric "vp-static-alloc",
10501095a5dSDimitry Andric cl::desc("Do static counter allocation for value profiler"),
10601095a5dSDimitry Andric cl::init(true));
10771d5a254SDimitry Andric
10801095a5dSDimitry Andric cl::opt<double> NumCountersPerValueSite(
10901095a5dSDimitry Andric "vp-counters-per-site",
11001095a5dSDimitry Andric cl::desc("The average number of profile counters allocated "
11101095a5dSDimitry Andric "per value profiling site."),
11201095a5dSDimitry Andric // This is set to a very small value because in real programs, only
11301095a5dSDimitry Andric // a very small percentage of value sites have non-zero targets, e.g, 1/30.
11401095a5dSDimitry Andric // For those sites with non-zero profile, the average number of targets
11501095a5dSDimitry Andric // is usually smaller than 2.
11601095a5dSDimitry Andric cl::init(1.0));
11701095a5dSDimitry Andric
118d8e91e46SDimitry Andric cl::opt<bool> AtomicCounterUpdateAll(
119145449b1SDimitry Andric "instrprof-atomic-counter-update-all",
120d8e91e46SDimitry Andric cl::desc("Make all profile counter updates atomic (for testing only)"),
121d8e91e46SDimitry Andric cl::init(false));
122d8e91e46SDimitry Andric
12308bbd35aSDimitry Andric cl::opt<bool> AtomicCounterUpdatePromoted(
124145449b1SDimitry Andric "atomic-counter-update-promoted",
12508bbd35aSDimitry Andric cl::desc("Do counter update using atomic fetch add "
12608bbd35aSDimitry Andric " for promoted counters only"),
12708bbd35aSDimitry Andric cl::init(false));
12808bbd35aSDimitry Andric
129cfca06d7SDimitry Andric cl::opt<bool> AtomicFirstCounter(
130145449b1SDimitry Andric "atomic-first-counter",
131cfca06d7SDimitry Andric cl::desc("Use atomic fetch add for first counter in a function (usually "
132cfca06d7SDimitry Andric "the entry counter)"),
133cfca06d7SDimitry Andric cl::init(false));
134cfca06d7SDimitry Andric
13508bbd35aSDimitry Andric // If the option is not specified, the default behavior about whether
13608bbd35aSDimitry Andric // counter promotion is done depends on how instrumentaiton lowering
13708bbd35aSDimitry Andric // pipeline is setup, i.e., the default value of true of this option
13808bbd35aSDimitry Andric // does not mean the promotion will be done by default. Explicitly
13908bbd35aSDimitry Andric // setting this option can override the default behavior.
140145449b1SDimitry Andric cl::opt<bool> DoCounterPromotion("do-counter-promotion",
14108bbd35aSDimitry Andric cl::desc("Do counter register promotion"),
14208bbd35aSDimitry Andric cl::init(false));
14308bbd35aSDimitry Andric cl::opt<unsigned> MaxNumOfPromotionsPerLoop(
144145449b1SDimitry Andric "max-counter-promotions-per-loop", cl::init(20),
14508bbd35aSDimitry Andric cl::desc("Max number counter promotions per loop to avoid"
14608bbd35aSDimitry Andric " increasing register pressure too much"));
14708bbd35aSDimitry Andric
14808bbd35aSDimitry Andric // A debug option
14908bbd35aSDimitry Andric cl::opt<int>
150145449b1SDimitry Andric MaxNumOfPromotions("max-counter-promotions", cl::init(-1),
15108bbd35aSDimitry Andric cl::desc("Max number of allowed counter promotions"));
15208bbd35aSDimitry Andric
153ca089b24SDimitry Andric cl::opt<unsigned> SpeculativeCounterPromotionMaxExiting(
154145449b1SDimitry Andric "speculative-counter-promotion-max-exiting", cl::init(3),
155ca089b24SDimitry Andric cl::desc("The max number of exiting blocks of a loop to allow "
156ca089b24SDimitry Andric " speculative counter promotion"));
157ca089b24SDimitry Andric
158ca089b24SDimitry Andric cl::opt<bool> SpeculativeCounterPromotionToLoop(
159145449b1SDimitry Andric "speculative-counter-promotion-to-loop",
160ca089b24SDimitry Andric cl::desc("When the option is false, if the target block is in a loop, "
161ca089b24SDimitry Andric "the promotion will be disallowed unless the promoted counter "
162ca089b24SDimitry Andric " update can be further/iteratively promoted into an acyclic "
163ca089b24SDimitry Andric " region."));
164ca089b24SDimitry Andric
165ca089b24SDimitry Andric cl::opt<bool> IterativeCounterPromotion(
166145449b1SDimitry Andric "iterative-counter-promotion", cl::init(true),
167ca089b24SDimitry Andric cl::desc("Allow counter promotion across the whole loop nest."));
16808bbd35aSDimitry Andric
169b60736ecSDimitry Andric cl::opt<bool> SkipRetExitBlock(
170145449b1SDimitry Andric "skip-ret-exit-block", cl::init(true),
171b60736ecSDimitry Andric cl::desc("Suppress counter promotion if exit blocks contain ret."));
172b60736ecSDimitry Andric
173ac9a064cSDimitry Andric static cl::opt<bool> SampledInstr("sampled-instrumentation", cl::ZeroOrMore,
174ac9a064cSDimitry Andric cl::init(false),
175ac9a064cSDimitry Andric cl::desc("Do PGO instrumentation sampling"));
176ac9a064cSDimitry Andric
177ac9a064cSDimitry Andric static cl::opt<unsigned> SampledInstrPeriod(
178ac9a064cSDimitry Andric "sampled-instr-period",
179ac9a064cSDimitry Andric cl::desc("Set the profile instrumentation sample period. For each sample "
180ac9a064cSDimitry Andric "period, a fixed number of consecutive samples will be recorded. "
181ac9a064cSDimitry Andric "The number is controlled by 'sampled-instr-burst-duration' flag. "
182ac9a064cSDimitry Andric "The default sample period of 65535 is optimized for generating "
183ac9a064cSDimitry Andric "efficient code that leverages unsigned integer wrapping in "
184ac9a064cSDimitry Andric "overflow."),
185ac9a064cSDimitry Andric cl::init(65535));
186ac9a064cSDimitry Andric
187ac9a064cSDimitry Andric static cl::opt<unsigned> SampledInstrBurstDuration(
188ac9a064cSDimitry Andric "sampled-instr-burst-duration",
189ac9a064cSDimitry Andric cl::desc("Set the profile instrumentation burst duration, which can range "
190ac9a064cSDimitry Andric "from 0 to one less than the value of 'sampled-instr-period'. "
191ac9a064cSDimitry Andric "This number of samples will be recorded for each "
192ac9a064cSDimitry Andric "'sampled-instr-period' count update. Setting to 1 enables "
193ac9a064cSDimitry Andric "simple sampling, in which case it is recommended to set "
194ac9a064cSDimitry Andric "'sampled-instr-period' to a prime number."),
195ac9a064cSDimitry Andric cl::init(200));
196ac9a064cSDimitry Andric
197312c0ed1SDimitry Andric using LoadStorePair = std::pair<Instruction *, Instruction *>;
198312c0ed1SDimitry Andric
getIntModuleFlagOrZero(const Module & M,StringRef Flag)199ac9a064cSDimitry Andric static uint64_t getIntModuleFlagOrZero(const Module &M, StringRef Flag) {
200ac9a064cSDimitry Andric auto *MD = dyn_cast_or_null<ConstantAsMetadata>(M.getModuleFlag(Flag));
201ac9a064cSDimitry Andric if (!MD)
202ac9a064cSDimitry Andric return 0;
203ac9a064cSDimitry Andric
204ac9a064cSDimitry Andric // If the flag is a ConstantAsMetadata, it should be an integer representable
205ac9a064cSDimitry Andric // in 64-bits.
206ac9a064cSDimitry Andric return cast<ConstantInt>(MD->getValue())->getZExtValue();
207ac9a064cSDimitry Andric }
208ac9a064cSDimitry Andric
enablesValueProfiling(const Module & M)209ac9a064cSDimitry Andric static bool enablesValueProfiling(const Module &M) {
210ac9a064cSDimitry Andric return isIRPGOFlagSet(&M) ||
211ac9a064cSDimitry Andric getIntModuleFlagOrZero(M, "EnableValueProfiling") != 0;
212ac9a064cSDimitry Andric }
213ac9a064cSDimitry Andric
214ac9a064cSDimitry Andric // Conservatively returns true if value profiling is enabled.
profDataReferencedByCode(const Module & M)215ac9a064cSDimitry Andric static bool profDataReferencedByCode(const Module &M) {
216ac9a064cSDimitry Andric return enablesValueProfiling(M);
217ac9a064cSDimitry Andric }
218ac9a064cSDimitry Andric
219312c0ed1SDimitry Andric class InstrLowerer final {
220312c0ed1SDimitry Andric public:
InstrLowerer(Module & M,const InstrProfOptions & Options,std::function<const TargetLibraryInfo & (Function & F)> GetTLI,bool IsCS)221312c0ed1SDimitry Andric InstrLowerer(Module &M, const InstrProfOptions &Options,
222312c0ed1SDimitry Andric std::function<const TargetLibraryInfo &(Function &F)> GetTLI,
223312c0ed1SDimitry Andric bool IsCS)
224312c0ed1SDimitry Andric : M(M), Options(Options), TT(Triple(M.getTargetTriple())), IsCS(IsCS),
225ac9a064cSDimitry Andric GetTLI(GetTLI), DataReferencedByCode(profDataReferencedByCode(M)) {}
226312c0ed1SDimitry Andric
227312c0ed1SDimitry Andric bool lower();
228312c0ed1SDimitry Andric
229312c0ed1SDimitry Andric private:
230312c0ed1SDimitry Andric Module &M;
231312c0ed1SDimitry Andric const InstrProfOptions Options;
232312c0ed1SDimitry Andric const Triple TT;
233312c0ed1SDimitry Andric // Is this lowering for the context-sensitive instrumentation.
234312c0ed1SDimitry Andric const bool IsCS;
235312c0ed1SDimitry Andric
236312c0ed1SDimitry Andric std::function<const TargetLibraryInfo &(Function &F)> GetTLI;
237ac9a064cSDimitry Andric
238ac9a064cSDimitry Andric const bool DataReferencedByCode;
239ac9a064cSDimitry Andric
240312c0ed1SDimitry Andric struct PerFunctionProfileData {
241312c0ed1SDimitry Andric uint32_t NumValueSites[IPVK_Last + 1] = {};
242312c0ed1SDimitry Andric GlobalVariable *RegionCounters = nullptr;
243312c0ed1SDimitry Andric GlobalVariable *DataVar = nullptr;
244312c0ed1SDimitry Andric GlobalVariable *RegionBitmaps = nullptr;
245312c0ed1SDimitry Andric uint32_t NumBitmapBytes = 0;
246312c0ed1SDimitry Andric
247312c0ed1SDimitry Andric PerFunctionProfileData() = default;
248312c0ed1SDimitry Andric };
249312c0ed1SDimitry Andric DenseMap<GlobalVariable *, PerFunctionProfileData> ProfileDataMap;
250ac9a064cSDimitry Andric // Key is virtual table variable, value is 'VTableProfData' in the form of
251ac9a064cSDimitry Andric // GlobalVariable.
252ac9a064cSDimitry Andric DenseMap<GlobalVariable *, GlobalVariable *> VTableDataMap;
253312c0ed1SDimitry Andric /// If runtime relocation is enabled, this maps functions to the load
254312c0ed1SDimitry Andric /// instruction that produces the profile relocation bias.
255312c0ed1SDimitry Andric DenseMap<const Function *, LoadInst *> FunctionToProfileBiasMap;
256312c0ed1SDimitry Andric std::vector<GlobalValue *> CompilerUsedVars;
257312c0ed1SDimitry Andric std::vector<GlobalValue *> UsedVars;
258312c0ed1SDimitry Andric std::vector<GlobalVariable *> ReferencedNames;
259ac9a064cSDimitry Andric // The list of virtual table variables of which the VTableProfData is
260ac9a064cSDimitry Andric // collected.
261ac9a064cSDimitry Andric std::vector<GlobalVariable *> ReferencedVTables;
262312c0ed1SDimitry Andric GlobalVariable *NamesVar = nullptr;
263312c0ed1SDimitry Andric size_t NamesSize = 0;
264312c0ed1SDimitry Andric
265ac9a064cSDimitry Andric /// The instance of [[alwaysinline]] rmw_or(ptr, i8).
266ac9a064cSDimitry Andric /// This is name-insensitive.
267ac9a064cSDimitry Andric Function *RMWOrFunc = nullptr;
268ac9a064cSDimitry Andric
269312c0ed1SDimitry Andric // vector of counter load/store pairs to be register promoted.
270312c0ed1SDimitry Andric std::vector<LoadStorePair> PromotionCandidates;
271312c0ed1SDimitry Andric
272312c0ed1SDimitry Andric int64_t TotalCountersPromoted = 0;
273312c0ed1SDimitry Andric
274312c0ed1SDimitry Andric /// Lower instrumentation intrinsics in the function. Returns true if there
275312c0ed1SDimitry Andric /// any lowering.
276312c0ed1SDimitry Andric bool lowerIntrinsics(Function *F);
277312c0ed1SDimitry Andric
278312c0ed1SDimitry Andric /// Register-promote counter loads and stores in loops.
279312c0ed1SDimitry Andric void promoteCounterLoadStores(Function *F);
280312c0ed1SDimitry Andric
281312c0ed1SDimitry Andric /// Returns true if relocating counters at runtime is enabled.
282312c0ed1SDimitry Andric bool isRuntimeCounterRelocationEnabled() const;
283312c0ed1SDimitry Andric
284312c0ed1SDimitry Andric /// Returns true if profile counter update register promotion is enabled.
285312c0ed1SDimitry Andric bool isCounterPromotionEnabled() const;
286312c0ed1SDimitry Andric
287ac9a064cSDimitry Andric /// Return true if profile sampling is enabled.
288ac9a064cSDimitry Andric bool isSamplingEnabled() const;
289ac9a064cSDimitry Andric
290312c0ed1SDimitry Andric /// Count the number of instrumented value sites for the function.
291312c0ed1SDimitry Andric void computeNumValueSiteCounts(InstrProfValueProfileInst *Ins);
292312c0ed1SDimitry Andric
293312c0ed1SDimitry Andric /// Replace instrprof.value.profile with a call to runtime library.
294312c0ed1SDimitry Andric void lowerValueProfileInst(InstrProfValueProfileInst *Ins);
295312c0ed1SDimitry Andric
296312c0ed1SDimitry Andric /// Replace instrprof.cover with a store instruction to the coverage byte.
297312c0ed1SDimitry Andric void lowerCover(InstrProfCoverInst *Inc);
298312c0ed1SDimitry Andric
299312c0ed1SDimitry Andric /// Replace instrprof.timestamp with a call to
300312c0ed1SDimitry Andric /// INSTR_PROF_PROFILE_SET_TIMESTAMP.
301312c0ed1SDimitry Andric void lowerTimestamp(InstrProfTimestampInst *TimestampInstruction);
302312c0ed1SDimitry Andric
303312c0ed1SDimitry Andric /// Replace instrprof.increment with an increment of the appropriate value.
304312c0ed1SDimitry Andric void lowerIncrement(InstrProfIncrementInst *Inc);
305312c0ed1SDimitry Andric
306312c0ed1SDimitry Andric /// Force emitting of name vars for unused functions.
307312c0ed1SDimitry Andric void lowerCoverageData(GlobalVariable *CoverageNamesVar);
308312c0ed1SDimitry Andric
309312c0ed1SDimitry Andric /// Replace instrprof.mcdc.tvbitmask.update with a shift and or instruction
310312c0ed1SDimitry Andric /// using the index represented by the a temp value into a bitmap.
311312c0ed1SDimitry Andric void lowerMCDCTestVectorBitmapUpdate(InstrProfMCDCTVBitmapUpdate *Ins);
312312c0ed1SDimitry Andric
313ac9a064cSDimitry Andric /// Get the Bias value for data to access mmap-ed area.
314ac9a064cSDimitry Andric /// Create it if it hasn't been seen.
315ac9a064cSDimitry Andric GlobalVariable *getOrCreateBiasVar(StringRef VarName);
316312c0ed1SDimitry Andric
317312c0ed1SDimitry Andric /// Compute the address of the counter value that this profiling instruction
318312c0ed1SDimitry Andric /// acts on.
319312c0ed1SDimitry Andric Value *getCounterAddress(InstrProfCntrInstBase *I);
320312c0ed1SDimitry Andric
321ac9a064cSDimitry Andric /// Lower the incremental instructions under profile sampling predicates.
322ac9a064cSDimitry Andric void doSampling(Instruction *I);
323ac9a064cSDimitry Andric
324312c0ed1SDimitry Andric /// Get the region counters for an increment, creating them if necessary.
325312c0ed1SDimitry Andric ///
326312c0ed1SDimitry Andric /// If the counter array doesn't yet exist, the profile data variables
327312c0ed1SDimitry Andric /// referring to them will also be created.
328312c0ed1SDimitry Andric GlobalVariable *getOrCreateRegionCounters(InstrProfCntrInstBase *Inc);
329312c0ed1SDimitry Andric
330312c0ed1SDimitry Andric /// Create the region counters.
331312c0ed1SDimitry Andric GlobalVariable *createRegionCounters(InstrProfCntrInstBase *Inc,
332312c0ed1SDimitry Andric StringRef Name,
333312c0ed1SDimitry Andric GlobalValue::LinkageTypes Linkage);
334312c0ed1SDimitry Andric
335ac9a064cSDimitry Andric /// Create [[alwaysinline]] rmw_or(ptr, i8).
336ac9a064cSDimitry Andric /// This doesn't update `RMWOrFunc`.
337ac9a064cSDimitry Andric Function *createRMWOrFunc();
338ac9a064cSDimitry Andric
339ac9a064cSDimitry Andric /// Get the call to `rmw_or`.
340ac9a064cSDimitry Andric /// Create the instance if it is unknown.
341ac9a064cSDimitry Andric CallInst *getRMWOrCall(Value *Addr, Value *Val);
342ac9a064cSDimitry Andric
343312c0ed1SDimitry Andric /// Compute the address of the test vector bitmap that this profiling
344312c0ed1SDimitry Andric /// instruction acts on.
345312c0ed1SDimitry Andric Value *getBitmapAddress(InstrProfMCDCTVBitmapUpdate *I);
346312c0ed1SDimitry Andric
347312c0ed1SDimitry Andric /// Get the region bitmaps for an increment, creating them if necessary.
348312c0ed1SDimitry Andric ///
349312c0ed1SDimitry Andric /// If the bitmap array doesn't yet exist, the profile data variables
350312c0ed1SDimitry Andric /// referring to them will also be created.
351312c0ed1SDimitry Andric GlobalVariable *getOrCreateRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc);
352312c0ed1SDimitry Andric
353312c0ed1SDimitry Andric /// Create the MC/DC bitmap as a byte-aligned array of bytes associated with
354312c0ed1SDimitry Andric /// an MC/DC Decision region. The number of bytes required is indicated by
355312c0ed1SDimitry Andric /// the intrinsic used (type InstrProfMCDCBitmapInstBase). This is called
356312c0ed1SDimitry Andric /// as part of setupProfileSection() and is conceptually very similar to
357312c0ed1SDimitry Andric /// what is done for profile data counters in createRegionCounters().
358312c0ed1SDimitry Andric GlobalVariable *createRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc,
359312c0ed1SDimitry Andric StringRef Name,
360312c0ed1SDimitry Andric GlobalValue::LinkageTypes Linkage);
361312c0ed1SDimitry Andric
362312c0ed1SDimitry Andric /// Set Comdat property of GV, if required.
363ac9a064cSDimitry Andric void maybeSetComdat(GlobalVariable *GV, GlobalObject *GO, StringRef VarName);
364312c0ed1SDimitry Andric
365312c0ed1SDimitry Andric /// Setup the sections into which counters and bitmaps are allocated.
366312c0ed1SDimitry Andric GlobalVariable *setupProfileSection(InstrProfInstBase *Inc,
367312c0ed1SDimitry Andric InstrProfSectKind IPSK);
368312c0ed1SDimitry Andric
369312c0ed1SDimitry Andric /// Create INSTR_PROF_DATA variable for counters and bitmaps.
370312c0ed1SDimitry Andric void createDataVariable(InstrProfCntrInstBase *Inc);
371312c0ed1SDimitry Andric
372ac9a064cSDimitry Andric /// Get the counters for virtual table values, creating them if necessary.
373ac9a064cSDimitry Andric void getOrCreateVTableProfData(GlobalVariable *GV);
374ac9a064cSDimitry Andric
375312c0ed1SDimitry Andric /// Emit the section with compressed function names.
376312c0ed1SDimitry Andric void emitNameData();
377312c0ed1SDimitry Andric
378ac9a064cSDimitry Andric /// Emit the section with compressed vtable names.
379ac9a064cSDimitry Andric void emitVTableNames();
380ac9a064cSDimitry Andric
381312c0ed1SDimitry Andric /// Emit value nodes section for value profiling.
382312c0ed1SDimitry Andric void emitVNodes();
383312c0ed1SDimitry Andric
384312c0ed1SDimitry Andric /// Emit runtime registration functions for each profile data variable.
385312c0ed1SDimitry Andric void emitRegistration();
386312c0ed1SDimitry Andric
387312c0ed1SDimitry Andric /// Emit the necessary plumbing to pull in the runtime initialization.
388312c0ed1SDimitry Andric /// Returns true if a change was made.
389312c0ed1SDimitry Andric bool emitRuntimeHook();
390312c0ed1SDimitry Andric
391312c0ed1SDimitry Andric /// Add uses of our data variables and runtime hook.
392312c0ed1SDimitry Andric void emitUses();
393312c0ed1SDimitry Andric
394312c0ed1SDimitry Andric /// Create a static initializer for our data, on platforms that need it,
395312c0ed1SDimitry Andric /// and for any profile output file that was specified.
396312c0ed1SDimitry Andric void emitInitialization();
397312c0ed1SDimitry Andric };
398312c0ed1SDimitry Andric
399ca089b24SDimitry Andric ///
40008bbd35aSDimitry Andric /// A helper class to promote one counter RMW operation in the loop
40108bbd35aSDimitry Andric /// into register update.
40208bbd35aSDimitry Andric ///
40308bbd35aSDimitry Andric /// RWM update for the counter will be sinked out of the loop after
40408bbd35aSDimitry Andric /// the transformation.
40508bbd35aSDimitry Andric ///
40608bbd35aSDimitry Andric class PGOCounterPromoterHelper : public LoadAndStorePromoter {
40708bbd35aSDimitry Andric public:
PGOCounterPromoterHelper(Instruction * L,Instruction * S,SSAUpdater & SSA,Value * Init,BasicBlock * PH,ArrayRef<BasicBlock * > ExitBlocks,ArrayRef<Instruction * > InsertPts,DenseMap<Loop *,SmallVector<LoadStorePair,8>> & LoopToCands,LoopInfo & LI)408ca089b24SDimitry Andric PGOCounterPromoterHelper(
409ca089b24SDimitry Andric Instruction *L, Instruction *S, SSAUpdater &SSA, Value *Init,
410ca089b24SDimitry Andric BasicBlock *PH, ArrayRef<BasicBlock *> ExitBlocks,
411ca089b24SDimitry Andric ArrayRef<Instruction *> InsertPts,
412ca089b24SDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCands,
413ca089b24SDimitry Andric LoopInfo &LI)
41408bbd35aSDimitry Andric : LoadAndStorePromoter({L, S}, SSA), Store(S), ExitBlocks(ExitBlocks),
415ca089b24SDimitry Andric InsertPts(InsertPts), LoopToCandidates(LoopToCands), LI(LI) {
41608bbd35aSDimitry Andric assert(isa<LoadInst>(L));
41708bbd35aSDimitry Andric assert(isa<StoreInst>(S));
41808bbd35aSDimitry Andric SSA.AddAvailableValue(PH, Init);
41908bbd35aSDimitry Andric }
420ca089b24SDimitry Andric
doExtraRewritesBeforeFinalDeletion()421e6d15924SDimitry Andric void doExtraRewritesBeforeFinalDeletion() override {
42208bbd35aSDimitry Andric for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
42308bbd35aSDimitry Andric BasicBlock *ExitBlock = ExitBlocks[i];
42408bbd35aSDimitry Andric Instruction *InsertPos = InsertPts[i];
42508bbd35aSDimitry Andric // Get LiveIn value into the ExitBlock. If there are multiple
42608bbd35aSDimitry Andric // predecessors, the value is defined by a PHI node in this
42708bbd35aSDimitry Andric // block.
42808bbd35aSDimitry Andric Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
42908bbd35aSDimitry Andric Value *Addr = cast<StoreInst>(Store)->getPointerOperand();
430e6d15924SDimitry Andric Type *Ty = LiveInValue->getType();
43108bbd35aSDimitry Andric IRBuilder<> Builder(InsertPos);
432145449b1SDimitry Andric if (auto *AddrInst = dyn_cast_or_null<IntToPtrInst>(Addr)) {
433145449b1SDimitry Andric // If isRuntimeCounterRelocationEnabled() is true then the address of
434145449b1SDimitry Andric // the store instruction is computed with two instructions in
435145449b1SDimitry Andric // InstrProfiling::getCounterAddress(). We need to copy those
436145449b1SDimitry Andric // instructions to this block to compute Addr correctly.
437145449b1SDimitry Andric // %BiasAdd = add i64 ptrtoint <__profc_>, <__llvm_profile_counter_bias>
438145449b1SDimitry Andric // %Addr = inttoptr i64 %BiasAdd to i64*
439145449b1SDimitry Andric auto *OrigBiasInst = dyn_cast<BinaryOperator>(AddrInst->getOperand(0));
440145449b1SDimitry Andric assert(OrigBiasInst->getOpcode() == Instruction::BinaryOps::Add);
441145449b1SDimitry Andric Value *BiasInst = Builder.Insert(OrigBiasInst->clone());
442b1c73532SDimitry Andric Addr = Builder.CreateIntToPtr(BiasInst,
443b1c73532SDimitry Andric PointerType::getUnqual(Ty->getContext()));
444145449b1SDimitry Andric }
44508bbd35aSDimitry Andric if (AtomicCounterUpdatePromoted)
446ca089b24SDimitry Andric // automic update currently can only be promoted across the current
447ca089b24SDimitry Andric // loop, not the whole loop nest.
44808bbd35aSDimitry Andric Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, LiveInValue,
449344a3780SDimitry Andric MaybeAlign(),
45008bbd35aSDimitry Andric AtomicOrdering::SequentiallyConsistent);
45108bbd35aSDimitry Andric else {
452e6d15924SDimitry Andric LoadInst *OldVal = Builder.CreateLoad(Ty, Addr, "pgocount.promoted");
45308bbd35aSDimitry Andric auto *NewVal = Builder.CreateAdd(OldVal, LiveInValue);
454ca089b24SDimitry Andric auto *NewStore = Builder.CreateStore(NewVal, Addr);
455ca089b24SDimitry Andric
456ca089b24SDimitry Andric // Now update the parent loop's candidate list:
457ca089b24SDimitry Andric if (IterativeCounterPromotion) {
458ca089b24SDimitry Andric auto *TargetLoop = LI.getLoopFor(ExitBlock);
459ca089b24SDimitry Andric if (TargetLoop)
460ca089b24SDimitry Andric LoopToCandidates[TargetLoop].emplace_back(OldVal, NewStore);
461ca089b24SDimitry Andric }
46208bbd35aSDimitry Andric }
46308bbd35aSDimitry Andric }
46408bbd35aSDimitry Andric }
46508bbd35aSDimitry Andric
46608bbd35aSDimitry Andric private:
46708bbd35aSDimitry Andric Instruction *Store;
46808bbd35aSDimitry Andric ArrayRef<BasicBlock *> ExitBlocks;
46908bbd35aSDimitry Andric ArrayRef<Instruction *> InsertPts;
470ca089b24SDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCandidates;
471ca089b24SDimitry Andric LoopInfo &LI;
47208bbd35aSDimitry Andric };
47308bbd35aSDimitry Andric
47408bbd35aSDimitry Andric /// A helper class to do register promotion for all profile counter
47508bbd35aSDimitry Andric /// updates in a loop.
47608bbd35aSDimitry Andric ///
47708bbd35aSDimitry Andric class PGOCounterPromoter {
47808bbd35aSDimitry Andric public:
PGOCounterPromoter(DenseMap<Loop *,SmallVector<LoadStorePair,8>> & LoopToCands,Loop & CurLoop,LoopInfo & LI,BlockFrequencyInfo * BFI)479ca089b24SDimitry Andric PGOCounterPromoter(
480ca089b24SDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCands,
481e6d15924SDimitry Andric Loop &CurLoop, LoopInfo &LI, BlockFrequencyInfo *BFI)
4826f8fc217SDimitry Andric : LoopToCandidates(LoopToCands), L(CurLoop), LI(LI), BFI(BFI) {
48308bbd35aSDimitry Andric
484cfca06d7SDimitry Andric // Skip collection of ExitBlocks and InsertPts for loops that will not be
485cfca06d7SDimitry Andric // able to have counters promoted.
48608bbd35aSDimitry Andric SmallVector<BasicBlock *, 8> LoopExitBlocks;
48708bbd35aSDimitry Andric SmallPtrSet<BasicBlock *, 8> BlockSet;
488cfca06d7SDimitry Andric
489ca089b24SDimitry Andric L.getExitBlocks(LoopExitBlocks);
490cfca06d7SDimitry Andric if (!isPromotionPossible(&L, LoopExitBlocks))
491cfca06d7SDimitry Andric return;
49208bbd35aSDimitry Andric
49308bbd35aSDimitry Andric for (BasicBlock *ExitBlock : LoopExitBlocks) {
494b1c73532SDimitry Andric if (BlockSet.insert(ExitBlock).second &&
495b1c73532SDimitry Andric llvm::none_of(predecessors(ExitBlock), [&](const BasicBlock *Pred) {
496b1c73532SDimitry Andric return llvm::isPresplitCoroSuspendExitEdge(*Pred, *ExitBlock);
497b1c73532SDimitry Andric })) {
49808bbd35aSDimitry Andric ExitBlocks.push_back(ExitBlock);
49908bbd35aSDimitry Andric InsertPts.push_back(&*ExitBlock->getFirstInsertionPt());
50008bbd35aSDimitry Andric }
50108bbd35aSDimitry Andric }
50208bbd35aSDimitry Andric }
50308bbd35aSDimitry Andric
run(int64_t * NumPromoted)50408bbd35aSDimitry Andric bool run(int64_t *NumPromoted) {
505044eb2f6SDimitry Andric // Skip 'infinite' loops:
506044eb2f6SDimitry Andric if (ExitBlocks.size() == 0)
507044eb2f6SDimitry Andric return false;
508b60736ecSDimitry Andric
509b60736ecSDimitry Andric // Skip if any of the ExitBlocks contains a ret instruction.
510b60736ecSDimitry Andric // This is to prevent dumping of incomplete profile -- if the
511b60736ecSDimitry Andric // the loop is a long running loop and dump is called in the middle
512b60736ecSDimitry Andric // of the loop, the result profile is incomplete.
513b60736ecSDimitry Andric // FIXME: add other heuristics to detect long running loops.
514b60736ecSDimitry Andric if (SkipRetExitBlock) {
515e3b55780SDimitry Andric for (auto *BB : ExitBlocks)
516b60736ecSDimitry Andric if (isa<ReturnInst>(BB->getTerminator()))
517b60736ecSDimitry Andric return false;
518b60736ecSDimitry Andric }
519b60736ecSDimitry Andric
520ca089b24SDimitry Andric unsigned MaxProm = getMaxNumOfPromotionsInLoop(&L);
521ca089b24SDimitry Andric if (MaxProm == 0)
52208bbd35aSDimitry Andric return false;
52308bbd35aSDimitry Andric
52408bbd35aSDimitry Andric unsigned Promoted = 0;
525ca089b24SDimitry Andric for (auto &Cand : LoopToCandidates[&L]) {
52608bbd35aSDimitry Andric
52708bbd35aSDimitry Andric SmallVector<PHINode *, 4> NewPHIs;
52808bbd35aSDimitry Andric SSAUpdater SSA(&NewPHIs);
52908bbd35aSDimitry Andric Value *InitVal = ConstantInt::get(Cand.first->getType(), 0);
530ca089b24SDimitry Andric
531e6d15924SDimitry Andric // If BFI is set, we will use it to guide the promotions.
532e6d15924SDimitry Andric if (BFI) {
533e6d15924SDimitry Andric auto *BB = Cand.first->getParent();
534e6d15924SDimitry Andric auto InstrCount = BFI->getBlockProfileCount(BB);
535e6d15924SDimitry Andric if (!InstrCount)
536e6d15924SDimitry Andric continue;
537e6d15924SDimitry Andric auto PreheaderCount = BFI->getBlockProfileCount(L.getLoopPreheader());
538e6d15924SDimitry Andric // If the average loop trip count is not greater than 1.5, we skip
539e6d15924SDimitry Andric // promotion.
540145449b1SDimitry Andric if (PreheaderCount && (*PreheaderCount * 3) >= (*InstrCount * 2))
541e6d15924SDimitry Andric continue;
542e6d15924SDimitry Andric }
543e6d15924SDimitry Andric
54408bbd35aSDimitry Andric PGOCounterPromoterHelper Promoter(Cand.first, Cand.second, SSA, InitVal,
545ca089b24SDimitry Andric L.getLoopPreheader(), ExitBlocks,
546ca089b24SDimitry Andric InsertPts, LoopToCandidates, LI);
54708bbd35aSDimitry Andric Promoter.run(SmallVector<Instruction *, 2>({Cand.first, Cand.second}));
54808bbd35aSDimitry Andric Promoted++;
549ca089b24SDimitry Andric if (Promoted >= MaxProm)
55008bbd35aSDimitry Andric break;
551ca089b24SDimitry Andric
55208bbd35aSDimitry Andric (*NumPromoted)++;
55308bbd35aSDimitry Andric if (MaxNumOfPromotions != -1 && *NumPromoted >= MaxNumOfPromotions)
55408bbd35aSDimitry Andric break;
55508bbd35aSDimitry Andric }
55608bbd35aSDimitry Andric
557eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << Promoted << " counters promoted for loop (depth="
558ca089b24SDimitry Andric << L.getLoopDepth() << ")\n");
55908bbd35aSDimitry Andric return Promoted != 0;
56008bbd35aSDimitry Andric }
56108bbd35aSDimitry Andric
56208bbd35aSDimitry Andric private:
allowSpeculativeCounterPromotion(Loop * LP)563ca089b24SDimitry Andric bool allowSpeculativeCounterPromotion(Loop *LP) {
564ca089b24SDimitry Andric SmallVector<BasicBlock *, 8> ExitingBlocks;
565ca089b24SDimitry Andric L.getExitingBlocks(ExitingBlocks);
566ca089b24SDimitry Andric // Not considierered speculative.
567ca089b24SDimitry Andric if (ExitingBlocks.size() == 1)
568ca089b24SDimitry Andric return true;
569ca089b24SDimitry Andric if (ExitingBlocks.size() > SpeculativeCounterPromotionMaxExiting)
570ca089b24SDimitry Andric return false;
571ca089b24SDimitry Andric return true;
572ca089b24SDimitry Andric }
573ca089b24SDimitry Andric
574cfca06d7SDimitry Andric // Check whether the loop satisfies the basic conditions needed to perform
575cfca06d7SDimitry Andric // Counter Promotions.
576f65dcba8SDimitry Andric bool
isPromotionPossible(Loop * LP,const SmallVectorImpl<BasicBlock * > & LoopExitBlocks)577f65dcba8SDimitry Andric isPromotionPossible(Loop *LP,
578cfca06d7SDimitry Andric const SmallVectorImpl<BasicBlock *> &LoopExitBlocks) {
579ca089b24SDimitry Andric // We can't insert into a catchswitch.
580ca089b24SDimitry Andric if (llvm::any_of(LoopExitBlocks, [](BasicBlock *Exit) {
581ca089b24SDimitry Andric return isa<CatchSwitchInst>(Exit->getTerminator());
582ca089b24SDimitry Andric }))
583cfca06d7SDimitry Andric return false;
584ca089b24SDimitry Andric
585ca089b24SDimitry Andric if (!LP->hasDedicatedExits())
586cfca06d7SDimitry Andric return false;
587ca089b24SDimitry Andric
588ca089b24SDimitry Andric BasicBlock *PH = LP->getLoopPreheader();
589ca089b24SDimitry Andric if (!PH)
590cfca06d7SDimitry Andric return false;
591cfca06d7SDimitry Andric
592cfca06d7SDimitry Andric return true;
593cfca06d7SDimitry Andric }
594cfca06d7SDimitry Andric
595cfca06d7SDimitry Andric // Returns the max number of Counter Promotions for LP.
getMaxNumOfPromotionsInLoop(Loop * LP)596cfca06d7SDimitry Andric unsigned getMaxNumOfPromotionsInLoop(Loop *LP) {
597cfca06d7SDimitry Andric SmallVector<BasicBlock *, 8> LoopExitBlocks;
598cfca06d7SDimitry Andric LP->getExitBlocks(LoopExitBlocks);
599cfca06d7SDimitry Andric if (!isPromotionPossible(LP, LoopExitBlocks))
600ca089b24SDimitry Andric return 0;
601ca089b24SDimitry Andric
602ca089b24SDimitry Andric SmallVector<BasicBlock *, 8> ExitingBlocks;
603ca089b24SDimitry Andric LP->getExitingBlocks(ExitingBlocks);
604e6d15924SDimitry Andric
605e6d15924SDimitry Andric // If BFI is set, we do more aggressive promotions based on BFI.
606e6d15924SDimitry Andric if (BFI)
607e6d15924SDimitry Andric return (unsigned)-1;
608e6d15924SDimitry Andric
609ca089b24SDimitry Andric // Not considierered speculative.
610ca089b24SDimitry Andric if (ExitingBlocks.size() == 1)
611ca089b24SDimitry Andric return MaxNumOfPromotionsPerLoop;
612ca089b24SDimitry Andric
613ca089b24SDimitry Andric if (ExitingBlocks.size() > SpeculativeCounterPromotionMaxExiting)
614ca089b24SDimitry Andric return 0;
615ca089b24SDimitry Andric
616ca089b24SDimitry Andric // Whether the target block is in a loop does not matter:
617ca089b24SDimitry Andric if (SpeculativeCounterPromotionToLoop)
618ca089b24SDimitry Andric return MaxNumOfPromotionsPerLoop;
619ca089b24SDimitry Andric
620ca089b24SDimitry Andric // Now check the target block:
621ca089b24SDimitry Andric unsigned MaxProm = MaxNumOfPromotionsPerLoop;
622ca089b24SDimitry Andric for (auto *TargetBlock : LoopExitBlocks) {
623ca089b24SDimitry Andric auto *TargetLoop = LI.getLoopFor(TargetBlock);
624ca089b24SDimitry Andric if (!TargetLoop)
625ca089b24SDimitry Andric continue;
626ca089b24SDimitry Andric unsigned MaxPromForTarget = getMaxNumOfPromotionsInLoop(TargetLoop);
627ca089b24SDimitry Andric unsigned PendingCandsInTarget = LoopToCandidates[TargetLoop].size();
628ca089b24SDimitry Andric MaxProm =
629ca089b24SDimitry Andric std::min(MaxProm, std::max(MaxPromForTarget, PendingCandsInTarget) -
630ca089b24SDimitry Andric PendingCandsInTarget);
631ca089b24SDimitry Andric }
632ca089b24SDimitry Andric return MaxProm;
633ca089b24SDimitry Andric }
634ca089b24SDimitry Andric
635ca089b24SDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCandidates;
63608bbd35aSDimitry Andric SmallVector<BasicBlock *, 8> ExitBlocks;
63708bbd35aSDimitry Andric SmallVector<Instruction *, 8> InsertPts;
638ca089b24SDimitry Andric Loop &L;
639ca089b24SDimitry Andric LoopInfo &LI;
640e6d15924SDimitry Andric BlockFrequencyInfo *BFI;
64108bbd35aSDimitry Andric };
64208bbd35aSDimitry Andric
643b60736ecSDimitry Andric enum class ValueProfilingCallType {
644b60736ecSDimitry Andric // Individual values are tracked. Currently used for indiret call target
645b60736ecSDimitry Andric // profiling.
646b60736ecSDimitry Andric Default,
647b60736ecSDimitry Andric
648b60736ecSDimitry Andric // MemOp: the memop size value profiling.
649b60736ecSDimitry Andric MemOp
650b60736ecSDimitry Andric };
651b60736ecSDimitry Andric
65271d5a254SDimitry Andric } // end anonymous namespace
65367c32a98SDimitry Andric
run(Module & M,ModuleAnalysisManager & AM)654312c0ed1SDimitry Andric PreservedAnalyses InstrProfilingLoweringPass::run(Module &M,
655312c0ed1SDimitry Andric ModuleAnalysisManager &AM) {
6561d5ae102SDimitry Andric FunctionAnalysisManager &FAM =
6571d5ae102SDimitry Andric AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
6581d5ae102SDimitry Andric auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
6591d5ae102SDimitry Andric return FAM.getResult<TargetLibraryAnalysis>(F);
6601d5ae102SDimitry Andric };
661312c0ed1SDimitry Andric InstrLowerer Lowerer(M, Options, GetTLI, IsCS);
662312c0ed1SDimitry Andric if (!Lowerer.lower())
66301095a5dSDimitry Andric return PreservedAnalyses::all();
66401095a5dSDimitry Andric
66501095a5dSDimitry Andric return PreservedAnalyses::none();
66601095a5dSDimitry Andric }
66701095a5dSDimitry Andric
668ac9a064cSDimitry Andric //
669ac9a064cSDimitry Andric // Perform instrumentation sampling.
670ac9a064cSDimitry Andric //
671ac9a064cSDimitry Andric // There are 3 favors of sampling:
672ac9a064cSDimitry Andric // (1) Full burst sampling: We transform:
673ac9a064cSDimitry Andric // Increment_Instruction;
674ac9a064cSDimitry Andric // to:
675ac9a064cSDimitry Andric // if (__llvm_profile_sampling__ < SampledInstrBurstDuration) {
676ac9a064cSDimitry Andric // Increment_Instruction;
677ac9a064cSDimitry Andric // }
678ac9a064cSDimitry Andric // __llvm_profile_sampling__ += 1;
679ac9a064cSDimitry Andric // if (__llvm_profile_sampling__ >= SampledInstrPeriod) {
680ac9a064cSDimitry Andric // __llvm_profile_sampling__ = 0;
681ac9a064cSDimitry Andric // }
682ac9a064cSDimitry Andric //
683ac9a064cSDimitry Andric // "__llvm_profile_sampling__" is a thread-local global shared by all PGO
684ac9a064cSDimitry Andric // counters (value-instrumentation and edge instrumentation).
685ac9a064cSDimitry Andric //
686ac9a064cSDimitry Andric // (2) Fast burst sampling:
687ac9a064cSDimitry Andric // "__llvm_profile_sampling__" variable is an unsigned type, meaning it will
688ac9a064cSDimitry Andric // wrap around to zero when overflows. In this case, the second check is
689ac9a064cSDimitry Andric // unnecessary, so we won't generate check2 when the SampledInstrPeriod is
690ac9a064cSDimitry Andric // set to 65535 (64K - 1). The code after:
691ac9a064cSDimitry Andric // if (__llvm_profile_sampling__ < SampledInstrBurstDuration) {
692ac9a064cSDimitry Andric // Increment_Instruction;
693ac9a064cSDimitry Andric // }
694ac9a064cSDimitry Andric // __llvm_profile_sampling__ += 1;
695ac9a064cSDimitry Andric //
696ac9a064cSDimitry Andric // (3) Simple sampling:
697ac9a064cSDimitry Andric // When SampledInstrBurstDuration sets to 1, we do a simple sampling:
698ac9a064cSDimitry Andric // __llvm_profile_sampling__ += 1;
699ac9a064cSDimitry Andric // if (__llvm_profile_sampling__ >= SampledInstrPeriod) {
700ac9a064cSDimitry Andric // __llvm_profile_sampling__ = 0;
701ac9a064cSDimitry Andric // Increment_Instruction;
702ac9a064cSDimitry Andric // }
703ac9a064cSDimitry Andric //
704ac9a064cSDimitry Andric // Note that, the code snippet after the transformation can still be counter
705ac9a064cSDimitry Andric // promoted. However, with sampling enabled, counter updates are expected to
706ac9a064cSDimitry Andric // be infrequent, making the benefits of counter promotion negligible.
707ac9a064cSDimitry Andric // Moreover, counter promotion can potentially cause issues in server
708ac9a064cSDimitry Andric // applications, particularly when the counters are dumped without a clean
709ac9a064cSDimitry Andric // exit. To mitigate this risk, counter promotion is disabled by default when
710ac9a064cSDimitry Andric // sampling is enabled. This behavior can be overridden using the internal
711ac9a064cSDimitry Andric // option.
doSampling(Instruction * I)712ac9a064cSDimitry Andric void InstrLowerer::doSampling(Instruction *I) {
713ac9a064cSDimitry Andric if (!isSamplingEnabled())
714ac9a064cSDimitry Andric return;
715ac9a064cSDimitry Andric
716ac9a064cSDimitry Andric unsigned SampledBurstDuration = SampledInstrBurstDuration.getValue();
717ac9a064cSDimitry Andric unsigned SampledPeriod = SampledInstrPeriod.getValue();
718ac9a064cSDimitry Andric if (SampledBurstDuration >= SampledPeriod) {
719ac9a064cSDimitry Andric report_fatal_error(
720ac9a064cSDimitry Andric "SampledPeriod needs to be greater than SampledBurstDuration");
721ac9a064cSDimitry Andric }
722ac9a064cSDimitry Andric bool UseShort = (SampledPeriod <= USHRT_MAX);
723ac9a064cSDimitry Andric bool IsSimpleSampling = (SampledBurstDuration == 1);
724ac9a064cSDimitry Andric // If (SampledBurstDuration == 1 && SampledPeriod == 65535), generate
725ac9a064cSDimitry Andric // the simple sampling style code.
726ac9a064cSDimitry Andric bool IsFastSampling = (!IsSimpleSampling && SampledPeriod == 65535);
727ac9a064cSDimitry Andric
728ac9a064cSDimitry Andric auto GetConstant = [UseShort](IRBuilder<> &Builder, uint32_t C) {
729ac9a064cSDimitry Andric if (UseShort)
730ac9a064cSDimitry Andric return Builder.getInt16(C);
731ac9a064cSDimitry Andric else
732ac9a064cSDimitry Andric return Builder.getInt32(C);
733ac9a064cSDimitry Andric };
734ac9a064cSDimitry Andric
735ac9a064cSDimitry Andric IntegerType *SamplingVarTy;
736ac9a064cSDimitry Andric if (UseShort)
737ac9a064cSDimitry Andric SamplingVarTy = Type::getInt16Ty(M.getContext());
738ac9a064cSDimitry Andric else
739ac9a064cSDimitry Andric SamplingVarTy = Type::getInt32Ty(M.getContext());
740ac9a064cSDimitry Andric auto *SamplingVar =
741ac9a064cSDimitry Andric M.getGlobalVariable(INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_SAMPLING_VAR));
742ac9a064cSDimitry Andric assert(SamplingVar && "SamplingVar not set properly");
743ac9a064cSDimitry Andric
744ac9a064cSDimitry Andric // Create the condition for checking the burst duration.
745ac9a064cSDimitry Andric Instruction *SamplingVarIncr;
746ac9a064cSDimitry Andric Value *NewSamplingVarVal;
747ac9a064cSDimitry Andric MDBuilder MDB(I->getContext());
748ac9a064cSDimitry Andric MDNode *BranchWeight;
749ac9a064cSDimitry Andric IRBuilder<> CondBuilder(I);
750ac9a064cSDimitry Andric auto *LoadSamplingVar = CondBuilder.CreateLoad(SamplingVarTy, SamplingVar);
751ac9a064cSDimitry Andric if (IsSimpleSampling) {
752ac9a064cSDimitry Andric // For the simple sampling, just create the load and increments.
753ac9a064cSDimitry Andric IRBuilder<> IncBuilder(I);
754ac9a064cSDimitry Andric NewSamplingVarVal =
755ac9a064cSDimitry Andric IncBuilder.CreateAdd(LoadSamplingVar, GetConstant(IncBuilder, 1));
756ac9a064cSDimitry Andric SamplingVarIncr = IncBuilder.CreateStore(NewSamplingVarVal, SamplingVar);
757ac9a064cSDimitry Andric } else {
758ac9a064cSDimitry Andric // For the bust-sampling, create the conditonal update.
759ac9a064cSDimitry Andric auto *DurationCond = CondBuilder.CreateICmpULE(
760ac9a064cSDimitry Andric LoadSamplingVar, GetConstant(CondBuilder, SampledBurstDuration));
761ac9a064cSDimitry Andric BranchWeight = MDB.createBranchWeights(
762ac9a064cSDimitry Andric SampledBurstDuration, SampledPeriod + 1 - SampledBurstDuration);
763ac9a064cSDimitry Andric Instruction *ThenTerm = SplitBlockAndInsertIfThen(
764ac9a064cSDimitry Andric DurationCond, I, /* Unreachable */ false, BranchWeight);
765ac9a064cSDimitry Andric IRBuilder<> IncBuilder(I);
766ac9a064cSDimitry Andric NewSamplingVarVal =
767ac9a064cSDimitry Andric IncBuilder.CreateAdd(LoadSamplingVar, GetConstant(IncBuilder, 1));
768ac9a064cSDimitry Andric SamplingVarIncr = IncBuilder.CreateStore(NewSamplingVarVal, SamplingVar);
769ac9a064cSDimitry Andric I->moveBefore(ThenTerm);
770ac9a064cSDimitry Andric }
771ac9a064cSDimitry Andric
772ac9a064cSDimitry Andric if (IsFastSampling)
773ac9a064cSDimitry Andric return;
774ac9a064cSDimitry Andric
775ac9a064cSDimitry Andric // Create the condtion for checking the period.
776ac9a064cSDimitry Andric Instruction *ThenTerm, *ElseTerm;
777ac9a064cSDimitry Andric IRBuilder<> PeriodCondBuilder(SamplingVarIncr);
778ac9a064cSDimitry Andric auto *PeriodCond = PeriodCondBuilder.CreateICmpUGE(
779ac9a064cSDimitry Andric NewSamplingVarVal, GetConstant(PeriodCondBuilder, SampledPeriod));
780ac9a064cSDimitry Andric BranchWeight = MDB.createBranchWeights(1, SampledPeriod);
781ac9a064cSDimitry Andric SplitBlockAndInsertIfThenElse(PeriodCond, SamplingVarIncr, &ThenTerm,
782ac9a064cSDimitry Andric &ElseTerm, BranchWeight);
783ac9a064cSDimitry Andric
784ac9a064cSDimitry Andric // For the simple sampling, the counter update happens in sampling var reset.
785ac9a064cSDimitry Andric if (IsSimpleSampling)
786ac9a064cSDimitry Andric I->moveBefore(ThenTerm);
787ac9a064cSDimitry Andric
788ac9a064cSDimitry Andric IRBuilder<> ResetBuilder(ThenTerm);
789ac9a064cSDimitry Andric ResetBuilder.CreateStore(GetConstant(ResetBuilder, 0), SamplingVar);
790ac9a064cSDimitry Andric SamplingVarIncr->moveBefore(ElseTerm);
791ac9a064cSDimitry Andric }
792ac9a064cSDimitry Andric
lowerIntrinsics(Function * F)793312c0ed1SDimitry Andric bool InstrLowerer::lowerIntrinsics(Function *F) {
79408bbd35aSDimitry Andric bool MadeChange = false;
79508bbd35aSDimitry Andric PromotionCandidates.clear();
796ac9a064cSDimitry Andric SmallVector<InstrProfInstBase *, 8> InstrProfInsts;
797ac9a064cSDimitry Andric
798ac9a064cSDimitry Andric // To ensure compatibility with sampling, we save the intrinsics into
799ac9a064cSDimitry Andric // a buffer to prevent potential breakage of the iterator (as the
800ac9a064cSDimitry Andric // intrinsics will be moved to a different BB).
80108bbd35aSDimitry Andric for (BasicBlock &BB : *F) {
802c0981da4SDimitry Andric for (Instruction &Instr : llvm::make_early_inc_range(BB)) {
803ac9a064cSDimitry Andric if (auto *IP = dyn_cast<InstrProfInstBase>(&Instr))
804ac9a064cSDimitry Andric InstrProfInsts.push_back(IP);
805ac9a064cSDimitry Andric }
806ac9a064cSDimitry Andric }
807ac9a064cSDimitry Andric
808ac9a064cSDimitry Andric for (auto *Instr : InstrProfInsts) {
809ac9a064cSDimitry Andric doSampling(Instr);
810ac9a064cSDimitry Andric if (auto *IPIS = dyn_cast<InstrProfIncrementInstStep>(Instr)) {
8116f8fc217SDimitry Andric lowerIncrement(IPIS);
81208bbd35aSDimitry Andric MadeChange = true;
813ac9a064cSDimitry Andric } else if (auto *IPI = dyn_cast<InstrProfIncrementInst>(Instr)) {
8146f8fc217SDimitry Andric lowerIncrement(IPI);
8156f8fc217SDimitry Andric MadeChange = true;
816ac9a064cSDimitry Andric } else if (auto *IPC = dyn_cast<InstrProfTimestampInst>(Instr)) {
8177fa27ce4SDimitry Andric lowerTimestamp(IPC);
8187fa27ce4SDimitry Andric MadeChange = true;
819ac9a064cSDimitry Andric } else if (auto *IPC = dyn_cast<InstrProfCoverInst>(Instr)) {
820ecbca9f5SDimitry Andric lowerCover(IPC);
821ecbca9f5SDimitry Andric MadeChange = true;
822ac9a064cSDimitry Andric } else if (auto *IPVP = dyn_cast<InstrProfValueProfileInst>(Instr)) {
8236f8fc217SDimitry Andric lowerValueProfileInst(IPVP);
82408bbd35aSDimitry Andric MadeChange = true;
825ac9a064cSDimitry Andric } else if (auto *IPMP = dyn_cast<InstrProfMCDCBitmapParameters>(Instr)) {
826b1c73532SDimitry Andric IPMP->eraseFromParent();
827b1c73532SDimitry Andric MadeChange = true;
828ac9a064cSDimitry Andric } else if (auto *IPBU = dyn_cast<InstrProfMCDCTVBitmapUpdate>(Instr)) {
829b1c73532SDimitry Andric lowerMCDCTestVectorBitmapUpdate(IPBU);
830b1c73532SDimitry Andric MadeChange = true;
83108bbd35aSDimitry Andric }
83208bbd35aSDimitry Andric }
83308bbd35aSDimitry Andric
83408bbd35aSDimitry Andric if (!MadeChange)
83508bbd35aSDimitry Andric return false;
83608bbd35aSDimitry Andric
83708bbd35aSDimitry Andric promoteCounterLoadStores(F);
83808bbd35aSDimitry Andric return true;
83908bbd35aSDimitry Andric }
84008bbd35aSDimitry Andric
isRuntimeCounterRelocationEnabled() const841312c0ed1SDimitry Andric bool InstrLowerer::isRuntimeCounterRelocationEnabled() const {
842344a3780SDimitry Andric // Mach-O don't support weak external references.
843344a3780SDimitry Andric if (TT.isOSBinFormatMachO())
844344a3780SDimitry Andric return false;
845344a3780SDimitry Andric
846cfca06d7SDimitry Andric if (RuntimeCounterRelocation.getNumOccurrences() > 0)
847cfca06d7SDimitry Andric return RuntimeCounterRelocation;
848cfca06d7SDimitry Andric
849344a3780SDimitry Andric // Fuchsia uses runtime counter relocation by default.
850cfca06d7SDimitry Andric return TT.isOSFuchsia();
851cfca06d7SDimitry Andric }
852cfca06d7SDimitry Andric
isSamplingEnabled() const853ac9a064cSDimitry Andric bool InstrLowerer::isSamplingEnabled() const {
854ac9a064cSDimitry Andric if (SampledInstr.getNumOccurrences() > 0)
855ac9a064cSDimitry Andric return SampledInstr;
856ac9a064cSDimitry Andric return Options.Sampling;
857ac9a064cSDimitry Andric }
858ac9a064cSDimitry Andric
isCounterPromotionEnabled() const859312c0ed1SDimitry Andric bool InstrLowerer::isCounterPromotionEnabled() const {
86008bbd35aSDimitry Andric if (DoCounterPromotion.getNumOccurrences() > 0)
86108bbd35aSDimitry Andric return DoCounterPromotion;
86208bbd35aSDimitry Andric
86308bbd35aSDimitry Andric return Options.DoCounterPromotion;
86408bbd35aSDimitry Andric }
86508bbd35aSDimitry Andric
promoteCounterLoadStores(Function * F)866312c0ed1SDimitry Andric void InstrLowerer::promoteCounterLoadStores(Function *F) {
86708bbd35aSDimitry Andric if (!isCounterPromotionEnabled())
86808bbd35aSDimitry Andric return;
86908bbd35aSDimitry Andric
87008bbd35aSDimitry Andric DominatorTree DT(*F);
87108bbd35aSDimitry Andric LoopInfo LI(DT);
87208bbd35aSDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> LoopPromotionCandidates;
87308bbd35aSDimitry Andric
874e6d15924SDimitry Andric std::unique_ptr<BlockFrequencyInfo> BFI;
875e6d15924SDimitry Andric if (Options.UseBFIInPromotion) {
876e6d15924SDimitry Andric std::unique_ptr<BranchProbabilityInfo> BPI;
8771d5ae102SDimitry Andric BPI.reset(new BranchProbabilityInfo(*F, LI, &GetTLI(*F)));
878e6d15924SDimitry Andric BFI.reset(new BlockFrequencyInfo(*F, *BPI, LI));
879e6d15924SDimitry Andric }
880e6d15924SDimitry Andric
88108bbd35aSDimitry Andric for (const auto &LoadStore : PromotionCandidates) {
88208bbd35aSDimitry Andric auto *CounterLoad = LoadStore.first;
88308bbd35aSDimitry Andric auto *CounterStore = LoadStore.second;
88408bbd35aSDimitry Andric BasicBlock *BB = CounterLoad->getParent();
88508bbd35aSDimitry Andric Loop *ParentLoop = LI.getLoopFor(BB);
88608bbd35aSDimitry Andric if (!ParentLoop)
88708bbd35aSDimitry Andric continue;
88808bbd35aSDimitry Andric LoopPromotionCandidates[ParentLoop].emplace_back(CounterLoad, CounterStore);
88908bbd35aSDimitry Andric }
89008bbd35aSDimitry Andric
89108bbd35aSDimitry Andric SmallVector<Loop *, 4> Loops = LI.getLoopsInPreorder();
89208bbd35aSDimitry Andric
893ca089b24SDimitry Andric // Do a post-order traversal of the loops so that counter updates can be
894ca089b24SDimitry Andric // iteratively hoisted outside the loop nest.
895ca089b24SDimitry Andric for (auto *Loop : llvm::reverse(Loops)) {
896e6d15924SDimitry Andric PGOCounterPromoter Promoter(LoopPromotionCandidates, *Loop, LI, BFI.get());
89708bbd35aSDimitry Andric Promoter.run(&TotalCountersPromoted);
89808bbd35aSDimitry Andric }
89908bbd35aSDimitry Andric }
90008bbd35aSDimitry Andric
needsRuntimeHookUnconditionally(const Triple & TT)901c0981da4SDimitry Andric static bool needsRuntimeHookUnconditionally(const Triple &TT) {
902c0981da4SDimitry Andric // On Fuchsia, we only need runtime hook if any counters are present.
903c0981da4SDimitry Andric if (TT.isOSFuchsia())
904c0981da4SDimitry Andric return false;
905c0981da4SDimitry Andric
906c0981da4SDimitry Andric return true;
907c0981da4SDimitry Andric }
908c0981da4SDimitry Andric
909eb11fae6SDimitry Andric /// Check if the module contains uses of any profiling intrinsics.
containsProfilingIntrinsics(Module & M)910eb11fae6SDimitry Andric static bool containsProfilingIntrinsics(Module &M) {
9116f8fc217SDimitry Andric auto containsIntrinsic = [&](int ID) {
9126f8fc217SDimitry Andric if (auto *F = M.getFunction(Intrinsic::getName(ID)))
9136f8fc217SDimitry Andric return !F->use_empty();
914eb11fae6SDimitry Andric return false;
9156f8fc217SDimitry Andric };
916ecbca9f5SDimitry Andric return containsIntrinsic(llvm::Intrinsic::instrprof_cover) ||
917ecbca9f5SDimitry Andric containsIntrinsic(llvm::Intrinsic::instrprof_increment) ||
9186f8fc217SDimitry Andric containsIntrinsic(llvm::Intrinsic::instrprof_increment_step) ||
9197fa27ce4SDimitry Andric containsIntrinsic(llvm::Intrinsic::instrprof_timestamp) ||
9206f8fc217SDimitry Andric containsIntrinsic(llvm::Intrinsic::instrprof_value_profile);
921eb11fae6SDimitry Andric }
92267c32a98SDimitry Andric
lower()923312c0ed1SDimitry Andric bool InstrLowerer::lower() {
924c0981da4SDimitry Andric bool MadeChange = false;
925e3b55780SDimitry Andric bool NeedsRuntimeHook = needsRuntimeHookUnconditionally(TT);
926e3b55780SDimitry Andric if (NeedsRuntimeHook)
927c0981da4SDimitry Andric MadeChange = emitRuntimeHook();
928eb11fae6SDimitry Andric
929ac9a064cSDimitry Andric if (!IsCS && isSamplingEnabled())
930ac9a064cSDimitry Andric createProfileSamplingVar(M);
931ac9a064cSDimitry Andric
932e3b55780SDimitry Andric bool ContainsProfiling = containsProfilingIntrinsics(M);
933eb11fae6SDimitry Andric GlobalVariable *CoverageNamesVar =
934eb11fae6SDimitry Andric M.getNamedGlobal(getCoverageUnusedNamesVarName());
935e3b55780SDimitry Andric // Improve compile time by avoiding linear scans when there is no work.
936e3b55780SDimitry Andric if (!ContainsProfiling && !CoverageNamesVar)
937eb11fae6SDimitry Andric return MadeChange;
938eb11fae6SDimitry Andric
939dd58ef01SDimitry Andric // We did not know how many value sites there would be inside
940dd58ef01SDimitry Andric // the instrumented function. This is counting the number of instrumented
941dd58ef01SDimitry Andric // target value sites to enter it as field in the profile data variable.
94201095a5dSDimitry Andric for (Function &F : M) {
943b1c73532SDimitry Andric InstrProfCntrInstBase *FirstProfInst = nullptr;
944b1c73532SDimitry Andric for (BasicBlock &BB : F) {
945b1c73532SDimitry Andric for (auto I = BB.begin(), E = BB.end(); I != E; I++) {
94601095a5dSDimitry Andric if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(I))
947dd58ef01SDimitry Andric computeNumValueSiteCounts(Ind);
948b1c73532SDimitry Andric else {
949b1c73532SDimitry Andric if (FirstProfInst == nullptr &&
9507fa27ce4SDimitry Andric (isa<InstrProfIncrementInst>(I) || isa<InstrProfCoverInst>(I)))
951b1c73532SDimitry Andric FirstProfInst = dyn_cast<InstrProfCntrInstBase>(I);
952b1c73532SDimitry Andric // If the MCDCBitmapParameters intrinsic seen, create the bitmaps.
953b1c73532SDimitry Andric if (const auto &Params = dyn_cast<InstrProfMCDCBitmapParameters>(I))
954b1c73532SDimitry Andric static_cast<void>(getOrCreateRegionBitmaps(Params));
955b1c73532SDimitry Andric }
956b1c73532SDimitry Andric }
957b1c73532SDimitry Andric }
95801095a5dSDimitry Andric
959b1c73532SDimitry Andric // Use a profile intrinsic to create the region counters and data variable.
960b1c73532SDimitry Andric // Also create the data variable based on the MCDCParams.
961b1c73532SDimitry Andric if (FirstProfInst != nullptr) {
9627fa27ce4SDimitry Andric static_cast<void>(getOrCreateRegionCounters(FirstProfInst));
96301095a5dSDimitry Andric }
964b1c73532SDimitry Andric }
965dd58ef01SDimitry Andric
966ac9a064cSDimitry Andric if (EnableVTableValueProfiling)
967ac9a064cSDimitry Andric for (GlobalVariable &GV : M.globals())
968ac9a064cSDimitry Andric // Global variables with type metadata are virtual table variables.
969ac9a064cSDimitry Andric if (GV.hasMetadata(LLVMContext::MD_type))
970ac9a064cSDimitry Andric getOrCreateVTableProfData(&GV);
971ac9a064cSDimitry Andric
972dd58ef01SDimitry Andric for (Function &F : M)
97308bbd35aSDimitry Andric MadeChange |= lowerIntrinsics(&F);
974dd58ef01SDimitry Andric
975eb11fae6SDimitry Andric if (CoverageNamesVar) {
976050e163aSDimitry Andric lowerCoverageData(CoverageNamesVar);
977608e6659SDimitry Andric MadeChange = true;
978608e6659SDimitry Andric }
979dd58ef01SDimitry Andric
98067c32a98SDimitry Andric if (!MadeChange)
98167c32a98SDimitry Andric return false;
98267c32a98SDimitry Andric
98301095a5dSDimitry Andric emitVNodes();
98401095a5dSDimitry Andric emitNameData();
985ac9a064cSDimitry Andric emitVTableNames();
986e3b55780SDimitry Andric
987e3b55780SDimitry Andric // Emit runtime hook for the cases where the target does not unconditionally
988e3b55780SDimitry Andric // require pulling in profile runtime, and coverage is enabled on code that is
989e3b55780SDimitry Andric // not eliminated by the front-end, e.g. unused functions with internal
990e3b55780SDimitry Andric // linkage.
991e3b55780SDimitry Andric if (!NeedsRuntimeHook && ContainsProfiling)
992c0981da4SDimitry Andric emitRuntimeHook();
993e3b55780SDimitry Andric
99467c32a98SDimitry Andric emitRegistration();
99567c32a98SDimitry Andric emitUses();
99667c32a98SDimitry Andric emitInitialization();
99767c32a98SDimitry Andric return true;
99867c32a98SDimitry Andric }
99967c32a98SDimitry Andric
getOrInsertValueProfilingCall(Module & M,const TargetLibraryInfo & TLI,ValueProfilingCallType CallType=ValueProfilingCallType::Default)1000b60736ecSDimitry Andric static FunctionCallee getOrInsertValueProfilingCall(
1001b60736ecSDimitry Andric Module &M, const TargetLibraryInfo &TLI,
1002b60736ecSDimitry Andric ValueProfilingCallType CallType = ValueProfilingCallType::Default) {
1003dd58ef01SDimitry Andric LLVMContext &Ctx = M.getContext();
1004dd58ef01SDimitry Andric auto *ReturnTy = Type::getVoidTy(M.getContext());
100571d5a254SDimitry Andric
1006e6d15924SDimitry Andric AttributeList AL;
1007e6d15924SDimitry Andric if (auto AK = TLI.getExtAttrForI32Param(false))
1008e6d15924SDimitry Andric AL = AL.addParamAttribute(M.getContext(), 2, AK);
1009e6d15924SDimitry Andric
1010b60736ecSDimitry Andric assert((CallType == ValueProfilingCallType::Default ||
1011b60736ecSDimitry Andric CallType == ValueProfilingCallType::MemOp) &&
1012b60736ecSDimitry Andric "Must be Default or MemOp");
1013dd58ef01SDimitry Andric Type *ParamTypes[] = {
1014dd58ef01SDimitry Andric #define VALUE_PROF_FUNC_PARAM(ParamType, ParamName, ParamLLVMType) ParamLLVMType
1015dd58ef01SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1016dd58ef01SDimitry Andric };
1017dd58ef01SDimitry Andric auto *ValueProfilingCallTy =
1018e3b55780SDimitry Andric FunctionType::get(ReturnTy, ArrayRef(ParamTypes), false);
1019b60736ecSDimitry Andric StringRef FuncName = CallType == ValueProfilingCallType::Default
1020b60736ecSDimitry Andric ? getInstrProfValueProfFuncName()
1021b60736ecSDimitry Andric : getInstrProfValueProfMemOpFuncName();
1022b60736ecSDimitry Andric return M.getOrInsertFunction(FuncName, ValueProfilingCallTy, AL);
1023dd58ef01SDimitry Andric }
1024dd58ef01SDimitry Andric
computeNumValueSiteCounts(InstrProfValueProfileInst * Ind)1025312c0ed1SDimitry Andric void InstrLowerer::computeNumValueSiteCounts(InstrProfValueProfileInst *Ind) {
1026dd58ef01SDimitry Andric GlobalVariable *Name = Ind->getName();
1027dd58ef01SDimitry Andric uint64_t ValueKind = Ind->getValueKind()->getZExtValue();
1028dd58ef01SDimitry Andric uint64_t Index = Ind->getIndex()->getZExtValue();
1029f65dcba8SDimitry Andric auto &PD = ProfileDataMap[Name];
1030f65dcba8SDimitry Andric PD.NumValueSites[ValueKind] =
1031f65dcba8SDimitry Andric std::max(PD.NumValueSites[ValueKind], (uint32_t)(Index + 1));
1032dd58ef01SDimitry Andric }
1033dd58ef01SDimitry Andric
lowerValueProfileInst(InstrProfValueProfileInst * Ind)1034312c0ed1SDimitry Andric void InstrLowerer::lowerValueProfileInst(InstrProfValueProfileInst *Ind) {
103577fc4c14SDimitry Andric // TODO: Value profiling heavily depends on the data section which is omitted
103677fc4c14SDimitry Andric // in lightweight mode. We need to move the value profile pointer to the
103777fc4c14SDimitry Andric // Counter struct to get this working.
103877fc4c14SDimitry Andric assert(
1039312c0ed1SDimitry Andric !DebugInfoCorrelate && ProfileCorrelate == InstrProfCorrelator::NONE &&
104077fc4c14SDimitry Andric "Value profiling is not yet supported with lightweight instrumentation");
1041dd58ef01SDimitry Andric GlobalVariable *Name = Ind->getName();
1042dd58ef01SDimitry Andric auto It = ProfileDataMap.find(Name);
1043dd58ef01SDimitry Andric assert(It != ProfileDataMap.end() && It->second.DataVar &&
1044dd58ef01SDimitry Andric "value profiling detected in function with no counter incerement");
1045dd58ef01SDimitry Andric
1046dd58ef01SDimitry Andric GlobalVariable *DataVar = It->second.DataVar;
1047dd58ef01SDimitry Andric uint64_t ValueKind = Ind->getValueKind()->getZExtValue();
1048dd58ef01SDimitry Andric uint64_t Index = Ind->getIndex()->getZExtValue();
1049dd58ef01SDimitry Andric for (uint32_t Kind = IPVK_First; Kind < ValueKind; ++Kind)
1050dd58ef01SDimitry Andric Index += It->second.NumValueSites[Kind];
1051dd58ef01SDimitry Andric
1052dd58ef01SDimitry Andric IRBuilder<> Builder(Ind);
1053b60736ecSDimitry Andric bool IsMemOpSize = (Ind->getValueKind()->getZExtValue() ==
105471d5a254SDimitry Andric llvm::InstrProfValueKind::IPVK_MemOPSize);
105571d5a254SDimitry Andric CallInst *Call = nullptr;
10561d5ae102SDimitry Andric auto *TLI = &GetTLI(*Ind->getFunction());
1057cfca06d7SDimitry Andric
1058cfca06d7SDimitry Andric // To support value profiling calls within Windows exception handlers, funclet
1059cfca06d7SDimitry Andric // information contained within operand bundles needs to be copied over to
1060cfca06d7SDimitry Andric // the library call. This is required for the IR to be processed by the
1061cfca06d7SDimitry Andric // WinEHPrepare pass.
1062cfca06d7SDimitry Andric SmallVector<OperandBundleDef, 1> OpBundles;
1063cfca06d7SDimitry Andric Ind->getOperandBundlesAsDefs(OpBundles);
1064b60736ecSDimitry Andric if (!IsMemOpSize) {
1065b1c73532SDimitry Andric Value *Args[3] = {Ind->getTargetValue(), DataVar, Builder.getInt32(Index)};
1066312c0ed1SDimitry Andric Call = Builder.CreateCall(getOrInsertValueProfilingCall(M, *TLI), Args,
1067cfca06d7SDimitry Andric OpBundles);
106871d5a254SDimitry Andric } else {
1069b1c73532SDimitry Andric Value *Args[3] = {Ind->getTargetValue(), DataVar, Builder.getInt32(Index)};
1070b60736ecSDimitry Andric Call = Builder.CreateCall(
1071312c0ed1SDimitry Andric getOrInsertValueProfilingCall(M, *TLI, ValueProfilingCallType::MemOp),
1072cfca06d7SDimitry Andric Args, OpBundles);
107371d5a254SDimitry Andric }
1074b915e9e0SDimitry Andric if (auto AK = TLI->getExtAttrForI32Param(false))
1075148779dfSDimitry Andric Call->addParamAttr(2, AK);
1076b915e9e0SDimitry Andric Ind->replaceAllUsesWith(Call);
1077dd58ef01SDimitry Andric Ind->eraseFromParent();
1078dd58ef01SDimitry Andric }
1079dd58ef01SDimitry Andric
getOrCreateBiasVar(StringRef VarName)1080ac9a064cSDimitry Andric GlobalVariable *InstrLowerer::getOrCreateBiasVar(StringRef VarName) {
1081ac9a064cSDimitry Andric GlobalVariable *Bias = M.getGlobalVariable(VarName);
1082ac9a064cSDimitry Andric if (Bias)
1083ac9a064cSDimitry Andric return Bias;
1084ac9a064cSDimitry Andric
1085ac9a064cSDimitry Andric Type *Int64Ty = Type::getInt64Ty(M.getContext());
1086ac9a064cSDimitry Andric
1087ac9a064cSDimitry Andric // Compiler must define this variable when runtime counter relocation
1088ac9a064cSDimitry Andric // is being used. Runtime has a weak external reference that is used
1089ac9a064cSDimitry Andric // to check whether that's the case or not.
1090ac9a064cSDimitry Andric Bias = new GlobalVariable(M, Int64Ty, false, GlobalValue::LinkOnceODRLinkage,
1091ac9a064cSDimitry Andric Constant::getNullValue(Int64Ty), VarName);
1092ac9a064cSDimitry Andric Bias->setVisibility(GlobalVariable::HiddenVisibility);
1093ac9a064cSDimitry Andric // A definition that's weak (linkonce_odr) without being in a COMDAT
1094ac9a064cSDimitry Andric // section wouldn't lead to link errors, but it would lead to a dead
1095ac9a064cSDimitry Andric // data word from every TU but one. Putting it in COMDAT ensures there
1096ac9a064cSDimitry Andric // will be exactly one data slot in the link.
1097ac9a064cSDimitry Andric if (TT.supportsCOMDAT())
1098ac9a064cSDimitry Andric Bias->setComdat(M.getOrInsertComdat(VarName));
1099ac9a064cSDimitry Andric
1100ac9a064cSDimitry Andric return Bias;
1101ac9a064cSDimitry Andric }
1102ac9a064cSDimitry Andric
getCounterAddress(InstrProfCntrInstBase * I)1103312c0ed1SDimitry Andric Value *InstrLowerer::getCounterAddress(InstrProfCntrInstBase *I) {
1104ecbca9f5SDimitry Andric auto *Counters = getOrCreateRegionCounters(I);
1105ecbca9f5SDimitry Andric IRBuilder<> Builder(I);
110667c32a98SDimitry Andric
11077fa27ce4SDimitry Andric if (isa<InstrProfTimestampInst>(I))
11087fa27ce4SDimitry Andric Counters->setAlignment(Align(8));
11097fa27ce4SDimitry Andric
1110ecbca9f5SDimitry Andric auto *Addr = Builder.CreateConstInBoundsGEP2_32(
1111ecbca9f5SDimitry Andric Counters->getValueType(), Counters, 0, I->getIndex()->getZExtValue());
1112d8e91e46SDimitry Andric
1113ecbca9f5SDimitry Andric if (!isRuntimeCounterRelocationEnabled())
1114ecbca9f5SDimitry Andric return Addr;
1115ecbca9f5SDimitry Andric
1116312c0ed1SDimitry Andric Type *Int64Ty = Type::getInt64Ty(M.getContext());
1117ecbca9f5SDimitry Andric Function *Fn = I->getParent()->getParent();
1118145449b1SDimitry Andric LoadInst *&BiasLI = FunctionToProfileBiasMap[Fn];
1119145449b1SDimitry Andric if (!BiasLI) {
1120145449b1SDimitry Andric IRBuilder<> EntryBuilder(&Fn->getEntryBlock().front());
1121ac9a064cSDimitry Andric auto *Bias = getOrCreateBiasVar(getInstrProfCounterBiasVarName());
1122ac9a064cSDimitry Andric BiasLI = EntryBuilder.CreateLoad(Int64Ty, Bias, "profc_bias");
1123ac9a064cSDimitry Andric // Bias doesn't change after startup.
1124ac9a064cSDimitry Andric BiasLI->setMetadata(LLVMContext::MD_invariant_load,
1125ac9a064cSDimitry Andric MDNode::get(M.getContext(), std::nullopt));
1126cfca06d7SDimitry Andric }
1127145449b1SDimitry Andric auto *Add = Builder.CreateAdd(Builder.CreatePtrToInt(Addr, Int64Ty), BiasLI);
1128ecbca9f5SDimitry Andric return Builder.CreateIntToPtr(Add, Addr->getType());
1129cfca06d7SDimitry Andric }
1130cfca06d7SDimitry Andric
1131ac9a064cSDimitry Andric /// Create `void [[alwaysinline]] rmw_or(uint8_t *ArgAddr, uint8_t ArgVal)`
1132ac9a064cSDimitry Andric /// "Basic" sequence is `*ArgAddr |= ArgVal`
createRMWOrFunc()1133ac9a064cSDimitry Andric Function *InstrLowerer::createRMWOrFunc() {
1134ac9a064cSDimitry Andric auto &Ctx = M.getContext();
1135ac9a064cSDimitry Andric auto *Int8Ty = Type::getInt8Ty(Ctx);
1136ac9a064cSDimitry Andric Function *Fn = Function::Create(
1137ac9a064cSDimitry Andric FunctionType::get(Type::getVoidTy(Ctx),
1138ac9a064cSDimitry Andric {PointerType::getUnqual(Ctx), Int8Ty}, false),
1139ac9a064cSDimitry Andric Function::LinkageTypes::PrivateLinkage, "rmw_or", M);
1140ac9a064cSDimitry Andric Fn->addFnAttr(Attribute::AlwaysInline);
1141ac9a064cSDimitry Andric auto *ArgAddr = Fn->getArg(0);
1142ac9a064cSDimitry Andric auto *ArgVal = Fn->getArg(1);
1143ac9a064cSDimitry Andric IRBuilder<> Builder(BasicBlock::Create(Ctx, "", Fn));
1144ac9a064cSDimitry Andric
1145ac9a064cSDimitry Andric // Load profile bitmap byte.
1146ac9a064cSDimitry Andric // %mcdc.bits = load i8, ptr %4, align 1
1147ac9a064cSDimitry Andric auto *Bitmap = Builder.CreateLoad(Int8Ty, ArgAddr, "mcdc.bits");
1148ac9a064cSDimitry Andric
1149ac9a064cSDimitry Andric if (Options.Atomic || AtomicCounterUpdateAll) {
1150ac9a064cSDimitry Andric // If ((Bitmap & Val) != Val), then execute atomic (Bitmap |= Val).
1151ac9a064cSDimitry Andric // Note, just-loaded Bitmap might not be up-to-date. Use it just for
1152ac9a064cSDimitry Andric // early testing.
1153ac9a064cSDimitry Andric auto *Masked = Builder.CreateAnd(Bitmap, ArgVal);
1154ac9a064cSDimitry Andric auto *ShouldStore = Builder.CreateICmpNE(Masked, ArgVal);
1155ac9a064cSDimitry Andric auto *ThenTerm = BasicBlock::Create(Ctx, "", Fn);
1156ac9a064cSDimitry Andric auto *ElseTerm = BasicBlock::Create(Ctx, "", Fn);
1157ac9a064cSDimitry Andric // Assume updating will be rare.
1158ac9a064cSDimitry Andric auto *Unlikely = MDBuilder(Ctx).createUnlikelyBranchWeights();
1159ac9a064cSDimitry Andric Builder.CreateCondBr(ShouldStore, ThenTerm, ElseTerm, Unlikely);
1160ac9a064cSDimitry Andric
1161ac9a064cSDimitry Andric IRBuilder<> ThenBuilder(ThenTerm);
1162ac9a064cSDimitry Andric ThenBuilder.CreateAtomicRMW(AtomicRMWInst::Or, ArgAddr, ArgVal,
1163ac9a064cSDimitry Andric MaybeAlign(), AtomicOrdering::Monotonic);
1164ac9a064cSDimitry Andric ThenBuilder.CreateRetVoid();
1165ac9a064cSDimitry Andric
1166ac9a064cSDimitry Andric IRBuilder<> ElseBuilder(ElseTerm);
1167ac9a064cSDimitry Andric ElseBuilder.CreateRetVoid();
1168ac9a064cSDimitry Andric
1169ac9a064cSDimitry Andric return Fn;
1170ac9a064cSDimitry Andric }
1171ac9a064cSDimitry Andric
1172ac9a064cSDimitry Andric // Perform logical OR of profile bitmap byte and shifted bit offset.
1173ac9a064cSDimitry Andric // %8 = or i8 %mcdc.bits, %7
1174ac9a064cSDimitry Andric auto *Result = Builder.CreateOr(Bitmap, ArgVal);
1175ac9a064cSDimitry Andric
1176ac9a064cSDimitry Andric // Store the updated profile bitmap byte.
1177ac9a064cSDimitry Andric // store i8 %8, ptr %3, align 1
1178ac9a064cSDimitry Andric Builder.CreateStore(Result, ArgAddr);
1179ac9a064cSDimitry Andric
1180ac9a064cSDimitry Andric // Terminator
1181ac9a064cSDimitry Andric Builder.CreateRetVoid();
1182ac9a064cSDimitry Andric
1183ac9a064cSDimitry Andric return Fn;
1184ac9a064cSDimitry Andric }
1185ac9a064cSDimitry Andric
getRMWOrCall(Value * Addr,Value * Val)1186ac9a064cSDimitry Andric CallInst *InstrLowerer::getRMWOrCall(Value *Addr, Value *Val) {
1187ac9a064cSDimitry Andric if (!RMWOrFunc)
1188ac9a064cSDimitry Andric RMWOrFunc = createRMWOrFunc();
1189ac9a064cSDimitry Andric
1190ac9a064cSDimitry Andric return CallInst::Create(RMWOrFunc, {Addr, Val});
1191ac9a064cSDimitry Andric }
1192ac9a064cSDimitry Andric
getBitmapAddress(InstrProfMCDCTVBitmapUpdate * I)1193312c0ed1SDimitry Andric Value *InstrLowerer::getBitmapAddress(InstrProfMCDCTVBitmapUpdate *I) {
1194b1c73532SDimitry Andric auto *Bitmaps = getOrCreateRegionBitmaps(I);
1195b1c73532SDimitry Andric IRBuilder<> Builder(I);
1196b1c73532SDimitry Andric
1197b1c73532SDimitry Andric if (isRuntimeCounterRelocationEnabled()) {
1198312c0ed1SDimitry Andric LLVMContext &Ctx = M.getContext();
1199b1c73532SDimitry Andric Ctx.diagnose(DiagnosticInfoPGOProfile(
1200312c0ed1SDimitry Andric M.getName().data(),
1201b1c73532SDimitry Andric Twine("Runtime counter relocation is presently not supported for MC/DC "
1202b1c73532SDimitry Andric "bitmaps."),
1203b1c73532SDimitry Andric DS_Warning));
1204b1c73532SDimitry Andric }
1205b1c73532SDimitry Andric
1206ac9a064cSDimitry Andric return Bitmaps;
1207b1c73532SDimitry Andric }
1208b1c73532SDimitry Andric
lowerCover(InstrProfCoverInst * CoverInstruction)1209312c0ed1SDimitry Andric void InstrLowerer::lowerCover(InstrProfCoverInst *CoverInstruction) {
1210ecbca9f5SDimitry Andric auto *Addr = getCounterAddress(CoverInstruction);
1211ecbca9f5SDimitry Andric IRBuilder<> Builder(CoverInstruction);
1212ecbca9f5SDimitry Andric // We store zero to represent that this block is covered.
1213ecbca9f5SDimitry Andric Builder.CreateStore(Builder.getInt8(0), Addr);
1214ecbca9f5SDimitry Andric CoverInstruction->eraseFromParent();
1215ecbca9f5SDimitry Andric }
1216ecbca9f5SDimitry Andric
lowerTimestamp(InstrProfTimestampInst * TimestampInstruction)1217312c0ed1SDimitry Andric void InstrLowerer::lowerTimestamp(
12187fa27ce4SDimitry Andric InstrProfTimestampInst *TimestampInstruction) {
12197fa27ce4SDimitry Andric assert(TimestampInstruction->getIndex()->isZeroValue() &&
12207fa27ce4SDimitry Andric "timestamp probes are always the first probe for a function");
1221312c0ed1SDimitry Andric auto &Ctx = M.getContext();
12227fa27ce4SDimitry Andric auto *TimestampAddr = getCounterAddress(TimestampInstruction);
12237fa27ce4SDimitry Andric IRBuilder<> Builder(TimestampInstruction);
12247fa27ce4SDimitry Andric auto *CalleeTy =
12257fa27ce4SDimitry Andric FunctionType::get(Type::getVoidTy(Ctx), TimestampAddr->getType(), false);
1226312c0ed1SDimitry Andric auto Callee = M.getOrInsertFunction(
12277fa27ce4SDimitry Andric INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_SET_TIMESTAMP), CalleeTy);
12287fa27ce4SDimitry Andric Builder.CreateCall(Callee, {TimestampAddr});
12297fa27ce4SDimitry Andric TimestampInstruction->eraseFromParent();
12307fa27ce4SDimitry Andric }
12317fa27ce4SDimitry Andric
lowerIncrement(InstrProfIncrementInst * Inc)1232312c0ed1SDimitry Andric void InstrLowerer::lowerIncrement(InstrProfIncrementInst *Inc) {
1233ecbca9f5SDimitry Andric auto *Addr = getCounterAddress(Inc);
1234ecbca9f5SDimitry Andric
1235ecbca9f5SDimitry Andric IRBuilder<> Builder(Inc);
1236cfca06d7SDimitry Andric if (Options.Atomic || AtomicCounterUpdateAll ||
1237ecbca9f5SDimitry Andric (Inc->getIndex()->isZeroValue() && AtomicFirstCounter)) {
1238d8e91e46SDimitry Andric Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, Inc->getStep(),
1239344a3780SDimitry Andric MaybeAlign(), AtomicOrdering::Monotonic);
1240d8e91e46SDimitry Andric } else {
1241e6d15924SDimitry Andric Value *IncStep = Inc->getStep();
1242e6d15924SDimitry Andric Value *Load = Builder.CreateLoad(IncStep->getType(), Addr, "pgocount");
124308bbd35aSDimitry Andric auto *Count = Builder.CreateAdd(Load, Inc->getStep());
124408bbd35aSDimitry Andric auto *Store = Builder.CreateStore(Count, Addr);
124508bbd35aSDimitry Andric if (isCounterPromotionEnabled())
124608bbd35aSDimitry Andric PromotionCandidates.emplace_back(cast<Instruction>(Load), Store);
1247d8e91e46SDimitry Andric }
124867c32a98SDimitry Andric Inc->eraseFromParent();
124967c32a98SDimitry Andric }
125067c32a98SDimitry Andric
lowerCoverageData(GlobalVariable * CoverageNamesVar)1251312c0ed1SDimitry Andric void InstrLowerer::lowerCoverageData(GlobalVariable *CoverageNamesVar) {
1252050e163aSDimitry Andric ConstantArray *Names =
1253050e163aSDimitry Andric cast<ConstantArray>(CoverageNamesVar->getInitializer());
1254050e163aSDimitry Andric for (unsigned I = 0, E = Names->getNumOperands(); I < E; ++I) {
1255050e163aSDimitry Andric Constant *NC = Names->getOperand(I);
1256050e163aSDimitry Andric Value *V = NC->stripPointerCasts();
1257608e6659SDimitry Andric assert(isa<GlobalVariable>(V) && "Missing reference to function name");
1258608e6659SDimitry Andric GlobalVariable *Name = cast<GlobalVariable>(V);
1259608e6659SDimitry Andric
126001095a5dSDimitry Andric Name->setLinkage(GlobalValue::PrivateLinkage);
126101095a5dSDimitry Andric ReferencedNames.push_back(Name);
1262145449b1SDimitry Andric if (isa<ConstantExpr>(NC))
126371d5a254SDimitry Andric NC->dropAllReferences();
1264608e6659SDimitry Andric }
126571d5a254SDimitry Andric CoverageNamesVar->eraseFromParent();
1266608e6659SDimitry Andric }
1267608e6659SDimitry Andric
lowerMCDCTestVectorBitmapUpdate(InstrProfMCDCTVBitmapUpdate * Update)1268312c0ed1SDimitry Andric void InstrLowerer::lowerMCDCTestVectorBitmapUpdate(
1269b1c73532SDimitry Andric InstrProfMCDCTVBitmapUpdate *Update) {
1270b1c73532SDimitry Andric IRBuilder<> Builder(Update);
1271312c0ed1SDimitry Andric auto *Int8Ty = Type::getInt8Ty(M.getContext());
1272312c0ed1SDimitry Andric auto *Int32Ty = Type::getInt32Ty(M.getContext());
1273b1c73532SDimitry Andric auto *MCDCCondBitmapAddr = Update->getMCDCCondBitmapAddr();
1274b1c73532SDimitry Andric auto *BitmapAddr = getBitmapAddress(Update);
1275b1c73532SDimitry Andric
1276ac9a064cSDimitry Andric // Load Temp Val + BitmapIdx.
1277b1c73532SDimitry Andric // %mcdc.temp = load i32, ptr %mcdc.addr, align 4
1278ac9a064cSDimitry Andric auto *Temp = Builder.CreateAdd(
1279ac9a064cSDimitry Andric Builder.CreateLoad(Int32Ty, MCDCCondBitmapAddr, "mcdc.temp"),
1280ac9a064cSDimitry Andric Update->getBitmapIndex());
1281b1c73532SDimitry Andric
1282b1c73532SDimitry Andric // Calculate byte offset using div8.
1283b1c73532SDimitry Andric // %1 = lshr i32 %mcdc.temp, 3
1284b1c73532SDimitry Andric auto *BitmapByteOffset = Builder.CreateLShr(Temp, 0x3);
1285b1c73532SDimitry Andric
1286b1c73532SDimitry Andric // Add byte offset to section base byte address.
1287ac9a064cSDimitry Andric // %4 = getelementptr inbounds i8, ptr @__profbm_test, i32 %1
1288b1c73532SDimitry Andric auto *BitmapByteAddr =
1289ac9a064cSDimitry Andric Builder.CreateInBoundsPtrAdd(BitmapAddr, BitmapByteOffset);
1290b1c73532SDimitry Andric
1291b1c73532SDimitry Andric // Calculate bit offset into bitmap byte by using div8 remainder (AND ~8)
1292b1c73532SDimitry Andric // %5 = and i32 %mcdc.temp, 7
1293b1c73532SDimitry Andric // %6 = trunc i32 %5 to i8
1294b1c73532SDimitry Andric auto *BitToSet = Builder.CreateTrunc(Builder.CreateAnd(Temp, 0x7), Int8Ty);
1295b1c73532SDimitry Andric
1296b1c73532SDimitry Andric // Shift bit offset left to form a bitmap.
1297b1c73532SDimitry Andric // %7 = shl i8 1, %6
1298b1c73532SDimitry Andric auto *ShiftedVal = Builder.CreateShl(Builder.getInt8(0x1), BitToSet);
1299b1c73532SDimitry Andric
1300ac9a064cSDimitry Andric Builder.Insert(getRMWOrCall(BitmapByteAddr, ShiftedVal));
1301b1c73532SDimitry Andric Update->eraseFromParent();
1302b1c73532SDimitry Andric }
1303b1c73532SDimitry Andric
130467c32a98SDimitry Andric /// Get the name of a profiling variable for a particular function.
getVarName(InstrProfInstBase * Inc,StringRef Prefix,bool & Renamed)13056f8fc217SDimitry Andric static std::string getVarName(InstrProfInstBase *Inc, StringRef Prefix,
1306c0981da4SDimitry Andric bool &Renamed) {
1307dd58ef01SDimitry Andric StringRef NamePrefix = getInstrProfNameVarPrefix();
1308dd58ef01SDimitry Andric StringRef Name = Inc->getName()->getName().substr(NamePrefix.size());
1309581a6d85SDimitry Andric Function *F = Inc->getParent()->getParent();
1310581a6d85SDimitry Andric Module *M = F->getParent();
1311581a6d85SDimitry Andric if (!DoHashBasedCounterSplit || !isIRPGOFlagSet(M) ||
1312c0981da4SDimitry Andric !canRenameComdatFunc(*F)) {
1313c0981da4SDimitry Andric Renamed = false;
1314dd58ef01SDimitry Andric return (Prefix + Name).str();
1315c0981da4SDimitry Andric }
1316c0981da4SDimitry Andric Renamed = true;
1317581a6d85SDimitry Andric uint64_t FuncHash = Inc->getHash()->getZExtValue();
1318581a6d85SDimitry Andric SmallVector<char, 24> HashPostfix;
1319b1c73532SDimitry Andric if (Name.ends_with((Twine(".") + Twine(FuncHash)).toStringRef(HashPostfix)))
1320581a6d85SDimitry Andric return (Prefix + Name).str();
1321581a6d85SDimitry Andric return (Prefix + Name + "." + Twine(FuncHash)).str();
1322dd58ef01SDimitry Andric }
1323dd58ef01SDimitry Andric
shouldRecordFunctionAddr(Function * F)1324dd58ef01SDimitry Andric static inline bool shouldRecordFunctionAddr(Function *F) {
1325344a3780SDimitry Andric // Only record function addresses if IR PGO is enabled or if clang value
1326344a3780SDimitry Andric // profiling is enabled. Recording function addresses greatly increases object
1327344a3780SDimitry Andric // file size, because it prevents the inliner from deleting functions that
1328344a3780SDimitry Andric // have been inlined everywhere.
1329344a3780SDimitry Andric if (!profDataReferencedByCode(*F->getParent()))
1330344a3780SDimitry Andric return false;
1331344a3780SDimitry Andric
1332dd58ef01SDimitry Andric // Check the linkage
13337c7aba6eSDimitry Andric bool HasAvailableExternallyLinkage = F->hasAvailableExternallyLinkage();
1334dd58ef01SDimitry Andric if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() &&
13357c7aba6eSDimitry Andric !HasAvailableExternallyLinkage)
1336dd58ef01SDimitry Andric return true;
13377c7aba6eSDimitry Andric
13387c7aba6eSDimitry Andric // A function marked 'alwaysinline' with available_externally linkage can't
13397c7aba6eSDimitry Andric // have its address taken. Doing so would create an undefined external ref to
13407c7aba6eSDimitry Andric // the function, which would fail to link.
13417c7aba6eSDimitry Andric if (HasAvailableExternallyLinkage &&
13427c7aba6eSDimitry Andric F->hasFnAttribute(Attribute::AlwaysInline))
13437c7aba6eSDimitry Andric return false;
13447c7aba6eSDimitry Andric
134501095a5dSDimitry Andric // Prohibit function address recording if the function is both internal and
134601095a5dSDimitry Andric // COMDAT. This avoids the profile data variable referencing internal symbols
134701095a5dSDimitry Andric // in COMDAT.
134801095a5dSDimitry Andric if (F->hasLocalLinkage() && F->hasComdat())
134901095a5dSDimitry Andric return false;
13507c7aba6eSDimitry Andric
1351dd58ef01SDimitry Andric // Check uses of this function for other than direct calls or invokes to it.
135201095a5dSDimitry Andric // Inline virtual functions have linkeOnceODR linkage. When a key method
135301095a5dSDimitry Andric // exists, the vtable will only be emitted in the TU where the key method
135401095a5dSDimitry Andric // is defined. In a TU where vtable is not available, the function won't
135501095a5dSDimitry Andric // be 'addresstaken'. If its address is not recorded here, the profile data
135601095a5dSDimitry Andric // with missing address may be picked by the linker leading to missing
135701095a5dSDimitry Andric // indirect call target info.
135801095a5dSDimitry Andric return F->hasAddressTaken() || F->hasLinkOnceLinkage();
1359dd58ef01SDimitry Andric }
1360dd58ef01SDimitry Andric
shouldUsePublicSymbol(Function * Fn)13617fa27ce4SDimitry Andric static inline bool shouldUsePublicSymbol(Function *Fn) {
13627fa27ce4SDimitry Andric // It isn't legal to make an alias of this function at all
13637fa27ce4SDimitry Andric if (Fn->isDeclarationForLinker())
13647fa27ce4SDimitry Andric return true;
13657fa27ce4SDimitry Andric
13667fa27ce4SDimitry Andric // Symbols with local linkage can just use the symbol directly without
13677fa27ce4SDimitry Andric // introducing relocations
13687fa27ce4SDimitry Andric if (Fn->hasLocalLinkage())
13697fa27ce4SDimitry Andric return true;
13707fa27ce4SDimitry Andric
13717fa27ce4SDimitry Andric // PGO + ThinLTO + CFI cause duplicate symbols to be introduced due to some
13727fa27ce4SDimitry Andric // unfavorable interaction between the new alias and the alias renaming done
13737fa27ce4SDimitry Andric // in LowerTypeTests under ThinLTO. For comdat functions that would normally
13747fa27ce4SDimitry Andric // be deduplicated, but the renaming scheme ends up preventing renaming, since
13757fa27ce4SDimitry Andric // it creates unique names for each alias, resulting in duplicated symbols. In
13767fa27ce4SDimitry Andric // the future, we should update the CFI related passes to migrate these
13777fa27ce4SDimitry Andric // aliases to the same module as the jump-table they refer to will be defined.
13787fa27ce4SDimitry Andric if (Fn->hasMetadata(LLVMContext::MD_type))
13797fa27ce4SDimitry Andric return true;
13807fa27ce4SDimitry Andric
13817fa27ce4SDimitry Andric // For comdat functions, an alias would need the same linkage as the original
13827fa27ce4SDimitry Andric // function and hidden visibility. There is no point in adding an alias with
13837fa27ce4SDimitry Andric // identical linkage an visibility to avoid introducing symbolic relocations.
13847fa27ce4SDimitry Andric if (Fn->hasComdat() &&
13857fa27ce4SDimitry Andric (Fn->getVisibility() == GlobalValue::VisibilityTypes::HiddenVisibility))
13867fa27ce4SDimitry Andric return true;
13877fa27ce4SDimitry Andric
13887fa27ce4SDimitry Andric // its OK to use an alias
13897fa27ce4SDimitry Andric return false;
13907fa27ce4SDimitry Andric }
13917fa27ce4SDimitry Andric
getFuncAddrForProfData(Function * Fn)13927fa27ce4SDimitry Andric static inline Constant *getFuncAddrForProfData(Function *Fn) {
1393b1c73532SDimitry Andric auto *Int8PtrTy = PointerType::getUnqual(Fn->getContext());
13947fa27ce4SDimitry Andric // Store a nullptr in __llvm_profd, if we shouldn't use a real address
13957fa27ce4SDimitry Andric if (!shouldRecordFunctionAddr(Fn))
13967fa27ce4SDimitry Andric return ConstantPointerNull::get(Int8PtrTy);
13977fa27ce4SDimitry Andric
13987fa27ce4SDimitry Andric // If we can't use an alias, we must use the public symbol, even though this
13997fa27ce4SDimitry Andric // may require a symbolic relocation.
14007fa27ce4SDimitry Andric if (shouldUsePublicSymbol(Fn))
1401b1c73532SDimitry Andric return Fn;
14027fa27ce4SDimitry Andric
14037fa27ce4SDimitry Andric // When possible use a private alias to avoid symbolic relocations.
14047fa27ce4SDimitry Andric auto *GA = GlobalAlias::create(GlobalValue::LinkageTypes::PrivateLinkage,
14057fa27ce4SDimitry Andric Fn->getName() + ".local", Fn);
14067fa27ce4SDimitry Andric
14077fa27ce4SDimitry Andric // When the instrumented function is a COMDAT function, we cannot use a
14087fa27ce4SDimitry Andric // private alias. If we did, we would create reference to a local label in
14097fa27ce4SDimitry Andric // this function's section. If this version of the function isn't selected by
14107fa27ce4SDimitry Andric // the linker, then the metadata would introduce a reference to a discarded
14117fa27ce4SDimitry Andric // section. So, for COMDAT functions, we need to adjust the linkage of the
14127fa27ce4SDimitry Andric // alias. Using hidden visibility avoids a dynamic relocation and an entry in
14137fa27ce4SDimitry Andric // the dynamic symbol table.
14147fa27ce4SDimitry Andric //
14157fa27ce4SDimitry Andric // Note that this handles COMDAT functions with visibility other than Hidden,
14167fa27ce4SDimitry Andric // since that case is covered in shouldUsePublicSymbol()
14177fa27ce4SDimitry Andric if (Fn->hasComdat()) {
14187fa27ce4SDimitry Andric GA->setLinkage(Fn->getLinkage());
14197fa27ce4SDimitry Andric GA->setVisibility(GlobalValue::VisibilityTypes::HiddenVisibility);
14207fa27ce4SDimitry Andric }
14217fa27ce4SDimitry Andric
14227fa27ce4SDimitry Andric // appendToCompilerUsed(*Fn->getParent(), {GA});
14237fa27ce4SDimitry Andric
1424b1c73532SDimitry Andric return GA;
14257fa27ce4SDimitry Andric }
14267fa27ce4SDimitry Andric
needsRuntimeRegistrationOfSectionRange(const Triple & TT)1427e6d15924SDimitry Andric static bool needsRuntimeRegistrationOfSectionRange(const Triple &TT) {
1428aca2e42cSDimitry Andric // compiler-rt uses linker support to get data/counters/name start/end for
1429aca2e42cSDimitry Andric // ELF, COFF, Mach-O and XCOFF.
1430aca2e42cSDimitry Andric if (TT.isOSBinFormatELF() || TT.isOSBinFormatCOFF() ||
1431aca2e42cSDimitry Andric TT.isOSBinFormatMachO() || TT.isOSBinFormatXCOFF())
143201095a5dSDimitry Andric return false;
143301095a5dSDimitry Andric
143401095a5dSDimitry Andric return true;
143501095a5dSDimitry Andric }
143601095a5dSDimitry Andric
maybeSetComdat(GlobalVariable * GV,GlobalObject * GO,StringRef CounterGroupName)1437ac9a064cSDimitry Andric void InstrLowerer::maybeSetComdat(GlobalVariable *GV, GlobalObject *GO,
1438ac9a064cSDimitry Andric StringRef CounterGroupName) {
1439ac9a064cSDimitry Andric // Place lowered global variables in a comdat group if the associated function
1440ac9a064cSDimitry Andric // or global variable is a COMDAT. This will make sure that only one copy of
1441ac9a064cSDimitry Andric // global variable (e.g. function counters) of the COMDAT function will be
1442ac9a064cSDimitry Andric // emitted after linking.
1443ac9a064cSDimitry Andric bool NeedComdat = needsComdatForCounter(*GO, M);
1444b1c73532SDimitry Andric bool UseComdat = (NeedComdat || TT.isOSBinFormatELF());
1445b1c73532SDimitry Andric
1446b1c73532SDimitry Andric if (!UseComdat)
1447b1c73532SDimitry Andric return;
1448b1c73532SDimitry Andric
1449ac9a064cSDimitry Andric // Keep in mind that this pass may run before the inliner, so we need to
1450ac9a064cSDimitry Andric // create a new comdat group (for counters, profiling data, etc). If we use
1451ac9a064cSDimitry Andric // the comdat of the parent function, that will result in relocations against
1452ac9a064cSDimitry Andric // discarded sections.
1453ac9a064cSDimitry Andric //
1454ac9a064cSDimitry Andric // If the data variable is referenced by code, non-counter variables (notably
1455ac9a064cSDimitry Andric // profiling data) and counters have to be in different comdats for COFF
1456ac9a064cSDimitry Andric // because the Visual C++ linker will report duplicate symbol errors if there
1457ac9a064cSDimitry Andric // are multiple external symbols with the same name marked
1458ac9a064cSDimitry Andric // IMAGE_COMDAT_SELECT_ASSOCIATIVE.
1459ac9a064cSDimitry Andric StringRef GroupName = TT.isOSBinFormatCOFF() && DataReferencedByCode
1460ac9a064cSDimitry Andric ? GV->getName()
1461ac9a064cSDimitry Andric : CounterGroupName;
1462312c0ed1SDimitry Andric Comdat *C = M.getOrInsertComdat(GroupName);
1463ac9a064cSDimitry Andric
1464ac9a064cSDimitry Andric if (!NeedComdat) {
1465ac9a064cSDimitry Andric // Object file format must be ELF since `UseComdat && !NeedComdat` is true.
1466ac9a064cSDimitry Andric //
1467ac9a064cSDimitry Andric // For ELF, when not using COMDAT, put counters, data and values into a
1468ac9a064cSDimitry Andric // nodeduplicate COMDAT which is lowered to a zero-flag section group. This
1469ac9a064cSDimitry Andric // allows -z start-stop-gc to discard the entire group when the function is
1470ac9a064cSDimitry Andric // discarded.
1471b1c73532SDimitry Andric C->setSelectionKind(Comdat::NoDeduplicate);
1472ac9a064cSDimitry Andric }
1473b1c73532SDimitry Andric GV->setComdat(C);
1474b1c73532SDimitry Andric // COFF doesn't allow the comdat group leader to have private linkage, so
1475b1c73532SDimitry Andric // upgrade private linkage to internal linkage to produce a symbol table
1476b1c73532SDimitry Andric // entry.
1477b1c73532SDimitry Andric if (TT.isOSBinFormatCOFF() && GV->hasPrivateLinkage())
1478b1c73532SDimitry Andric GV->setLinkage(GlobalValue::InternalLinkage);
1479ecbca9f5SDimitry Andric }
1480ecbca9f5SDimitry Andric
shouldRecordVTableAddr(GlobalVariable * GV)1481ac9a064cSDimitry Andric static inline bool shouldRecordVTableAddr(GlobalVariable *GV) {
1482ac9a064cSDimitry Andric if (!profDataReferencedByCode(*GV->getParent()))
1483ac9a064cSDimitry Andric return false;
1484ac9a064cSDimitry Andric
1485ac9a064cSDimitry Andric if (!GV->hasLinkOnceLinkage() && !GV->hasLocalLinkage() &&
1486ac9a064cSDimitry Andric !GV->hasAvailableExternallyLinkage())
1487ac9a064cSDimitry Andric return true;
1488ac9a064cSDimitry Andric
1489ac9a064cSDimitry Andric // This avoids the profile data from referencing internal symbols in
1490ac9a064cSDimitry Andric // COMDAT.
1491ac9a064cSDimitry Andric if (GV->hasLocalLinkage() && GV->hasComdat())
1492ac9a064cSDimitry Andric return false;
1493ac9a064cSDimitry Andric
1494ac9a064cSDimitry Andric return true;
1495ac9a064cSDimitry Andric }
1496ac9a064cSDimitry Andric
1497ac9a064cSDimitry Andric // FIXME: Introduce an internal alias like what's done for functions to reduce
1498ac9a064cSDimitry Andric // the number of relocation entries.
getVTableAddrForProfData(GlobalVariable * GV)1499ac9a064cSDimitry Andric static inline Constant *getVTableAddrForProfData(GlobalVariable *GV) {
1500ac9a064cSDimitry Andric auto *Int8PtrTy = PointerType::getUnqual(GV->getContext());
1501ac9a064cSDimitry Andric
1502ac9a064cSDimitry Andric // Store a nullptr in __profvt_ if a real address shouldn't be used.
1503ac9a064cSDimitry Andric if (!shouldRecordVTableAddr(GV))
1504ac9a064cSDimitry Andric return ConstantPointerNull::get(Int8PtrTy);
1505ac9a064cSDimitry Andric
1506ac9a064cSDimitry Andric return ConstantExpr::getBitCast(GV, Int8PtrTy);
1507ac9a064cSDimitry Andric }
1508ac9a064cSDimitry Andric
getOrCreateVTableProfData(GlobalVariable * GV)1509ac9a064cSDimitry Andric void InstrLowerer::getOrCreateVTableProfData(GlobalVariable *GV) {
1510ac9a064cSDimitry Andric assert(!DebugInfoCorrelate &&
1511ac9a064cSDimitry Andric "Value profiling is not supported with lightweight instrumentation");
1512ac9a064cSDimitry Andric if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
1513ac9a064cSDimitry Andric return;
1514ac9a064cSDimitry Andric
1515ac9a064cSDimitry Andric // Skip llvm internal global variable or __prof variables.
1516ac9a064cSDimitry Andric if (GV->getName().starts_with("llvm.") ||
1517ac9a064cSDimitry Andric GV->getName().starts_with("__llvm") ||
1518ac9a064cSDimitry Andric GV->getName().starts_with("__prof"))
1519ac9a064cSDimitry Andric return;
1520ac9a064cSDimitry Andric
1521ac9a064cSDimitry Andric // VTableProfData already created
1522ac9a064cSDimitry Andric auto It = VTableDataMap.find(GV);
1523ac9a064cSDimitry Andric if (It != VTableDataMap.end() && It->second)
1524ac9a064cSDimitry Andric return;
1525ac9a064cSDimitry Andric
1526ac9a064cSDimitry Andric GlobalValue::LinkageTypes Linkage = GV->getLinkage();
1527ac9a064cSDimitry Andric GlobalValue::VisibilityTypes Visibility = GV->getVisibility();
1528ac9a064cSDimitry Andric
1529ac9a064cSDimitry Andric // This is to keep consistent with per-function profile data
1530ac9a064cSDimitry Andric // for correctness.
1531ac9a064cSDimitry Andric if (TT.isOSBinFormatXCOFF()) {
1532ac9a064cSDimitry Andric Linkage = GlobalValue::InternalLinkage;
1533ac9a064cSDimitry Andric Visibility = GlobalValue::DefaultVisibility;
1534ac9a064cSDimitry Andric }
1535ac9a064cSDimitry Andric
1536ac9a064cSDimitry Andric LLVMContext &Ctx = M.getContext();
1537ac9a064cSDimitry Andric Type *DataTypes[] = {
1538ac9a064cSDimitry Andric #define INSTR_PROF_VTABLE_DATA(Type, LLVMType, Name, Init) LLVMType,
1539ac9a064cSDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1540ac9a064cSDimitry Andric #undef INSTR_PROF_VTABLE_DATA
1541ac9a064cSDimitry Andric };
1542ac9a064cSDimitry Andric
1543ac9a064cSDimitry Andric auto *DataTy = StructType::get(Ctx, ArrayRef(DataTypes));
1544ac9a064cSDimitry Andric
1545ac9a064cSDimitry Andric // Used by INSTR_PROF_VTABLE_DATA MACRO
1546ac9a064cSDimitry Andric Constant *VTableAddr = getVTableAddrForProfData(GV);
1547ac9a064cSDimitry Andric const std::string PGOVTableName = getPGOName(*GV);
1548ac9a064cSDimitry Andric // Record the length of the vtable. This is needed since vtable pointers
1549ac9a064cSDimitry Andric // loaded from C++ objects might be from the middle of a vtable definition.
1550ac9a064cSDimitry Andric uint32_t VTableSizeVal =
1551ac9a064cSDimitry Andric M.getDataLayout().getTypeAllocSize(GV->getValueType());
1552ac9a064cSDimitry Andric
1553ac9a064cSDimitry Andric Constant *DataVals[] = {
1554ac9a064cSDimitry Andric #define INSTR_PROF_VTABLE_DATA(Type, LLVMType, Name, Init) Init,
1555ac9a064cSDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1556ac9a064cSDimitry Andric #undef INSTR_PROF_VTABLE_DATA
1557ac9a064cSDimitry Andric };
1558ac9a064cSDimitry Andric
1559ac9a064cSDimitry Andric auto *Data =
1560ac9a064cSDimitry Andric new GlobalVariable(M, DataTy, /*constant=*/false, Linkage,
1561ac9a064cSDimitry Andric ConstantStruct::get(DataTy, DataVals),
1562ac9a064cSDimitry Andric getInstrProfVTableVarPrefix() + PGOVTableName);
1563ac9a064cSDimitry Andric
1564ac9a064cSDimitry Andric Data->setVisibility(Visibility);
1565ac9a064cSDimitry Andric Data->setSection(getInstrProfSectionName(IPSK_vtab, TT.getObjectFormat()));
1566ac9a064cSDimitry Andric Data->setAlignment(Align(8));
1567ac9a064cSDimitry Andric
1568ac9a064cSDimitry Andric maybeSetComdat(Data, GV, Data->getName());
1569ac9a064cSDimitry Andric
1570ac9a064cSDimitry Andric VTableDataMap[GV] = Data;
1571ac9a064cSDimitry Andric
1572ac9a064cSDimitry Andric ReferencedVTables.push_back(GV);
1573ac9a064cSDimitry Andric
1574ac9a064cSDimitry Andric // VTable <Hash, Addr> is used by runtime but not referenced by other
1575ac9a064cSDimitry Andric // sections. Conservatively mark it linker retained.
1576ac9a064cSDimitry Andric UsedVars.push_back(Data);
1577ac9a064cSDimitry Andric }
1578ac9a064cSDimitry Andric
setupProfileSection(InstrProfInstBase * Inc,InstrProfSectKind IPSK)1579312c0ed1SDimitry Andric GlobalVariable *InstrLowerer::setupProfileSection(InstrProfInstBase *Inc,
1580b1c73532SDimitry Andric InstrProfSectKind IPSK) {
1581dd58ef01SDimitry Andric GlobalVariable *NamePtr = Inc->getName();
158267c32a98SDimitry Andric
1583344a3780SDimitry Andric // Match the linkage and visibility of the name global.
158485d8b2bbSDimitry Andric Function *Fn = Inc->getParent()->getParent();
1585e6d15924SDimitry Andric GlobalValue::LinkageTypes Linkage = NamePtr->getLinkage();
1586e6d15924SDimitry Andric GlobalValue::VisibilityTypes Visibility = NamePtr->getVisibility();
1587e6d15924SDimitry Andric
158877fc4c14SDimitry Andric // Use internal rather than private linkage so the counter variable shows up
158977fc4c14SDimitry Andric // in the symbol table when using debug info for correlation.
1590312c0ed1SDimitry Andric if ((DebugInfoCorrelate ||
1591312c0ed1SDimitry Andric ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO) &&
1592312c0ed1SDimitry Andric TT.isOSBinFormatMachO() && Linkage == GlobalValue::PrivateLinkage)
159377fc4c14SDimitry Andric Linkage = GlobalValue::InternalLinkage;
159477fc4c14SDimitry Andric
1595c0981da4SDimitry Andric // Due to the limitation of binder as of 2021/09/28, the duplicate weak
1596c0981da4SDimitry Andric // symbols in the same csect won't be discarded. When there are duplicate weak
1597c0981da4SDimitry Andric // symbols, we can NOT guarantee that the relocations get resolved to the
1598c0981da4SDimitry Andric // intended weak symbol, so we can not ensure the correctness of the relative
1599c0981da4SDimitry Andric // CounterPtr, so we have to use private linkage for counter and data symbols.
1600c0981da4SDimitry Andric if (TT.isOSBinFormatXCOFF()) {
1601c0981da4SDimitry Andric Linkage = GlobalValue::PrivateLinkage;
1602c0981da4SDimitry Andric Visibility = GlobalValue::DefaultVisibility;
1603c0981da4SDimitry Andric }
1604ac9a064cSDimitry Andric // Move the name variable to the right section.
1605c0981da4SDimitry Andric bool Renamed;
1606b1c73532SDimitry Andric GlobalVariable *Ptr;
1607b1c73532SDimitry Andric StringRef VarPrefix;
1608b1c73532SDimitry Andric std::string VarName;
1609b1c73532SDimitry Andric if (IPSK == IPSK_cnts) {
1610b1c73532SDimitry Andric VarPrefix = getInstrProfCountersVarPrefix();
1611b1c73532SDimitry Andric VarName = getVarName(Inc, VarPrefix, Renamed);
1612b1c73532SDimitry Andric InstrProfCntrInstBase *CntrIncrement = dyn_cast<InstrProfCntrInstBase>(Inc);
1613b1c73532SDimitry Andric Ptr = createRegionCounters(CntrIncrement, VarName, Linkage);
1614b1c73532SDimitry Andric } else if (IPSK == IPSK_bitmap) {
1615b1c73532SDimitry Andric VarPrefix = getInstrProfBitmapVarPrefix();
1616b1c73532SDimitry Andric VarName = getVarName(Inc, VarPrefix, Renamed);
1617b1c73532SDimitry Andric InstrProfMCDCBitmapInstBase *BitmapUpdate =
1618b1c73532SDimitry Andric dyn_cast<InstrProfMCDCBitmapInstBase>(Inc);
1619b1c73532SDimitry Andric Ptr = createRegionBitmaps(BitmapUpdate, VarName, Linkage);
1620b1c73532SDimitry Andric } else {
1621b1c73532SDimitry Andric llvm_unreachable("Profile Section must be for Counters or Bitmaps");
1622344a3780SDimitry Andric }
162367c32a98SDimitry Andric
1624b1c73532SDimitry Andric Ptr->setVisibility(Visibility);
1625b1c73532SDimitry Andric // Put the counters and bitmaps in their own sections so linkers can
1626b1c73532SDimitry Andric // remove unneeded sections.
1627b1c73532SDimitry Andric Ptr->setSection(getInstrProfSectionName(IPSK, TT.getObjectFormat()));
1628b1c73532SDimitry Andric Ptr->setLinkage(Linkage);
1629b1c73532SDimitry Andric maybeSetComdat(Ptr, Fn, VarName);
1630b1c73532SDimitry Andric return Ptr;
1631b1c73532SDimitry Andric }
1632b1c73532SDimitry Andric
1633b1c73532SDimitry Andric GlobalVariable *
createRegionBitmaps(InstrProfMCDCBitmapInstBase * Inc,StringRef Name,GlobalValue::LinkageTypes Linkage)1634312c0ed1SDimitry Andric InstrLowerer::createRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc,
1635b1c73532SDimitry Andric StringRef Name,
1636b1c73532SDimitry Andric GlobalValue::LinkageTypes Linkage) {
1637ac9a064cSDimitry Andric uint64_t NumBytes = Inc->getNumBitmapBytes();
1638312c0ed1SDimitry Andric auto *BitmapTy = ArrayType::get(Type::getInt8Ty(M.getContext()), NumBytes);
1639312c0ed1SDimitry Andric auto GV = new GlobalVariable(M, BitmapTy, false, Linkage,
1640b1c73532SDimitry Andric Constant::getNullValue(BitmapTy), Name);
1641b1c73532SDimitry Andric GV->setAlignment(Align(1));
1642b1c73532SDimitry Andric return GV;
1643b1c73532SDimitry Andric }
1644b1c73532SDimitry Andric
1645b1c73532SDimitry Andric GlobalVariable *
getOrCreateRegionBitmaps(InstrProfMCDCBitmapInstBase * Inc)1646312c0ed1SDimitry Andric InstrLowerer::getOrCreateRegionBitmaps(InstrProfMCDCBitmapInstBase *Inc) {
1647b1c73532SDimitry Andric GlobalVariable *NamePtr = Inc->getName();
1648b1c73532SDimitry Andric auto &PD = ProfileDataMap[NamePtr];
1649b1c73532SDimitry Andric if (PD.RegionBitmaps)
1650b1c73532SDimitry Andric return PD.RegionBitmaps;
1651b1c73532SDimitry Andric
1652b1c73532SDimitry Andric // If RegionBitmaps doesn't already exist, create it by first setting up
1653b1c73532SDimitry Andric // the corresponding profile section.
1654b1c73532SDimitry Andric auto *BitmapPtr = setupProfileSection(Inc, IPSK_bitmap);
1655b1c73532SDimitry Andric PD.RegionBitmaps = BitmapPtr;
1656ac9a064cSDimitry Andric PD.NumBitmapBytes = Inc->getNumBitmapBytes();
1657b1c73532SDimitry Andric return PD.RegionBitmaps;
1658b1c73532SDimitry Andric }
1659b1c73532SDimitry Andric
1660b1c73532SDimitry Andric GlobalVariable *
createRegionCounters(InstrProfCntrInstBase * Inc,StringRef Name,GlobalValue::LinkageTypes Linkage)1661312c0ed1SDimitry Andric InstrLowerer::createRegionCounters(InstrProfCntrInstBase *Inc, StringRef Name,
1662b1c73532SDimitry Andric GlobalValue::LinkageTypes Linkage) {
166367c32a98SDimitry Andric uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
1664312c0ed1SDimitry Andric auto &Ctx = M.getContext();
1665b1c73532SDimitry Andric GlobalVariable *GV;
1666b1c73532SDimitry Andric if (isa<InstrProfCoverInst>(Inc)) {
1667b1c73532SDimitry Andric auto *CounterTy = Type::getInt8Ty(Ctx);
1668b1c73532SDimitry Andric auto *CounterArrTy = ArrayType::get(CounterTy, NumCounters);
1669b1c73532SDimitry Andric // TODO: `Constant::getAllOnesValue()` does not yet accept an array type.
1670b1c73532SDimitry Andric std::vector<Constant *> InitialValues(NumCounters,
1671b1c73532SDimitry Andric Constant::getAllOnesValue(CounterTy));
1672312c0ed1SDimitry Andric GV = new GlobalVariable(M, CounterArrTy, false, Linkage,
1673b1c73532SDimitry Andric ConstantArray::get(CounterArrTy, InitialValues),
1674b1c73532SDimitry Andric Name);
1675b1c73532SDimitry Andric GV->setAlignment(Align(1));
1676b1c73532SDimitry Andric } else {
1677b1c73532SDimitry Andric auto *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters);
1678312c0ed1SDimitry Andric GV = new GlobalVariable(M, CounterTy, false, Linkage,
1679b1c73532SDimitry Andric Constant::getNullValue(CounterTy), Name);
1680b1c73532SDimitry Andric GV->setAlignment(Align(8));
1681b1c73532SDimitry Andric }
1682b1c73532SDimitry Andric return GV;
1683b1c73532SDimitry Andric }
168467c32a98SDimitry Andric
1685b1c73532SDimitry Andric GlobalVariable *
getOrCreateRegionCounters(InstrProfCntrInstBase * Inc)1686312c0ed1SDimitry Andric InstrLowerer::getOrCreateRegionCounters(InstrProfCntrInstBase *Inc) {
1687b1c73532SDimitry Andric GlobalVariable *NamePtr = Inc->getName();
1688b1c73532SDimitry Andric auto &PD = ProfileDataMap[NamePtr];
1689b1c73532SDimitry Andric if (PD.RegionCounters)
1690b1c73532SDimitry Andric return PD.RegionCounters;
1691b1c73532SDimitry Andric
1692b1c73532SDimitry Andric // If RegionCounters doesn't already exist, create it by first setting up
1693b1c73532SDimitry Andric // the corresponding profile section.
1694b1c73532SDimitry Andric auto *CounterPtr = setupProfileSection(Inc, IPSK_cnts);
1695f65dcba8SDimitry Andric PD.RegionCounters = CounterPtr;
1696b1c73532SDimitry Andric
1697312c0ed1SDimitry Andric if (DebugInfoCorrelate ||
1698312c0ed1SDimitry Andric ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO) {
1699312c0ed1SDimitry Andric LLVMContext &Ctx = M.getContext();
1700b1c73532SDimitry Andric Function *Fn = Inc->getParent()->getParent();
170177fc4c14SDimitry Andric if (auto *SP = Fn->getSubprogram()) {
1702312c0ed1SDimitry Andric DIBuilder DB(M, true, SP->getUnit());
170377fc4c14SDimitry Andric Metadata *FunctionNameAnnotation[] = {
170477fc4c14SDimitry Andric MDString::get(Ctx, InstrProfCorrelator::FunctionNameAttributeName),
170577fc4c14SDimitry Andric MDString::get(Ctx, getPGOFuncNameVarInitializer(NamePtr)),
170677fc4c14SDimitry Andric };
170777fc4c14SDimitry Andric Metadata *CFGHashAnnotation[] = {
170877fc4c14SDimitry Andric MDString::get(Ctx, InstrProfCorrelator::CFGHashAttributeName),
170977fc4c14SDimitry Andric ConstantAsMetadata::get(Inc->getHash()),
171077fc4c14SDimitry Andric };
171177fc4c14SDimitry Andric Metadata *NumCountersAnnotation[] = {
171277fc4c14SDimitry Andric MDString::get(Ctx, InstrProfCorrelator::NumCountersAttributeName),
171377fc4c14SDimitry Andric ConstantAsMetadata::get(Inc->getNumCounters()),
171477fc4c14SDimitry Andric };
171577fc4c14SDimitry Andric auto Annotations = DB.getOrCreateArray({
171677fc4c14SDimitry Andric MDNode::get(Ctx, FunctionNameAnnotation),
171777fc4c14SDimitry Andric MDNode::get(Ctx, CFGHashAnnotation),
171877fc4c14SDimitry Andric MDNode::get(Ctx, NumCountersAnnotation),
171977fc4c14SDimitry Andric });
172077fc4c14SDimitry Andric auto *DICounter = DB.createGlobalVariableExpression(
172177fc4c14SDimitry Andric SP, CounterPtr->getName(), /*LinkageName=*/StringRef(), SP->getFile(),
172277fc4c14SDimitry Andric /*LineNo=*/0, DB.createUnspecifiedType("Profile Data Type"),
172377fc4c14SDimitry Andric CounterPtr->hasLocalLinkage(), /*IsDefined=*/true, /*Expr=*/nullptr,
172477fc4c14SDimitry Andric /*Decl=*/nullptr, /*TemplateParams=*/nullptr, /*AlignInBits=*/0,
172577fc4c14SDimitry Andric Annotations);
172677fc4c14SDimitry Andric CounterPtr->addDebugInfo(DICounter);
172777fc4c14SDimitry Andric DB.finalize();
172877fc4c14SDimitry Andric }
172967c32a98SDimitry Andric
1730b1c73532SDimitry Andric // Mark the counter variable as used so that it isn't optimized out.
1731b1c73532SDimitry Andric CompilerUsedVars.push_back(PD.RegionCounters);
1732b1c73532SDimitry Andric }
1733b1c73532SDimitry Andric
1734b1c73532SDimitry Andric // Create the data variable (if it doesn't already exist).
1735b1c73532SDimitry Andric createDataVariable(Inc);
1736b1c73532SDimitry Andric
1737b1c73532SDimitry Andric return PD.RegionCounters;
1738b1c73532SDimitry Andric }
1739b1c73532SDimitry Andric
createDataVariable(InstrProfCntrInstBase * Inc)1740312c0ed1SDimitry Andric void InstrLowerer::createDataVariable(InstrProfCntrInstBase *Inc) {
1741b1c73532SDimitry Andric // When debug information is correlated to profile data, a data variable
1742b1c73532SDimitry Andric // is not needed.
1743312c0ed1SDimitry Andric if (DebugInfoCorrelate || ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO)
1744b1c73532SDimitry Andric return;
1745b1c73532SDimitry Andric
1746b1c73532SDimitry Andric GlobalVariable *NamePtr = Inc->getName();
1747b1c73532SDimitry Andric auto &PD = ProfileDataMap[NamePtr];
1748b1c73532SDimitry Andric
1749b1c73532SDimitry Andric // Return if data variable was already created.
1750b1c73532SDimitry Andric if (PD.DataVar)
1751b1c73532SDimitry Andric return;
1752b1c73532SDimitry Andric
1753312c0ed1SDimitry Andric LLVMContext &Ctx = M.getContext();
1754b1c73532SDimitry Andric
1755b1c73532SDimitry Andric Function *Fn = Inc->getParent()->getParent();
1756b1c73532SDimitry Andric GlobalValue::LinkageTypes Linkage = NamePtr->getLinkage();
1757b1c73532SDimitry Andric GlobalValue::VisibilityTypes Visibility = NamePtr->getVisibility();
1758b1c73532SDimitry Andric
1759b1c73532SDimitry Andric // Due to the limitation of binder as of 2021/09/28, the duplicate weak
1760b1c73532SDimitry Andric // symbols in the same csect won't be discarded. When there are duplicate weak
1761b1c73532SDimitry Andric // symbols, we can NOT guarantee that the relocations get resolved to the
1762b1c73532SDimitry Andric // intended weak symbol, so we can not ensure the correctness of the relative
1763b1c73532SDimitry Andric // CounterPtr, so we have to use private linkage for counter and data symbols.
1764b1c73532SDimitry Andric if (TT.isOSBinFormatXCOFF()) {
1765b1c73532SDimitry Andric Linkage = GlobalValue::PrivateLinkage;
1766b1c73532SDimitry Andric Visibility = GlobalValue::DefaultVisibility;
1767b1c73532SDimitry Andric }
1768b1c73532SDimitry Andric
1769312c0ed1SDimitry Andric bool NeedComdat = needsComdatForCounter(*Fn, M);
1770b1c73532SDimitry Andric bool Renamed;
1771b1c73532SDimitry Andric
1772b1c73532SDimitry Andric // The Data Variable section is anchored to profile counters.
1773b1c73532SDimitry Andric std::string CntsVarName =
1774b1c73532SDimitry Andric getVarName(Inc, getInstrProfCountersVarPrefix(), Renamed);
1775b1c73532SDimitry Andric std::string DataVarName =
1776b1c73532SDimitry Andric getVarName(Inc, getInstrProfDataVarPrefix(), Renamed);
1777b1c73532SDimitry Andric
1778b1c73532SDimitry Andric auto *Int8PtrTy = PointerType::getUnqual(Ctx);
177901095a5dSDimitry Andric // Allocate statically the array of pointers to value profile nodes for
178001095a5dSDimitry Andric // the current function.
178101095a5dSDimitry Andric Constant *ValuesPtrExpr = ConstantPointerNull::get(Int8PtrTy);
178201095a5dSDimitry Andric uint64_t NS = 0;
178301095a5dSDimitry Andric for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
178401095a5dSDimitry Andric NS += PD.NumValueSites[Kind];
1785344a3780SDimitry Andric if (NS > 0 && ValueProfileStaticAlloc &&
1786344a3780SDimitry Andric !needsRuntimeRegistrationOfSectionRange(TT)) {
178701095a5dSDimitry Andric ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS);
1788344a3780SDimitry Andric auto *ValuesVar = new GlobalVariable(
1789312c0ed1SDimitry Andric M, ValuesTy, false, Linkage, Constant::getNullValue(ValuesTy),
1790c0981da4SDimitry Andric getVarName(Inc, getInstrProfValuesVarPrefix(), Renamed));
1791e6d15924SDimitry Andric ValuesVar->setVisibility(Visibility);
1792b1c73532SDimitry Andric setGlobalVariableLargeSection(TT, *ValuesVar);
179371d5a254SDimitry Andric ValuesVar->setSection(
179471d5a254SDimitry Andric getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
17951d5ae102SDimitry Andric ValuesVar->setAlignment(Align(8));
1796b1c73532SDimitry Andric maybeSetComdat(ValuesVar, Fn, CntsVarName);
1797b1c73532SDimitry Andric ValuesPtrExpr = ValuesVar;
179801095a5dSDimitry Andric }
179901095a5dSDimitry Andric
1800b1c73532SDimitry Andric uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
1801b1c73532SDimitry Andric auto *CounterPtr = PD.RegionCounters;
1802b1c73532SDimitry Andric
1803b1c73532SDimitry Andric uint64_t NumBitmapBytes = PD.NumBitmapBytes;
180477fc4c14SDimitry Andric
180501095a5dSDimitry Andric // Create data variable.
1806312c0ed1SDimitry Andric auto *IntPtrTy = M.getDataLayout().getIntPtrType(M.getContext());
1807dd58ef01SDimitry Andric auto *Int16Ty = Type::getInt16Ty(Ctx);
1808dd58ef01SDimitry Andric auto *Int16ArrayTy = ArrayType::get(Int16Ty, IPVK_Last + 1);
1809dd58ef01SDimitry Andric Type *DataTypes[] = {
1810dd58ef01SDimitry Andric #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) LLVMType,
1811dd58ef01SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1812dd58ef01SDimitry Andric };
1813e3b55780SDimitry Andric auto *DataTy = StructType::get(Ctx, ArrayRef(DataTypes));
1814dd58ef01SDimitry Andric
18157fa27ce4SDimitry Andric Constant *FunctionAddr = getFuncAddrForProfData(Fn);
1816dd58ef01SDimitry Andric
1817dd58ef01SDimitry Andric Constant *Int16ArrayVals[IPVK_Last + 1];
1818dd58ef01SDimitry Andric for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
1819dd58ef01SDimitry Andric Int16ArrayVals[Kind] = ConstantInt::get(Int16Ty, PD.NumValueSites[Kind]);
1820dd58ef01SDimitry Andric
1821344a3780SDimitry Andric // If the data variable is not referenced by code (if we don't emit
1822344a3780SDimitry Andric // @llvm.instrprof.value.profile, NS will be 0), and the counter keeps the
1823344a3780SDimitry Andric // data variable live under linker GC, the data variable can be private. This
1824344a3780SDimitry Andric // optimization applies to ELF.
1825344a3780SDimitry Andric //
1826344a3780SDimitry Andric // On COFF, a comdat leader cannot be local so we require DataReferencedByCode
1827344a3780SDimitry Andric // to be false.
1828c0981da4SDimitry Andric //
1829c0981da4SDimitry Andric // If profd is in a deduplicate comdat, NS==0 with a hash suffix guarantees
1830c0981da4SDimitry Andric // that other copies must have the same CFG and cannot have value profiling.
1831c0981da4SDimitry Andric // If no hash suffix, other profd copies may be referenced by code.
1832c0981da4SDimitry Andric if (NS == 0 && !(DataReferencedByCode && NeedComdat && !Renamed) &&
1833c0981da4SDimitry Andric (TT.isOSBinFormatELF() ||
1834344a3780SDimitry Andric (!DataReferencedByCode && TT.isOSBinFormatCOFF()))) {
1835344a3780SDimitry Andric Linkage = GlobalValue::PrivateLinkage;
1836344a3780SDimitry Andric Visibility = GlobalValue::DefaultVisibility;
1837344a3780SDimitry Andric }
1838b60736ecSDimitry Andric auto *Data =
1839312c0ed1SDimitry Andric new GlobalVariable(M, DataTy, false, Linkage, nullptr, DataVarName);
1840312c0ed1SDimitry Andric Constant *RelativeCounterPtr;
1841b1c73532SDimitry Andric GlobalVariable *BitmapPtr = PD.RegionBitmaps;
1842b1c73532SDimitry Andric Constant *RelativeBitmapPtr = ConstantInt::get(IntPtrTy, 0);
1843312c0ed1SDimitry Andric InstrProfSectKind DataSectionKind;
1844312c0ed1SDimitry Andric // With binary profile correlation, profile data is not loaded into memory.
1845312c0ed1SDimitry Andric // profile data must reference profile counter with an absolute relocation.
1846312c0ed1SDimitry Andric if (ProfileCorrelate == InstrProfCorrelator::BINARY) {
1847312c0ed1SDimitry Andric DataSectionKind = IPSK_covdata;
1848312c0ed1SDimitry Andric RelativeCounterPtr = ConstantExpr::getPtrToInt(CounterPtr, IntPtrTy);
1849312c0ed1SDimitry Andric if (BitmapPtr != nullptr)
1850312c0ed1SDimitry Andric RelativeBitmapPtr = ConstantExpr::getPtrToInt(BitmapPtr, IntPtrTy);
1851312c0ed1SDimitry Andric } else {
1852312c0ed1SDimitry Andric // Reference the counter variable with a label difference (link-time
1853312c0ed1SDimitry Andric // constant).
1854312c0ed1SDimitry Andric DataSectionKind = IPSK_data;
1855312c0ed1SDimitry Andric RelativeCounterPtr =
1856312c0ed1SDimitry Andric ConstantExpr::getSub(ConstantExpr::getPtrToInt(CounterPtr, IntPtrTy),
1857312c0ed1SDimitry Andric ConstantExpr::getPtrToInt(Data, IntPtrTy));
1858312c0ed1SDimitry Andric if (BitmapPtr != nullptr)
1859b1c73532SDimitry Andric RelativeBitmapPtr =
1860b1c73532SDimitry Andric ConstantExpr::getSub(ConstantExpr::getPtrToInt(BitmapPtr, IntPtrTy),
1861b1c73532SDimitry Andric ConstantExpr::getPtrToInt(Data, IntPtrTy));
1862b1c73532SDimitry Andric }
1863b1c73532SDimitry Andric
1864c0981da4SDimitry Andric Constant *DataVals[] = {
1865c0981da4SDimitry Andric #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init,
1866c0981da4SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1867c0981da4SDimitry Andric };
1868c0981da4SDimitry Andric Data->setInitializer(ConstantStruct::get(DataTy, DataVals));
1869c0981da4SDimitry Andric
1870e6d15924SDimitry Andric Data->setVisibility(Visibility);
1871312c0ed1SDimitry Andric Data->setSection(
1872312c0ed1SDimitry Andric getInstrProfSectionName(DataSectionKind, TT.getObjectFormat()));
18731d5ae102SDimitry Andric Data->setAlignment(Align(INSTR_PROF_DATA_ALIGNMENT));
1874b1c73532SDimitry Andric maybeSetComdat(Data, Fn, CntsVarName);
1875dd58ef01SDimitry Andric
1876dd58ef01SDimitry Andric PD.DataVar = Data;
187767c32a98SDimitry Andric
187867c32a98SDimitry Andric // Mark the data variable as used so that it isn't stripped out.
1879344a3780SDimitry Andric CompilerUsedVars.push_back(Data);
188001095a5dSDimitry Andric // Now that the linkage set by the FE has been passed to the data and counter
188101095a5dSDimitry Andric // variables, reset Name variable's linkage and visibility to private so that
188201095a5dSDimitry Andric // it can be removed later by the compiler.
188301095a5dSDimitry Andric NamePtr->setLinkage(GlobalValue::PrivateLinkage);
188401095a5dSDimitry Andric // Collect the referenced names to be used by emitNameData.
188501095a5dSDimitry Andric ReferencedNames.push_back(NamePtr);
188667c32a98SDimitry Andric }
188767c32a98SDimitry Andric
emitVNodes()1888312c0ed1SDimitry Andric void InstrLowerer::emitVNodes() {
188901095a5dSDimitry Andric if (!ValueProfileStaticAlloc)
189067c32a98SDimitry Andric return;
189167c32a98SDimitry Andric
189201095a5dSDimitry Andric // For now only support this on platforms that do
189301095a5dSDimitry Andric // not require runtime registration to discover
189401095a5dSDimitry Andric // named section start/end.
1895e6d15924SDimitry Andric if (needsRuntimeRegistrationOfSectionRange(TT))
189601095a5dSDimitry Andric return;
189701095a5dSDimitry Andric
189801095a5dSDimitry Andric size_t TotalNS = 0;
189901095a5dSDimitry Andric for (auto &PD : ProfileDataMap) {
190001095a5dSDimitry Andric for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
190101095a5dSDimitry Andric TotalNS += PD.second.NumValueSites[Kind];
190201095a5dSDimitry Andric }
190301095a5dSDimitry Andric
190401095a5dSDimitry Andric if (!TotalNS)
190501095a5dSDimitry Andric return;
190601095a5dSDimitry Andric
190701095a5dSDimitry Andric uint64_t NumCounters = TotalNS * NumCountersPerValueSite;
190801095a5dSDimitry Andric // Heuristic for small programs with very few total value sites.
190901095a5dSDimitry Andric // The default value of vp-counters-per-site is chosen based on
191001095a5dSDimitry Andric // the observation that large apps usually have a low percentage
191101095a5dSDimitry Andric // of value sites that actually have any profile data, and thus
191201095a5dSDimitry Andric // the average number of counters per site is low. For small
191301095a5dSDimitry Andric // apps with very few sites, this may not be true. Bump up the
191401095a5dSDimitry Andric // number of counters in this case.
191501095a5dSDimitry Andric #define INSTR_PROF_MIN_VAL_COUNTS 10
191601095a5dSDimitry Andric if (NumCounters < INSTR_PROF_MIN_VAL_COUNTS)
191701095a5dSDimitry Andric NumCounters = std::max(INSTR_PROF_MIN_VAL_COUNTS, (int)NumCounters * 2);
191801095a5dSDimitry Andric
1919312c0ed1SDimitry Andric auto &Ctx = M.getContext();
192001095a5dSDimitry Andric Type *VNodeTypes[] = {
192101095a5dSDimitry Andric #define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Init) LLVMType,
192201095a5dSDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
192301095a5dSDimitry Andric };
1924e3b55780SDimitry Andric auto *VNodeTy = StructType::get(Ctx, ArrayRef(VNodeTypes));
192501095a5dSDimitry Andric
192601095a5dSDimitry Andric ArrayType *VNodesTy = ArrayType::get(VNodeTy, NumCounters);
192701095a5dSDimitry Andric auto *VNodesVar = new GlobalVariable(
1928312c0ed1SDimitry Andric M, VNodesTy, false, GlobalValue::PrivateLinkage,
192901095a5dSDimitry Andric Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName());
1930b1c73532SDimitry Andric setGlobalVariableLargeSection(TT, *VNodesVar);
193171d5a254SDimitry Andric VNodesVar->setSection(
193271d5a254SDimitry Andric getInstrProfSectionName(IPSK_vnodes, TT.getObjectFormat()));
1933312c0ed1SDimitry Andric VNodesVar->setAlignment(M.getDataLayout().getABITypeAlign(VNodesTy));
1934344a3780SDimitry Andric // VNodesVar is used by runtime but not referenced via relocation by other
1935344a3780SDimitry Andric // sections. Conservatively make it linker retained.
193601095a5dSDimitry Andric UsedVars.push_back(VNodesVar);
193701095a5dSDimitry Andric }
193801095a5dSDimitry Andric
emitNameData()1939312c0ed1SDimitry Andric void InstrLowerer::emitNameData() {
194001095a5dSDimitry Andric std::string UncompressedData;
194101095a5dSDimitry Andric
194201095a5dSDimitry Andric if (ReferencedNames.empty())
194301095a5dSDimitry Andric return;
194401095a5dSDimitry Andric
194501095a5dSDimitry Andric std::string CompressedNameStr;
194601095a5dSDimitry Andric if (Error E = collectPGOFuncNameStrings(ReferencedNames, CompressedNameStr,
1947cfca06d7SDimitry Andric DoInstrProfNameCompression)) {
1948c0981da4SDimitry Andric report_fatal_error(Twine(toString(std::move(E))), false);
194901095a5dSDimitry Andric }
195001095a5dSDimitry Andric
1951312c0ed1SDimitry Andric auto &Ctx = M.getContext();
1952f65dcba8SDimitry Andric auto *NamesVal =
1953f65dcba8SDimitry Andric ConstantDataArray::getString(Ctx, StringRef(CompressedNameStr), false);
1954312c0ed1SDimitry Andric NamesVar = new GlobalVariable(M, NamesVal->getType(), true,
195571d5a254SDimitry Andric GlobalValue::PrivateLinkage, NamesVal,
195671d5a254SDimitry Andric getInstrProfNamesVarName());
195701095a5dSDimitry Andric NamesSize = CompressedNameStr.size();
1958b1c73532SDimitry Andric setGlobalVariableLargeSection(TT, *NamesVar);
195971d5a254SDimitry Andric NamesVar->setSection(
1960312c0ed1SDimitry Andric ProfileCorrelate == InstrProfCorrelator::BINARY
1961312c0ed1SDimitry Andric ? getInstrProfSectionName(IPSK_covname, TT.getObjectFormat())
1962312c0ed1SDimitry Andric : getInstrProfSectionName(IPSK_name, TT.getObjectFormat()));
1963e6d15924SDimitry Andric // On COFF, it's important to reduce the alignment down to 1 to prevent the
1964e6d15924SDimitry Andric // linker from inserting padding before the start of the names section or
1965e6d15924SDimitry Andric // between names entries.
1966cfca06d7SDimitry Andric NamesVar->setAlignment(Align(1));
1967344a3780SDimitry Andric // NamesVar is used by runtime but not referenced via relocation by other
1968344a3780SDimitry Andric // sections. Conservatively make it linker retained.
196901095a5dSDimitry Andric UsedVars.push_back(NamesVar);
197071d5a254SDimitry Andric
197171d5a254SDimitry Andric for (auto *NamePtr : ReferencedNames)
197271d5a254SDimitry Andric NamePtr->eraseFromParent();
197301095a5dSDimitry Andric }
197401095a5dSDimitry Andric
emitVTableNames()1975ac9a064cSDimitry Andric void InstrLowerer::emitVTableNames() {
1976ac9a064cSDimitry Andric if (!EnableVTableValueProfiling || ReferencedVTables.empty())
1977ac9a064cSDimitry Andric return;
1978ac9a064cSDimitry Andric
1979ac9a064cSDimitry Andric // Collect the PGO names of referenced vtables and compress them.
1980ac9a064cSDimitry Andric std::string CompressedVTableNames;
1981ac9a064cSDimitry Andric if (Error E = collectVTableStrings(ReferencedVTables, CompressedVTableNames,
1982ac9a064cSDimitry Andric DoInstrProfNameCompression)) {
1983ac9a064cSDimitry Andric report_fatal_error(Twine(toString(std::move(E))), false);
1984ac9a064cSDimitry Andric }
1985ac9a064cSDimitry Andric
1986ac9a064cSDimitry Andric auto &Ctx = M.getContext();
1987ac9a064cSDimitry Andric auto *VTableNamesVal = ConstantDataArray::getString(
1988ac9a064cSDimitry Andric Ctx, StringRef(CompressedVTableNames), false /* AddNull */);
1989ac9a064cSDimitry Andric GlobalVariable *VTableNamesVar =
1990ac9a064cSDimitry Andric new GlobalVariable(M, VTableNamesVal->getType(), true /* constant */,
1991ac9a064cSDimitry Andric GlobalValue::PrivateLinkage, VTableNamesVal,
1992ac9a064cSDimitry Andric getInstrProfVTableNamesVarName());
1993ac9a064cSDimitry Andric VTableNamesVar->setSection(
1994ac9a064cSDimitry Andric getInstrProfSectionName(IPSK_vname, TT.getObjectFormat()));
1995ac9a064cSDimitry Andric VTableNamesVar->setAlignment(Align(1));
1996ac9a064cSDimitry Andric // Make VTableNames linker retained.
1997ac9a064cSDimitry Andric UsedVars.push_back(VTableNamesVar);
1998ac9a064cSDimitry Andric }
1999ac9a064cSDimitry Andric
emitRegistration()2000312c0ed1SDimitry Andric void InstrLowerer::emitRegistration() {
2001e6d15924SDimitry Andric if (!needsRuntimeRegistrationOfSectionRange(TT))
2002dd58ef01SDimitry Andric return;
2003dd58ef01SDimitry Andric
200467c32a98SDimitry Andric // Construct the function.
2005312c0ed1SDimitry Andric auto *VoidTy = Type::getVoidTy(M.getContext());
2006312c0ed1SDimitry Andric auto *VoidPtrTy = PointerType::getUnqual(M.getContext());
2007312c0ed1SDimitry Andric auto *Int64Ty = Type::getInt64Ty(M.getContext());
200867c32a98SDimitry Andric auto *RegisterFTy = FunctionType::get(VoidTy, false);
200967c32a98SDimitry Andric auto *RegisterF = Function::Create(RegisterFTy, GlobalValue::InternalLinkage,
2010dd58ef01SDimitry Andric getInstrProfRegFuncsName(), M);
201101095a5dSDimitry Andric RegisterF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
201201095a5dSDimitry Andric if (Options.NoRedZone)
201301095a5dSDimitry Andric RegisterF->addFnAttr(Attribute::NoRedZone);
201467c32a98SDimitry Andric
201585d8b2bbSDimitry Andric auto *RuntimeRegisterTy = FunctionType::get(VoidTy, VoidPtrTy, false);
201667c32a98SDimitry Andric auto *RuntimeRegisterF =
201767c32a98SDimitry Andric Function::Create(RuntimeRegisterTy, GlobalVariable::ExternalLinkage,
2018dd58ef01SDimitry Andric getInstrProfRegFuncName(), M);
201967c32a98SDimitry Andric
2020312c0ed1SDimitry Andric IRBuilder<> IRB(BasicBlock::Create(M.getContext(), "", RegisterF));
2021344a3780SDimitry Andric for (Value *Data : CompilerUsedVars)
2022344a3780SDimitry Andric if (!isa<Function>(Data))
2023b1c73532SDimitry Andric IRB.CreateCall(RuntimeRegisterF, Data);
202467c32a98SDimitry Andric for (Value *Data : UsedVars)
2025b7eb8e35SDimitry Andric if (Data != NamesVar && !isa<Function>(Data))
2026b1c73532SDimitry Andric IRB.CreateCall(RuntimeRegisterF, Data);
202701095a5dSDimitry Andric
202801095a5dSDimitry Andric if (NamesVar) {
202901095a5dSDimitry Andric Type *ParamTypes[] = {VoidPtrTy, Int64Ty};
203001095a5dSDimitry Andric auto *NamesRegisterTy =
2031e3b55780SDimitry Andric FunctionType::get(VoidTy, ArrayRef(ParamTypes), false);
203201095a5dSDimitry Andric auto *NamesRegisterF =
203301095a5dSDimitry Andric Function::Create(NamesRegisterTy, GlobalVariable::ExternalLinkage,
203401095a5dSDimitry Andric getInstrProfNamesRegFuncName(), M);
2035b1c73532SDimitry Andric IRB.CreateCall(NamesRegisterF, {NamesVar, IRB.getInt64(NamesSize)});
203601095a5dSDimitry Andric }
203701095a5dSDimitry Andric
203867c32a98SDimitry Andric IRB.CreateRetVoid();
203967c32a98SDimitry Andric }
204067c32a98SDimitry Andric
emitRuntimeHook()2041312c0ed1SDimitry Andric bool InstrLowerer::emitRuntimeHook() {
2042c0981da4SDimitry Andric // We expect the linker to be invoked with -u<hook_var> flag for Linux
2043c0981da4SDimitry Andric // in which case there is no need to emit the external variable.
2044e3b55780SDimitry Andric if (TT.isOSLinux() || TT.isOSAIX())
2045eb11fae6SDimitry Andric return false;
204667c32a98SDimitry Andric
204767c32a98SDimitry Andric // If the module's provided its own runtime, we don't need to do anything.
2048312c0ed1SDimitry Andric if (M.getGlobalVariable(getInstrProfRuntimeHookVarName()))
2049eb11fae6SDimitry Andric return false;
205067c32a98SDimitry Andric
205167c32a98SDimitry Andric // Declare an external variable that will pull in the runtime initialization.
2052312c0ed1SDimitry Andric auto *Int32Ty = Type::getInt32Ty(M.getContext());
205367c32a98SDimitry Andric auto *Var =
2054312c0ed1SDimitry Andric new GlobalVariable(M, Int32Ty, false, GlobalValue::ExternalLinkage,
2055dd58ef01SDimitry Andric nullptr, getInstrProfRuntimeHookVarName());
20561f917f69SDimitry Andric Var->setVisibility(GlobalValue::HiddenVisibility);
205767c32a98SDimitry Andric
2058145449b1SDimitry Andric if (TT.isOSBinFormatELF() && !TT.isPS()) {
2059c0981da4SDimitry Andric // Mark the user variable as used so that it isn't stripped out.
2060c0981da4SDimitry Andric CompilerUsedVars.push_back(Var);
2061c0981da4SDimitry Andric } else {
206267c32a98SDimitry Andric // Make a function that uses it.
2063dd58ef01SDimitry Andric auto *User = Function::Create(FunctionType::get(Int32Ty, false),
2064dd58ef01SDimitry Andric GlobalValue::LinkOnceODRLinkage,
2065dd58ef01SDimitry Andric getInstrProfRuntimeHookVarUseFuncName(), M);
206667c32a98SDimitry Andric User->addFnAttr(Attribute::NoInline);
206701095a5dSDimitry Andric if (Options.NoRedZone)
206801095a5dSDimitry Andric User->addFnAttr(Attribute::NoRedZone);
20695a5ac124SDimitry Andric User->setVisibility(GlobalValue::HiddenVisibility);
2070e6d15924SDimitry Andric if (TT.supportsCOMDAT())
2071312c0ed1SDimitry Andric User->setComdat(M.getOrInsertComdat(User->getName()));
207267c32a98SDimitry Andric
2073312c0ed1SDimitry Andric IRBuilder<> IRB(BasicBlock::Create(M.getContext(), "", User));
2074e6d15924SDimitry Andric auto *Load = IRB.CreateLoad(Int32Ty, Var);
207567c32a98SDimitry Andric IRB.CreateRet(Load);
207667c32a98SDimitry Andric
2077c0981da4SDimitry Andric // Mark the function as used so that it isn't stripped out.
2078344a3780SDimitry Andric CompilerUsedVars.push_back(User);
2079c0981da4SDimitry Andric }
2080eb11fae6SDimitry Andric return true;
208167c32a98SDimitry Andric }
208267c32a98SDimitry Andric
emitUses()2083312c0ed1SDimitry Andric void InstrLowerer::emitUses() {
2084344a3780SDimitry Andric // The metadata sections are parallel arrays. Optimizers (e.g.
2085344a3780SDimitry Andric // GlobalOpt/ConstantMerge) may not discard associated sections as a unit, so
2086344a3780SDimitry Andric // we conservatively retain all unconditionally in the compiler.
2087344a3780SDimitry Andric //
2088c0981da4SDimitry Andric // On ELF and Mach-O, the linker can guarantee the associated sections will be
2089c0981da4SDimitry Andric // retained or discarded as a unit, so llvm.compiler.used is sufficient.
2090c0981da4SDimitry Andric // Similarly on COFF, if prof data is not referenced by code we use one comdat
2091c0981da4SDimitry Andric // and ensure this GC property as well. Otherwise, we have to conservatively
2092c0981da4SDimitry Andric // make all of the sections retained by the linker.
2093c0981da4SDimitry Andric if (TT.isOSBinFormatELF() || TT.isOSBinFormatMachO() ||
2094ac9a064cSDimitry Andric (TT.isOSBinFormatCOFF() && !DataReferencedByCode))
2095312c0ed1SDimitry Andric appendToCompilerUsed(M, CompilerUsedVars);
2096344a3780SDimitry Andric else
2097312c0ed1SDimitry Andric appendToUsed(M, CompilerUsedVars);
2098344a3780SDimitry Andric
2099344a3780SDimitry Andric // We do not add proper references from used metadata sections to NamesVar and
2100344a3780SDimitry Andric // VNodesVar, so we have to be conservative and place them in llvm.used
2101344a3780SDimitry Andric // regardless of the target,
2102312c0ed1SDimitry Andric appendToUsed(M, UsedVars);
210367c32a98SDimitry Andric }
210467c32a98SDimitry Andric
emitInitialization()2105312c0ed1SDimitry Andric void InstrLowerer::emitInitialization() {
2106e6d15924SDimitry Andric // Create ProfileFileName variable. Don't don't this for the
2107e6d15924SDimitry Andric // context-sensitive instrumentation lowering: This lowering is after
2108e6d15924SDimitry Andric // LTO/ThinLTO linking. Pass PGOInstrumentationGenCreateVar should
2109e6d15924SDimitry Andric // have already create the variable before LTO/ThinLTO linking.
2110e6d15924SDimitry Andric if (!IsCS)
2111312c0ed1SDimitry Andric createProfileFileNameVar(M, Options.InstrProfileOutput);
2112312c0ed1SDimitry Andric Function *RegisterF = M.getFunction(getInstrProfRegFuncsName());
2113b915e9e0SDimitry Andric if (!RegisterF)
211401095a5dSDimitry Andric return;
211567c32a98SDimitry Andric
211667c32a98SDimitry Andric // Create the initialization function.
2117312c0ed1SDimitry Andric auto *VoidTy = Type::getVoidTy(M.getContext());
2118dd58ef01SDimitry Andric auto *F = Function::Create(FunctionType::get(VoidTy, false),
2119dd58ef01SDimitry Andric GlobalValue::InternalLinkage,
2120dd58ef01SDimitry Andric getInstrProfInitFuncName(), M);
212101095a5dSDimitry Andric F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
212267c32a98SDimitry Andric F->addFnAttr(Attribute::NoInline);
212301095a5dSDimitry Andric if (Options.NoRedZone)
212401095a5dSDimitry Andric F->addFnAttr(Attribute::NoRedZone);
212567c32a98SDimitry Andric
212667c32a98SDimitry Andric // Add the basic block and the necessary calls.
2127312c0ed1SDimitry Andric IRBuilder<> IRB(BasicBlock::Create(M.getContext(), "", F));
21285a5ac124SDimitry Andric IRB.CreateCall(RegisterF, {});
212967c32a98SDimitry Andric IRB.CreateRetVoid();
213067c32a98SDimitry Andric
2131312c0ed1SDimitry Andric appendToGlobalCtors(M, F, 0);
213267c32a98SDimitry Andric }
2133ac9a064cSDimitry Andric
2134ac9a064cSDimitry Andric namespace llvm {
2135ac9a064cSDimitry Andric // Create the variable for profile sampling.
createProfileSamplingVar(Module & M)2136ac9a064cSDimitry Andric void createProfileSamplingVar(Module &M) {
2137ac9a064cSDimitry Andric const StringRef VarName(INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_SAMPLING_VAR));
2138ac9a064cSDimitry Andric IntegerType *SamplingVarTy;
2139ac9a064cSDimitry Andric Constant *ValueZero;
2140ac9a064cSDimitry Andric if (SampledInstrPeriod.getValue() <= USHRT_MAX) {
2141ac9a064cSDimitry Andric SamplingVarTy = Type::getInt16Ty(M.getContext());
2142ac9a064cSDimitry Andric ValueZero = Constant::getIntegerValue(SamplingVarTy, APInt(16, 0));
2143ac9a064cSDimitry Andric } else {
2144ac9a064cSDimitry Andric SamplingVarTy = Type::getInt32Ty(M.getContext());
2145ac9a064cSDimitry Andric ValueZero = Constant::getIntegerValue(SamplingVarTy, APInt(32, 0));
2146ac9a064cSDimitry Andric }
2147ac9a064cSDimitry Andric auto SamplingVar = new GlobalVariable(
2148ac9a064cSDimitry Andric M, SamplingVarTy, false, GlobalValue::WeakAnyLinkage, ValueZero, VarName);
2149ac9a064cSDimitry Andric SamplingVar->setVisibility(GlobalValue::DefaultVisibility);
2150ac9a064cSDimitry Andric SamplingVar->setThreadLocal(true);
2151ac9a064cSDimitry Andric Triple TT(M.getTargetTriple());
2152ac9a064cSDimitry Andric if (TT.supportsCOMDAT()) {
2153ac9a064cSDimitry Andric SamplingVar->setLinkage(GlobalValue::ExternalLinkage);
2154ac9a064cSDimitry Andric SamplingVar->setComdat(M.getOrInsertComdat(VarName));
2155ac9a064cSDimitry Andric }
2156ac9a064cSDimitry Andric appendToCompilerUsed(M, SamplingVar);
2157ac9a064cSDimitry Andric }
2158ac9a064cSDimitry Andric } // namespace llvm
2159