Skip to content
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

[SYCL] Support or diagnose use of namespace std types as kernel type names #1963

Merged
merged 21 commits into from
Sep 14, 2020
Merged

[SYCL] Support or diagnose use of namespace std types as kernel type names #1963

merged 21 commits into from
Sep 14, 2020

Conversation

jtmott-intel
Copy link
Contributor

This is a continuation of #1579. Sorry I couldn't commit to the branch named in that PR.

This PR has premanandrao's original commit plus one of mine to address the comments in 1579 -- specifically this conversation.

I removed the changes to the generated header and added a diagnostic to make nullptr_t in kernel names an error. It's possible to make nullptr_t work like int works, but sounds like we don't want to encourage using builtin types as kernel names. The diagnostic message is open to wordsmithing.

premanandrao and others added 3 commits April 23, 2020 12:23
…names

When std::nullptr_t is used as a kernel type, the generated
integration header uses 'nullptr_t'.  This causes lookup
errors.  Use 'std::nullptr_t' instead.

std::max_align_t is defined (in one implementation) as a typedef
of an anonymous struct.  This causes errors when attempting to
forward declare the type in the integration header.  Diagnose
such cases earlier.

Signed-off-by: Premanand M Rao <premanand.m.rao@intel.com>
# Conflicts:
#	clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10835,6 +10835,7 @@ def err_sycl_kernel_incorrectly_named : Error<
"kernel %select{name is missing"
"|needs to have a globally-visible name"
"|name is invalid. Unscoped enum requires fixed underlying type"
"|name cannot be or use std::nullptr_t"
Copy link
Contributor

Choose a reason for hiding this comment

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

Just wondering, why we disallow only nullptr_t?
Your PR message says " sounds like we don't want to encourage using builtin types as kernel names. "

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nullptr_t is special because builtin type names are (typically) accessible without a header, but nullptr_t is a builtin type that isn't known by any name until we include a header (or forward declare). The "don't want to encourage using builtins" comes from rolandschulz's comment -- "Adding extra support for std types is not needed," and, "there is no promise that std types work as lambda name." But I may have misinterpreted his comments, and others asking him for clarification.

Comment on lines 1900 to 1901
Diag.Report(KernelLocation, diag::err_sycl_kernel_incorrectly_named)
<< /* kernel name is missing */ 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

I spend some time looking into these changes, and I don't get why we didn't start emitting "kernel name is missing" on each unnamed lambda, because before your changes this diagnostic was under if (!UnnamedLambdaSupport) and it looked correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The original "if" was if (TD && !UnnamedLambdaSupport), and when this evaluates false, then the else block would still use TD anyway -- which seems weird. premanandrao's commit refactored the TD check out to if (!TD) break;

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm still a bit confused about this change. Can you give an example where if (TD) evaluates true and KernelNameIsMissing i.e. TD does not have a name?

Also, this change is not technically required for 'std' namespace check right? Or am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this happens when it is invalid.
It is not needed strictly for the specific 'std' namespace check, but it occurs in those contexts too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Normally the if (TD) check would ensure that a kernel name type is a TagDecl -- that is, one of a struct/union/class/enum -- which would catch kernel name types such as int. I say "normally", though, because earlier in the call stack, we also ensure that a kernel name type is a CXXRecordDecl -- that is, one of a struct/union/class. Which means, sadly, that the if (TD) part may actually be dead code. But, it was dead code even before, and independent of, this PR. I had considered doing a clean-up of the existing code, but... I feel like this PR has already exceed its side-quest quota. :-)

Copy link
Contributor Author

@jtmott-intel jtmott-intel Sep 10, 2020

Choose a reason for hiding this comment

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

Yes this is part of what's being checked in, but the original had dead code too, and this part just moves the dead code a couple lines over.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. In that case, I don't mind this being addressed in a separate PR.

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 then sounds like we're opting to not revert the April refactoring? And this PR would stay as is?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems like folks still aren't comfortable with those changes, and since they come from an older time in this PR and don't seem to be needed anymore, I pushed a commit to revert that bit of refactoring. Buildbot is running. I'll ping folks when ready for re-review approvals.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The changes @elizabethandrews was concerned about are reverted. All checks passed. Need review approvals again. @premanandrao @rbegam

@erichkeane
Copy link
Contributor

I disagree with this approach. While Roland's comment is 'Because there is no promise that std types work as lambda name', that only applies as the top level item. a kernel named

<std::string>

SHOULD be illegal, if we're going to implement Roland's comment, we should cover EVERY type in std.

However,

<SomeTemplate<std::string>>
or
<SomeTemplate<std::nullptr_t>>

the std type is NOT the kernel name, an instance of SomeTemplate is. We should have to support this case.

I believe we'd discussed before that we should just serialize std::nullptr_t as decltype(nullptr) to make this work.

@premanandrao
Copy link
Contributor

I disagree with this approach. While Roland's comment is 'Because there is no promise that std types work as lambda name', that only applies as the top level item. a kernel named

<std::string>

SHOULD be illegal, if we're going to implement Roland's comment, we should cover EVERY type in std.

However,

<SomeTemplate<std::string>>
or
<SomeTemplate<std::nullptr_t>>

the std type is NOT the kernel name, an instance of SomeTemplate is. We should have to support this case.

I believe we'd discussed before that we should just serialize std::nullptr_t as decltype(nullptr) to make this work.

Agreed with the second part - only top-level should be disallowed.
About the first part - did Roland mean 'all' std types or just the fundamental ones like size_t, ptrdiff_t etc.?

@erichkeane
Copy link
Contributor

I disagree with this approach. While Roland's comment is 'Because there is no promise that std types work as lambda name', that only applies as the top level item. a kernel named

<std::string>

SHOULD be illegal, if we're going to implement Roland's comment, we should cover EVERY type in std.
However,

<SomeTemplate<std::string>>
or
<SomeTemplate<std::nullptr_t>>

the std type is NOT the kernel name, an instance of SomeTemplate is. We should have to support this case.
I believe we'd discussed before that we should just serialize std::nullptr_t as decltype(nullptr) to make this work.

Agreed with the second part - only top-level should be disallowed.
About the first part - did Roland mean 'all' std types or just the fundamental ones like size_t, ptrdiff_t etc.?

I read it as 'all'... @rolandschulz can you clarify?

@jtmott-intel
Copy link
Contributor Author

While we wait for clarification, just adding a couple notes:

  • If we use the decltype(nullptr) trick, then std::nullptr_t would work for *both* the top-level kernel name and as a template parameter.
  • Some types may never work, not even as template parameters, such as <SomeTemplate<std::max_align_t>>, because max_align_t is an anonymous struct. The issue isn't whether it's the top-level kernel name or template parameter. The issue is can we write it out as textual source to the integration header, and that complication isn't limited to std types.

@rolandschulz
Copy link
Contributor

Yes I meant all std types. Only types which can be forward declared have to be supported and it isn't valid to forward declare std types.

@erichkeane
Copy link
Contributor

* Some types may never work, not even as template parameters, such as `<SomeTemplate<std::max_align_t>>`, because max_align_t is an anonymous struct. The issue isn't whether it's the top-level kernel name or template parameter. The issue is can we write it out as textual source to the integration header, and that complication isn't limited to std types.

This point here is particularly annoying... @rolandschulz : what clarification to the SYCL spec needs to me made to allow us to prevent ANY use of namespace-std in kernel names? Or do you and @mkinsner / @jbrodman /etc already feel that is the case?

@rolandschulz
Copy link
Contributor

For the implementation we should just assume that it's OK that nothing in std is allowed. This is clearly the intention. If someone thinks this needs to be clarified in the spec even for 1.2.1 not just upcoming SYCL we can do that.

@jtmott-intel
Copy link
Contributor Author

One of the relevant use cases seems to be a kernel inside a function template, because the function template parameters get reused in the kernel name to keep each name type unique. We do this ourselves in the SYCL handler "fill" function template. The value type to fill is a parameter that gets reused in the kernel name. If we call fill with a std::complex number, then if the kernel rejects it, fill rejects it.

@jtmott-intel
Copy link
Contributor Author

Latest commit disallows names from std namespace. std::nullptr_t is still special cased since it resolves to a builtin instead of a decl.

@jtmott-intel jtmott-intel requested a review from a team as a code owner July 10, 2020 17:48
@jtmott-intel jtmott-intel requested a review from rbegam July 10, 2020 17:48
# Conflicts:
#	sycl/test/sub_group/reduce.cpp
#	sycl/test/sub_group/scan.cpp
@bader
Copy link
Contributor

bader commented Jul 15, 2020

@jtmott-intel, please, resolve CI failures.

@jtmott-intel
Copy link
Contributor Author

All checks have passed.

Here's a quick re-summary.

Originally we were going to emit an error diagnostic for kernel names with std::nullptr_t. That type was never guaranteed to work as a kernel name, and indeed the integration header wasn't generating correctly for that type.

Later we decided to disallow all std types, since the standard doesn't allow us to forward declare anything in std. If ever a std type appeared to work in a kernel name, it's because the dragons were merciful.

After implementing this change, several tests broke because they were (indirectly) using std types in their kernel names. Most of those occurrences were a kernel inside a template, because the template needs different kernel names for each generated specialization, and when we re-purposed the template's parameters for the kernel name, then any std type passed to the template also ended up in the name.

// example, before this PR
template<typename T> void test() {
    ...
    cgh.parallel_for<KernelName<T>>( ...
    ...
}
test<std::nullptr_t>();       // bad, std::nullptr_t indirectly used in kernel name
test<std::complex<double>>(); // bad, std::complex indirectly used in kernel name

I updated the impacted tests and made the kernel name its own distinct template parameter so we wouldn't need to re-purpose the other parameters anymore.

// example, after this PR
template<typename SpecializationKernelName, typename T> void test() {
    ...
    cgh.parallel_for<SpecializationKernelName>( ...
    ...
}
test<class SpecializationKernelName_ABC, std::nullptr_t>();       // ok, kernel name and std::nullptr_t are separate
test<class SpecializationKernelName_XYZ, std::complex<double>>(); // ok, kernel name and std::complex are separate

This does, however, put more responsibility on the user to pass unique kernel names. If they don't, then existing diagnostics will already tell them.

@bader
Copy link
Contributor

bader commented Jul 16, 2020

This is a continuation of #1579. Sorry I couldn't commit to the branch named in that PR.

Please, close #1579 if you are not going to merge it.

@erichkeane
Copy link
Contributor

Lambda names are required in SYCL 1.2.1 but not in DPC++ or SYCL 2020 provisional. For the later the extension should be enabled by default. Also note that SYCL 1.2.1 doesn't require diagnostic for missing lambda names. Therefore in theory we could always enable the extension. But it would be good to have a warning for the users in SYCL 1.2.1 mode for them to know this isn't portable if they don't provide a lambda name. But such a diagnostic could be done independent of our implementation using the string representation (as we do for the extension) rather than the type (as we do without the extension).

I see, thanks for the update! So we COULD still enable unnamed lambdas in SYCL 2020 mode.

That said, we should still have the prohibition on std types in 1.2.1 mode. I believe the enabling unnamed lambdas in 2020 mode is orthogonal to this patch, so I'd think we want to do that as a separate patch.

# Conflicts:
#	clang/test/SemaSYCL/unnamed-kernel.cpp
#	sycl/test/group-algorithm/exclusive_scan.cpp
#	sycl/test/group-algorithm/inclusive_scan.cpp
#	sycl/test/group-algorithm/reduce.cpp
#	sycl/test/reduction/reduction_ctor.cpp
#	sycl/test/reduction/reduction_nd_conditional.cpp
#	sycl/test/reduction/reduction_nd_ext_type.hpp
#	sycl/test/reduction/reduction_nd_s0_dw.cpp
#	sycl/test/reduction/reduction_nd_s0_rw.cpp
#	sycl/test/reduction/reduction_nd_s1_dw.cpp
#	sycl/test/reduction/reduction_nd_s1_rw.cpp
#	sycl/test/reduction/reduction_placeholder.cpp
#	sycl/test/reduction/reduction_transparent.cpp
#	sycl/test/reduction/reduction_usm.cpp
#	sycl/test/sub_group/generic-shuffle.cpp
#	sycl/test/sub_group/reduce.hpp
#	sycl/test/sub_group/scan.hpp
@jtmott-intel
Copy link
Contributor Author

Hi, @bader . Any chance this PR is having a problem with the Windows buildbots? There's no significant code changes since the last "all checks passed". The specific tests that fail can be different on each run -- sometimes it's reduction/reduction_transparent.cpp, sometimes it's host-interop-task/interop-task.cpp -- but it's always Windows-only. And I haven't been able to reproduce the failures locally.

@romanovvlad
Copy link
Contributor

Hi, @bader . Any chance this PR is having a problem with the Windows buildbots? There's no significant code changes since the last "all checks passed". The specific tests that fail can be different on each run -- sometimes it's reduction/reduction_transparent.cpp, sometimes it's host-interop-task/interop-task.cpp -- but it's always Windows-only. And I haven't been able to reproduce the failures locally.

The test is flaky, we disabled it on windows. Could you please merge your branch with the latest sycl branch?

@jtmott-intel
Copy link
Contributor Author

@romanovvlad After the latest merge from sycl, I'm getting a Windows-only error for sycl/test/reduction/reduction_transparent.cpp and reduction_usm.cpp. They're returning exit code 3221226505 and no output on stdout or stderr. I'm not familiar with that exit code but googling suggests it's a generic "Internal process error" coming from Windows. I can keep investigating but I wanted to check if this a buildbot issue?

@romanovvlad
Copy link
Contributor

@romanovvlad After the latest merge from sycl, I'm getting a Windows-only error for sycl/test/reduction/reduction_transparent.cpp and reduction_usm.cpp. They're returning exit code 3221226505 and no output on stdout or stderr. I'm not familiar with that exit code but googling suggests it's a generic "Internal process error" coming from Windows. I can keep investigating but I wanted to check if this a buildbot issue?

I have not seen this fails before. @vladimirlaz @tfzhu have you seen this issue in other PRs?
@jtmott-intel Are you sure that this issue is not introduced by your patch?

@jtmott-intel
Copy link
Contributor Author

@romanovvlad This PR does touch the two failing tests, but I also got an "all checks passed" earlier, and since then I've only merged from sycl branch. I've looked over the changes to those files character by character, and everything still looks just as right as when all checks passed. None of the changes are OS-specific. And I've tried to reproduce the failure locally but can't reproduce.

@romanovvlad
Copy link
Contributor

@romanovvlad This PR does touch the two failing tests, but I also got an "all checks passed" earlier, and since then I've only merged from sycl branch. I've looked over the changes to those files character by character, and everything still looks just as right as when all checks passed. None of the changes are OS-specific. And I've tried to reproduce the failure locally but can't reproduce.

I've checked several other failing pre-commits on windows and I do not see these test failing.
Your patch may introduce sporadic failure.

@jtmott-intel
Copy link
Contributor Author

All checks passed! Sorry, folks. Yes this latest problem was my fault. I made a mistake in a merge resolution and used the same kernel name twice. I didn't feel good about using a PR to troubleshoot the issue, but I couldn't reproduce it any other way, so I finally used a separate dummy PR to narrow down where the problem was coming from, and -- I'm happy to say it's fixed now. Final approval and merge may commence. I assume folks will prefer a squash merge for this one? :-)

@romanovvlad @elizabethandrews @premanandrao

premanandrao
premanandrao previously approved these changes Sep 10, 2020
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.

@jtmott-intel, I don't see any major changes since I last reviewed this. The set of changes look good to me.

@elizabethandrews, @Fznamznon, okay with you?

@jtmott-intel
Copy link
Contributor Author

jtmott-intel commented Sep 10, 2020

I see @premanandrao 's approval, but github now appears to be blocking because it's waiting on an approval from someone in the intel/llvm-reviewers-runtime team. @romanovvlad @rbegam ?

rbegam
rbegam previously approved these changes Sep 10, 2020
Copy link
Contributor

@rbegam rbegam left a comment

Choose a reason for hiding this comment

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

LGTM

…el type names"

This reverts commit 46c54c6.

# Conflicts:
#	clang/test/CodeGenSYCL/stdtypes_kernel_type.cpp
#	clang/test/SemaSYCL/unnamed-kernel.cpp
@jtmott-intel jtmott-intel dismissed stale reviews from rbegam and premanandrao via 8d0087e September 11, 2020 16:56
Copy link
Contributor

@elizabethandrews elizabethandrews left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks!

Can you file a GitHub issue to look into the dead code so we don't forget about it?

@jtmott-intel
Copy link
Contributor Author

The base branch restricts merging to authorized users -- and apparently I'm not an authorized user. :-) Maybe @premanandrao or @elizabethandrews can one of you click the merge button for me?

@bader bader merged commit dd7fec8 into intel:sycl Sep 14, 2020
@elizabethandrews
Copy link
Contributor

The base branch restricts merging to authorized users -- and apparently I'm not an authorized user. :-) Maybe @premanandrao or @elizabethandrews can one of you click the merge button for me?

We're not authorized to either :) I see @bader already merged your commit but FYI, @bader and @pvchupin have merge rights.

@jtmott-intel jtmott-intel deleted the remote_fwd_decl_namespace branch September 14, 2020 14:54
@jtmott-intel jtmott-intel restored the remote_fwd_decl_namespace branch September 15, 2020 16:32
aelovikov-intel pushed a commit to aelovikov-intel/llvm that referenced this pull request Mar 27, 2023
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.

9 participants