[flang-commits] [flang] 1d32844 - [flang][OpenMP] Upstream lowering of `ParallelOp` clauses

Sourabh Singh Tomar via flang-commits flang-commits at lists.llvm.org
Fri Oct 23 07:51:47 PDT 2020


Author: Sourabh Singh Tomar
Date: 2020-10-23T20:21:39+05:30
New Revision: 1d328446bf92f76f1861d0e5f84d67732d76c8fd

URL: https://github.com/llvm/llvm-project/commit/1d328446bf92f76f1861d0e5f84d67732d76c8fd
DIFF: https://github.com/llvm/llvm-project/commit/1d328446bf92f76f1861d0e5f84d67732d76c8fd.diff

LOG: [flang][OpenMP] Upstream lowering of `ParallelOp` clauses

Note: This patch reflects the work that can be upstreamed from PR's(merged):

1. https://github.com/flang-compiler/f18-llvm-project/pull/456
2. https://github.com/flang-compiler/f18-llvm-project/pull/485

Also replaced TODO with new TODO.

Reviewed By: kiranchandramohan

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

Added: 
    

Modified: 
    flang/lib/Lower/OpenMP.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp
index 169e225bdae9..9c9c0a298dd6 100644
--- a/flang/lib/Lower/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP.cpp
@@ -11,15 +11,54 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Lower/OpenMP.h"
+#include "flang/Common/idioms.h"
 #include "flang/Lower/Bridge.h"
 #include "flang/Lower/FIRBuilder.h"
 #include "flang/Lower/PFTBuilder.h"
+#include "flang/Lower/Support/BoxValue.h"
+#include "flang/Lower/Todo.h"
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/tools.h"
 #include "mlir/Dialect/OpenMP/OpenMPDialect.h"
 #include "llvm/Frontend/OpenMP/OMPConstants.h"
 
-#define TODO() llvm_unreachable("not yet implemented")
+static const Fortran::parser::Name *
+getDesignatorNameIfDataRef(const Fortran::parser::Designator &designator) {
+  const auto *dataRef = std::get_if<Fortran::parser::DataRef>(&designator.u);
+  return dataRef ? std::get_if<Fortran::parser::Name>(&dataRef->u) : nullptr;
+}
+
+static void genObjectList(const Fortran::parser::OmpObjectList &objectList,
+                          Fortran::lower::AbstractConverter &converter,
+                          SmallVectorImpl<Value> &operands) {
+  for (const auto &ompObject : objectList.v) {
+    std::visit(
+        Fortran::common::visitors{
+            [&](const Fortran::parser::Designator &designator) {
+              if (const auto *name = getDesignatorNameIfDataRef(designator)) {
+                const auto variable = converter.getSymbolAddress(*name->symbol);
+                operands.push_back(variable);
+              }
+            },
+            [&](const Fortran::parser::Name &name) {
+              const auto variable = converter.getSymbolAddress(*name.symbol);
+              operands.push_back(variable);
+            }},
+        ompObject.u);
+  }
+}
+
+template <typename Op>
+static void createBodyOfOp(Op &op, Fortran::lower::FirOpBuilder &firOpBuilder,
+                           mlir::Location &loc) {
+  firOpBuilder.createBlock(&op.getRegion());
+  auto &block = op.getRegion().back();
+  firOpBuilder.setInsertionPointToStart(&block);
+  // Ensure the block is well-formed.
+  firOpBuilder.create<mlir::omp::TerminatorOp>(loc);
+  // Reset the insertion point to the start of the first block.
+  firOpBuilder.setInsertionPointToStart(&block);
+}
 
 static void genOMP(Fortran::lower::AbstractConverter &converter,
                    Fortran::lower::pft::Evaluation &eval,
@@ -44,13 +83,13 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
         converter.getCurrentLocation());
     break;
   case llvm::omp::Directive::OMPD_target_enter_data:
-    TODO();
+    TODO("");
   case llvm::omp::Directive::OMPD_target_exit_data:
-    TODO();
+    TODO("");
   case llvm::omp::Directive::OMPD_target_update:
-    TODO();
+    TODO("");
   case llvm::omp::Directive::OMPD_ordered:
-    TODO();
+    TODO("");
   }
 }
 
@@ -68,10 +107,10 @@ genOMP(Fortran::lower::AbstractConverter &converter,
             TODO();
           },
           [&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) {
-            TODO();
+            TODO("");
           },
           [&](const Fortran::parser::OpenMPCancellationPointConstruct
-                  &cancellationPointConstruct) { TODO(); },
+                  &cancellationPointConstruct) { TODO(""); },
       },
       standaloneConstruct.u);
 }
@@ -80,45 +119,115 @@ static void
 genOMP(Fortran::lower::AbstractConverter &converter,
        Fortran::lower::pft::Evaluation &eval,
        const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
-  const auto &blockDirective =
+  const auto &beginBlockDirective =
       std::get<Fortran::parser::OmpBeginBlockDirective>(blockConstruct.t);
-  const auto &parallelDirective =
-      std::get<Fortran::parser::OmpBlockDirective>(blockDirective.t);
-  if (parallelDirective.v == llvm::omp::OMPD_parallel) {
-    auto &firOpBuilder = converter.getFirOpBuilder();
-    auto currentLocation = converter.getCurrentLocation();
+  const auto &blockDirective =
+      std::get<Fortran::parser::OmpBlockDirective>(beginBlockDirective.t);
 
-    // Clauses.
-    // FIXME: Add support for other clauses.
-    mlir::Value numThreads;
+  auto &firOpBuilder = converter.getFirOpBuilder();
+  auto currentLocation = converter.getCurrentLocation();
+  llvm::ArrayRef<mlir::Type> argTy;
+  if (blockDirective.v == llvm::omp::OMPD_parallel) {
+
+    mlir::Value ifClauseOperand, numThreadsClauseOperand;
+    SmallVector<Value, 4> privateClauseOperands, firstprivateClauseOperands,
+        sharedClauseOperands, copyinClauseOperands;
+    Attribute defaultClauseOperand, procBindClauseOperand;
 
     const auto &parallelOpClauseList =
-        std::get<Fortran::parser::OmpClauseList>(blockDirective.t);
+        std::get<Fortran::parser::OmpClauseList>(beginBlockDirective.t);
     for (const auto &clause : parallelOpClauseList.v) {
-      if (const auto &numThreadsClause =
-              std::get_if<Fortran::parser::OmpClause::NumThreads>(&clause.u)) {
+      if (const auto &ifClause =
+              std::get_if<Fortran::parser::OmpIfClause>(&clause.u)) {
+        auto &expr = std::get<Fortran::parser::ScalarLogicalExpr>(ifClause->t);
+        ifClauseOperand = fir::getBase(
+            converter.genExprValue(*Fortran::semantics::GetExpr(expr)));
+      } else if (const auto &numThreadsClause =
+                     std::get_if<Fortran::parser::OmpClause::NumThreads>(
+                         &clause.u)) {
         // OMPIRBuilder expects `NUM_THREAD` clause as a `Value`.
-        numThreads = converter.genExprValue(
-            *Fortran::semantics::GetExpr(numThreadsClause->v));
+        numThreadsClauseOperand = fir::getBase(converter.genExprValue(
+            *Fortran::semantics::GetExpr(numThreadsClause->v)));
+      } else if (const auto &privateClause =
+                     std::get_if<Fortran::parser::OmpClause::Private>(
+                         &clause.u)) {
+        const Fortran::parser::OmpObjectList &ompObjectList = privateClause->v;
+        genObjectList(ompObjectList, converter, privateClauseOperands);
+      } else if (const auto &firstprivateClause =
+                     std::get_if<Fortran::parser::OmpClause::Firstprivate>(
+                         &clause.u)) {
+        const Fortran::parser::OmpObjectList &ompObjectList =
+            firstprivateClause->v;
+        genObjectList(ompObjectList, converter, firstprivateClauseOperands);
+      } else if (const auto &sharedClause =
+                     std::get_if<Fortran::parser::OmpClause::Shared>(
+                         &clause.u)) {
+        const Fortran::parser::OmpObjectList &ompObjectList = sharedClause->v;
+        genObjectList(ompObjectList, converter, sharedClauseOperands);
+      } else if (const auto &copyinClause =
+                     std::get_if<Fortran::parser::OmpClause::Copyin>(
+                         &clause.u)) {
+        const Fortran::parser::OmpObjectList &ompObjectList = copyinClause->v;
+        genObjectList(ompObjectList, converter, copyinClauseOperands);
       }
     }
-    llvm::ArrayRef<mlir::Type> argTy;
-    Attribute defaultValue, procBindValue;
     // Create and insert the operation.
-    // Create the Op with empty ranges for clauses that are yet to be lowered.
     auto parallelOp = firOpBuilder.create<mlir::omp::ParallelOp>(
-        currentLocation, argTy, Value(), numThreads,
-        defaultValue.dyn_cast_or_null<StringAttr>(), ValueRange(), ValueRange(),
-        ValueRange(), ValueRange(), ValueRange(), ValueRange(),
-        procBindValue.dyn_cast_or_null<StringAttr>());
-    firOpBuilder.createBlock(&parallelOp.getRegion());
-    auto &block = parallelOp.getRegion().back();
-    firOpBuilder.setInsertionPointToStart(&block);
-    // Ensure the block is well-formed.
-    firOpBuilder.create<mlir::omp::TerminatorOp>(currentLocation);
-
-    // Place the insertion point to the start of the first block.
-    firOpBuilder.setInsertionPointToStart(&block);
+        currentLocation, argTy, ifClauseOperand, numThreadsClauseOperand,
+        defaultClauseOperand.dyn_cast_or_null<StringAttr>(),
+        privateClauseOperands, firstprivateClauseOperands, sharedClauseOperands,
+        copyinClauseOperands, ValueRange(), ValueRange(),
+        procBindClauseOperand.dyn_cast_or_null<StringAttr>());
+    // Handle attribute based clauses.
+    for (const auto &clause : parallelOpClauseList.v) {
+      if (const auto &defaultClause =
+              std::get_if<Fortran::parser::OmpDefaultClause>(&clause.u)) {
+        switch (defaultClause->v) {
+        case Fortran::parser::OmpDefaultClause::Type::Private:
+          parallelOp.default_valAttr(firOpBuilder.getStringAttr(
+              omp::stringifyClauseDefault(omp::ClauseDefault::defprivate)));
+          break;
+        case Fortran::parser::OmpDefaultClause::Type::Firstprivate:
+          parallelOp.default_valAttr(
+              firOpBuilder.getStringAttr(omp::stringifyClauseDefault(
+                  omp::ClauseDefault::deffirstprivate)));
+          break;
+        case Fortran::parser::OmpDefaultClause::Type::Shared:
+          parallelOp.default_valAttr(firOpBuilder.getStringAttr(
+              omp::stringifyClauseDefault(omp::ClauseDefault::defshared)));
+          break;
+        case Fortran::parser::OmpDefaultClause::Type::None:
+          parallelOp.default_valAttr(firOpBuilder.getStringAttr(
+              omp::stringifyClauseDefault(omp::ClauseDefault::defnone)));
+          break;
+        }
+      }
+      if (const auto &procBindClause =
+              std::get_if<Fortran::parser::OmpProcBindClause>(&clause.u)) {
+        switch (procBindClause->v) {
+        case Fortran::parser::OmpProcBindClause::Type::Master:
+          parallelOp.proc_bind_valAttr(
+              firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind(
+                  omp::ClauseProcBindKind::master)));
+          break;
+        case Fortran::parser::OmpProcBindClause::Type::Close:
+          parallelOp.proc_bind_valAttr(
+              firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind(
+                  omp::ClauseProcBindKind::close)));
+          break;
+        case Fortran::parser::OmpProcBindClause::Type::Spread:
+          parallelOp.proc_bind_valAttr(
+              firOpBuilder.getStringAttr(omp::stringifyClauseProcBindKind(
+                  omp::ClauseProcBindKind::spread)));
+          break;
+        }
+      }
+    }
+    createBodyOfOp<omp::ParallelOp>(parallelOp, firOpBuilder, currentLocation);
+  } else if (blockDirective.v == llvm::omp::OMPD_master) {
+    auto masterOp =
+        firOpBuilder.create<mlir::omp::MasterOp>(currentLocation, argTy);
+    createBodyOfOp<omp::MasterOp>(masterOp, firOpBuilder, currentLocation);
   }
 }
 
@@ -134,18 +243,18 @@ void Fortran::lower::genOpenMPConstruct(
             genOMP(converter, eval, standaloneConstruct);
           },
           [&](const Fortran::parser::OpenMPSectionsConstruct
-                  &sectionsConstruct) { TODO(); },
+                  &sectionsConstruct) { TODO(""); },
           [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
-            TODO();
+            TODO("");
           },
           [&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) {
             genOMP(converter, eval, blockConstruct);
           },
           [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) {
-            TODO();
+            TODO("");
           },
           [&](const Fortran::parser::OpenMPCriticalConstruct
-                  &criticalConstruct) { TODO(); },
+                  &criticalConstruct) { TODO(""); },
       },
       ompConstruct.u);
 }
@@ -153,5 +262,5 @@ void Fortran::lower::genOpenMPConstruct(
 void Fortran::lower::genOpenMPEndLoop(
     Fortran::lower::AbstractConverter &, Fortran::lower::pft::Evaluation &,
     const Fortran::parser::OmpEndLoopDirective &) {
-  TODO();
+  TODO("");
 }


        


More information about the flang-commits mailing list