[flang][cuda] Relax semanctic check in cuf kernel and openacc compute constructs (#125750)

Previous patch was too restrictive and didn't take into account cuf
kernels and openacc compute constructs as being device context.
This commit is contained in:
Valentin Clement (バレンタイン クレメン)
2025-02-04 13:10:47 -08:00
committed by GitHub
parent c8ca486573
commit bbc90f899a
3 changed files with 108 additions and 2 deletions

View File

@@ -42,6 +42,7 @@ public:
void Analyze(const parser::AssignmentStmt &);
void Analyze(const parser::PointerAssignmentStmt &);
void Analyze(const parser::ConcurrentControl &);
int deviceConstructDepth_{0};
private:
bool CheckForPureContext(const SomeExpr &rhs, parser::CharBlock rhsSource);
@@ -94,7 +95,7 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
common::LanguageFeature::CUDA)) {
const auto &scope{context_.FindScope(lhsLoc)};
const Scope &progUnit{GetProgramUnitContaining(scope)};
if (!IsCUDADeviceContext(&progUnit)) {
if (!IsCUDADeviceContext(&progUnit) && deviceConstructDepth_ == 0) {
if (Fortran::evaluate::HasCUDADeviceAttrs(lhs) &&
Fortran::evaluate::HasCUDAImplicitTransfer(rhs)) {
context_.Say(lhsLoc, "Unsupported CUDA data transfer"_err_en_US);
@@ -228,6 +229,46 @@ void AssignmentChecker::Enter(const parser::MaskedElsewhereStmt &x) {
void AssignmentChecker::Leave(const parser::MaskedElsewhereStmt &) {
context_.value().PopWhereContext();
}
void AssignmentChecker::Enter(const parser::CUFKernelDoConstruct &x) {
++context_.value().deviceConstructDepth_;
}
void AssignmentChecker::Leave(const parser::CUFKernelDoConstruct &) {
--context_.value().deviceConstructDepth_;
}
static bool IsOpenACCComputeConstruct(const parser::OpenACCBlockConstruct &x) {
const auto &beginBlockDirective =
std::get<Fortran::parser::AccBeginBlockDirective>(x.t);
const auto &blockDirective =
std::get<Fortran::parser::AccBlockDirective>(beginBlockDirective.t);
if (blockDirective.v == llvm::acc::ACCD_parallel ||
blockDirective.v == llvm::acc::ACCD_serial ||
blockDirective.v == llvm::acc::ACCD_kernels) {
return true;
}
return false;
}
void AssignmentChecker::Enter(const parser::OpenACCBlockConstruct &x) {
if (IsOpenACCComputeConstruct(x)) {
++context_.value().deviceConstructDepth_;
}
}
void AssignmentChecker::Leave(const parser::OpenACCBlockConstruct &x) {
if (IsOpenACCComputeConstruct(x)) {
--context_.value().deviceConstructDepth_;
}
}
void AssignmentChecker::Enter(const parser::OpenACCCombinedConstruct &) {
++context_.value().deviceConstructDepth_;
}
void AssignmentChecker::Leave(const parser::OpenACCCombinedConstruct &) {
--context_.value().deviceConstructDepth_;
}
void AssignmentChecker::Enter(const parser::OpenACCLoopConstruct &) {
++context_.value().deviceConstructDepth_;
}
void AssignmentChecker::Leave(const parser::OpenACCLoopConstruct &) {
--context_.value().deviceConstructDepth_;
}
} // namespace Fortran::semantics
template class Fortran::common::Indirection<