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/CodeGen/MBFIWrapper.h"
16 #include "llvm/Analysis/ProfileSummaryInfo.h"
17 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
18 
19 using namespace llvm;
20 
21 extern cl::opt<bool> EnablePGSO;
22 extern cl::opt<bool> PGSOLargeWorkingSetSizeOnly;
23 extern cl::opt<bool> ForcePGSO;
24 extern cl::opt<int> PgsoCutoffInstrProf;
25 extern cl::opt<int> PgsoCutoffSampleProf;
26 
27 namespace machine_size_opts_detail {
28 
29 /// Like ProfileSummaryInfo::isColdBlock but for MachineBasicBlock.
30 bool isColdBlock(const MachineBasicBlock *MBB,
31                  ProfileSummaryInfo *PSI,
32                  const MachineBlockFrequencyInfo *MBFI) {
33   auto Count = MBFI->getBlockProfileCount(MBB);
34   return Count && PSI->isColdCount(*Count);
35 }
36 
37 bool isColdBlock(BlockFrequency BlockFreq,
38                  ProfileSummaryInfo *PSI,
39                  const MachineBlockFrequencyInfo *MBFI) {
40   auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency());
41   return Count && PSI->isColdCount(*Count);
42 }
43 
44 /// Like ProfileSummaryInfo::isHotBlockNthPercentile but for MachineBasicBlock.
45 static bool isHotBlockNthPercentile(int PercentileCutoff,
46                                     const MachineBasicBlock *MBB,
47                                     ProfileSummaryInfo *PSI,
48                                     const MachineBlockFrequencyInfo *MBFI) {
49   auto Count = MBFI->getBlockProfileCount(MBB);
50   return Count && PSI->isHotCountNthPercentile(PercentileCutoff, *Count);
51 }
52 
53 static bool isHotBlockNthPercentile(int PercentileCutoff,
54                                     BlockFrequency BlockFreq,
55                                     ProfileSummaryInfo *PSI,
56                                     const MachineBlockFrequencyInfo *MBFI) {
57   auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency());
58   return Count && PSI->isHotCountNthPercentile(PercentileCutoff, *Count);
59 }
60 
61 /// Like ProfileSummaryInfo::isFunctionColdInCallGraph but for
62 /// MachineFunction.
63 bool isFunctionColdInCallGraph(
64     const MachineFunction *MF,
65     ProfileSummaryInfo *PSI,
66     const MachineBlockFrequencyInfo &MBFI) {
67   if (auto FunctionCount = MF->getFunction().getEntryCount())
68     if (!PSI->isColdCount(FunctionCount.getCount()))
69       return false;
70   for (const auto &MBB : *MF)
71     if (!isColdBlock(&MBB, PSI, &MBFI))
72       return false;
73   return true;
74 }
75 
76 /// Like ProfileSummaryInfo::isFunctionHotInCallGraphNthPercentile but for
77 /// MachineFunction.
78 bool isFunctionHotInCallGraphNthPercentile(
79     int PercentileCutoff,
80     const MachineFunction *MF,
81     ProfileSummaryInfo *PSI,
82     const MachineBlockFrequencyInfo &MBFI) {
83   if (auto FunctionCount = MF->getFunction().getEntryCount())
84     if (PSI->isHotCountNthPercentile(PercentileCutoff,
85                                      FunctionCount.getCount()))
86       return true;
87   for (const auto &MBB : *MF)
88     if (isHotBlockNthPercentile(PercentileCutoff, &MBB, PSI, &MBFI))
89       return true;
90   return false;
91 }
92 } // namespace machine_size_opts_detail
93 
94 namespace {
95 struct MachineBasicBlockBFIAdapter {
96   static bool isFunctionColdInCallGraph(const MachineFunction *MF,
97                                         ProfileSummaryInfo *PSI,
98                                         const MachineBlockFrequencyInfo &MBFI) {
99     return machine_size_opts_detail::isFunctionColdInCallGraph(MF, PSI, MBFI);
100   }
101   static bool isFunctionHotInCallGraphNthPercentile(
102       int CutOff,
103       const MachineFunction *MF,
104       ProfileSummaryInfo *PSI,
105       const MachineBlockFrequencyInfo &MBFI) {
106     return machine_size_opts_detail::isFunctionHotInCallGraphNthPercentile(
107         CutOff, MF, PSI, MBFI);
108   }
109   static bool isColdBlock(const MachineBasicBlock *MBB,
110                           ProfileSummaryInfo *PSI,
111                           const MachineBlockFrequencyInfo *MBFI) {
112     return machine_size_opts_detail::isColdBlock(MBB, PSI, MBFI);
113   }
114   static bool isColdBlock(BlockFrequency BlockFreq,
115                           ProfileSummaryInfo *PSI,
116                           const MachineBlockFrequencyInfo *MBFI) {
117     return machine_size_opts_detail::isColdBlock(BlockFreq, PSI, MBFI);
118   }
119   static bool isHotBlockNthPercentile(int CutOff,
120                                       const MachineBasicBlock *MBB,
121                                       ProfileSummaryInfo *PSI,
122                                       const MachineBlockFrequencyInfo *MBFI) {
123     return machine_size_opts_detail::isHotBlockNthPercentile(
124         CutOff, MBB, PSI, MBFI);
125   }
126   static bool isHotBlockNthPercentile(int CutOff,
127                                       BlockFrequency BlockFreq,
128                                       ProfileSummaryInfo *PSI,
129                                       const MachineBlockFrequencyInfo *MBFI) {
130     return machine_size_opts_detail::isHotBlockNthPercentile(
131         CutOff, BlockFreq, PSI, MBFI);
132   }
133 };
134 } // end anonymous namespace
135 
136 bool llvm::shouldOptimizeForSize(const MachineFunction *MF,
137                                  ProfileSummaryInfo *PSI,
138                                  const MachineBlockFrequencyInfo *MBFI,
139                                  PGSOQueryType QueryType) {
140   return shouldFuncOptimizeForSizeImpl<MachineBasicBlockBFIAdapter>(
141       MF, PSI, MBFI, QueryType);
142 }
143 
144 bool llvm::shouldOptimizeForSize(const MachineBasicBlock *MBB,
145                                  ProfileSummaryInfo *PSI,
146                                  const MachineBlockFrequencyInfo *MBFI,
147                                  PGSOQueryType QueryType) {
148   assert(MBB);
149   return shouldOptimizeForSizeImpl<MachineBasicBlockBFIAdapter>(
150       MBB, PSI, MBFI, QueryType);
151 }
152 
153 bool llvm::shouldOptimizeForSize(const MachineBasicBlock *MBB,
154                                  ProfileSummaryInfo *PSI,
155                                  MBFIWrapper *MBFIW,
156                                  PGSOQueryType QueryType) {
157   assert(MBB);
158   if (!PSI || !MBFIW)
159     return false;
160   BlockFrequency BlockFreq = MBFIW->getBlockFreq(MBB);
161   return shouldOptimizeForSizeImpl<MachineBasicBlockBFIAdapter>(
162       BlockFreq, PSI, &MBFIW->getMBFI(), QueryType);
163 }
164