Skip to content

Commit dd29614

Browse files
committed
[flang][OpenMP] Add util for mapping or cloning region outsiders
Similar to llvm#1993 and llvm#1994, this adds a util to map or clone region outsiders. This util is used by both the lowering and `do concurrent` mapping components.
1 parent ccc3c58 commit dd29614

File tree

4 files changed

+53
-89
lines changed

4 files changed

+53
-89
lines changed

flang/include/flang/Support/OpenMP-utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ mlir::omp::MapInfoOp createMapInfoOp(mlir::OpBuilder &builder,
8686

8787
mlir::Value mapTemporaryValue(fir::FirOpBuilder &firOpBuilder,
8888
mlir::omp::TargetOp targetOp, mlir::Value val, llvm::StringRef name);
89+
90+
void cloneOrMapRegionOutsiders(
91+
fir::FirOpBuilder &firOpBuilder, mlir::omp::TargetOp targetOp);
8992
} // namespace Fortran::common::openmp
9093

9194
#endif // FORTRAN_SUPPORT_OPENMP_UTILS_H_

flang/lib/Lower/OpenMP/OpenMP.cpp

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,9 +1333,7 @@ static void genBodyOfTargetOp(
13331333
ConstructQueue::const_iterator item, DataSharingProcessor &dsp) {
13341334
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
13351335
auto argIface = llvm::cast<mlir::omp::BlockArgOpenMPOpInterface>(*targetOp);
1336-
1337-
mlir::Region &region = targetOp.getRegion();
1338-
mlir::Block *entryBlock = genEntryBlock(firOpBuilder, args, region);
1336+
genEntryBlock(firOpBuilder, args, targetOp.getRegion());
13391337

13401338
if (!enableDelayedPrivatizationStaging)
13411339
dsp.processStep2();
@@ -1348,41 +1346,7 @@ static void genBodyOfTargetOp(
13481346
// If so, then either clone them as well if they are MemoryEffectFree, or else
13491347
// copy them to a new temporary and add them to the map and block_argument
13501348
// lists and replace their uses with the new temporary.
1351-
llvm::SetVector<mlir::Value> valuesDefinedAbove;
1352-
mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);
1353-
while (!valuesDefinedAbove.empty()) {
1354-
for (mlir::Value val : valuesDefinedAbove) {
1355-
mlir::Operation *valOp = val.getDefiningOp();
1356-
assert(valOp != nullptr);
1357-
1358-
// NOTE: We skip BoxDimsOp's as the lesser of two evils is to map the
1359-
// indices separately, as the alternative is to eventually map the Box,
1360-
// which comes with a fairly large overhead comparatively. We could be
1361-
// more robust about this and check using a BackwardsSlice to see if we
1362-
// run the risk of mapping a box.
1363-
if (mlir::isMemoryEffectFree(valOp) &&
1364-
!mlir::isa<fir::BoxDimsOp>(valOp)) {
1365-
mlir::Operation *clonedOp = valOp->clone();
1366-
entryBlock->push_front(clonedOp);
1367-
1368-
auto replace = [entryBlock](mlir::OpOperand &use) {
1369-
return use.getOwner()->getBlock() == entryBlock;
1370-
};
1371-
1372-
valOp->getResults().replaceUsesWithIf(clonedOp->getResults(), replace);
1373-
valOp->replaceUsesWithIf(clonedOp, replace);
1374-
} else {
1375-
mlir::Value mappedTemp = Fortran::common::openmp::mapTemporaryValue(
1376-
firOpBuilder, targetOp, val,
1377-
/*name=*/{});
1378-
val.replaceUsesWithIf(mappedTemp, [entryBlock](mlir::OpOperand &use) {
1379-
return use.getOwner()->getBlock() == entryBlock;
1380-
});
1381-
}
1382-
}
1383-
valuesDefinedAbove.clear();
1384-
mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);
1385-
}
1349+
Fortran::common::openmp::cloneOrMapRegionOutsiders(firOpBuilder, targetOp);
13861350

13871351
// Insert dummy instruction to remember the insertion position. The
13881352
// marker will be deleted since there are not uses.

flang/lib/Optimizer/OpenMP/DoConcurrentConversion.cpp

Lines changed: 6 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -39,56 +39,6 @@ namespace flangomp {
3939
#define DEBUG_TYPE "do-concurrent-conversion"
4040
#define DBGS() (llvm::dbgs() << "[" DEBUG_TYPE << "]: ")
4141

42-
namespace Fortran {
43-
namespace lower {
44-
namespace omp {
45-
namespace internal {
46-
/// Check if cloning the bounds introduced any dependency on the outer region.
47-
/// If so, then either clone them as well if they are MemoryEffectFree, or else
48-
/// copy them to a new temporary and add them to the map and block_argument
49-
/// lists and replace their uses with the new temporary.
50-
///
51-
/// TODO: similar to the above functions, this is copied from OpenMP lowering
52-
/// (in this case, from `genBodyOfTargetOp`). Once we move to a common lib for
53-
/// these utils this will move as well.
54-
void cloneOrMapRegionOutsiders(fir::FirOpBuilder &builder,
55-
mlir::omp::TargetOp targetOp) {
56-
mlir::Region &targetRegion = targetOp.getRegion();
57-
mlir::Block *targetEntryBlock = &targetRegion.getBlocks().front();
58-
llvm::SetVector<mlir::Value> valuesDefinedAbove;
59-
mlir::getUsedValuesDefinedAbove(targetRegion, valuesDefinedAbove);
60-
61-
while (!valuesDefinedAbove.empty()) {
62-
for (mlir::Value val : valuesDefinedAbove) {
63-
mlir::Operation *valOp = val.getDefiningOp();
64-
assert(valOp != nullptr);
65-
if (mlir::isMemoryEffectFree(valOp)) {
66-
mlir::Operation *clonedOp = valOp->clone();
67-
targetEntryBlock->push_front(clonedOp);
68-
assert(clonedOp->getNumResults() == 1);
69-
val.replaceUsesWithIf(
70-
clonedOp->getResult(0), [targetEntryBlock](mlir::OpOperand &use) {
71-
return use.getOwner()->getBlock() == targetEntryBlock;
72-
});
73-
} else {
74-
mlir::Value mappedTemp = Fortran::common::openmp::mapTemporaryValue(
75-
builder, targetOp, val,
76-
/*name=*/llvm::StringRef{});
77-
val.replaceUsesWithIf(
78-
mappedTemp, [targetEntryBlock](mlir::OpOperand &use) {
79-
return use.getOwner()->getBlock() == targetEntryBlock;
80-
});
81-
}
82-
}
83-
valuesDefinedAbove.clear();
84-
mlir::getUsedValuesDefinedAbove(targetRegion, valuesDefinedAbove);
85-
}
86-
}
87-
} // namespace internal
88-
} // namespace omp
89-
} // namespace lower
90-
} // namespace Fortran
91-
9242
namespace {
9343
namespace looputils {
9444
/// Stores info needed about the induction/iteration variable for each `do
@@ -665,7 +615,12 @@ class DoConcurrentConversion
665615
mapper.lookup(loopNestClauseOps.loopSteps[i]);
666616
}
667617

668-
Fortran::lower::omp::internal::cloneOrMapRegionOutsiders(builder, targetOp);
618+
// Check if cloning the bounds introduced any dependency on the outer
619+
// region. If so, then either clone them as well if they are
620+
// MemoryEffectFree, or else copy them to a new temporary and add them to
621+
// the map and block_argument lists and replace their uses with the new
622+
// temporary.
623+
Fortran::common::openmp::cloneOrMapRegionOutsiders(builder, targetOp);
669624
rewriter.setInsertionPoint(
670625
rewriter.create<mlir::omp::TerminatorOp>(targetOp.getLoc()));
671626

flang/lib/Support/OpenMP-utils.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
1515
#include "mlir/IR/OpDefinition.h"
16+
#include "mlir/Transforms/RegionUtils.h"
1617

1718
#include "llvm/Frontend/OpenMP/OMPConstants.h"
1819

@@ -149,4 +150,45 @@ mlir::Value mapTemporaryValue(fir::FirOpBuilder &firOpBuilder,
149150
return loadOp.getResult();
150151
}
151152

153+
void cloneOrMapRegionOutsiders(fir::FirOpBuilder &firOpBuilder,
154+
mlir::omp::TargetOp targetOp) {
155+
mlir::Region &region = targetOp.getRegion();
156+
mlir::Block *entryBlock = &region.getBlocks().front();
157+
158+
llvm::SetVector<mlir::Value> valuesDefinedAbove;
159+
mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);
160+
while (!valuesDefinedAbove.empty()) {
161+
for (mlir::Value val : valuesDefinedAbove) {
162+
mlir::Operation *valOp = val.getDefiningOp();
163+
assert(valOp != nullptr);
164+
165+
// NOTE: We skip BoxDimsOp's as the lesser of two evils is to map the
166+
// indices separately, as the alternative is to eventually map the Box,
167+
// which comes with a fairly large overhead comparatively. We could be
168+
// more robust about this and check using a BackwardsSlice to see if we
169+
// run the risk of mapping a box.
170+
if (mlir::isMemoryEffectFree(valOp) &&
171+
!mlir::isa<fir::BoxDimsOp>(valOp)) {
172+
mlir::Operation *clonedOp = valOp->clone();
173+
entryBlock->push_front(clonedOp);
174+
175+
auto replace = [entryBlock](mlir::OpOperand &use) {
176+
return use.getOwner()->getBlock() == entryBlock;
177+
};
178+
179+
valOp->getResults().replaceUsesWithIf(clonedOp->getResults(), replace);
180+
valOp->replaceUsesWithIf(clonedOp, replace);
181+
} else {
182+
mlir::Value mappedTemp = Fortran::common::openmp::mapTemporaryValue(
183+
firOpBuilder, targetOp, val,
184+
/*name=*/{});
185+
val.replaceUsesWithIf(mappedTemp, [entryBlock](mlir::OpOperand &use) {
186+
return use.getOwner()->getBlock() == entryBlock;
187+
});
188+
}
189+
}
190+
valuesDefinedAbove.clear();
191+
mlir::getUsedValuesDefinedAbove(region, valuesDefinedAbove);
192+
}
193+
}
152194
} // namespace Fortran::common::openmp

0 commit comments

Comments
 (0)