[flang-commits] [flang] b63514c - [flang][cuda] Add more support for data transfer with constant (#211944)
via flang-commits
flang-commits at lists.llvm.org
Fri Jul 24 15:52:18 PDT 2026
Author: Valentin Clement (バレンタイン クレメン)
Date: 2026-07-24T22:52:12Z
New Revision: b63514c9b0d77ff01a0d9d85ce00044ba7fcd2ce
URL: https://github.com/llvm/llvm-project/commit/b63514c9b0d77ff01a0d9d85ce00044ba7fcd2ce
DIFF: https://github.com/llvm/llvm-project/commit/b63514c9b0d77ff01a0d9d85ce00044ba7fcd2ce.diff
LOG: [flang][cuda] Add more support for data transfer with constant (#211944)
Extent support where rhs has some constant variables in an expression.
This match what is accepted in the legacy compiler.
Added:
Modified:
flang/include/flang/Evaluate/tools.h
flang/lib/Evaluate/tools.cpp
flang/lib/Lower/Bridge.cpp
flang/lib/Semantics/check-cuda.cpp
flang/test/Lower/CUDA/cuda-data-transfer.cuf
Removed:
################################################################################
diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index 45c45b78bb694..a60848bea714e 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -1439,6 +1439,9 @@ inline bool IsCUDADataTransfer(const A &lhs, const B &rhs) {
/// implicit data transfer.
bool HasCUDAImplicitTransfer(const Expr<SomeType> &expr);
+/// Check if the expression is a mix of host and constant variables.
+bool HasOnlyCUDAConstntImplicitTransfer(const Expr<SomeType> &expr);
+
// Checks whether the symbol on the LHS is present in the RHS expression.
bool CheckForSymbolMatch(const Expr<SomeType> *lhs, const Expr<SomeType> *rhs);
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 8742bb5000588..ebd8687e5bf96 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1246,7 +1246,8 @@ int GetNbOfUniqueCUDADeviceSymbols(const Expr<SomeType> &expr) {
return symbols.size();
}
-bool HasCUDAImplicitTransfer(const Expr<SomeType> &expr) {
+std::pair<semantics::UnorderedSymbolSet, semantics::UnorderedSymbolSet>
+GetHostAndDeviceSymbols(const Expr<SomeType> &expr) {
semantics::UnorderedSymbolSet hostSymbols;
semantics::UnorderedSymbolSet deviceSymbols;
semantics::UnorderedSymbolSet cudaSymbols{CollectCudaSymbols(expr)};
@@ -1272,10 +1273,29 @@ bool HasCUDAImplicitTransfer(const Expr<SomeType> &expr) {
skipNext = false;
}
}
+ return std::make_pair(hostSymbols, deviceSymbols);
+}
+
+bool HasCUDAImplicitTransfer(const Expr<SomeType> &expr) {
+ auto [hostSymbols, deviceSymbols] = GetHostAndDeviceSymbols(expr);
bool hasConstant{HasConstant(expr)};
return (hasConstant || (hostSymbols.size() > 0)) && deviceSymbols.size() > 0;
}
+bool HasOnlyCUDAConstntImplicitTransfer(const Expr<SomeType> &expr) {
+ auto [hostSymbols, deviceSymbols] = GetHostAndDeviceSymbols(expr);
+ for (const Symbol &sym : deviceSymbols) {
+ if (const auto *details =
+ sym.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()) {
+ if (details->cudaDataAttr() &&
+ (*details->cudaDataAttr() != common::CUDADataAttr::Constant)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
bool IsCUDADeviceSymbol(const Symbol &sym) {
if (const auto *details =
sym.GetUltimate().detailsIf<semantics::ObjectEntityDetails>()) {
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index fec9106a9ec38..ed8b256f47fd4 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -5590,9 +5590,22 @@ class FirConverter : public Fortran::lower::AbstractConverter {
if (lhs.getDefiningOp())
attachInlineAttributes(*lhs.getDefiningOp(), dirs);
}
- hlfir::AssignOp::create(builder, loc, rhs, lhs,
- isWholeAllocatableAssignment,
- keepLhsLengthInAllocatableAssignment);
+ if (isCUDATransfer && hasCUDAImplicitTransfer &&
+ Fortran::evaluate::HasCUDADeviceAttrs(assign.lhs)) {
+ auto [temp, cleanup] = hlfir::createTempFromMold(loc, builder, lhs);
+ hlfir::AssignOp::create(builder, loc, rhs, temp,
+ isWholeAllocatableAssignment,
+ keepLhsLengthInAllocatableAssignment);
+ auto transferKindAttr = cuf::DataTransferKindAttr::get(
+ builder.getContext(), cuf::DataTransferKind::HostDevice);
+ cuf::DataTransferOp::create(builder, loc, temp, lhs,
+ /*shape=*/mlir::Value{},
+ transferKindAttr);
+ } else {
+ hlfir::AssignOp::create(builder, loc, rhs, lhs,
+ isWholeAllocatableAssignment,
+ keepLhsLengthInAllocatableAssignment);
+ }
}
if (hasCUDAImplicitTransfer && !isInDeviceContext) {
localSymbols.popScope();
diff --git a/flang/lib/Semantics/check-cuda.cpp b/flang/lib/Semantics/check-cuda.cpp
index 260e17262dcc0..e592812f7503d 100644
--- a/flang/lib/Semantics/check-cuda.cpp
+++ b/flang/lib/Semantics/check-cuda.cpp
@@ -842,7 +842,8 @@ void CUDAChecker::Enter(const parser::AssignmentStmt &x) {
}
if (evaluate::HasCUDADeviceAttrs(assign->lhs) &&
- evaluate::HasCUDAImplicitTransfer(assign->rhs)) {
+ (evaluate::HasCUDAImplicitTransfer(assign->rhs) &&
+ !evaluate::HasOnlyCUDAConstntImplicitTransfer(assign->rhs))) {
if (GetNbOfCUDAManagedOrUnifiedSymbols(assign->lhs) == 1 &&
GetNbOfCUDAManagedOrUnifiedSymbols(assign->rhs) == 1 && nbRhs == 1) {
return; // This is a special case handled on the host.
diff --git a/flang/test/Lower/CUDA/cuda-data-transfer.cuf b/flang/test/Lower/CUDA/cuda-data-transfer.cuf
index 439a5f4bfb77c..54cf439e66d9c 100644
--- a/flang/test/Lower/CUDA/cuda-data-transfer.cuf
+++ b/flang/test/Lower/CUDA/cuda-data-transfer.cuf
@@ -3,6 +3,11 @@
! Test CUDA Fortran data transfer using assignment statements.
module mod1
+
+ real, parameter :: pi = 0.9189385332046727417803297
+ real, constant :: rconst
+ real, constant :: csconst
+
type :: t1
integer :: i
end type
@@ -774,3 +779,16 @@ end subroutine
! CHECK-LABEL: func.func @_QPsub45
! CHECK-LABEL: @_QFsub45Pcompute
! CHECK: cuf.data_transfer %{{.*}} to %{{.*}} {transfer_kind = #cuf.cuda_transfer<host_device>} : !fir.box<!fir.array<?x?xcomplex<f64>>>, !fir.box<!fir.array<?x?xcomplex<f64>>>
+
+subroutine sub46()
+ use mod1
+ csconst = rconst * pi/6
+end subroutine
+
+! CHECK-LABEL: func.func @_QPsub46()
+! CHECK: cuf.data_transfer
+! CHECK: arith.mulf
+! CHECK: arith.constant
+! CHECK: arith.divf
+! CHECK: hlfir.assign
+! CHECK: cuf.data_transfer
More information about the flang-commits
mailing list