-
Notifications
You must be signed in to change notification settings - Fork 769
[SYCL] Wrap pointer fields inside a generated struct #2288
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
Commit 0b2de9e implemented decomposition of kernel parameters of struct type i.e. fields of a struct are now individually passed as separate kernel arguments. This results in an error for pointer fields, violating SYCL spec. Copy of structs with pointers is allowed according to the spec (value of pointer is undefined). This patch fixes this error by wrapping all pointer fields in a 'wrapper_struct'. Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
Why are we doing this? I worry this is going to cause a performance regression. There only should've been an error decomposing structs if the integration header isn't updated to flag the pointers as kind_pointer instead of kind_std_layout. |
clang/lib/Sema/SemaSYCL.cpp
Outdated
RecordDecl *WrapperClass = | ||
SemaRef.getASTContext().buildImplicitRecord("wrapper_class"); |
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.
Please add __
prefix to the class name so this class won't conflict with user-defined classes.
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 there value to making it an anonymous struct? Doesn't seem much value to making it named.
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'm not sure. I can take a look.
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 didn't change this to use anonymous structs. I don't think it makes a difference in terms of functionality/behavior. Personally I feel naming it makes intention clear. I didn't see a problem with LLVM IR. It handles the names as wrapper_class, wrapper_class.0, etc
Can you elaborate on this @jbrodman ?
This change was required because unused pointers in structs were causing an error in the backend when being passed as a direct kernel parameters (after decomposition fields are passed individually. Earlier they were passed inside the struct as a whole). According to the spec, this shouldn't throw an error.
I can look into doing this only for user code where pointers are inside structs, instead of unconditionally doing it for all pointers. That way current USM functionality shouldn't be affected. I think. |
clang/lib/Sema/SemaSYCL.cpp
Outdated
RecordDecl *WrapperClass = | ||
SemaRef.getASTContext().buildImplicitRecord("wrapper_class"); |
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 there value to making it an anonymous struct? Doesn't seem much value to making it named.
At least in the past, pointers in structs tended to be treated as being generic and not global, and I know this was causing all sorts of problems. If we can make sure all the pointers remain global, even in structs, then that's probably ok? |
At the moment, they are yes. Struct decomposition implemented this by 'accident'. |
Ok that's probably a net positive then :) |
There seems to be other issues though. Bunch of USM tests are failing with 'invalid value'. Need to debug this. |
I guess the problem with such pointers and that there are buffers, which runtime can set as kernel arguments, so the solution is to handle them as USM pointers. I expect that runtime just sets host-side pointer value as kernel argument in this case and it should work w/o wrapping the pointer into a struct. Right? Another option - pointer value can be passed in unsigned integer with size == sizeof (pointer type), but it also prevents compiler memory analysis, so it's better to preserve the type. |
Right now those are wrapped in structures as well. From a front-end perspective I don't think we can tell which a USM pointer is vs an invalid pointer, so everything is getting wrapped to avoid the runtime error. I think we can avoid wrapping pointers which are directly captured. That should solve this I think. |
What is "invalid pointer"? I think the compiler assumes that any pointer other than "accessor pointer" is a USM pointer. |
Because in the frontend we cannot distinguish between USM and non-USM pointer (invalid pointer). And unused non-USM pointers inside structs which are now being passed directly as kernel argument (after struct decomposition) is causing an error in backend when it should not(Spec allows pointers inside structs). The proposed solution for this problem was to just wrap all pointers inside a struct and pass them. Upon thinking of this more, I think this is incorrect. We still need to throw an error if an invalid pointer is directly captured. So I'm modifying this patch to not wrap these. |
Only pointer fields i.e. fields of struct type kernel arguments are wrapped. Patch also reverts a few test changes I made in previous commit, and adds a test for integration header generation. Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
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 one https://github.com/intel/llvm/blob/sycl/clang/test/CodeGenSYCL/pointers-in-structs.cpp will likely fail after your change.
Yes it did. I modified the test in this commit. EDIT: 928a7ff |
Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
1. Correct a comment. 2. Renamed test and wrote description for it. 3. Modified test to use headers and changed RUN line.
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.
FE changes LGTM, thanks
@intel/llvm-reviewers-runtime This PR has a runtime test. Could you please review? |
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.
The test looks good.
…2288) The translator failed assertion with V->user_empty() during regularize function when shl i1 or lshr i1 result is used. E.g. %2 = shl i1 %0 %1 store %2, ptr addrspace(1) @G.1, align 1 Instruction shl i1 is converted to lshr i32 which arithmetic have the same behavior. Original commit: KhronosGroup/SPIRV-LLVM-Translator@239fbd4
[NFC] Update documentation to detail match files
Commit 0b2de9e implemented decomposition of kernel parameters
of struct type i.e. fields of a struct are now individually
passed as separate kernel arguments. This results in an error
for pointer fields of the struct, violating SYCL spec. Copy of structs
with pointers is allowed according to the spec (value of pointer is
undefined). This patch fixes this error by wrapping the pointer
fields in a '__wrapper_class' after the decomposition of struct type.
Signed-off-by: Elizabeth Andrews elizabeth.andrews@intel.com