[flang-commits] [flang] [flang][cuda] Assign a scalar character function result on the host (PR #217076)
via flang-commits
flang-commits at lists.llvm.org
Tue Aug 18 09:47:00 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Matsu (khaki3)
<details>
<summary>Changes</summary>
A managed function result makes an assignment a cuf.data_transfer:
function f() result(r)
character(len=:), allocatable :: r ! managed under -gpu=mem:managed
end function
character(len=256) :: c
c = f()
The rank-0 result r is lowered to a !fir.boxchar<1>, an {address, length}
value rather than a reference, so the non-descriptor transfer path has no
address to take:
'fir.convert' op invalid type conversion '!fir.boxchar<1>' / '!fir.llvm_ptr<i8>'
A fixed-length result does have an address, but the copy is sized by the
character kind instead of the length: one character copied, c left unpadded.
Managed and unified results are host accessible, so assign a scalar character
result on the host and get the padding rules. Array results pass by
descriptor and are unaffected.
---
Full diff: https://github.com/llvm/llvm-project/pull/217076.diff
2 Files Affected:
- (modified) flang/lib/Lower/Bridge.cpp (+9-1)
- (modified) flang/test/Lower/CUDA/cuda-managed-assign.cuf (+21)
``````````diff
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index bff6b51e50e18..d6d7b1838df58 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -5284,11 +5284,19 @@ class FirConverter : public Fortran::lower::AbstractConverter {
// attribute. Such a result may be produced by an asynchronous kernel, so
// consuming it in an assignment must be a synchronizing data transfer rather
// than a plain host assignment. A whole-allocatable left-hand side is
- // excluded: it has reallocation semantics and is performed on the host.
+ // excluded: it has reallocation semantics and is performed on the host, and
+ // so is a scalar character result: it carries its length outside of a
+ // descriptor, so a transfer would copy raw bytes instead of padding or
+ // truncating the destination.
bool
isCUDAFunctionResultTransfer(const Fortran::evaluate::Assignment &assign) {
if (Fortran::evaluate::IsAllocatableDesignator(assign.lhs))
return false;
+ if (assign.rhs.Rank() == 0)
+ if (std::optional<Fortran::evaluate::DynamicType> type{
+ assign.rhs.GetType()})
+ if (type->category() == Fortran::common::TypeCategory::Character)
+ return false;
const Fortran::evaluate::ProcedureRef *procRef =
Fortran::evaluate::UnwrapProcedureRef(assign.rhs);
if (!procRef)
diff --git a/flang/test/Lower/CUDA/cuda-managed-assign.cuf b/flang/test/Lower/CUDA/cuda-managed-assign.cuf
index 694555a173cf6..09bfcd5296c89 100644
--- a/flang/test/Lower/CUDA/cuda-managed-assign.cuf
+++ b/flang/test/Lower/CUDA/cuda-managed-assign.cuf
@@ -14,6 +14,15 @@ contains
allocate(r(n))
r = 7
end function
+ function frchar(n) result(r)
+ integer, value :: n
+ character(len=:), allocatable, managed :: r
+ allocate(character(len=n) :: r)
+ end function
+ function frcharfix() result(r)
+ character(len=4), allocatable, managed :: r
+ allocate(r)
+ end function
end module
! Assignments that are data transfers.
@@ -310,3 +319,15 @@ end subroutine
! CHECK-LABEL: func.func @_QPmanaged_component_attr_section_assign()
! CHECK-NOT: cuf.data_transfer
+
+! A scalar character result carries its length outside of a descriptor, so a
+! transfer would copy raw bytes instead of padding or truncating the destination.
+subroutine managed_char_func_result()
+ use mfr
+ character(len=16) :: h
+ h = frchar(4)
+ h = frcharfix()
+end subroutine
+
+! CHECK-LABEL: func.func @_QPmanaged_char_func_result()
+! CHECK-NOT: cuf.data_transfer
``````````
</details>
https://github.com/llvm/llvm-project/pull/217076
More information about the flang-commits
mailing list