-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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][MLIR][OpenMP] Extend delayed privatization for CHARACTER
#85369
Conversation
@llvm/pr-subscribers-flang-fir-hlfir @llvm/pr-subscribers-flang-openmp Author: Kareem Ergawy (ergawy) ChangesExtends delayed privatization to support scalar Patch is 29.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/85369.diff 10 Files Affected:
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index a668ba4116faab..6d3ec7247687c0 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -748,7 +748,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
void copyVar(mlir::Location loc, mlir::Value dst,
mlir::Value src) override final {
- copyVarHLFIR(loc, dst, src);
+ copyVarHLFIR(loc, Fortran::lower::SymbolBox::Intrinsic{dst},
+ Fortran::lower::SymbolBox::Intrinsic{src});
}
void copyHostAssociateVar(
@@ -1009,10 +1010,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
// `omp.private`'s `alloc` block. If this is the case, we return this
// `SymbolBox::Intrinsic` value.
if (Fortran::lower::SymbolBox v = symMap->lookupSymbol(sym))
- return v.match(
- [&](const Fortran::lower::SymbolBox::Intrinsic &)
- -> Fortran::lower::SymbolBox { return v; },
- [](const auto &) -> Fortran::lower::SymbolBox { return {}; });
+ return v;
return {};
}
@@ -1060,15 +1058,20 @@ class FirConverter : public Fortran::lower::AbstractConverter {
const Fortran::lower::SymbolBox &rhs_sb) {
mlir::Location loc = genLocation(sym.name());
if (lowerToHighLevelFIR())
- copyVarHLFIR(loc, lhs_sb.getAddr(), rhs_sb.getAddr());
+ copyVarHLFIR(loc, lhs_sb, rhs_sb);
else
copyVarFIR(loc, sym, lhs_sb, rhs_sb);
}
- void copyVarHLFIR(mlir::Location loc, mlir::Value dst, mlir::Value src) {
+ void copyVarHLFIR(mlir::Location loc, Fortran::lower::SymbolBox dst,
+ Fortran::lower::SymbolBox src) {
assert(lowerToHighLevelFIR());
- hlfir::Entity lhs{dst};
- hlfir::Entity rhs{src};
+ //llvm::errs() << ">>>> dst box: " << dst << "\n";
+ //llvm::errs() << ">>>> dst addr: " << dst.getAddr()
+ // << ", type: " << dst.getAddr().getType() << "\n";
+ hlfir::Entity lhs{dst.getAddr()};
+ //llvm::errs() << ">>>> src addr: " << src.getAddr() << "\n";
+ hlfir::Entity rhs{src.getAddr()};
// Temporary_lhs is set to true in hlfir.assign below to avoid user
// assignment to be used and finalization to be called on the LHS.
// This may or may not be correct but mimics the current behaviour
@@ -1082,7 +1085,22 @@ class FirConverter : public Fortran::lower::AbstractConverter {
/*keepLhsLengthInAllocatableAssignment=*/false,
/*temporary_lhs=*/true);
};
- if (lhs.isAllocatable()) {
+
+ bool isBoxAllocatable = dst.match(
+ [](const fir::MutableBoxValue &box) { return box.isAllocatable(); },
+ [](const fir::FortranVariableOpInterface &box) {
+ return fir::FortranVariableOpInterface(box).isAllocatable();
+ },
+ [](const auto &box) { return false; });
+
+ bool isBoxPointer = dst.match(
+ [](const fir::MutableBoxValue &box) { return box.isPointer(); },
+ [](const fir::FortranVariableOpInterface &box) {
+ return fir::FortranVariableOpInterface(box).isPointer();
+ },
+ [](const auto &box) { return false; });
+
+ if (isBoxAllocatable) {
// Deep copy allocatable if it is allocated.
// Note that when allocated, the RHS is already allocated with the LHS
// shape for copy on entry in createHostAssociateVarClone.
@@ -1097,7 +1115,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
copyData(lhs, rhs);
})
.end();
- } else if (lhs.isPointer()) {
+ } else if (isBoxPointer) {
// Set LHS target to the target of RHS (do not copy the RHS
// target data into the LHS target storage).
auto loadVal = builder->create<fir::LoadOp>(loc, rhs);
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index 717b8cc0276a30..a2a56bf718af26 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -16,6 +16,7 @@
#include "flang/Lower/PFTBuilder.h"
#include "flang/Lower/SymbolMap.h"
#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "flang/Semantics/tools.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
@@ -50,6 +51,7 @@ void DataSharingProcessor::processStep2(mlir::Operation *op, bool isLoop) {
}
void DataSharingProcessor::insertDeallocs() {
+ // TODO Extend delayed privatization to include a `dealloc` region.
for (const Fortran::semantics::Symbol *sym : privatizedSymbols)
if (Fortran::semantics::IsAllocatable(sym->GetUltimate())) {
converter.createHostAssociateVarCloneDealloc(*sym);
@@ -350,6 +352,8 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
Fortran::lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym);
assert(hsb && "Host symbol box not found");
+ //llvm::errs() << ">>>> hsb: " << hsb << "\n";
+
mlir::Type symType = hsb.getAddr().getType();
mlir::Location symLoc = hsb.getAddr().getLoc();
@@ -376,9 +380,59 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
symLoc, uniquePrivatizerName, symType,
isFirstPrivate ? mlir::omp::DataSharingClauseType::FirstPrivate
: mlir::omp::DataSharingClauseType::Private);
+ fir::ExtendedValue symExV = converter.getSymbolExtendedValue(*sym);
+ //llvm::errs() << ">>>> symExV: " << symExV << "\n";
symTable->pushScope();
+ auto addSymbol = [&](mlir::Region ®ion, unsigned argIdx,
+ bool force = false) {
+ symExV.match(
+ [&](const fir::ArrayBoxValue &box) {
+ auto idxTy = firOpBuilder.getIndexType();
+ llvm::SmallVector<mlir::Value> extents;
+ llvm::SmallVector<mlir::Value> lBounds;
+
+ for (unsigned dim = 0; dim < box.getExtents().size(); ++dim) {
+ mlir::Value dimVal =
+ firOpBuilder.createIntegerConstant(symLoc, idxTy, dim);
+ fir::BoxDimsOp dimInfo = firOpBuilder.create<fir::BoxDimsOp>(
+ symLoc, idxTy, idxTy, idxTy, region.getArgument(argIdx),
+ dimVal);
+ extents.push_back(dimInfo.getExtent());
+ lBounds.push_back(dimInfo.getLowerBound());
+ }
+
+ symTable->addSymbol(*sym,
+ fir::ArrayBoxValue(region.getArgument(argIdx),
+ extents, lBounds),
+ force);
+ },
+ [&](const fir::CharBoxValue &box) {
+ fir::BoxCharType boxCharType = symType.cast<fir::BoxCharType>();
+ mlir::Type charRefType =
+ firOpBuilder.getRefType(boxCharType.getEleTy());
+
+ fir::UnboxCharOp unboxedArg = firOpBuilder.create<fir::UnboxCharOp>(
+ symLoc, charRefType, firOpBuilder.getCharacterLengthType(),
+ region.getArgument(argIdx));
+ llvm::errs() << ">>>> unboxedArg: " << unboxedArg << "\n";
+ // return fir::CharBoxValue(unboxedArg.getResult(0),
+ // unboxedArg.getResult(1));
+ // return fir::BoxValue(copyRegion.getArgument(argIdx));
+ // return fir::substBase(box, copyRegion.getArgument(argIdx));
+ hlfir::DeclareOp localVar = firOpBuilder.create<hlfir::DeclareOp>(
+ symLoc, unboxedArg.getResult(0), converter.mangleName(*sym),
+ nullptr,
+ llvm::SmallVector<mlir::Value>{unboxedArg.getResult(1)});
+ symTable->addVariableDefinition(*sym, localVar, force);
+ },
+ [&](const auto &box) {
+ symTable->addSymbol(
+ *sym, fir::substBase(box, region.getArgument(argIdx)), force);
+ });
+ };
+
// Populate the `alloc` region.
{
mlir::Region &allocRegion = result.getAllocRegion();
@@ -386,7 +440,8 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
&allocRegion, /*insertPt=*/{}, symType, symLoc);
firOpBuilder.setInsertionPointToEnd(allocEntryBlock);
- symTable->addSymbol(*sym, allocRegion.getArgument(0));
+
+ addSymbol(allocRegion, 0);
symTable->pushScope();
cloneSymbol(sym);
firOpBuilder.create<mlir::omp::YieldOp>(
@@ -403,10 +458,15 @@ void DataSharingProcessor::doPrivatize(const Fortran::semantics::Symbol *sym) {
mlir::Block *copyEntryBlock = firOpBuilder.createBlock(
©Region, /*insertPt=*/{}, {symType, symType}, {symLoc, symLoc});
firOpBuilder.setInsertionPointToEnd(copyEntryBlock);
- symTable->addSymbol(*sym, copyRegion.getArgument(0),
- /*force=*/true);
+
+
+
+ addSymbol(copyRegion, 0, true);
+ //symTable->addSymbol(*sym, xxx(0),
+ // [>force=<]true);
symTable->pushScope();
- symTable->addSymbol(*sym, copyRegion.getArgument(1));
+ addSymbol(copyRegion, 1);
+ //symTable->addSymbol(*sym, xxx(1));
auto ip = firOpBuilder.saveInsertionPoint();
copyFirstPrivateSymbol(sym, &ip);
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 25bb4d9cff5d16..9f07eb922876ce 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -655,20 +655,31 @@ genParallelOp(Fortran::lower::AbstractConverter &converter,
llvm::transform(privateVars, std::back_inserter(privateVarLocs),
[](mlir::Value v) { return v.getLoc(); });
- converter.getFirOpBuilder().createBlock(®ion, /*insertPt=*/{},
+ fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+ builder.createBlock(®ion, /*insertPt=*/{},
privateVarTypes, privateVarLocs);
llvm::SmallVector<const Fortran::semantics::Symbol *> allSymbols =
reductionSymbols;
allSymbols.append(delayedPrivatizationInfo.symbols);
- for (auto [arg, prv] : llvm::zip_equal(allSymbols, region.getArguments())) {
- converter.bindSymbol(*arg, prv);
- }
+ for (auto [arg, prv] : llvm::zip_equal(allSymbols, region.getArguments()))
+ if (fir::BoxCharType boxCharTy =
+ prv.getType().dyn_cast<fir::BoxCharType>()) {
+ mlir::Type charRefType = builder.getRefType(boxCharTy.getEleTy());
+
+ fir::UnboxCharOp unboxedArg = builder.create<fir::UnboxCharOp>(
+ builder.getUnknownLoc(), charRefType,
+ builder.getCharacterLengthType(), prv);
+
+ fir::CharBoxValue newBox(unboxedArg.getResult(0),
+ unboxedArg.getResult(1));
+ converter.bindSymbol(*arg, newBox);
+ } else
+ converter.bindSymbol(*arg, prv);
return allSymbols;
};
- // TODO Merge with the reduction CB.
genInfo.setGenRegionEntryCb(genRegionEntryCB).setDataSharingProcessor(&dsp);
llvm::SmallVector<mlir::Attribute> privatizers(
diff --git a/flang/lib/Optimizer/Builder/HLFIRTools.cpp b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
index c7a550814e1d58..760c0e18b86df2 100644
--- a/flang/lib/Optimizer/Builder/HLFIRTools.cpp
+++ b/flang/lib/Optimizer/Builder/HLFIRTools.cpp
@@ -850,6 +850,7 @@ static fir::ExtendedValue
translateVariableToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
hlfir::Entity variable,
bool forceHlfirBase = false) {
+ //llvm::errs() << ">>>> translateVariableToExtendedValue\n";
assert(variable.isVariable() && "must be a variable");
/// When going towards FIR, use the original base value to avoid
/// introducing descriptors at runtime when they are not required.
@@ -858,8 +859,10 @@ translateVariableToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
if (variable.isMutableBox())
return fir::MutableBoxValue(base, getExplicitTypeParams(variable),
fir::MutableProperties{});
+ //llvm::errs() << "1>>>>\n";
if (base.getType().isa<fir::BaseBoxType>()) {
+ //llvm::errs() << "2>>>>\n";
if (!variable.isSimplyContiguous() || variable.isPolymorphic() ||
variable.isDerivedWithLengthParameters() || variable.isOptional()) {
llvm::SmallVector<mlir::Value> nonDefaultLbounds =
@@ -869,34 +872,49 @@ translateVariableToExtendedValue(mlir::Location loc, fir::FirOpBuilder &builder,
}
// Otherwise, the variable can be represented in a fir::ExtendedValue
// without the overhead of a fir.box.
+ //llvm::errs() << "3>>>>\n";
base = genVariableRawAddress(loc, builder, variable);
}
+ //llvm::errs() << "4>>>> base:" << base
+ // << ", with type: " << base.getType() << "\n";
if (variable.isScalar()) {
if (variable.isCharacter()) {
+ //llvm::errs() << "5>>>>\n";
if (base.getType().isa<fir::BoxCharType>())
return genUnboxChar(loc, builder, base);
+ //llvm::errs() << "5.5>>>> base:" << base
+ // << ", with type: " << base.getType() << "\n";
mlir::Value len = genCharacterVariableLength(loc, builder, variable);
return fir::CharBoxValue{base, len};
}
+ //llvm::errs() << "6>>>>\n";
return base;
}
llvm::SmallVector<mlir::Value> extents;
llvm::SmallVector<mlir::Value> nonDefaultLbounds;
+ //llvm::errs() << "7>>>>\n";
if (variable.getType().isa<fir::BaseBoxType>() &&
!variable.getIfVariableInterface()) {
+ //llvm::errs() << "8>>>>\n";
// This special case avoids generating two sets of identical
// fir.box_dim to get both the lower bounds and extents.
genLboundsAndExtentsFromBox(loc, builder, variable, nonDefaultLbounds,
&extents);
} else {
+ //llvm::errs() << "9>>>>\n";
extents = getVariableExtents(loc, builder, variable);
nonDefaultLbounds = getNonDefaultLowerBounds(loc, builder, variable);
}
- if (variable.isCharacter())
+ //llvm::errs() << "10>>>>\n";
+ if (variable.isCharacter()) {
+ //llvm::errs() << ">>>> creating char box value: " << base
+ // << ", with type: " << base.getType() << "\n";
return fir::CharArrayBoxValue{
base, genCharacterVariableLength(loc, builder, variable), extents,
nonDefaultLbounds};
+ }
+ //llvm::errs() << "11>>>>\n";
return fir::ArrayBoxValue{base, extents, nonDefaultLbounds};
}
diff --git a/flang/test/Lower/OpenMP/delayed-privatization-allocatable-array.f90 b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-array.f90
new file mode 100644
index 00000000000000..47e163014fe868
--- /dev/null
+++ b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-array.f90
@@ -0,0 +1,67 @@
+! Test delayed privatization for allocatable arrays.
+
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \
+! RUN: -o - %s 2>&1 | FileCheck %s
+! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 |\
+! RUN: FileCheck %s
+
+subroutine delayed_privatization_private(var1, l1)
+ implicit none
+ integer(8):: l1
+ integer, allocatable, dimension(:) :: var1
+
+!$omp parallel firstprivate(var1)
+ var1(l1 + 1) = 10
+!$omp end parallel
+end subroutine
+
+! CHECK-LABEL: omp.private {type = firstprivate}
+! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.ref<!fir.box<!fir.heap<!fir.array<\?xi32>>>>]] alloc {
+
+! CHECK-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]):
+! CHECK-NEXT: %[[PRIV_ALLOC:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<{{\?}}xi32>>> {bindc_name = "var1", pinned, uniq_name = "_QFdelayed_privatization_privateEvar1"}
+
+! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]]
+! CHECK-NEXT: %[[PRIV_ARG_BOX:.*]] = fir.box_addr %[[PRIV_ARG_VAL]]
+! CHECK-NEXT: %[[PRIV_ARG_ADDR:.*]] = fir.convert %[[PRIV_ARG_BOX]]
+! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64
+! CHECK-NEXT: %[[ALLOC_COND:.*]] = arith.cmpi ne, %[[PRIV_ARG_ADDR]], %[[C0]] : i64
+
+! CHECK-NEXT: fir.if %[[ALLOC_COND]] {
+! CHECK-NEXT: %[[PRIV_ARG_VAL:.*]] = fir.load %[[PRIV_ARG]] : [[TYPE]]
+! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : index
+! CHECK-NEXT: %[[DIMS:.*]]:3 = fir.box_dims %[[PRIV_ARG_VAL]], %[[C0]]
+! CHECK-NEXT: fir.box_addr %[[PRIV_ARG_VAL]]
+! CHECK-NEXT: %[[C0_2:.*]] = arith.constant 0 : index
+! CHECK-NEXT: %[[CMP:.*]] = arith.cmpi sgt, %[[DIMS]]#1, %[[C0_2]] : index
+! CHECK-NEXT: %[[SELECT:.*]] = arith.select %[[CMP]], %[[DIMS]]#1, %[[C0_2]] : index
+! CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[SELECT]]
+! CHECK-NEXT: %[[SHAPE_SHIFT:.*]] = fir.shape_shift %[[DIMS]]#0, %[[SELECT]] : (index, index) -> !fir.shapeshift<1>
+! CHECK-NEXT: %[[EMBOX:.*]] = fir.embox %[[MEM]](%[[SHAPE_SHIFT]])
+! CHECK-NEXT: fir.store %[[EMBOX]] to %[[PRIV_ALLOC]]
+! CHECK-NEXT: } else {
+! CHECK-NEXT: %[[ZEROS:.*]] = fir.zero_bits
+! CHECK-NEXT: %[[C0_3:.*]] = arith.constant 0 : index
+! CHECK-NEXT: %[[SHAPE:.*]] = fir.shape %[[C0_3]] : (index) -> !fir.shape<1>
+! CHECK-NEXT: %[[EMBOX_2:.*]] = fir.embox %[[ZEROS]](%[[SHAPE]])
+! CHECK-NEXT: fir.store %[[EMBOX_2]] to %[[PRIV_ALLOC]]
+! CHECK-NEXT: }
+
+! CHECK-NEXT: hlfir.declare
+! CHECK-NEXT: omp.yield
+
+! CHECK-NEXT: } copy {
+! CHECK-NEXT: ^bb0(%[[PRIV_ORIG_ARG:.*]]: [[TYPE]], %[[PRIV_PRIV_ARG:.*]]: [[TYPE]]):
+! CHECK-NEXT: %[[PRIV_BASE_VAL:.*]] = fir.load %[[PRIV_PRIV_ARG]]
+! CHECK-NEXT: %[[PRIV_BASE_BOX:.*]] = fir.box_addr %[[PRIV_BASE_VAL]]
+! CHECK-NEXT: %[[PRIV_BASE_ADDR:.*]] = fir.convert %[[PRIV_BASE_BOX]]
+! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64
+! CHECK-NEXT: %[[COPY_COND:.*]] = arith.cmpi ne, %[[PRIV_BASE_ADDR]], %[[C0]] : i64
+
+
+! CHECK-NEXT: fir.if %[[COPY_COND]] {
+! CHECK-NEXT: %[[PRIV_ORIG_ARG_VAL:.*]] = fir.load %[[PRIV_ORIG_ARG]]
+! CHECK-NEXT: hlfir.assign %[[PRIV_ORIG_ARG_VAL]] to %[[PRIV_BASE_VAL]] temporary_lhs
+! CHECK-NEXT: }
+! CHECK-NEXT: omp.yield
+! CHECK-NEXT: }
diff --git a/flang/test/Lower/OpenMP/delayed-privatization-allocatable-firstprivate.f90 b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-firstprivate.f90
new file mode 100644
index 00000000000000..aa835f82b2730b
--- /dev/null
+++ b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-firstprivate.f90
@@ -0,0 +1,36 @@
+! Test delayed privatization for allocatables: `firstprivate`.
+
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \
+! RUN: -o - %s 2>&1 | FileCheck %s
+! RUN: bbc -emit-hlfir -fopenmp --openmp-enable-delayed-privatization -o - %s 2>&1 |\
+! RUN: FileCheck %s
+
+subroutine delayed_privatization_allocatable
+ implicit none
+ integer, allocatable :: var1
+
+!$omp parallel firstprivate(var1)
+ var1 = 10
+!$omp end parallel
+end subroutine
+
+! CHECK-LABEL: omp.private {type = firstprivate}
+! CHECK-SAME: @[[PRIVATIZER_SYM:.*]] : [[TYPE:!fir.ref<!fir.box<!fir.heap<i32>>>]] alloc {
+
+! CHECK-NEXT: ^bb0(%[[PRIV_ARG:.*]]: [[TYPE]]):
+
+! CHECK: } copy {
+! CHECK: ^bb0(%[[PRIV_ORIG_ARG:.*]]: [[TYPE]], %[[PRIV_PRIV_ARG:.*]]: [[TYPE]]):
+
+! CHECK-NEXT: %[[PRIV_BASE_VAL:.*]] = fir.load %[[PRIV_PRIV_ARG]]
+! CHECK-NEXT: %[[PRIV_BASE_BOX:.*]] = fir.box_addr %[[PRIV_BASE_VAL]]
+! CHECK-NEXT: %[[PRIV_BASE_ADDR:.*]] = fir.convert %[[PRIV_BASE_BOX]]
+! CHECK-NEXT: %[[C0:.*]] = arith.constant 0 : i64
+! CHECK-NEXT: %[[COPY_COND:.*]] = arith.cmpi ne, %[[PRIV_BASE_ADDR]], %[[C0]] : i64
+
+! CHECK-NEXT: fir.if %[[COPY_COND]] {
+! CHECK-NEXT: %[[ORIG_BASE_VAL:.*]] = fir.load %[[PRIV_ORIG_ARG]]
+! CHECK-NEXT: %[[ORIG_BASE_ADDR:.*]] = fir.box_addr %[[ORIG_BASE_VAL]]
+! CHECK-NEXT: %[[ORIG_BASE_LD:.*]] = fir.load %[[ORIG_BASE_ADDR]]
+! CHECK-NEXT: hlfir.assign %[[ORIG_BASE_LD]] to %[[PRIV_BASE_BOX]] temporary_lhs
+! CHECK-NEXT: }
diff --git a/flang/test/Lower/OpenMP/delayed-privatization-allocatable-private.f90 b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-private.f90
new file mode 100644
index 00000000000000..cc1818b00b809c
--- /dev/null
+++ b/flang/test/Lower/OpenMP/delayed-privatization-allocatable-private.f90
@@ -0,0 +1,43 @@
+! Test delayed privatization for allocatables: `private`.
+
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -mmlir --openmp-enable-delayed-privatization \
+! RUN:...
[truncated]
|
7c1dc02
to
1bb8364
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
1bb8364
to
26b5485
Compare
26b5485
to
97da682
Compare
One more step in delayed privatization, this PR extends support for arrays. In the delayed privatizer, a `fir.box_dims` operation is emitted to retrieve the array bounds and extents. The result of these `fir.box_dims` and the privatizer argument, are then used to create a new `ExtendedValue`.
Extends delayed privatization to support scalar `CHARACTER` variables. `fir.unbox` is used to extract the relevant values from the privatized value: its `!fir.ref<!fir.char<1,?>>` and length. The extracted values are then used to reconstruct the variable through `hlfir.declare` to which the symbol is mapped.
97da682
to
8bbc584
Compare
Extends delayed privatization to support scalar
CHARACTER
variables.fir.unbox
is used to extract the relevant values from the privatizedvalue: its
!fir.ref<!fir.char<1,?>>
and length. The extracted valuesare then used to reconstruct the variable through
hlfir.declare
towhich the symbol is mapped.