[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