1//===----------------------------------------------------------------------===//
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#include "llvm/Transforms/Instrumentation/PGOForceFunctionAttrs.h"
10#include "llvm/Analysis/BlockFrequencyInfo.h"
11#include "llvm/Analysis/ProfileSummaryInfo.h"
12#include "llvm/IR/Module.h"
13#include "llvm/IR/PassManager.h"
14#include "llvm/Support/ErrorHandling.h"
15
16using namespace llvm;
17
18static bool shouldRunOnFunction(Function &F, ProfileSummaryInfo &PSI,
19 FunctionAnalysisManager &FAM) {
20 if (F.isDeclaration())
21 return false;
22 // Respect existing attributes.
23 if (F.hasOptNone() || F.hasOptSize() || F.hasMinSize())
24 return false;
25 if (F.hasFnAttribute(Kind: Attribute::Cold))
26 return true;
27 if (!PSI.hasProfileSummary())
28 return false;
29 BlockFrequencyInfo &BFI = FAM.getResult<BlockFrequencyAnalysis>(IR&: F);
30 return PSI.isFunctionColdInCallGraph(F: &F, BFI);
31}
32
33PreservedAnalyses PGOForceFunctionAttrsPass::run(Module &M,
34 ModuleAnalysisManager &AM) {
35 if (ColdType == PGOOptions::ColdFuncOpt::Default)
36 return PreservedAnalyses::all();
37 ProfileSummaryInfo &PSI = AM.getResult<ProfileSummaryAnalysis>(IR&: M);
38 FunctionAnalysisManager &FAM =
39 AM.getResult<FunctionAnalysisManagerModuleProxy>(IR&: M).getManager();
40 bool MadeChange = false;
41 for (Function &F : M) {
42 if (!shouldRunOnFunction(F, PSI, FAM))
43 continue;
44 switch (ColdType) {
45 case PGOOptions::ColdFuncOpt::Default:
46 llvm_unreachable("bailed out for default above");
47 break;
48 case PGOOptions::ColdFuncOpt::OptSize:
49 F.addFnAttr(Kind: Attribute::OptimizeForSize);
50 break;
51 case PGOOptions::ColdFuncOpt::MinSize:
52 F.addFnAttr(Kind: Attribute::MinSize);
53 break;
54 case PGOOptions::ColdFuncOpt::OptNone:
55 // alwaysinline is incompatible with optnone.
56 if (F.hasFnAttribute(Kind: Attribute::AlwaysInline))
57 continue;
58 F.addFnAttr(Kind: Attribute::OptimizeNone);
59 F.addFnAttr(Kind: Attribute::NoInline);
60 break;
61 }
62 MadeChange = true;
63 }
64 return MadeChange ? PreservedAnalyses::none() : PreservedAnalyses::all();
65}
66