[llvm] [SimplifyCFG] Supporting hoisting/sinking callbases with differing attrs (PR #109472)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 23 07:30:45 PDT 2024
================
@@ -1591,10 +1591,150 @@ static void hoistLockstepIdenticalDbgVariableRecords(
}
}
+// See if we can intersect the attributes for two callbases (used for
+// hoisting/sinking).
+static std::optional<AttributeList> tryIntersectAttrs(const CallBase *CB0,
+ const CallBase *CB1) {
+ assert(CB0->getCalledFunction() == CB1->getCalledFunction() &&
+ "Merging attrs for different functions!");
+
+ AttributeList AL0 = CB0->getAttributes();
+ AttributeList AL1 = CB1->getAttributes();
+
+ // Trivial case if attributes match
+ if (AL0 == AL1)
+ return AL0;
+
+ // Otherwise go through all attributes present and make sure they either match
+ // or that dropping them is okay.
+ // Note: At the moment the logic is only concerned with correctness (i.e we
+ // can't sink a callbase with a `ByVal` attr on a param with one that doesn't
+ // have the attr). But there may be some attributes that are not preferable to
+ // drop i.e a certain Range attr might trivialize inlining so intersecting it
+ // with a callbase without the attr might not be profitable.
+ LLVMContext &Ctx = CB0->getContext();
+ auto IntersectAttrs = [&Ctx](AttributeSet AS0,
+ AttributeSet AS1) -> std::optional<AttrBuilder> {
+ AttrBuilder Intersected(Ctx);
+
+ AttributeSet AllAttrs = AS0.addAttributes(Ctx, AS1);
+ for (Attribute Attr : AllAttrs) {
+ if (!Attr.isValid())
+ return std::nullopt;
+
+ // Only supporting enum attrs for now.
+ if (!Attr.hasKindAsEnum())
+ return std::nullopt;
+
+ Attribute::AttrKind Kind = Attr.getKindAsEnum();
+ bool BothContain = AS0.hasAttribute(Kind) && AS1.hasAttribute(Kind);
+ switch (Kind) {
+ default:
+ // Except for the below attrs we know we can intersect safely, fail if
+ // the attributes don't match.
+ if (!BothContain)
+ return std::nullopt;
+ if (AS0.getAttribute(Kind) != AS1.getAttribute(Kind))
+ return std::nullopt;
+ Intersected.addAttribute(Attr);
+ break;
+ // Attributes that can safely be intersected and can safely be thrown
+ // away.
+ case Attribute::Cold:
+ case Attribute::Hot:
+ case Attribute::MustProgress:
+ case Attribute::NoAlias:
+ case Attribute::NoCallback:
+ case Attribute::NoCapture:
+ case Attribute::NoFree:
+ case Attribute::NoRecurse:
+ case Attribute::NoReturn:
+ case Attribute::NoSync:
+ case Attribute::NoUndef:
+ case Attribute::NoUnwind:
+ case Attribute::NonNull:
+ case Attribute::OptimizeForSize:
+ // TODO: We could merge ReadNone + Readonly -> ReadOnly
+ case Attribute::ReadNone:
+ case Attribute::ReadOnly:
+ case Attribute::Returned:
+ case Attribute::Speculatable:
+ case Attribute::WillReturn:
+ case Attribute::Writable:
+ case Attribute::WriteOnly:
----------------
goldsteinn wrote:
I was looking at doing that originally, decided with the lazy approach. Will do.
https://github.com/llvm/llvm-project/pull/109472
More information about the llvm-commits
mailing list