Skip to content

Commit bbc90f8

Browse files
authored
[flang][cuda] Relax semanctic check in cuf kernel and openacc compute constructs (llvm#125750)
Previous patch was too restrictive and didn't take into account cuf kernels and openacc compute constructs as being device context.
1 parent c8ca486 commit bbc90f8

File tree

3 files changed

+108
-2
lines changed

3 files changed

+108
-2
lines changed

flang/lib/Semantics/assignment.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class AssignmentContext {
4242
void Analyze(const parser::AssignmentStmt &);
4343
void Analyze(const parser::PointerAssignmentStmt &);
4444
void Analyze(const parser::ConcurrentControl &);
45+
int deviceConstructDepth_{0};
4546

4647
private:
4748
bool CheckForPureContext(const SomeExpr &rhs, parser::CharBlock rhsSource);
@@ -94,7 +95,7 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
9495
common::LanguageFeature::CUDA)) {
9596
const auto &scope{context_.FindScope(lhsLoc)};
9697
const Scope &progUnit{GetProgramUnitContaining(scope)};
97-
if (!IsCUDADeviceContext(&progUnit)) {
98+
if (!IsCUDADeviceContext(&progUnit) && deviceConstructDepth_ == 0) {
9899
if (Fortran::evaluate::HasCUDADeviceAttrs(lhs) &&
99100
Fortran::evaluate::HasCUDAImplicitTransfer(rhs)) {
100101
context_.Say(lhsLoc, "Unsupported CUDA data transfer"_err_en_US);
@@ -228,6 +229,46 @@ void AssignmentChecker::Enter(const parser::MaskedElsewhereStmt &x) {
228229
void AssignmentChecker::Leave(const parser::MaskedElsewhereStmt &) {
229230
context_.value().PopWhereContext();
230231
}
232+
void AssignmentChecker::Enter(const parser::CUFKernelDoConstruct &x) {
233+
++context_.value().deviceConstructDepth_;
234+
}
235+
void AssignmentChecker::Leave(const parser::CUFKernelDoConstruct &) {
236+
--context_.value().deviceConstructDepth_;
237+
}
238+
static bool IsOpenACCComputeConstruct(const parser::OpenACCBlockConstruct &x) {
239+
const auto &beginBlockDirective =
240+
std::get<Fortran::parser::AccBeginBlockDirective>(x.t);
241+
const auto &blockDirective =
242+
std::get<Fortran::parser::AccBlockDirective>(beginBlockDirective.t);
243+
if (blockDirective.v == llvm::acc::ACCD_parallel ||
244+
blockDirective.v == llvm::acc::ACCD_serial ||
245+
blockDirective.v == llvm::acc::ACCD_kernels) {
246+
return true;
247+
}
248+
return false;
249+
}
250+
void AssignmentChecker::Enter(const parser::OpenACCBlockConstruct &x) {
251+
if (IsOpenACCComputeConstruct(x)) {
252+
++context_.value().deviceConstructDepth_;
253+
}
254+
}
255+
void AssignmentChecker::Leave(const parser::OpenACCBlockConstruct &x) {
256+
if (IsOpenACCComputeConstruct(x)) {
257+
--context_.value().deviceConstructDepth_;
258+
}
259+
}
260+
void AssignmentChecker::Enter(const parser::OpenACCCombinedConstruct &) {
261+
++context_.value().deviceConstructDepth_;
262+
}
263+
void AssignmentChecker::Leave(const parser::OpenACCCombinedConstruct &) {
264+
--context_.value().deviceConstructDepth_;
265+
}
266+
void AssignmentChecker::Enter(const parser::OpenACCLoopConstruct &) {
267+
++context_.value().deviceConstructDepth_;
268+
}
269+
void AssignmentChecker::Leave(const parser::OpenACCLoopConstruct &) {
270+
--context_.value().deviceConstructDepth_;
271+
}
231272

232273
} // namespace Fortran::semantics
233274
template class Fortran::common::Indirection<

flang/lib/Semantics/assignment.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ class AssignmentChecker : public virtual BaseChecker {
4545
void Leave(const parser::EndWhereStmt &);
4646
void Enter(const parser::MaskedElsewhereStmt &);
4747
void Leave(const parser::MaskedElsewhereStmt &);
48+
void Enter(const parser::CUFKernelDoConstruct &);
49+
void Leave(const parser::CUFKernelDoConstruct &);
50+
void Enter(const parser::OpenACCBlockConstruct &);
51+
void Leave(const parser::OpenACCBlockConstruct &);
52+
void Enter(const parser::OpenACCCombinedConstruct &);
53+
void Leave(const parser::OpenACCCombinedConstruct &);
54+
void Enter(const parser::OpenACCLoopConstruct &);
55+
void Leave(const parser::OpenACCLoopConstruct &);
4856

4957
private:
5058
common::Indirection<AssignmentContext> context_;

flang/test/Semantics/cuf18.cuf

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,67 @@
1-
! RUN: %python %S/test_errors.py %s %flang_fc1
1+
! RUN: %python %S/test_errors.py %s %flang_fc1 -fopenacc
22

33
subroutine sub1()
44
real, allocatable, device :: a(:)
5+
integer :: i
56

67
!ERROR: Unsupported CUDA data transfer
78
a = a + 10 ! Illegal expression according to 3.4.2
9+
10+
!$cuf kernel do
11+
do i = 1, 10
12+
a(i) = a(i) + 10 ! ok in cuf kernel do
13+
end do
14+
15+
!$acc parallel loop
16+
do i = 1, 10
17+
a(i) = a(i) + 10 ! ok in openacc combined construct
18+
end do
19+
20+
!$acc serial loop
21+
do i = 1, 10
22+
a(i) = a(i) + 10 ! ok in openacc combined construct
23+
end do
24+
25+
!$acc kernels loop
26+
do i = 1, 10
27+
a(i) = a(i) + 10 ! ok in openacc combined construct
28+
end do
29+
30+
!$acc parallel
31+
!$acc loop
32+
do i = 1, 10
33+
a(i) = a(i) + 10 ! ok in nested openacc construct
34+
end do
35+
!$acc end parallel
36+
37+
!$acc kernels
38+
!$acc loop
39+
do i = 1, 10
40+
a(i) = a(i) + 10 ! ok in nested openacc construct
41+
end do
42+
!$acc end kernels
43+
44+
!$acc serial
45+
!$acc loop
46+
do i = 1, 10
47+
a(i) = a(i) + 10 ! ok in nested openacc construct
48+
end do
49+
!$acc end serial
50+
51+
!$acc loop
52+
do i = 1, 10
53+
a(i) = a(i) + 10 ! ok acc loop
54+
end do
55+
56+
!$acc data
57+
58+
do i = 1, 10
59+
!ERROR: Unsupported CUDA data transfer
60+
a(i) = a(i) + 10
61+
end do
62+
63+
!$acc end data
64+
865
end subroutine
966

1067

0 commit comments

Comments
 (0)