16cad45d5SLiqiang Tao //===- ModuleInliner.cpp - Code related to module inliner -----------------===// 26cad45d5SLiqiang Tao // 36cad45d5SLiqiang Tao // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 46cad45d5SLiqiang Tao // See https://llvm.org/LICENSE.txt for license information. 56cad45d5SLiqiang Tao // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 66cad45d5SLiqiang Tao // 76cad45d5SLiqiang Tao //===----------------------------------------------------------------------===// 86cad45d5SLiqiang Tao // 96cad45d5SLiqiang Tao // This file implements the mechanics required to implement inlining without 106cad45d5SLiqiang Tao // missing any calls in the module level. It doesn't need any infromation about 116cad45d5SLiqiang Tao // SCC or call graph, which is different from the SCC inliner. The decisions of 126cad45d5SLiqiang Tao // which calls are profitable to inline are implemented elsewhere. 136cad45d5SLiqiang Tao // 146cad45d5SLiqiang Tao //===----------------------------------------------------------------------===// 156cad45d5SLiqiang Tao 166cad45d5SLiqiang Tao #include "llvm/Transforms/IPO/ModuleInliner.h" 176cad45d5SLiqiang Tao #include "llvm/ADT/ScopeExit.h" 186cad45d5SLiqiang Tao #include "llvm/ADT/SmallVector.h" 196cad45d5SLiqiang Tao #include "llvm/ADT/Statistic.h" 20f1985a3fSserge-sans-paille #include "llvm/Analysis/AliasAnalysis.h" 216cad45d5SLiqiang Tao #include "llvm/Analysis/AssumptionCache.h" 226cad45d5SLiqiang Tao #include "llvm/Analysis/BlockFrequencyInfo.h" 2332097666SMircea Trofin #include "llvm/Analysis/CtxProfAnalysis.h" 246cad45d5SLiqiang Tao #include "llvm/Analysis/InlineAdvisor.h" 256cad45d5SLiqiang Tao #include "llvm/Analysis/InlineCost.h" 266cad45d5SLiqiang Tao #include "llvm/Analysis/InlineOrder.h" 276cad45d5SLiqiang Tao #include "llvm/Analysis/OptimizationRemarkEmitter.h" 286cad45d5SLiqiang Tao #include "llvm/Analysis/ProfileSummaryInfo.h" 29f1985a3fSserge-sans-paille #include "llvm/Analysis/ReplayInlineAdvisor.h" 306cad45d5SLiqiang Tao #include "llvm/Analysis/TargetLibraryInfo.h" 316cad45d5SLiqiang Tao #include "llvm/IR/DiagnosticInfo.h" 326cad45d5SLiqiang Tao #include "llvm/IR/Function.h" 336cad45d5SLiqiang Tao #include "llvm/IR/InstIterator.h" 346cad45d5SLiqiang Tao #include "llvm/IR/Instruction.h" 356cad45d5SLiqiang Tao #include "llvm/IR/IntrinsicInst.h" 366cad45d5SLiqiang Tao #include "llvm/IR/Module.h" 376cad45d5SLiqiang Tao #include "llvm/IR/PassManager.h" 386cad45d5SLiqiang Tao #include "llvm/Support/CommandLine.h" 396cad45d5SLiqiang Tao #include "llvm/Support/Debug.h" 406cad45d5SLiqiang Tao #include "llvm/Support/raw_ostream.h" 416cad45d5SLiqiang Tao #include "llvm/Transforms/Utils/CallPromotionUtils.h" 426cad45d5SLiqiang Tao #include "llvm/Transforms/Utils/Cloning.h" 436cad45d5SLiqiang Tao #include <cassert> 446cad45d5SLiqiang Tao 456cad45d5SLiqiang Tao using namespace llvm; 466cad45d5SLiqiang Tao 476cad45d5SLiqiang Tao #define DEBUG_TYPE "module-inline" 486cad45d5SLiqiang Tao 496cad45d5SLiqiang Tao STATISTIC(NumInlined, "Number of functions inlined"); 506cad45d5SLiqiang Tao STATISTIC(NumDeleted, "Number of functions deleted because all callers found"); 516cad45d5SLiqiang Tao 52*c8365feeSMircea Trofin cl::opt<bool> CtxProfPromoteAlwaysInline( 53*c8365feeSMircea Trofin "ctx-prof-promote-alwaysinline", cl::init(false), cl::Hidden, 54*c8365feeSMircea Trofin cl::desc("If using a contextual profile in this module, and an indirect " 55*c8365feeSMircea Trofin "call target is marked as alwaysinline, perform indirect call " 56*c8365feeSMircea Trofin "promotion for that target. If multiple targets for an indirect " 57*c8365feeSMircea Trofin "call site fit this description, they are all promoted.")); 58*c8365feeSMircea Trofin 596cad45d5SLiqiang Tao /// Return true if the specified inline history ID 606cad45d5SLiqiang Tao /// indicates an inline history that includes the specified function. 616cad45d5SLiqiang Tao static bool inlineHistoryIncludes( 626cad45d5SLiqiang Tao Function *F, int InlineHistoryID, 636cad45d5SLiqiang Tao const SmallVectorImpl<std::pair<Function *, int>> &InlineHistory) { 646cad45d5SLiqiang Tao while (InlineHistoryID != -1) { 656cad45d5SLiqiang Tao assert(unsigned(InlineHistoryID) < InlineHistory.size() && 666cad45d5SLiqiang Tao "Invalid inline history ID"); 676cad45d5SLiqiang Tao if (InlineHistory[InlineHistoryID].first == F) 686cad45d5SLiqiang Tao return true; 696cad45d5SLiqiang Tao InlineHistoryID = InlineHistory[InlineHistoryID].second; 706cad45d5SLiqiang Tao } 716cad45d5SLiqiang Tao return false; 726cad45d5SLiqiang Tao } 736cad45d5SLiqiang Tao 746cad45d5SLiqiang Tao InlineAdvisor &ModuleInlinerPass::getAdvisor(const ModuleAnalysisManager &MAM, 756cad45d5SLiqiang Tao FunctionAnalysisManager &FAM, 766cad45d5SLiqiang Tao Module &M) { 776cad45d5SLiqiang Tao if (OwnedAdvisor) 786cad45d5SLiqiang Tao return *OwnedAdvisor; 796cad45d5SLiqiang Tao 806cad45d5SLiqiang Tao auto *IAA = MAM.getCachedResult<InlineAdvisorAnalysis>(M); 816cad45d5SLiqiang Tao if (!IAA) { 826cad45d5SLiqiang Tao // It should still be possible to run the inliner as a stand-alone module 836cad45d5SLiqiang Tao // pass, for test scenarios. In that case, we default to the 846cad45d5SLiqiang Tao // DefaultInlineAdvisor, which doesn't need to keep state between module 856cad45d5SLiqiang Tao // pass runs. It also uses just the default InlineParams. In this case, we 866cad45d5SLiqiang Tao // need to use the provided FAM, which is valid for the duration of the 876cad45d5SLiqiang Tao // inliner pass, and thus the lifetime of the owned advisor. The one we 886cad45d5SLiqiang Tao // would get from the MAM can be invalidated as a result of the inliner's 896cad45d5SLiqiang Tao // activity. 90e0d06959SMingming Liu OwnedAdvisor = std::make_unique<DefaultInlineAdvisor>( 919111920aSKazu Hirata M, FAM, Params, InlineContext{LTOPhase, InlinePass::ModuleInliner}); 926cad45d5SLiqiang Tao 936cad45d5SLiqiang Tao return *OwnedAdvisor; 946cad45d5SLiqiang Tao } 956cad45d5SLiqiang Tao assert(IAA->getAdvisor() && 966cad45d5SLiqiang Tao "Expected a present InlineAdvisorAnalysis also have an " 976cad45d5SLiqiang Tao "InlineAdvisor initialized"); 986cad45d5SLiqiang Tao return *IAA->getAdvisor(); 996cad45d5SLiqiang Tao } 1006cad45d5SLiqiang Tao 1016cad45d5SLiqiang Tao static bool isKnownLibFunction(Function &F, TargetLibraryInfo &TLI) { 1026cad45d5SLiqiang Tao LibFunc LF; 1036cad45d5SLiqiang Tao 1046cad45d5SLiqiang Tao // Either this is a normal library function or a "vectorizable" 1056cad45d5SLiqiang Tao // function. Not using the VFDatabase here because this query 1066cad45d5SLiqiang Tao // is related only to libraries handled via the TLI. 1076cad45d5SLiqiang Tao return TLI.getLibFunc(F, LF) || 1086cad45d5SLiqiang Tao TLI.isKnownVectorFunctionInLibrary(F.getName()); 1096cad45d5SLiqiang Tao } 1106cad45d5SLiqiang Tao 1116cad45d5SLiqiang Tao PreservedAnalyses ModuleInlinerPass::run(Module &M, 1126cad45d5SLiqiang Tao ModuleAnalysisManager &MAM) { 1136cad45d5SLiqiang Tao LLVM_DEBUG(dbgs() << "---- Module Inliner is Running ---- \n"); 1146cad45d5SLiqiang Tao 1156cad45d5SLiqiang Tao auto &IAA = MAM.getResult<InlineAdvisorAnalysis>(M); 1169111920aSKazu Hirata if (!IAA.tryCreate(Params, Mode, {}, 117e0d06959SMingming Liu InlineContext{LTOPhase, InlinePass::ModuleInliner})) { 1186cad45d5SLiqiang Tao M.getContext().emitError( 1196cad45d5SLiqiang Tao "Could not setup Inlining Advisor for the requested " 1206cad45d5SLiqiang Tao "mode and/or options"); 1216cad45d5SLiqiang Tao return PreservedAnalyses::all(); 1226cad45d5SLiqiang Tao } 1236cad45d5SLiqiang Tao 12432097666SMircea Trofin auto &CtxProf = MAM.getResult<CtxProfAnalysis>(M); 12532097666SMircea Trofin 1266cad45d5SLiqiang Tao bool Changed = false; 1276cad45d5SLiqiang Tao 1286cad45d5SLiqiang Tao ProfileSummaryInfo *PSI = MAM.getCachedResult<ProfileSummaryAnalysis>(M); 1296cad45d5SLiqiang Tao 1306cad45d5SLiqiang Tao FunctionAnalysisManager &FAM = 1316cad45d5SLiqiang Tao MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 1326cad45d5SLiqiang Tao 1336cad45d5SLiqiang Tao auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & { 1346cad45d5SLiqiang Tao return FAM.getResult<TargetLibraryAnalysis>(F); 1356cad45d5SLiqiang Tao }; 1366cad45d5SLiqiang Tao 1376cad45d5SLiqiang Tao InlineAdvisor &Advisor = getAdvisor(MAM, FAM, M); 1386cad45d5SLiqiang Tao Advisor.onPassEntry(); 1396cad45d5SLiqiang Tao 1406cad45d5SLiqiang Tao auto AdvisorOnExit = make_scope_exit([&] { Advisor.onPassExit(); }); 1416cad45d5SLiqiang Tao 1426cad45d5SLiqiang Tao // In the module inliner, a priority-based worklist is used for calls across 1436cad45d5SLiqiang Tao // the entire Module. With this module inliner, the inline order is not 1446cad45d5SLiqiang Tao // limited to bottom-up order. More globally scope inline order is enabled. 1456cad45d5SLiqiang Tao // Also, the inline deferral logic become unnecessary in this module inliner. 1466cad45d5SLiqiang Tao // It is possible to use other priority heuristics, e.g. profile-based 1476cad45d5SLiqiang Tao // heuristic. 1486cad45d5SLiqiang Tao // 1496cad45d5SLiqiang Tao // TODO: Here is a huge amount duplicate code between the module inliner and 1506cad45d5SLiqiang Tao // the SCC inliner, which need some refactoring. 15165f7ebe7Sibricchi auto Calls = getInlineOrder(FAM, Params, MAM, M); 1526cad45d5SLiqiang Tao assert(Calls != nullptr && "Expected an initialized InlineOrder"); 1536cad45d5SLiqiang Tao 1546cad45d5SLiqiang Tao // Populate the initial list of calls in this module. 155*c8365feeSMircea Trofin SetVector<std::pair<CallBase *, Function *>> ICPCandidates; 1566cad45d5SLiqiang Tao for (Function &F : M) { 1576cad45d5SLiqiang Tao auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F); 158*c8365feeSMircea Trofin for (Instruction &I : instructions(F)) { 159*c8365feeSMircea Trofin if (auto *CB = dyn_cast<CallBase>(&I)) { 1606cad45d5SLiqiang Tao if (Function *Callee = CB->getCalledFunction()) { 1616cad45d5SLiqiang Tao if (!Callee->isDeclaration()) 1626cad45d5SLiqiang Tao Calls->push({CB, -1}); 1636cad45d5SLiqiang Tao else if (!isa<IntrinsicInst>(I)) { 1646cad45d5SLiqiang Tao using namespace ore; 1656cad45d5SLiqiang Tao setInlineRemark(*CB, "unavailable definition"); 1666cad45d5SLiqiang Tao ORE.emit([&]() { 1676cad45d5SLiqiang Tao return OptimizationRemarkMissed(DEBUG_TYPE, "NoDefinition", &I) 1686cad45d5SLiqiang Tao << NV("Callee", Callee) << " will not be inlined into " 1696cad45d5SLiqiang Tao << NV("Caller", CB->getCaller()) 1706cad45d5SLiqiang Tao << " because its definition is unavailable" 1716cad45d5SLiqiang Tao << setIsVerbose(); 1726cad45d5SLiqiang Tao }); 1736cad45d5SLiqiang Tao } 174*c8365feeSMircea Trofin } else if (CtxProfPromoteAlwaysInline && CtxProf && 175*c8365feeSMircea Trofin CB->isIndirectCall()) { 176*c8365feeSMircea Trofin CtxProfAnalysis::collectIndirectCallPromotionList(*CB, CtxProf, 177*c8365feeSMircea Trofin ICPCandidates); 1786cad45d5SLiqiang Tao } 1796cad45d5SLiqiang Tao } 180*c8365feeSMircea Trofin } 181*c8365feeSMircea Trofin } 182*c8365feeSMircea Trofin for (auto &[CB, Target] : ICPCandidates) { 183*c8365feeSMircea Trofin if (auto *DirectCB = promoteCallWithIfThenElse(*CB, *Target, CtxProf)) 184*c8365feeSMircea Trofin Calls->push({DirectCB, -1}); 185*c8365feeSMircea Trofin } 1866cad45d5SLiqiang Tao if (Calls->empty()) 1876cad45d5SLiqiang Tao return PreservedAnalyses::all(); 1886cad45d5SLiqiang Tao 1896cad45d5SLiqiang Tao // When inlining a callee produces new call sites, we want to keep track of 1906cad45d5SLiqiang Tao // the fact that they were inlined from the callee. This allows us to avoid 1916cad45d5SLiqiang Tao // infinite inlining in some obscure cases. To represent this, we use an 1926cad45d5SLiqiang Tao // index into the InlineHistory vector. 1936cad45d5SLiqiang Tao SmallVector<std::pair<Function *, int>, 16> InlineHistory; 1946cad45d5SLiqiang Tao 1956cad45d5SLiqiang Tao // Track the dead functions to delete once finished with inlining calls. We 1966cad45d5SLiqiang Tao // defer deleting these to make it easier to handle the call graph updates. 1976cad45d5SLiqiang Tao SmallVector<Function *, 4> DeadFunctions; 1986cad45d5SLiqiang Tao 1996cad45d5SLiqiang Tao // Loop forward over all of the calls. 2006cad45d5SLiqiang Tao while (!Calls->empty()) { 201d3b95eccSKazu Hirata auto P = Calls->pop(); 202d3b95eccSKazu Hirata CallBase *CB = P.first; 203d3b95eccSKazu Hirata const int InlineHistoryID = P.second; 204d3b95eccSKazu Hirata Function &F = *CB->getCaller(); 205d3b95eccSKazu Hirata Function &Callee = *CB->getCalledFunction(); 2066cad45d5SLiqiang Tao 2076cad45d5SLiqiang Tao LLVM_DEBUG(dbgs() << "Inlining calls in: " << F.getName() << "\n" 2086cad45d5SLiqiang Tao << " Function size: " << F.getInstructionCount() 2096cad45d5SLiqiang Tao << "\n"); 210d3b95eccSKazu Hirata (void)F; 2116cad45d5SLiqiang Tao 2126cad45d5SLiqiang Tao auto GetAssumptionCache = [&](Function &F) -> AssumptionCache & { 2136cad45d5SLiqiang Tao return FAM.getResult<AssumptionAnalysis>(F); 2146cad45d5SLiqiang Tao }; 2156cad45d5SLiqiang Tao 2166cad45d5SLiqiang Tao if (InlineHistoryID != -1 && 2176cad45d5SLiqiang Tao inlineHistoryIncludes(&Callee, InlineHistoryID, InlineHistory)) { 2186cad45d5SLiqiang Tao setInlineRemark(*CB, "recursive"); 2196cad45d5SLiqiang Tao continue; 2206cad45d5SLiqiang Tao } 2216cad45d5SLiqiang Tao 2226cad45d5SLiqiang Tao auto Advice = Advisor.getAdvice(*CB, /*OnlyMandatory*/ false); 2236cad45d5SLiqiang Tao // Check whether we want to inline this callsite. 2246cad45d5SLiqiang Tao if (!Advice->isInliningRecommended()) { 2256cad45d5SLiqiang Tao Advice->recordUnattemptedInlining(); 2266cad45d5SLiqiang Tao continue; 2276cad45d5SLiqiang Tao } 2286cad45d5SLiqiang Tao 2296cad45d5SLiqiang Tao // Setup the data structure used to plumb customization into the 2306cad45d5SLiqiang Tao // `InlineFunction` routine. 2316cad45d5SLiqiang Tao InlineFunctionInfo IFI( 232fa6ea7a4SArthur Eubanks GetAssumptionCache, PSI, 2336cad45d5SLiqiang Tao &FAM.getResult<BlockFrequencyAnalysis>(*(CB->getCaller())), 2346cad45d5SLiqiang Tao &FAM.getResult<BlockFrequencyAnalysis>(Callee)); 2356cad45d5SLiqiang Tao 2366cad45d5SLiqiang Tao InlineResult IR = 23732097666SMircea Trofin InlineFunction(*CB, IFI, CtxProf, /*MergeAttributes=*/true, 23800874c48SKazu Hirata &FAM.getResult<AAManager>(*CB->getCaller())); 2396cad45d5SLiqiang Tao if (!IR.isSuccess()) { 2406cad45d5SLiqiang Tao Advice->recordUnsuccessfulInlining(IR); 2416cad45d5SLiqiang Tao continue; 2426cad45d5SLiqiang Tao } 2436cad45d5SLiqiang Tao 2446e4fbd2fSKazu Hirata Changed = true; 2456cad45d5SLiqiang Tao ++NumInlined; 2466cad45d5SLiqiang Tao 24777501bfaSKazu Hirata LLVM_DEBUG(dbgs() << " Size after inlining: " << F.getInstructionCount() 24877501bfaSKazu Hirata << "\n"); 2496cad45d5SLiqiang Tao 2506cad45d5SLiqiang Tao // Add any new callsites to defined functions to the worklist. 2516cad45d5SLiqiang Tao if (!IFI.InlinedCallSites.empty()) { 2526cad45d5SLiqiang Tao int NewHistoryID = InlineHistory.size(); 2536cad45d5SLiqiang Tao InlineHistory.push_back({&Callee, InlineHistoryID}); 2546cad45d5SLiqiang Tao 2556cad45d5SLiqiang Tao for (CallBase *ICB : reverse(IFI.InlinedCallSites)) { 2566cad45d5SLiqiang Tao Function *NewCallee = ICB->getCalledFunction(); 2576cad45d5SLiqiang Tao if (!NewCallee) { 2586cad45d5SLiqiang Tao // Try to promote an indirect (virtual) call without waiting for 2596cad45d5SLiqiang Tao // the post-inline cleanup and the next DevirtSCCRepeatedPass 2606cad45d5SLiqiang Tao // iteration because the next iteration may not happen and we may 2616cad45d5SLiqiang Tao // miss inlining it. 2623b226180SMircea Trofin // FIXME: enable for ctxprof. 2633b226180SMircea Trofin if (!CtxProf) 2646cad45d5SLiqiang Tao if (tryPromoteCall(*ICB)) 2656cad45d5SLiqiang Tao NewCallee = ICB->getCalledFunction(); 2666cad45d5SLiqiang Tao } 2676cad45d5SLiqiang Tao if (NewCallee) 2686cad45d5SLiqiang Tao if (!NewCallee->isDeclaration()) 2696cad45d5SLiqiang Tao Calls->push({ICB, NewHistoryID}); 2706cad45d5SLiqiang Tao } 2716cad45d5SLiqiang Tao } 2726cad45d5SLiqiang Tao 2736cad45d5SLiqiang Tao // For local functions, check whether this makes the callee trivially 2746cad45d5SLiqiang Tao // dead. In that case, we can drop the body of the function eagerly 2756cad45d5SLiqiang Tao // which may reduce the number of callers of other functions to one, 2766cad45d5SLiqiang Tao // changing inline cost thresholds. 2776cad45d5SLiqiang Tao bool CalleeWasDeleted = false; 2786cad45d5SLiqiang Tao if (Callee.hasLocalLinkage()) { 2796cad45d5SLiqiang Tao // To check this we also need to nuke any dead constant uses (perhaps 2806cad45d5SLiqiang Tao // made dead by this operation on other functions). 2816cad45d5SLiqiang Tao Callee.removeDeadConstantUsers(); 2826cad45d5SLiqiang Tao // if (Callee.use_empty() && !CG.isLibFunction(Callee)) { 2836cad45d5SLiqiang Tao if (Callee.use_empty() && !isKnownLibFunction(Callee, GetTLI(Callee))) { 2846cad45d5SLiqiang Tao Calls->erase_if([&](const std::pair<CallBase *, int> &Call) { 2856cad45d5SLiqiang Tao return Call.first->getCaller() == &Callee; 2866cad45d5SLiqiang Tao }); 2876cad45d5SLiqiang Tao // Clear the body and queue the function itself for deletion when we 2886cad45d5SLiqiang Tao // finish inlining. 2896cad45d5SLiqiang Tao // Note that after this point, it is an error to do anything other 2906cad45d5SLiqiang Tao // than use the callee's address or delete it. 2916cad45d5SLiqiang Tao Callee.dropAllReferences(); 2926cad45d5SLiqiang Tao assert(!is_contained(DeadFunctions, &Callee) && 2936cad45d5SLiqiang Tao "Cannot put cause a function to become dead twice!"); 2946cad45d5SLiqiang Tao DeadFunctions.push_back(&Callee); 2956cad45d5SLiqiang Tao CalleeWasDeleted = true; 2966cad45d5SLiqiang Tao } 2976cad45d5SLiqiang Tao } 2986cad45d5SLiqiang Tao if (CalleeWasDeleted) 2996cad45d5SLiqiang Tao Advice->recordInliningWithCalleeDeleted(); 3006cad45d5SLiqiang Tao else 3016cad45d5SLiqiang Tao Advice->recordInlining(); 3026cad45d5SLiqiang Tao } 3036cad45d5SLiqiang Tao 3046cad45d5SLiqiang Tao // Now that we've finished inlining all of the calls across this module, 3056cad45d5SLiqiang Tao // delete all of the trivially dead functions. 3066cad45d5SLiqiang Tao // 3076cad45d5SLiqiang Tao // Note that this walks a pointer set which has non-deterministic order but 3086cad45d5SLiqiang Tao // that is OK as all we do is delete things and add pointers to unordered 3096cad45d5SLiqiang Tao // sets. 3106cad45d5SLiqiang Tao for (Function *DeadF : DeadFunctions) { 3116cad45d5SLiqiang Tao // Clear out any cached analyses. 3126cad45d5SLiqiang Tao FAM.clear(*DeadF, DeadF->getName()); 3136cad45d5SLiqiang Tao 3146cad45d5SLiqiang Tao // And delete the actual function from the module. 315fe827a93SArthur Eubanks M.getFunctionList().erase(DeadF); 3166cad45d5SLiqiang Tao 3176cad45d5SLiqiang Tao ++NumDeleted; 3186cad45d5SLiqiang Tao } 3196cad45d5SLiqiang Tao 3206cad45d5SLiqiang Tao if (!Changed) 3216cad45d5SLiqiang Tao return PreservedAnalyses::all(); 3226cad45d5SLiqiang Tao 3236cad45d5SLiqiang Tao return PreservedAnalyses::none(); 3246cad45d5SLiqiang Tao } 325