Skip to content

[SYCL] Turn indirectly-callable property into sycl_device attribute #13819

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

AlexeySachkov
Copy link
Contributor

This PR is a part of virtual functions feature being designed in #10540. One aspects of the proposed language specification is to be able to mark functions as device functions using SYCL compile-time properties mechanism.

Compile-time properties are lowered into
[[__sycl_detail__::add_ir_attribute_function()]] attribute and this patch introduces extra processing for the attribute: property names passed to the attribute are analyzed so we can generate other attributes based on those strings.

The only example of such property/attribute pair is indirectly-callable string that indicates that a function with such property should be treated as if it had sycl_device attribute attached to it and we do exactly that implicitly now.

Note that there were changes required to the attribute parsing logic: because we now access its argument way earlier than we used to, that logic had to be improved to be more robust and pass existing SemaSYCL/attr-add-ir-attributes.cpp test.

This PR is a part of virtual functions feature being designed in
intel#10540. One aspects of the proposed language specification is
to be able to mark functions as device functions using SYCL compile-time
properties mechanism.

Compile-time properties are lowered into
`[[__sycl_detail__::add_ir_attribute_function()]]` attribute and this
patch introduces extra processing for the attribute: property names
passed to the attribute are analyzed so we can generate other attributes
based on those strings.

The only example of such property/attribute pair is
`indirectly-callable` string that indicates that a function with such
property should be treated as if it had `sycl_device` attribute attached
to it and we do exactly that implicitly now.

Note that there were changes required to the attribute parsing logic:
because we now access its argument way earlier than we used to, that
logic had to be improved to be more robust and pass existing
`SemaSYCL/attr-add-ir-attributes.cpp` test.
@AlexeySachkov AlexeySachkov requested a review from a team as a code owner May 17, 2024 13:39
@@ -1816,7 +1841,7 @@ def SYCLAddIRAttrCommonMembers : SYCLAddIRAttrMemberCodeHolder<[{
ValueQType->getArrayElementTypeNoTypeQual()
->isIntegralOrEnumerationType())) {
SmallString<10> StrBuffer;
for (unsigned I = 0; I < Value.getArraySize(); ++I) {
for (unsigned I = 0; I < Value.getArrayInitializedElts(); ++I) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for reviewers: this particular change was done to avoid assertion failure within APInt on the following test case:

[[__sycl_detail__::add_ir_attributes_function("Attr1", CEStr)]] void FunctionCEVal2() {}

@@ -1782,7 +1806,8 @@ def SYCLAddIRAttrCommonMembers : SYCLAddIRAttrMemberCodeHolder<[{
NameLValue = NameCE->getAPValueResult();

if (!NameLValue.isLValue())
return std::nullopt;
return getValidAttributeNameAsString(NameLValue, Context,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note for reviewers: this particular change was done to avoid assertion failure due to invalid attribute name (nullopt being returned) on the following test case:

[[__sycl_detail__::add_ir_attributes_function(CEAttrName1, nullptr)]] void FunctionCEName1() {}

Copy link
Contributor

@elizabethandrews elizabethandrews May 20, 2024

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. Why did your change cause this and the test mentioned below to break? I understand getFilteredAttributeNameValuePairs is now called earlier but I don't understand why that causes these specific issues.

Copy link
Contributor Author

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. Why did your change cause this and the test mentioned below to break?

I honestly don't understand that myself. I can do a bit more of a debugging here to see why we see this particular AST and not another. My current guess is that it can be related to evaluation of constexpr variables, i.e. by the time we parse this attribute, we haven't done some processing of CEAttrName1 (due to lazy nature of that processing), but it is always done before we reach CodeGen and therefore we haven't seen this problem before

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I seem to have figured it out. The issue is reproducible even without my changes, it is just hidden by the test without my changes. If you try to compile the following file with plain intel/llvm:

$ cat p.cpp
constexpr const char CEAttrName1[] = "CEAttr1";

__attribute__((sycl_device)) [[__sycl_detail__::add_ir_attributes_function(CEAttrName1, nullptr)]] void FunctionCEName1() {}
$ clang++ -cc1 -fsycl-is-device -fsyntax-only p.cpp
clang++: github.com/intel/llvm/build/tools/clang/include/clang/AST/Attrs.inc:11988: llvm::SmallVector<std::pair<std::__cxx11::basic_strin
g<char>, std::__cxx11::basic_string<char> >, 4> clang::SYCLAddIRAttributesFunctionAttr::getFilteredAttributeNameValuePairs(const std::optional<llvm::SmallSet<
llvm::StringRef, 4> >&, const clang::ASTContext&) const: Assertion `NameStr && "Attribute name is not a valid string."' failed.
PLEASE submit a bug report to https://github.com/intel/llvm/issues and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: ./bin/clang++ -cc1 -fsycl-is-device -fsyntax-only p.cpp
1.      <eof> parser at end of file
2.      p.cpp:3:123: parsing function body 'FunctionCEName1'

Because the test also contains lines that cause compilation errors, we exit early from parsing/handling some of the things and therefore we don't see this assert. With the attribute arguments analysis performed earlier, we always go through that path and any "early exits" due to errors in the code do not help us avoid this issue.

Copy link
Contributor

@premanandrao premanandrao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@smanna12 smanna12 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you for applying the comment.

@AlexeySachkov
Copy link
Contributor Author

Pre-commit on CUDA seem to have failed due to infrastructure reason. Previous run had passed and the only change added since then is a non-functional commit to use '\0' instead of 0 when comparing char literals. I will proceed with merge

@AlexeySachkov AlexeySachkov merged commit 54dd232 into intel:sycl May 22, 2024
@AlexeySachkov
Copy link
Contributor Author

@rdeodhar, FYI: you can probably re-use this infrastructure in free kernel functions extension to avoid the need of using SYCL_EXTERNAL when defining kernel as a plain function

@rdeodhar
Copy link
Contributor

@rdeodhar, FYI: you can probably re-use this infrastructure in free kernel functions extension to avoid the need of using SYCL_EXTERNAL when defining kernel as a plain function

I noticed that some joint matrix tests used add_ir_attributes_function with non-constexpr values for the value part. Then, using getFilteredAttributeNameValuePairs as the primary means of detecting free functions choked over those joint matrix functions. Using SYCL_EXTERNAL as a first filter eliminated those joint matrix functions from being run through getFilteredAttributeNameValuePairs. That is why free functins currently use SYCL_EXTERNAL as the first criterion.

@AlexeySachkov
Copy link
Contributor Author

I noticed that some joint matrix tests used add_ir_attributes_function with non-constexpr values for the value part.

Curious. My understanding is that the attribute is intended to generate LLVM IR, we can't pass anything that can't be evaluated in compile-time to it. Perhaps those tests were hitting cases that I've fixed in this PR with the attribute arguments parsing

@rdeodhar
Copy link
Contributor

Yes, those values should be constexprs. I plan to try again with your fix in place to see if that issue no longer affects free function detection. Otherwise, I will work with the owners of those joint matrix tests to make everything constexpr.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants