Skip to content

Commit afc0557

Browse files
authored
[IR][Attribute] Add support for intersecting AttributeLists; NFC (#109719)
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.
1 parent 0dab022 commit afc0557

File tree

6 files changed

+731
-120
lines changed

6 files changed

+731
-120
lines changed

llvm/include/llvm/IR/Attributes.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ class Attribute {
117117
static bool canUseAsParamAttr(AttrKind Kind);
118118
static bool canUseAsRetAttr(AttrKind Kind);
119119

120+
static bool intersectMustPreserve(AttrKind Kind);
121+
static bool intersectWithAnd(AttrKind Kind);
122+
static bool intersectWithMin(AttrKind Kind);
123+
static bool intersectWithCustom(AttrKind Kind);
124+
120125
private:
121126
AttributeImpl *pImpl = nullptr;
122127

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

216+
/// Returns true if the attribute's kind can be represented as an enum (Enum,
217+
/// Integer, Type, ConstantRange, or ConstantRangeList attribute).
218+
bool hasKindAsEnum() const { return !isStringAttribute(); }
219+
211220
/// Return the attribute's kind as an enum (Attribute::AttrKind). This
212-
/// requires the attribute to be an enum, integer, or type attribute.
221+
/// requires the attribute be representable as an enum (see: `hasKindAsEnum`).
213222
Attribute::AttrKind getKindAsEnum() const;
214223

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

307+
/// Used to sort attribute by kind.
308+
int cmpKind(Attribute A) const;
309+
298310
/// Less-than operator. Useful for sorting the attributes list.
299311
bool operator<(Attribute A) const;
300312

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

398+
/// Try to intersect this AttributeSet with Other. Returns std::nullopt if
399+
/// the two lists are inherently incompatible (imply different behavior, not
400+
/// just analysis).
401+
[[nodiscard]] std::optional<AttributeSet>
402+
intersectWith(LLVMContext &C, AttributeSet Other) const;
403+
386404
/// Return the number of attributes in this set.
387405
unsigned getNumAttributes() const;
388406

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

796+
/// Try to intersect this AttributeList with Other. Returns std::nullopt if
797+
/// the two lists are inherently incompatible (imply different behavior, not
798+
/// just analysis).
799+
[[nodiscard]] std::optional<AttributeList>
800+
intersectWith(LLVMContext &C, AttributeList Other) const;
801+
778802
//===--------------------------------------------------------------------===//
779803
// AttributeList Accessors
780804
//===--------------------------------------------------------------------===//

0 commit comments

Comments
 (0)