-
Notifications
You must be signed in to change notification settings - Fork 787
[sycl] [clang] Add sycl global var attribute #3746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Normally global variables are disallowed within kernels, but the presence of this new sycl_global_var attribute will cause sema to allow that particular global variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this attribute be wrapped into a predefined macro (e.g. __SYCL_GLOBAL_VAR__
) so, that DPCPP headers will contain the following as guard for the case when attribute isn't supported?
#ifndef __SYCL_GLOBAL_VAR__
#define __SYCL_GLOBAL_VAR__
#endif
Is there a spec for this extension? |
This is to allow for mutable global variable, required for assert feature. See #3461 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of nits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something we expect users to know when to sprinkle in their own code? I'm rather skeptical of these "trust me, I know what I'm doing" kind of attributes that take code which is otherwise ill-formed and make it behave as though it's well-formed.
Clarified attribute name in comment. Co-authored-by: premanandrao <[email protected]>
Tweak docs verbiage. Co-authored-by: Aaron Ballman <[email protected]>
Remove custom heading. Co-authored-by: Aaron Ballman <[email protected]>
|
||
// expected-warning@+1 {{attribute only applies to global variables}} | ||
__attribute__((sycl_global_var)) void F() { | ||
__attribute__((sycl_global_var)) static int StaticLocalVar; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have expected a diagnostic here as a local variable is not a global variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have expected a diagnostic here as a local variable is not a global variable.
This is an interesting question. SYCL spec applies the "global variable" restriction (that it must be const) to variables of static storage duration.
Here: https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#sec:language.restrictions.kernels
and here: https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#subsec:commonAddressSpace
Given this, I wonder if the attribute could be applied to the file-scope static variables to override the restriction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the tests and added the anonymous static union.
The anonymous union is not considered a global (doesn't accept the attribute) and isn't allowed in a kernel.
The static local var, surprisingly, is considered a global and accepts the attribute, though still not allowed in a kernel (because I didn't use the attribute's presence to allow that specific case).
These are interesting results. In my changes, I relied on the pre-defined "GlobalVar" subject list. "GlobalVar" is defined earlier as a Var where the code check S->hasGlobalStorage()
is true.
I'm stepping through code so I can answer why some of these results "have global storage" and some don't.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ultimately, though, this isn't a feature we're expecting external users to use. This is meant to be used by us to enable the assert feature. Perhaps there's a different subject list I can use that applies to fewer things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Returns true for all variables that do not have local storage.
///
/// This includes all global variables as well as static variables declared
/// within a function.
bool hasGlobalStorage() const { return !hasLocalStorage(); }
That's why you get the behavior you're getting (and the name GlobalVar
in Attr.td is awful, IMHO).
Ultimately, though, this isn't a feature we're expecting external users to use. This is meant to be used by us to enable the assert feature. Perhaps there's a different subject list I can use that applies to fewer things?
It doesn't much matter what we expect -- once we expose the attribute, users will use the attribute. This is basically giving users a blessed way to opt-in to using global variables whenever they'd like (I'm not convinced this is a good idea, btw) because we found a use case where we want to do it ourselves. We can give this attribute whatever semantics we'd like, so there may be a more restrictive predicate we can use, but without a design document for the feature as such, I don't really know what the right answer is as a reviewer (I can't go off the SYCL 2020 spec because this attribute is intended specifically to do things the SYCL spec doesn't allow).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Latest commit expands the test to distinguish between user code and system-include code. Currently, the attribute is still allowed to appear in user code, but it won't have any effect. The attribute will only have an effect if it's used from a system header. To disallow the attribute from even appearing in user code, I'll need to figure out how to do a source location check from within a tablegen subject list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the second thought, here is another example:
// sycl.hpp, system header
template <typename T>
struct Struct {
__attribute__((sycl_global_var)) static T Variable;
};
// main.cpp, user's application
struct UserTy {
int X;
int Y;
};
Struct<UserTy> Global;
Is this use-case allowed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would imagine that use case should be allowed -- the declaration of the variable is appropriately marked, the fact that the type comes from a user instantiation shouldn't matter to the attribute's semantics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Latest commit updated with non-simple handler. Also included templates in tests. Struct<UserTy>::StaticMember
would work, but Struct<UserTy> Global;
would not because you can't use a global in the kernel, and you can't apply the attribute to a global in the user's cpp file (only system headers).
Tweak docs verbiage. Co-authored-by: Aaron Ballman <[email protected]>
This is a useful feature for us for our HLS back-end instead of our OpenCL-ish SPIR-df back-end. |
Good questions!
I view this attribute as being akin to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we decided that GlobalVar
was the wrong predicate (it's looking at storage only and we care about declaration context as well) and what we really want is a new kind of subject rather than checking part of the subject in Attr.td and part of it in SemaDeclAttr.cpp.
The SYCL spec hasn't really illuminated me yet, but as far as I understand the idea behind the restriction is that it restricts access based on storage (so a local static variable is disallowed because that has global storage) and something I'm not quite clear on but is either scope or linkage. Here are some code examples to demonstrate what I think should work and give errors (please correct me where I'm wrong), assuming all of this code is within a system header:
#define ATTR __attribute__((sycl_global_var))
ATTR int i; // ok
ATTR static int j; // ok
ATTR extern int k; // ok
namespace N {
ATTR int i; // ok
}
namespace {
ATTR int a; // ok
}
struct S {
ATTR int i; // error
ATTR static int j; // ok
};
void func(ATTR int i /* error */) {
ATTR int l; // error
ATTR static int m; // error
ATTR extern int n; // error
ATTR static constexpr int o = 0; // error
if (ATTR static int p = 0; p == 0) // error
;
}
Assuming I've not gotten anything wrong, then I think the predicate we want is hasGlobalStorage() && !isLocalVarDeclOrParm()
. The first allows it to be applied to a static data member of a class while the second prevents a static local variable.
Paging @erichkeane for a sanity check.
clang/include/clang/Basic/Attr.td
Outdated
let Spellings = [GNU<"sycl_global_var">]; | ||
let Subjects = SubjectList<[GlobalVar], ErrorDiag>; | ||
let LangOpts = [SYCLIsDevice]; | ||
let Documentation = [SYCLGlobalVarDocs]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that this is only usable in system headers, this can go back to being undocumented with a comment about it only being used internally by the SYCL implementation (and the docs can be removed from AttrDocs.td).
The SYCL restriction is because global storage is not something we can properly move across the host/device barrier I think. I think the global-storage restriction for this attribute + the local-variable-or-parm restrction makes sense. |
Thanks for double-checking! @jtmott-intel -- in this case, I think you should add a new subject to Attr.td:
I'm struggling to figure out what a good name is for |
The |
…eader diagnostic message, add parameter test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you!
I'm not authorized to merge. Could someone perform a squash merge? |
FWIW, @bader often presses the magic button automatically once the appropriate reviewers have signed off on it. |
Normally global variables are disallowed within kernels, but the presence of
this new sycl_global_var attribute will cause sema to allow that particular
global variable.