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