-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial support for the align_value attribute
This adds support for the align_value attribute. This attribute is supported by Intel's compiler (versions 14.0+), and several of my HPC users have requested support in Clang. It specifies an alignment assumption on the values to which a pointer points, and is used by numerical libraries to encourage efficient generation of vector code. Of course, we already have an aligned attribute that can specify enhanced alignment for a type, so why is this additional attribute important? The problem is that if you want to specify that an input array of T is, say, 64-byte aligned, you could try this: typedef double aligned_double attribute((aligned(64))); void foo(aligned_double *P) { double x = P[0]; // This is fine. double y = P[1]; // What alignment did those doubles have again? } the access here to P[1] causes problems. P was specified as a pointer to type aligned_double, and any object of type aligned_double must be 64-byte aligned. But if P[0] is 64-byte aligned, then P[1] cannot be, and this access causes undefined behavior. Getting round this problem requires a lot of awkward casting and hand-unrolling of loops, all of which is bad. With the align_value attribute, we can accomplish what we'd like in a well defined way: typedef double *aligned_double_ptr attribute((align_value(64))); void foo(aligned_double_ptr P) { double x = P[0]; // This is fine. double y = P[1]; // This is fine too. } This attribute does not create a new type (and so it not part of the type system), and so will only "propagate" through templates, auto, etc. by optimizer deduction after inlining. This seems consistent with Intel's implementation (thanks to Alexey for confirming the various Intel-compiler behaviors). As a final note, I would have chosen to call this aligned_value, not align_value, for better naming consistency with the aligned attribute, but I think it would be more useful to users to adopt Intel's name. llvm-svn: 218910
- Loading branch information
Hal Finkel
committed
Oct 2, 2014
1 parent
13a6578
commit 1b0d24e
Showing
11 changed files
with
210 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s | ||
|
||
typedef double * __attribute__((align_value(64))) aligned_double; | ||
|
||
void foo(aligned_double x, double * y __attribute__((align_value(32))), | ||
double & z __attribute__((align_value(128)))) { }; | ||
// CHECK: define void @_Z3fooPdS_Rd(double* align 64 %x, double* align 32 %y, double* dereferenceable(8) align 128 %z) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
// RUN: %clang_cc1 -fsyntax-only -verify %s | ||
|
||
typedef double * __attribute__((align_value(64))) aligned_double; | ||
|
||
void foo(aligned_double x, double * y __attribute__((align_value(32)))) { }; | ||
|
||
// expected-error@+1 {{requested alignment is not a power of 2}} | ||
typedef double * __attribute__((align_value(63))) aligned_double1; | ||
|
||
// expected-error@+1 {{requested alignment is not a power of 2}} | ||
typedef double * __attribute__((align_value(-2))) aligned_double2; | ||
|
||
// expected-error@+1 {{attribute takes one argument}} | ||
typedef double * __attribute__((align_value(63, 4))) aligned_double3; | ||
|
||
// expected-error@+1 {{attribute takes one argument}} | ||
typedef double * __attribute__((align_value())) aligned_double3a; | ||
|
||
// expected-error@+1 {{attribute takes one argument}} | ||
typedef double * __attribute__((align_value)) aligned_double3b; | ||
|
||
// expected-error@+1 {{'align_value' attribute requires integer constant}} | ||
typedef double * __attribute__((align_value(4.5))) aligned_double4; | ||
|
||
// expected-warning@+1 {{'align_value' attribute only applies to a pointer or reference ('int' is invalid)}} | ||
typedef int __attribute__((align_value(32))) aligned_int; | ||
|
||
typedef double * __attribute__((align_value(32*2))) aligned_double5; | ||
|
||
// expected-warning@+1 {{'align_value' attribute only applies to variables and typedefs}} | ||
void foo() __attribute__((align_value(32))); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// RUN: %clang_cc1 -fsyntax-only -verify %s | ||
|
||
typedef double * __attribute__((align_value(64))) aligned_double; | ||
|
||
void foo(aligned_double x, double * y __attribute__((align_value(32))), | ||
double & z __attribute__((align_value(128)))) { }; | ||
|
||
template <typename T, int Q> | ||
struct x { | ||
typedef T* aligned_int __attribute__((align_value(32+8*Q))); | ||
aligned_int V; | ||
|
||
void foo(aligned_int a, T &b __attribute__((align_value(sizeof(T)*4)))); | ||
}; | ||
|
||
x<float, 4> y; | ||
|
||
template <typename T, int Q> | ||
struct nope { | ||
// expected-error@+1 {{requested alignment is not a power of 2}} | ||
void foo(T &b __attribute__((align_value(sizeof(T)+1)))); | ||
}; | ||
|
||
// expected-note@+1 {{in instantiation of template class 'nope<long double, 4>' requested here}} | ||
nope<long double, 4> y2; | ||
|