xref: /llvm-project/llvm/lib/Analysis/InlineOrder.cpp (revision ab4253f6dff194a1e09448c8628809d21f148df9)
1d52e775bSLiqiang Tao //===- InlineOrder.cpp - Inlining order abstraction -*- C++ ---*-----------===//
2d52e775bSLiqiang Tao //
3d52e775bSLiqiang Tao // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4d52e775bSLiqiang Tao // See https://llvm.org/LICENSE.txt for license information.
5d52e775bSLiqiang Tao // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d52e775bSLiqiang Tao //
7d52e775bSLiqiang Tao //===----------------------------------------------------------------------===//
8d52e775bSLiqiang Tao 
9d52e775bSLiqiang Tao #include "llvm/Analysis/InlineOrder.h"
10d52e775bSLiqiang Tao #include "llvm/Analysis/AssumptionCache.h"
11d52e775bSLiqiang Tao #include "llvm/Analysis/BlockFrequencyInfo.h"
12d52e775bSLiqiang Tao #include "llvm/Analysis/GlobalsModRef.h"
13d52e775bSLiqiang Tao #include "llvm/Analysis/InlineAdvisor.h"
14d52e775bSLiqiang Tao #include "llvm/Analysis/InlineCost.h"
15d52e775bSLiqiang Tao #include "llvm/Analysis/OptimizationRemarkEmitter.h"
16d52e775bSLiqiang Tao #include "llvm/Analysis/ProfileSummaryInfo.h"
17d52e775bSLiqiang Tao #include "llvm/Analysis/TargetLibraryInfo.h"
18d52e775bSLiqiang Tao #include "llvm/Analysis/TargetTransformInfo.h"
195faf4bf1SKazu Hirata #include "llvm/Support/CommandLine.h"
20d52e775bSLiqiang Tao 
21d52e775bSLiqiang Tao using namespace llvm;
22d52e775bSLiqiang Tao 
23d52e775bSLiqiang Tao #define DEBUG_TYPE "inline-order"
24d52e775bSLiqiang Tao 
252d6ec146SKazu Hirata enum class InlinePriorityMode : int { Size, Cost, CostBenefit, ML };
265faf4bf1SKazu Hirata 
275faf4bf1SKazu Hirata static cl::opt<InlinePriorityMode> UseInlinePriority(
285faf4bf1SKazu Hirata     "inline-priority-mode", cl::init(InlinePriorityMode::Size), cl::Hidden,
295faf4bf1SKazu Hirata     cl::desc("Choose the priority mode to use in module inline"),
305faf4bf1SKazu Hirata     cl::values(clEnumValN(InlinePriorityMode::Size, "size",
315faf4bf1SKazu Hirata                           "Use callee size priority."),
325faf4bf1SKazu Hirata                clEnumValN(InlinePriorityMode::Cost, "cost",
334e9dd210SKazu Hirata                           "Use inline cost priority."),
344e9dd210SKazu Hirata                clEnumValN(InlinePriorityMode::CostBenefit, "cost-benefit",
352d6ec146SKazu Hirata                           "Use cost-benefit ratio."),
3665f7ebe7Sibricchi                clEnumValN(InlinePriorityMode::ML, "ml", "Use ML.")));
374e9dd210SKazu Hirata 
384e9dd210SKazu Hirata static cl::opt<int> ModuleInlinerTopPriorityThreshold(
39d40fd9e1SSiu Chi Chan     "module-inliner-top-priority-threshold", cl::Hidden, cl::init(0),
404e9dd210SKazu Hirata     cl::desc("The cost threshold for call sites that get inlined without the "
414e9dd210SKazu Hirata              "cost-benefit analysis"));
425faf4bf1SKazu Hirata 
43e0bc76ebSKazu Hirata namespace {
44e0bc76ebSKazu Hirata 
4500d98269SKazu Hirata llvm::InlineCost getInlineCostWrapper(CallBase &CB,
4600d98269SKazu Hirata                                       FunctionAnalysisManager &FAM,
4700d98269SKazu Hirata                                       const InlineParams &Params) {
4800d98269SKazu Hirata   Function &Caller = *CB.getCaller();
4900d98269SKazu Hirata   ProfileSummaryInfo *PSI =
5000d98269SKazu Hirata       FAM.getResult<ModuleAnalysisManagerFunctionProxy>(Caller)
5100d98269SKazu Hirata           .getCachedResult<ProfileSummaryAnalysis>(
5200d98269SKazu Hirata               *CB.getParent()->getParent()->getParent());
5300d98269SKazu Hirata 
5400d98269SKazu Hirata   auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(Caller);
5500d98269SKazu Hirata   auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & {
5600d98269SKazu Hirata     return FAM.getResult<AssumptionAnalysis>(F);
5700d98269SKazu Hirata   };
5800d98269SKazu Hirata   auto GetBFI = [&](Function &F) -> BlockFrequencyInfo & {
5900d98269SKazu Hirata     return FAM.getResult<BlockFrequencyAnalysis>(F);
6000d98269SKazu Hirata   };
6100d98269SKazu Hirata   auto GetTLI = [&](Function &F) -> const TargetLibraryInfo & {
6200d98269SKazu Hirata     return FAM.getResult<TargetLibraryAnalysis>(F);
6300d98269SKazu Hirata   };
6400d98269SKazu Hirata 
6500d98269SKazu Hirata   Function &Callee = *CB.getCalledFunction();
6600d98269SKazu Hirata   auto &CalleeTTI = FAM.getResult<TargetIRAnalysis>(Callee);
6700d98269SKazu Hirata   bool RemarksEnabled =
6800d98269SKazu Hirata       Callee.getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
6900d98269SKazu Hirata           DEBUG_TYPE);
7000d98269SKazu Hirata   return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI,
7100d98269SKazu Hirata                        GetBFI, PSI, RemarksEnabled ? &ORE : nullptr);
7200d98269SKazu Hirata }
7300d98269SKazu Hirata 
740a0ccc85SKazu Hirata class SizePriority {
75e0bc76ebSKazu Hirata public:
760a0ccc85SKazu Hirata   SizePriority() = default;
770a0ccc85SKazu Hirata   SizePriority(const CallBase *CB, FunctionAnalysisManager &,
780a0ccc85SKazu Hirata                const InlineParams &) {
79e0bc76ebSKazu Hirata     Function *Callee = CB->getCalledFunction();
800a0ccc85SKazu Hirata     Size = Callee->getInstructionCount();
81e0bc76ebSKazu Hirata   }
82e0bc76ebSKazu Hirata 
830a0ccc85SKazu Hirata   static bool isMoreDesirable(const SizePriority &P1, const SizePriority &P2) {
840a0ccc85SKazu Hirata     return P1.Size < P2.Size;
85e0bc76ebSKazu Hirata   }
86e0bc76ebSKazu Hirata 
870a0ccc85SKazu Hirata private:
88ba7cf9d1SKazu Hirata   unsigned Size = UINT_MAX;
89e0bc76ebSKazu Hirata };
90e0bc76ebSKazu Hirata 
910a0ccc85SKazu Hirata class CostPriority {
920a0ccc85SKazu Hirata public:
930a0ccc85SKazu Hirata   CostPriority() = default;
940a0ccc85SKazu Hirata   CostPriority(const CallBase *CB, FunctionAnalysisManager &FAM,
950a0ccc85SKazu Hirata                const InlineParams &Params) {
960a0ccc85SKazu Hirata     auto IC = getInlineCostWrapper(const_cast<CallBase &>(*CB), FAM, Params);
97e0bc76ebSKazu Hirata     if (IC.isVariable())
9871b12030SKazu Hirata       Cost = IC.getCost();
99e0bc76ebSKazu Hirata     else
10071b12030SKazu Hirata       Cost = IC.isNever() ? INT_MAX : INT_MIN;
101e0bc76ebSKazu Hirata   }
102e0bc76ebSKazu Hirata 
1030a0ccc85SKazu Hirata   static bool isMoreDesirable(const CostPriority &P1, const CostPriority &P2) {
1040a0ccc85SKazu Hirata     return P1.Cost < P2.Cost;
105e0bc76ebSKazu Hirata   }
106e0bc76ebSKazu Hirata 
1070a0ccc85SKazu Hirata private:
108ba7cf9d1SKazu Hirata   int Cost = INT_MAX;
1090a0ccc85SKazu Hirata };
110e0bc76ebSKazu Hirata 
1114e9dd210SKazu Hirata class CostBenefitPriority {
1124e9dd210SKazu Hirata public:
1134e9dd210SKazu Hirata   CostBenefitPriority() = default;
1144e9dd210SKazu Hirata   CostBenefitPriority(const CallBase *CB, FunctionAnalysisManager &FAM,
1154e9dd210SKazu Hirata                       const InlineParams &Params) {
1164e9dd210SKazu Hirata     auto IC = getInlineCostWrapper(const_cast<CallBase &>(*CB), FAM, Params);
117d3127889SXiangyang (Mark) Guo     if (IC.isVariable())
1184e9dd210SKazu Hirata       Cost = IC.getCost();
119d3127889SXiangyang (Mark) Guo     else
120d3127889SXiangyang (Mark) Guo       Cost = IC.isNever() ? INT_MAX : INT_MIN;
1214e9dd210SKazu Hirata     StaticBonusApplied = IC.getStaticBonusApplied();
1224e9dd210SKazu Hirata     CostBenefit = IC.getCostBenefit();
1234e9dd210SKazu Hirata   }
1244e9dd210SKazu Hirata 
1254e9dd210SKazu Hirata   static bool isMoreDesirable(const CostBenefitPriority &P1,
1264e9dd210SKazu Hirata                               const CostBenefitPriority &P2) {
1274e9dd210SKazu Hirata     // We prioritize call sites in the dictionary order of the following
1284e9dd210SKazu Hirata     // priorities:
1294e9dd210SKazu Hirata     //
1304e9dd210SKazu Hirata     // 1. Those call sites that are expected to reduce the caller size when
1314e9dd210SKazu Hirata     //    inlined.  Within them, we prioritize those call sites with bigger
1324e9dd210SKazu Hirata     //    reduction.
1334e9dd210SKazu Hirata     //
1344e9dd210SKazu Hirata     // 2. Those call sites that have gone through the cost-benefit analysis.
1354e9dd210SKazu Hirata     //    Currently, they are limited to hot call sites.  Within them, we
1364e9dd210SKazu Hirata     //    prioritize those call sites with higher benefit-to-cost ratios.
1374e9dd210SKazu Hirata     //
1384e9dd210SKazu Hirata     // 3. Remaining call sites are prioritized according to their costs.
1394e9dd210SKazu Hirata 
1404e9dd210SKazu Hirata     // We add back StaticBonusApplied to determine whether we expect the caller
1414e9dd210SKazu Hirata     // to shrink (even if we don't delete the callee).
1424e9dd210SKazu Hirata     bool P1ReducesCallerSize =
1434e9dd210SKazu Hirata         P1.Cost + P1.StaticBonusApplied < ModuleInlinerTopPriorityThreshold;
1444e9dd210SKazu Hirata     bool P2ReducesCallerSize =
1454e9dd210SKazu Hirata         P2.Cost + P2.StaticBonusApplied < ModuleInlinerTopPriorityThreshold;
1464e9dd210SKazu Hirata     if (P1ReducesCallerSize || P2ReducesCallerSize) {
1474e9dd210SKazu Hirata       // If one reduces the caller size while the other doesn't, then return
1484e9dd210SKazu Hirata       // true iff P1 reduces the caller size.
1494e9dd210SKazu Hirata       if (P1ReducesCallerSize != P2ReducesCallerSize)
1504e9dd210SKazu Hirata         return P1ReducesCallerSize;
1514e9dd210SKazu Hirata 
1524e9dd210SKazu Hirata       // If they both reduce the caller size, pick the one with the smaller
1534e9dd210SKazu Hirata       // cost.
1544e9dd210SKazu Hirata       return P1.Cost < P2.Cost;
1554e9dd210SKazu Hirata     }
1564e9dd210SKazu Hirata 
1574e9dd210SKazu Hirata     bool P1HasCB = P1.CostBenefit.has_value();
1584e9dd210SKazu Hirata     bool P2HasCB = P2.CostBenefit.has_value();
1594e9dd210SKazu Hirata     if (P1HasCB || P2HasCB) {
1604e9dd210SKazu Hirata       // If one has undergone the cost-benefit analysis while the other hasn't,
1614e9dd210SKazu Hirata       // then return true iff P1 has.
1624e9dd210SKazu Hirata       if (P1HasCB != P2HasCB)
1634e9dd210SKazu Hirata         return P1HasCB;
1644e9dd210SKazu Hirata 
1654e9dd210SKazu Hirata       // If they have undergone the cost-benefit analysis, then pick the one
1664e9dd210SKazu Hirata       // with a higher benefit-to-cost ratio.
1674e9dd210SKazu Hirata       APInt LHS = P1.CostBenefit->getBenefit() * P2.CostBenefit->getCost();
1684e9dd210SKazu Hirata       APInt RHS = P2.CostBenefit->getBenefit() * P1.CostBenefit->getCost();
1694e9dd210SKazu Hirata       return LHS.ugt(RHS);
1704e9dd210SKazu Hirata     }
1714e9dd210SKazu Hirata 
1724e9dd210SKazu Hirata     // Remaining call sites are ordered according to their costs.
1734e9dd210SKazu Hirata     return P1.Cost < P2.Cost;
1744e9dd210SKazu Hirata   }
1754e9dd210SKazu Hirata 
1764e9dd210SKazu Hirata private:
177ba7cf9d1SKazu Hirata   int Cost = INT_MAX;
178ba7cf9d1SKazu Hirata   int StaticBonusApplied = 0;
179d4b6fcb3SFangrui Song   std::optional<CostBenefitPair> CostBenefit;
1804e9dd210SKazu Hirata };
1814e9dd210SKazu Hirata 
1822d6ec146SKazu Hirata class MLPriority {
1832d6ec146SKazu Hirata public:
1842d6ec146SKazu Hirata   MLPriority() = default;
1852d6ec146SKazu Hirata   MLPriority(const CallBase *CB, FunctionAnalysisManager &FAM,
1862d6ec146SKazu Hirata              const InlineParams &Params) {
1872d6ec146SKazu Hirata     auto IC = getInlineCostWrapper(const_cast<CallBase &>(*CB), FAM, Params);
1882d6ec146SKazu Hirata     if (IC.isVariable())
1892d6ec146SKazu Hirata       Cost = IC.getCost();
1902d6ec146SKazu Hirata     else
1912d6ec146SKazu Hirata       Cost = IC.isNever() ? INT_MAX : INT_MIN;
1922d6ec146SKazu Hirata   }
1932d6ec146SKazu Hirata 
1942d6ec146SKazu Hirata   static bool isMoreDesirable(const MLPriority &P1, const MLPriority &P2) {
1952d6ec146SKazu Hirata     return P1.Cost < P2.Cost;
1962d6ec146SKazu Hirata   }
1972d6ec146SKazu Hirata 
1982d6ec146SKazu Hirata private:
1992d6ec146SKazu Hirata   int Cost = INT_MAX;
2002d6ec146SKazu Hirata };
2012d6ec146SKazu Hirata 
2020a0ccc85SKazu Hirata template <typename PriorityT>
2030a0ccc85SKazu Hirata class PriorityInlineOrder : public InlineOrder<std::pair<CallBase *, int>> {
2040a0ccc85SKazu Hirata   using T = std::pair<CallBase *, int>;
2050a0ccc85SKazu Hirata 
2060a0ccc85SKazu Hirata   bool hasLowerPriority(const CallBase *L, const CallBase *R) const {
207e0bc76ebSKazu Hirata     const auto I1 = Priorities.find(L);
208e0bc76ebSKazu Hirata     const auto I2 = Priorities.find(R);
209e0bc76ebSKazu Hirata     assert(I1 != Priorities.end() && I2 != Priorities.end());
2100a0ccc85SKazu Hirata     return PriorityT::isMoreDesirable(I2->second, I1->second);
211e0bc76ebSKazu Hirata   }
212e0bc76ebSKazu Hirata 
2130a0ccc85SKazu Hirata   bool updateAndCheckDecreased(const CallBase *CB) {
214e0bc76ebSKazu Hirata     auto It = Priorities.find(CB);
215e0bc76ebSKazu Hirata     const auto OldPriority = It->second;
2160a0ccc85SKazu Hirata     It->second = PriorityT(CB, FAM, Params);
217e0bc76ebSKazu Hirata     const auto NewPriority = It->second;
2180a0ccc85SKazu Hirata     return PriorityT::isMoreDesirable(OldPriority, NewPriority);
219e0bc76ebSKazu Hirata   }
220e0bc76ebSKazu Hirata 
221e0bc76ebSKazu Hirata   // A call site could become less desirable for inlining because of the size
222e0bc76ebSKazu Hirata   // growth from prior inlining into the callee. This method is used to lazily
223e0bc76ebSKazu Hirata   // update the desirability of a call site if it's decreasing. It is only
22481d651e7SKazu Hirata   // called on pop(), not every time the desirability changes. When the
22581d651e7SKazu Hirata   // desirability of the front call site decreases, an updated one would be
22681d651e7SKazu Hirata   // pushed right back into the heap. For simplicity, those cases where the
22781d651e7SKazu Hirata   // desirability of a call site increases are ignored here.
228f65cd04aSKazu Hirata   void pop_heap_adjust() {
229e0bc76ebSKazu Hirata     std::pop_heap(Heap.begin(), Heap.end(), isLess);
23033430205SKazu Hirata     while (updateAndCheckDecreased(Heap.back())) {
231e0bc76ebSKazu Hirata       std::push_heap(Heap.begin(), Heap.end(), isLess);
23233430205SKazu Hirata       std::pop_heap(Heap.begin(), Heap.end(), isLess);
233e0bc76ebSKazu Hirata     }
234e0bc76ebSKazu Hirata   }
235e0bc76ebSKazu Hirata 
236e0bc76ebSKazu Hirata public:
2370a0ccc85SKazu Hirata   PriorityInlineOrder(FunctionAnalysisManager &FAM, const InlineParams &Params)
2380a0ccc85SKazu Hirata       : FAM(FAM), Params(Params) {
2390a0ccc85SKazu Hirata     isLess = [&](const CallBase *L, const CallBase *R) {
2400a0ccc85SKazu Hirata       return hasLowerPriority(L, R);
241e0bc76ebSKazu Hirata     };
242e0bc76ebSKazu Hirata   }
243e0bc76ebSKazu Hirata 
244e0bc76ebSKazu Hirata   size_t size() override { return Heap.size(); }
245e0bc76ebSKazu Hirata 
246e0bc76ebSKazu Hirata   void push(const T &Elt) override {
247e0bc76ebSKazu Hirata     CallBase *CB = Elt.first;
248e0bc76ebSKazu Hirata     const int InlineHistoryID = Elt.second;
249e0bc76ebSKazu Hirata 
250e0bc76ebSKazu Hirata     Heap.push_back(CB);
2510a0ccc85SKazu Hirata     Priorities[CB] = PriorityT(CB, FAM, Params);
252e0bc76ebSKazu Hirata     std::push_heap(Heap.begin(), Heap.end(), isLess);
253e0bc76ebSKazu Hirata     InlineHistoryMap[CB] = InlineHistoryID;
254e0bc76ebSKazu Hirata   }
255e0bc76ebSKazu Hirata 
256e0bc76ebSKazu Hirata   T pop() override {
257e0bc76ebSKazu Hirata     assert(size() > 0);
258f65cd04aSKazu Hirata     pop_heap_adjust();
259e0bc76ebSKazu Hirata 
2603fb3df36SKazu Hirata     CallBase *CB = Heap.pop_back_val();
261e0bc76ebSKazu Hirata     T Result = std::make_pair(CB, InlineHistoryMap[CB]);
262e0bc76ebSKazu Hirata     InlineHistoryMap.erase(CB);
263e0bc76ebSKazu Hirata     return Result;
264e0bc76ebSKazu Hirata   }
265e0bc76ebSKazu Hirata 
266e0bc76ebSKazu Hirata   void erase_if(function_ref<bool(T)> Pred) override {
267e0bc76ebSKazu Hirata     auto PredWrapper = [=](CallBase *CB) -> bool {
26806ca52e2SVincent Lee       return Pred(std::make_pair(CB, InlineHistoryMap[CB]));
269e0bc76ebSKazu Hirata     };
270e0bc76ebSKazu Hirata     llvm::erase_if(Heap, PredWrapper);
271e0bc76ebSKazu Hirata     std::make_heap(Heap.begin(), Heap.end(), isLess);
272e0bc76ebSKazu Hirata   }
273e0bc76ebSKazu Hirata 
274e0bc76ebSKazu Hirata private:
275e0bc76ebSKazu Hirata   SmallVector<CallBase *, 16> Heap;
276e0bc76ebSKazu Hirata   std::function<bool(const CallBase *L, const CallBase *R)> isLess;
277e0bc76ebSKazu Hirata   DenseMap<CallBase *, int> InlineHistoryMap;
2780a0ccc85SKazu Hirata   DenseMap<const CallBase *, PriorityT> Priorities;
2790a0ccc85SKazu Hirata   FunctionAnalysisManager &FAM;
2800a0ccc85SKazu Hirata   const InlineParams &Params;
281e0bc76ebSKazu Hirata };
282e0bc76ebSKazu Hirata 
283e0bc76ebSKazu Hirata } // namespace
284e0bc76ebSKazu Hirata 
28565f7ebe7Sibricchi AnalysisKey llvm::PluginInlineOrderAnalysis::Key;
28665f7ebe7Sibricchi 
287d52e775bSLiqiang Tao std::unique_ptr<InlineOrder<std::pair<CallBase *, int>>>
28865f7ebe7Sibricchi llvm::getDefaultInlineOrder(FunctionAnalysisManager &FAM,
28965f7ebe7Sibricchi                             const InlineParams &Params,
29065f7ebe7Sibricchi                             ModuleAnalysisManager &MAM, Module &M) {
291d52e775bSLiqiang Tao   switch (UseInlinePriority) {
292d52e775bSLiqiang Tao   case InlinePriorityMode::Size:
293d52e775bSLiqiang Tao     LLVM_DEBUG(dbgs() << "    Current used priority: Size priority ---- \n");
2940a0ccc85SKazu Hirata     return std::make_unique<PriorityInlineOrder<SizePriority>>(FAM, Params);
295d52e775bSLiqiang Tao 
296d52e775bSLiqiang Tao   case InlinePriorityMode::Cost:
297d52e775bSLiqiang Tao     LLVM_DEBUG(dbgs() << "    Current used priority: Cost priority ---- \n");
2980a0ccc85SKazu Hirata     return std::make_unique<PriorityInlineOrder<CostPriority>>(FAM, Params);
299d52e775bSLiqiang Tao 
3004e9dd210SKazu Hirata   case InlinePriorityMode::CostBenefit:
3014e9dd210SKazu Hirata     LLVM_DEBUG(
3024e9dd210SKazu Hirata         dbgs() << "    Current used priority: cost-benefit priority ---- \n");
30365f7ebe7Sibricchi     return std::make_unique<PriorityInlineOrder<CostBenefitPriority>>(FAM,
30465f7ebe7Sibricchi                                                                       Params);
3052d6ec146SKazu Hirata   case InlinePriorityMode::ML:
30665f7ebe7Sibricchi     LLVM_DEBUG(dbgs() << "    Current used priority: ML priority ---- \n");
3072d6ec146SKazu Hirata     return std::make_unique<PriorityInlineOrder<MLPriority>>(FAM, Params);
308d52e775bSLiqiang Tao   }
309d52e775bSLiqiang Tao   return nullptr;
310d52e775bSLiqiang Tao }
31165f7ebe7Sibricchi 
31265f7ebe7Sibricchi std::unique_ptr<InlineOrder<std::pair<CallBase *, int>>>
31365f7ebe7Sibricchi llvm::getInlineOrder(FunctionAnalysisManager &FAM, const InlineParams &Params,
31465f7ebe7Sibricchi                      ModuleAnalysisManager &MAM, Module &M) {
315*ab4253f6SMichele Scandale   if (MAM.isPassRegistered<PluginInlineOrderAnalysis>()) {
31665f7ebe7Sibricchi     LLVM_DEBUG(dbgs() << "    Current used priority: plugin ---- \n");
31765f7ebe7Sibricchi     return MAM.getResult<PluginInlineOrderAnalysis>(M).Factory(FAM, Params, MAM,
31865f7ebe7Sibricchi                                                                M);
31965f7ebe7Sibricchi   }
32065f7ebe7Sibricchi   return getDefaultInlineOrder(FAM, Params, MAM, M);
32165f7ebe7Sibricchi }
322