Skip to content

Commit 61ae6ef

Browse files
committed
InlineFunction: Split inlining into predicate and apply functions
This is to support a new inline function reduction in llvm-reduce, which should pre-filter callsites that are not eligible for inlining. This code was mostly structured as a match and apply, with a few exceptions. The ugliest piece is for propagating and verifying compatible getGC and personalities. Also collection of EHPad and the convergence token to use are now cached in InlineFunctionInfo. I was initially confused by the split between the checks performed here and isInlineViable, so better document how this system is supposed to work. It turns out this split does make sense, in that isInlineViable checks if it's possible based on the callee content and the ultimate inline depended on the callsite context. I think more renames of these functions would help, and isInlineViable should probably move out of InlineCost to be with these transfoms.
1 parent a54736a commit 61ae6ef

File tree

3 files changed

+114
-43
lines changed

3 files changed

+114
-43
lines changed

llvm/include/llvm/Analysis/InlineCost.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,11 @@ std::optional<InlineCostFeatures> getInliningCostFeatures(
334334
ProfileSummaryInfo *PSI = nullptr,
335335
OptimizationRemarkEmitter *ORE = nullptr);
336336

337-
/// Minimal filter to detect invalid constructs for inlining.
337+
/// Check if it is mechanically possible to inline the function \p Callee, based
338+
/// on the contents of the function.
339+
///
340+
/// See also \p CanInlineCallSite as an additional precondition necessary to
341+
/// perform a valid inline in a particular use context.
338342
InlineResult isInlineViable(Function &Callee);
339343

340344
// This pass is used to annotate instructions during the inline process for

llvm/include/llvm/Transforms/Utils/Cloning.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ class InlineFunctionInfo {
263263
/// `InlinedCalls` above is used.
264264
SmallVector<CallBase *, 8> InlinedCallSites;
265265

266+
Value *ConvergenceControlToken = nullptr;
267+
Instruction *CallSiteEHPad = nullptr;
268+
266269
/// Update profile for callee as well as cloned version. We need to do this
267270
/// for regular inlining, but not for inlining from sample profile loader.
268271
bool UpdateProfile;
@@ -271,9 +274,34 @@ class InlineFunctionInfo {
271274
StaticAllocas.clear();
272275
InlinedCalls.clear();
273276
InlinedCallSites.clear();
277+
ConvergenceControlToken = nullptr;
278+
CallSiteEHPad = nullptr;
274279
}
275280
};
276281

282+
/// Check if it is legal to perform inlining of the function called by \p CB
283+
/// into the caller at this particular use, and sets fields in \p IFI.
284+
///
285+
/// This does not consider whether it is possible for the function callee itself
286+
/// to be inlined; for that see isInlineViable.
287+
InlineResult CanInlineCallSite(const CallBase &CB, InlineFunctionInfo &IFI);
288+
289+
/// This should generally not be used, use InlineFunction instead.
290+
///
291+
/// Perform mechanical inlining of \p CB into the caller.
292+
///
293+
/// This does not perform any legality or profitability checks for the
294+
/// inlining. This assumes that CanInlineCallSite was already called, populated
295+
/// \p IFI, and returned InlineResult::success.
296+
///
297+
/// Also assumes that isInlineViable returned InlineResult::success for the
298+
/// called function.
299+
void InlineFunctionImpl(CallBase &CB, InlineFunctionInfo &IFI,
300+
bool MergeAttributes = false,
301+
AAResults *CalleeAAR = nullptr,
302+
bool InsertLifetime = true,
303+
Function *ForwardVarArgsTo = nullptr);
304+
277305
/// This function inlines the called function into the basic
278306
/// block of the caller. This returns false if it is not possible to inline
279307
/// this call. The program is still in a well defined state if this occurs

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 81 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2446,19 +2446,8 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24462446
return Ret;
24472447
}
24482448

2449-
/// This function inlines the called function into the basic block of the
2450-
/// caller. This returns false if it is not possible to inline this call.
2451-
/// The program is still in a well defined state if this occurs though.
2452-
///
2453-
/// Note that this only does one level of inlining. For example, if the
2454-
/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
2455-
/// exists in the instruction stream. Similarly this will inline a recursive
2456-
/// function by one level.
2457-
llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
2458-
bool MergeAttributes,
2459-
AAResults *CalleeAAR,
2460-
bool InsertLifetime,
2461-
Function *ForwardVarArgsTo) {
2449+
llvm::InlineResult llvm::CanInlineCallSite(const CallBase &CB,
2450+
InlineFunctionInfo &IFI) {
24622451
assert(CB.getParent() && CB.getFunction() && "Instruction not in function!");
24632452

24642453
// FIXME: we don't inline callbr yet.
@@ -2475,7 +2464,6 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24752464

24762465
// The inliner does not know how to inline through calls with operand bundles
24772466
// in general ...
2478-
Value *ConvergenceControlToken = nullptr;
24792467
if (CB.hasOperandBundles()) {
24802468
for (int i = 0, e = CB.getNumOperandBundles(); i != e; ++i) {
24812469
auto OBUse = CB.getOperandBundleAt(i);
@@ -2491,7 +2479,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24912479
if (Tag == LLVMContext::OB_kcfi)
24922480
continue;
24932481
if (Tag == LLVMContext::OB_convergencectrl) {
2494-
ConvergenceControlToken = OBUse.Inputs[0].get();
2482+
IFI.ConvergenceControlToken = OBUse.Inputs[0].get();
24952483
continue;
24962484
}
24972485

@@ -2509,28 +2497,22 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
25092497
// fully implements convergence control tokens, there is no mixing of
25102498
// controlled and uncontrolled convergent operations in the whole program.
25112499
if (CB.isConvergent()) {
2512-
if (!ConvergenceControlToken &&
2500+
if (!IFI.ConvergenceControlToken &&
25132501
getConvergenceEntry(CalledFunc->getEntryBlock())) {
25142502
return InlineResult::failure(
25152503
"convergent call needs convergencectrl operand");
25162504
}
25172505
}
25182506

2519-
// If the call to the callee cannot throw, set the 'nounwind' flag on any
2520-
// calls that we inline.
2521-
bool MarkNoUnwind = CB.doesNotThrow();
2522-
2523-
BasicBlock *OrigBB = CB.getParent();
2524-
Function *Caller = OrigBB->getParent();
2507+
const BasicBlock *OrigBB = CB.getParent();
2508+
const Function *Caller = OrigBB->getParent();
25252509

25262510
// GC poses two hazards to inlining, which only occur when the callee has GC:
25272511
// 1. If the caller has no GC, then the callee's GC must be propagated to the
25282512
// caller.
25292513
// 2. If the caller has a differing GC, it is invalid to inline.
25302514
if (CalledFunc->hasGC()) {
2531-
if (!Caller->hasGC())
2532-
Caller->setGC(CalledFunc->getGC());
2533-
else if (CalledFunc->getGC() != Caller->getGC())
2515+
if (Caller->hasGC() && CalledFunc->getGC() != Caller->getGC())
25342516
return InlineResult::failure("incompatible GC");
25352517
}
25362518

@@ -2548,34 +2530,31 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
25482530
? Caller->getPersonalityFn()->stripPointerCasts()
25492531
: nullptr;
25502532
if (CalledPersonality) {
2551-
if (!CallerPersonality)
2552-
Caller->setPersonalityFn(CalledPersonality);
25532533
// If the personality functions match, then we can perform the
25542534
// inlining. Otherwise, we can't inline.
25552535
// TODO: This isn't 100% true. Some personality functions are proper
25562536
// supersets of others and can be used in place of the other.
2557-
else if (CalledPersonality != CallerPersonality)
2537+
if (CallerPersonality && CalledPersonality != CallerPersonality)
25582538
return InlineResult::failure("incompatible personality");
25592539
}
25602540

25612541
// We need to figure out which funclet the callsite was in so that we may
25622542
// properly nest the callee.
2563-
Instruction *CallSiteEHPad = nullptr;
25642543
if (CallerPersonality) {
25652544
EHPersonality Personality = classifyEHPersonality(CallerPersonality);
25662545
if (isScopedEHPersonality(Personality)) {
25672546
std::optional<OperandBundleUse> ParentFunclet =
25682547
CB.getOperandBundle(LLVMContext::OB_funclet);
25692548
if (ParentFunclet)
2570-
CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());
2549+
IFI.CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());
25712550

25722551
// OK, the inlining site is legal. What about the target function?
25732552

2574-
if (CallSiteEHPad) {
2553+
if (IFI.CallSiteEHPad) {
25752554
if (Personality == EHPersonality::MSVC_CXX) {
25762555
// The MSVC personality cannot tolerate catches getting inlined into
25772556
// cleanup funclets.
2578-
if (isa<CleanupPadInst>(CallSiteEHPad)) {
2557+
if (isa<CleanupPadInst>(IFI.CallSiteEHPad)) {
25792558
// Ok, the call site is within a cleanuppad. Let's check the callee
25802559
// for catchpads.
25812560
for (const BasicBlock &CalledBB : *CalledFunc) {
@@ -2595,13 +2574,33 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
25952574
}
25962575
}
25972576

2577+
return InlineResult::success();
2578+
}
2579+
2580+
/// This function inlines the called function into the basic block of the
2581+
/// caller. This returns false if it is not possible to inline this call.
2582+
/// The program is still in a well defined state if this occurs though.
2583+
///
2584+
/// Note that this only does one level of inlining. For example, if the
2585+
/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
2586+
/// exists in the instruction stream. Similarly this will inline a recursive
2587+
/// function by one level.
2588+
void llvm::InlineFunctionImpl(CallBase &CB, InlineFunctionInfo &IFI,
2589+
bool MergeAttributes, AAResults *CalleeAAR,
2590+
bool InsertLifetime, Function *ForwardVarArgsTo) {
2591+
BasicBlock *OrigBB = CB.getParent();
2592+
Function *Caller = OrigBB->getParent();
2593+
Function *CalledFunc = CB.getCalledFunction();
2594+
assert(CalledFunc && !CalledFunc->isDeclaration() &&
2595+
"CanInlineCallSite should have verified direct call to definition");
2596+
25982597
// Determine if we are dealing with a call in an EHPad which does not unwind
25992598
// to caller.
26002599
bool EHPadForCallUnwindsLocally = false;
2601-
if (CallSiteEHPad && isa<CallInst>(CB)) {
2600+
if (IFI.CallSiteEHPad && isa<CallInst>(CB)) {
26022601
UnwindDestMemoTy FuncletUnwindMap;
26032602
Value *CallSiteUnwindDestToken =
2604-
getUnwindDestToken(CallSiteEHPad, FuncletUnwindMap);
2603+
getUnwindDestToken(IFI.CallSiteEHPad, FuncletUnwindMap);
26052604

26062605
EHPadForCallUnwindsLocally =
26072606
CallSiteUnwindDestToken &&
@@ -2618,6 +2617,30 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
26182617
ClonedCodeInfo InlinedFunctionInfo;
26192618
Function::iterator FirstNewBlock;
26202619

2620+
// GC poses two hazards to inlining, which only occur when the callee has GC:
2621+
// 1. If the caller has no GC, then the callee's GC must be propagated to the
2622+
// caller.
2623+
// 2. If the caller has a differing GC, it is invalid to inline.
2624+
if (CalledFunc->hasGC()) {
2625+
if (!Caller->hasGC())
2626+
Caller->setGC(CalledFunc->getGC());
2627+
else {
2628+
assert(CalledFunc->getGC() == Caller->getGC() &&
2629+
"CanInlineCallSite should have verified compatible GCs");
2630+
}
2631+
}
2632+
2633+
if (CalledFunc->hasPersonalityFn()) {
2634+
Constant *CalledPersonality =
2635+
CalledFunc->getPersonalityFn()->stripPointerCasts();
2636+
if (!Caller->hasPersonalityFn()) {
2637+
Caller->setPersonalityFn(CalledPersonality);
2638+
} else
2639+
assert(Caller->getPersonalityFn()->stripPointerCasts() ==
2640+
CalledPersonality &&
2641+
"CanInlineCallSite should have verified compatible personality");
2642+
}
2643+
26212644
{ // Scope to destroy VMap after cloning.
26222645
ValueToValueMapTy VMap;
26232646
struct ByValInit {
@@ -2802,10 +2825,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
28022825
IFI.GetAssumptionCache(*Caller).registerAssumption(II);
28032826
}
28042827

2805-
if (ConvergenceControlToken) {
2828+
if (IFI.ConvergenceControlToken) {
28062829
IntrinsicInst *IntrinsicCall = getConvergenceEntry(*FirstNewBlock);
28072830
if (IntrinsicCall) {
2808-
IntrinsicCall->replaceAllUsesWith(ConvergenceControlToken);
2831+
IntrinsicCall->replaceAllUsesWith(IFI.ConvergenceControlToken);
28092832
IntrinsicCall->eraseFromParent();
28102833
}
28112834
}
@@ -2852,6 +2875,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
28522875
}
28532876
}
28542877

2878+
// If the call to the callee cannot throw, set the 'nounwind' flag on any
2879+
// calls that we inline.
2880+
bool MarkNoUnwind = CB.doesNotThrow();
2881+
28552882
SmallVector<Value*,4> VarArgsToForward;
28562883
SmallVector<AttributeSet, 4> VarArgsAttrs;
28572884
for (unsigned i = CalledFunc->getFunctionType()->getNumParams();
@@ -3038,12 +3065,12 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
30383065
// Update the lexical scopes of the new funclets and callsites.
30393066
// Anything that had 'none' as its parent is now nested inside the callsite's
30403067
// EHPad.
3041-
if (CallSiteEHPad) {
3068+
if (IFI.CallSiteEHPad) {
30423069
for (Function::iterator BB = FirstNewBlock->getIterator(),
30433070
E = Caller->end();
30443071
BB != E; ++BB) {
30453072
// Add bundle operands to inlined call sites.
3046-
PropagateOperandBundles(BB, CallSiteEHPad);
3073+
PropagateOperandBundles(BB, IFI.CallSiteEHPad);
30473074

30483075
// It is problematic if the inlinee has a cleanupret which unwinds to
30493076
// caller and we inline it into a call site which doesn't unwind but into
@@ -3059,11 +3086,11 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
30593086

30603087
if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
30613088
if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
3062-
CatchSwitch->setParentPad(CallSiteEHPad);
3089+
CatchSwitch->setParentPad(IFI.CallSiteEHPad);
30633090
} else {
30643091
auto *FPI = cast<FuncletPadInst>(I);
30653092
if (isa<ConstantTokenNone>(FPI->getParentPad()))
3066-
FPI->setParentPad(CallSiteEHPad);
3093+
FPI->setParentPad(IFI.CallSiteEHPad);
30673094
}
30683095
}
30693096
}
@@ -3219,7 +3246,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
32193246
AttributeFuncs::mergeAttributesForInlining(*Caller, *CalledFunc);
32203247

32213248
// We are now done with the inlining.
3222-
return InlineResult::success();
3249+
return;
32233250
}
32243251

32253252
// Otherwise, we have the normal case, of more than one block to inline or
@@ -3379,6 +3406,18 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
33793406

33803407
if (MergeAttributes)
33813408
AttributeFuncs::mergeAttributesForInlining(*Caller, *CalledFunc);
3409+
}
33823410

3383-
return InlineResult::success();
3411+
llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
3412+
bool MergeAttributes,
3413+
AAResults *CalleeAAR,
3414+
bool InsertLifetime,
3415+
Function *ForwardVarArgsTo) {
3416+
llvm::InlineResult Result = CanInlineCallSite(CB, IFI);
3417+
if (Result.isSuccess()) {
3418+
InlineFunctionImpl(CB, IFI, MergeAttributes, CalleeAAR, InsertLifetime,
3419+
ForwardVarArgsTo);
3420+
}
3421+
3422+
return Result;
33843423
}

0 commit comments

Comments
 (0)