Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 1 | //===- IndirectCallPromotion.cpp - Optimizations based on value profiling -===// |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file implements the transformation that promotes indirect calls to |
| 10 | // conditional direct calls when the indirect-call value profile metadata is |
| 11 | // available. |
| 12 | // |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 15 | #include "llvm/ADT/ArrayRef.h" |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 16 | #include "llvm/ADT/STLExtras.h" |
| 17 | #include "llvm/ADT/SmallVector.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 18 | #include "llvm/ADT/Statistic.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/StringRef.h" |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 20 | #include "llvm/Analysis/IndirectCallPromotionAnalysis.h" |
Chandler Carruth | 57578aa | 2019-01-07 07:15:51 +0000 | [diff] [blame] | 21 | #include "llvm/Analysis/IndirectCallVisitor.h" |
Adam Nemet | 0965da2 | 2017-10-09 23:19:02 +0000 | [diff] [blame] | 22 | #include "llvm/Analysis/OptimizationRemarkEmitter.h" |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 23 | #include "llvm/Analysis/ProfileSummaryInfo.h" |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 24 | #include "llvm/IR/Attributes.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 25 | #include "llvm/IR/BasicBlock.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 26 | #include "llvm/IR/CallSite.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 27 | #include "llvm/IR/DerivedTypes.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 28 | #include "llvm/IR/DiagnosticInfo.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 29 | #include "llvm/IR/Function.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 30 | #include "llvm/IR/IRBuilder.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 31 | #include "llvm/IR/InstrTypes.h" |
| 32 | #include "llvm/IR/Instruction.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 33 | #include "llvm/IR/Instructions.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 34 | #include "llvm/IR/LLVMContext.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 35 | #include "llvm/IR/MDBuilder.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 36 | #include "llvm/IR/PassManager.h" |
| 37 | #include "llvm/IR/Type.h" |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 38 | #include "llvm/IR/Value.h" |
Reid Kleckner | 05da2fe | 2019-11-13 13:15:01 -0800 | [diff] [blame] | 39 | #include "llvm/InitializePasses.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 40 | #include "llvm/Pass.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 41 | #include "llvm/ProfileData/InstrProf.h" |
| 42 | #include "llvm/Support/Casting.h" |
| 43 | #include "llvm/Support/CommandLine.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 44 | #include "llvm/Support/Debug.h" |
Chandler Carruth | 57578aa | 2019-01-07 07:15:51 +0000 | [diff] [blame] | 45 | #include "llvm/Support/Error.h" |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 46 | #include "llvm/Support/raw_ostream.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 47 | #include "llvm/Transforms/Instrumentation.h" |
David Blaikie | 4fe1fe1 | 2018-03-23 22:11:06 +0000 | [diff] [blame] | 48 | #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 49 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" |
Matthew Simpson | e363d2c | 2017-12-06 21:22:54 +0000 | [diff] [blame] | 50 | #include "llvm/Transforms/Utils/CallPromotionUtils.h" |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 51 | #include <cassert> |
| 52 | #include <cstdint> |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 53 | #include <memory> |
| 54 | #include <string> |
| 55 | #include <utility> |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 56 | #include <vector> |
| 57 | |
| 58 | using namespace llvm; |
| 59 | |
Xinliang David Li | 0b29330 | 2016-06-02 01:52:05 +0000 | [diff] [blame] | 60 | #define DEBUG_TYPE "pgo-icall-prom" |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 61 | |
| 62 | STATISTIC(NumOfPGOICallPromotion, "Number of indirect call promotions."); |
| 63 | STATISTIC(NumOfPGOICallsites, "Number of indirect call candidate sites."); |
| 64 | |
| 65 | // Command line option to disable indirect-call promotion with the default as |
| 66 | // false. This is for debug purpose. |
| 67 | static cl::opt<bool> DisableICP("disable-icp", cl::init(false), cl::Hidden, |
| 68 | cl::desc("Disable indirect call promotion")); |
| 69 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 70 | // Set the cutoff value for the promotion. If the value is other than 0, we |
| 71 | // stop the transformation once the total number of promotions equals the cutoff |
| 72 | // value. |
| 73 | // For debug use only. |
| 74 | static cl::opt<unsigned> |
| 75 | ICPCutOff("icp-cutoff", cl::init(0), cl::Hidden, cl::ZeroOrMore, |
Craig Topper | a49e768 | 2017-05-05 22:31:11 +0000 | [diff] [blame] | 76 | cl::desc("Max number of promotions for this compilation")); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 77 | |
| 78 | // If ICPCSSkip is non zero, the first ICPCSSkip callsites will be skipped. |
| 79 | // For debug use only. |
| 80 | static cl::opt<unsigned> |
| 81 | ICPCSSkip("icp-csskip", cl::init(0), cl::Hidden, cl::ZeroOrMore, |
Craig Topper | a49e768 | 2017-05-05 22:31:11 +0000 | [diff] [blame] | 82 | cl::desc("Skip Callsite up to this number for this compilation")); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 83 | |
| 84 | // Set if the pass is called in LTO optimization. The difference for LTO mode |
| 85 | // is the pass won't prefix the source module name to the internal linkage |
| 86 | // symbols. |
| 87 | static cl::opt<bool> ICPLTOMode("icp-lto", cl::init(false), cl::Hidden, |
| 88 | cl::desc("Run indirect-call promotion in LTO " |
| 89 | "mode")); |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 90 | |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 91 | // Set if the pass is called in SamplePGO mode. The difference for SamplePGO |
| 92 | // mode is it will add prof metadatato the created direct call. |
| 93 | static cl::opt<bool> |
| 94 | ICPSamplePGOMode("icp-samplepgo", cl::init(false), cl::Hidden, |
| 95 | cl::desc("Run indirect-call promotion in SamplePGO mode")); |
| 96 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 97 | // If the option is set to true, only call instructions will be considered for |
| 98 | // transformation -- invoke instructions will be ignored. |
| 99 | static cl::opt<bool> |
| 100 | ICPCallOnly("icp-call-only", cl::init(false), cl::Hidden, |
| 101 | cl::desc("Run indirect-call promotion for call instructions " |
| 102 | "only")); |
| 103 | |
| 104 | // If the option is set to true, only invoke instructions will be considered for |
| 105 | // transformation -- call instructions will be ignored. |
| 106 | static cl::opt<bool> ICPInvokeOnly("icp-invoke-only", cl::init(false), |
| 107 | cl::Hidden, |
| 108 | cl::desc("Run indirect-call promotion for " |
| 109 | "invoke instruction only")); |
| 110 | |
| 111 | // Dump the function level IR if the transformation happened in this |
| 112 | // function. For debug use only. |
| 113 | static cl::opt<bool> |
| 114 | ICPDUMPAFTER("icp-dumpafter", cl::init(false), cl::Hidden, |
| 115 | cl::desc("Dump IR after transformation happens")); |
| 116 | |
| 117 | namespace { |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 118 | |
Xinliang David Li | 7261618 | 2016-05-15 01:04:24 +0000 | [diff] [blame] | 119 | class PGOIndirectCallPromotionLegacyPass : public ModulePass { |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 120 | public: |
| 121 | static char ID; |
| 122 | |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 123 | PGOIndirectCallPromotionLegacyPass(bool InLTO = false, bool SamplePGO = false) |
| 124 | : ModulePass(ID), InLTO(InLTO), SamplePGO(SamplePGO) { |
Xinliang David Li | 7261618 | 2016-05-15 01:04:24 +0000 | [diff] [blame] | 125 | initializePGOIndirectCallPromotionLegacyPassPass( |
| 126 | *PassRegistry::getPassRegistry()); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 127 | } |
| 128 | |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 129 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
| 130 | AU.addRequired<ProfileSummaryInfoWrapperPass>(); |
| 131 | } |
| 132 | |
Mehdi Amini | 117296c | 2016-10-01 02:56:57 +0000 | [diff] [blame] | 133 | StringRef getPassName() const override { return "PGOIndirectCallPromotion"; } |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 134 | |
| 135 | private: |
| 136 | bool runOnModule(Module &M) override; |
| 137 | |
| 138 | // If this pass is called in LTO. We need to special handling the PGOFuncName |
| 139 | // for the static variables due to LTO's internalization. |
| 140 | bool InLTO; |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 141 | |
| 142 | // If this pass is called in SamplePGO. We need to add the prof metadata to |
| 143 | // the promoted direct call. |
| 144 | bool SamplePGO; |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 145 | }; |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 146 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 147 | } // end anonymous namespace |
| 148 | |
Xinliang David Li | 7261618 | 2016-05-15 01:04:24 +0000 | [diff] [blame] | 149 | char PGOIndirectCallPromotionLegacyPass::ID = 0; |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 150 | |
Dehao Chen | 45847d3 | 2017-08-14 23:25:21 +0000 | [diff] [blame] | 151 | INITIALIZE_PASS_BEGIN(PGOIndirectCallPromotionLegacyPass, "pgo-icall-prom", |
| 152 | "Use PGO instrumentation profile to promote indirect " |
| 153 | "calls to direct calls.", |
| 154 | false, false) |
| 155 | INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass) |
| 156 | INITIALIZE_PASS_END(PGOIndirectCallPromotionLegacyPass, "pgo-icall-prom", |
| 157 | "Use PGO instrumentation profile to promote indirect " |
| 158 | "calls to direct calls.", |
| 159 | false, false) |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 160 | |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 161 | ModulePass *llvm::createPGOIndirectCallPromotionLegacyPass(bool InLTO, |
| 162 | bool SamplePGO) { |
| 163 | return new PGOIndirectCallPromotionLegacyPass(InLTO, SamplePGO); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 164 | } |
| 165 | |
Benjamin Kramer | a65b610 | 2016-05-15 15:18:11 +0000 | [diff] [blame] | 166 | namespace { |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 167 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 168 | // The class for main data structure to promote indirect calls to conditional |
| 169 | // direct calls. |
| 170 | class ICallPromotionFunc { |
| 171 | private: |
| 172 | Function &F; |
| 173 | Module *M; |
| 174 | |
| 175 | // Symtab that maps indirect call profile values to function names and |
| 176 | // defines. |
| 177 | InstrProfSymtab *Symtab; |
| 178 | |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 179 | bool SamplePGO; |
| 180 | |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 181 | OptimizationRemarkEmitter &ORE; |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 182 | |
| 183 | // A struct that records the direct target and it's call count. |
| 184 | struct PromotionCandidate { |
| 185 | Function *TargetFunction; |
| 186 | uint64_t Count; |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 187 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 188 | PromotionCandidate(Function *F, uint64_t C) : TargetFunction(F), Count(C) {} |
| 189 | }; |
| 190 | |
| 191 | // Check if the indirect-call call site should be promoted. Return the number |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 192 | // of promotions. Inst is the candidate indirect call, ValueDataRef |
| 193 | // contains the array of value profile data for profiled targets, |
| 194 | // TotalCount is the total profiled count of call executions, and |
| 195 | // NumCandidates is the number of candidate entries in ValueDataRef. |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 196 | std::vector<PromotionCandidate> getPromotionCandidatesForCallSite( |
| 197 | Instruction *Inst, const ArrayRef<InstrProfValueData> &ValueDataRef, |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 198 | uint64_t TotalCount, uint32_t NumCandidates); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 199 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 200 | // Promote a list of targets for one indirect-call callsite. Return |
| 201 | // the number of promotions. |
| 202 | uint32_t tryToPromote(Instruction *Inst, |
| 203 | const std::vector<PromotionCandidate> &Candidates, |
| 204 | uint64_t &TotalCount); |
| 205 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 206 | public: |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 207 | ICallPromotionFunc(Function &Func, Module *Modu, InstrProfSymtab *Symtab, |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 208 | bool SamplePGO, OptimizationRemarkEmitter &ORE) |
| 209 | : F(Func), M(Modu), Symtab(Symtab), SamplePGO(SamplePGO), ORE(ORE) {} |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 210 | ICallPromotionFunc(const ICallPromotionFunc &) = delete; |
| 211 | ICallPromotionFunc &operator=(const ICallPromotionFunc &) = delete; |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 212 | |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 213 | bool processFunction(ProfileSummaryInfo *PSI); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 214 | }; |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 215 | |
Benjamin Kramer | a65b610 | 2016-05-15 15:18:11 +0000 | [diff] [blame] | 216 | } // end anonymous namespace |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 217 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 218 | // Indirect-call promotion heuristic. The direct targets are sorted based on |
| 219 | // the count. Stop at the first target that is not promoted. |
| 220 | std::vector<ICallPromotionFunc::PromotionCandidate> |
| 221 | ICallPromotionFunc::getPromotionCandidatesForCallSite( |
| 222 | Instruction *Inst, const ArrayRef<InstrProfValueData> &ValueDataRef, |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 223 | uint64_t TotalCount, uint32_t NumCandidates) { |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 224 | std::vector<PromotionCandidate> Ret; |
| 225 | |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 226 | LLVM_DEBUG(dbgs() << " \nWork on callsite #" << NumOfPGOICallsites << *Inst |
| 227 | << " Num_targets: " << ValueDataRef.size() |
| 228 | << " Num_candidates: " << NumCandidates << "\n"); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 229 | NumOfPGOICallsites++; |
| 230 | if (ICPCSSkip != 0 && NumOfPGOICallsites <= ICPCSSkip) { |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 231 | LLVM_DEBUG(dbgs() << " Skip: User options.\n"); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 232 | return Ret; |
| 233 | } |
| 234 | |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 235 | for (uint32_t I = 0; I < NumCandidates; I++) { |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 236 | uint64_t Count = ValueDataRef[I].Count; |
| 237 | assert(Count <= TotalCount); |
| 238 | uint64_t Target = ValueDataRef[I].Value; |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 239 | LLVM_DEBUG(dbgs() << " Candidate " << I << " Count=" << Count |
| 240 | << " Target_func: " << Target << "\n"); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 241 | |
Fangrui Song | 2c5c12c | 2019-04-05 16:16:23 +0000 | [diff] [blame] | 242 | if (ICPInvokeOnly && isa<CallInst>(Inst)) { |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 243 | LLVM_DEBUG(dbgs() << " Not promote: User options.\n"); |
Vivek Pandya | 9590658 | 2017-10-11 17:12:59 +0000 | [diff] [blame] | 244 | ORE.emit([&]() { |
| 245 | return OptimizationRemarkMissed(DEBUG_TYPE, "UserOptions", Inst) |
| 246 | << " Not promote: User options"; |
| 247 | }); |
Teresa Johnson | ce7de9b | 2016-07-17 14:46:58 +0000 | [diff] [blame] | 248 | break; |
| 249 | } |
Fangrui Song | 2c5c12c | 2019-04-05 16:16:23 +0000 | [diff] [blame] | 250 | if (ICPCallOnly && isa<InvokeInst>(Inst)) { |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 251 | LLVM_DEBUG(dbgs() << " Not promote: User option.\n"); |
Vivek Pandya | 9590658 | 2017-10-11 17:12:59 +0000 | [diff] [blame] | 252 | ORE.emit([&]() { |
| 253 | return OptimizationRemarkMissed(DEBUG_TYPE, "UserOptions", Inst) |
| 254 | << " Not promote: User options"; |
| 255 | }); |
Teresa Johnson | ce7de9b | 2016-07-17 14:46:58 +0000 | [diff] [blame] | 256 | break; |
| 257 | } |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 258 | if (ICPCutOff != 0 && NumOfPGOICallPromotion >= ICPCutOff) { |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 259 | LLVM_DEBUG(dbgs() << " Not promote: Cutoff reached.\n"); |
Vivek Pandya | 9590658 | 2017-10-11 17:12:59 +0000 | [diff] [blame] | 260 | ORE.emit([&]() { |
| 261 | return OptimizationRemarkMissed(DEBUG_TYPE, "CutOffReached", Inst) |
| 262 | << " Not promote: Cutoff reached"; |
| 263 | }); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 264 | break; |
| 265 | } |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 266 | |
| 267 | Function *TargetFunction = Symtab->getFunction(Target); |
| 268 | if (TargetFunction == nullptr) { |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 269 | LLVM_DEBUG(dbgs() << " Not promote: Cannot find the target\n"); |
Vivek Pandya | 9590658 | 2017-10-11 17:12:59 +0000 | [diff] [blame] | 270 | ORE.emit([&]() { |
| 271 | return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToFindTarget", Inst) |
Xinliang David Li | bcf726a | 2018-08-24 21:38:24 +0000 | [diff] [blame] | 272 | << "Cannot promote indirect call: target with md5sum " |
| 273 | << ore::NV("target md5sum", Target) << " not found"; |
Vivek Pandya | 9590658 | 2017-10-11 17:12:59 +0000 | [diff] [blame] | 274 | }); |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 275 | break; |
| 276 | } |
| 277 | |
Dehao Chen | 6775f5d | 2017-01-30 22:46:37 +0000 | [diff] [blame] | 278 | const char *Reason = nullptr; |
Matthew Simpson | e363d2c | 2017-12-06 21:22:54 +0000 | [diff] [blame] | 279 | if (!isLegalToPromote(CallSite(Inst), TargetFunction, &Reason)) { |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 280 | using namespace ore; |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 281 | |
Vivek Pandya | 9590658 | 2017-10-11 17:12:59 +0000 | [diff] [blame] | 282 | ORE.emit([&]() { |
| 283 | return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToPromote", Inst) |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 284 | << "Cannot promote indirect call to " |
| 285 | << NV("TargetFunction", TargetFunction) << " with count of " |
Vivek Pandya | 9590658 | 2017-10-11 17:12:59 +0000 | [diff] [blame] | 286 | << NV("Count", Count) << ": " << Reason; |
| 287 | }); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 288 | break; |
| 289 | } |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 290 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 291 | Ret.push_back(PromotionCandidate(TargetFunction, Count)); |
| 292 | TotalCount -= Count; |
| 293 | } |
| 294 | return Ret; |
| 295 | } |
| 296 | |
Matthew Simpson | e363d2c | 2017-12-06 21:22:54 +0000 | [diff] [blame] | 297 | Instruction *llvm::pgo::promoteIndirectCall(Instruction *Inst, |
| 298 | Function *DirectCallee, |
| 299 | uint64_t Count, uint64_t TotalCount, |
| 300 | bool AttachProfToDirectCall, |
| 301 | OptimizationRemarkEmitter *ORE) { |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 302 | |
| 303 | uint64_t ElseCount = TotalCount - Count; |
| 304 | uint64_t MaxCount = (Count >= ElseCount ? Count : ElseCount); |
| 305 | uint64_t Scale = calculateCountScale(MaxCount); |
| 306 | MDBuilder MDB(Inst->getContext()); |
| 307 | MDNode *BranchWeights = MDB.createBranchWeights( |
| 308 | scaleBranchCount(Count, Scale), scaleBranchCount(ElseCount, Scale)); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 309 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 310 | Instruction *NewInst = |
Matthew Simpson | e363d2c | 2017-12-06 21:22:54 +0000 | [diff] [blame] | 311 | promoteCallWithIfThenElse(CallSite(Inst), DirectCallee, BranchWeights); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 312 | |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 313 | if (AttachProfToDirectCall) { |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 314 | MDBuilder MDB(NewInst->getContext()); |
Teresa Johnson | 4bdf82c | 2019-02-05 00:18:38 +0000 | [diff] [blame] | 315 | NewInst->setMetadata( |
| 316 | LLVMContext::MD_prof, |
| 317 | MDB.createBranchWeights({static_cast<uint32_t>(Count)})); |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 318 | } |
| 319 | |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 320 | using namespace ore; |
Eugene Zelenko | fce4357 | 2017-10-21 00:57:46 +0000 | [diff] [blame] | 321 | |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 322 | if (ORE) |
Vivek Pandya | 9590658 | 2017-10-11 17:12:59 +0000 | [diff] [blame] | 323 | ORE->emit([&]() { |
| 324 | return OptimizationRemark(DEBUG_TYPE, "Promoted", Inst) |
| 325 | << "Promote indirect call to " << NV("DirectCallee", DirectCallee) |
| 326 | << " with count " << NV("Count", Count) << " out of " |
| 327 | << NV("TotalCount", TotalCount); |
| 328 | }); |
Dehao Chen | 14bf029 | 2017-01-23 23:18:24 +0000 | [diff] [blame] | 329 | return NewInst; |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 330 | } |
| 331 | |
| 332 | // Promote indirect-call to conditional direct-call for one callsite. |
| 333 | uint32_t ICallPromotionFunc::tryToPromote( |
| 334 | Instruction *Inst, const std::vector<PromotionCandidate> &Candidates, |
| 335 | uint64_t &TotalCount) { |
| 336 | uint32_t NumPromoted = 0; |
| 337 | |
| 338 | for (auto &C : Candidates) { |
| 339 | uint64_t Count = C.Count; |
Matthew Simpson | e363d2c | 2017-12-06 21:22:54 +0000 | [diff] [blame] | 340 | pgo::promoteIndirectCall(Inst, C.TargetFunction, Count, TotalCount, |
| 341 | SamplePGO, &ORE); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 342 | assert(TotalCount >= Count); |
| 343 | TotalCount -= Count; |
| 344 | NumOfPGOICallPromotion++; |
| 345 | NumPromoted++; |
| 346 | } |
| 347 | return NumPromoted; |
| 348 | } |
| 349 | |
| 350 | // Traverse all the indirect-call callsite and get the value profile |
| 351 | // annotation to perform indirect-call promotion. |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 352 | bool ICallPromotionFunc::processFunction(ProfileSummaryInfo *PSI) { |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 353 | bool Changed = false; |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 354 | ICallPromotionAnalysis ICallAnalysis; |
Chandler Carruth | 57578aa | 2019-01-07 07:15:51 +0000 | [diff] [blame] | 355 | for (auto &I : findIndirectCalls(F)) { |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 356 | uint32_t NumVals, NumCandidates; |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 357 | uint64_t TotalCount; |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 358 | auto ICallProfDataRef = ICallAnalysis.getPromotionCandidatesForInstruction( |
| 359 | I, NumVals, TotalCount, NumCandidates); |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 360 | if (!NumCandidates || |
| 361 | (PSI && PSI->hasProfileSummary() && !PSI->isHotCount(TotalCount))) |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 362 | continue; |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 363 | auto PromotionCandidates = getPromotionCandidatesForCallSite( |
| 364 | I, ICallProfDataRef, TotalCount, NumCandidates); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 365 | uint32_t NumPromoted = tryToPromote(I, PromotionCandidates, TotalCount); |
| 366 | if (NumPromoted == 0) |
| 367 | continue; |
| 368 | |
| 369 | Changed = true; |
| 370 | // Adjust the MD.prof metadata. First delete the old one. |
Eugene Zelenko | cdc7161 | 2016-08-11 17:20:18 +0000 | [diff] [blame] | 371 | I->setMetadata(LLVMContext::MD_prof, nullptr); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 372 | // If all promoted, we don't need the MD.prof metadata. |
| 373 | if (TotalCount == 0 || NumPromoted == NumVals) |
| 374 | continue; |
| 375 | // Otherwise we need update with the un-promoted records back. |
Teresa Johnson | 1e44b5d | 2016-07-12 21:13:44 +0000 | [diff] [blame] | 376 | annotateValueSite(*M, *I, ICallProfDataRef.slice(NumPromoted), TotalCount, |
| 377 | IPVK_IndirectCallTarget, NumCandidates); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 378 | } |
| 379 | return Changed; |
| 380 | } |
| 381 | |
| 382 | // A wrapper function that does the actual work. |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 383 | static bool promoteIndirectCalls(Module &M, ProfileSummaryInfo *PSI, |
| 384 | bool InLTO, bool SamplePGO, |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 385 | ModuleAnalysisManager *AM = nullptr) { |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 386 | if (DisableICP) |
| 387 | return false; |
| 388 | InstrProfSymtab Symtab; |
Vedant Kumar | b5794ca | 2017-06-20 01:38:56 +0000 | [diff] [blame] | 389 | if (Error E = Symtab.create(M, InLTO)) { |
| 390 | std::string SymtabFailure = toString(std::move(E)); |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 391 | LLVM_DEBUG(dbgs() << "Failed to create symtab: " << SymtabFailure << "\n"); |
Vedant Kumar | b5794ca | 2017-06-20 01:38:56 +0000 | [diff] [blame] | 392 | (void)SymtabFailure; |
| 393 | return false; |
| 394 | } |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 395 | bool Changed = false; |
| 396 | for (auto &F : M) { |
Evandro Menezes | 85bd397 | 2019-04-04 22:40:06 +0000 | [diff] [blame] | 397 | if (F.isDeclaration() || F.hasOptNone()) |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 398 | continue; |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 399 | |
| 400 | std::unique_ptr<OptimizationRemarkEmitter> OwnedORE; |
| 401 | OptimizationRemarkEmitter *ORE; |
| 402 | if (AM) { |
| 403 | auto &FAM = |
| 404 | AM->getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); |
| 405 | ORE = &FAM.getResult<OptimizationRemarkEmitterAnalysis>(F); |
| 406 | } else { |
Jonas Devlieghere | 0eaee54 | 2019-08-15 15:54:37 +0000 | [diff] [blame] | 407 | OwnedORE = std::make_unique<OptimizationRemarkEmitter>(&F); |
Adam Nemet | 0d8b5d6 | 2017-07-27 16:54:15 +0000 | [diff] [blame] | 408 | ORE = OwnedORE.get(); |
| 409 | } |
| 410 | |
| 411 | ICallPromotionFunc ICallPromotion(F, &M, &Symtab, SamplePGO, *ORE); |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 412 | bool FuncChanged = ICallPromotion.processFunction(PSI); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 413 | if (ICPDUMPAFTER && FuncChanged) { |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 414 | LLVM_DEBUG(dbgs() << "\n== IR Dump After =="; F.print(dbgs())); |
| 415 | LLVM_DEBUG(dbgs() << "\n"); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 416 | } |
| 417 | Changed |= FuncChanged; |
| 418 | if (ICPCutOff != 0 && NumOfPGOICallPromotion >= ICPCutOff) { |
Nicola Zaghen | d34e60c | 2018-05-14 12:53:11 +0000 | [diff] [blame] | 419 | LLVM_DEBUG(dbgs() << " Stop: Cutoff reached.\n"); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 420 | break; |
| 421 | } |
| 422 | } |
| 423 | return Changed; |
| 424 | } |
| 425 | |
Xinliang David Li | 7261618 | 2016-05-15 01:04:24 +0000 | [diff] [blame] | 426 | bool PGOIndirectCallPromotionLegacyPass::runOnModule(Module &M) { |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 427 | ProfileSummaryInfo *PSI = |
Vedant Kumar | e7b789b | 2018-11-19 05:23:16 +0000 | [diff] [blame] | 428 | &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI(); |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 429 | |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 430 | // Command-line option has the priority for InLTO. |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 431 | return promoteIndirectCalls(M, PSI, InLTO | ICPLTOMode, |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 432 | SamplePGO | ICPSamplePGOMode); |
Rong Xu | 6e34c49 | 2016-04-27 23:20:27 +0000 | [diff] [blame] | 433 | } |
Xinliang David Li | f3c7a35 | 2016-05-16 16:31:07 +0000 | [diff] [blame] | 434 | |
Dehao Chen | cc75d24 | 2017-02-23 22:15:18 +0000 | [diff] [blame] | 435 | PreservedAnalyses PGOIndirectCallPromotion::run(Module &M, |
| 436 | ModuleAnalysisManager &AM) { |
Dehao Chen | 34cfcb2 | 2017-08-08 20:57:33 +0000 | [diff] [blame] | 437 | ProfileSummaryInfo *PSI = &AM.getResult<ProfileSummaryAnalysis>(M); |
| 438 | |
| 439 | if (!promoteIndirectCalls(M, PSI, InLTO | ICPLTOMode, |
| 440 | SamplePGO | ICPSamplePGOMode, &AM)) |
Xinliang David Li | f3c7a35 | 2016-05-16 16:31:07 +0000 | [diff] [blame] | 441 | return PreservedAnalyses::all(); |
| 442 | |
| 443 | return PreservedAnalyses::none(); |
| 444 | } |