[flang-commits] [flang] [flang][OpenMP] Support using copyprivate with fir.boxchar arguments (PR #144092)
Kajetan Puchalski via flang-commits
flang-commits at lists.llvm.org
Mon Jun 16 05:12:02 PDT 2025
https://github.com/mrkajetanp updated https://github.com/llvm/llvm-project/pull/144092
>From 43f05fb9c59194897bf75b66b8dfb0bab49ad409 Mon Sep 17 00:00:00 2001
From: Kajetan Puchalski <kajetan.puchalski at arm.com>
Date: Fri, 13 Jun 2025 14:31:38 +0000
Subject: [PATCH 1/2] [flang][OpenMP] Support using copyprivate with
fir.boxchar arguments
Implement the lowering for passing a fir.boxchar argument to the
copyprivate clause.
Signed-off-by: Kajetan Puchalski <kajetan.puchalski at arm.com>
---
flang/lib/Lower/OpenMP/ClauseProcessor.cpp | 42 +++++++++++++++++-----
flang/test/Lower/OpenMP/copyprivate5.f90 | 32 +++++++++++++++++
2 files changed, 65 insertions(+), 9 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/copyprivate5.f90
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index 88baad8827e92..bf91623936cf1 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -727,12 +727,15 @@ class TypeInfo {
// Is the type inside a box?
bool isBox() const { return inBox; }
+ bool isBoxChar() const { return inBoxChar; }
+
private:
void typeScan(mlir::Type type);
std::optional<fir::CharacterType::LenType> charLen;
llvm::SmallVector<int64_t> shape;
bool inBox = false;
+ bool inBoxChar = false;
};
void TypeInfo::typeScan(mlir::Type ty) {
@@ -748,6 +751,9 @@ void TypeInfo::typeScan(mlir::Type ty) {
typeScan(cty.getEleTy());
} else if (auto cty = mlir::dyn_cast<fir::CharacterType>(ty)) {
charLen = cty.getLen();
+ } else if (auto cty = mlir::dyn_cast<fir::BoxCharType>(ty)) {
+ inBoxChar = true;
+ typeScan(cty.getEleTy());
} else if (auto hty = mlir::dyn_cast<fir::HeapType>(ty)) {
typeScan(hty.getEleTy());
} else if (auto pty = mlir::dyn_cast<fir::PointerType>(ty)) {
@@ -791,12 +797,6 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
fir::FortranVariableFlagsAttr attrs;
if (varAttrs != fir::FortranVariableFlagsEnum::None)
attrs = fir::FortranVariableFlagsAttr::get(builder.getContext(), varAttrs);
- llvm::SmallVector<mlir::Value> typeparams;
- if (typeInfo.getCharLength().has_value()) {
- mlir::Value charLen = builder.createIntegerConstant(
- loc, builder.getCharacterLengthType(), *typeInfo.getCharLength());
- typeparams.push_back(charLen);
- }
mlir::Value shape;
if (!typeInfo.isBox() && !typeInfo.getShape().empty()) {
llvm::SmallVector<mlir::Value> extents;
@@ -805,11 +805,34 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
builder.createIntegerConstant(loc, builder.getIndexType(), extent));
shape = builder.create<fir::ShapeOp>(loc, extents);
}
+ mlir::Value dst = funcOp.getArgument(0);
+ mlir::Value src = funcOp.getArgument(1);
+ llvm::SmallVector<mlir::Value> typeparams;
+ if (typeInfo.isBoxChar()) {
+ // fir.boxchar will be passed here as fir.ref<fir.boxchar>
+ auto loadDst = builder.create<fir::LoadOp>(loc, dst);
+ auto loadSrc = builder.create<fir::LoadOp>(loc, src);
+ // get the actual fir.ref<fir.char> type
+ mlir::Type refType =
+ fir::ReferenceType::get(mlir::cast<fir::BoxCharType>(eleTy).getEleTy());
+ auto unboxedDst = builder.create<fir::UnboxCharOp>(
+ loc, refType, builder.getIndexType(), loadDst);
+ auto unboxedSrc = builder.create<fir::UnboxCharOp>(
+ loc, refType, builder.getIndexType(), loadSrc);
+ // Add length to type parameters
+ typeparams.push_back(unboxedDst.getResult(1));
+ dst = unboxedDst.getResult(0);
+ src = unboxedSrc.getResult(0);
+ } else if (typeInfo.getCharLength().has_value()) {
+ mlir::Value charLen = builder.createIntegerConstant(
+ loc, builder.getCharacterLengthType(), *typeInfo.getCharLength());
+ typeparams.push_back(charLen);
+ }
auto declDst = builder.create<hlfir::DeclareOp>(
- loc, funcOp.getArgument(0), copyFuncName + "_dst", shape, typeparams,
+ loc, dst, copyFuncName + "_dst", shape, typeparams,
/*dummy_scope=*/nullptr, attrs);
auto declSrc = builder.create<hlfir::DeclareOp>(
- loc, funcOp.getArgument(1), copyFuncName + "_src", shape, typeparams,
+ loc, src, copyFuncName + "_src", shape, typeparams,
/*dummy_scope=*/nullptr, attrs);
converter.copyVar(loc, declDst.getBase(), declSrc.getBase(), varAttrs);
builder.create<mlir::func::ReturnOp>(loc);
@@ -838,7 +861,8 @@ bool ClauseProcessor::processCopyprivate(
// In these cases to retrieve the appropriate !fir.ref<!fir.box<...>> to
// access the data we need we must perform an alloca and then store to it
// and retrieve the data from the new alloca.
- if (mlir::isa<fir::BaseBoxType>(symType)) {
+ if (mlir::isa<fir::BaseBoxType>(symType) ||
+ mlir::isa<fir::BoxCharType>(symType)) {
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
auto alloca = builder.create<fir::AllocaOp>(currentLocation, symType);
builder.create<fir::StoreOp>(currentLocation, symVal, alloca);
diff --git a/flang/test/Lower/OpenMP/copyprivate5.f90 b/flang/test/Lower/OpenMP/copyprivate5.f90
new file mode 100644
index 0000000000000..59509f82da343
--- /dev/null
+++ b/flang/test/Lower/OpenMP/copyprivate5.f90
@@ -0,0 +1,32 @@
+! Test lowering of COPYPRIVATE with character arguments
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+! Testcase from: https://github.com/llvm/llvm-project/issues/142123
+
+! CHECK-LABEL: func.func private @_copy_boxchar_c8xU(
+! CHECK-SAME: %arg0: [[TYPE:!fir.ref<!fir.boxchar<1>>]],
+! CHECK-SAME: %arg1: [[TYPE]]) attributes {llvm.linkage = #llvm.linkage<internal>} {
+! CHECK: %[[RDST:.*]] = fir.load %arg0 : [[TYPE]]
+! CHECK: %[[RSRC:.*]] = fir.load %arg1 : [[TYPE]]
+! CHECK: %[[UDST:.*]]:2 = fir.unboxchar %[[RDST:.*]] : ([[UTYPE:!fir.boxchar<1>]]) -> ([[RTYPE:!fir.ref<!fir.char<1,\?>>]], [[ITYPE:index]])
+! CHECK: %[[USRC:.*]]:2 = fir.unboxchar %[[RSRC:.*]] : ([[UTYPE]]) -> ([[RTYPE]], [[ITYPE]])
+! CHECK: %[[DST:.*]]:2 = hlfir.declare %[[UDST:.*]]#0 typeparams %[[UDST:.*]]#1 {uniq_name = "_copy_boxchar_c8xU_dst"} : ([[RTYPE]], [[ITYPE]]) -> ([[UTYPE]], [[RTYPE]])
+! CHECK: %[[SRC:.*]]:2 = hlfir.declare %[[USRC:.*]]#0 typeparams %[[UDST:.*]]#1 {uniq_name = "_copy_boxchar_c8xU_src"} : ([[RTYPE]], [[ITYPE]]) -> ([[UTYPE]], [[RTYPE]])
+! CHECK: hlfir.assign %[[SRC:.*]]#0 to %[[DST:.*]]#0 : [[UTYPE]], [[UTYPE]]
+! CHECK: return
+! CHECK: }
+
+! CHECK-LABEL: func.func @_QPs(%arg0: !fir.boxchar<1> {fir.bindc_name = "c"}) {
+! CHECK: omp.single copyprivate(%3 -> @_copy_boxchar_c8xU : !fir.ref<!fir.boxchar<1>>) {
+! CHECK: omp.terminator
+! CHECK: }
+
+subroutine s(c)
+character(*) :: c
+!$omp single copyprivate(c)
+!$omp end single
+end subroutine
+
+character(len=3) :: c
+call s(c)
+end
>From 16753d9e98d3a2332551773e069e8aaf809c177f Mon Sep 17 00:00:00 2001
From: Kajetan Puchalski <kajetan.puchalski at arm.com>
Date: Mon, 16 Jun 2025 12:11:11 +0000
Subject: [PATCH 2/2] Expand test
---
flang/test/Lower/OpenMP/copyprivate5.f90 | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/flang/test/Lower/OpenMP/copyprivate5.f90 b/flang/test/Lower/OpenMP/copyprivate5.f90
index 59509f82da343..80d46e04ad3ef 100644
--- a/flang/test/Lower/OpenMP/copyprivate5.f90
+++ b/flang/test/Lower/OpenMP/copyprivate5.f90
@@ -17,13 +17,17 @@
! CHECK: }
! CHECK-LABEL: func.func @_QPs(%arg0: !fir.boxchar<1> {fir.bindc_name = "c"}) {
-! CHECK: omp.single copyprivate(%3 -> @_copy_boxchar_c8xU : !fir.ref<!fir.boxchar<1>>) {
+! CHECK: %[[ALLOC:.*]] = fir.alloca !fir.boxchar<1>
+! CHECK: fir.store %[[SRC:.*]] to %[[ALLOC:.*]] : !fir.ref<!fir.boxchar<1>>
+! CHECK: omp.single copyprivate([[ALLOC:.*]] -> @_copy_boxchar_c8xU : !fir.ref<!fir.boxchar<1>>) {
+! CHECK: hlfir.assign %[[NEW_VAL:.*]] to %[[SRC:.*]] : !fir.ref<!fir.char<1,3>>, !fir.boxchar<1>
! CHECK: omp.terminator
! CHECK: }
subroutine s(c)
character(*) :: c
!$omp single copyprivate(c)
+c = "bar"
!$omp end single
end subroutine
More information about the flang-commits
mailing list