diff options
author | goldsteinn <35538541+goldsteinn@users.noreply.github.com> | 2024-10-17 21:28:47 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-10-17 20:28:47 -0500 |
commit | 69a798a996e0cd9d521db38167cadf841d629d38 (patch) | |
tree | 7cad9a07fb45ee354c861c8ad01aaba5eb938ae1 /llvm/lib/Transforms/Utils/InlineFunction.cpp | |
parent | e9eec14bb3566f6578950797559de98678f16985 (diff) | |
download | llvm-69a798a996e0cd9d521db38167cadf841d629d38.zip llvm-69a798a996e0cd9d521db38167cadf841d629d38.tar.gz llvm-69a798a996e0cd9d521db38167cadf841d629d38.tar.bz2 |
Reapply "[Inliner] Propagate more attributes to params when inlining (#91101)" (2nd Attempt) (#112749)
Root cause of the bug was code hanging onto `range` attr after
changing BitWidth. This was fixed in PR #112633.
Diffstat (limited to 'llvm/lib/Transforms/Utils/InlineFunction.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/InlineFunction.cpp | 90 |
1 files changed, 74 insertions, 16 deletions
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index a0a93dc..4ad4262 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -34,6 +34,7 @@ #include "llvm/Analysis/VectorUtils.h" #include "llvm/IR/Argument.h" #include "llvm/IR/AttributeMask.h" +#include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constant.h" @@ -59,6 +60,7 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/IR/ProfDataUtils.h" #include "llvm/IR/Type.h" #include "llvm/IR/User.h" @@ -1358,18 +1360,36 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB, auto &Context = CalledFunction->getContext(); // Collect valid attributes for all params. - SmallVector<AttrBuilder> ValidParamAttrs; + SmallVector<AttrBuilder> ValidObjParamAttrs, ValidExactParamAttrs; bool HasAttrToPropagate = false; + // Attributes we can only propagate if the exact parameter is forwarded. + // We can propagate both poison generating and UB generating attributes + // without any extra checks. The only attribute that is tricky to propagate + // is `noundef` (skipped for now) as that can create new UB where previous + // behavior was just using a poison value. + static const Attribute::AttrKind ExactAttrsToPropagate[] = { + Attribute::Dereferenceable, Attribute::DereferenceableOrNull, + Attribute::NonNull, Attribute::Alignment, Attribute::Range}; + for (unsigned I = 0, E = CB.arg_size(); I < E; ++I) { - ValidParamAttrs.emplace_back(AttrBuilder{CB.getContext()}); + ValidObjParamAttrs.emplace_back(AttrBuilder{CB.getContext()}); + ValidExactParamAttrs.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); + ValidObjParamAttrs.back().addAttribute(Attribute::ReadNone); if (CB.paramHasAttr(I, Attribute::ReadOnly)) - ValidParamAttrs.back().addAttribute(Attribute::ReadOnly); - HasAttrToPropagate |= ValidParamAttrs.back().hasAttributes(); + ValidObjParamAttrs.back().addAttribute(Attribute::ReadOnly); + + for (Attribute::AttrKind AK : ExactAttrsToPropagate) { + Attribute Attr = CB.getParamAttr(I, AK); + if (Attr.isValid()) + ValidExactParamAttrs.back().addAttribute(Attr); + } + + HasAttrToPropagate |= ValidObjParamAttrs.back().hasAttributes(); + HasAttrToPropagate |= ValidExactParamAttrs.back().hasAttributes(); } // Won't be able to propagate anything. @@ -1391,22 +1411,60 @@ static void AddParamAndFnBasicAttributes(const CallBase &CB, 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) + // It's unsound or requires special handling to propagate + // attributes to byval arguments. Even if CalledFunction + // doesn't e.g. write to the argument (readonly), the call to + // NewInnerCB may write to its by-value copy. + if (NewInnerCB->paramHasAttr(I, Attribute::ByVal)) continue; - if (NewInnerCB->paramHasAttr(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. + // Don't bother propagating attrs to constants. + if (match(NewInnerCB->getArgOperand(I), + llvm::PatternMatch::m_ImmConstant())) continue; - unsigned ArgNo = Arg->getArgNo(); + // Check if the underlying value for the parameter is an argument. + const Argument *Arg = dyn_cast<Argument>(InnerCB->getArgOperand(I)); + unsigned ArgNo; + if (Arg) { + ArgNo = Arg->getArgNo(); + // For dereferenceable, dereferenceable_or_null, align, etc... + // we don't want to propagate if the existing param has the same + // attribute with "better" constraints. So remove from the + // new AL if the region of the existing param is larger than + // what we can propagate. + AttrBuilder NewAB{ + Context, AttributeSet::get(Context, ValidExactParamAttrs[ArgNo])}; + if (AL.getParamDereferenceableBytes(I) > + NewAB.getDereferenceableBytes()) + NewAB.removeAttribute(Attribute::Dereferenceable); + if (AL.getParamDereferenceableOrNullBytes(I) > + NewAB.getDereferenceableOrNullBytes()) + NewAB.removeAttribute(Attribute::DereferenceableOrNull); + if (AL.getParamAlignment(I).valueOrOne() > + NewAB.getAlignment().valueOrOne()) + NewAB.removeAttribute(Attribute::Alignment); + if (auto ExistingRange = AL.getParamRange(I)) { + if (auto NewRange = NewAB.getRange()) { + ConstantRange CombinedRange = + ExistingRange->intersectWith(*NewRange); + NewAB.removeAttribute(Attribute::Range); + NewAB.addRangeAttr(CombinedRange); + } + } + AL = AL.addParamAttributes(Context, I, NewAB); + } else { + // Check if the underlying value for the parameter is an argument. + const Value *UnderlyingV = + getUnderlyingObject(InnerCB->getArgOperand(I)); + Arg = dyn_cast<Argument>(UnderlyingV); + if (!Arg) + continue; + ArgNo = Arg->getArgNo(); + } + // If so, propagate its access attributes. - AL = AL.addParamAttributes(Context, I, ValidParamAttrs[ArgNo]); + AL = AL.addParamAttributes(Context, I, ValidObjParamAttrs[ArgNo]); // We can have conflicting attributes from the inner callsite and // to-be-inlined callsite. In that case, choose the most // restrictive. |