[llvm] [IR][Attribute] Add support for intersecting AttributeLists; NFC (PR #109719)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 26 12:49:26 PDT 2024
================
@@ -22,290 +22,323 @@ def ParamAttr : AttrProperty;
/// Can be used as return attribute.
def RetAttr : AttrProperty;
+
+
+/// Intersection rules. Used for example in sinking/hoisting two
+/// callbases to find a set of attributes that apply to both.
+/// Note, there are some attributes we can (probably) legally drop
+/// but are intentionally excluded as of now. Those include:
+/// - initializes
+/// - allockind
+/// - allocsize
+/// - minsize
+/// - optsize
+/// - optnone
+/// - optdebug
+/// - optforfuzzing
+///
+/// When intersecting the attributes must both present and equal.
+/// Use this for attributes you are not certain it is safe to drop
+/// at any time. I.e `byval(Ty)` on a parameter.
+def IntersectPreserve : AttrProperty;
+
+/// When intersecting take the AND of the two attrs.
+/// Only valid for Enum attrs.
+def IntersectAnd : AttrProperty;
+
+/// When intersecting take the min value of the two attrs.
+/// Only valid for Int attrs.
+def IntersectMin : AttrProperty;
+
+/// When intersecting rely on some specially defined code.
+def IntersectCustom : AttrProperty;
+
+
+
/// Attribute base class.
-class Attr<string S, list<AttrProperty> P> {
+class Attr<string S, AttrProperty I, list<AttrProperty> P> {
// String representation of this attribute in the IR.
string AttrString = S;
- list<AttrProperty> Properties = P;
+ list<AttrProperty> Properties = P # [I];
}
/// Enum attribute.
-class EnumAttr<string S, list<AttrProperty> P> : Attr<S, P>;
+class EnumAttr<string S, AttrProperty I, list<AttrProperty> P> : Attr<S, I, P>;
/// Int attribute.
-class IntAttr<string S, list<AttrProperty> P> : Attr<S, P>;
+class IntAttr<string S, AttrProperty I, list<AttrProperty> P> : Attr<S, I, P>;
/// Type attribute.
-class TypeAttr<string S, list<AttrProperty> P> : Attr<S, P>;
+class TypeAttr<string S, AttrProperty I, list<AttrProperty> P> : Attr<S, I, P>;
/// StringBool attribute.
-class StrBoolAttr<string S> : Attr<S, []>;
+class StrBoolAttr<string S> : Attr<S, IntersectPreserve, []>;
/// Arbitrary string attribute.
-class ComplexStrAttr<string S, list<AttrProperty> P> : Attr<S, P>;
+class ComplexStrAttr<string S, list<AttrProperty> P> : Attr<S, IntersectPreserve, P>;
/// ConstantRange attribute.
-class ConstantRangeAttr<string S, list<AttrProperty> P> : Attr<S, P>;
+class ConstantRangeAttr<string S, AttrProperty I, list<AttrProperty> P> : Attr<S, I, P>;
/// ConstantRangeList attribute.
-class ConstantRangeListAttr<string S, list<AttrProperty> P> : Attr<S, P>;
+class ConstantRangeListAttr<string S, AttrProperty I, list<AttrProperty> P> : Attr<S, I, P>;
/// Target-independent enum attributes.
/// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias.
/// 0 means unaligned (different from align(1)).
-def Alignment : IntAttr<"align", [ParamAttr, RetAttr]>;
+def Alignment : IntAttr<"align", IntersectCustom, [ParamAttr, RetAttr]>;
/// Parameter of a function that tells us the alignment of an allocation, as in
/// aligned_alloc and aligned ::operator::new.
-def AllocAlign: EnumAttr<"allocalign", [ParamAttr]>;
+def AllocAlign: EnumAttr<"allocalign", IntersectAnd, [ParamAttr]>;
/// Describes behavior of an allocator function in terms of known properties.
-def AllocKind: IntAttr<"allockind", [FnAttr]>;
+def AllocKind: IntAttr<"allockind", IntersectPreserve, [FnAttr]>;
/// Parameter is the pointer to be manipulated by the allocator function.
-def AllocatedPointer : EnumAttr<"allocptr", [ParamAttr]>;
+def AllocatedPointer : EnumAttr<"allocptr", IntersectAnd, [ParamAttr]>;
/// The result of the function is guaranteed to point to a number of bytes that
/// we can determine if we know the value of the function's arguments.
-def AllocSize : IntAttr<"allocsize", [FnAttr]>;
+def AllocSize : IntAttr<"allocsize", IntersectPreserve, [FnAttr]>;
/// inline=always.
-def AlwaysInline : EnumAttr<"alwaysinline", [FnAttr]>;
+def AlwaysInline : EnumAttr<"alwaysinline", IntersectPreserve, [FnAttr]>;
/// Callee is recognized as a builtin, despite nobuiltin attribute on its
/// declaration.
-def Builtin : EnumAttr<"builtin", [FnAttr]>;
+def Builtin : EnumAttr<"builtin", IntersectPreserve, [FnAttr]>;
/// Pass structure by value.
-def ByVal : TypeAttr<"byval", [ParamAttr]>;
+def ByVal : TypeAttr<"byval", IntersectPreserve, [ParamAttr]>;
/// Mark in-memory ABI type.
-def ByRef : TypeAttr<"byref", [ParamAttr]>;
+def ByRef : TypeAttr<"byref", IntersectPreserve, [ParamAttr]>;
/// Parameter or return value may not contain uninitialized or poison bits.
-def NoUndef : EnumAttr<"noundef", [ParamAttr, RetAttr]>;
+def NoUndef : EnumAttr<"noundef", IntersectAnd, [ParamAttr, RetAttr]>;
/// Marks function as being in a cold path.
-def Cold : EnumAttr<"cold", [FnAttr]>;
+def Cold : EnumAttr<"cold", IntersectAnd, [FnAttr]>;
/// Can only be moved to control-equivalent blocks.
-def Convergent : EnumAttr<"convergent", [FnAttr]>;
+def Convergent : EnumAttr<"convergent", IntersectAnd, [FnAttr]>;
----------------
nikic wrote:
This is not correct, the semantics here would be more along the lines of IntersectOr. You can just mark it as preserve for now.
https://github.com/llvm/llvm-project/pull/109719
More information about the llvm-commits
mailing list