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