-
Notifications
You must be signed in to change notification settings - Fork 788
[SYCL] Fix FE attribute handling in SYCL_EXTERNAL functions. #1778
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 |
---|---|---|
|
@@ -1460,6 +1460,15 @@ void Sema::MarkDevice(void) { | |
// it is recursive. | ||
MarkDeviceFunction Marker(*this); | ||
Marker.SYCLCG.addToCallGraph(getASTContext().getTranslationUnitDecl()); | ||
|
||
// Iterate through SYCL_EXTERNAL functions and add them to the device decls. | ||
for (const auto &entry : *Marker.SYCLCG.getRoot()) { | ||
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. IIRC, @Fznamznon pointed out that this won't add class member functions, which are marked as 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 wasn't sure about it, so I double checked it locally, seems everything is fine with class members, but we could add a corresponding test in next patches. |
||
if (auto *FD = dyn_cast<FunctionDecl>(entry.Callee->getDecl())) { | ||
if (FD->hasAttr<SYCLDeviceAttr>() && !FD->hasAttr<SYCLKernelAttr>()) | ||
addSyclDeviceDecl(FD); | ||
} | ||
} | ||
|
||
for (Decl *D : syclDeviceDecls()) { | ||
if (auto SYCLKernel = dyn_cast<FunctionDecl>(D)) { | ||
llvm::SmallPtrSet<FunctionDecl *, 10> VisitedSet; | ||
|
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -48,6 +48,17 @@ void bar() { | |||||||
kernel<class kernel_name5>([]() [[cl::intel_reqd_sub_group_size(2)]] { }); | ||||||||
} | ||||||||
|
||||||||
#ifdef TRIGGER_ERROR | ||||||||
// expected-note@+1 {{conflicting attribute is here}} | ||||||||
[[cl::intel_reqd_sub_group_size(2)]] void sg_size2() {} | ||||||||
|
||||||||
// expected-note@+2 {{conflicting attribute is here}} | ||||||||
// expected-error@+1 {{conflicting attributes applied to a SYCL kernel}} | ||||||||
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 diagnostic doesn't seem to be correct, because function it is pointing to is not a SYCL kernel 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 diagnostic seems strange as well, why does it think that sg_size4 and sg_size2 are the same kernel? Should this conflict be diagnosed on a call expression instead? 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.
OK 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.
Why do you think "it think that sg_size4 and sg_size2 are the same kernel" - please elaborate.
This is a question to existing design. I'm not changing anything in the diagnostics mechanism. I'm fixing existing bug where SYCL_EXTERNAL functions were missing in that diagnostics - I add them. 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. From the error message, it says "conflicting attributes applied to a SYCL kernel". From the notes, it specifies attributes on two separate declarations. So by reading the error + notes, it implies that there are two conflicting attributes on a single kernel, yet they are on different functions. 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 error message existed before - I did not invent it, I just used it for SYCL_EXTERNAL function. Do you suggest to fix prior problems? 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. We do this already? We have other conditions where we diagnose an error on a kernel about conflicting attributes, and then point to an attribute on another declaration? 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. Yep. SYCL attributes are propagated from called device function up to the kernel (AFAIK it is spec defined behavior which I find pretty magic), sometimes there are several functions called from kernel and their attribute values can conflict. Diagnosing happens here llvm/clang/lib/Sema/SemaSYCL.cpp Line 1484 in 12d14e8
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. Ah, well, the way we report that is awful. But not needing to be fixed in this patch. Thanks @Fznamznon. The error-message should likely be changed to be more clear about this if anyone ends up getting to it. 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.
Suggested change
|
||||||||
[[cl::intel_reqd_sub_group_size(4)]] __attribute__((sycl_device)) void sg_size4() { | ||||||||
sg_size2(); | ||||||||
} | ||||||||
#endif | ||||||||
|
||||||||
// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name1 | ||||||||
// CHECK: IntelReqdSubGroupSizeAttr {{.*}} 16 | ||||||||
// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name2 | ||||||||
|
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.
Why make this change? Switching to a setVector doesn't seem to help anything here, particularly when we are using it like a vector.
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.
SetVector allows both deduplication and deterministic iteration order. The former is needed because SYCL_EXTERNAL functions can also be called from kernels, in which case addSyclDeviceDecl(FD) on vector would lead to duplicates. The latter is needed for deterministic compiler behavior.
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.
Thanks for clarifying. Can you elaborate the problem better in the pull request message? I still don't have a good hold of the problem you're trying to solve.
Uh oh!
There was an error while loading. Please reload this page.
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.
It is all in the test case I added:
SYCL_EXTERNAL function with reqd_sub_group_size 4 calls a function with reqd_sub_group_size 2. This shoud be an error. Existing implementation detects it only when there is a kernel in place of SYCL_EXTERNAL function, and silently generates incorrect code for SYCL_EXTERNAL.
Uh oh!
There was an error while loading. Please reload this page.
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.
SYCL_EXTERNAL
==__attribute__((sycl_device))
, BTW