diff options
author | Noah Goldstein <goldstein.w.n@gmail.com> | 2024-06-17 23:48:57 -0500 |
---|---|---|
committer | Noah Goldstein <goldstein.w.n@gmail.com> | 2024-06-21 16:14:28 +0800 |
commit | db03d9d33a84b184ac0ce0d9bcf1c0d3da202b61 (patch) | |
tree | f417a03630797ab99b417b74c116e72fb07869a8 /llvm/lib/Transforms/Utils/InlineFunction.cpp | |
parent | 0adecfbc393e86def951bca3516593a0a58ca7d0 (diff) | |
download | llvm-db03d9d33a84b184ac0ce0d9bcf1c0d3da202b61.zip llvm-db03d9d33a84b184ac0ce0d9bcf1c0d3da202b61.tar.gz llvm-db03d9d33a84b184ac0ce0d9bcf1c0d3da202b61.tar.bz2 |
Recommit "[Inliner] Propagate callee argument memory access attributes before inlining" (2nd Try)
In the re-commit, just dropping the propagation of `writeonly` as that
is the only attribute that can play poorly with call slot optimization
(see issue: #95152 for more details).
Closes #95888
Diffstat (limited to 'llvm/lib/Transforms/Utils/InlineFunction.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/InlineFunction.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index c4baafd..39e3a2c 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1344,6 +1344,83 @@ static bool MayContainThrowingOrExitingCallAfterCB(CallBase *Begin, ++BeginIt, End->getIterator(), InlinerAttributeWindow + 1); } +// Add attributes from CB params and Fn attributes that can always be propagated +// to the corresponding argument / inner callbases. +static void AddParamAndFnBasicAttributes(const CallBase &CB, + ValueToValueMapTy &VMap) { + auto *CalledFunction = CB.getCalledFunction(); + auto &Context = CalledFunction->getContext(); + + // Collect valid attributes for all params. + SmallVector<AttrBuilder> ValidParamAttrs; + bool HasAttrToPropagate = false; + + for (unsigned I = 0, E = CB.arg_size(); I < E; ++I) { + ValidParamAttrs.emplace_back(AttrBuilder{CB.getContext()}); + // Access attributes can be propagated to any param with the same underlying + // object as the argument. + if (CB.paramHasAttr(I, Attribute::ReadNone)) + ValidParamAttrs.back().addAttribute(Attribute::ReadNone); + if (CB.paramHasAttr(I, Attribute::ReadOnly)) + ValidParamAttrs.back().addAttribute(Attribute::ReadOnly); + HasAttrToPropagate |= ValidParamAttrs.back().hasAttributes(); + } + + // Won't be able to propagate anything. + if (!HasAttrToPropagate) + return; + + for (BasicBlock &BB : *CalledFunction) { + for (Instruction &Ins : BB) { + const auto *InnerCB = dyn_cast<CallBase>(&Ins); + if (!InnerCB) + continue; + auto *NewInnerCB = dyn_cast_or_null<CallBase>(VMap.lookup(InnerCB)); + if (!NewInnerCB) + continue; + AttributeList AL = NewInnerCB->getAttributes(); + for (unsigned I = 0, E = InnerCB->arg_size(); I < E; ++I) { + // Check if the underlying value for the parameter is an argument. + const Value *UnderlyingV = + getUnderlyingObject(InnerCB->getArgOperand(I)); + const Argument *Arg = dyn_cast<Argument>(UnderlyingV); + if (!Arg) + continue; + + if (AL.hasParamAttr(I, Attribute::ByVal)) + // It's unsound to propagate memory attributes to byval arguments. + // Even if CalledFunction doesn't e.g. write to the argument, + // the call to NewInnerCB may write to its by-value copy. + continue; + + unsigned ArgNo = Arg->getArgNo(); + // If so, propagate its access attributes. + AL = AL.addParamAttributes(Context, I, ValidParamAttrs[ArgNo]); + // We can have conflicting attributes from the inner callsite and + // to-be-inlined callsite. In that case, choose the most + // restrictive. + + // readonly + writeonly means we can never deref so make readnone. + if (AL.hasParamAttr(I, Attribute::ReadOnly) && + AL.hasParamAttr(I, Attribute::WriteOnly)) + AL = AL.addParamAttribute(Context, I, Attribute::ReadNone); + + // If have readnone, need to clear readonly/writeonly + if (AL.hasParamAttr(I, Attribute::ReadNone)) { + AL = AL.removeParamAttribute(Context, I, Attribute::ReadOnly); + AL = AL.removeParamAttribute(Context, I, Attribute::WriteOnly); + } + + // Writable cannot exist in conjunction w/ readonly/readnone + if (AL.hasParamAttr(I, Attribute::ReadOnly) || + AL.hasParamAttr(I, Attribute::ReadNone)) + AL = AL.removeParamAttribute(Context, I, Attribute::Writable); + } + NewInnerCB->setAttributes(AL); + } + } +} + // Only allow these white listed attributes to be propagated back to the // callee. This is because other attributes may only be valid on the call // itself, i.e. attributes such as signext and zeroext. @@ -2363,6 +2440,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, // function which feed into its return value. AddReturnAttributes(CB, VMap); + // Clone attributes on the params of the callsite to calls within the + // inlined function which use the same param. + AddParamAndFnBasicAttributes(CB, VMap); + propagateMemProfMetadata(CalledFunc, CB, InlinedFunctionInfo.ContainsMemProfMetadata, VMap); |