diff --git a/flang/include/flang/Lower/OpenMP.h b/flang/include/flang/Lower/OpenMP.h --- a/flang/include/flang/Lower/OpenMP.h +++ b/flang/include/flang/Lower/OpenMP.h @@ -33,7 +33,9 @@ } // namespace pft void genOpenMPConstruct(AbstractConverter &, pft::Evaluation &, - const parser::OpenMPConstruct &); + const parser::OpenMPConstruct &, + const Fortran::parser::OmpClauseList + *ompParentConstructClauseList = nullptr); void genOpenMPDeclarativeConstruct(AbstractConverter &, pft::Evaluation &, const parser::OpenMPDeclarativeConstruct &); int64_t getCollapseValue(const Fortran::parser::OmpClauseList &clauseList); diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -1639,6 +1639,7 @@ void genFIR(const Fortran::parser::OpenMPConstruct &omp) { mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint(); localSymbols.pushScope(); + genOpenMPConstruct(*this, getEval(), omp); const Fortran::parser::OpenMPLoopConstruct *ompLoop = @@ -1664,8 +1665,35 @@ } } - for (Fortran::lower::pft::Evaluation &e : curEval->getNestedEvaluations()) - genFIR(e); + const Fortran::parser::OmpClauseList *ompSectionsClauseList = nullptr; + if (const auto ompSections = + std::get_if(&omp.u)) { + const Fortran::parser::OmpBeginSectionsDirective + &ompbeginSectionsDirective = + std::get( + ompSections->t); + const Fortran::parser::OmpClauseList *ompSectionsClauseList = + &std::get( + ompbeginSectionsDirective.t); + const Fortran::parser::OmpSectionBlocks &ompSectionBlocks = + std::get(ompSections->t); + auto ompSectionBlocksIter = ompSectionBlocks.v.begin(); + for (Fortran::lower::pft::Evaluation &e : + curEval->getNestedEvaluations()) { + mlir::OpBuilder::InsertPoint insertPt = builder->saveInsertionPoint(); + localSymbols.pushScope(); + genOpenMPConstruct(*this, e, *ompSectionBlocksIter, + ompSectionsClauseList); + for (Fortran::lower::pft::Evaluation §ionBlockEvaluation : + e.getNestedEvaluations()) + genFIR(sectionBlockEvaluation); + localSymbols.popScope(); + builder->restoreInsertionPoint(insertPt); + ompSectionBlocksIter++; + } + } else + for (Fortran::lower::pft::Evaluation &e : curEval->getNestedEvaluations()) + genFIR(e); if (ompLoop) genOpenMPReduction(*this, *loopOpClauseList); 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 @@ -88,12 +88,14 @@ const Fortran::parser::OmpClauseList &opClauseList) { fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); auto insPt = firOpBuilder.saveInsertionPoint(); - firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); + if (mlir::isa(op)) + firOpBuilder.setInsertionPointToStart(&op.getRegion().back()); + else + firOpBuilder.setInsertionPointToStart(firOpBuilder.getAllocaBlock()); bool hasFirstPrivateOp = false; bool hasLastPrivateOp = false; // We need just one ICmpOp for multiple LastPrivate clauses. mlir::arith::CmpIOp cmpOp; - for (const Fortran::parser::OmpClause &clause : opClauseList.v) { if (const auto &privateClause = std::get_if(&clause.u)) { @@ -1180,13 +1182,20 @@ static void genOMP(Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { + const Fortran::parser::OpenMPSectionConstruct §ionConstruct, + const Fortran::parser::OmpClauseList *ompParentConstructClauseList = + nullptr) { auto &firOpBuilder = converter.getFirOpBuilder(); auto currentLocation = converter.getCurrentLocation(); mlir::omp::SectionOp sectionOp = firOpBuilder.create(currentLocation); - createBodyOfOp(sectionOp, converter, currentLocation, eval); + // TODO: For private/firstprivate symbols defined on `omp.sections` + // operations, + // // inside each `omp.section` region, privatize only the symbols used in + // that `omp.section` region. + createBodyOfOp(sectionOp, converter, currentLocation, eval, + ompParentConstructClauseList); } // TODO: Add support for reduction @@ -1482,7 +1491,8 @@ void Fortran::lower::genOpenMPConstruct( Fortran::lower::AbstractConverter &converter, Fortran::lower::pft::Evaluation &eval, - const Fortran::parser::OpenMPConstruct &ompConstruct) { + const Fortran::parser::OpenMPConstruct &ompConstruct, + const Fortran::parser::OmpClauseList *ompParentConstructClauseList) { std::visit( common::visitors{ @@ -1495,7 +1505,8 @@ genOMP(converter, eval, sectionsConstruct); }, [&](const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { - genOMP(converter, eval, sectionConstruct); + genOMP(converter, eval, sectionConstruct, + ompParentConstructClauseList); }, [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { genOMP(converter, eval, loopConstruct); 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 @@ -4,44 +4,49 @@ !CHECK: func @_QQmain() { !CHECK: %[[COUNT:.*]] = fir.address_of(@_QFEcount) : !fir.ref -!CHECK: %[[DOUBLE_COUNT:.*]] = fir.address_of(@_QFEdouble_count) : !fir.ref !CHECK: %[[ETA:.*]] = fir.alloca f32 {bindc_name = "eta", uniq_name = "_QFEeta"} !CHECK: %[[CONST_1:.*]] = arith.constant 1 : i32 !CHECK: omp.sections allocate(%[[CONST_1]] : i32 -> %0 : !fir.ref) { !CHECK: omp.section { -!CHECK: {{.*}} = arith.constant 5 : i32 -!CHECK: fir.store {{.*}} to {{.*}} : !fir.ref -!CHECK: {{.*}} = fir.load %[[COUNT]] : !fir.ref -!CHECK: {{.*}} = fir.load %[[DOUBLE_COUNT]] : !fir.ref -!CHECK: {{.*}} = arith.muli {{.*}}, {{.*}} : i32 -!CHECK: {{.*}} = fir.convert {{.*}} : (i32) -> f32 -!CHECK: fir.store {{.*}} to %[[ETA]] : !fir.ref +!CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"} +!CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"} +!CHECK: %[[const:.*]] = arith.constant 5 : i32 +!CHECK: fir.store %[[const]] to %[[COUNT]] : !fir.ref +!CHECK: %[[temp_count:.*]] = fir.load %[[COUNT]] : !fir.ref +!CHECK: %[[temp_double_count:.*]] = fir.load %[[PRIVATE_DOUBLE_COUNT]] : !fir.ref +!CHECK: %[[result:.*]] = arith.muli %[[temp_count]], %[[temp_double_count]] : i32 +!CHECK: {{.*}} = fir.convert %[[result]] : (i32) -> f32 +!CHECK: fir.store {{.*}} to %[[PRIVATE_ETA]] : !fir.ref !CHECK: omp.terminator !CHECK: } !CHECK: omp.section { -!CHECK: {{.*}} = fir.load %[[DOUBLE_COUNT]] : !fir.ref -!CHECK: {{.*}} = arith.constant 1 : i32 -!CHECK: {{.*}} = arith.addi {{.*}} : i32 -!CHECK: fir.store {{.*}} to %[[DOUBLE_COUNT]] : !fir.ref +!CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"} +!CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"} +!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_DOUBLE_COUNT]] : !fir.ref +!CHECK: %[[const:.*]] = arith.constant 1 : i32 +!CHECK: %[[result:.*]] = arith.addi %[[temp]], %[[const]] : i32 +!CHECK: fir.store %[[result]] to %[[PRIVATE_DOUBLE_COUNT]] : !fir.ref !CHECK: omp.terminator !CHECK: } !CHECK: omp.section { -!CHECK: {{.*}} = fir.load %[[ETA]] : !fir.ref -!CHECK: {{.*}} = arith.constant 7.000000e+00 : f32 -!CHECK: {{.*}} = arith.subf {{.*}} : f32 -!CHECK: fir.store {{.*}} to %[[ETA]] : !fir.ref +!CHECK: %[[PRIVATE_ETA:.*]] = fir.alloca f32 {bindc_name = "eta", pinned, uniq_name = "_QFEeta"} +!CHECK: %[[PRIVATE_DOUBLE_COUNT:.*]] = fir.alloca i32 {bindc_name = "double_count", pinned, uniq_name = "_QFEdouble_count"} +!CHECK: %[[temp:.*]] = fir.load %[[PRIVATE_ETA]] : !fir.ref +!CHECK: %[[const:.*]] = arith.constant 7.000000e+00 : f32 +!CHECK: %[[result:.*]] = arith.subf %[[temp]], %[[const]] : f32 +!CHECK: fir.store %[[result]] to %[[PRIVATE_ETA]] : !fir.ref !CHECK: {{.*}} = fir.load %[[COUNT]] : !fir.ref -!CHECK: {{.*}} = fir.convert {{.*}} : (i32) -> f32 -!CHECK: {{.*}} = fir.load %[[ETA]] : !fir.ref -!CHECK: {{.*}} = arith.mulf {{.*}}, {{.*}} : f32 -!CHECK: {{.*}} = fir.convert {{.*}} : (f32) -> i32 -!CHECK: fir.store {{.*}} to %[[COUNT]] : !fir.ref +!CHECK: %[[temp_count:.*]] = fir.convert {{.*}} : (i32) -> f32 +!CHECK: %[[temp_eta:.*]] = fir.load %[[PRIVATE_ETA]] : !fir.ref +!CHECK: {{.*}} = arith.mulf %[[temp_count]], %[[temp_eta]] : f32 +!CHECK: %[[result:.*]] = fir.convert {{.*}} : (f32) -> i32 +!CHECK: fir.store %[[result]] to %[[COUNT]] : !fir.ref !CHECK: {{.*}} = fir.load %[[COUNT]] : !fir.ref -!CHECK: {{.*}} = fir.convert {{.*}} : (i32) -> f32 -!CHECK: {{.*}} = fir.load %[[ETA]] : !fir.ref -!CHECK: {{.*}} = arith.subf {{.*}}, {{.*}} : f32 -!CHECK: {{.*}} = fir.convert {{.*}} : (f32) -> i32 -!CHECK: fir.store {{.*}} to %[[DOUBLE_COUNT]] : !fir.ref +!CHECK: %[[temp_count:.*]] = fir.convert {{.*}} : (i32) -> f32 +!CHECK: %[[temp_eta:.*]] = fir.load %[[PRIVATE_ETA]] : !fir.ref +!CHECK: {{.*}} = arith.subf %[[temp_count]], %[[temp_eta]] : f32 +!CHECK: %[[result:.*]] = fir.convert {{.*}} : (f32) -> i32 +!CHECK: fir.store %[[result]] to %[[PRIVATE_DOUBLE_COUNT]] : !fir.ref !CHECK: omp.terminator !CHECK: } !CHECK: omp.terminator @@ -74,6 +79,10 @@ !CHECK: func @_QPfirstprivate(%[[ARG:.*]]: !fir.ref {fir.bindc_name = "alpha"}) { !CHECK: omp.sections { !CHECK: omp.section { +!CHECK: %[[PRIVATE_ALPHA:.*]] = fir.alloca f32 {bindc_name = "alpha", pinned, uniq_name = "_QFfirstprivateEalpha"} +!CHECK: %[[temp:.*]] = fir.load %[[ARG]] : !fir.ref +!CHECK: fir.store %[[temp]] to %[[PRIVATE_ALPHA]] : !fir.ref +!CHECK: omp.barrier !CHECK: omp.terminator !CHECK: } !CHECK: omp.terminator diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp --- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp @@ -636,9 +636,6 @@ assert(isa(*sectionsOp.region().op_begin())); - // TODO: Perform appropriate actions according to the data-sharing - // attribute (shared, private, firstprivate, ...) of variables. - // Currently defaults to shared. auto privCB = [&](InsertPointTy, InsertPointTy codeGenIP, llvm::Value &, llvm::Value &vPtr, llvm::Value *&replacementValue) -> InsertPointTy {