Skip to content

Commit 0a41fb7

Browse files
authored
[Clang] Treat ext_vector_type as a regular type attribute (#130177)
Summary: This attribute is mostly borrowed from OpenCL, but is useful in general for accessing the LLVM vector types. Previously the only way to use it was through typedefs. This patch changes that to allow use as a regular type attribute, similar to address spaces.
1 parent 67960e5 commit 0a41fb7

File tree

8 files changed

+66
-23
lines changed

8 files changed

+66
-23
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ Adding [[clang::unsafe_buffer_usage]] attribute to a method definition now turns
151151
related warnings within the method body.
152152

153153
- The ``no_sanitize`` attribute now accepts both ``gnu`` and ``clang`` names.
154+
- The ``ext_vector_type(n)`` attribute can now be used as a generic type attribute.
154155
- Clang now diagnoses use of declaration attributes on void parameters. (#GH108819)
155156
- Clang now allows ``__attribute__((model("small")))`` and
156157
``__attribute__((model("large")))`` on non-TLS globals in x86-64 compilations.

clang/include/clang/Basic/Attr.td

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,17 +1721,10 @@ def EnableIf : InheritableAttr {
17211721
let Documentation = [EnableIfDocs];
17221722
}
17231723

1724-
def ExtVectorType : Attr {
1725-
// This is an OpenCL-related attribute and does not receive a [[]] spelling.
1726-
let Spellings = [GNU<"ext_vector_type">];
1727-
// FIXME: This subject list is wrong; this is a type attribute.
1728-
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
1724+
def ExtVectorType : TypeAttr {
1725+
let Spellings = [Clang<"ext_vector_type">];
17291726
let Args = [ExprArgument<"NumElements">];
1730-
let ASTNode = 0;
1731-
let Documentation = [Undocumented];
1732-
// This is a type attribute with an incorrect subject list, so should not be
1733-
// permitted by #pragma clang attribute.
1734-
let PragmaAttributeSupport = 0;
1727+
let Documentation = [ExtVectorTypeDocs];
17351728
}
17361729

17371730
def FallThrough : StmtAttr {

clang/include/clang/Basic/AttrDocs.td

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,42 @@ template instantiation, so the value for ``T::number`` is known.
11131113
}];
11141114
}
11151115

1116+
def ExtVectorTypeDocs : Documentation {
1117+
let Category = DocCatFunction;
1118+
let Content = [{
1119+
The ext_vector_type(N) attribute specifies that a type is a vector with N
1120+
elements, directly mapping to an LLVM vector type. Originally from OpenCL, it
1121+
allows element access the array subscript operator ``[]``, ``sN`` where ``N`` is
1122+
a hexadecimal value, or ``x``, ``y``, ``z``, ``w`` for graphics-style indexing.
1123+
This attribute enables efficient SIMD operations and is usable in
1124+
general-purpose code.
1125+
1126+
.. code-block:: c++
1127+
1128+
template <typename T, uint32_t N>
1129+
constexpr T simd_reduce(T [[clang::ext_vector_type(N)]] v) {
1130+
static_assert((N & (N - 1)) == 0, "N must be a power of two");
1131+
if constexpr (N == 1) {
1132+
return v[0];
1133+
} else {
1134+
T [[clang::ext_vector_type(N / 2)]] reduced = v.hi + v.lo;
1135+
return simd_reduce(reduced);
1136+
}
1137+
}
1138+
1139+
The vector type also supports swizzling up to sixteen elements. This can be done
1140+
using the object accessors. The OpenCL documentation lists the full list of
1141+
accepted values.
1142+
.. code-block:: c++
1143+
1144+
using f16_x16 = _Float16 __attribute__((ext_vector_type(16)));
1145+
1146+
f16_x16 reverse(f16_x16 v) { return v.sfedcba9876543210; }
1147+
1148+
See the OpenCL documentation for some more complete examples.
1149+
}];
1150+
}
1151+
11161152
def DiagnoseIfDocs : Documentation {
11171153
let Category = DocCatFunction;
11181154
let Content = [{

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1191,7 +1191,8 @@ static void handleTestTypestateAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
11911191

11921192
static void handleExtVectorTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
11931193
// Remember this typedef decl, we will need it later for diagnostics.
1194-
S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
1194+
if (isa<TypedefNameDecl>(D))
1195+
S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
11951196
}
11961197

11971198
static void handlePackedAttr(Sema &S, Decl *D, const ParsedAttr &AL) {

clang/test/CodeGen/vector.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ void test1(void) {
88
__v4hi x = {1,2,3};
99
__v4hi y = {1,2,3,4};
1010

11+
12+
// CHECK: @z = local_unnamed_addr global <8 x float> zeroinitializer
13+
float z __attribute__((ext_vector_type(8)));
14+
1115
typedef int vty __attribute((vector_size(16)));
1216
int test2(void) { vty b; return b[2LL]; }
1317

@@ -18,9 +22,6 @@ void test3 ( vec4* a, char b, float c ) {
1822
(*a)[b] = c;
1923
}
2024

21-
22-
23-
2425
#include <mmintrin.h>
2526

2627
int test4(int argc, char *argv[]) {

clang/test/CodeGenCUDA/amdgpu-bf16.cu

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,19 +111,15 @@ __device__ __bf16 test_call( __bf16 in) {
111111
// CHECK-NEXT: ret void
112112
//
113113
__device__ void test_vec_assign() {
114-
typedef __attribute__((ext_vector_type(2))) __bf16 bf16_x2;
115-
bf16_x2 vec2_a, vec2_b;
114+
__bf16 [[clang::ext_vector_type(2)]] vec2_a, vec2_b;
116115
vec2_a = vec2_b;
117116

118-
typedef __attribute__((ext_vector_type(4))) __bf16 bf16_x4;
119-
bf16_x4 vec4_a, vec4_b;
117+
__bf16 __attribute__((ext_vector_type(4))) vec4_a, vec4_b;
120118
vec4_a = vec4_b;
121119

122-
typedef __attribute__((ext_vector_type(8))) __bf16 bf16_x8;
123-
bf16_x8 vec8_a, vec8_b;
120+
__bf16 [[clang::ext_vector_type(8)]] vec8_a, vec8_b;
124121
vec8_a = vec8_b;
125122

126-
typedef __attribute__((ext_vector_type(16))) __bf16 bf16_x16;
127-
bf16_x16 vec16_a, vec16_b;
123+
__bf16 __attribute__((ext_vector_type(16))) vec16_a, vec16_b;
128124
vec16_a = vec16_b;
129125
}

clang/test/Sema/types.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ typedef int __attribute__((ext_vector_type(0))) e4; // expected-e
7878
// no support for vector enum type
7979
enum { e_2 } x3 __attribute__((vector_size(64))); // expected-error {{invalid vector element type}}
8080

81-
int x4 __attribute__((ext_vector_type(64))); // expected-error {{'ext_vector_type' attribute only applies to typedefs}}
81+
int x4 __attribute__((ext_vector_type(64)));
8282

8383
typedef __attribute__ ((ext_vector_type(32),__aligned__(32))) unsigned char uchar32;
8484

clang/test/Sema/vector-ast.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang_cc1 %s -verify -ast-dump | FileCheck %s
2+
3+
// expected-no-diagnostics
4+
5+
// CHECK: ExtVectorType {{.*}} 'int __attribute__((ext_vector_type(4)))' 4
6+
// CHECK-NEXT: BuiltinType {{.*}} 'int'
7+
int x __attribute__((ext_vector_type(4)));
8+
using ExtVecType = decltype(x);
9+
10+
// CHECK: FunctionDecl {{.*}} 'int () __attribute__((ext_vector_type(4)))'
11+
int __attribute__((ext_vector_type(4))) foo() { return x; }
12+
// CHECK: CompoundStmt
13+
// CHECK-NEXT: ReturnStmt
14+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int __attribute__((ext_vector_type(4)))' <LValueToRValue>
15+
// CHECK-NEXT: DeclRefExpr {{.*}} 'int __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'x' 'int __attribute__((ext_vector_type(4)))'

0 commit comments

Comments
 (0)