[flang-commits] [flang] [flang] Refine checks for intrinsic operator conflicts with CUDA defi… (PR #94389)
via flang-commits
flang-commits at lists.llvm.org
Tue Jun 4 12:29:33 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
…ned operators
The checks for conflicts between defined operators/assignments and the intrinsic operators/assignment need to take CUDA procedure and data attributes into account to avoid false positive error messages.
---
Full diff: https://github.com/llvm/llvm-project/pull/94389.diff
2 Files Affected:
- (modified) flang/lib/Semantics/check-declarations.cpp (+43-12)
- (added) flang/test/Semantics/cuf16.cuf (+95)
``````````diff
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 25de9d4af1ffb..bfb38fa1340ec 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -1887,11 +1887,34 @@ void CheckHelper::CheckSpecifics(
helper.Check(generic.owner());
}
+static bool CUDAHostDeviceDiffer(
+ const Procedure &proc, const DummyDataObject &arg) {
+ auto procCUDA{
+ proc.cudaSubprogramAttrs.value_or(common::CUDASubprogramAttrs::Host)};
+ bool procIsHostOnly{procCUDA == common::CUDASubprogramAttrs::Host};
+ bool procIsDeviceOnly{
+ !procIsHostOnly && procCUDA != common::CUDASubprogramAttrs::HostDevice};
+ const auto &argCUDA{arg.cudaDataAttr};
+ bool argIsHostOnly{!argCUDA || *argCUDA == common::CUDADataAttr::Pinned};
+ bool argIsDeviceOnly{(!argCUDA && procIsDeviceOnly) ||
+ (argCUDA &&
+ (*argCUDA != common::CUDADataAttr::Managed &&
+ *argCUDA != common::CUDADataAttr::Pinned &&
+ *argCUDA != common::CUDADataAttr::Unified))};
+ return (procIsHostOnly && argIsDeviceOnly) ||
+ (procIsDeviceOnly && argIsHostOnly);
+}
+
static bool ConflictsWithIntrinsicAssignment(const Procedure &proc) {
- auto lhs{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
- auto rhs{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
- return Tristate::No ==
- IsDefinedAssignment(lhs.type(), lhs.Rank(), rhs.type(), rhs.Rank());
+ const auto &lhsData{std::get<DummyDataObject>(proc.dummyArguments[0].u)};
+ const auto &lhsTnS{lhsData.type};
+ const auto &rhsData{std::get<DummyDataObject>(proc.dummyArguments[1].u)};
+ const auto &rhsTnS{rhsData.type};
+ return !CUDAHostDeviceDiffer(proc, lhsData) &&
+ !CUDAHostDeviceDiffer(proc, rhsData) &&
+ Tristate::No ==
+ IsDefinedAssignment(
+ lhsTnS.type(), lhsTnS.Rank(), rhsTnS.type(), rhsTnS.Rank());
}
static bool ConflictsWithIntrinsicOperator(
@@ -1899,8 +1922,12 @@ static bool ConflictsWithIntrinsicOperator(
if (!kind.IsIntrinsicOperator()) {
return false;
}
- auto arg0{std::get<DummyDataObject>(proc.dummyArguments[0].u).type};
- auto type0{arg0.type()};
+ const auto &arg0Data{std::get<DummyDataObject>(proc.dummyArguments[0].u)};
+ if (CUDAHostDeviceDiffer(proc, arg0Data)) {
+ return false;
+ }
+ const auto &arg0TnS{arg0Data.type};
+ auto type0{arg0TnS.type()};
if (proc.dummyArguments.size() == 1) { // unary
return common::visit(
common::visitors{
@@ -1910,10 +1937,14 @@ static bool ConflictsWithIntrinsicOperator(
},
kind.u);
} else { // binary
- int rank0{arg0.Rank()};
- auto arg1{std::get<DummyDataObject>(proc.dummyArguments[1].u).type};
- auto type1{arg1.type()};
- int rank1{arg1.Rank()};
+ int rank0{arg0TnS.Rank()};
+ const auto &arg1Data{std::get<DummyDataObject>(proc.dummyArguments[1].u)};
+ if (CUDAHostDeviceDiffer(proc, arg1Data)) {
+ return false;
+ }
+ const auto &arg1TnS{arg1Data.type};
+ auto type1{arg1TnS.type()};
+ int rank1{arg1TnS.Rank()};
return common::visit(
common::visitors{
[&](common::NumericOperator) {
@@ -2087,8 +2118,8 @@ bool CheckHelper::CheckDefinedAssignment(
if (!(ok0 && ok1)) {
return false; // error was reported
} else if (ConflictsWithIntrinsicAssignment(proc)) {
- msg = "Defined assignment subroutine '%s' conflicts with"
- " intrinsic assignment"_err_en_US;
+ msg =
+ "Defined assignment subroutine '%s' conflicts with intrinsic assignment"_err_en_US;
} else {
return true; // OK
}
diff --git a/flang/test/Semantics/cuf16.cuf b/flang/test/Semantics/cuf16.cuf
new file mode 100644
index 0000000000000..4a7595b479503
--- /dev/null
+++ b/flang/test/Semantics/cuf16.cuf
@@ -0,0 +1,95 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+module m
+ interface operator(-)
+ !ERROR: OPERATOR(-) function 'f1' conflicts with intrinsic operator
+ function f1(x)
+ real, intent(in) :: x
+ end
+ !ERROR: OPERATOR(-) function 'f2' conflicts with intrinsic operator
+ attributes(device) function f2(x)
+ real, intent(in), device :: x(:)
+ end
+ function f3(x) ! ok
+ real, intent(in), device :: x(:,:)
+ end
+ !ERROR: OPERATOR(-) function 'f4' conflicts with intrinsic operator
+ attributes(device) function f4(x)
+ real, intent(in) :: x(:,:,:)
+ end
+ !ERROR: OPERATOR(-) function 'f5' conflicts with intrinsic operator
+ function f5(x)
+ real, intent(in), unified :: x(:,:,:,:)
+ end
+ !ERROR: OPERATOR(-) function 'f6' conflicts with intrinsic operator
+ attributes(device) function f6(x)
+ real, intent(in), managed :: x(:,:,:,:,:)
+ end
+ end interface
+ interface operator(*)
+ !ERROR: OPERATOR(*) function 'f11' conflicts with intrinsic operator
+ function f11(x, y)
+ real, intent(in) :: x, y
+ end
+ !ERROR: OPERATOR(*) function 'f12' conflicts with intrinsic operator
+ attributes(device) function f12(x, y)
+ real, intent(in), device :: x, y(:)
+ end
+ !ERROR: OPERATOR(*) function 'f13' conflicts with intrinsic operator
+ attributes(device) function f13(x, y)
+ real, intent(in) :: x(:), y
+ end
+ function f14a(x, y) ! ok
+ real, intent(in), device :: x(:)
+ real, intent(in) :: y(:)
+ end
+ function f14b(x, y) ! ok
+ real, intent(in) :: x
+ real, intent(in), device :: y(:,:)
+ end
+ !ERROR: OPERATOR(*) function 'f15' conflicts with intrinsic operator
+ function f15(x, y)
+ real, intent(in) :: x(:,:)
+ real, intent(in), unified :: y
+ end
+ !ERROR: OPERATOR(*) function 'f16' conflicts with intrinsic operator
+ attributes(device) function f16(x, y)
+ real, intent(in), device :: x(:,:)
+ real, intent(in), managed :: y(:,:)
+ end
+ end interface
+ interface assignment(=)
+ !ERROR: Defined assignment subroutine 's1' conflicts with intrinsic assignment
+ subroutine s1(x, y)
+ real, intent(in out) :: x
+ real, intent(in) :: y
+ end
+ !ERROR: Defined assignment subroutine 's2' conflicts with intrinsic assignment
+ attributes(device) subroutine s2(x, y)
+ real, intent(in out), device :: x(:)
+ real, intent(in), device :: y
+ end
+ !ERROR: Defined assignment subroutine 's3' conflicts with intrinsic assignment
+ attributes(device) subroutine s3(x, y)
+ real, intent(in out) :: x(:)
+ real, intent(in) :: y(:)
+ end
+ subroutine s4a(x, y) ! ok
+ real, intent(in out), device :: x(:,:)
+ real, intent(in) :: y
+ end
+ subroutine s4b(x, y) ! ok
+ real, intent(in out) :: x(:,:)
+ real, intent(in), device :: y(:,:)
+ end
+ !ERROR: Defined assignment subroutine 's5' conflicts with intrinsic assignment
+ subroutine s5(x, y)
+ real, intent(in out) :: x(:,:,:)
+ real, intent(in), unified :: y
+ end
+ !ERROR: Defined assignment subroutine 's6' conflicts with intrinsic assignment
+ attributes(device) subroutine s6(x, y)
+ real, intent(in out), device :: x(:,:,:)
+ real, intent(in), managed :: y(:,:,:)
+ end
+ end interface
+end
``````````
</details>
https://github.com/llvm/llvm-project/pull/94389
More information about the flang-commits
mailing list