139d628a0SDimitry Andric //===-- InstrProfiling.cpp - Frontend instrumentation based profiling -----===//
239d628a0SDimitry Andric //
339d628a0SDimitry Andric // The LLVM Compiler Infrastructure
439d628a0SDimitry Andric //
539d628a0SDimitry Andric // This file is distributed under the University of Illinois Open Source
639d628a0SDimitry Andric // License. See LICENSE.TXT for details.
739d628a0SDimitry Andric //
839d628a0SDimitry Andric //===----------------------------------------------------------------------===//
939d628a0SDimitry Andric //
107d523365SDimitry Andric // This pass lowers instrprof_* intrinsics emitted by a frontend for profiling.
117d523365SDimitry Andric // It also builds the data structures and initialization code needed for
127d523365SDimitry Andric // updating execution counts and emitting the profile at runtime.
1339d628a0SDimitry Andric //
1439d628a0SDimitry Andric //===----------------------------------------------------------------------===//
1539d628a0SDimitry Andric
164ba319b5SDimitry Andric #include "llvm/Transforms/Instrumentation/InstrProfiling.h"
177a7e6055SDimitry Andric #include "llvm/ADT/ArrayRef.h"
187a7e6055SDimitry Andric #include "llvm/ADT/SmallVector.h"
197a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
2039d628a0SDimitry Andric #include "llvm/ADT/Triple.h"
217a7e6055SDimitry Andric #include "llvm/ADT/Twine.h"
22edd7eaddSDimitry Andric #include "llvm/Analysis/LoopInfo.h"
23d88c1a5aSDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
247a7e6055SDimitry Andric #include "llvm/IR/Attributes.h"
257a7e6055SDimitry Andric #include "llvm/IR/BasicBlock.h"
267a7e6055SDimitry Andric #include "llvm/IR/Constant.h"
277a7e6055SDimitry Andric #include "llvm/IR/Constants.h"
287a7e6055SDimitry Andric #include "llvm/IR/DerivedTypes.h"
29edd7eaddSDimitry Andric #include "llvm/IR/Dominators.h"
307a7e6055SDimitry Andric #include "llvm/IR/Function.h"
317a7e6055SDimitry Andric #include "llvm/IR/GlobalValue.h"
327a7e6055SDimitry Andric #include "llvm/IR/GlobalVariable.h"
33db17bf38SDimitry Andric #include "llvm/IR/IRBuilder.h"
347a7e6055SDimitry Andric #include "llvm/IR/Instruction.h"
357a7e6055SDimitry Andric #include "llvm/IR/Instructions.h"
3639d628a0SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
3739d628a0SDimitry Andric #include "llvm/IR/Module.h"
387a7e6055SDimitry Andric #include "llvm/IR/Type.h"
397a7e6055SDimitry Andric #include "llvm/Pass.h"
407d523365SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
417a7e6055SDimitry Andric #include "llvm/Support/Casting.h"
427a7e6055SDimitry Andric #include "llvm/Support/CommandLine.h"
437a7e6055SDimitry Andric #include "llvm/Support/Error.h"
447a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
45edd7eaddSDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
4639d628a0SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
47edd7eaddSDimitry Andric #include "llvm/Transforms/Utils/SSAUpdater.h"
487a7e6055SDimitry Andric #include <algorithm>
497a7e6055SDimitry Andric #include <cassert>
507a7e6055SDimitry Andric #include <cstddef>
517a7e6055SDimitry Andric #include <cstdint>
527a7e6055SDimitry Andric #include <string>
5339d628a0SDimitry Andric
5439d628a0SDimitry Andric using namespace llvm;
5539d628a0SDimitry Andric
5639d628a0SDimitry Andric #define DEBUG_TYPE "instrprof"
5739d628a0SDimitry Andric
587a7e6055SDimitry Andric // The start and end values of precise value profile range for memory
597a7e6055SDimitry Andric // intrinsic sizes
607a7e6055SDimitry Andric cl::opt<std::string> MemOPSizeRange(
617a7e6055SDimitry Andric "memop-size-range",
627a7e6055SDimitry Andric cl::desc("Set the range of size in memory intrinsic calls to be profiled "
637a7e6055SDimitry Andric "precisely, in a format of <start_val>:<end_val>"),
647a7e6055SDimitry Andric cl::init(""));
657a7e6055SDimitry Andric
667a7e6055SDimitry Andric // The value that considered to be large value in memory intrinsic.
677a7e6055SDimitry Andric cl::opt<unsigned> MemOPSizeLarge(
687a7e6055SDimitry Andric "memop-size-large",
697a7e6055SDimitry Andric cl::desc("Set large value thresthold in memory intrinsic size profiling. "
707a7e6055SDimitry Andric "Value of 0 disables the large value profiling."),
717a7e6055SDimitry Andric cl::init(8192));
727a7e6055SDimitry Andric
7339d628a0SDimitry Andric namespace {
7439d628a0SDimitry Andric
753ca95b02SDimitry Andric cl::opt<bool> DoNameCompression("enable-name-compression",
763ca95b02SDimitry Andric cl::desc("Enable name string compression"),
773ca95b02SDimitry Andric cl::init(true));
783ca95b02SDimitry Andric
79f1a29dd3SDimitry Andric cl::opt<bool> DoHashBasedCounterSplit(
80f1a29dd3SDimitry Andric "hash-based-counter-split",
81f1a29dd3SDimitry Andric cl::desc("Rename counter variable of a comdat function based on cfg hash"),
82f1a29dd3SDimitry Andric cl::init(true));
83f1a29dd3SDimitry Andric
843ca95b02SDimitry Andric cl::opt<bool> ValueProfileStaticAlloc(
853ca95b02SDimitry Andric "vp-static-alloc",
863ca95b02SDimitry Andric cl::desc("Do static counter allocation for value profiler"),
873ca95b02SDimitry Andric cl::init(true));
887a7e6055SDimitry Andric
893ca95b02SDimitry Andric cl::opt<double> NumCountersPerValueSite(
903ca95b02SDimitry Andric "vp-counters-per-site",
913ca95b02SDimitry Andric cl::desc("The average number of profile counters allocated "
923ca95b02SDimitry Andric "per value profiling site."),
933ca95b02SDimitry Andric // This is set to a very small value because in real programs, only
943ca95b02SDimitry Andric // a very small percentage of value sites have non-zero targets, e.g, 1/30.
953ca95b02SDimitry Andric // For those sites with non-zero profile, the average number of targets
963ca95b02SDimitry Andric // is usually smaller than 2.
973ca95b02SDimitry Andric cl::init(1.0));
983ca95b02SDimitry Andric
99*b5893f02SDimitry Andric cl::opt<bool> AtomicCounterUpdateAll(
100*b5893f02SDimitry Andric "instrprof-atomic-counter-update-all", cl::ZeroOrMore,
101*b5893f02SDimitry Andric cl::desc("Make all profile counter updates atomic (for testing only)"),
102*b5893f02SDimitry Andric cl::init(false));
103*b5893f02SDimitry Andric
104edd7eaddSDimitry Andric cl::opt<bool> AtomicCounterUpdatePromoted(
105edd7eaddSDimitry Andric "atomic-counter-update-promoted", cl::ZeroOrMore,
106edd7eaddSDimitry Andric cl::desc("Do counter update using atomic fetch add "
107edd7eaddSDimitry Andric " for promoted counters only"),
108edd7eaddSDimitry Andric cl::init(false));
109edd7eaddSDimitry Andric
110edd7eaddSDimitry Andric // If the option is not specified, the default behavior about whether
111edd7eaddSDimitry Andric // counter promotion is done depends on how instrumentaiton lowering
112edd7eaddSDimitry Andric // pipeline is setup, i.e., the default value of true of this option
113edd7eaddSDimitry Andric // does not mean the promotion will be done by default. Explicitly
114edd7eaddSDimitry Andric // setting this option can override the default behavior.
115edd7eaddSDimitry Andric cl::opt<bool> DoCounterPromotion("do-counter-promotion", cl::ZeroOrMore,
116edd7eaddSDimitry Andric cl::desc("Do counter register promotion"),
117edd7eaddSDimitry Andric cl::init(false));
118edd7eaddSDimitry Andric cl::opt<unsigned> MaxNumOfPromotionsPerLoop(
119c4394386SDimitry Andric cl::ZeroOrMore, "max-counter-promotions-per-loop", cl::init(20),
120edd7eaddSDimitry Andric cl::desc("Max number counter promotions per loop to avoid"
121edd7eaddSDimitry Andric " increasing register pressure too much"));
122edd7eaddSDimitry Andric
123edd7eaddSDimitry Andric // A debug option
124edd7eaddSDimitry Andric cl::opt<int>
125edd7eaddSDimitry Andric MaxNumOfPromotions(cl::ZeroOrMore, "max-counter-promotions", cl::init(-1),
126edd7eaddSDimitry Andric cl::desc("Max number of allowed counter promotions"));
127edd7eaddSDimitry Andric
128c4394386SDimitry Andric cl::opt<unsigned> SpeculativeCounterPromotionMaxExiting(
129c4394386SDimitry Andric cl::ZeroOrMore, "speculative-counter-promotion-max-exiting", cl::init(3),
130c4394386SDimitry Andric cl::desc("The max number of exiting blocks of a loop to allow "
131c4394386SDimitry Andric " speculative counter promotion"));
132c4394386SDimitry Andric
133c4394386SDimitry Andric cl::opt<bool> SpeculativeCounterPromotionToLoop(
134c4394386SDimitry Andric cl::ZeroOrMore, "speculative-counter-promotion-to-loop", cl::init(false),
135c4394386SDimitry Andric cl::desc("When the option is false, if the target block is in a loop, "
136c4394386SDimitry Andric "the promotion will be disallowed unless the promoted counter "
137c4394386SDimitry Andric " update can be further/iteratively promoted into an acyclic "
138c4394386SDimitry Andric " region."));
139c4394386SDimitry Andric
140c4394386SDimitry Andric cl::opt<bool> IterativeCounterPromotion(
141c4394386SDimitry Andric cl::ZeroOrMore, "iterative-counter-promotion", cl::init(true),
142c4394386SDimitry Andric cl::desc("Allow counter promotion across the whole loop nest."));
143edd7eaddSDimitry Andric
1443ca95b02SDimitry Andric class InstrProfilingLegacyPass : public ModulePass {
1453ca95b02SDimitry Andric InstrProfiling InstrProf;
1463ca95b02SDimitry Andric
14739d628a0SDimitry Andric public:
14839d628a0SDimitry Andric static char ID;
1497a7e6055SDimitry Andric
InstrProfilingLegacyPass()1507a7e6055SDimitry Andric InstrProfilingLegacyPass() : ModulePass(ID) {}
InstrProfilingLegacyPass(const InstrProfOptions & Options)1513ca95b02SDimitry Andric InstrProfilingLegacyPass(const InstrProfOptions &Options)
1523ca95b02SDimitry Andric : ModulePass(ID), InstrProf(Options) {}
1537a7e6055SDimitry Andric
getPassName() const154d88c1a5aSDimitry Andric StringRef getPassName() const override {
15539d628a0SDimitry Andric return "Frontend instrumentation-based coverage lowering";
15639d628a0SDimitry Andric }
15739d628a0SDimitry Andric
runOnModule(Module & M)158d88c1a5aSDimitry Andric bool runOnModule(Module &M) override {
159d88c1a5aSDimitry Andric return InstrProf.run(M, getAnalysis<TargetLibraryInfoWrapperPass>().getTLI());
160d88c1a5aSDimitry Andric }
16139d628a0SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const16239d628a0SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
16339d628a0SDimitry Andric AU.setPreservesCFG();
164d88c1a5aSDimitry Andric AU.addRequired<TargetLibraryInfoWrapperPass>();
16539d628a0SDimitry Andric }
16639d628a0SDimitry Andric };
16739d628a0SDimitry Andric
168c4394386SDimitry Andric ///
169edd7eaddSDimitry Andric /// A helper class to promote one counter RMW operation in the loop
170edd7eaddSDimitry Andric /// into register update.
171edd7eaddSDimitry Andric ///
172edd7eaddSDimitry Andric /// RWM update for the counter will be sinked out of the loop after
173edd7eaddSDimitry Andric /// the transformation.
174edd7eaddSDimitry Andric ///
175edd7eaddSDimitry Andric class PGOCounterPromoterHelper : public LoadAndStorePromoter {
176edd7eaddSDimitry 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)177c4394386SDimitry Andric PGOCounterPromoterHelper(
178c4394386SDimitry Andric Instruction *L, Instruction *S, SSAUpdater &SSA, Value *Init,
179c4394386SDimitry Andric BasicBlock *PH, ArrayRef<BasicBlock *> ExitBlocks,
180c4394386SDimitry Andric ArrayRef<Instruction *> InsertPts,
181c4394386SDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCands,
182c4394386SDimitry Andric LoopInfo &LI)
183edd7eaddSDimitry Andric : LoadAndStorePromoter({L, S}, SSA), Store(S), ExitBlocks(ExitBlocks),
184c4394386SDimitry Andric InsertPts(InsertPts), LoopToCandidates(LoopToCands), LI(LI) {
185edd7eaddSDimitry Andric assert(isa<LoadInst>(L));
186edd7eaddSDimitry Andric assert(isa<StoreInst>(S));
187edd7eaddSDimitry Andric SSA.AddAvailableValue(PH, Init);
188edd7eaddSDimitry Andric }
189c4394386SDimitry Andric
doExtraRewritesBeforeFinalDeletion() const190edd7eaddSDimitry Andric void doExtraRewritesBeforeFinalDeletion() const override {
191edd7eaddSDimitry Andric for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
192edd7eaddSDimitry Andric BasicBlock *ExitBlock = ExitBlocks[i];
193edd7eaddSDimitry Andric Instruction *InsertPos = InsertPts[i];
194edd7eaddSDimitry Andric // Get LiveIn value into the ExitBlock. If there are multiple
195edd7eaddSDimitry Andric // predecessors, the value is defined by a PHI node in this
196edd7eaddSDimitry Andric // block.
197edd7eaddSDimitry Andric Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);
198edd7eaddSDimitry Andric Value *Addr = cast<StoreInst>(Store)->getPointerOperand();
199edd7eaddSDimitry Andric IRBuilder<> Builder(InsertPos);
200edd7eaddSDimitry Andric if (AtomicCounterUpdatePromoted)
201c4394386SDimitry Andric // automic update currently can only be promoted across the current
202c4394386SDimitry Andric // loop, not the whole loop nest.
203edd7eaddSDimitry Andric Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, LiveInValue,
204edd7eaddSDimitry Andric AtomicOrdering::SequentiallyConsistent);
205edd7eaddSDimitry Andric else {
206edd7eaddSDimitry Andric LoadInst *OldVal = Builder.CreateLoad(Addr, "pgocount.promoted");
207edd7eaddSDimitry Andric auto *NewVal = Builder.CreateAdd(OldVal, LiveInValue);
208c4394386SDimitry Andric auto *NewStore = Builder.CreateStore(NewVal, Addr);
209c4394386SDimitry Andric
210c4394386SDimitry Andric // Now update the parent loop's candidate list:
211c4394386SDimitry Andric if (IterativeCounterPromotion) {
212c4394386SDimitry Andric auto *TargetLoop = LI.getLoopFor(ExitBlock);
213c4394386SDimitry Andric if (TargetLoop)
214c4394386SDimitry Andric LoopToCandidates[TargetLoop].emplace_back(OldVal, NewStore);
215c4394386SDimitry Andric }
216edd7eaddSDimitry Andric }
217edd7eaddSDimitry Andric }
218edd7eaddSDimitry Andric }
219edd7eaddSDimitry Andric
220edd7eaddSDimitry Andric private:
221edd7eaddSDimitry Andric Instruction *Store;
222edd7eaddSDimitry Andric ArrayRef<BasicBlock *> ExitBlocks;
223edd7eaddSDimitry Andric ArrayRef<Instruction *> InsertPts;
224c4394386SDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCandidates;
225c4394386SDimitry Andric LoopInfo &LI;
226edd7eaddSDimitry Andric };
227edd7eaddSDimitry Andric
228edd7eaddSDimitry Andric /// A helper class to do register promotion for all profile counter
229edd7eaddSDimitry Andric /// updates in a loop.
230edd7eaddSDimitry Andric ///
231edd7eaddSDimitry Andric class PGOCounterPromoter {
232edd7eaddSDimitry Andric public:
PGOCounterPromoter(DenseMap<Loop *,SmallVector<LoadStorePair,8>> & LoopToCands,Loop & CurLoop,LoopInfo & LI)233c4394386SDimitry Andric PGOCounterPromoter(
234c4394386SDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCands,
235c4394386SDimitry Andric Loop &CurLoop, LoopInfo &LI)
236c4394386SDimitry Andric : LoopToCandidates(LoopToCands), ExitBlocks(), InsertPts(), L(CurLoop),
237c4394386SDimitry Andric LI(LI) {
238edd7eaddSDimitry Andric
239edd7eaddSDimitry Andric SmallVector<BasicBlock *, 8> LoopExitBlocks;
240edd7eaddSDimitry Andric SmallPtrSet<BasicBlock *, 8> BlockSet;
241c4394386SDimitry Andric L.getExitBlocks(LoopExitBlocks);
242edd7eaddSDimitry Andric
243edd7eaddSDimitry Andric for (BasicBlock *ExitBlock : LoopExitBlocks) {
244edd7eaddSDimitry Andric if (BlockSet.insert(ExitBlock).second) {
245edd7eaddSDimitry Andric ExitBlocks.push_back(ExitBlock);
246edd7eaddSDimitry Andric InsertPts.push_back(&*ExitBlock->getFirstInsertionPt());
247edd7eaddSDimitry Andric }
248edd7eaddSDimitry Andric }
249edd7eaddSDimitry Andric }
250edd7eaddSDimitry Andric
run(int64_t * NumPromoted)251edd7eaddSDimitry Andric bool run(int64_t *NumPromoted) {
2522cab237bSDimitry Andric // Skip 'infinite' loops:
2532cab237bSDimitry Andric if (ExitBlocks.size() == 0)
2542cab237bSDimitry Andric return false;
255c4394386SDimitry Andric unsigned MaxProm = getMaxNumOfPromotionsInLoop(&L);
256c4394386SDimitry Andric if (MaxProm == 0)
257edd7eaddSDimitry Andric return false;
258edd7eaddSDimitry Andric
259edd7eaddSDimitry Andric unsigned Promoted = 0;
260c4394386SDimitry Andric for (auto &Cand : LoopToCandidates[&L]) {
261edd7eaddSDimitry Andric
262edd7eaddSDimitry Andric SmallVector<PHINode *, 4> NewPHIs;
263edd7eaddSDimitry Andric SSAUpdater SSA(&NewPHIs);
264edd7eaddSDimitry Andric Value *InitVal = ConstantInt::get(Cand.first->getType(), 0);
265c4394386SDimitry Andric
266edd7eaddSDimitry Andric PGOCounterPromoterHelper Promoter(Cand.first, Cand.second, SSA, InitVal,
267c4394386SDimitry Andric L.getLoopPreheader(), ExitBlocks,
268c4394386SDimitry Andric InsertPts, LoopToCandidates, LI);
269edd7eaddSDimitry Andric Promoter.run(SmallVector<Instruction *, 2>({Cand.first, Cand.second}));
270edd7eaddSDimitry Andric Promoted++;
271c4394386SDimitry Andric if (Promoted >= MaxProm)
272edd7eaddSDimitry Andric break;
273c4394386SDimitry Andric
274edd7eaddSDimitry Andric (*NumPromoted)++;
275edd7eaddSDimitry Andric if (MaxNumOfPromotions != -1 && *NumPromoted >= MaxNumOfPromotions)
276edd7eaddSDimitry Andric break;
277edd7eaddSDimitry Andric }
278edd7eaddSDimitry Andric
2794ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << Promoted << " counters promoted for loop (depth="
280c4394386SDimitry Andric << L.getLoopDepth() << ")\n");
281edd7eaddSDimitry Andric return Promoted != 0;
282edd7eaddSDimitry Andric }
283edd7eaddSDimitry Andric
284edd7eaddSDimitry Andric private:
allowSpeculativeCounterPromotion(Loop * LP)285c4394386SDimitry Andric bool allowSpeculativeCounterPromotion(Loop *LP) {
286c4394386SDimitry Andric SmallVector<BasicBlock *, 8> ExitingBlocks;
287c4394386SDimitry Andric L.getExitingBlocks(ExitingBlocks);
288c4394386SDimitry Andric // Not considierered speculative.
289c4394386SDimitry Andric if (ExitingBlocks.size() == 1)
290c4394386SDimitry Andric return true;
291c4394386SDimitry Andric if (ExitingBlocks.size() > SpeculativeCounterPromotionMaxExiting)
292c4394386SDimitry Andric return false;
293c4394386SDimitry Andric return true;
294c4394386SDimitry Andric }
295c4394386SDimitry Andric
296c4394386SDimitry Andric // Returns the max number of Counter Promotions for LP.
getMaxNumOfPromotionsInLoop(Loop * LP)297c4394386SDimitry Andric unsigned getMaxNumOfPromotionsInLoop(Loop *LP) {
298c4394386SDimitry Andric // We can't insert into a catchswitch.
299c4394386SDimitry Andric SmallVector<BasicBlock *, 8> LoopExitBlocks;
300c4394386SDimitry Andric LP->getExitBlocks(LoopExitBlocks);
301c4394386SDimitry Andric if (llvm::any_of(LoopExitBlocks, [](BasicBlock *Exit) {
302c4394386SDimitry Andric return isa<CatchSwitchInst>(Exit->getTerminator());
303c4394386SDimitry Andric }))
304c4394386SDimitry Andric return 0;
305c4394386SDimitry Andric
306c4394386SDimitry Andric if (!LP->hasDedicatedExits())
307c4394386SDimitry Andric return 0;
308c4394386SDimitry Andric
309c4394386SDimitry Andric BasicBlock *PH = LP->getLoopPreheader();
310c4394386SDimitry Andric if (!PH)
311c4394386SDimitry Andric return 0;
312c4394386SDimitry Andric
313c4394386SDimitry Andric SmallVector<BasicBlock *, 8> ExitingBlocks;
314c4394386SDimitry Andric LP->getExitingBlocks(ExitingBlocks);
315c4394386SDimitry Andric // Not considierered speculative.
316c4394386SDimitry Andric if (ExitingBlocks.size() == 1)
317c4394386SDimitry Andric return MaxNumOfPromotionsPerLoop;
318c4394386SDimitry Andric
319c4394386SDimitry Andric if (ExitingBlocks.size() > SpeculativeCounterPromotionMaxExiting)
320c4394386SDimitry Andric return 0;
321c4394386SDimitry Andric
322c4394386SDimitry Andric // Whether the target block is in a loop does not matter:
323c4394386SDimitry Andric if (SpeculativeCounterPromotionToLoop)
324c4394386SDimitry Andric return MaxNumOfPromotionsPerLoop;
325c4394386SDimitry Andric
326c4394386SDimitry Andric // Now check the target block:
327c4394386SDimitry Andric unsigned MaxProm = MaxNumOfPromotionsPerLoop;
328c4394386SDimitry Andric for (auto *TargetBlock : LoopExitBlocks) {
329c4394386SDimitry Andric auto *TargetLoop = LI.getLoopFor(TargetBlock);
330c4394386SDimitry Andric if (!TargetLoop)
331c4394386SDimitry Andric continue;
332c4394386SDimitry Andric unsigned MaxPromForTarget = getMaxNumOfPromotionsInLoop(TargetLoop);
333c4394386SDimitry Andric unsigned PendingCandsInTarget = LoopToCandidates[TargetLoop].size();
334c4394386SDimitry Andric MaxProm =
335c4394386SDimitry Andric std::min(MaxProm, std::max(MaxPromForTarget, PendingCandsInTarget) -
336c4394386SDimitry Andric PendingCandsInTarget);
337c4394386SDimitry Andric }
338c4394386SDimitry Andric return MaxProm;
339c4394386SDimitry Andric }
340c4394386SDimitry Andric
341c4394386SDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> &LoopToCandidates;
342edd7eaddSDimitry Andric SmallVector<BasicBlock *, 8> ExitBlocks;
343edd7eaddSDimitry Andric SmallVector<Instruction *, 8> InsertPts;
344c4394386SDimitry Andric Loop &L;
345c4394386SDimitry Andric LoopInfo &LI;
346edd7eaddSDimitry Andric };
347edd7eaddSDimitry Andric
3487a7e6055SDimitry Andric } // end anonymous namespace
34939d628a0SDimitry Andric
run(Module & M,ModuleAnalysisManager & AM)350d88c1a5aSDimitry Andric PreservedAnalyses InstrProfiling::run(Module &M, ModuleAnalysisManager &AM) {
351d88c1a5aSDimitry Andric auto &TLI = AM.getResult<TargetLibraryAnalysis>(M);
352d88c1a5aSDimitry Andric if (!run(M, TLI))
3533ca95b02SDimitry Andric return PreservedAnalyses::all();
3543ca95b02SDimitry Andric
3553ca95b02SDimitry Andric return PreservedAnalyses::none();
3563ca95b02SDimitry Andric }
3573ca95b02SDimitry Andric
3583ca95b02SDimitry Andric char InstrProfilingLegacyPass::ID = 0;
359d88c1a5aSDimitry Andric INITIALIZE_PASS_BEGIN(
360d88c1a5aSDimitry Andric InstrProfilingLegacyPass, "instrprof",
361d88c1a5aSDimitry Andric "Frontend instrumentation-based coverage lowering.", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)362d88c1a5aSDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
363d88c1a5aSDimitry Andric INITIALIZE_PASS_END(
364d88c1a5aSDimitry Andric InstrProfilingLegacyPass, "instrprof",
365d88c1a5aSDimitry Andric "Frontend instrumentation-based coverage lowering.", false, false)
36639d628a0SDimitry Andric
3673ca95b02SDimitry Andric ModulePass *
3683ca95b02SDimitry Andric llvm::createInstrProfilingLegacyPass(const InstrProfOptions &Options) {
3693ca95b02SDimitry Andric return new InstrProfilingLegacyPass(Options);
37039d628a0SDimitry Andric }
37139d628a0SDimitry Andric
castToIncrementInst(Instruction * Instr)372d88c1a5aSDimitry Andric static InstrProfIncrementInst *castToIncrementInst(Instruction *Instr) {
373d88c1a5aSDimitry Andric InstrProfIncrementInst *Inc = dyn_cast<InstrProfIncrementInstStep>(Instr);
374d88c1a5aSDimitry Andric if (Inc)
375d88c1a5aSDimitry Andric return Inc;
376d88c1a5aSDimitry Andric return dyn_cast<InstrProfIncrementInst>(Instr);
377d88c1a5aSDimitry Andric }
378d88c1a5aSDimitry Andric
lowerIntrinsics(Function * F)379edd7eaddSDimitry Andric bool InstrProfiling::lowerIntrinsics(Function *F) {
380edd7eaddSDimitry Andric bool MadeChange = false;
381edd7eaddSDimitry Andric PromotionCandidates.clear();
382edd7eaddSDimitry Andric for (BasicBlock &BB : *F) {
383edd7eaddSDimitry Andric for (auto I = BB.begin(), E = BB.end(); I != E;) {
384edd7eaddSDimitry Andric auto Instr = I++;
385edd7eaddSDimitry Andric InstrProfIncrementInst *Inc = castToIncrementInst(&*Instr);
386edd7eaddSDimitry Andric if (Inc) {
387edd7eaddSDimitry Andric lowerIncrement(Inc);
388edd7eaddSDimitry Andric MadeChange = true;
389edd7eaddSDimitry Andric } else if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(Instr)) {
390edd7eaddSDimitry Andric lowerValueProfileInst(Ind);
391edd7eaddSDimitry Andric MadeChange = true;
392edd7eaddSDimitry Andric }
393edd7eaddSDimitry Andric }
394edd7eaddSDimitry Andric }
395edd7eaddSDimitry Andric
396edd7eaddSDimitry Andric if (!MadeChange)
397edd7eaddSDimitry Andric return false;
398edd7eaddSDimitry Andric
399edd7eaddSDimitry Andric promoteCounterLoadStores(F);
400edd7eaddSDimitry Andric return true;
401edd7eaddSDimitry Andric }
402edd7eaddSDimitry Andric
isCounterPromotionEnabled() const403edd7eaddSDimitry Andric bool InstrProfiling::isCounterPromotionEnabled() const {
404edd7eaddSDimitry Andric if (DoCounterPromotion.getNumOccurrences() > 0)
405edd7eaddSDimitry Andric return DoCounterPromotion;
406edd7eaddSDimitry Andric
407edd7eaddSDimitry Andric return Options.DoCounterPromotion;
408edd7eaddSDimitry Andric }
409edd7eaddSDimitry Andric
promoteCounterLoadStores(Function * F)410edd7eaddSDimitry Andric void InstrProfiling::promoteCounterLoadStores(Function *F) {
411edd7eaddSDimitry Andric if (!isCounterPromotionEnabled())
412edd7eaddSDimitry Andric return;
413edd7eaddSDimitry Andric
414edd7eaddSDimitry Andric DominatorTree DT(*F);
415edd7eaddSDimitry Andric LoopInfo LI(DT);
416edd7eaddSDimitry Andric DenseMap<Loop *, SmallVector<LoadStorePair, 8>> LoopPromotionCandidates;
417edd7eaddSDimitry Andric
418edd7eaddSDimitry Andric for (const auto &LoadStore : PromotionCandidates) {
419edd7eaddSDimitry Andric auto *CounterLoad = LoadStore.first;
420edd7eaddSDimitry Andric auto *CounterStore = LoadStore.second;
421edd7eaddSDimitry Andric BasicBlock *BB = CounterLoad->getParent();
422edd7eaddSDimitry Andric Loop *ParentLoop = LI.getLoopFor(BB);
423edd7eaddSDimitry Andric if (!ParentLoop)
424edd7eaddSDimitry Andric continue;
425edd7eaddSDimitry Andric LoopPromotionCandidates[ParentLoop].emplace_back(CounterLoad, CounterStore);
426edd7eaddSDimitry Andric }
427edd7eaddSDimitry Andric
428edd7eaddSDimitry Andric SmallVector<Loop *, 4> Loops = LI.getLoopsInPreorder();
429edd7eaddSDimitry Andric
430c4394386SDimitry Andric // Do a post-order traversal of the loops so that counter updates can be
431c4394386SDimitry Andric // iteratively hoisted outside the loop nest.
432c4394386SDimitry Andric for (auto *Loop : llvm::reverse(Loops)) {
433c4394386SDimitry Andric PGOCounterPromoter Promoter(LoopPromotionCandidates, *Loop, LI);
434edd7eaddSDimitry Andric Promoter.run(&TotalCountersPromoted);
435edd7eaddSDimitry Andric }
436edd7eaddSDimitry Andric }
437edd7eaddSDimitry Andric
4384ba319b5SDimitry Andric /// Check if the module contains uses of any profiling intrinsics.
containsProfilingIntrinsics(Module & M)4394ba319b5SDimitry Andric static bool containsProfilingIntrinsics(Module &M) {
4404ba319b5SDimitry Andric if (auto *F = M.getFunction(
4414ba319b5SDimitry Andric Intrinsic::getName(llvm::Intrinsic::instrprof_increment)))
4424ba319b5SDimitry Andric if (!F->use_empty())
4434ba319b5SDimitry Andric return true;
4444ba319b5SDimitry Andric if (auto *F = M.getFunction(
4454ba319b5SDimitry Andric Intrinsic::getName(llvm::Intrinsic::instrprof_increment_step)))
4464ba319b5SDimitry Andric if (!F->use_empty())
4474ba319b5SDimitry Andric return true;
4484ba319b5SDimitry Andric if (auto *F = M.getFunction(
4494ba319b5SDimitry Andric Intrinsic::getName(llvm::Intrinsic::instrprof_value_profile)))
4504ba319b5SDimitry Andric if (!F->use_empty())
4514ba319b5SDimitry Andric return true;
4524ba319b5SDimitry Andric return false;
4534ba319b5SDimitry Andric }
45439d628a0SDimitry Andric
run(Module & M,const TargetLibraryInfo & TLI)4554ba319b5SDimitry Andric bool InstrProfiling::run(Module &M, const TargetLibraryInfo &TLI) {
45639d628a0SDimitry Andric this->M = &M;
457d88c1a5aSDimitry Andric this->TLI = &TLI;
4583ca95b02SDimitry Andric NamesVar = nullptr;
4593ca95b02SDimitry Andric NamesSize = 0;
4607d523365SDimitry Andric ProfileDataMap.clear();
46139d628a0SDimitry Andric UsedVars.clear();
4627a7e6055SDimitry Andric getMemOPSizeRangeFromOption(MemOPSizeRange, MemOPSizeRangeStart,
4637a7e6055SDimitry Andric MemOPSizeRangeLast);
4647a7e6055SDimitry Andric TT = Triple(M.getTargetTriple());
46539d628a0SDimitry Andric
4664ba319b5SDimitry Andric // Emit the runtime hook even if no counters are present.
4674ba319b5SDimitry Andric bool MadeChange = emitRuntimeHook();
4684ba319b5SDimitry Andric
4694ba319b5SDimitry Andric // Improve compile time by avoiding linear scans when there is no work.
4704ba319b5SDimitry Andric GlobalVariable *CoverageNamesVar =
4714ba319b5SDimitry Andric M.getNamedGlobal(getCoverageUnusedNamesVarName());
4724ba319b5SDimitry Andric if (!containsProfilingIntrinsics(M) && !CoverageNamesVar)
4734ba319b5SDimitry Andric return MadeChange;
4744ba319b5SDimitry Andric
4757d523365SDimitry Andric // We did not know how many value sites there would be inside
4767d523365SDimitry Andric // the instrumented function. This is counting the number of instrumented
4777d523365SDimitry Andric // target value sites to enter it as field in the profile data variable.
4783ca95b02SDimitry Andric for (Function &F : M) {
4793ca95b02SDimitry Andric InstrProfIncrementInst *FirstProfIncInst = nullptr;
48039d628a0SDimitry Andric for (BasicBlock &BB : F)
4813ca95b02SDimitry Andric for (auto I = BB.begin(), E = BB.end(); I != E; I++)
4823ca95b02SDimitry Andric if (auto *Ind = dyn_cast<InstrProfValueProfileInst>(I))
4837d523365SDimitry Andric computeNumValueSiteCounts(Ind);
4843ca95b02SDimitry Andric else if (FirstProfIncInst == nullptr)
4853ca95b02SDimitry Andric FirstProfIncInst = dyn_cast<InstrProfIncrementInst>(I);
4863ca95b02SDimitry Andric
4873ca95b02SDimitry Andric // Value profiling intrinsic lowering requires per-function profile data
4883ca95b02SDimitry Andric // variable to be created first.
4893ca95b02SDimitry Andric if (FirstProfIncInst != nullptr)
4903ca95b02SDimitry Andric static_cast<void>(getOrCreateRegionCounters(FirstProfIncInst));
4913ca95b02SDimitry Andric }
4927d523365SDimitry Andric
4937d523365SDimitry Andric for (Function &F : M)
494edd7eaddSDimitry Andric MadeChange |= lowerIntrinsics(&F);
4957d523365SDimitry Andric
4964ba319b5SDimitry Andric if (CoverageNamesVar) {
497444ed5c5SDimitry Andric lowerCoverageData(CoverageNamesVar);
49844f7b0dcSDimitry Andric MadeChange = true;
49944f7b0dcSDimitry Andric }
5007d523365SDimitry Andric
50139d628a0SDimitry Andric if (!MadeChange)
50239d628a0SDimitry Andric return false;
50339d628a0SDimitry Andric
5043ca95b02SDimitry Andric emitVNodes();
5053ca95b02SDimitry Andric emitNameData();
50639d628a0SDimitry Andric emitRegistration();
50739d628a0SDimitry Andric emitUses();
50839d628a0SDimitry Andric emitInitialization();
50939d628a0SDimitry Andric return true;
51039d628a0SDimitry Andric }
51139d628a0SDimitry Andric
getOrInsertValueProfilingCall(Module & M,const TargetLibraryInfo & TLI,bool IsRange=false)512d88c1a5aSDimitry Andric static Constant *getOrInsertValueProfilingCall(Module &M,
5137a7e6055SDimitry Andric const TargetLibraryInfo &TLI,
5147a7e6055SDimitry Andric bool IsRange = false) {
5157d523365SDimitry Andric LLVMContext &Ctx = M.getContext();
5167d523365SDimitry Andric auto *ReturnTy = Type::getVoidTy(M.getContext());
5177a7e6055SDimitry Andric
5187a7e6055SDimitry Andric Constant *Res;
5197a7e6055SDimitry Andric if (!IsRange) {
5207d523365SDimitry Andric Type *ParamTypes[] = {
5217d523365SDimitry Andric #define VALUE_PROF_FUNC_PARAM(ParamType, ParamName, ParamLLVMType) ParamLLVMType
5227d523365SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
5237d523365SDimitry Andric };
5247d523365SDimitry Andric auto *ValueProfilingCallTy =
5257d523365SDimitry Andric FunctionType::get(ReturnTy, makeArrayRef(ParamTypes), false);
5267a7e6055SDimitry Andric Res = M.getOrInsertFunction(getInstrProfValueProfFuncName(),
5277d523365SDimitry Andric ValueProfilingCallTy);
5287a7e6055SDimitry Andric } else {
5297a7e6055SDimitry Andric Type *RangeParamTypes[] = {
5307a7e6055SDimitry Andric #define VALUE_RANGE_PROF 1
5317a7e6055SDimitry Andric #define VALUE_PROF_FUNC_PARAM(ParamType, ParamName, ParamLLVMType) ParamLLVMType
5327a7e6055SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
5337a7e6055SDimitry Andric #undef VALUE_RANGE_PROF
5347a7e6055SDimitry Andric };
5357a7e6055SDimitry Andric auto *ValueRangeProfilingCallTy =
5367a7e6055SDimitry Andric FunctionType::get(ReturnTy, makeArrayRef(RangeParamTypes), false);
5377a7e6055SDimitry Andric Res = M.getOrInsertFunction(getInstrProfValueRangeProfFuncName(),
5387a7e6055SDimitry Andric ValueRangeProfilingCallTy);
5397a7e6055SDimitry Andric }
5407a7e6055SDimitry Andric
541d88c1a5aSDimitry Andric if (Function *FunRes = dyn_cast<Function>(Res)) {
542d88c1a5aSDimitry Andric if (auto AK = TLI.getExtAttrForI32Param(false))
543f37b6182SDimitry Andric FunRes->addParamAttr(2, AK);
544d88c1a5aSDimitry Andric }
545d88c1a5aSDimitry Andric return Res;
5467d523365SDimitry Andric }
5477d523365SDimitry Andric
computeNumValueSiteCounts(InstrProfValueProfileInst * Ind)5487d523365SDimitry Andric void InstrProfiling::computeNumValueSiteCounts(InstrProfValueProfileInst *Ind) {
5497d523365SDimitry Andric GlobalVariable *Name = Ind->getName();
5507d523365SDimitry Andric uint64_t ValueKind = Ind->getValueKind()->getZExtValue();
5517d523365SDimitry Andric uint64_t Index = Ind->getIndex()->getZExtValue();
5527d523365SDimitry Andric auto It = ProfileDataMap.find(Name);
5537d523365SDimitry Andric if (It == ProfileDataMap.end()) {
5547d523365SDimitry Andric PerFunctionProfileData PD;
5557d523365SDimitry Andric PD.NumValueSites[ValueKind] = Index + 1;
5567d523365SDimitry Andric ProfileDataMap[Name] = PD;
5577d523365SDimitry Andric } else if (It->second.NumValueSites[ValueKind] <= Index)
5587d523365SDimitry Andric It->second.NumValueSites[ValueKind] = Index + 1;
5597d523365SDimitry Andric }
5607d523365SDimitry Andric
lowerValueProfileInst(InstrProfValueProfileInst * Ind)5617d523365SDimitry Andric void InstrProfiling::lowerValueProfileInst(InstrProfValueProfileInst *Ind) {
5627d523365SDimitry Andric GlobalVariable *Name = Ind->getName();
5637d523365SDimitry Andric auto It = ProfileDataMap.find(Name);
5647d523365SDimitry Andric assert(It != ProfileDataMap.end() && It->second.DataVar &&
5657d523365SDimitry Andric "value profiling detected in function with no counter incerement");
5667d523365SDimitry Andric
5677d523365SDimitry Andric GlobalVariable *DataVar = It->second.DataVar;
5687d523365SDimitry Andric uint64_t ValueKind = Ind->getValueKind()->getZExtValue();
5697d523365SDimitry Andric uint64_t Index = Ind->getIndex()->getZExtValue();
5707d523365SDimitry Andric for (uint32_t Kind = IPVK_First; Kind < ValueKind; ++Kind)
5717d523365SDimitry Andric Index += It->second.NumValueSites[Kind];
5727d523365SDimitry Andric
5737d523365SDimitry Andric IRBuilder<> Builder(Ind);
5747a7e6055SDimitry Andric bool IsRange = (Ind->getValueKind()->getZExtValue() ==
5757a7e6055SDimitry Andric llvm::InstrProfValueKind::IPVK_MemOPSize);
5767a7e6055SDimitry Andric CallInst *Call = nullptr;
5777a7e6055SDimitry Andric if (!IsRange) {
5787d523365SDimitry Andric Value *Args[3] = {Ind->getTargetValue(),
5797d523365SDimitry Andric Builder.CreateBitCast(DataVar, Builder.getInt8PtrTy()),
5807d523365SDimitry Andric Builder.getInt32(Index)};
5817a7e6055SDimitry Andric Call = Builder.CreateCall(getOrInsertValueProfilingCall(*M, *TLI), Args);
5827a7e6055SDimitry Andric } else {
5837a7e6055SDimitry Andric Value *Args[6] = {
5847a7e6055SDimitry Andric Ind->getTargetValue(),
5857a7e6055SDimitry Andric Builder.CreateBitCast(DataVar, Builder.getInt8PtrTy()),
5867a7e6055SDimitry Andric Builder.getInt32(Index),
5877a7e6055SDimitry Andric Builder.getInt64(MemOPSizeRangeStart),
5887a7e6055SDimitry Andric Builder.getInt64(MemOPSizeRangeLast),
5897a7e6055SDimitry Andric Builder.getInt64(MemOPSizeLarge == 0 ? INT64_MIN : MemOPSizeLarge)};
5907a7e6055SDimitry Andric Call =
5917a7e6055SDimitry Andric Builder.CreateCall(getOrInsertValueProfilingCall(*M, *TLI, true), Args);
5927a7e6055SDimitry Andric }
593d88c1a5aSDimitry Andric if (auto AK = TLI->getExtAttrForI32Param(false))
594f37b6182SDimitry Andric Call->addParamAttr(2, AK);
595d88c1a5aSDimitry Andric Ind->replaceAllUsesWith(Call);
5967d523365SDimitry Andric Ind->eraseFromParent();
5977d523365SDimitry Andric }
5987d523365SDimitry Andric
lowerIncrement(InstrProfIncrementInst * Inc)59939d628a0SDimitry Andric void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) {
60039d628a0SDimitry Andric GlobalVariable *Counters = getOrCreateRegionCounters(Inc);
60139d628a0SDimitry Andric
6027d523365SDimitry Andric IRBuilder<> Builder(Inc);
60339d628a0SDimitry Andric uint64_t Index = Inc->getIndex()->getZExtValue();
60497bc6c73SDimitry Andric Value *Addr = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Index);
605*b5893f02SDimitry Andric
606*b5893f02SDimitry Andric if (Options.Atomic || AtomicCounterUpdateAll) {
607*b5893f02SDimitry Andric Builder.CreateAtomicRMW(AtomicRMWInst::Add, Addr, Inc->getStep(),
608*b5893f02SDimitry Andric AtomicOrdering::Monotonic);
609*b5893f02SDimitry Andric } else {
610edd7eaddSDimitry Andric Value *Load = Builder.CreateLoad(Addr, "pgocount");
611edd7eaddSDimitry Andric auto *Count = Builder.CreateAdd(Load, Inc->getStep());
612edd7eaddSDimitry Andric auto *Store = Builder.CreateStore(Count, Addr);
613edd7eaddSDimitry Andric if (isCounterPromotionEnabled())
614edd7eaddSDimitry Andric PromotionCandidates.emplace_back(cast<Instruction>(Load), Store);
615*b5893f02SDimitry Andric }
61639d628a0SDimitry Andric Inc->eraseFromParent();
61739d628a0SDimitry Andric }
61839d628a0SDimitry Andric
lowerCoverageData(GlobalVariable * CoverageNamesVar)619444ed5c5SDimitry Andric void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageNamesVar) {
620444ed5c5SDimitry Andric ConstantArray *Names =
621444ed5c5SDimitry Andric cast<ConstantArray>(CoverageNamesVar->getInitializer());
622444ed5c5SDimitry Andric for (unsigned I = 0, E = Names->getNumOperands(); I < E; ++I) {
623444ed5c5SDimitry Andric Constant *NC = Names->getOperand(I);
624444ed5c5SDimitry Andric Value *V = NC->stripPointerCasts();
62544f7b0dcSDimitry Andric assert(isa<GlobalVariable>(V) && "Missing reference to function name");
62644f7b0dcSDimitry Andric GlobalVariable *Name = cast<GlobalVariable>(V);
62744f7b0dcSDimitry Andric
6283ca95b02SDimitry Andric Name->setLinkage(GlobalValue::PrivateLinkage);
6293ca95b02SDimitry Andric ReferencedNames.push_back(Name);
6307a7e6055SDimitry Andric NC->dropAllReferences();
63144f7b0dcSDimitry Andric }
6327a7e6055SDimitry Andric CoverageNamesVar->eraseFromParent();
63344f7b0dcSDimitry Andric }
63444f7b0dcSDimitry Andric
63539d628a0SDimitry Andric /// Get the name of a profiling variable for a particular function.
getVarName(InstrProfIncrementInst * Inc,StringRef Prefix)6367d523365SDimitry Andric static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) {
6377d523365SDimitry Andric StringRef NamePrefix = getInstrProfNameVarPrefix();
6387d523365SDimitry Andric StringRef Name = Inc->getName()->getName().substr(NamePrefix.size());
639f1a29dd3SDimitry Andric Function *F = Inc->getParent()->getParent();
640f1a29dd3SDimitry Andric Module *M = F->getParent();
641f1a29dd3SDimitry Andric if (!DoHashBasedCounterSplit || !isIRPGOFlagSet(M) ||
642f1a29dd3SDimitry Andric !canRenameComdatFunc(*F))
6437d523365SDimitry Andric return (Prefix + Name).str();
644f1a29dd3SDimitry Andric uint64_t FuncHash = Inc->getHash()->getZExtValue();
645f1a29dd3SDimitry Andric SmallVector<char, 24> HashPostfix;
646f1a29dd3SDimitry Andric if (Name.endswith((Twine(".") + Twine(FuncHash)).toStringRef(HashPostfix)))
647f1a29dd3SDimitry Andric return (Prefix + Name).str();
648f1a29dd3SDimitry Andric return (Prefix + Name + "." + Twine(FuncHash)).str();
6497d523365SDimitry Andric }
6507d523365SDimitry Andric
shouldRecordFunctionAddr(Function * F)6517d523365SDimitry Andric static inline bool shouldRecordFunctionAddr(Function *F) {
6527d523365SDimitry Andric // Check the linkage
65324d58133SDimitry Andric bool HasAvailableExternallyLinkage = F->hasAvailableExternallyLinkage();
6547d523365SDimitry Andric if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() &&
65524d58133SDimitry Andric !HasAvailableExternallyLinkage)
6567d523365SDimitry Andric return true;
65724d58133SDimitry Andric
65824d58133SDimitry Andric // A function marked 'alwaysinline' with available_externally linkage can't
65924d58133SDimitry Andric // have its address taken. Doing so would create an undefined external ref to
66024d58133SDimitry Andric // the function, which would fail to link.
66124d58133SDimitry Andric if (HasAvailableExternallyLinkage &&
66224d58133SDimitry Andric F->hasFnAttribute(Attribute::AlwaysInline))
66324d58133SDimitry Andric return false;
66424d58133SDimitry Andric
6653ca95b02SDimitry Andric // Prohibit function address recording if the function is both internal and
6663ca95b02SDimitry Andric // COMDAT. This avoids the profile data variable referencing internal symbols
6673ca95b02SDimitry Andric // in COMDAT.
6683ca95b02SDimitry Andric if (F->hasLocalLinkage() && F->hasComdat())
6693ca95b02SDimitry Andric return false;
67024d58133SDimitry Andric
6717d523365SDimitry Andric // Check uses of this function for other than direct calls or invokes to it.
6723ca95b02SDimitry Andric // Inline virtual functions have linkeOnceODR linkage. When a key method
6733ca95b02SDimitry Andric // exists, the vtable will only be emitted in the TU where the key method
6743ca95b02SDimitry Andric // is defined. In a TU where vtable is not available, the function won't
6753ca95b02SDimitry Andric // be 'addresstaken'. If its address is not recorded here, the profile data
6763ca95b02SDimitry Andric // with missing address may be picked by the linker leading to missing
6773ca95b02SDimitry Andric // indirect call target info.
6783ca95b02SDimitry Andric return F->hasAddressTaken() || F->hasLinkOnceLinkage();
6797d523365SDimitry Andric }
6807d523365SDimitry Andric
getOrCreateProfileComdat(Module & M,Function & F,InstrProfIncrementInst * Inc)6813ca95b02SDimitry Andric static inline Comdat *getOrCreateProfileComdat(Module &M, Function &F,
6827d523365SDimitry Andric InstrProfIncrementInst *Inc) {
6833ca95b02SDimitry Andric if (!needsComdatForCounter(F, M))
6843ca95b02SDimitry Andric return nullptr;
6853ca95b02SDimitry Andric
6867d523365SDimitry Andric // COFF format requires a COMDAT section to have a key symbol with the same
6873ca95b02SDimitry Andric // name. The linker targeting COFF also requires that the COMDAT
6887d523365SDimitry Andric // a section is associated to must precede the associating section. For this
6893ca95b02SDimitry Andric // reason, we must choose the counter var's name as the name of the comdat.
6907d523365SDimitry Andric StringRef ComdatPrefix = (Triple(M.getTargetTriple()).isOSBinFormatCOFF()
6913ca95b02SDimitry Andric ? getInstrProfCountersVarPrefix()
6927d523365SDimitry Andric : getInstrProfComdatPrefix());
6937d523365SDimitry Andric return M.getOrInsertComdat(StringRef(getVarName(Inc, ComdatPrefix)));
69439d628a0SDimitry Andric }
69539d628a0SDimitry Andric
needsRuntimeRegistrationOfSectionRange(const Module & M)6963ca95b02SDimitry Andric static bool needsRuntimeRegistrationOfSectionRange(const Module &M) {
6973ca95b02SDimitry Andric // Don't do this for Darwin. compiler-rt uses linker magic.
6983ca95b02SDimitry Andric if (Triple(M.getTargetTriple()).isOSDarwin())
6993ca95b02SDimitry Andric return false;
7003ca95b02SDimitry Andric
7013ca95b02SDimitry Andric // Use linker script magic to get data/cnts/name start/end.
7023ca95b02SDimitry Andric if (Triple(M.getTargetTriple()).isOSLinux() ||
7033ca95b02SDimitry Andric Triple(M.getTargetTriple()).isOSFreeBSD() ||
704*b5893f02SDimitry Andric Triple(M.getTargetTriple()).isOSNetBSD() ||
7054ba319b5SDimitry Andric Triple(M.getTargetTriple()).isOSFuchsia() ||
7063ca95b02SDimitry Andric Triple(M.getTargetTriple()).isPS4CPU())
7073ca95b02SDimitry Andric return false;
7083ca95b02SDimitry Andric
7093ca95b02SDimitry Andric return true;
7103ca95b02SDimitry Andric }
7113ca95b02SDimitry Andric
71239d628a0SDimitry Andric GlobalVariable *
getOrCreateRegionCounters(InstrProfIncrementInst * Inc)71339d628a0SDimitry Andric InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
7147d523365SDimitry Andric GlobalVariable *NamePtr = Inc->getName();
7157d523365SDimitry Andric auto It = ProfileDataMap.find(NamePtr);
7167d523365SDimitry Andric PerFunctionProfileData PD;
7177d523365SDimitry Andric if (It != ProfileDataMap.end()) {
7187d523365SDimitry Andric if (It->second.RegionCounters)
7197d523365SDimitry Andric return It->second.RegionCounters;
7207d523365SDimitry Andric PD = It->second;
7217d523365SDimitry Andric }
72239d628a0SDimitry Andric
7237d523365SDimitry Andric // Move the name variable to the right section. Place them in a COMDAT group
7247d523365SDimitry Andric // if the associated function is a COMDAT. This will make sure that
7257d523365SDimitry Andric // only one copy of counters of the COMDAT function will be emitted after
7267d523365SDimitry Andric // linking.
72797bc6c73SDimitry Andric Function *Fn = Inc->getParent()->getParent();
7287d523365SDimitry Andric Comdat *ProfileVarsComdat = nullptr;
7293ca95b02SDimitry Andric ProfileVarsComdat = getOrCreateProfileComdat(*M, *Fn, Inc);
73039d628a0SDimitry Andric
73139d628a0SDimitry Andric uint64_t NumCounters = Inc->getNumCounters()->getZExtValue();
73239d628a0SDimitry Andric LLVMContext &Ctx = M->getContext();
73339d628a0SDimitry Andric ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters);
73439d628a0SDimitry Andric
73539d628a0SDimitry Andric // Create the counters variable.
7367d523365SDimitry Andric auto *CounterPtr =
7377d523365SDimitry Andric new GlobalVariable(*M, CounterTy, false, NamePtr->getLinkage(),
73839d628a0SDimitry Andric Constant::getNullValue(CounterTy),
7397d523365SDimitry Andric getVarName(Inc, getInstrProfCountersVarPrefix()));
7407d523365SDimitry Andric CounterPtr->setVisibility(NamePtr->getVisibility());
7417a7e6055SDimitry Andric CounterPtr->setSection(
7427a7e6055SDimitry Andric getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat()));
7437d523365SDimitry Andric CounterPtr->setAlignment(8);
7447d523365SDimitry Andric CounterPtr->setComdat(ProfileVarsComdat);
74539d628a0SDimitry Andric
74639d628a0SDimitry Andric auto *Int8PtrTy = Type::getInt8PtrTy(Ctx);
7473ca95b02SDimitry Andric // Allocate statically the array of pointers to value profile nodes for
7483ca95b02SDimitry Andric // the current function.
7493ca95b02SDimitry Andric Constant *ValuesPtrExpr = ConstantPointerNull::get(Int8PtrTy);
7503ca95b02SDimitry Andric if (ValueProfileStaticAlloc && !needsRuntimeRegistrationOfSectionRange(*M)) {
7513ca95b02SDimitry Andric uint64_t NS = 0;
7523ca95b02SDimitry Andric for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
7533ca95b02SDimitry Andric NS += PD.NumValueSites[Kind];
7543ca95b02SDimitry Andric if (NS) {
7553ca95b02SDimitry Andric ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS);
7563ca95b02SDimitry Andric
7573ca95b02SDimitry Andric auto *ValuesVar =
7583ca95b02SDimitry Andric new GlobalVariable(*M, ValuesTy, false, NamePtr->getLinkage(),
7593ca95b02SDimitry Andric Constant::getNullValue(ValuesTy),
7603ca95b02SDimitry Andric getVarName(Inc, getInstrProfValuesVarPrefix()));
7613ca95b02SDimitry Andric ValuesVar->setVisibility(NamePtr->getVisibility());
7627a7e6055SDimitry Andric ValuesVar->setSection(
7637a7e6055SDimitry Andric getInstrProfSectionName(IPSK_vals, TT.getObjectFormat()));
7643ca95b02SDimitry Andric ValuesVar->setAlignment(8);
7653ca95b02SDimitry Andric ValuesVar->setComdat(ProfileVarsComdat);
7663ca95b02SDimitry Andric ValuesPtrExpr =
7677a7e6055SDimitry Andric ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx));
7683ca95b02SDimitry Andric }
7693ca95b02SDimitry Andric }
7703ca95b02SDimitry Andric
7713ca95b02SDimitry Andric // Create data variable.
7727d523365SDimitry Andric auto *Int16Ty = Type::getInt16Ty(Ctx);
7737d523365SDimitry Andric auto *Int16ArrayTy = ArrayType::get(Int16Ty, IPVK_Last + 1);
7747d523365SDimitry Andric Type *DataTypes[] = {
7757d523365SDimitry Andric #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) LLVMType,
7767d523365SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
7777d523365SDimitry Andric };
77839d628a0SDimitry Andric auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes));
7797d523365SDimitry Andric
7803ca95b02SDimitry Andric Constant *FunctionAddr = shouldRecordFunctionAddr(Fn)
7813ca95b02SDimitry Andric ? ConstantExpr::getBitCast(Fn, Int8PtrTy)
7823ca95b02SDimitry Andric : ConstantPointerNull::get(Int8PtrTy);
7837d523365SDimitry Andric
7847d523365SDimitry Andric Constant *Int16ArrayVals[IPVK_Last + 1];
7857d523365SDimitry Andric for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
7867d523365SDimitry Andric Int16ArrayVals[Kind] = ConstantInt::get(Int16Ty, PD.NumValueSites[Kind]);
7877d523365SDimitry Andric
78839d628a0SDimitry Andric Constant *DataVals[] = {
7897d523365SDimitry Andric #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init,
7907d523365SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
7917d523365SDimitry Andric };
7927d523365SDimitry Andric auto *Data = new GlobalVariable(*M, DataTy, false, NamePtr->getLinkage(),
79339d628a0SDimitry Andric ConstantStruct::get(DataTy, DataVals),
7947d523365SDimitry Andric getVarName(Inc, getInstrProfDataVarPrefix()));
7957d523365SDimitry Andric Data->setVisibility(NamePtr->getVisibility());
7967a7e6055SDimitry Andric Data->setSection(getInstrProfSectionName(IPSK_data, TT.getObjectFormat()));
7977d523365SDimitry Andric Data->setAlignment(INSTR_PROF_DATA_ALIGNMENT);
7987d523365SDimitry Andric Data->setComdat(ProfileVarsComdat);
7997d523365SDimitry Andric
8007d523365SDimitry Andric PD.RegionCounters = CounterPtr;
8017d523365SDimitry Andric PD.DataVar = Data;
8027d523365SDimitry Andric ProfileDataMap[NamePtr] = PD;
80339d628a0SDimitry Andric
80439d628a0SDimitry Andric // Mark the data variable as used so that it isn't stripped out.
80539d628a0SDimitry Andric UsedVars.push_back(Data);
8063ca95b02SDimitry Andric // Now that the linkage set by the FE has been passed to the data and counter
8073ca95b02SDimitry Andric // variables, reset Name variable's linkage and visibility to private so that
8083ca95b02SDimitry Andric // it can be removed later by the compiler.
8093ca95b02SDimitry Andric NamePtr->setLinkage(GlobalValue::PrivateLinkage);
8103ca95b02SDimitry Andric // Collect the referenced names to be used by emitNameData.
8113ca95b02SDimitry Andric ReferencedNames.push_back(NamePtr);
81239d628a0SDimitry Andric
8137d523365SDimitry Andric return CounterPtr;
81439d628a0SDimitry Andric }
81539d628a0SDimitry Andric
emitVNodes()8163ca95b02SDimitry Andric void InstrProfiling::emitVNodes() {
8173ca95b02SDimitry Andric if (!ValueProfileStaticAlloc)
81839d628a0SDimitry Andric return;
81939d628a0SDimitry Andric
8203ca95b02SDimitry Andric // For now only support this on platforms that do
8213ca95b02SDimitry Andric // not require runtime registration to discover
8223ca95b02SDimitry Andric // named section start/end.
8233ca95b02SDimitry Andric if (needsRuntimeRegistrationOfSectionRange(*M))
8243ca95b02SDimitry Andric return;
8253ca95b02SDimitry Andric
8263ca95b02SDimitry Andric size_t TotalNS = 0;
8273ca95b02SDimitry Andric for (auto &PD : ProfileDataMap) {
8283ca95b02SDimitry Andric for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
8293ca95b02SDimitry Andric TotalNS += PD.second.NumValueSites[Kind];
8303ca95b02SDimitry Andric }
8313ca95b02SDimitry Andric
8323ca95b02SDimitry Andric if (!TotalNS)
8333ca95b02SDimitry Andric return;
8343ca95b02SDimitry Andric
8353ca95b02SDimitry Andric uint64_t NumCounters = TotalNS * NumCountersPerValueSite;
8363ca95b02SDimitry Andric // Heuristic for small programs with very few total value sites.
8373ca95b02SDimitry Andric // The default value of vp-counters-per-site is chosen based on
8383ca95b02SDimitry Andric // the observation that large apps usually have a low percentage
8393ca95b02SDimitry Andric // of value sites that actually have any profile data, and thus
8403ca95b02SDimitry Andric // the average number of counters per site is low. For small
8413ca95b02SDimitry Andric // apps with very few sites, this may not be true. Bump up the
8423ca95b02SDimitry Andric // number of counters in this case.
8433ca95b02SDimitry Andric #define INSTR_PROF_MIN_VAL_COUNTS 10
8443ca95b02SDimitry Andric if (NumCounters < INSTR_PROF_MIN_VAL_COUNTS)
8453ca95b02SDimitry Andric NumCounters = std::max(INSTR_PROF_MIN_VAL_COUNTS, (int)NumCounters * 2);
8463ca95b02SDimitry Andric
8473ca95b02SDimitry Andric auto &Ctx = M->getContext();
8483ca95b02SDimitry Andric Type *VNodeTypes[] = {
8493ca95b02SDimitry Andric #define INSTR_PROF_VALUE_NODE(Type, LLVMType, Name, Init) LLVMType,
8503ca95b02SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
8513ca95b02SDimitry Andric };
8523ca95b02SDimitry Andric auto *VNodeTy = StructType::get(Ctx, makeArrayRef(VNodeTypes));
8533ca95b02SDimitry Andric
8543ca95b02SDimitry Andric ArrayType *VNodesTy = ArrayType::get(VNodeTy, NumCounters);
8553ca95b02SDimitry Andric auto *VNodesVar = new GlobalVariable(
8567a7e6055SDimitry Andric *M, VNodesTy, false, GlobalValue::PrivateLinkage,
8573ca95b02SDimitry Andric Constant::getNullValue(VNodesTy), getInstrProfVNodesVarName());
8587a7e6055SDimitry Andric VNodesVar->setSection(
8597a7e6055SDimitry Andric getInstrProfSectionName(IPSK_vnodes, TT.getObjectFormat()));
8603ca95b02SDimitry Andric UsedVars.push_back(VNodesVar);
8613ca95b02SDimitry Andric }
8623ca95b02SDimitry Andric
emitNameData()8633ca95b02SDimitry Andric void InstrProfiling::emitNameData() {
8643ca95b02SDimitry Andric std::string UncompressedData;
8653ca95b02SDimitry Andric
8663ca95b02SDimitry Andric if (ReferencedNames.empty())
8673ca95b02SDimitry Andric return;
8683ca95b02SDimitry Andric
8693ca95b02SDimitry Andric std::string CompressedNameStr;
8703ca95b02SDimitry Andric if (Error E = collectPGOFuncNameStrings(ReferencedNames, CompressedNameStr,
8713ca95b02SDimitry Andric DoNameCompression)) {
8727a7e6055SDimitry Andric report_fatal_error(toString(std::move(E)), false);
8733ca95b02SDimitry Andric }
8743ca95b02SDimitry Andric
8753ca95b02SDimitry Andric auto &Ctx = M->getContext();
8767a7e6055SDimitry Andric auto *NamesVal = ConstantDataArray::getString(
8773ca95b02SDimitry Andric Ctx, StringRef(CompressedNameStr), false);
8787a7e6055SDimitry Andric NamesVar = new GlobalVariable(*M, NamesVal->getType(), true,
8797a7e6055SDimitry Andric GlobalValue::PrivateLinkage, NamesVal,
8807a7e6055SDimitry Andric getInstrProfNamesVarName());
8813ca95b02SDimitry Andric NamesSize = CompressedNameStr.size();
8827a7e6055SDimitry Andric NamesVar->setSection(
8837a7e6055SDimitry Andric getInstrProfSectionName(IPSK_name, TT.getObjectFormat()));
8843ca95b02SDimitry Andric UsedVars.push_back(NamesVar);
8857a7e6055SDimitry Andric
8867a7e6055SDimitry Andric for (auto *NamePtr : ReferencedNames)
8877a7e6055SDimitry Andric NamePtr->eraseFromParent();
8883ca95b02SDimitry Andric }
8893ca95b02SDimitry Andric
emitRegistration()8903ca95b02SDimitry Andric void InstrProfiling::emitRegistration() {
8913ca95b02SDimitry Andric if (!needsRuntimeRegistrationOfSectionRange(*M))
8927d523365SDimitry Andric return;
8937d523365SDimitry Andric
89439d628a0SDimitry Andric // Construct the function.
89539d628a0SDimitry Andric auto *VoidTy = Type::getVoidTy(M->getContext());
89639d628a0SDimitry Andric auto *VoidPtrTy = Type::getInt8PtrTy(M->getContext());
8973ca95b02SDimitry Andric auto *Int64Ty = Type::getInt64Ty(M->getContext());
89839d628a0SDimitry Andric auto *RegisterFTy = FunctionType::get(VoidTy, false);
89939d628a0SDimitry Andric auto *RegisterF = Function::Create(RegisterFTy, GlobalValue::InternalLinkage,
9007d523365SDimitry Andric getInstrProfRegFuncsName(), M);
9013ca95b02SDimitry Andric RegisterF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
9023ca95b02SDimitry Andric if (Options.NoRedZone)
9033ca95b02SDimitry Andric RegisterF->addFnAttr(Attribute::NoRedZone);
90439d628a0SDimitry Andric
90597bc6c73SDimitry Andric auto *RuntimeRegisterTy = FunctionType::get(VoidTy, VoidPtrTy, false);
90639d628a0SDimitry Andric auto *RuntimeRegisterF =
90739d628a0SDimitry Andric Function::Create(RuntimeRegisterTy, GlobalVariable::ExternalLinkage,
9087d523365SDimitry Andric getInstrProfRegFuncName(), M);
90939d628a0SDimitry Andric
91039d628a0SDimitry Andric IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", RegisterF));
91139d628a0SDimitry Andric for (Value *Data : UsedVars)
9124ba319b5SDimitry Andric if (Data != NamesVar && !isa<Function>(Data))
91339d628a0SDimitry Andric IRB.CreateCall(RuntimeRegisterF, IRB.CreateBitCast(Data, VoidPtrTy));
9143ca95b02SDimitry Andric
9153ca95b02SDimitry Andric if (NamesVar) {
9163ca95b02SDimitry Andric Type *ParamTypes[] = {VoidPtrTy, Int64Ty};
9173ca95b02SDimitry Andric auto *NamesRegisterTy =
9183ca95b02SDimitry Andric FunctionType::get(VoidTy, makeArrayRef(ParamTypes), false);
9193ca95b02SDimitry Andric auto *NamesRegisterF =
9203ca95b02SDimitry Andric Function::Create(NamesRegisterTy, GlobalVariable::ExternalLinkage,
9213ca95b02SDimitry Andric getInstrProfNamesRegFuncName(), M);
9223ca95b02SDimitry Andric IRB.CreateCall(NamesRegisterF, {IRB.CreateBitCast(NamesVar, VoidPtrTy),
9233ca95b02SDimitry Andric IRB.getInt64(NamesSize)});
9243ca95b02SDimitry Andric }
9253ca95b02SDimitry Andric
92639d628a0SDimitry Andric IRB.CreateRetVoid();
92739d628a0SDimitry Andric }
92839d628a0SDimitry Andric
emitRuntimeHook()9294ba319b5SDimitry Andric bool InstrProfiling::emitRuntimeHook() {
9307d523365SDimitry Andric // We expect the linker to be invoked with -u<hook_var> flag for linux,
9317d523365SDimitry Andric // for which case there is no need to emit the user function.
9327d523365SDimitry Andric if (Triple(M->getTargetTriple()).isOSLinux())
9334ba319b5SDimitry Andric return false;
93439d628a0SDimitry Andric
93539d628a0SDimitry Andric // If the module's provided its own runtime, we don't need to do anything.
9363ca95b02SDimitry Andric if (M->getGlobalVariable(getInstrProfRuntimeHookVarName()))
9374ba319b5SDimitry Andric return false;
93839d628a0SDimitry Andric
93939d628a0SDimitry Andric // Declare an external variable that will pull in the runtime initialization.
94039d628a0SDimitry Andric auto *Int32Ty = Type::getInt32Ty(M->getContext());
94139d628a0SDimitry Andric auto *Var =
94239d628a0SDimitry Andric new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
9437d523365SDimitry Andric nullptr, getInstrProfRuntimeHookVarName());
94439d628a0SDimitry Andric
94539d628a0SDimitry Andric // Make a function that uses it.
9467d523365SDimitry Andric auto *User = Function::Create(FunctionType::get(Int32Ty, false),
9477d523365SDimitry Andric GlobalValue::LinkOnceODRLinkage,
9487d523365SDimitry Andric getInstrProfRuntimeHookVarUseFuncName(), M);
94939d628a0SDimitry Andric User->addFnAttr(Attribute::NoInline);
9503ca95b02SDimitry Andric if (Options.NoRedZone)
9513ca95b02SDimitry Andric User->addFnAttr(Attribute::NoRedZone);
952ff0cc061SDimitry Andric User->setVisibility(GlobalValue::HiddenVisibility);
9533ca95b02SDimitry Andric if (Triple(M->getTargetTriple()).supportsCOMDAT())
9543ca95b02SDimitry Andric User->setComdat(M->getOrInsertComdat(User->getName()));
95539d628a0SDimitry Andric
95639d628a0SDimitry Andric IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", User));
95739d628a0SDimitry Andric auto *Load = IRB.CreateLoad(Var);
95839d628a0SDimitry Andric IRB.CreateRet(Load);
95939d628a0SDimitry Andric
96039d628a0SDimitry Andric // Mark the user variable as used so that it isn't stripped out.
96139d628a0SDimitry Andric UsedVars.push_back(User);
9624ba319b5SDimitry Andric return true;
96339d628a0SDimitry Andric }
96439d628a0SDimitry Andric
emitUses()96539d628a0SDimitry Andric void InstrProfiling::emitUses() {
966d88c1a5aSDimitry Andric if (!UsedVars.empty())
967d88c1a5aSDimitry Andric appendToUsed(*M, UsedVars);
96839d628a0SDimitry Andric }
96939d628a0SDimitry Andric
emitInitialization()97039d628a0SDimitry Andric void InstrProfiling::emitInitialization() {
971d88c1a5aSDimitry Andric StringRef InstrProfileOutput = Options.InstrProfileOutput;
972d88c1a5aSDimitry Andric
973d88c1a5aSDimitry Andric if (!InstrProfileOutput.empty()) {
974d88c1a5aSDimitry Andric // Create variable for profile name.
975d88c1a5aSDimitry Andric Constant *ProfileNameConst =
976d88c1a5aSDimitry Andric ConstantDataArray::getString(M->getContext(), InstrProfileOutput, true);
977d88c1a5aSDimitry Andric GlobalVariable *ProfileNameVar = new GlobalVariable(
978d88c1a5aSDimitry Andric *M, ProfileNameConst->getType(), true, GlobalValue::WeakAnyLinkage,
979d88c1a5aSDimitry Andric ProfileNameConst, INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR));
980d88c1a5aSDimitry Andric if (TT.supportsCOMDAT()) {
981d88c1a5aSDimitry Andric ProfileNameVar->setLinkage(GlobalValue::ExternalLinkage);
982d88c1a5aSDimitry Andric ProfileNameVar->setComdat(M->getOrInsertComdat(
983d88c1a5aSDimitry Andric StringRef(INSTR_PROF_QUOTE(INSTR_PROF_PROFILE_NAME_VAR))));
984d88c1a5aSDimitry Andric }
985d88c1a5aSDimitry Andric }
986ff0cc061SDimitry Andric
9877d523365SDimitry Andric Constant *RegisterF = M->getFunction(getInstrProfRegFuncsName());
988d88c1a5aSDimitry Andric if (!RegisterF)
9893ca95b02SDimitry Andric return;
99039d628a0SDimitry Andric
99139d628a0SDimitry Andric // Create the initialization function.
99239d628a0SDimitry Andric auto *VoidTy = Type::getVoidTy(M->getContext());
9937d523365SDimitry Andric auto *F = Function::Create(FunctionType::get(VoidTy, false),
9947d523365SDimitry Andric GlobalValue::InternalLinkage,
9957d523365SDimitry Andric getInstrProfInitFuncName(), M);
9963ca95b02SDimitry Andric F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
99739d628a0SDimitry Andric F->addFnAttr(Attribute::NoInline);
9983ca95b02SDimitry Andric if (Options.NoRedZone)
9993ca95b02SDimitry Andric F->addFnAttr(Attribute::NoRedZone);
100039d628a0SDimitry Andric
100139d628a0SDimitry Andric // Add the basic block and the necessary calls.
100239d628a0SDimitry Andric IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", F));
1003ff0cc061SDimitry Andric if (RegisterF)
1004ff0cc061SDimitry Andric IRB.CreateCall(RegisterF, {});
100539d628a0SDimitry Andric IRB.CreateRetVoid();
100639d628a0SDimitry Andric
100739d628a0SDimitry Andric appendToGlobalCtors(*M, F, 0);
100839d628a0SDimitry Andric }
1009