-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[flang][OpenMP] Support using copyprivate with fir.boxchar arguments #144092
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang][OpenMP] Support using copyprivate with fir.boxchar arguments #144092
Conversation
Implement the lowering for passing a fir.boxchar argument to the copyprivate clause. Signed-off-by: Kajetan Puchalski <[email protected]>
@llvm/pr-subscribers-flang-fir-hlfir Author: Kajetan Puchalski (mrkajetanp) ChangesImplement the lowering for passing a fir.boxchar argument to the copyprivate clause. Resolves #142123. Full diff: https://github.com/llvm/llvm-project/pull/144092.diff 2 Files Affected:
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
|
@llvm/pr-subscribers-flang-openmp Author: Kajetan Puchalski (mrkajetanp) ChangesImplement the lowering for passing a fir.boxchar argument to the copyprivate clause. Resolves #142123. Full diff: https://github.com/llvm/llvm-project/pull/144092.diff 2 Files Affected:
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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work on this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the patch @mrkajetanp. Just some minor nits.
…lvm#144092) Implement the lowering for passing a fir.boxchar argument to the copyprivate clause. Resolves llvm#142123. --------- Signed-off-by: Kajetan Puchalski <[email protected]>
…lvm#144092) Implement the lowering for passing a fir.boxchar argument to the copyprivate clause. Resolves llvm#142123. --------- Signed-off-by: Kajetan Puchalski <[email protected]>
Implement the lowering for passing a fir.boxchar argument to the copyprivate clause.
Resolves #142123.