[IR] Allow the 'align' param attr on vectors of pointers
authorFraser Cormack <fraser@codeplay.com>
Mon, 6 Dec 2021 15:49:23 +0000 (15:49 +0000)
committerFraser Cormack <fraser@codeplay.com>
Mon, 3 Jan 2022 12:32:46 +0000 (12:32 +0000)
This patch extends the available uses of the 'align' parameter attribute
to include vectors of pointers. The attribute specifies pointer
alignment element-wise.

This change was previously requested and discussed in D87304.

The vector predication (VP) intrinsics intend to use this for scatter
and gather operations, as they lack the explicit alignment parameter
that the masked versions use.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D115161

llvm/docs/LangRef.rst
llvm/lib/IR/Attributes.cpp
llvm/test/Bitcode/attributes.ll

index ce3af42..8c72e32 100644 (file)
@@ -1210,12 +1210,14 @@ Currently, only the following parameter attributes are defined:
 .. _attr_align:
 
 ``align <n>`` or ``align(<n>)``
-    This indicates that the pointer value has the specified alignment.
-    If the pointer value does not have the specified alignment,
-    :ref:`poison value <poisonvalues>` is returned or passed instead. The
-    ``align`` attribute should be combined with the ``noundef`` attribute to
-    ensure a pointer is aligned, or otherwise the behavior is undefined. Note
-    that ``align 1`` has no effect on non-byval, non-preallocated arguments.
+    This indicates that the pointer value or vector of pointers has the
+    specified alignment. If applied to a vector of pointers, *all* pointers
+    (elements) have the specified alignment. If the pointer value does not have
+    the specified alignment, :ref:`poison value <poisonvalues>` is returned or
+    passed instead.  The ``align`` attribute should be combined with the
+    ``noundef`` attribute to ensure a pointer is aligned, or otherwise the
+    behavior is undefined. Note that ``align 1`` has no effect on non-byval,
+    non-preallocated arguments.
 
     Note that this attribute has additional semantics when combined with the
     ``byval`` or ``preallocated`` attribute, which are documented there.
index c899afa..2c917e4 100644 (file)
@@ -1839,12 +1839,12 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
   AttrBuilder Incompatible;
 
   if (!Ty->isIntegerTy())
-    // Attribute that only apply to integers.
+    // Attributes that only apply to integers.
     Incompatible.addAttribute(Attribute::SExt)
       .addAttribute(Attribute::ZExt);
 
   if (!Ty->isPointerTy())
-    // Attribute that only apply to pointers.
+    // Attributes that only apply to pointers.
     Incompatible.addAttribute(Attribute::Nest)
         .addAttribute(Attribute::NoAlias)
         .addAttribute(Attribute::NoCapture)
@@ -1852,7 +1852,6 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
         .addAttribute(Attribute::ReadNone)
         .addAttribute(Attribute::ReadOnly)
         .addAttribute(Attribute::SwiftError)
-        .addAlignmentAttr(1)             // the int here is ignored
         .addDereferenceableAttr(1)       // the int here is ignored
         .addDereferenceableOrNullAttr(1) // the int here is ignored
         .addPreallocatedAttr(Ty)
@@ -1862,6 +1861,10 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
         .addByRefAttr(Ty)
         .addTypeAttr(Attribute::ElementType, Ty);
 
+  if (!Ty->isPtrOrPtrVectorTy())
+    // Attributes that only apply to pointers or vectors of pointers.
+    Incompatible.addAlignmentAttr(1); // the int here is ignored
+
   // Some attributes can apply to all "values" but there are no `void` values.
   if (Ty->isVoidTy())
     Incompatible.addAttribute(Attribute::NoUndef);
index ec4f903..b2b92bb 100644 (file)
@@ -510,6 +510,12 @@ define void @f82(i32* %0)
         ret void;
 }
 
+; CHECK-TYPED: define void @f83(<4 x i8*> align 32 %0, <vscale x 1 x double*> align 64 %1)
+; CHECK-OPQUE: define void @f83(<4 x ptr> align 32 %0, <vscale x 1 x ptr> align 64 %1)
+define void @f83(<4 x i8*> align 32 %0, <vscale x 1 x double*> align 64 %1) {
+  ret void
+}
+
 ; CHECK: attributes #0 = { noreturn }
 ; CHECK: attributes #1 = { nounwind }
 ; CHECK: attributes #2 = { readnone }