1//===- llvm/Transforms/Utils/SizeOpts.h - size optimization -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains some shared code size optimization related code.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_TRANSFORMS_UTILS_SIZEOPTS_H
14#define LLVM_TRANSFORMS_UTILS_SIZEOPTS_H
15
16#include "llvm/Analysis/BlockFrequencyInfo.h"
17#include "llvm/Analysis/ProfileSummaryInfo.h"
18#include "llvm/Support/CommandLine.h"
19
20extern llvm::cl::opt<bool> EnablePGSO;
21extern llvm::cl::opt<bool> PGSOLargeWorkingSetSizeOnly;
22extern llvm::cl::opt<bool> PGSOColdCodeOnly;
23extern llvm::cl::opt<bool> PGSOColdCodeOnlyForInstrPGO;
24extern llvm::cl::opt<bool> PGSOColdCodeOnlyForSamplePGO;
25extern llvm::cl::opt<bool> PGSOColdCodeOnlyForPartialSamplePGO;
26extern llvm::cl::opt<bool> ForcePGSO;
27extern llvm::cl::opt<int> PgsoCutoffInstrProf;
28extern llvm::cl::opt<int> PgsoCutoffSampleProf;
29
30namespace llvm {
31
32class BasicBlock;
33class BlockFrequencyInfo;
34class Function;
35
36enum class PGSOQueryType {
37 IRPass, // A query call from an IR-level transform pass.
38 Test, // A query call from a unit test.
39 Other, // Others.
40};
41
42static inline bool isPGSOColdCodeOnly(ProfileSummaryInfo *PSI) {
43 return PGSOColdCodeOnly ||
44 (PSI->hasInstrumentationProfile() && PGSOColdCodeOnlyForInstrPGO) ||
45 (PSI->hasSampleProfile() &&
46 ((!PSI->hasPartialSampleProfile() && PGSOColdCodeOnlyForSamplePGO) ||
47 (PSI->hasPartialSampleProfile() &&
48 PGSOColdCodeOnlyForPartialSamplePGO))) ||
49 (PGSOLargeWorkingSetSizeOnly && !PSI->hasLargeWorkingSetSize());
50}
51
52template<typename AdapterT, typename FuncT, typename BFIT>
53bool shouldFuncOptimizeForSizeImpl(const FuncT *F, ProfileSummaryInfo *PSI,
54 BFIT *BFI, PGSOQueryType QueryType) {
55 assert(F);
56 if (!PSI || !BFI || !PSI->hasProfileSummary())
57 return false;
58 if (ForcePGSO)
59 return true;
60 if (!EnablePGSO)
61 return false;
62 if (isPGSOColdCodeOnly(PSI))
63 return AdapterT::isFunctionColdInCallGraph(F, PSI, *BFI);
64 if (PSI->hasSampleProfile())
65 // The "isCold" check seems to work better for Sample PGO as it could have
66 // many profile-unannotated functions.
67 return AdapterT::isFunctionColdInCallGraphNthPercentile(
68 PgsoCutoffSampleProf, F, PSI, *BFI);
69 return !AdapterT::isFunctionHotInCallGraphNthPercentile(PgsoCutoffInstrProf,
70 F, PSI, *BFI);
71}
72
73template<typename AdapterT, typename BlockTOrBlockFreq, typename BFIT>
74bool shouldOptimizeForSizeImpl(BlockTOrBlockFreq BBOrBlockFreq, ProfileSummaryInfo *PSI,
75 BFIT *BFI, PGSOQueryType QueryType) {
76 if (!PSI || !BFI || !PSI->hasProfileSummary())
77 return false;
78 if (ForcePGSO)
79 return true;
80 if (!EnablePGSO)
81 return false;
82 if (isPGSOColdCodeOnly(PSI))
83 return AdapterT::isColdBlock(BBOrBlockFreq, PSI, BFI);
84 if (PSI->hasSampleProfile())
85 // The "isCold" check seems to work better for Sample PGO as it could have
86 // many profile-unannotated functions.
87 return AdapterT::isColdBlockNthPercentile(PgsoCutoffSampleProf,
88 BBOrBlockFreq, PSI, BFI);
89 return !AdapterT::isHotBlockNthPercentile(PgsoCutoffInstrProf, BBOrBlockFreq,
90 PSI, BFI);
91}
92
93/// Returns true if function \p F is suggested to be size-optimized based on the
94/// profile.
95bool shouldOptimizeForSize(const Function *F, ProfileSummaryInfo *PSI,
96 BlockFrequencyInfo *BFI,
97 PGSOQueryType QueryType = PGSOQueryType::Other);
98
99/// Returns true if basic block \p BB is suggested to be size-optimized based on
100/// the profile.
101bool shouldOptimizeForSize(const BasicBlock *BB, ProfileSummaryInfo *PSI,
102 BlockFrequencyInfo *BFI,
103 PGSOQueryType QueryType = PGSOQueryType::Other);
104
105} // end namespace llvm
106
107#endif // LLVM_TRANSFORMS_UTILS_SIZEOPTS_H
108