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 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 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