Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 33 additions & 9 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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)) {
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
36 changes: 36 additions & 0 deletions flang/test/Lower/OpenMP/copyprivate5.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
! 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: %[[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

character(len=3) :: c
call s(c)
end
Loading