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