diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -105,10 +105,12 @@ insPt = firOpBuilder.saveInsertionPoint(); collectSymbolsForPrivatization(); insertLastPrivateCompare(op); - if (mlir::isa(op)) - firOpBuilder.setInsertionPointToStart(&op->getRegion(0).back()); - else + if (mlir::isa(op)) { + if (!eval.lowerAsUnstructured()) + firOpBuilder.setInsertionPointToStart(&op->getRegion(0).back()); + } else { firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); + } privatize(); collectDefaultSymbols(); defaultPrivatize(); @@ -233,40 +235,53 @@ // a dedicated sub-region in `omp.section` where // lastprivate FIR can reside. Later canonicalizations // will optimize away this operation. - - auto ifOp = firOpBuilder.create( - op->getLoc(), - firOpBuilder.createIntegerConstant( - op->getLoc(), firOpBuilder.getIntegerType(1), 0x1), - /*else*/ false); - firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - - const Fortran::parser::OpenMPConstruct *parentOmpConstruct = - eval.parentConstruct->getIf(); - assert(parentOmpConstruct && - "Expected a valid enclosing OpenMP construct"); - const Fortran::parser::OpenMPSectionsConstruct *sectionsConstruct = - std::get_if( - &parentOmpConstruct->u); - assert(sectionsConstruct && - "Expected an enclosing omp.sections construct"); - const Fortran::parser::OmpClauseList §ionsEndClauseList = - std::get( - std::get( - sectionsConstruct->t) - .t); - for (const Fortran::parser::OmpClause &otherClause : - sectionsEndClauseList.v) - if (std::get_if(&otherClause.u)) - // Emit implicit barrier to synchronize threads and avoid data - // races on post-update of lastprivate variables when `nowait` - // clause is present. - firOpBuilder.create( - converter.getCurrentLocation()); - firOpBuilder.setInsertionPointToStart(&ifOp.getThenRegion().front()); - lastPrivIP = firOpBuilder.saveInsertionPoint(); - firOpBuilder.setInsertionPoint(ifOp); - insPt = firOpBuilder.saveInsertionPoint(); + if (!eval.lowerAsUnstructured()) { + auto ifOp = firOpBuilder.create( + op->getLoc(), + firOpBuilder.createIntegerConstant( + op->getLoc(), firOpBuilder.getIntegerType(1), 0x1), + /*else*/ false); + firOpBuilder.setInsertionPointToStart( + &ifOp.getThenRegion().front()); + + const Fortran::parser::OpenMPConstruct *parentOmpConstruct = + eval.parentConstruct->getIf(); + assert(parentOmpConstruct && + "Expected a valid enclosing OpenMP construct"); + const Fortran::parser::OpenMPSectionsConstruct *sectionsConstruct = + std::get_if( + &parentOmpConstruct->u); + assert(sectionsConstruct && + "Expected an enclosing omp.sections construct"); + const Fortran::parser::OmpClauseList §ionsEndClauseList = + std::get( + std::get( + sectionsConstruct->t) + .t); + for (const Fortran::parser::OmpClause &otherClause : + sectionsEndClauseList.v) + if (std::get_if( + &otherClause.u)) + // Emit implicit barrier to synchronize threads and avoid data + // races on post-update of lastprivate variables when `nowait` + // clause is present. + firOpBuilder.create( + converter.getCurrentLocation()); + firOpBuilder.setInsertionPointToStart( + &ifOp.getThenRegion().front()); + lastPrivIP = firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPoint(ifOp); + insPt = firOpBuilder.saveInsertionPoint(); + } else { + // Lastprivate operation is inserted at the end + // of the lexically last section in the sections + // construct + mlir::OpBuilder::InsertPoint unstructuredSectionsIP = + firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPointToStart(&op->getRegion(0).back()); + lastPrivIP = firOpBuilder.saveInsertionPoint(); + firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP); + } } } else if (mlir::isa(op)) { mlir::Operation *lastOper = op->getRegion(0).back().getTerminator(); diff --git a/flang/test/Lower/OpenMP/sections.f90 b/flang/test/Lower/OpenMP/sections.f90 --- a/flang/test/Lower/OpenMP/sections.f90 +++ b/flang/test/Lower/OpenMP/sections.f90 @@ -217,4 +217,26 @@ !CHECK: omp.terminator !CHECK: } !$omp end sections nowait + +!CHECK: omp.sections { +!CHECK: omp.section { +!CHECK: %[[PRIVATE_X:.*]] = fir.alloca i32 {bindc_name = "x", pinned, uniq_name = "_QFlastprivateEx"} +!CHECK: cf.br ^bb1 +!CHECK: ^bb1: // pred: ^bb0 +!CHECK: %[[INNER_PRIVATE_X:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref +!CHECK: %[[const:.*]] = arith.constant 1 : i32 +!CHECK: %[[result:.*]] = arith.addi %[[INNER_PRIVATE_X]], %[[const]] : i32 +!CHECK: fir.store %[[result]] to %[[PRIVATE_X]] : !fir.ref +!CHECK: %[[loaded_value:.*]] = fir.load %[[PRIVATE_X]] : !fir.ref +!CHECK: fir.store %[[loaded_value]] to %[[X]] : !fir.ref +!CHECK: omp.terminator +!CHECK: } +!CHECK: omp.terminator +!CHECK: } + + !$omp sections lastprivate(x) + !$omp section + goto 30 + 30 x = x + 1 + !$omp end sections end subroutine