aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/InlineFunction.cpp
diff options
context:
space:
mode:
authorNoah Goldstein <goldstein.w.n@gmail.com>2024-06-17 23:48:57 -0500
committerNoah Goldstein <goldstein.w.n@gmail.com>2024-06-21 16:14:28 +0800
commitdb03d9d33a84b184ac0ce0d9bcf1c0d3da202b61 (patch)
treef417a03630797ab99b417b74c116e72fb07869a8 /llvm/lib/Transforms/Utils/InlineFunction.cpp
parent0adecfbc393e86def951bca3516593a0a58ca7d0 (diff)
downloadllvm-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.cpp81
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);