[flang-commits] [flang] 04cb01c - [flang][OpenMP] Lowering for task construct

Shraiysh Vaishay via flang-commits flang-commits at lists.llvm.org
Mon May 9 22:12:18 PDT 2022


Author: Shraiysh Vaishay
Date: 2022-05-10T10:42:08+05:30
New Revision: 04cb01cf102a3ecb52de4cd3f007dceb5698e6a0

URL: https://github.com/llvm/llvm-project/commit/04cb01cf102a3ecb52de4cd3f007dceb5698e6a0
DIFF: https://github.com/llvm/llvm-project/commit/04cb01cf102a3ecb52de4cd3f007dceb5698e6a0.diff

LOG: [flang][OpenMP] Lowering for task construct

This patch adds lowering for task construct from Fortran to
`omp.task` operation in OpenMPDialect Dialect (mlir). Also added tests
for the same.

Reviewed By: kiranchandramohan, peixin

Differential Revision: https://reviews.llvm.org/D124138

Added: 
    flang/test/Lower/OpenMP/task.f90

Modified: 
    flang/lib/Lower/OpenMP.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index 8cc18bea602fc..156aa89c1562e 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -261,10 +261,11 @@ genOMP(Fortran::lower::AbstractConverter &converter,
 
   Fortran::lower::StatementContext stmtCtx;
   llvm::ArrayRef<mlir::Type> argTy;
-  mlir::Value ifClauseOperand, numThreadsClauseOperand;
+  mlir::Value ifClauseOperand, numThreadsClauseOperand, finalClauseOperand,
+      priorityClauseOperand;
   mlir::omp::ClauseProcBindKindAttr procBindKindAttr;
   SmallVector<Value> allocateOperands, allocatorOperands;
-  mlir::UnitAttr nowaitAttr;
+  mlir::UnitAttr nowaitAttr, untiedAttr, mergeableAttr;
 
   const auto &opClauseList =
       std::get<Fortran::parser::OmpClauseList>(beginBlockDirective.t);
@@ -315,6 +316,21 @@ genOMP(Fortran::lower::AbstractConverter &converter,
     } else if (std::get_if<Fortran::parser::OmpClause::Threads>(&clause.u)) {
       // Nothing needs to be done for threads clause.
       continue;
+    } else if (const auto &finalClause =
+                   std::get_if<Fortran::parser::OmpClause::Final>(&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<Fortran::parser::OmpClause::Untied>(&clause.u)) {
+      untiedAttr = firOpBuilder.getUnitAttr();
+    } else if (std::get_if<Fortran::parser::OmpClause::Mergeable>(&clause.u)) {
+      mergeableAttr = firOpBuilder.getUnitAttr();
+    } else if (const auto &priorityClause =
+                   std::get_if<Fortran::parser::OmpClause::Priority>(
+                       &clause.u)) {
+      priorityClauseOperand = fir::getBase(converter.genExprValue(
+          *Fortran::semantics::GetExpr(priorityClause->v), stmtCtx));
     } else {
       TODO(currentLocation, "OpenMP Block construct clauses");
     }
@@ -346,6 +362,13 @@ genOMP(Fortran::lower::AbstractConverter &converter,
     auto orderedOp = firOpBuilder.create<mlir::omp::OrderedRegionOp>(
         currentLocation, /*simd=*/nullptr);
     createBodyOfOp<omp::OrderedRegionOp>(orderedOp, converter, currentLocation);
+  } else if (blockDirective.v == llvm::omp::OMPD_task) {
+    auto taskOp = firOpBuilder.create<mlir::omp::TaskOp>(
+        currentLocation, ifClauseOperand, finalClauseOperand, untiedAttr,
+        mergeableAttr, /*in_reduction_vars=*/ValueRange(),
+        /*in_reductions=*/nullptr, priorityClauseOperand, allocateOperands,
+        allocatorOperands);
+    createBodyOfOp(taskOp, converter, currentLocation, &opClauseList);
   } 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
index 0000000000000..4ad8758771089
--- /dev/null
+++ b/flang/test/Lower/OpenMP/task.f90
@@ -0,0 +1,190 @@
+!RUN: %flang_fc1 -emit-fir -fopenmp %s -o - | FileCheck %s
+
+!CHECK-LABEL: func @_QPomp_task_simple() {
+subroutine omp_task_simple
+  !CHECK: omp.task {
+  !$omp task
+  !CHECK: fir.call @_QPfoo() : () -> ()
+  call foo()
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine omp_task_simple
+
+!===============================================================================
+! `if` clause
+!===============================================================================
+
+!CHECK-LABEL: func @_QPomp_task_if(%{{.+}}) {
+subroutine omp_task_if(bar)
+  logical, intent(inout) :: bar
+  !CHECK: omp.task if(%{{.+}}) {
+  !$omp task if(bar)
+  !CHECK: fir.call @_QPfoo() : () -> ()
+  call foo()
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine omp_task_if
+
+!===============================================================================
+! `final` clause
+!===============================================================================
+
+!CHECK-LABEL: func @_QPomp_task_final(%{{.+}}) {
+subroutine omp_task_final(bar)
+  logical, intent(inout) :: bar
+  !CHECK: omp.task final(%{{.+}}) {
+  !$omp task final(bar)
+  !CHECK: fir.call @_QPfoo() : () -> ()
+  call foo()
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine omp_task_final
+
+!===============================================================================
+! `untied` clause
+!===============================================================================
+
+!CHECK-LABEL: func @_QPomp_task_untied() {
+subroutine omp_task_untied()
+  !CHECK: omp.task untied {
+  !$omp task untied
+  !CHECK: fir.call @_QPfoo() : () -> ()
+  call foo()
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine omp_task_untied
+
+!===============================================================================
+! `mergeable` clause
+!===============================================================================
+
+!CHECK-LABEL: func @_QPomp_task_mergeable() {
+subroutine omp_task_mergeable()
+  !CHECK: omp.task mergeable {
+  !$omp task mergeable
+  !CHECK: fir.call @_QPfoo() : () -> ()
+  call foo()
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine omp_task_mergeable
+
+!===============================================================================
+! `priority` clause
+!===============================================================================
+
+!CHECK-LABEL: func @_QPomp_task_priority(%{{.+}}) {
+subroutine omp_task_priority(bar)
+  integer, intent(inout) :: bar
+  !CHECK: omp.task priority(%{{.+}}) {
+  !$omp task priority(bar)
+  !CHECK: fir.call @_QPfoo() : () -> ()
+  call foo()
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine omp_task_priority
+
+!===============================================================================
+! `allocate` clause
+!===============================================================================
+
+!CHECK-LABEL: func @_QPtask_allocate
+subroutine task_allocate()
+  use omp_lib
+  integer :: x
+  !CHECK: omp.task allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) {
+  !$omp task allocate(omp_high_bw_mem_alloc: x) private(x)
+  !CHECK: arith.addi
+  x = x + 12
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine task_allocate
+
+!===============================================================================
+! `private` clause
+!===============================================================================
+!CHECK-LABEL: func @_QPtask_private
+subroutine task_private
+  type mytype
+  integer :: x
+  end type mytype
+
+  !CHECK: %[[int_var:.+]] = fir.alloca i32
+  !CHECK: %[[mytype_var:.+]] = fir.alloca !fir.type<_QFtask_privateTmytype{x:i32}>
+  integer :: int_var
+  type(mytype) :: mytype_var
+
+  !CHECK: fir.call @_QPbar(%[[int_var]], %[[mytype_var]]) : (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>) -> ()
+  call bar(int_var, mytype_var)
+
+  !CHECK: omp.task {
+  !$omp task private(int_var, mytype_var)
+  !CHECK: %[[int_var_private:.+]] = fir.alloca i32
+  !CHECK: %[[mytype_var_private:.+]] = fir.alloca !fir.type<_QFtask_privateTmytype{x:i32}>
+
+  !CHECK: fir.call @_QPbar(%[[int_var_private]], %[[mytype_var_private]]) : (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_privateTmytype{x:i32}>>) -> ()
+  call bar(int_var, mytype_var)
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine task_private
+
+!===============================================================================
+! `firstprivate` clause
+!===============================================================================
+!CHECK-LABEL: func @_QPtask_firstprivate
+subroutine task_firstprivate
+  type mytype
+  integer :: x
+  end type mytype
+
+  !CHECK: %[[int_var:.+]] = fir.alloca i32
+  !CHECK: %[[mytype_var:.+]] = fir.alloca !fir.type<_QFtask_firstprivateTmytype{x:i32}>
+  integer :: int_var
+  type(mytype) :: mytype_var
+
+  !CHECK: fir.call @_QPbaz(%[[int_var]], %[[mytype_var]]) : (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>) -> ()
+  call baz(int_var, mytype_var)
+
+  !CHECK: omp.task {
+  !$omp task firstprivate(int_var, mytype_var)
+  !CHECK: %[[int_var_firstprivate:.+]] = fir.alloca i32
+  !CHECK: %[[int_var_load:.+]] = fir.load %[[int_var]] : !fir.ref<i32>
+  !CHECK: fir.store %[[int_var_load]] to %[[int_var_firstprivate]] : !fir.ref<i32>
+  !CHECK: %[[mytype_var_firstprivate:.+]] = fir.alloca !fir.type<_QFtask_firstprivateTmytype{x:i32}>
+  !CHECK: %[[mytype_var_load:.+]] = fir.load %[[mytype_var]] : !fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>
+  !CHECK: fir.store %[[mytype_var_load]] to %[[mytype_var_firstprivate]]
+  !CHECK: fir.call @_QPbaz(%[[int_var_firstprivate]], %[[mytype_var_firstprivate]]) : (!fir.ref<i32>, !fir.ref<!fir.type<_QFtask_firstprivateTmytype{x:i32}>>) -> ()
+  call baz(int_var, mytype_var)
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine task_firstprivate
+
+!===============================================================================
+! Multiple clauses
+!===============================================================================
+
+!CHECK-LABEL: func @_QPtask_multiple_clauses
+subroutine task_multiple_clauses()
+  use omp_lib
+
+  !CHECK: %[[x:.+]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFtask_multiple_clausesEx"}
+  !CHECK: %[[y:.+]] = fir.alloca i32 {bindc_name = "y", uniq_name = "_QFtask_multiple_clausesEy"}
+  !CHECK: %[[z:.+]] = fir.alloca i32 {bindc_name = "z", uniq_name = "_QFtask_multiple_clausesEz"}
+  integer :: x, y, z
+  logical :: buzz
+
+  !CHECK: omp.task if(%{{.+}}) final(%{{.+}}) untied mergeable priority(%{{.+}}) allocate(%{{.+}} : i32 -> %{{.+}} : !fir.ref<i32>) {
+  !$omp task if(buzz) final(buzz) untied mergeable priority(z) allocate(omp_high_bw_mem_alloc: x) private(x) firstprivate(y)
+
+  !CHECK: %[[x_priv:.+]] = fir.alloca i32
+  !CHECK: %[[y_priv:.+]] = fir.alloca i32
+  !CHECK: %[[y_load:.+]] = fir.load %[[y]] : !fir.ref<i32>
+  !CHECK: fir.store %[[y_load]] to %[[y_priv]] : !fir.ref<i32>
+
+  !CHECK: arith.addi
+  x = x + 12
+  !CHECK: arith.subi
+  y = y - 12
+
+  !CHECK: omp.terminator
+  !$omp end task
+end subroutine task_multiple_clauses


        


More information about the flang-commits mailing list