@@ -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 ();
@@ -687,7 +693,8 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
687
693
// / FIXME: if InlineCostCallAnalyzer is derived from, this may need
688
694
// / to instantiate the derived class.
689
695
InlineCostCallAnalyzer CA (*F, Call, IndirectCallParams, TTI,
690
- GetAssumptionCache, GetBFI, PSI, ORE, false );
696
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE,
697
+ false );
691
698
if (CA.analyze ().isSuccess ()) {
692
699
// We were able to inline the indirect call! Subtract the cost from the
693
700
// threshold to get the bonus we want to apply, but don't go below zero.
@@ -1105,10 +1112,12 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
1105
1112
const TargetTransformInfo &TTI,
1106
1113
function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
1107
1114
function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr ,
1115
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr ,
1108
1116
ProfileSummaryInfo *PSI = nullptr ,
1109
1117
OptimizationRemarkEmitter *ORE = nullptr , bool BoostIndirect = true ,
1110
1118
bool IgnoreThreshold = false )
1111
- : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI, ORE),
1119
+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI, PSI,
1120
+ ORE),
1112
1121
ComputeFullInlineCost (OptComputeFullInlineCost ||
1113
1122
Params.ComputeFullInlineCost || ORE ||
1114
1123
isCostBenefitAnalysisEnabled ()),
@@ -1226,8 +1235,8 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
1226
1235
InlineConstants::IndirectCallThreshold;
1227
1236
1228
1237
InlineCostCallAnalyzer CA (*F, Call, IndirectCallParams, TTI,
1229
- GetAssumptionCache, GetBFI, PSI, ORE, false ,
1230
- true );
1238
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE ,
1239
+ false , true );
1231
1240
if (CA.analyze ().isSuccess ()) {
1232
1241
increment (InlineCostFeatureIndex::nested_inline_cost_estimate,
1233
1242
CA.getCost ());
@@ -1353,9 +1362,11 @@ class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
1353
1362
const TargetTransformInfo &TTI,
1354
1363
function_ref<AssumptionCache &(Function &)> &GetAssumptionCache,
1355
1364
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
1365
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
1356
1366
ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE, Function &Callee,
1357
1367
CallBase &Call)
1358
- : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, PSI) {}
1368
+ : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI,
1369
+ PSI) {}
1359
1370
1360
1371
const InlineCostFeatures &features () const { return Cost; }
1361
1372
};
@@ -2258,6 +2269,44 @@ bool CallAnalyzer::simplifyCallSite(Function *F, CallBase &Call) {
2258
2269
return false ;
2259
2270
}
2260
2271
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
+
2261
2310
bool CallAnalyzer::visitCallBase (CallBase &Call) {
2262
2311
if (!onCallBaseVisitStart (Call))
2263
2312
return true ;
@@ -2339,7 +2388,7 @@ bool CallAnalyzer::visitCallBase(CallBase &Call) {
2339
2388
return false ;
2340
2389
}
2341
2390
2342
- if (TTI. isLoweredToCall (F)) {
2391
+ if (isLoweredToCall (F, Call )) {
2343
2392
onLoweredCall (F, Call, IsIndirectCall);
2344
2393
}
2345
2394
@@ -2943,6 +2992,7 @@ std::optional<int> llvm::getInliningCostEstimate(
2943
2992
CallBase &Call, TargetTransformInfo &CalleeTTI,
2944
2993
function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
2945
2994
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
2995
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
2946
2996
ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
2947
2997
const InlineParams Params = {/* DefaultThreshold*/ 0 ,
2948
2998
/* HintThreshold*/ {},
@@ -2956,7 +3006,7 @@ std::optional<int> llvm::getInliningCostEstimate(
2956
3006
/* EnableDeferral*/ true };
2957
3007
2958
3008
InlineCostCallAnalyzer CA (*Call.getCalledFunction (), Call, Params, CalleeTTI,
2959
- GetAssumptionCache, GetBFI, PSI, ORE, true ,
3009
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE, true ,
2960
3010
/* IgnoreThreshold*/ true );
2961
3011
auto R = CA.analyze ();
2962
3012
if (!R.isSuccess ())
@@ -2968,9 +3018,10 @@ std::optional<InlineCostFeatures> llvm::getInliningCostFeatures(
2968
3018
CallBase &Call, TargetTransformInfo &CalleeTTI,
2969
3019
function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
2970
3020
function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
3021
+ function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
2971
3022
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);
2974
3025
auto R = CFA.analyze ();
2975
3026
if (!R.isSuccess ())
2976
3027
return std::nullopt;
@@ -3070,7 +3121,7 @@ InlineCost llvm::getInlineCost(
3070
3121
<< " )\n " );
3071
3122
3072
3123
InlineCostCallAnalyzer CA (*Callee, Call, Params, CalleeTTI,
3073
- GetAssumptionCache, GetBFI, PSI, ORE);
3124
+ GetAssumptionCache, GetBFI, GetTLI, PSI, ORE);
3074
3125
InlineResult ShouldInline = CA.analyze ();
3075
3126
3076
3127
LLVM_DEBUG (CA.dump ());
@@ -3262,7 +3313,8 @@ InlineCostAnnotationPrinterPass::run(Function &F,
3262
3313
continue ;
3263
3314
OptimizationRemarkEmitter ORE (CalledFunction);
3264
3315
InlineCostCallAnalyzer ICCA (*CalledFunction, *CI, Params, TTI,
3265
- GetAssumptionCache, nullptr , &PSI, &ORE);
3316
+ GetAssumptionCache, nullptr , nullptr , &PSI,
3317
+ &ORE);
3266
3318
ICCA.analyze ();
3267
3319
OS << " Analyzing call of " << CalledFunction->getName ()
3268
3320
<< " ... (caller:" << CI->getCaller ()->getName () << " )\n " ;
0 commit comments