-
Notifications
You must be signed in to change notification settings - Fork 787
[Clang] Improve generation of GV for virtual funcs #7449
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
[Clang] Improve generation of GV for virtual funcs #7449
Conversation
@intel/dpcpp-cfe-reviewers @intel/sycl-language-enabling-triage take a look please |
@@ -20,9 +20,9 @@ int main() { | |||
// Struct layout big enough for vtable. | |||
// CHECK: %struct.Struct = type { i32 (...)** } | |||
// VTable: | |||
// CHECK: @_ZTV6Struct = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI6Struct to i8*), i8* bitcast (void (%struct.Struct addrspace(4)*)* @_ZN6Struct3fooEv to i8*)] }, comdat, align 8 | |||
// CHECK: @[[TYPEINFO:.+]] = external global i8* | |||
// CHECK: @_ZTV6Struct = linkonce_odr unnamed_addr constant { [3 x i8*] } { [3 x i8*] [i8* null, i8* bitcast ({ i8 addrspace(4)*, i8* }* @_ZTI6Struct to i8*), i8* bitcast (void (%struct.Struct addrspace(4)*)* @_ZN6Struct3fooEv to i8*)] }, comdat, align 8 |
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.
Sorry, I didn't paid attention to it before. That's going to create a GV the private address space (under the SPIR convention). The SPIR-V translator will map that to Function
storage class, which you can't use outside a function. So AFAIK, the generated SPIR-V won't be valid.
Out of curiosity, is there an extension you are working with here ? That would help to understand if the test is correct.
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.
Out of curiosity, is there an extension you are working with here ? That would help to understand if the test is correct.
We don't have any SYCL-level extensions and for SPIR-V level we have SPV_INTEL_function_pointers
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.
sorry, I meant a SPIR-V extension.
Looking at the function pointer ext, wouldn't this expression
i8* bitcast (void (%struct.Struct addrspace(4)*)* @_ZN6Struct3fooEv to i8*)
be a problem ? You can't cast to generic.
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.
Originally it was a problem described in your first comment - we were receiving function
storage class RTTI global variables and hence llvm-translator crash. Now it fixed because we receiving @_ZTVN10__cxxabiv117__class_type_infoE = external addrspace(1) global ptr addrspace(4)
, but not @_ZTVN10__cxxabiv117__class_type_infoE = external global ptr
.
I believe it's not a problem because applications run successfully.
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 believe it's not a problem because applications run successfully.
well, it is not a problem for a specific stack, which is quite different.
I can see the @[[TYPEINFO:.+]]
was indeed change the way you described it, and I think it make sense. But my comment for _ZTV6Struct
(and _ZTS6Struct
/ _ZTI6Struct
) still stand: this will generate invalid SPIR-V.
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.
i8* bitcast (void (%struct.Struct addrspace(4)*)* @_ZN6Struct3fooEv to i8*)
@Naghasan, here we don't cast from generic to private, we cast a private pointer to one type to private pointer to another type. We have a function pointer void(__generic Struct *)
which we cast to i8*
without changing the address space of that function pointer
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.
You are right, I mixed up a few things in my brain by cross checking the test and the func ptr extension.
So in order to generate void (%struct.Struct addrspace(4)*)* @_ZN6Struct3fooEv
you need to use OpConstantFunctionPointerINTEL
which yield a pointer to storage class CodeSectionINTEL
which you bitcast into a pointer to storage class Function
. This is more what bugged me (I saw this by thinking of the implication of banning cast from generic storage class hence the confusion).
Strictly speaking, SPIR-V doesn't ban casting between storage class (at least I couldn't find wording banning this), which I found very strange (so does others, I'll seek clarification on that point).
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.
So in order to generate void (%struct.Struct addrspace(4)) @_ZN6Struct3fooEv you need to use OpConstantFunctionPointerINTEL which yield a pointer to storage class CodeSectionINTEL which you bitcast into a pointer to storage class Function. This is more what bugged me (I saw this by thinking of the implication of banning cast from generic storage class hence the confusion).
In reality, we haven't implemented CodeSectionINTEL
storage class or at least we haven't allocated a dedicated LLVM IR address space for it. For now it all just works with address spaces which are assigned by default to function pointers
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 haven't implemented CodeSectionINTEL storage class
easy way to not hit the issue :)
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 am okay with the changes.
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.
Sorry, I hope you weren't waiting for my approval.
I still have the concern for the 2 points I highlighted but I think they should be addressed in different patches anyway.
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.
Looks ok to me but please update the commit message to describe the change and why it was required.
} | ||
} | ||
if (!VTable) | ||
VTable = CGM.CreateRuntimeVariable(CGM.DefaultInt8PtrTy, VTableName); |
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.
So instead of global address space you will now create pointer in generic address space?
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 main idea is still preserved - the global variable pointer should be in the global address space:
... = external addrspace(1) global ptr addrspace(4)
And it's ok for us.
Are you good with this commit message?
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 a little confused. Can you explain what this IR means. I know addresspace (1) = global and (4) is generic but what does it mean in here. What is in addresspace (4)?
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.
By the way I don't want to hold up this patch. I'm asking all the questions so I understand something I am not very familiar with. Since you have approvals from other FE code owners, you can merge this
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.
As I understand it, according to https://llvm.org/docs/LangRef.html#global-variables - here (in my example) addresspace (1) is the address space of the global variable, and (4) is the address space of the pointer it declares. @AlexeySachkov am I wrong?
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.
Every global is a pointer in LLVM IR. When you have a pointer as a global variable, you essentially have a pointer to pointer. The top-level address space was incorrectly generated as 0 (private) and that is now fixed. With this patch with have a program-scope variable which is a pointer to generic address space, which in turns contains a pointer to a global address space (that pointer points to actual data somewhere).
Shouldn't we commit this to llvm-project? Are there any dependencies on existing patches, except the test? |
Reduce the code intended to generate valid device code global pointers with global address space in SYCL by introducing a new
DefaultInt8PtrTy
type.