@@ -249,6 +249,9 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
249
249
// / Getter for BlockFrequencyInfo
250
250
function_ref<BlockFrequencyInfo &(Function &)> GetBFI;
251
251
252
+ // / Getter for TargetLibraryInfo
253
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI;
254
+
252
255
// / Profile summary information.
253
256
ProfileSummaryInfo *PSI;
254
257
@@ -433,6 +436,7 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
433
436
bool simplifyIntrinsicCallIsConstant (CallBase &CB);
434
437
bool simplifyIntrinsicCallObjectSize (CallBase &CB);
435
438
ConstantInt *stripAndComputeInBoundsConstantOffsets (Value *&V);
439
+ bool isLoweredToCall (Function *F, CallBase &Call);
436
440
437
441
// / Return true if the given argument to the function being considered for
438
442
// / inlining has the given attribute set either at the call site or the
@@ -492,13 +496,15 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
492
496
bool visitUnreachableInst (UnreachableInst &I);
493
497
494
498
public:
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 )
500
506
: 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),
502
508
CandidateCall(Call) {}
503
509
504
510
InlineResult analyze ();
@@ -688,7 +694,8 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
688
694
// / FIXME: if InlineCostCallAnalyzer is derived from, this may need
689
695
// / to instantiate the derived class.
690
696
InlineCostCallAnalyzer CA (*F, Call, IndirectCallParams, TTI,
691
- GetAssumptionCache, GetBFI, PSI, ORE, false );
697
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE,
698
+ false );
692
699
if (CA.analyze ().isSuccess ()) {
693
700
// We were able to inline the indirect call! Subtract the cost from the
694
701
// threshold to get the bonus we want to apply, but don't go below zero.
@@ -1106,10 +1113,12 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
1106
1113
const TargetTransformInfo &TTI,
1107
1114
function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
1108
1115
function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr ,
1116
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
1109
1117
ProfileSummaryInfo *PSI = nullptr ,
1110
1118
OptimizationRemarkEmitter *ORE = nullptr , bool BoostIndirect = true ,
1111
1119
bool IgnoreThreshold = false )
1112
- : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI, ORE),
1120
+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI, PSI,
1121
+ ORE),
1113
1122
ComputeFullInlineCost (OptComputeFullInlineCost ||
1114
1123
Params.ComputeFullInlineCost || ORE ||
1115
1124
isCostBenefitAnalysisEnabled ()),
@@ -1228,8 +1237,8 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
1228
1237
InlineConstants::IndirectCallThreshold;
1229
1238
1230
1239
InlineCostCallAnalyzer CA (*F, Call, IndirectCallParams, TTI,
1231
- GetAssumptionCache, GetBFI, PSI, ORE, false ,
1232
- true );
1240
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE ,
1241
+ false , true );
1233
1242
if (CA.analyze ().isSuccess ()) {
1234
1243
increment (InlineCostFeatureIndex::nested_inline_cost_estimate,
1235
1244
CA.getCost ());
@@ -1355,9 +1364,11 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
1355
1364
const TargetTransformInfo &TTI,
1356
1365
function_ref<AssumptionCache &(Function &)> &GetAssumptionCache,
1357
1366
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
1367
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
1358
1368
ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE, Function &Callee,
1359
1369
CallBase &Call)
1360
- : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI) {}
1370
+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI,
1371
+ PSI) {}
1361
1372
1362
1373
const InlineCostFeatures &features () const { return Cost; }
1363
1374
};
@@ -2260,6 +2271,44 @@ bool CallAnalyzer::simplifyCallSite(Function *F, CallBase &Call) {
2260
2271
return false ;
2261
2272
}
2262
2273
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
+
2263
2312
bool CallAnalyzer::visitCallBase (CallBase &Call) {
2264
2313
if (!onCallBaseVisitStart (Call))
2265
2314
return true ;
@@ -2341,7 +2390,7 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) {
2341
2390
return false ;
2342
2391
}
2343
2392
2344
- if (TTI. isLoweredToCall (F)) {
2393
+ if (isLoweredToCall (F, Call )) {
2345
2394
onLoweredCall (F, Call, IsIndirectCall);
2346
2395
}
2347
2396
@@ -2945,6 +2994,7 @@ std::optional<int> llvm::getInliningCostEstimate(
2945
2994
CallBase &Call, TargetTransformInfo &CalleeTTI,
2946
2995
function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
2947
2996
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
2997
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
2948
2998
ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
2949
2999
const InlineParams Params = {/* DefaultThreshold*/ 0 ,
2950
3000
/* HintThreshold*/ {},
@@ -2958,7 +3008,7 @@ std::optional<int> llvm::getInliningCostEstimate(
2958
3008
/* EnableDeferral*/ true };
2959
3009
2960
3010
InlineCostCallAnalyzer CA (*Call.getCalledFunction (), Call, Params, CalleeTTI,
2961
- GetAssumptionCache, GetBFI, PSI, ORE, true ,
3011
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE, true ,
2962
3012
/* IgnoreThreshold*/ true );
2963
3013
auto R = CA.analyze ();
2964
3014
if (!R.isSuccess ())
@@ -2970,9 +3020,10 @@ std::optional<InlineCostFeatures> llvm::getInliningCostFeatures(
2970
3020
CallBase &Call, TargetTransformInfo &CalleeTTI,
2971
3021
function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
2972
3022
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
3023
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
2973
3024
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);
2976
3027
auto R = CFA.analyze ();
2977
3028
if (!R.isSuccess ())
2978
3029
return std::nullopt;
@@ -3072,7 +3123,7 @@ InlineCost llvm::getInlineCost(
3072
3123
<< " )\n " );
3073
3124
3074
3125
InlineCostCallAnalyzer CA (*Callee, Call, Params, CalleeTTI,
3075
- GetAssumptionCache, GetBFI, PSI, ORE);
3126
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE);
3076
3127
InlineResult ShouldInline = CA.analyze ();
3077
3128
3078
3129
LLVM_DEBUG (CA.dump ());
@@ -3263,7 +3314,8 @@ InlineCostAnnotationPrinterPass::run(Function &F,
3263
3314
continue ;
3264
3315
OptimizationRemarkEmitter ORE (CalledFunction);
3265
3316
InlineCostCallAnalyzer ICCA (*CalledFunction, *CB, Params, TTI,
3266
- GetAssumptionCache, nullptr , &PSI, &ORE);
3317
+ GetAssumptionCache, nullptr , nullptr , &PSI,
3318
+ &ORE);
3267
3319
ICCA.analyze ();
3268
3320
OS << " Analyzing call of " << CalledFunction->getName ()
3269
3321
<< " ... (caller:" << CB->getCaller ()->getName () << " )\n " ;
0 commit comments