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 {
28 namespace machine_size_opts_detail {
29 
30 /// Like ProfileSummaryInfo::isColdBlock but for MachineBasicBlock.
31 bool isColdBlock(const MachineBasicBlock *MBB,
32                  ProfileSummaryInfo *PSI,
33                  const MachineBlockFrequencyInfo *MBFI) {
34   auto Count = MBFI->getBlockProfileCount(MBB);
35   return Count && PSI->isColdCount(*Count);
36 }
37 
38 bool isColdBlock(BlockFrequency BlockFreq,
39                  ProfileSummaryInfo *PSI,
40                  const MachineBlockFrequencyInfo *MBFI) {
41   auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency());
42   return Count && PSI->isColdCount(*Count);
43 }
44 
45 /// Like ProfileSummaryInfo::isHotBlockNthPercentile but for MachineBasicBlock.
46 static bool isHotBlockNthPercentile(int PercentileCutoff,
47                                     const MachineBasicBlock *MBB,
48                                     ProfileSummaryInfo *PSI,
49                                     const MachineBlockFrequencyInfo *MBFI) {
50   auto Count = MBFI->getBlockProfileCount(MBB);
51   return Count && PSI->isHotCountNthPercentile(PercentileCutoff, *Count);
52 }
53 
54 static bool isHotBlockNthPercentile(int PercentileCutoff,
55                                     BlockFrequency BlockFreq,
56                                     ProfileSummaryInfo *PSI,
57                                     const MachineBlockFrequencyInfo *MBFI) {
58   auto Count = MBFI->getProfileCountFromFreq(BlockFreq.getFrequency());
59   return Count && PSI->isHotCountNthPercentile(PercentileCutoff, *Count);
60 }
61 
62 /// Like ProfileSummaryInfo::isFunctionColdInCallGraph but for
63 /// MachineFunction.
64 bool isFunctionColdInCallGraph(
65     const MachineFunction *MF,
66     ProfileSummaryInfo *PSI,
67     const MachineBlockFrequencyInfo &MBFI) {
68   if (auto FunctionCount = MF->getFunction().getEntryCount())
69     if (!PSI->isColdCount(FunctionCount.getCount()))
70       return false;
71   for (const auto &MBB : *MF)
72     if (!isColdBlock(&MBB, PSI, &MBFI))
73       return false;
74   return true;
75 }
76 
77 /// Like ProfileSummaryInfo::isFunctionHotInCallGraphNthPercentile but for
78 /// MachineFunction.
79 bool isFunctionHotInCallGraphNthPercentile(
80     int PercentileCutoff,
81     const MachineFunction *MF,
82     ProfileSummaryInfo *PSI,
83     const MachineBlockFrequencyInfo &MBFI) {
84   if (auto FunctionCount = MF->getFunction().getEntryCount())
85     if (PSI->isHotCountNthPercentile(PercentileCutoff,
86                                      FunctionCount.getCount()))
87       return true;
88   for (const auto &MBB : *MF)
89     if (isHotBlockNthPercentile(PercentileCutoff, &MBB, PSI, &MBFI))
90       return true;
91   return false;
92 }
93 } // namespace machine_size_opts_detail
94 
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