[llvm] [flang] [compiler-rt] [clang] [clang-tools-extra] [Flang][OpenMP] Restructure recursive lowering in `createBodyOfOp` (PR #77761)
Kiran Chandramohan via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 19 08:56:26 PST 2024
================
@@ -2223,37 +2222,100 @@ static void createBodyOfOp(
mlir::omp::YieldOp>(
firOpBuilder, eval.getNestedEvaluations());
- // Insert the terminator.
- Fortran::lower::genOpenMPTerminator(firOpBuilder, op.getOperation(), loc);
- // Reset the insert point to before the terminator.
- resetBeforeTerminator(firOpBuilder, storeOp, block);
+ // Start with privatization, so that the lowering of the nested
+ // code will use the right symbols.
+ constexpr bool isLoop = std::is_same_v<Op, mlir::omp::WsLoopOp> ||
+ std::is_same_v<Op, mlir::omp::SimdLoopOp>;
+ bool privatize = clauses && !outerCombined;
- // Handle privatization. Do not privatize if this is the outer operation.
- if (clauses && !outerCombined) {
- constexpr bool isLoop = std::is_same_v<Op, mlir::omp::WsLoopOp> ||
- std::is_same_v<Op, mlir::omp::SimdLoopOp>;
+ firOpBuilder.setInsertionPoint(marker);
+ std::optional<DataSharingProcessor> tempDsp;
+ if (privatize) {
if (!dsp) {
- DataSharingProcessor proc(converter, *clauses, eval);
- proc.processStep1();
- proc.processStep2(op, isLoop);
- } else {
- if (isLoop && args.size() > 0)
- dsp->setLoopIV(converter.getSymbolAddress(*args[0]));
- dsp->processStep2(op, isLoop);
+ tempDsp.emplace(converter, *clauses, eval);
+ tempDsp->processStep1();
}
-
- if (storeOp)
- firOpBuilder.setInsertionPointAfter(storeOp);
}
if constexpr (std::is_same_v<Op, mlir::omp::ParallelOp>) {
threadPrivatizeVars(converter, eval);
- if (clauses)
+ if (clauses) {
+ firOpBuilder.setInsertionPoint(marker);
ClauseProcessor(converter, *clauses).processCopyin();
+ }
}
- if (genNested)
+ if (genNested) {
+ // genFIR(Evaluation&) tries to patch up unterminated blocks, causing
+ // a lot of trouble if the terminator generation is delayed past this
+ // point. Insert a temporary terminator here, then delete it.
+ firOpBuilder.setInsertionPointToEnd(&op.getRegion().back());
+ auto *temp = Fortran::lower::genOpenMPTerminator(firOpBuilder,
+ op.getOperation(), loc);
+ firOpBuilder.setInsertionPointAfter(marker);
genNestedEvaluations(converter, eval);
+ temp->erase();
+ }
+
+ // Get or create a unique exiting block from the given region, or
+ // return nullptr if there is no exiting block.
+ auto getUniqueExit = [&](mlir::Region ®ion) -> mlir::Block * {
+ // Find the blocks where the OMP terminator should go. In simple cases
+ // it is the single block in the operation's region. When the region
+ // is more complicated, especially with unstructured control flow, there
+ // may be multiple blocks, and some of them may have non-OMP terminators
+ // resulting from lowering of the code contained within the operation.
+ // All the remaining blocks are potential exit points from the op's region.
+ //
+ // Explicit control flow cannot exit any OpenMP region (other than via
+ // STOP), and that is enforced by semantic checks prior to lowering. STOP
+ // statements are lowered to a function call.
+
+ // Collect unterminated blocks.
+ llvm::SmallVector<mlir::Block *> exits;
+ for (mlir::Block &b : region) {
+ if (b.empty() || !b.back().hasTrait<mlir::OpTrait::IsTerminator>())
+ exits.push_back(&b);
+ }
+
+ if (exits.empty())
+ return nullptr;
+ // If there already is a unique exiting block, do not create another one.
+ // Additionally, some ops (e.g. omp.sections) require onlt 1 block in
----------------
kiranchandramohan wrote:
```suggestion
// Additionally, some ops (e.g. omp.sections) require only 1 block in
```
https://github.com/llvm/llvm-project/pull/77761
More information about the cfe-commits
mailing list