Skip to content

Commit 4cfe0d7

Browse files
authored
[flang][OpenMP] Support using copyprivate with fir.boxchar arguments (llvm#144092)
Implement the lowering for passing a fir.boxchar argument to the copyprivate clause. Resolves llvm#142123. --------- Signed-off-by: Kajetan Puchalski <[email protected]>
1 parent 0fb198e commit 4cfe0d7

File tree

2 files changed

+74
-12
lines changed

2 files changed

+74
-12
lines changed

flang/lib/Lower/OpenMP/ClauseProcessor.cpp

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -727,12 +727,15 @@ class TypeInfo {
727727
// Is the type inside a box?
728728
bool isBox() const { return inBox; }
729729

730+
bool isBoxChar() const { return inBoxChar; }
731+
730732
private:
731733
void typeScan(mlir::Type type);
732734

733735
std::optional<fir::CharacterType::LenType> charLen;
734736
llvm::SmallVector<int64_t> shape;
735737
bool inBox = false;
738+
bool inBoxChar = false;
736739
};
737740

738741
void TypeInfo::typeScan(mlir::Type ty) {
@@ -748,6 +751,9 @@ void TypeInfo::typeScan(mlir::Type ty) {
748751
typeScan(cty.getEleTy());
749752
} else if (auto cty = mlir::dyn_cast<fir::CharacterType>(ty)) {
750753
charLen = cty.getLen();
754+
} else if (auto cty = mlir::dyn_cast<fir::BoxCharType>(ty)) {
755+
inBoxChar = true;
756+
typeScan(cty.getEleTy());
751757
} else if (auto hty = mlir::dyn_cast<fir::HeapType>(ty)) {
752758
typeScan(hty.getEleTy());
753759
} else if (auto pty = mlir::dyn_cast<fir::PointerType>(ty)) {
@@ -791,12 +797,6 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
791797
fir::FortranVariableFlagsAttr attrs;
792798
if (varAttrs != fir::FortranVariableFlagsEnum::None)
793799
attrs = fir::FortranVariableFlagsAttr::get(builder.getContext(), varAttrs);
794-
llvm::SmallVector<mlir::Value> typeparams;
795-
if (typeInfo.getCharLength().has_value()) {
796-
mlir::Value charLen = builder.createIntegerConstant(
797-
loc, builder.getCharacterLengthType(), *typeInfo.getCharLength());
798-
typeparams.push_back(charLen);
799-
}
800800
mlir::Value shape;
801801
if (!typeInfo.isBox() && !typeInfo.getShape().empty()) {
802802
llvm::SmallVector<mlir::Value> extents;
@@ -805,11 +805,34 @@ createCopyFunc(mlir::Location loc, lower::AbstractConverter &converter,
805805
builder.createIntegerConstant(loc, builder.getIndexType(), extent));
806806
shape = builder.create<fir::ShapeOp>(loc, extents);
807807
}
808+
mlir::Value dst = funcOp.getArgument(0);
809+
mlir::Value src = funcOp.getArgument(1);
810+
llvm::SmallVector<mlir::Value> typeparams;
811+
if (typeInfo.isBoxChar()) {
812+
// fir.boxchar will be passed here as fir.ref<fir.boxchar>
813+
auto loadDst = builder.create<fir::LoadOp>(loc, dst);
814+
auto loadSrc = builder.create<fir::LoadOp>(loc, src);
815+
// get the actual fir.ref<fir.char> type
816+
mlir::Type refType =
817+
fir::ReferenceType::get(mlir::cast<fir::BoxCharType>(eleTy).getEleTy());
818+
auto unboxedDst = builder.create<fir::UnboxCharOp>(
819+
loc, refType, builder.getIndexType(), loadDst);
820+
auto unboxedSrc = builder.create<fir::UnboxCharOp>(
821+
loc, refType, builder.getIndexType(), loadSrc);
822+
// Add length to type parameters
823+
typeparams.push_back(unboxedDst.getResult(1));
824+
dst = unboxedDst.getResult(0);
825+
src = unboxedSrc.getResult(0);
826+
} else if (typeInfo.getCharLength().has_value()) {
827+
mlir::Value charLen = builder.createIntegerConstant(
828+
loc, builder.getCharacterLengthType(), *typeInfo.getCharLength());
829+
typeparams.push_back(charLen);
830+
}
808831
auto declDst = builder.create<hlfir::DeclareOp>(
809-
loc, funcOp.getArgument(0), copyFuncName + "_dst", shape, typeparams,
832+
loc, dst, copyFuncName + "_dst", shape, typeparams,
810833
/*dummy_scope=*/nullptr, attrs);
811834
auto declSrc = builder.create<hlfir::DeclareOp>(
812-
loc, funcOp.getArgument(1), copyFuncName + "_src", shape, typeparams,
835+
loc, src, copyFuncName + "_src", shape, typeparams,
813836
/*dummy_scope=*/nullptr, attrs);
814837
converter.copyVar(loc, declDst.getBase(), declSrc.getBase(), varAttrs);
815838
builder.create<mlir::func::ReturnOp>(loc);
@@ -835,10 +858,13 @@ bool ClauseProcessor::processCopyprivate(
835858

836859
// CopyPrivate variables must be passed by reference. However, in the case
837860
// of assumed shapes/vla the type is not a !fir.ref, but a !fir.box.
838-
// In these cases to retrieve the appropriate !fir.ref<!fir.box<...>> to
839-
// access the data we need we must perform an alloca and then store to it
840-
// and retrieve the data from the new alloca.
841-
if (mlir::isa<fir::BaseBoxType>(symType)) {
861+
// In the case of character types, the passed in type can also be
862+
// !fir.boxchar. In these cases to retrieve the appropriate
863+
// !fir.ref<!fir.box<...>> or !fir.ref<!fir.boxchar<..>> to access the data
864+
// we need we must perform an alloca and then store to it and retrieve the
865+
// data from the new alloca.
866+
if (mlir::isa<fir::BaseBoxType>(symType) ||
867+
mlir::isa<fir::BoxCharType>(symType)) {
842868
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
843869
auto alloca = builder.create<fir::AllocaOp>(currentLocation, symType);
844870
builder.create<fir::StoreOp>(currentLocation, symVal, alloca);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
! Test lowering of COPYPRIVATE with character arguments
2+
! RUN: %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
3+
4+
! Testcase from: https://github.com/llvm/llvm-project/issues/142123
5+
6+
! CHECK-LABEL: func.func private @_copy_boxchar_c8xU(
7+
! CHECK-SAME: %arg0: [[TYPE:!fir.ref<!fir.boxchar<1>>]],
8+
! CHECK-SAME: %arg1: [[TYPE]]) attributes {llvm.linkage = #llvm.linkage<internal>} {
9+
! CHECK: %[[RDST:.*]] = fir.load %arg0 : [[TYPE]]
10+
! CHECK: %[[RSRC:.*]] = fir.load %arg1 : [[TYPE]]
11+
! CHECK: %[[UDST:.*]]:2 = fir.unboxchar %[[RDST:.*]] : ([[UTYPE:!fir.boxchar<1>]]) -> ([[RTYPE:!fir.ref<!fir.char<1,\?>>]], [[ITYPE:index]])
12+
! CHECK: %[[USRC:.*]]:2 = fir.unboxchar %[[RSRC:.*]] : ([[UTYPE]]) -> ([[RTYPE]], [[ITYPE]])
13+
! CHECK: %[[DST:.*]]:2 = hlfir.declare %[[UDST:.*]]#0 typeparams %[[UDST:.*]]#1 {uniq_name = "[[NAME1:.*]]"} : ([[RTYPE]], [[ITYPE]]) -> ([[UTYPE]], [[RTYPE]])
14+
! CHECK: %[[SRC:.*]]:2 = hlfir.declare %[[USRC:.*]]#0 typeparams %[[UDST:.*]]#1 {uniq_name = "[[NAME2:.*]]"} : ([[RTYPE]], [[ITYPE]]) -> ([[UTYPE]], [[RTYPE]])
15+
! CHECK: hlfir.assign %[[SRC:.*]]#0 to %[[DST:.*]]#0 : [[UTYPE]], [[UTYPE]]
16+
! CHECK: return
17+
! CHECK: }
18+
19+
! CHECK-LABEL: func.func @_QPs(%arg0: !fir.boxchar<1> {fir.bindc_name = "c"}) {
20+
! CHECK: %[[ALLOC:.*]] = fir.alloca !fir.boxchar<1>
21+
! CHECK: fir.store %[[SRC:.*]] to %[[ALLOC:.*]] : !fir.ref<!fir.boxchar<1>>
22+
! CHECK: omp.single copyprivate([[ALLOC:.*]] -> @_copy_boxchar_c8xU : !fir.ref<!fir.boxchar<1>>) {
23+
! CHECK: hlfir.assign %[[NEW_VAL:.*]] to %[[SRC:.*]] : !fir.ref<!fir.char<1,3>>, !fir.boxchar<1>
24+
! CHECK: omp.terminator
25+
! CHECK: }
26+
27+
subroutine s(c)
28+
character(*) :: c
29+
!$omp single copyprivate(c)
30+
c = "bar"
31+
!$omp end single
32+
end subroutine
33+
34+
character(len=3) :: c
35+
call s(c)
36+
end

0 commit comments

Comments
 (0)