[flang-commits] [flang] e944455 - [flang][openacc] Lower parallel construct

via flang-commits flang-commits at lists.llvm.org
Mon Oct 12 10:23:32 PDT 2020


Author: Valentin Clement
Date: 2020-10-12T13:23:23-04:00
New Revision: e944455eaf1ed3b3bfe9876c5478ce18e9975eea

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

LOG: [flang][openacc] Lower parallel construct

This patch upstream the lowering of Parallel construct that was initially done in
https://github.com/flang-compiler/f18-llvm-project/pull/460.

Reviewed By: jeanPerier

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

Added: 
    

Modified: 
    flang/lib/Lower/OpenACC.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index ce97fc393b30..1d8f9f4ccfff 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -49,6 +49,26 @@ static void genObjectList(const Fortran::parser::AccObjectList &objectList,
   }
 }
 
+template <typename Clause>
+static void
+genObjectListWithModifier(const Clause *x,
+                          Fortran::lower::AbstractConverter &converter,
+                          Fortran::parser::AccDataModifier::Modifier mod,
+                          SmallVectorImpl<Value> &operandsWithModifier,
+                          SmallVectorImpl<Value> &operands) {
+  const Fortran::parser::AccObjectListWithModifier &listWithModifier = x->v;
+  const Fortran::parser::AccObjectList &accObjectList =
+      std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+  const auto &modifier =
+      std::get<std::optional<Fortran::parser::AccDataModifier>>(
+          listWithModifier.t);
+  if (modifier && (*modifier).v == mod) {
+    genObjectList(accObjectList, converter, operandsWithModifier);
+  } else {
+    genObjectList(accObjectList, converter, operands);
+  }
+}
+
 static void addOperands(SmallVectorImpl<Value> &operands,
                         SmallVectorImpl<int32_t> &operandSegments,
                         const SmallVectorImpl<Value> &clauseOperands) {
@@ -228,6 +248,193 @@ static void genACC(Fortran::lower::AbstractConverter &converter,
   }
 }
 
+static void
+genACCParallelOp(Fortran::lower::AbstractConverter &converter,
+                 const Fortran::parser::AccClauseList &accClauseList) {
+  mlir::Value async;
+  mlir::Value numGangs;
+  mlir::Value numWorkers;
+  mlir::Value vectorLength;
+  mlir::Value ifCond;
+  mlir::Value selfCond;
+  SmallVector<Value, 2> waitOperands, reductionOperands, copyOperands,
+      copyinOperands, copyinReadonlyOperands, copyoutOperands,
+      copyoutZeroOperands, createOperands, createZeroOperands, noCreateOperands,
+      presentOperands, devicePtrOperands, attachOperands, privateOperands,
+      firstprivateOperands;
+
+  // Async, wait and self clause have optional values but can be present with
+  // no value as well. When there is no value, the op has an attribute to
+  // represent the clause.
+  bool addAsyncAttr = false;
+  bool addWaitAttr = false;
+  bool addSelfAttr = false;
+
+  auto &firOpBuilder = converter.getFirOpBuilder();
+  auto currentLocation = converter.getCurrentLocation();
+
+  // Lower clauses values mapped to operands.
+  // Keep track of each group of operands separatly as clauses can appear
+  // more than once.
+  for (const auto &clause : accClauseList.v) {
+    if (const auto *asyncClause =
+            std::get_if<Fortran::parser::AccClause::Async>(&clause.u)) {
+      const auto &asyncClauseValue = asyncClause->v;
+      if (asyncClauseValue) { // async has a value.
+        async = fir::getBase(converter.genExprValue(
+            *Fortran::semantics::GetExpr(*asyncClauseValue)));
+      } else {
+        addAsyncAttr = true;
+      }
+    } else if (const auto *waitClause =
+                   std::get_if<Fortran::parser::AccClause::Wait>(&clause.u)) {
+      const auto &waitClauseValue = waitClause->v;
+      if (waitClauseValue) { // wait has a value.
+        const Fortran::parser::AccWaitArgument &waitArg = *waitClauseValue;
+        const std::list<Fortran::parser::ScalarIntExpr> &waitList =
+            std::get<std::list<Fortran::parser::ScalarIntExpr>>(waitArg.t);
+        for (const Fortran::parser::ScalarIntExpr &value : waitList) {
+          Value v = fir::getBase(
+              converter.genExprValue(*Fortran::semantics::GetExpr(value)));
+          waitOperands.push_back(v);
+        }
+      } else {
+        addWaitAttr = true;
+      }
+    } else if (const auto *numGangsClause =
+                   std::get_if<Fortran::parser::AccClause::NumGangs>(
+                       &clause.u)) {
+      numGangs = fir::getBase(converter.genExprValue(
+          *Fortran::semantics::GetExpr(numGangsClause->v)));
+    } else if (const auto *numWorkersClause =
+                   std::get_if<Fortran::parser::AccClause::NumWorkers>(
+                       &clause.u)) {
+      numWorkers = fir::getBase(converter.genExprValue(
+          *Fortran::semantics::GetExpr(numWorkersClause->v)));
+    } else if (const auto *vectorLengthClause =
+                   std::get_if<Fortran::parser::AccClause::VectorLength>(
+                       &clause.u)) {
+      vectorLength = fir::getBase(converter.genExprValue(
+          *Fortran::semantics::GetExpr(vectorLengthClause->v)));
+    } else if (const auto *ifClause =
+                   std::get_if<Fortran::parser::AccClause::If>(&clause.u)) {
+      Value cond = fir::getBase(
+          converter.genExprValue(*Fortran::semantics::GetExpr(ifClause->v)));
+      ifCond = firOpBuilder.createConvert(currentLocation,
+                                          firOpBuilder.getI1Type(), cond);
+    } else if (const auto *selfClause =
+                   std::get_if<Fortran::parser::AccClause::Self>(&clause.u)) {
+      if (selfClause->v) {
+        Value cond = fir::getBase(converter.genExprValue(
+            *Fortran::semantics::GetExpr(*(selfClause->v))));
+        selfCond = firOpBuilder.createConvert(currentLocation,
+                                              firOpBuilder.getI1Type(), cond);
+      } else {
+        addSelfAttr = true;
+      }
+    } else if (const auto *copyClause =
+                   std::get_if<Fortran::parser::AccClause::Copy>(&clause.u)) {
+      genObjectList(copyClause->v, converter, copyOperands);
+    } else if (const auto *copyinClause =
+                   std::get_if<Fortran::parser::AccClause::Copyin>(&clause.u)) {
+      genObjectListWithModifier<Fortran::parser::AccClause::Copyin>(
+          copyinClause, converter,
+          Fortran::parser::AccDataModifier::Modifier::ReadOnly,
+          copyinReadonlyOperands, copyinOperands);
+    } else if (const auto *copyoutClause =
+                   std::get_if<Fortran::parser::AccClause::Copyout>(
+                       &clause.u)) {
+      genObjectListWithModifier<Fortran::parser::AccClause::Copyout>(
+          copyoutClause, converter,
+          Fortran::parser::AccDataModifier::Modifier::Zero, copyoutZeroOperands,
+          copyoutOperands);
+    } else if (const auto *createClause =
+                   std::get_if<Fortran::parser::AccClause::Create>(&clause.u)) {
+      genObjectListWithModifier<Fortran::parser::AccClause::Create>(
+          createClause, converter,
+          Fortran::parser::AccDataModifier::Modifier::Zero, createZeroOperands,
+          createOperands);
+    } else if (const auto *noCreateClause =
+                   std::get_if<Fortran::parser::AccClause::NoCreate>(
+                       &clause.u)) {
+      genObjectList(noCreateClause->v, converter, noCreateOperands);
+    } else if (const auto *presentClause =
+                   std::get_if<Fortran::parser::AccClause::Present>(
+                       &clause.u)) {
+      genObjectList(presentClause->v, converter, presentOperands);
+    } else if (const auto *devicePtrClause =
+                   std::get_if<Fortran::parser::AccClause::Deviceptr>(
+                       &clause.u)) {
+      genObjectList(devicePtrClause->v, converter, devicePtrOperands);
+    } else if (const auto *attachClause =
+                   std::get_if<Fortran::parser::AccClause::Attach>(&clause.u)) {
+      genObjectList(attachClause->v, converter, attachOperands);
+    } else if (const auto *privateClause =
+                   std::get_if<Fortran::parser::AccClause::Private>(
+                       &clause.u)) {
+      genObjectList(privateClause->v, converter, privateOperands);
+    } else if (const auto *firstprivateClause =
+                   std::get_if<Fortran::parser::AccClause::Firstprivate>(
+                       &clause.u)) {
+      genObjectList(firstprivateClause->v, converter, firstprivateOperands);
+    }
+  }
+
+  // Prepare the operand segement size attribute and the operands value range.
+  SmallVector<Value, 8> operands;
+  SmallVector<int32_t, 8> operandSegments;
+  addOperand(operands, operandSegments, async);
+  addOperands(operands, operandSegments, waitOperands);
+  addOperand(operands, operandSegments, numGangs);
+  addOperand(operands, operandSegments, numWorkers);
+  addOperand(operands, operandSegments, vectorLength);
+  addOperand(operands, operandSegments, ifCond);
+  addOperand(operands, operandSegments, selfCond);
+  addOperands(operands, operandSegments, reductionOperands);
+  addOperands(operands, operandSegments, copyOperands);
+  addOperands(operands, operandSegments, copyinOperands);
+  addOperands(operands, operandSegments, copyinReadonlyOperands);
+  addOperands(operands, operandSegments, copyoutOperands);
+  addOperands(operands, operandSegments, copyoutZeroOperands);
+  addOperands(operands, operandSegments, createOperands);
+  addOperands(operands, operandSegments, createZeroOperands);
+  addOperands(operands, operandSegments, noCreateOperands);
+  addOperands(operands, operandSegments, presentOperands);
+  addOperands(operands, operandSegments, devicePtrOperands);
+  addOperands(operands, operandSegments, attachOperands);
+  addOperands(operands, operandSegments, privateOperands);
+  addOperands(operands, operandSegments, firstprivateOperands);
+
+  auto parallelOp = createRegionOp<mlir::acc::ParallelOp, mlir::acc::YieldOp>(
+      firOpBuilder, currentLocation, operands, operandSegments);
+
+  if (addAsyncAttr)
+    parallelOp.setAttr(mlir::acc::ParallelOp::getAsyncAttrName(),
+                       firOpBuilder.getUnitAttr());
+  if (addWaitAttr)
+    parallelOp.setAttr(mlir::acc::ParallelOp::getWaitAttrName(),
+                       firOpBuilder.getUnitAttr());
+  if (addSelfAttr)
+    parallelOp.setAttr(mlir::acc::ParallelOp::getSelfAttrName(),
+                       firOpBuilder.getUnitAttr());
+}
+
+static void
+genACC(Fortran::lower::AbstractConverter &converter,
+       Fortran::lower::pft::Evaluation &eval,
+       const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
+  const auto &beginBlockDirective =
+      std::get<Fortran::parser::AccBeginBlockDirective>(blockConstruct.t);
+  const auto &blockDirective =
+      std::get<Fortran::parser::AccBlockDirective>(beginBlockDirective.t);
+  const auto &accClauseList =
+      std::get<Fortran::parser::AccClauseList>(beginBlockDirective.t);
+
+  if (blockDirective.v == llvm::acc::ACCD_parallel) {
+    genACCParallelOp(converter, accClauseList);
+  }
+}
+
 void Fortran::lower::genOpenACCConstruct(
     Fortran::lower::AbstractConverter &converter,
     Fortran::lower::pft::Evaluation &eval,
@@ -236,7 +443,7 @@ void Fortran::lower::genOpenACCConstruct(
   std::visit(
       common::visitors{
           [&](const Fortran::parser::OpenACCBlockConstruct &blockConstruct) {
-            TODO();
+            genACC(converter, eval, blockConstruct);
           },
           [&](const Fortran::parser::OpenACCCombinedConstruct
                   &combinedConstruct) { TODO(); },


        


More information about the flang-commits mailing list