23#define DEBUG_TYPE "inline-order"
29 cl::desc(
"Choose the priority mode to use in module inline"),
31 "Use callee size priority."),
33 "Use inline cost priority."),
35 "Use cost-benefit ratio."),
40 cl::desc(
"The cost threshold for call sites that get inlined without the "
41 "cost-benefit analysis"));
51 .getCachedResult<ProfileSummaryAnalysis>(
52 *CB.
getParent()->getParent()->getParent());
68 Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
70 return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI,
71 GetBFI, PSI, RemarksEnabled ? &ORE :
nullptr);
76 SizePriority() =
default;
78 const InlineParams &) {
80 Size =
Callee->getInstructionCount();
83 static bool isMoreDesirable(
const SizePriority &P1,
const SizePriority &P2) {
84 return P1.Size <
P2.Size;
88 unsigned Size = UINT_MAX;
93 CostPriority() =
default;
95 const InlineParams &Params) {
96 auto IC = getInlineCostWrapper(
const_cast<CallBase &
>(*CB),
FAM, Params);
100 Cost = IC.isNever() ? INT_MAX : INT_MIN;
103 static bool isMoreDesirable(
const CostPriority &P1,
const CostPriority &P2) {
104 return P1.Cost <
P2.Cost;
111class CostBenefitPriority {
113 CostBenefitPriority() =
default;
115 const InlineParams &Params) {
116 auto IC = getInlineCostWrapper(
const_cast<CallBase &
>(*CB),
FAM, Params);
117 if (IC.isVariable()) {
119 StaticBonusApplied = IC.getStaticBonusApplied();
120 CostBenefit = IC.getCostBenefit();
122 Cost = IC.isNever() ? INT_MAX : INT_MIN;
123 StaticBonusApplied = 0;
124 CostBenefit = std::nullopt;
128 static bool isMoreDesirable(
const CostBenefitPriority &P1,
129 const CostBenefitPriority &P2) {
145 bool P1ReducesCallerSize =
147 bool P2ReducesCallerSize =
149 if (P1ReducesCallerSize || P2ReducesCallerSize) {
152 if (P1ReducesCallerSize != P2ReducesCallerSize)
153 return P1ReducesCallerSize;
157 return P1.Cost <
P2.Cost;
160 bool P1HasCB =
P1.CostBenefit.has_value();
161 bool P2HasCB =
P2.CostBenefit.has_value();
162 if (P1HasCB || P2HasCB) {
165 if (P1HasCB != P2HasCB)
170 APInt
LHS =
P1.CostBenefit->getBenefit() *
P2.CostBenefit->getCost();
171 APInt
RHS =
P2.CostBenefit->getBenefit() *
P1.CostBenefit->getCost();
176 return P1.Cost <
P2.Cost;
181 int StaticBonusApplied = 0;
182 std::optional<CostBenefitPair> CostBenefit;
187 MLPriority() =
default;
189 const InlineParams &Params) {
190 auto IC = getInlineCostWrapper(
const_cast<CallBase &
>(*CB),
FAM, Params);
194 Cost = IC.isNever() ? INT_MAX : INT_MIN;
197 static bool isMoreDesirable(
const MLPriority &P1,
const MLPriority &P2) {
198 return P1.Cost <
P2.Cost;
205template <
typename PriorityT>
class PriorityInlineOrder :
public InlineOrder {
206 bool hasLowerPriority(
const CallBase *L,
const CallBase *R)
const {
207 const auto I1 = Priorities.find(L);
208 const auto I2 = Priorities.find(R);
209 assert(I1 != Priorities.end() && I2 != Priorities.end());
210 return PriorityT::isMoreDesirable(I2->second,
I1->second);
213 bool updateAndCheckDecreased(
const CallBase *CB) {
214 auto It = Priorities.find(CB);
215 const auto OldPriority = It->second;
216 It->second = PriorityT(CB, FAM, Params);
217 const auto NewPriority = It->second;
218 return PriorityT::isMoreDesirable(OldPriority, NewPriority);
228 void pop_heap_adjust() {
229 std::pop_heap(Heap.begin(), Heap.end(), isLess);
230 while (updateAndCheckDecreased(Heap.back())) {
231 std::push_heap(Heap.begin(), Heap.end(), isLess);
232 std::pop_heap(Heap.begin(), Heap.end(), isLess);
238 : FAM(FAM), Params(Params) {
239 isLess = [&](
const CallBase *
L,
const CallBase *
R) {
240 return hasLowerPriority(L, R);
244 size_t size()
override {
return Heap.size(); }
246 void push(CallBase *CB)
override {
248 Priorities[CB] = PriorityT(CB, FAM, Params);
249 std::push_heap(Heap.begin(), Heap.end(), isLess);
252 CallBase *pop()
override {
256 return Heap.pop_back_val();
259 void erase_if(function_ref<
bool(CallBase *)> Pred)
override {
261 std::make_heap(Heap.begin(), Heap.end(), isLess);
266 std::function<bool(
const CallBase *L,
const CallBase *R)> isLess;
267 DenseMap<const CallBase *, PriorityT> Priorities;
269 const InlineParams &Params;
276std::unique_ptr<InlineOrder>
282 LLVM_DEBUG(
dbgs() <<
" Current used priority: Size priority ---- \n");
283 return std::make_unique<PriorityInlineOrder<SizePriority>>(
FAM, Params);
286 LLVM_DEBUG(
dbgs() <<
" Current used priority: Cost priority ---- \n");
287 return std::make_unique<PriorityInlineOrder<CostPriority>>(
FAM, Params);
291 dbgs() <<
" Current used priority: cost-benefit priority ---- \n");
292 return std::make_unique<PriorityInlineOrder<CostBenefitPriority>>(
FAM,
295 LLVM_DEBUG(
dbgs() <<
" Current used priority: ML priority ---- \n");
296 return std::make_unique<PriorityInlineOrder<MLPriority>>(
FAM, Params);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This is the interface for a simple mod/ref and alias analysis over globals.
static cl::opt< int > ModuleInlinerTopPriorityThreshold("module-inliner-top-priority-threshold", cl::Hidden, cl::init(0), cl::desc("The cost threshold for call sites that get inlined without the " "cost-benefit analysis"))
static cl::opt< InlinePriorityMode > UseInlinePriority("inline-priority-mode", cl::init(InlinePriorityMode::Size), cl::Hidden, cl::desc("Choose the priority mode to use in module inline"), cl::values(clEnumValN(InlinePriorityMode::Size, "size", "Use callee size priority."), clEnumValN(InlinePriorityMode::Cost, "cost", "Use inline cost priority."), clEnumValN(InlinePriorityMode::CostBenefit, "cost-benefit", "Use cost-benefit ratio."), clEnumValN(InlinePriorityMode::ML, "ml", "Use ML.")))
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
Represents the cost of inlining a function.
A Module instance is used to store all the information related to an LLVM module.
Used for dynamically loading instances of InlineOrder as plugins.
static LLVM_ABI AnalysisKey Key
Analysis providing profile information.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
const ParentTy * getParent() const
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< const TargetLibraryInfo &(Function &)> GetTLI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr, function_ref< EphemeralValuesCache &(Function &)> GetEphValuesCache=nullptr)
Get an InlineCost object representing the cost of inlining this callsite.
LLVM_ABI std::unique_ptr< InlineOrder > getDefaultInlineOrder(FunctionAnalysisManager &FAM, const InlineParams &Params, ModuleAnalysisManager &MAM, Module &M)
LLVM_ABI std::unique_ptr< InlineOrder > getInlineOrder(FunctionAnalysisManager &FAM, const InlineParams &Params, ModuleAnalysisManager &MAM, Module &M)
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
A special type used by analysis passes to provide an address that identifies that particular analysis...
Thresholds to tune inline cost analysis.