@@ -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 ();
@@ -688,7 +694,8 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
688694 // / FIXME: if InlineCostCallAnalyzer is derived from, this may need
689695 // / to instantiate the derived class.
690696 InlineCostCallAnalyzer CA (*F, Call, IndirectCallParams, TTI,
691- GetAssumptionCache, GetBFI, PSI, ORE, false );
697+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE,
698+ false );
692699 if (CA.analyze ().isSuccess ()) {
693700 // We were able to inline the indirect call! Subtract the cost from the
694701 // threshold to get the bonus we want to apply, but don't go below zero.
@@ -1106,10 +1113,12 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
11061113 const TargetTransformInfo &TTI,
11071114 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
11081115 function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr ,
1116+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
11091117 ProfileSummaryInfo *PSI = nullptr ,
11101118 OptimizationRemarkEmitter *ORE = nullptr , bool BoostIndirect = true ,
11111119 bool IgnoreThreshold = false )
1112- : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI, ORE),
1120+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI, PSI,
1121+ ORE),
11131122 ComputeFullInlineCost (OptComputeFullInlineCost ||
11141123 Params.ComputeFullInlineCost || ORE ||
11151124 isCostBenefitAnalysisEnabled ()),
@@ -1228,8 +1237,8 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
12281237 InlineConstants::IndirectCallThreshold;
12291238
12301239 InlineCostCallAnalyzer CA (*F, Call, IndirectCallParams, TTI,
1231- GetAssumptionCache, GetBFI, PSI, ORE, false ,
1232- true );
1240+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE ,
1241+ false , true );
12331242 if (CA.analyze ().isSuccess ()) {
12341243 increment (InlineCostFeatureIndex::nested_inline_cost_estimate,
12351244 CA.getCost ());
@@ -1355,9 +1364,11 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
13551364 const TargetTransformInfo &TTI,
13561365 function_ref<AssumptionCache &(Function &)> &GetAssumptionCache,
13571366 function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
1367+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
13581368 ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE, Function &Callee,
13591369 CallBase &Call)
1360- : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI) {}
1370+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI,
1371+ PSI) {}
13611372
13621373 const InlineCostFeatures &features () const { return Cost; }
13631374};
@@ -2260,6 +2271,44 @@ bool CallAnalyzer::simplifyCallSite(Function *F, CallBase &Call) {
22602271 return false ;
22612272}
22622273
2274+ bool CallAnalyzer::isLoweredToCall (Function *F, CallBase &Call) {
2275+ const TargetLibraryInfo *TLI = GetTLI ? &GetTLI (*F) : nullptr ;
2276+ LibFunc LF;
2277+ if (!TLI || !TLI->getLibFunc (*F, LF) || !TLI->has (LF))
2278+ return TTI.isLoweredToCall (F);
2279+
2280+ switch (LF) {
2281+ case LibFunc_memcpy_chk:
2282+ case LibFunc_memmove_chk:
2283+ case LibFunc_mempcpy_chk:
2284+ case LibFunc_memset_chk: {
2285+ // Calls to __memcpy_chk whose length is known to fit within the object
2286+ // size will eventually be replaced by inline stores. Therefore, these
2287+ // should not incur a call penalty. This is only really relevant on
2288+ // platforms whose headers redirect memcpy to __memcpy_chk (e.g. Darwin), as
2289+ // other platforms use memcpy intrinsics, which are already exempt from the
2290+ // call penalty.
2291+ auto *LenOp = dyn_cast<ConstantInt>(Call.getOperand (2 ));
2292+ if (!LenOp)
2293+ LenOp = dyn_cast_or_null<ConstantInt>(
2294+ SimplifiedValues.lookup (Call.getOperand (2 )));
2295+ auto *ObjSizeOp = dyn_cast<ConstantInt>(Call.getOperand (3 ));
2296+ if (!ObjSizeOp)
2297+ ObjSizeOp = dyn_cast_or_null<ConstantInt>(
2298+ SimplifiedValues.lookup (Call.getOperand (3 )));
2299+ if (LenOp && ObjSizeOp &&
2300+ LenOp->getLimitedValue () <= ObjSizeOp->getLimitedValue ()) {
2301+ return false ;
2302+ }
2303+ break ;
2304+ }
2305+ default :
2306+ break ;
2307+ }
2308+
2309+ return TTI.isLoweredToCall (F);
2310+ }
2311+
22632312bool CallAnalyzer::visitCallBase (CallBase &Call) {
22642313 if (!onCallBaseVisitStart (Call))
22652314 return true ;
@@ -2341,7 +2390,7 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) {
23412390 return false ;
23422391 }
23432392
2344- if (TTI. isLoweredToCall (F)) {
2393+ if (isLoweredToCall (F, Call )) {
23452394 onLoweredCall (F, Call, IsIndirectCall);
23462395 }
23472396
@@ -2945,6 +2994,7 @@ std::optional<int> llvm::getInliningCostEstimate(
29452994 CallBase &Call, TargetTransformInfo &CalleeTTI,
29462995 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
29472996 function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
2997+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
29482998 ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
29492999 const InlineParams Params = {/* DefaultThreshold*/ 0 ,
29503000 /* HintThreshold*/ {},
@@ -2958,7 +3008,7 @@ std::optional<int> llvm::getInliningCostEstimate(
29583008 /* EnableDeferral*/ true };
29593009
29603010 InlineCostCallAnalyzer CA (*Call.getCalledFunction (), Call, Params, CalleeTTI,
2961- GetAssumptionCache, GetBFI, PSI, ORE, true ,
3011+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE, true ,
29623012 /* IgnoreThreshold*/ true );
29633013 auto R = CA.analyze ();
29643014 if (!R.isSuccess ())
@@ -2970,9 +3020,10 @@ std::optional<InlineCostFeatures> llvm::getInliningCostFeatures(
29703020 CallBase &Call, TargetTransformInfo &CalleeTTI,
29713021 function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
29723022 function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
3023+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
29733024 ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
2974- InlineCostFeaturesAnalyzer CFA (CalleeTTI, GetAssumptionCache, GetBFI, PSI ,
2975- ORE, *Call.getCalledFunction (), Call);
3025+ InlineCostFeaturesAnalyzer CFA (CalleeTTI, GetAssumptionCache, GetBFI, GetTLI ,
3026+ PSI, ORE, *Call.getCalledFunction (), Call);
29763027 auto R = CFA.analyze ();
29773028 if (!R.isSuccess ())
29783029 return std::nullopt ;
@@ -3072,7 +3123,7 @@ InlineCost llvm::getInlineCost(
30723123 << " )\n " );
30733124
30743125 InlineCostCallAnalyzer CA (*Callee, Call, Params, CalleeTTI,
3075- GetAssumptionCache, GetBFI, PSI, ORE);
3126+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE);
30763127 InlineResult ShouldInline = CA.analyze ();
30773128
30783129 LLVM_DEBUG (CA.dump ());
@@ -3263,7 +3314,8 @@ InlineCostAnnotationPrinterPass::run(Function &F,
32633314 continue ;
32643315 OptimizationRemarkEmitter ORE (CalledFunction);
32653316 InlineCostCallAnalyzer ICCA (*CalledFunction, *CB, Params, TTI,
3266- GetAssumptionCache, nullptr , &PSI, &ORE);
3317+ GetAssumptionCache, nullptr , nullptr , &PSI,
3318+ &ORE);
32673319 ICCA.analyze ();
32683320 OS << " Analyzing call of " << CalledFunction->getName ()
32693321 << " ... (caller:" << CB->getCaller ()->getName () << " )\n " ;
0 commit comments