[flang-commits] [flang] 2e73a1f - [flang][openacc] Lower exit data directive

via flang-commits flang-commits at lists.llvm.org
Wed Nov 4 11:34:52 PST 2020


Author: Valentin Clement
Date: 2020-11-04T14:34:43-05:00
New Revision: 2e73a1f9faafe0a9bc6f8f177d7e92d8e6ae06b3

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

LOG: [flang][openacc] Lower exit data directive

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

Reviewed By: schweitz

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

Added: 
    

Modified: 
    flang/lib/Lower/OpenACC.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 53ff3f34d2a1..c254d04f3a3b 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -107,6 +107,18 @@ static Op createRegionOp(Fortran::lower::FirOpBuilder &builder,
   return op;
 }
 
+template <typename Op>
+static Op createSimpleOp(Fortran::lower::FirOpBuilder &builder,
+                         mlir::Location loc,
+                         const SmallVectorImpl<Value> &operands,
+                         const SmallVectorImpl<int32_t> &operandSegments) {
+  llvm::ArrayRef<mlir::Type> argTy;
+  Op op = builder.create<Op>(loc, argTy, operands);
+  op.setAttr(Op::getOperandSegmentSizeAttr(),
+             builder.getI32VectorAttr(operandSegments));
+  return op;
+}
+
 static void genACC(Fortran::lower::AbstractConverter &converter,
                    Fortran::lower::pft::Evaluation &eval,
                    const Fortran::parser::OpenACCLoopConstruct &loopConstruct) {
@@ -516,6 +528,128 @@ genACC(Fortran::lower::AbstractConverter &converter,
   }
 }
 
+static void
+genACCExitDataOp(Fortran::lower::AbstractConverter &converter,
+                 const Fortran::parser::AccClauseList &accClauseList) {
+  mlir::Value ifCond, async, waitDevnum;
+  SmallVector<Value, 2> copyoutOperands, deleteOperands, detachOperands,
+      waitOperands;
+
+  // Async and wait 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 addFinalizeAttr = 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 *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 *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);
+        }
+
+        const std::optional<Fortran::parser::ScalarIntExpr> &waitDevnumValue =
+            std::get<std::optional<Fortran::parser::ScalarIntExpr>>(waitArg.t);
+        if (waitDevnumValue)
+          waitDevnum = fir::getBase(converter.genExprValue(
+              *Fortran::semantics::GetExpr(*waitDevnumValue)));
+      } else {
+        addWaitAttr = true;
+      }
+    } else if (const auto *copyoutClause =
+                   std::get_if<Fortran::parser::AccClause::Copyout>(
+                       &clause.u)) {
+      const Fortran::parser::AccObjectListWithModifier &listWithModifier =
+          copyoutClause->v;
+      const Fortran::parser::AccObjectList &accObjectList =
+          std::get<Fortran::parser::AccObjectList>(listWithModifier.t);
+      genObjectList(accObjectList, converter, copyoutOperands);
+    } else if (const auto *deleteClause =
+                   std::get_if<Fortran::parser::AccClause::Delete>(&clause.u)) {
+      genObjectList(deleteClause->v, converter, deleteOperands);
+    } else if (const auto *detachClause =
+                   std::get_if<Fortran::parser::AccClause::Detach>(&clause.u)) {
+      genObjectList(detachClause->v, converter, detachOperands);
+    } else if (std::get_if<Fortran::parser::AccClause::Finalize>(&clause.u)) {
+      addFinalizeAttr = true;
+    }
+  }
+
+  // Prepare the operand segement size attribute and the operands value range.
+  SmallVector<Value, 8> operands;
+  SmallVector<int32_t, 8> operandSegments;
+  addOperand(operands, operandSegments, ifCond);
+  addOperand(operands, operandSegments, async);
+  addOperand(operands, operandSegments, waitDevnum);
+  addOperands(operands, operandSegments, waitOperands);
+  addOperands(operands, operandSegments, copyoutOperands);
+  addOperands(operands, operandSegments, deleteOperands);
+  addOperands(operands, operandSegments, detachOperands);
+
+  auto exitDataOp = createSimpleOp<mlir::acc::ExitDataOp>(
+      firOpBuilder, currentLocation, operands, operandSegments);
+
+  if (addAsyncAttr)
+    exitDataOp.asyncAttr(firOpBuilder.getUnitAttr());
+  if (addWaitAttr)
+    exitDataOp.waitAttr(firOpBuilder.getUnitAttr());
+  if (addFinalizeAttr)
+    exitDataOp.finalizeAttr(firOpBuilder.getUnitAttr());
+}
+
+static void
+genACC(Fortran::lower::AbstractConverter &converter,
+       Fortran::lower::pft::Evaluation &eval,
+       const Fortran::parser::OpenACCStandaloneConstruct &standaloneConstruct) {
+  const auto &standaloneDirective =
+      std::get<Fortran::parser::AccStandaloneDirective>(standaloneConstruct.t);
+  const auto &accClauseList =
+      std::get<Fortran::parser::AccClauseList>(standaloneConstruct.t);
+
+  if (standaloneDirective.v == llvm::acc::Directive::ACCD_enter_data) {
+    TODO("OpenACC enter data directive not lowered yet!");
+  } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_exit_data) {
+    genACCExitDataOp(converter, accClauseList);
+  } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_init) {
+    TODO("OpenACC init directive not lowered yet!");
+  } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_shutdown) {
+    TODO("OpenACC shutdown directive not lowered yet!");
+  } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_set) {
+    TODO("OpenACC set directive not lowered yet!");
+  } else if (standaloneDirective.v == llvm::acc::Directive::ACCD_update) {
+    TODO("OpenACC update directive not lowered yet!");
+  }
+}
+
 void Fortran::lower::genOpenACCConstruct(
     Fortran::lower::AbstractConverter &converter,
     Fortran::lower::pft::Evaluation &eval,
@@ -535,7 +669,7 @@ void Fortran::lower::genOpenACCConstruct(
           },
           [&](const Fortran::parser::OpenACCStandaloneConstruct
                   &standaloneConstruct) {
-            TODO("OpenACC Standalone construct not lowered yet!");
+            genACC(converter, eval, standaloneConstruct);
           },
           [&](const Fortran::parser::OpenACCRoutineConstruct
                   &routineConstruct) {


        


More information about the flang-commits mailing list