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 @@ -243,10 +243,11 @@ Fortran::lower::StatementContext stmtCtx; llvm::ArrayRef argTy; - mlir::Value ifClauseOperand, numThreadsClauseOperand; + mlir::Value ifClauseOperand, numThreadsClauseOperand, finalClauseOperand, + priorityClauseOperand; mlir::omp::ClauseProcBindKindAttr procBindKindAttr; SmallVector allocateOperands, allocatorOperands; - mlir::UnitAttr nowaitAttr; + mlir::UnitAttr nowaitAttr, untiedAttr, mergeableAttr; const auto &opClauseList = std::get(beginBlockDirective.t); @@ -254,8 +255,10 @@ if (const auto &ifClause = std::get_if(&clause.u)) { auto &expr = std::get(ifClause->v.t); - ifClauseOperand = fir::getBase( + mlir::Value ifVal = fir::getBase( converter.genExprValue(*Fortran::semantics::GetExpr(expr), stmtCtx)); + ifClauseOperand = firOpBuilder.createConvert( + currentLocation, firOpBuilder.getI1Type(), ifVal); } else if (const auto &numThreadsClause = std::get_if( &clause.u)) { @@ -295,6 +298,21 @@ } else if (std::get_if(&clause.u)) { // Nothing needs to be done for threads clause. continue; + } else if (const auto &finalClause = + std::get_if(&clause.u)) { + mlir::Value finalVal = fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(finalClause->v), stmtCtx)); + finalClauseOperand = firOpBuilder.createConvert( + currentLocation, firOpBuilder.getI1Type(), finalVal); + } else if (std::get_if(&clause.u)) { + untiedAttr = firOpBuilder.getUnitAttr(); + } else if (std::get_if(&clause.u)) { + mergeableAttr = firOpBuilder.getUnitAttr(); + } else if (const auto &priorityClause = + std::get_if( + &clause.u)) { + priorityClauseOperand = fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(priorityClause->v), stmtCtx)); } else { TODO(currentLocation, "OpenMP Block construct clauses"); } @@ -326,6 +344,13 @@ auto orderedOp = firOpBuilder.create( currentLocation, /*simd=*/nullptr); createBodyOfOp(orderedOp, converter, currentLocation); + } else if (blockDirective.v == llvm::omp::OMPD_task) { + auto taskOp = firOpBuilder.create( + currentLocation, ifClauseOperand, finalClauseOperand, untiedAttr, + mergeableAttr, /*in_reduction_vars=*/ValueRange(), + /*in_reductions=*/nullptr, priorityClauseOperand, allocateOperands, + allocatorOperands); + createBodyOfOp(taskOp, converter, currentLocation); } else { TODO(converter.getCurrentLocation(), "Unhandled block directive"); } diff --git a/flang/test/Lower/OpenMP/task.f90 b/flang/test/Lower/OpenMP/task.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenMP/task.f90 @@ -0,0 +1,119 @@ +!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s --check-prefixes="FIRDialect,OMPDialect" +!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | fir-opt --fir-to-llvm-ir | FileCheck %s --check-prefixes="OMPDialect" + +!FIRDialect-LABEL: func @_QPomp_task_simple() { +subroutine omp_task_simple + !OMPDialect: omp.task { + !$omp task + !FIRDialect: fir.call @_QPfoo() : () -> () + call foo() + !OMPDialect: omp.terminator + !$omp end task +end subroutine omp_task_simple + +!=============================================================================== +! `if` clause +!=============================================================================== + +!FIRDialect-LABEL: func @_QPomp_task_if(%{{.+}}) { +subroutine omp_task_if(bar) + logical, intent(inout) :: bar + !OMPDialect: omp.task if(%{{.+}}) { + !$omp task if(bar) + !FIRDialect: fir.call @_QPfoo() : () -> () + call foo() + !OMPDialect: omp.terminator + !$omp end task +end subroutine omp_task_if + +!=============================================================================== +! `final` clause +!=============================================================================== + +!FIRDialect-LABEL: func @_QPomp_task_final(%{{.+}}) { +subroutine omp_task_final(bar) + logical, intent(inout) :: bar + !OMPDialect: omp.task final(%{{.+}}) { + !$omp task final(bar) + !FIRDialect: fir.call @_QPfoo() : () -> () + call foo() + !OMPDialect: omp.terminator + !$omp end task +end subroutine omp_task_final + +!=============================================================================== +! `untied` clause +!=============================================================================== + +!FIRDialect-LABEL: func @_QPomp_task_untied() { +subroutine omp_task_untied() + !OMPDialect: omp.task untied { + !$omp task untied + !FIRDialect: fir.call @_QPfoo() : () -> () + call foo() + !OMPDialect: omp.terminator + !$omp end task +end subroutine omp_task_untied + +!=============================================================================== +! `mergeable` clause +!=============================================================================== + +!FIRDialect-LABEL: func @_QPomp_task_mergeable() { +subroutine omp_task_mergeable() + !OMPDialect: omp.task mergeable { + !$omp task mergeable + !FIRDialect: fir.call @_QPfoo() : () -> () + call foo() + !OMPDialect: omp.terminator + !$omp end task +end subroutine omp_task_mergeable + +!=============================================================================== +! `priority` clause +!=============================================================================== + +!FIRDialect-LABEL: func @_QPomp_task_priority(%{{.+}}) { +subroutine omp_task_priority(bar) + integer, intent(inout) :: bar + !OMPDialect: omp.task priority(%{{.+}}) { + !$omp task priority(bar) + !FIRDialect: fir.call @_QPfoo() : () -> () + call foo() + !OMPDialect: omp.terminator + !$omp end task +end subroutine omp_task_priority + +!=============================================================================== +! `allocate` clause +!=============================================================================== + +!FIRDialect-LABEL: func @_QPtask_allocate +subroutine task_allocate() + use omp_lib + integer :: x + !OMPDialect: omp.task allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref) { + !$omp task allocate(omp_high_bw_mem_alloc: x) private(x) + !FIRDialect: arith.addi + x = x + 12 + !OMPDialect: omp.terminator + !$omp end task +end subroutine task_allocate + +!=============================================================================== +! Multiple clauses +!=============================================================================== + +!FIRDialect-LABEL: func @_QPtask_multiple_clauses +subroutine task_multiple_clauses(bar, buzz) + use omp_lib + integer, intent(inout) :: bar + logical, intent(inout) :: buzz + integer :: x + !OMPDialect: omp.task if(%{{.+}}) final(%{{.+}}) untied mergeable priority(%{{.+}}) allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref) { + !$omp task if(buzz) final(buzz) untied mergeable priority(bar) allocate(omp_high_bw_mem_alloc: x) private(x) + !FIRDialect: arith.addi + x = x + 12 + !OMPDialect: omp.terminator + !$omp end task +end subroutine task_multiple_clauses