Skip to content

Commit ea4c6a7

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 d3a9cde commit ea4c6a7

File tree

3 files changed

+126
-53
lines changed

3 files changed

+126
-53
lines changed

llvm/include/llvm/Analysis/InlineCost.h

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

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

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

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

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,9 @@ class InlineFunctionInfo {
279279
/// `InlinedCalls` above is used.
280280
SmallVector<CallBase *, 8> InlinedCallSites;
281281

282+
Value *ConvergenceControlToken = nullptr;
283+
Instruction *CallSiteEHPad = nullptr;
284+
282285
/// Update profile for callee as well as cloned version. We need to do this
283286
/// for regular inlining, but not for inlining from sample profile loader.
284287
bool UpdateProfile;
@@ -287,9 +290,36 @@ class InlineFunctionInfo {
287290
StaticAllocas.clear();
288291
InlinedCalls.clear();
289292
InlinedCallSites.clear();
293+
ConvergenceControlToken = nullptr;
294+
CallSiteEHPad = nullptr;
290295
}
291296
};
292297

298+
/// Check if it is legal to perform inlining of the function called by \p CB
299+
/// into the caller at this particular use, and sets fields in \p IFI.
300+
///
301+
/// This does not consider whether it is possible for the function callee itself
302+
/// to be inlined; for that see isInlineViable.
303+
LLVM_ABI InlineResult CanInlineCallSite(const CallBase &CB,
304+
InlineFunctionInfo &IFI);
305+
306+
/// This should generally not be used, use InlineFunction instead.
307+
///
308+
/// Perform mechanical inlining of \p CB into the caller.
309+
///
310+
/// This does not perform any legality or profitability checks for the
311+
/// inlining. This assumes that CanInlineCallSite was already called, populated
312+
/// \p IFI, and returned InlineResult::success.
313+
///
314+
/// Also assumes that isInlineViable returned InlineResult::success for the
315+
/// called function.
316+
LLVM_ABI void InlineFunctionImpl(CallBase &CB, InlineFunctionInfo &IFI,
317+
bool MergeAttributes = false,
318+
AAResults *CalleeAAR = nullptr,
319+
bool InsertLifetime = true,
320+
Function *ForwardVarArgsTo = nullptr,
321+
OptimizationRemarkEmitter *ORE = nullptr);
322+
293323
/// This function inlines the called function into the basic
294324
/// block of the caller. This returns false if it is not possible to inline
295325
/// this call. The program is still in a well defined state if this occurs
@@ -328,7 +358,8 @@ LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
328358
bool MergeAttributes = false,
329359
AAResults *CalleeAAR = nullptr,
330360
bool InsertLifetime = true,
331-
Function *ForwardVarArgsTo = nullptr);
361+
Function *ForwardVarArgsTo = nullptr,
362+
OptimizationRemarkEmitter *ORE = nullptr);
332363

333364
/// Clones a loop \p OrigLoop. Returns the loop and the blocks in \p
334365
/// Blocks.

llvm/lib/Transforms/Utils/InlineFunction.cpp

Lines changed: 89 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2361,15 +2361,13 @@ remapIndices(Function &Caller, BasicBlock *StartBB,
23612361
// Updating the contextual profile after an inlining means, at a high level,
23622362
// copying over the data of the callee, **intentionally without any value
23632363
// scaling**, and copying over the callees of the inlined callee.
2364-
llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
2365-
PGOContextualProfile &CtxProf,
2366-
bool MergeAttributes,
2367-
AAResults *CalleeAAR,
2368-
bool InsertLifetime,
2369-
Function *ForwardVarArgsTo) {
2364+
llvm::InlineResult llvm::InlineFunction(
2365+
CallBase &CB, InlineFunctionInfo &IFI, PGOContextualProfile &CtxProf,
2366+
bool MergeAttributes, AAResults *CalleeAAR, bool InsertLifetime,
2367+
Function *ForwardVarArgsTo, OptimizationRemarkEmitter *ORE) {
23702368
if (!CtxProf.isInSpecializedModule())
23712369
return InlineFunction(CB, IFI, MergeAttributes, CalleeAAR, InsertLifetime,
2372-
ForwardVarArgsTo);
2370+
ForwardVarArgsTo, ORE);
23732371

23742372
auto &Caller = *CB.getCaller();
23752373
auto &Callee = *CB.getCalledFunction();
@@ -2387,7 +2385,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
23872385
const auto NumCalleeCallsites = CtxProf.getNumCallsites(Callee);
23882386

23892387
auto Ret = InlineFunction(CB, IFI, MergeAttributes, CalleeAAR, InsertLifetime,
2390-
ForwardVarArgsTo);
2388+
ForwardVarArgsTo, ORE);
23912389
if (!Ret.isSuccess())
23922390
return Ret;
23932391

@@ -2457,20 +2455,8 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24572455
return Ret;
24582456
}
24592457

2460-
/// This function inlines the called function into the basic block of the
2461-
/// caller. This returns false if it is not possible to inline this call.
2462-
/// The program is still in a well defined state if this occurs though.
2463-
///
2464-
/// Note that this only does one level of inlining. For example, if the
2465-
/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
2466-
/// exists in the instruction stream. Similarly this will inline a recursive
2467-
/// function by one level.
2468-
llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
2469-
bool MergeAttributes,
2470-
AAResults *CalleeAAR,
2471-
bool InsertLifetime,
2472-
Function *ForwardVarArgsTo,
2473-
OptimizationRemarkEmitter *ORE) {
2458+
llvm::InlineResult llvm::CanInlineCallSite(const CallBase &CB,
2459+
InlineFunctionInfo &IFI) {
24742460
assert(CB.getParent() && CB.getFunction() && "Instruction not in function!");
24752461

24762462
// FIXME: we don't inline callbr yet.
@@ -2487,7 +2473,6 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24872473

24882474
// The inliner does not know how to inline through calls with operand bundles
24892475
// in general ...
2490-
Value *ConvergenceControlToken = nullptr;
24912476
if (CB.hasOperandBundles()) {
24922477
for (int i = 0, e = CB.getNumOperandBundles(); i != e; ++i) {
24932478
auto OBUse = CB.getOperandBundleAt(i);
@@ -2503,7 +2488,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
25032488
if (Tag == LLVMContext::OB_kcfi)
25042489
continue;
25052490
if (Tag == LLVMContext::OB_convergencectrl) {
2506-
ConvergenceControlToken = OBUse.Inputs[0].get();
2491+
IFI.ConvergenceControlToken = OBUse.Inputs[0].get();
25072492
continue;
25082493
}
25092494

@@ -2521,28 +2506,22 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
25212506
// fully implements convergence control tokens, there is no mixing of
25222507
// controlled and uncontrolled convergent operations in the whole program.
25232508
if (CB.isConvergent()) {
2524-
if (!ConvergenceControlToken &&
2509+
if (!IFI.ConvergenceControlToken &&
25252510
getConvergenceEntry(CalledFunc->getEntryBlock())) {
25262511
return InlineResult::failure(
25272512
"convergent call needs convergencectrl operand");
25282513
}
25292514
}
25302515

2531-
// If the call to the callee cannot throw, set the 'nounwind' flag on any
2532-
// calls that we inline.
2533-
bool MarkNoUnwind = CB.doesNotThrow();
2534-
2535-
BasicBlock *OrigBB = CB.getParent();
2536-
Function *Caller = OrigBB->getParent();
2516+
const BasicBlock *OrigBB = CB.getParent();
2517+
const Function *Caller = OrigBB->getParent();
25372518

25382519
// GC poses two hazards to inlining, which only occur when the callee has GC:
25392520
// 1. If the caller has no GC, then the callee's GC must be propagated to the
25402521
// caller.
25412522
// 2. If the caller has a differing GC, it is invalid to inline.
25422523
if (CalledFunc->hasGC()) {
2543-
if (!Caller->hasGC())
2544-
Caller->setGC(CalledFunc->getGC());
2545-
else if (CalledFunc->getGC() != Caller->getGC())
2524+
if (Caller->hasGC() && CalledFunc->getGC() != Caller->getGC())
25462525
return InlineResult::failure("incompatible GC");
25472526
}
25482527

@@ -2560,34 +2539,31 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
25602539
? Caller->getPersonalityFn()->stripPointerCasts()
25612540
: nullptr;
25622541
if (CalledPersonality) {
2563-
if (!CallerPersonality)
2564-
Caller->setPersonalityFn(CalledPersonality);
25652542
// If the personality functions match, then we can perform the
25662543
// inlining. Otherwise, we can't inline.
25672544
// TODO: This isn't 100% true. Some personality functions are proper
25682545
// supersets of others and can be used in place of the other.
2569-
else if (CalledPersonality != CallerPersonality)
2546+
if (CallerPersonality && CalledPersonality != CallerPersonality)
25702547
return InlineResult::failure("incompatible personality");
25712548
}
25722549

25732550
// We need to figure out which funclet the callsite was in so that we may
25742551
// properly nest the callee.
2575-
Instruction *CallSiteEHPad = nullptr;
25762552
if (CallerPersonality) {
25772553
EHPersonality Personality = classifyEHPersonality(CallerPersonality);
25782554
if (isScopedEHPersonality(Personality)) {
25792555
std::optional<OperandBundleUse> ParentFunclet =
25802556
CB.getOperandBundle(LLVMContext::OB_funclet);
25812557
if (ParentFunclet)
2582-
CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());
2558+
IFI.CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());
25832559

25842560
// OK, the inlining site is legal. What about the target function?
25852561

2586-
if (CallSiteEHPad) {
2562+
if (IFI.CallSiteEHPad) {
25872563
if (Personality == EHPersonality::MSVC_CXX) {
25882564
// The MSVC personality cannot tolerate catches getting inlined into
25892565
// cleanup funclets.
2590-
if (isa<CleanupPadInst>(CallSiteEHPad)) {
2566+
if (isa<CleanupPadInst>(IFI.CallSiteEHPad)) {
25912567
// Ok, the call site is within a cleanuppad. Let's check the callee
25922568
// for catchpads.
25932569
for (const BasicBlock &CalledBB : *CalledFunc) {
@@ -2607,13 +2583,34 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
26072583
}
26082584
}
26092585

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

26182615
EHPadForCallUnwindsLocally =
26192616
CallSiteUnwindDestToken &&
@@ -2630,6 +2627,30 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
26302627
ClonedCodeInfo InlinedFunctionInfo;
26312628
Function::iterator FirstNewBlock;
26322629

2630+
// GC poses two hazards to inlining, which only occur when the callee has GC:
2631+
// 1. If the caller has no GC, then the callee's GC must be propagated to the
2632+
// caller.
2633+
// 2. If the caller has a differing GC, it is invalid to inline.
2634+
if (CalledFunc->hasGC()) {
2635+
if (!Caller->hasGC())
2636+
Caller->setGC(CalledFunc->getGC());
2637+
else {
2638+
assert(CalledFunc->getGC() == Caller->getGC() &&
2639+
"CanInlineCallSite should have verified compatible GCs");
2640+
}
2641+
}
2642+
2643+
if (CalledFunc->hasPersonalityFn()) {
2644+
Constant *CalledPersonality =
2645+
CalledFunc->getPersonalityFn()->stripPointerCasts();
2646+
if (!Caller->hasPersonalityFn()) {
2647+
Caller->setPersonalityFn(CalledPersonality);
2648+
} else
2649+
assert(Caller->getPersonalityFn()->stripPointerCasts() ==
2650+
CalledPersonality &&
2651+
"CanInlineCallSite should have verified compatible personality");
2652+
}
2653+
26332654
{ // Scope to destroy VMap after cloning.
26342655
ValueToValueMapTy VMap;
26352656
struct ByValInit {
@@ -2819,10 +2840,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
28192840
IFI.GetAssumptionCache(*Caller).registerAssumption(II);
28202841
}
28212842

2822-
if (ConvergenceControlToken) {
2843+
if (IFI.ConvergenceControlToken) {
28232844
IntrinsicInst *IntrinsicCall = getConvergenceEntry(*FirstNewBlock);
28242845
if (IntrinsicCall) {
2825-
IntrinsicCall->replaceAllUsesWith(ConvergenceControlToken);
2846+
IntrinsicCall->replaceAllUsesWith(IFI.ConvergenceControlToken);
28262847
IntrinsicCall->eraseFromParent();
28272848
}
28282849
}
@@ -2869,6 +2890,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
28692890
}
28702891
}
28712892

2893+
// If the call to the callee cannot throw, set the 'nounwind' flag on any
2894+
// calls that we inline.
2895+
bool MarkNoUnwind = CB.doesNotThrow();
2896+
28722897
SmallVector<Value*,4> VarArgsToForward;
28732898
SmallVector<AttributeSet, 4> VarArgsAttrs;
28742899
for (unsigned i = CalledFunc->getFunctionType()->getNumParams();
@@ -3055,12 +3080,12 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
30553080
// Update the lexical scopes of the new funclets and callsites.
30563081
// Anything that had 'none' as its parent is now nested inside the callsite's
30573082
// EHPad.
3058-
if (CallSiteEHPad) {
3083+
if (IFI.CallSiteEHPad) {
30593084
for (Function::iterator BB = FirstNewBlock->getIterator(),
30603085
E = Caller->end();
30613086
BB != E; ++BB) {
30623087
// Add bundle operands to inlined call sites.
3063-
PropagateOperandBundles(BB, CallSiteEHPad);
3088+
PropagateOperandBundles(BB, IFI.CallSiteEHPad);
30643089

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

30773102
if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
30783103
if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
3079-
CatchSwitch->setParentPad(CallSiteEHPad);
3104+
CatchSwitch->setParentPad(IFI.CallSiteEHPad);
30803105
} else {
30813106
auto *FPI = cast<FuncletPadInst>(I);
30823107
if (isa<ConstantTokenNone>(FPI->getParentPad()))
3083-
FPI->setParentPad(CallSiteEHPad);
3108+
FPI->setParentPad(IFI.CallSiteEHPad);
30843109
}
30853110
}
30863111
}
@@ -3236,7 +3261,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
32363261
AttributeFuncs::mergeAttributesForInlining(*Caller, *CalledFunc);
32373262

32383263
// We are now done with the inlining.
3239-
return InlineResult::success();
3264+
return;
32403265
}
32413266

32423267
// Otherwise, we have the normal case, of more than one block to inline or
@@ -3404,6 +3429,19 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
34043429

34053430
if (MergeAttributes)
34063431
AttributeFuncs::mergeAttributesForInlining(*Caller, *CalledFunc);
3432+
}
34073433

3408-
return InlineResult::success();
3434+
llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
3435+
bool MergeAttributes,
3436+
AAResults *CalleeAAR,
3437+
bool InsertLifetime,
3438+
Function *ForwardVarArgsTo,
3439+
OptimizationRemarkEmitter *ORE) {
3440+
llvm::InlineResult Result = CanInlineCallSite(CB, IFI);
3441+
if (Result.isSuccess()) {
3442+
InlineFunctionImpl(CB, IFI, MergeAttributes, CalleeAAR, InsertLifetime,
3443+
ForwardVarArgsTo, ORE);
3444+
}
3445+
3446+
return Result;
34093447
}

0 commit comments

Comments
 (0)