-
Notifications
You must be signed in to change notification settings - Fork 15.7k
[flang][cuda] Emit error when a device actual argument is used in host intrinsic #172914
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
|
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-fir-hlfir Author: Valentin Clement (バレンタイン クレメン) (clementval) ChangesThis can lead to segfault if a device variable is used in a host intrinsic. Emit an error in semantic. Full diff: https://github.com/llvm/llvm-project/pull/172914.diff 7 Files Affected:
diff --git a/flang/include/flang/Semantics/scope.h b/flang/include/flang/Semantics/scope.h
index ecffdb468bf6c..25806fafc689a 100644
--- a/flang/include/flang/Semantics/scope.h
+++ b/flang/include/flang/Semantics/scope.h
@@ -61,7 +61,7 @@ class Scope {
public:
ENUM_CLASS(Kind, Global, IntrinsicModules, Module, MainProgram, Subprogram,
BlockData, DerivedType, BlockConstruct, Forall, OtherConstruct,
- OpenACCConstruct, ImpliedDos, OtherClause)
+ OpenACCConstruct, ImpliedDos, OtherClause, CUFKernelDoConstruct)
using ImportKind = common::ImportKind;
// Create the Global scope -- the root of the scope tree
diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index 1c3477013b559..1ea40bbb43e61 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -46,6 +46,7 @@ const Scope *FindModuleOrSubmoduleContaining(const Scope &);
const Scope *FindModuleFileContaining(const Scope &);
const Scope *FindPureProcedureContaining(const Scope &);
const Scope *FindOpenACCConstructContaining(const Scope *);
+const Scope *FindCUFKernelDoConstructContaining(const Scope *);
const Symbol *FindInterface(const Symbol &);
const Symbol *FindSubprogram(const Symbol &);
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 022b4289b4e7c..2bf1d41e4e449 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -1145,6 +1145,37 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
dummyName, toStr(dummyDataAttr), toStr(actualDataAttr));
}
}
+ // Emit an error message if an actual argument passed to a host intrinsic is
+ // on the device.
+ if (intrinsic && !FindCUDADeviceContext(scope) &&
+ !FindOpenACCConstructContaining(scope) &&
+ !FindCUFKernelDoConstructContaining(scope)) {
+ if (intrinsic->name != "__builtin_c_f_pointer" &&
+ intrinsic->name != "__builtin_c_loc") {
+ std::optional<common::CUDADataAttr> actualDataAttr;
+ if (const auto *actualObject{actualLastSymbol
+ ? actualLastSymbol->detailsIf<ObjectEntityDetails>()
+ : nullptr}) {
+ actualDataAttr = actualObject->cudaDataAttr();
+ }
+ if (actualDataAttr && *actualDataAttr == common::CUDADataAttr::Device) {
+ // Allocatable or pointer with device attribute have their descriptor in
+ // managed memory. It is allowed to pass them to some inquiry
+ // intrinsics.
+ if (!actualLastSymbol || !IsAllocatableOrPointer(*actualLastSymbol) ||
+ (IsAllocatableOrPointer(*actualLastSymbol) &&
+ intrinsic->name != "size" && intrinsic->name != "lbound" &&
+ intrinsic->name != "ubound" && intrinsic->name != "shape" &&
+ intrinsic->name != "allocated" &&
+ intrinsic->name != "associated" && intrinsic->name != "kind" &&
+ intrinsic->name != "present")) {
+ messages.Say(
+ "Actual argument %s associated with host intrinsic %s is on the device"_err_en_US,
+ actualLastSymbol->name(), intrinsic->name);
+ }
+ }
+ }
+ }
// Warning for breaking F'2023 change with character allocatables
if (intrinsic && dummy.intent != common::Intent::In) {
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 345a0e4e8ecce..a7c5d5c3ca317 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1081,6 +1081,8 @@ class DeclarationVisitor : public ArraySpecVisitor,
bool Pre(const parser::SaveStmt &);
bool Pre(const parser::BasedPointer &);
void Post(const parser::BasedPointer &);
+ bool Pre(const parser::CUFKernelDoConstruct &);
+ void Post(const parser::CUFKernelDoConstruct &);
void PointerInitialization(
const parser::Name &, const parser::InitialDataTarget &);
@@ -9257,6 +9259,15 @@ void DeclarationVisitor::LegacyDataInitialization(const parser::Name &name,
}
}
+bool DeclarationVisitor::Pre(const parser::CUFKernelDoConstruct &x) {
+ PushScope(Scope::Kind::CUFKernelDoConstruct, nullptr);
+ return true;
+}
+
+void DeclarationVisitor::Post(const parser::CUFKernelDoConstruct &x) {
+ PopScope();
+}
+
void ResolveNamesVisitor::HandleCall(
Symbol::Flag procFlag, const parser::Call &call) {
common::visit(
diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index cf1e5e7d44565..c1d7c288d27f7 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -122,6 +122,14 @@ const Scope *FindOpenACCConstructContaining(const Scope *scope) {
: nullptr;
}
+const Scope *FindCUFKernelDoConstructContaining(const Scope *scope) {
+ return scope ? FindScopeContaining(*scope,
+ [](const Scope &s) {
+ return s.kind() == Scope::Kind::CUFKernelDoConstruct;
+ })
+ : nullptr;
+}
+
// 7.5.2.4 "same derived type" test -- rely on IsTkCompatibleWith() and its
// infrastructure to detect and handle comparisons on distinct (but "same")
// sequence/bind(C) derived types
diff --git a/flang/test/Lower/CUDA/cuda-data-transfer.cuf b/flang/test/Lower/CUDA/cuda-data-transfer.cuf
index 015947430b07c..e0c23a1d5df8f 100644
--- a/flang/test/Lower/CUDA/cuda-data-transfer.cuf
+++ b/flang/test/Lower/CUDA/cuda-data-transfer.cuf
@@ -22,6 +22,15 @@ module mod1
end function
end interface
+ interface
+ function somefunction(d, n)
+ integer :: n
+ real(8), device :: d(n,n)
+ real(8) :: somefunction(n)
+ end function
+ end interface
+
+
contains
function dev1(a)
integer, device :: a(:)
@@ -447,9 +456,10 @@ end subroutine
! CHECK: cuf.data_transfer
subroutine sub23(n)
+ use mod1
integer :: n
real(8), device :: d(n,n), x(n)
- x = sum(d,dim=2) ! Was triggering Unsupported CUDA data transfer
+ x = somefunction(d,2) ! Was triggering Unsupported CUDA data transfer
end subroutine
! CHECK-LABEL: func.func @_QPsub23
diff --git a/flang/test/Semantics/cuf23.cuf b/flang/test/Semantics/cuf23.cuf
index 8c03c18d9b0db..73f13d1d46a17 100644
--- a/flang/test/Semantics/cuf23.cuf
+++ b/flang/test/Semantics/cuf23.cuf
@@ -53,3 +53,10 @@ attributes(global) subroutine global_with_block()
print*, a ! ok
end block
end subroutine
+
+subroutine intrinsic_error(n)
+ integer :: n
+ real(8), device :: d(n,n), x(n)
+!ERROR: Actual argument d associated with host intrinsic sum is on the device
+ x = sum(d,dim=2)
+end subroutine
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
ergawy
left a comment
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.
LGTM! Thanks for taking care of my comment.
…ment is used in host intrinsic" (#174019) Reverts llvm/llvm-project#172914
…t intrinsic (llvm#172914) This can lead to segfault if a device variable is used in a host intrinsic. Emit an error in semantic.
…t intrinsic (llvm#172914) This can lead to segfault if a device variable is used in a host intrinsic. Emit an error in semantic.
…t intrinsic (llvm#172914) This can lead to segfault if a device variable is used in a host intrinsic. Emit an error in semantic.
…t intrinsic (llvm#172914) This can lead to segfault if a device variable is used in a host intrinsic. Emit an error in semantic.
…d in host intrinsic" (llvm#174019) Reverts llvm#172914
…t intrinsic (llvm#174025) This can lead to segfault if a device variable is used in a host intrinsic. Emit an error in semantic. Reland llvm#172914 with the addition of `__builtin_c_devloc `, `loc` and `present` as skipped intrinsic
This can lead to segfault if a device variable is used in a host intrinsic. Emit an error in semantic.