@@ -249,6 +249,9 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
249249 // / Getter for BlockFrequencyInfo
250250 function_ref<BlockFrequencyInfo &(Function &)> GetBFI;
251251
252+ // / Getter for TargetLibraryInfo
253+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI;
254+
252255 // / Profile summary information.
253256 ProfileSummaryInfo *PSI;
254257
@@ -433,6 +436,7 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
433436 bool simplifyIntrinsicCallIsConstant (CallBase &CB);
434437 bool simplifyIntrinsicCallObjectSize (CallBase &CB);
435438 ConstantInt *stripAndComputeInBoundsConstantOffsets (Value *&V);
439+ bool isLoweredToCall (Function *F, CallBase &Call);
436440
437441 // / Return true if the given argument to the function being considered for
438442 // / inlining has the given attribute set either at the call site or the
@@ -492,13 +496,15 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
492496 bool visitUnreachableInst (UnreachableInst &I);
493497
494498public:
495- CallAnalyzer (Function &Callee, CallBase &Call, const TargetTransformInfo &TTI,
496- function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
497- function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr ,
498- ProfileSummaryInfo *PSI = nullptr ,
499- OptimizationRemarkEmitter *ORE = nullptr )
499+ CallAnalyzer (
500+ Function &Callee, CallBase &Call, const TargetTransformInfo &TTI,
501+ function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
502+ function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr ,
503+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
504+ ProfileSummaryInfo *PSI = nullptr ,
505+ OptimizationRemarkEmitter *ORE = nullptr )
500506 : TTI(TTI), GetAssumptionCache(GetAssumptionCache), GetBFI(GetBFI),
501- PSI (PSI), F(Callee), DL(F.getDataLayout()), ORE(ORE),
507+ GetTLI (GetTLI), PSI(PSI), F(Callee), DL(F.getDataLayout()), ORE(ORE),
502508 CandidateCall(Call) {}
503509
504510 InlineResult analyze ();
@@ -687,7 +693,8 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
687693 // / FIXME: if InlineCostCallAnalyzer is derived from, this may need
688694 // / to instantiate the derived class.
689695 InlineCostCallAnalyzer CA (*F, Call, IndirectCallParams, TTI,
690- GetAssumptionCache, GetBFI, PSI, ORE, false );
696+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE,
697+ false );
691698 if (CA.analyze ().isSuccess ()) {
692699 // We were able to inline the indirect call! Subtract the cost from the
693700 // threshold to get the bonus we want to apply, but don't go below zero.
@@ -1105,10 +1112,12 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
11051112 const TargetTransformInfo &TTI,
11061113 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
11071114 function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr ,
1115+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
11081116 ProfileSummaryInfo *PSI = nullptr ,
11091117 OptimizationRemarkEmitter *ORE = nullptr , bool BoostIndirect = true ,
11101118 bool IgnoreThreshold = false )
1111- : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI, ORE),
1119+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI, PSI,
1120+ ORE),
11121121 ComputeFullInlineCost (OptComputeFullInlineCost ||
11131122 Params.ComputeFullInlineCost || ORE ||
11141123 isCostBenefitAnalysisEnabled ()),
@@ -1226,8 +1235,8 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
12261235 InlineConstants::IndirectCallThreshold;
12271236
12281237 InlineCostCallAnalyzer CA (*F, Call, IndirectCallParams, TTI,
1229- GetAssumptionCache, GetBFI, PSI, ORE, false ,
1230- true );
1238+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE ,
1239+ false , true );
12311240 if (CA.analyze ().isSuccess ()) {
12321241 increment (InlineCostFeatureIndex::nested_inline_cost_estimate,
12331242 CA.getCost ());
@@ -1353,9 +1362,11 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
13531362 const TargetTransformInfo &TTI,
13541363 function_ref<AssumptionCache &(Function &)> &GetAssumptionCache,
13551364 function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
1365+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
13561366 ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE, Function &Callee,
13571367 CallBase &Call)
1358- : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI) {}
1368+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI,
1369+ PSI) {}
13591370
13601371 const InlineCostFeatures &features () const { return Cost; }
13611372};
@@ -2258,6 +2269,44 @@ bool CallAnalyzer::simplifyCallSite(Function *F, CallBase &Call) {
22582269 return false ;
22592270}
22602271
2272+ bool CallAnalyzer::isLoweredToCall (Function *F, CallBase &Call) {
2273+ const TargetLibraryInfo *TLI = GetTLI ? &GetTLI (*F) : nullptr ;
2274+ LibFunc LF;
2275+ if (!TLI || !TLI->getLibFunc (*F, LF) || !TLI->has (LF))
2276+ return TTI.isLoweredToCall (F);
2277+
2278+ switch (LF) {
2279+ case LibFunc_memcpy_chk:
2280+ case LibFunc_memmove_chk:
2281+ case LibFunc_mempcpy_chk:
2282+ case LibFunc_memset_chk: {
2283+ // Calls to __memcpy_chk whose length is known to fit within the object
2284+ // size will eventually be replaced by inline stores. Therefore, these
2285+ // should not incur a call penalty. This is only really relevant on
2286+ // platforms whose headers redirect memcpy to __memcpy_chk (e.g. Darwin), as
2287+ // other platforms use memcpy intrinsics, which are already exempt from the
2288+ // call penalty.
2289+ auto *LenOp = dyn_cast<ConstantInt>(Call.getOperand (2 ));
2290+ if (!LenOp)
2291+ LenOp = dyn_cast_or_null<ConstantInt>(
2292+ SimplifiedValues.lookup (Call.getOperand (2 )));
2293+ auto *ObjSizeOp = dyn_cast<ConstantInt>(Call.getOperand (3 ));
2294+ if (!ObjSizeOp)
2295+ ObjSizeOp = dyn_cast_or_null<ConstantInt>(
2296+ SimplifiedValues.lookup (Call.getOperand (3 )));
2297+ if (LenOp && ObjSizeOp &&
2298+ LenOp->getLimitedValue () <= ObjSizeOp->getLimitedValue ()) {
2299+ return false ;
2300+ }
2301+ break ;
2302+ }
2303+ default :
2304+ break ;
2305+ }
2306+
2307+ return TTI.isLoweredToCall (F);
2308+ }
2309+
22612310bool CallAnalyzer::visitCallBase (CallBase &Call) {
22622311 if (!onCallBaseVisitStart (Call))
22632312 return true ;
@@ -2339,7 +2388,7 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) {
23392388 return false ;
23402389 }
23412390
2342- if (TTI. isLoweredToCall (F)) {
2391+ if (isLoweredToCall (F, Call )) {
23432392 onLoweredCall (F, Call, IsIndirectCall);
23442393 }
23452394
@@ -2943,6 +2992,7 @@ std::optional<int> llvm::getInliningCostEstimate(
29432992 CallBase &Call, TargetTransformInfo &CalleeTTI,
29442993 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
29452994 function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
2995+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
29462996 ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
29472997 const InlineParams Params = {/* DefaultThreshold*/ 0 ,
29482998 /* HintThreshold*/ {},
@@ -2956,7 +3006,7 @@ std::optional<int> llvm::getInliningCostEstimate(
29563006 /* EnableDeferral*/ true };
29573007
29583008 InlineCostCallAnalyzer CA (*Call.getCalledFunction (), Call, Params, CalleeTTI,
2959- GetAssumptionCache, GetBFI, PSI, ORE, true ,
3009+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE, true ,
29603010 /* IgnoreThreshold*/ true );
29613011 auto R = CA.analyze ();
29623012 if (!R.isSuccess ())
@@ -2968,9 +3018,10 @@ std::optional<InlineCostFeatures> llvm::getInliningCostFeatures(
29683018 CallBase &Call, TargetTransformInfo &CalleeTTI,
29693019 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
29703020 function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
3021+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
29713022 ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
2972- InlineCostFeaturesAnalyzer CFA (CalleeTTI, GetAssumptionCache, GetBFI, PSI ,
2973- ORE, *Call.getCalledFunction (), Call);
3023+ InlineCostFeaturesAnalyzer CFA (CalleeTTI, GetAssumptionCache, GetBFI, GetTLI ,
3024+ PSI, ORE, *Call.getCalledFunction (), Call);
29743025 auto R = CFA.analyze ();
29753026 if (!R.isSuccess ())
29763027 return std::nullopt ;
@@ -3070,7 +3121,7 @@ InlineCost llvm::getInlineCost(
30703121 << " )\n " );
30713122
30723123 InlineCostCallAnalyzer CA (*Callee, Call, Params, CalleeTTI,
3073- GetAssumptionCache, GetBFI, PSI, ORE);
3124+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE);
30743125 InlineResult ShouldInline = CA.analyze ();
30753126
30763127 LLVM_DEBUG (CA.dump ());
@@ -3262,7 +3313,8 @@ InlineCostAnnotationPrinterPass::run(Function &F,
32623313 continue ;
32633314 OptimizationRemarkEmitter ORE (CalledFunction);
32643315 InlineCostCallAnalyzer ICCA (*CalledFunction, *CI, Params, TTI,
3265- GetAssumptionCache, nullptr , &PSI, &ORE);
3316+ GetAssumptionCache, nullptr , nullptr , &PSI,
3317+ &ORE);
32663318 ICCA.analyze ();
32673319 OS << " Analyzing call of " << CalledFunction->getName ()
32683320 << " ... (caller:" << CI->getCaller ()->getName () << " )\n " ;
0 commit comments