Skip to content

Commit

Permalink
[IR][Attribute] Add support for intersecting AttributeLists; NFC (#10…
Browse files Browse the repository at this point in the history
…9719)

Add support for taking the intersection of two AttributeLists s.t the
result list contains attributes that are valid in the context of both
inputs.

i.e if we have `nonnull align(32) noundef` intersected with `nonnull
align(16) dereferenceable(10)`, the result is `nonnull align(16)`.

Further it handles attributes that are not-droppable. For example
dropping `byval` can change the nature of a callsite/function so its
impossible to correct a correct intersection if its dropped from the
result. i.e `nonnull byval(i64)` intersected with `nonnull` is
invalid.

The motivation for the infrastructure is to enable sinking/hoisting
callsites with differing attributes.
  • Loading branch information
goldsteinn authored Oct 1, 2024
1 parent 0dab022 commit afc0557
Show file tree
Hide file tree
Showing 6 changed files with 731 additions and 120 deletions.
26 changes: 25 additions & 1 deletion llvm/include/llvm/IR/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ class Attribute {
static bool canUseAsParamAttr(AttrKind Kind);
static bool canUseAsRetAttr(AttrKind Kind);

static bool intersectMustPreserve(AttrKind Kind);
static bool intersectWithAnd(AttrKind Kind);
static bool intersectWithMin(AttrKind Kind);
static bool intersectWithCustom(AttrKind Kind);

private:
AttributeImpl *pImpl = nullptr;

Expand Down Expand Up @@ -208,8 +213,12 @@ class Attribute {
/// Return true if the target-dependent attribute is present.
bool hasAttribute(StringRef Val) const;

/// Returns true if the attribute's kind can be represented as an enum (Enum,
/// Integer, Type, ConstantRange, or ConstantRangeList attribute).
bool hasKindAsEnum() const { return !isStringAttribute(); }

/// Return the attribute's kind as an enum (Attribute::AttrKind). This
/// requires the attribute to be an enum, integer, or type attribute.
/// requires the attribute be representable as an enum (see: `hasKindAsEnum`).
Attribute::AttrKind getKindAsEnum() const;

/// Return the attribute's value as an integer. This requires that the
Expand Down Expand Up @@ -295,6 +304,9 @@ class Attribute {
bool operator==(Attribute A) const { return pImpl == A.pImpl; }
bool operator!=(Attribute A) const { return pImpl != A.pImpl; }

/// Used to sort attribute by kind.
int cmpKind(Attribute A) const;

/// Less-than operator. Useful for sorting the attributes list.
bool operator<(Attribute A) const;

Expand Down Expand Up @@ -383,6 +395,12 @@ class AttributeSet {
[[nodiscard]] AttributeSet
removeAttributes(LLVMContext &C, const AttributeMask &AttrsToRemove) const;

/// Try to intersect this AttributeSet with Other. Returns std::nullopt if
/// the two lists are inherently incompatible (imply different behavior, not
/// just analysis).
[[nodiscard]] std::optional<AttributeSet>
intersectWith(LLVMContext &C, AttributeSet Other) const;

/// Return the number of attributes in this set.
unsigned getNumAttributes() const;

Expand Down Expand Up @@ -775,6 +793,12 @@ class AttributeList {
addAllocSizeParamAttr(LLVMContext &C, unsigned ArgNo, unsigned ElemSizeArg,
const std::optional<unsigned> &NumElemsArg) const;

/// Try to intersect this AttributeList with Other. Returns std::nullopt if
/// the two lists are inherently incompatible (imply different behavior, not
/// just analysis).
[[nodiscard]] std::optional<AttributeList>
intersectWith(LLVMContext &C, AttributeList Other) const;

//===--------------------------------------------------------------------===//
// AttributeList Accessors
//===--------------------------------------------------------------------===//
Expand Down
Loading

0 comments on commit afc0557

Please sign in to comment.