1 //===- MachineSizeOpts.cpp - code size optimization related code ----------===//
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 machine IR code size optimization related
10 // code.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/CodeGen/MachineSizeOpts.h"
15 #include "llvm/Analysis/ProfileSummaryInfo.h"
16 #include "llvm/CodeGen/MBFIWrapper.h"
17 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
18 #include "llvm/IR/Function.h"
19 
20 using namespace llvm;
21 
22 extern cl::opt<bool> EnablePGSO;
23 extern cl::opt<bool> PGSOLargeWorkingSetSizeOnly;
24 extern cl::opt<bool> ForcePGSO;
25 extern cl::opt<int> PgsoCutoffInstrProf;
26 extern cl::opt<int> PgsoCutoffSampleProf;
27 
28 namespace {
29 namespace machine_size_opts_detail {
30 
31 /// Like ProfileSummaryInfo::isColdBlock but for MachineBasicBlock.
32 bool isColdBlock(const MachineBasicBlock *MBB,
33                  ProfileSummaryInfo *PSI,
34                  const MachineBlockFrequencyInfo *MBFI) {
35   auto Count = MBFI->getBlockProfileCount(MBB);
36   return Count && PSI->isColdCount(*Count);
37 }
38 
39 bool isColdBlock(BlockFrequency BlockFreq,
40                  ProfileSummaryInfo *PSI,
41                  const MachineBlockFrequencyInfo *MBFI) {
42   auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency());
43   return Count && PSI->isColdCount(*Count);
44 }
45 
46 /// Like ProfileSummaryInfo::isHotBlockNthPercentile but for MachineBasicBlock.
47 static bool isHotBlockNthPercentile(int PercentileCutoff,
48                                     const MachineBasicBlock *MBB,
49                                     ProfileSummaryInfo *PSI,
50                                     const MachineBlockFrequencyInfo *MBFI) {
51   auto Count = MBFI->getBlockProfileCount(MBB);
52   return Count && PSI->isHotCountNthPercentile(PercentileCutoff, *Count);
53 }
54 
55 static bool isHotBlockNthPercentile(int PercentileCutoff,
56                                     BlockFrequency BlockFreq,
57                                     ProfileSummaryInfo *PSI,
58                                     const MachineBlockFrequencyInfo *MBFI) {
59   auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency());
60   return Count && PSI->isHotCountNthPercentile(PercentileCutoff, *Count);
61 }
62 
63 static bool isColdBlockNthPercentile(int PercentileCutoff,
64                                      const MachineBasicBlock *MBB,
65                                      ProfileSummaryInfo *PSI,
66                                      const MachineBlockFrequencyInfo *MBFI) {
67   auto Count = MBFI->getBlockProfileCount(MBB);
68   return Count && PSI->isColdCountNthPercentile(PercentileCutoff, *Count);
69 }
70 
71 static bool isColdBlockNthPercentile(int PercentileCutoff,
72                                      BlockFrequency BlockFreq,
73                                      ProfileSummaryInfo *PSI,
74                                      const MachineBlockFrequencyInfo *MBFI) {
75   auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency());
76   return Count && PSI->isColdCountNthPercentile(PercentileCutoff, *Count);
77 }
78 
79 /// Like ProfileSummaryInfo::isFunctionColdInCallGraph but for
80 /// MachineFunction.
81 bool isFunctionColdInCallGraph(
82     const MachineFunction *MF,
83     ProfileSummaryInfo *PSI,
84     const MachineBlockFrequencyInfo &MBFI) {
85   if (auto FunctionCount = MF->getFunction().getEntryCount())
86     if (!PSI->isColdCount(FunctionCount.getCount()))
87       return false;
88   for (const auto &MBB : *MF)
89     if (!isColdBlock(&MBB, PSI, &MBFI))
90       return false;
91   return true;
92 }
93 
94 /// Like ProfileSummaryInfo::isFunctionHotInCallGraphNthPercentile but for
95 /// MachineFunction.
96 bool isFunctionHotInCallGraphNthPercentile(
97     int PercentileCutoff,
98     const MachineFunction *MF,
99     ProfileSummaryInfo *PSI,
100     const MachineBlockFrequencyInfo &MBFI) {
101   if (auto FunctionCount = MF->getFunction().getEntryCount())
102     if (PSI->isHotCountNthPercentile(PercentileCutoff,
103                                      FunctionCount.getCount()))
104       return true;
105   for (const auto &MBB : *MF)
106     if (isHotBlockNthPercentile(PercentileCutoff, &MBB, PSI, &MBFI))
107       return true;
108   return false;
109 }
110 
111 bool isFunctionColdInCallGraphNthPercentile(
112     int PercentileCutoff, const MachineFunction *MF, ProfileSummaryInfo *PSI,
113     const MachineBlockFrequencyInfo &MBFI) {
114   if (auto FunctionCount = MF->getFunction().getEntryCount())
115     if (!PSI->isColdCountNthPercentile(PercentileCutoff,
116                                        FunctionCount.getCount()))
117       return false;
118   for (const auto &MBB : *MF)
119     if (!isColdBlockNthPercentile(PercentileCutoff, &MBB, PSI, &MBFI))
120       return false;
121   return true;
122 }
123 } // namespace machine_size_opts_detail
124 
125 struct MachineBasicBlockBFIAdapter {
126   static bool isFunctionColdInCallGraph(const MachineFunction *MF,
127                                         ProfileSummaryInfo *PSI,
128                                         const MachineBlockFrequencyInfo &MBFI) {
129     return machine_size_opts_detail::isFunctionColdInCallGraph(MF, PSI, MBFI);
130   }
131   static bool isFunctionHotInCallGraphNthPercentile(
132       int CutOff,
133       const MachineFunction *MF,
134       ProfileSummaryInfo *PSI,
135       const MachineBlockFrequencyInfo &MBFI) {
136     return machine_size_opts_detail::isFunctionHotInCallGraphNthPercentile(
137         CutOff, MF, PSI, MBFI);
138   }
139   static bool isFunctionColdInCallGraphNthPercentile(
140       int CutOff, const MachineFunction *MF, ProfileSummaryInfo *PSI,
141       const MachineBlockFrequencyInfo &MBFI) {
142     return machine_size_opts_detail::isFunctionColdInCallGraphNthPercentile(
143         CutOff, MF, PSI, MBFI);
144   }
145   static bool isColdBlock(const MachineBasicBlock *MBB,
146                           ProfileSummaryInfo *PSI,
147                           const MachineBlockFrequencyInfo *MBFI) {
148     return machine_size_opts_detail::isColdBlock(MBB, PSI, MBFI);
149   }
150   static bool isColdBlock(BlockFrequency BlockFreq,
151                           ProfileSummaryInfo *PSI,
152                           const MachineBlockFrequencyInfo *MBFI) {
153     return machine_size_opts_detail::isColdBlock(BlockFreq, PSI, MBFI);
154   }
155   static bool isHotBlockNthPercentile(int CutOff,
156                                       const MachineBasicBlock *MBB,
157                                       ProfileSummaryInfo *PSI,
158                                       const MachineBlockFrequencyInfo *MBFI) {
159     return machine_size_opts_detail::isHotBlockNthPercentile(
160         CutOff, MBB, PSI, MBFI);
161   }
162   static bool isHotBlockNthPercentile(int CutOff,
163                                       BlockFrequency BlockFreq,
164                                       ProfileSummaryInfo *PSI,
165                                       const MachineBlockFrequencyInfo *MBFI) {
166     return machine_size_opts_detail::isHotBlockNthPercentile(
167         CutOff, BlockFreq, PSI, MBFI);
168   }
169   static bool isColdBlockNthPercentile(int CutOff, const MachineBasicBlock *MBB,
170                                        ProfileSummaryInfo *PSI,
171                                        const MachineBlockFrequencyInfo *MBFI) {
172     return machine_size_opts_detail::isColdBlockNthPercentile(CutOff, MBB, PSI,
173                                                               MBFI);
174   }
175   static bool isColdBlockNthPercentile(int CutOff, BlockFrequency BlockFreq,
176                                        ProfileSummaryInfo *PSI,
177                                        const MachineBlockFrequencyInfo *MBFI) {
178     return machine_size_opts_detail::isColdBlockNthPercentile(CutOff, BlockFreq,
179                                                               PSI, MBFI);
180   }
181 };
182 } // end anonymous namespace
183 
184 bool llvm::shouldOptimizeForSize(const MachineFunction *MF,
185                                  ProfileSummaryInfo *PSI,
186                                  const MachineBlockFrequencyInfo *MBFI,
187                                  PGSOQueryType QueryType) {
188   return shouldFuncOptimizeForSizeImpl<MachineBasicBlockBFIAdapter>(
189       MF, PSI, MBFI, QueryType);
190 }
191 
192 bool llvm::shouldOptimizeForSize(const MachineBasicBlock *MBB,
193                                  ProfileSummaryInfo *PSI,
194                                  const MachineBlockFrequencyInfo *MBFI,
195                                  PGSOQueryType QueryType) {
196   assert(MBB);
197   return shouldOptimizeForSizeImpl<MachineBasicBlockBFIAdapter>(
198       MBB, PSI, MBFI, QueryType);
199 }
200 
201 bool llvm::shouldOptimizeForSize(const MachineBasicBlock *MBB,
202                                  ProfileSummaryInfo *PSI,
203                                  MBFIWrapper *MBFIW,
204                                  PGSOQueryType QueryType) {
205   assert(MBB);
206   if (!PSI || !MBFIW)
207     return false;
208   BlockFrequency BlockFreq = MBFIW->getBlockFreq(MBB);
209   return shouldOptimizeForSizeImpl<MachineBasicBlockBFIAdapter>(
210       BlockFreq, PSI, &MBFIW->getMBFI(), QueryType);
211 }
212