Skip to content

Commit b3f6884

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 1277837 commit b3f6884

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
@@ -2452,19 +2452,8 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24522452
return Ret;
24532453
}
24542454

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

24702459
// FIXME: we don't inline callbr yet.
@@ -2481,7 +2470,6 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24812470

24822471
// The inliner does not know how to inline through calls with operand bundles
24832472
// in general ...
2484-
Value *ConvergenceControlToken = nullptr;
24852473
if (CB.hasOperandBundles()) {
24862474
for (int i = 0, e = CB.getNumOperandBundles(); i != e; ++i) {
24872475
auto OBUse = CB.getOperandBundleAt(i);
@@ -2497,7 +2485,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
24972485
if (Tag == LLVMContext::OB_kcfi)
24982486
continue;
24992487
if (Tag == LLVMContext::OB_convergencectrl) {
2500-
ConvergenceControlToken = OBUse.Inputs[0].get();
2488+
IFI.ConvergenceControlToken = OBUse.Inputs[0].get();
25012489
continue;
25022490
}
25032491

@@ -2515,28 +2503,22 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
25152503
// fully implements convergence control tokens, there is no mixing of
25162504
// controlled and uncontrolled convergent operations in the whole program.
25172505
if (CB.isConvergent()) {
2518-
if (!ConvergenceControlToken &&
2506+
if (!IFI.ConvergenceControlToken &&
25192507
getConvergenceEntry(CalledFunc->getEntryBlock())) {
25202508
return InlineResult::failure(
25212509
"convergent call needs convergencectrl operand");
25222510
}
25232511
}
25242512

2525-
// If the call to the callee cannot throw, set the 'nounwind' flag on any
2526-
// calls that we inline.
2527-
bool MarkNoUnwind = CB.doesNotThrow();
2528-
2529-
BasicBlock *OrigBB = CB.getParent();
2530-
Function *Caller = OrigBB->getParent();
2513+
const BasicBlock *OrigBB = CB.getParent();
2514+
const Function *Caller = OrigBB->getParent();
25312515

25322516
// GC poses two hazards to inlining, which only occur when the callee has GC:
25332517
// 1. If the caller has no GC, then the callee's GC must be propagated to the
25342518
// caller.
25352519
// 2. If the caller has a differing GC, it is invalid to inline.
25362520
if (CalledFunc->hasGC()) {
2537-
if (!Caller->hasGC())
2538-
Caller->setGC(CalledFunc->getGC());
2539-
else if (CalledFunc->getGC() != Caller->getGC())
2521+
if (Caller->hasGC() && CalledFunc->getGC() != Caller->getGC())
25402522
return InlineResult::failure("incompatible GC");
25412523
}
25422524

@@ -2554,34 +2536,31 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
25542536
? Caller->getPersonalityFn()->stripPointerCasts()
25552537
: nullptr;
25562538
if (CalledPersonality) {
2557-
if (!CallerPersonality)
2558-
Caller->setPersonalityFn(CalledPersonality);
25592539
// If the personality functions match, then we can perform the
25602540
// inlining. Otherwise, we can't inline.
25612541
// TODO: This isn't 100% true. Some personality functions are proper
25622542
// supersets of others and can be used in place of the other.
2563-
else if (CalledPersonality != CallerPersonality)
2543+
if (CallerPersonality && CalledPersonality != CallerPersonality)
25642544
return InlineResult::failure("incompatible personality");
25652545
}
25662546

25672547
// We need to figure out which funclet the callsite was in so that we may
25682548
// properly nest the callee.
2569-
Instruction *CallSiteEHPad = nullptr;
25702549
if (CallerPersonality) {
25712550
EHPersonality Personality = classifyEHPersonality(CallerPersonality);
25722551
if (isScopedEHPersonality(Personality)) {
25732552
std::optional<OperandBundleUse> ParentFunclet =
25742553
CB.getOperandBundle(LLVMContext::OB_funclet);
25752554
if (ParentFunclet)
2576-
CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());
2555+
IFI.CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());
25772556

25782557
// OK, the inlining site is legal. What about the target function?
25792558

2580-
if (CallSiteEHPad) {
2559+
if (IFI.CallSiteEHPad) {
25812560
if (Personality == EHPersonality::MSVC_CXX) {
25822561
// The MSVC personality cannot tolerate catches getting inlined into
25832562
// cleanup funclets.
2584-
if (isa<CleanupPadInst>(CallSiteEHPad)) {
2563+
if (isa<CleanupPadInst>(IFI.CallSiteEHPad)) {
25852564
// Ok, the call site is within a cleanuppad. Let's check the callee
25862565
// for catchpads.
25872566
for (const BasicBlock &CalledBB : *CalledFunc) {
@@ -2601,13 +2580,33 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
26012580
}
26022581
}
26032582

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

26122611
EHPadForCallUnwindsLocally =
26132612
CallSiteUnwindDestToken &&
@@ -2624,6 +2623,30 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
26242623
ClonedCodeInfo InlinedFunctionInfo;
26252624
Function::iterator FirstNewBlock;
26262625

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

2816-
if (ConvergenceControlToken) {
2839+
if (IFI.ConvergenceControlToken) {
28172840
IntrinsicInst *IntrinsicCall = getConvergenceEntry(*FirstNewBlock);
28182841
if (IntrinsicCall) {
2819-
IntrinsicCall->replaceAllUsesWith(ConvergenceControlToken);
2842+
IntrinsicCall->replaceAllUsesWith(IFI.ConvergenceControlToken);
28202843
IntrinsicCall->eraseFromParent();
28212844
}
28222845
}
@@ -2863,6 +2886,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
28632886
}
28642887
}
28652888

2889+
// If the call to the callee cannot throw, set the 'nounwind' flag on any
2890+
// calls that we inline.
2891+
bool MarkNoUnwind = CB.doesNotThrow();
2892+
28662893
SmallVector<Value*,4> VarArgsToForward;
28672894
SmallVector<AttributeSet, 4> VarArgsAttrs;
28682895
for (unsigned i = CalledFunc->getFunctionType()->getNumParams();
@@ -3049,12 +3076,12 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
30493076
// Update the lexical scopes of the new funclets and callsites.
30503077
// Anything that had 'none' as its parent is now nested inside the callsite's
30513078
// EHPad.
3052-
if (CallSiteEHPad) {
3079+
if (IFI.CallSiteEHPad) {
30533080
for (Function::iterator BB = FirstNewBlock->getIterator(),
30543081
E = Caller->end();
30553082
BB != E; ++BB) {
30563083
// Add bundle operands to inlined call sites.
3057-
PropagateOperandBundles(BB, CallSiteEHPad);
3084+
PropagateOperandBundles(BB, IFI.CallSiteEHPad);
30583085

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

30713098
if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
30723099
if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
3073-
CatchSwitch->setParentPad(CallSiteEHPad);
3100+
CatchSwitch->setParentPad(IFI.CallSiteEHPad);
30743101
} else {
30753102
auto *FPI = cast<FuncletPadInst>(I);
30763103
if (isa<ConstantTokenNone>(FPI->getParentPad()))
3077-
FPI->setParentPad(CallSiteEHPad);
3104+
FPI->setParentPad(IFI.CallSiteEHPad);
30783105
}
30793106
}
30803107
}
@@ -3230,7 +3257,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
32303257
AttributeFuncs::mergeAttributesForInlining(*Caller, *CalledFunc);
32313258

32323259
// We are now done with the inlining.
3233-
return InlineResult::success();
3260+
return;
32343261
}
32353262

32363263
// Otherwise, we have the normal case, of more than one block to inline or
@@ -3390,6 +3417,18 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
33903417

33913418
if (MergeAttributes)
33923419
AttributeFuncs::mergeAttributesForInlining(*Caller, *CalledFunc);
3420+
}
33933421

3394-
return InlineResult::success();
3422+
llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
3423+
bool MergeAttributes,
3424+
AAResults *CalleeAAR,
3425+
bool InsertLifetime,
3426+
Function *ForwardVarArgsTo) {
3427+
llvm::InlineResult Result = CanInlineCallSite(CB, IFI);
3428+
if (Result.isSuccess()) {
3429+
InlineFunctionImpl(CB, IFI, MergeAttributes, CalleeAAR, InsertLifetime,
3430+
ForwardVarArgsTo);
3431+
}
3432+
3433+
return Result;
33953434
}

0 commit comments

Comments
 (0)