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/ProfileSummaryInfo.h"
17 #include "llvm/Support/CommandLine.h"
18 
19 namespace llvm {
20 extern cl::opt<bool> EnablePGSO;
21 extern cl::opt<bool> PGSOLargeWorkingSetSizeOnly;
22 extern cl::opt<bool> PGSOColdCodeOnly;
23 extern cl::opt<bool> PGSOColdCodeOnlyForInstrPGO;
24 extern cl::opt<bool> PGSOColdCodeOnlyForSamplePGO;
25 extern cl::opt<bool> PGSOColdCodeOnlyForPartialSamplePGO;
26 extern cl::opt<bool> ForcePGSO;
27 extern cl::opt<int> PgsoCutoffInstrProf;
28 extern cl::opt<int> PgsoCutoffSampleProf;
29 
30 class BasicBlock;
31 class BlockFrequencyInfo;
32 class Function;
33 
34 enum class PGSOQueryType {
35   IRPass, // A query call from an IR-level transform pass.
36   Test,   // A query call from a unit test.
37   Other,  // Others.
38 };
39 
40 static inline bool isPGSOColdCodeOnly(ProfileSummaryInfo *PSI) {
41   return PGSOColdCodeOnly ||
42          (PSI->hasInstrumentationProfile() && PGSOColdCodeOnlyForInstrPGO) ||
43          (PSI->hasSampleProfile() &&
44           ((!PSI->hasPartialSampleProfile() && PGSOColdCodeOnlyForSamplePGO) ||
45            (PSI->hasPartialSampleProfile() &&
46             PGSOColdCodeOnlyForPartialSamplePGO))) ||
47          (PGSOLargeWorkingSetSizeOnly && !PSI->hasLargeWorkingSetSize());
48 }
49 
50 template<typename AdapterT, typename FuncT, typename BFIT>
51 bool shouldFuncOptimizeForSizeImpl(const FuncT *F, ProfileSummaryInfo *PSI,
52                                    BFIT *BFI, PGSOQueryType QueryType) {
53   assert(F);
54   if (!PSI || !BFI || !PSI->hasProfileSummary())
55     return false;
56   if (ForcePGSO)
57     return true;
58   if (!EnablePGSO)
59     return false;
60   if (isPGSOColdCodeOnly(PSI))
61     return AdapterT::isFunctionColdInCallGraph(F, PSI, *BFI);
62   if (PSI->hasSampleProfile())
63     // The "isCold" check seems to work better for Sample PGO as it could have
64     // many profile-unannotated functions.
65     return AdapterT::isFunctionColdInCallGraphNthPercentile(
66         PgsoCutoffSampleProf, F, PSI, *BFI);
67   return !AdapterT::isFunctionHotInCallGraphNthPercentile(PgsoCutoffInstrProf,
68                                                           F, PSI, *BFI);
69 }
70 
71 template<typename AdapterT, typename BlockTOrBlockFreq, typename BFIT>
72 bool shouldOptimizeForSizeImpl(BlockTOrBlockFreq BBOrBlockFreq, ProfileSummaryInfo *PSI,
73                                BFIT *BFI, PGSOQueryType QueryType) {
74   if (!PSI || !BFI || !PSI->hasProfileSummary())
75     return false;
76   if (ForcePGSO)
77     return true;
78   if (!EnablePGSO)
79     return false;
80   if (isPGSOColdCodeOnly(PSI))
81     return AdapterT::isColdBlock(BBOrBlockFreq, PSI, BFI);
82   if (PSI->hasSampleProfile())
83     // The "isCold" check seems to work better for Sample PGO as it could have
84     // many profile-unannotated functions.
85     return AdapterT::isColdBlockNthPercentile(PgsoCutoffSampleProf,
86                                               BBOrBlockFreq, PSI, BFI);
87   return !AdapterT::isHotBlockNthPercentile(PgsoCutoffInstrProf, BBOrBlockFreq,
88                                             PSI, BFI);
89 }
90 
91 /// Returns true if function \p F is suggested to be size-optimized based on the
92 /// profile.
93 bool shouldOptimizeForSize(const Function *F, ProfileSummaryInfo *PSI,
94                            BlockFrequencyInfo *BFI,
95                            PGSOQueryType QueryType = PGSOQueryType::Other);
96 
97 /// Returns true if basic block \p BB is suggested to be size-optimized based on
98 /// the profile.
99 bool shouldOptimizeForSize(const BasicBlock *BB, ProfileSummaryInfo *PSI,
100                            BlockFrequencyInfo *BFI,
101                            PGSOQueryType QueryType = PGSOQueryType::Other);
102 
103 } // end namespace llvm
104 
105 #endif // LLVM_TRANSFORMS_UTILS_SIZEOPTS_H
106