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 @@ -147,39 +147,51 @@ // will optimize away this operation. omp::SectionOp *sectionOp = dyn_cast(&op); - mlir::scf::IfOp ifOp = firOpBuilder.create( - sectionOp->getLoc(), - firOpBuilder.createIntegerConstant( - sectionOp->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()) { + mlir::scf::IfOp ifOp = firOpBuilder.create( + sectionOp->getLoc(), + firOpBuilder.createIntegerConstant( + sectionOp->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 { + mlir::OpBuilder::InsertPoint unstructuredSectionsIP = + firOpBuilder.saveInsertionPoint(); + firOpBuilder.setInsertionPointToStart( + §ionOp->getRegion().back()); + lastPrivIP = firOpBuilder.saveInsertionPoint(); + firOpBuilder.restoreInsertionPoint(unstructuredSectionsIP); + } } } else if (std::is_same_v) { omp::WsLoopOp *wsLoopOp = dyn_cast(&op); @@ -274,9 +286,10 @@ } bool needBarrier = false; - if (mlir::isa(op)) - firOpBuilder.setInsertionPointToStart(&op.getRegion().back()); - else + if (mlir::isa(op)) { + if (!eval.lowerAsUnstructured()) + firOpBuilder.setInsertionPointToStart(&op.getRegion().back()); + } else firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); for (auto sym : privatizedSymbols) { privatizeSymbol(op, converter, sym, &lastPrivIP); 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,24 @@ !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 sections lastprivate(x) + !$omp section + goto 30 + 30 x = x + 1 + !$omp end sections end subroutine