-
Notifications
You must be signed in to change notification settings - Fork 769
[SYCL] Re-use OpenCL address space attributes for SYCL #1039
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,11 +33,6 @@ static const unsigned SPIRAddrSpaceMap[] = { | |
0, // cuda_device | ||
0, // cuda_constant | ||
0, // cuda_shared | ||
1, // sycl_global | ||
3, // sycl_local | ||
2, // sycl_constant | ||
0, // sycl_private | ||
4, // sycl_generic | ||
0, // ptr32_sptr | ||
0, // ptr32_uptr | ||
0 // ptr64 | ||
|
@@ -53,11 +48,6 @@ static const unsigned SYCLAddrSpaceMap[] = { | |
0, // cuda_device | ||
0, // cuda_constant | ||
0, // cuda_shared | ||
1, // sycl_global | ||
3, // sycl_local | ||
2, // sycl_constant | ||
0, // sycl_private | ||
4, // sycl_generic | ||
0, // ptr32_sptr | ||
0, // ptr32_uptr | ||
0 // ptr64 | ||
|
@@ -70,11 +60,9 @@ class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo { | |
TLSSupported = false; | ||
VLASupported = false; | ||
LongWidth = LongAlign = 64; | ||
if (Triple.getEnvironment() == llvm::Triple::SYCLDevice) { | ||
AddrSpaceMap = &SYCLAddrSpaceMap; | ||
} else { | ||
AddrSpaceMap = &SPIRAddrSpaceMap; | ||
} | ||
AddrSpaceMap = (Triple.getEnvironment() == llvm::Triple::SYCLDevice) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like an unrelated change. A good one, just not related. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure how to interpret this... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, sorry for not being clear. I guess the answer is: It depends on where this lands. I'd rather you do a separate commit for this formatting change here, but if you're submitting to llvm community, I'd rather the ternary version just be part of the patch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This patch is to SYCL project. WRT using different address space map for SYCL. I don't know if we break anything by mapping "default" address space to "4", which SPIR-V converter interprets as generic. It might that other programming models targeting SPIR rely on existing mapping. Tagging other SYCL implementers: @Naghasan, @keryell, @illuhad, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having lang address space in target information seems strange. Ideally the IR should be emitted as language agnostic as possible. What are you trying to achieve with this separate address space map? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm trying to map "pointer w/o address space qualifiers" to "generic" address space. Currently it's mapped to "private", which doesn't seems right. As mentioned in the previous comment if all other languages do not rely on that behavior, I can remove "language dependent" customization. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well OpenCL 2.0 does exactly the same. All pointer are in generic address space. Why don't you just add generic on AST while parsing the types? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @erichkeane answered this in this comment: https://github.com/intel/llvm/pull/1039/files#r370236039. |
||
? &SYCLAddrSpaceMap | ||
: &SPIRAddrSpaceMap; | ||
UseAddrSpaceMapMangling = true; | ||
HasLegalHalfType = true; | ||
HasFloat16 = true; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,8 +31,8 @@ __kernel void test_qual() { | |
//CHECK: |-CXXMethodDecl {{.*}} constexpr operator() 'void () const __generic' | ||
auto priv2 = []() __generic {}; | ||
priv2(); | ||
auto priv3 = []() __global {}; //expected-note{{candidate function not viable: 'this' object is in address space '__private', but method expects object in address space '__global'}} //expected-note{{conversion candidate of type 'void (*)()'}} | ||
priv3(); //expected-error{{no matching function for call to object of type}} | ||
auto priv3 = []() __global {}; //ex pected-note{{candidate function not viable: 'this' object is in address space '__private', but method expects object in address space '__global'}} //ex pected-note{{conversion candidate of type 'void (*)()'}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is happening here? The change to expected disables these tests, right? We dont want that, do we? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm not sure. I hope Anastasia can help to understand. #1039 (review).
Yes.
I'd like to understand why this patch affected the test and fix either the test or OpenCL mode. |
||
priv3(); //ex pected-error{{no matching function for call to object of type}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @AnastasiaStulova, I'd like to check with you if this is a bug in C++ for OpenCL compiler or not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain why you think this is a bug? In OpenCL all local variables are deduced to be in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the issue might be due to your downstream change in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It doesn't seem to work as you described if address space is deduced correctly, the mismatch will still be reported. It looks like compiler relies somehow on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sorry what doesn't work as I describe?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you know where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not how lambda parsing works in C++. The initializer is parsed separately and there is no danger of declaring it this way unless it's being called. I would suggest to check the comments on the review too that might help to clarify the topic: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://reviews.llvm.org/D69938 - the discussion started with an assumption that deduced address space for lambda object can be changed to legalize function call operator usages - https://reviews.llvm.org/D69938#1737196, but ended with an open question if it's really possible - https://reviews.llvm.org/D69938#1755709. It's still not clear whether it's the right approach to detect an error at the function call operator use or it should be done for lambda variable declaration. The case where address space of a lambda object is changed to make use of inconsistent declaration is not covered by tests. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright, I dug in. This fail basically happens because It seems that lambdas have predefined conversions to function pointer form:
C++ requres it:
But as you can see from the AST dump this conversion operator converts this lambda to a poiner to a function without address space qualifiers at all, i,e, everything what this function accepts can be in Default address space. Whereas calling operator of such lambda has
I'm not an expert in OpenCL and C++ for OpenCL but, if the philosophy of OpenCL address spaces is qualify ALL types with address space qualifier and if C++ for OpenCL should work like regular C++ for language features like lambdas, I think conversion from lambda object to function pointer must convert to a pointer to a function with the same address space qualifiers as operator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Submitted a bug https://bugs.llvm.org/show_bug.cgi?id=45472 . |
||
|
||
__constant auto const1 = []() __private{}; //expected-note{{candidate function not viable: 'this' object is in address space '__constant', but method expects object in address space '__private'}} //expected-note{{conversion candidate of type 'void (*)()'}} | ||
const1(); //expected-error{{no matching function for call to object of type '__constant (lambda at}} | ||
|
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.
This seems strange. Why do you need this downstream change here?
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.
What are you trying to achieve?
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'd like to avoid adding AS qualifiers to all types and treat all objects of "unqualified" types to be allocated in "generic" address space. This allows us to emit valid SPIR-V files for the SYCL code, which inter-operates regular C++ code satisfying SYCL kernel restrictions.
We qualify with address spaces only types required by the SPIR-V spec (e.g. kernel parameters, program scope variables, etc). All other objects (not qualified explicitly by user via SYCL pointer classes), are residing in "generic" address space. This approach allows us altering C++ type system.
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.
In OpenCL (and other languages too) we do qualifiers deduction during parsing. All pointers without explicit address space are in generic in OpenCL v2.0. I guess you could just do the same.
This function determines qualifier relations regardless of exact type. Also this function should just have the same behaviour as the one above since they are to be used interchangeably. I think we just added this function to allow calling it as a member but it just called the helper. So I don't understand why these two have different logic in your downstream changes. They should return the same result for the same pair of qualifiers.
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.
We have recently changed how deduction works:
https://reviews.llvm.org/D65744
My guess is you just need to alter
deduceOpenCLPointeeAddrSpace
slightly and make sure you invoke it in the same places.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 presume if pointer address space was provided explicitly you would keep it?
What about C++ features that can't be easily supported by OpenCL devices like virtual functions?
I don't see how they appear in CodeGen if you didn't have them in AST at all? I presume you have some address spaces somewhere in AST? Also how about address spaces that can't convert to generic like
constant
. Do you support this?That makes sense. I guess the limitation is if you compile separate translation modules or don't inline function calls then the inference will be limited.
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.
Yes, but the only way to do that is through sycl::multi_ptr (and sycl::accessor, forgot about it) classes. User never writes
We do support function pointers on CPU and GPU as an extension:
https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/SPIRV/SPV_INTEL_function_pointers.asciidoc
Sorry, I should've say this better.
You're correct, some address spaces are present in AST, but they are "hidden" from a user inside C++ classes, so there is no legal way to get their type.
Alloca as I mentioned, is always addrspace(0) from data layout, this address space does not come from AST.
Constant is not fully supported as a raw pointer. It cannot be converted to generic, so if we allow it, then we risk emitting LLVM IR that cannot be lowered to SPIR-V.
Constant can still be used with sycl::multi_ptr and sycl::accessor classes though.
Right. More limitations come if a pointer is stored in memory and then loaded elsewhere.
Unless mem2reg eliminates this store/load, it is difficult to prove anything.
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.
Right this is great! But I was thinking of generic supported by multiple vendors. Does it mean that SYCL will define a new type of devices that it supports i.e. not just any OpenCL device?
I am thinking of some language related aspect that you might miss to diagnose with this strategy. Let's say if user code creates pointers:
loc_ptr1 - pointer to local addr space
loc_ptr2 - pointer to local addr space
glob_ptr - pointer to global addr space
then are they cast to generic (no address space) straight away and then if they appear in the following statement:
loc_ptr1 = somevariable ? loc_ptr2 : glob_ptr;
if you don't have address spaces any more at this point you can't really provide an error saying that the code is likely illegal?
Are you aware of the cases like that and how severe they might be?
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.
Since OpenCL doesn't have this in the core specification, it is hard (impossible?) to provide a solution that works everywhere (with reasonable performance). But the extension is fairly generic, so I guess any vendor interested in this feature can implement it.
Address space qualifiers are not exposed in the SYCL language, so there is no way for a user to create a qualified raw pointer. (unless they use internal attributes directly; nobody should do this)
This is perfectly legal, if you write it without address space qualifiers.
Consider this (not real SYCL code, but close enough):
In LLVM IR this looks like:
Again, this a valid code for a device that supports generic address space. If a device doesn't support it, then compilation terminates (or gives a diagnostic) from the device backend/middle-end compiler (it is not as pretty as the a diagnostic from Clang). Although, for less capable devices, it is probably better to use C++ classes instead of raw pointers where possible.
Control flow, stored/loaded pointers from memory, arrays of pointers in different address spaces. I suspect these cases are pretty common for generic C++ code, and there is a runtime overhead for supporting them. User can optimize them manually (by using sycl::multi_ptr class), or rely on the compiler.
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.
In my original code I didn't use generic pointer. By adding generic you removed the ability to diagnose the behaviour that is illegal i.e. assigning local address space pointer into global.
Even in OpenCL 2.0 compatible devices address spaces are used for performance reasons so developers might want to avoid generic as much as possible. Then it is really helpful to get diagnostics from the compiler as debugging such issues can be very painful to nearly impossible on accelerators.
Ok I generally understand the reasoning behind your design. I just find it a bit unfortunate that you remove address spaces from AST early so you can't benefit from the power of semantical analysis fully. I don't know whether developers will find it valuable that the compiler compiles everything but then they get little help in what goes wrong.