[flang-commits] [flang] [flang][OpenMP][OpenACC] remove libEvaluate dependency in passes (PR #123784)

via flang-commits flang-commits at lists.llvm.org
Tue Jan 21 09:19:59 PST 2025


https://github.com/jeanPerier created https://github.com/llvm/llvm-project/pull/123784

Move OpenACC/OpenMP helpers from Lower/DirectivesCommon.h that are also used in OpenACC and OpenMP mlir passes into a new Optimizer/Builder/DirectivesCommon.h so that parser and evaluate headers are not included in Optimizer libraries (this both introduce compile-time and link-time pointless overheads).

This should fix https://github.com/llvm/llvm-project/issues/123377

>From 41b206d2249257edf3b3022dc5bae22c408ea514 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Tue, 21 Jan 2025 09:11:44 -0800
Subject: [PATCH] [flang][OpenMP][OpenACC] remove libEvaluate dependency in
 passes

---
 flang/include/flang/Lower/DirectivesCommon.h  | 256 +-----------------
 .../Optimizer/Builder/DirectivesCommon.h      | 256 ++++++++++++++++++
 flang/lib/Lower/OpenACC.cpp                   |   8 +-
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    |   2 +-
 flang/lib/Lower/OpenMP/OpenMP.cpp             |  18 +-
 flang/lib/Lower/OpenMP/Utils.cpp              |   7 +-
 .../OpenACC/FIROpenACCTypeInterfaces.cpp      |  14 +-
 flang/lib/Optimizer/OpenMP/CMakeLists.txt     |   1 -
 .../Optimizer/OpenMP/MapInfoFinalization.cpp  |  10 +-
 9 files changed, 301 insertions(+), 271 deletions(-)
 create mode 100644 flang/include/flang/Optimizer/Builder/DirectivesCommon.h

diff --git a/flang/include/flang/Lower/DirectivesCommon.h b/flang/include/flang/Lower/DirectivesCommon.h
index 6e2c6ee4b1bcdb..c7cac1357b2277 100644
--- a/flang/include/flang/Lower/DirectivesCommon.h
+++ b/flang/include/flang/Lower/DirectivesCommon.h
@@ -29,12 +29,9 @@
 #include "flang/Lower/PFTBuilder.h"
 #include "flang/Lower/StatementContext.h"
 #include "flang/Lower/Support/Utils.h"
-#include "flang/Optimizer/Builder/BoxValue.h"
-#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/DirectivesCommon.h"
 #include "flang/Optimizer/Builder/HLFIRTools.h"
-#include "flang/Optimizer/Builder/Todo.h"
 #include "flang/Optimizer/Dialect/FIRType.h"
-#include "flang/Optimizer/HLFIR/HLFIROps.h"
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/openmp-directive-sets.h"
 #include "flang/Semantics/tools.h"
@@ -49,31 +46,6 @@
 namespace Fortran {
 namespace lower {
 
-/// Information gathered to generate bounds operation and data entry/exit
-/// operations.
-struct AddrAndBoundsInfo {
-  explicit AddrAndBoundsInfo() {}
-  explicit AddrAndBoundsInfo(mlir::Value addr, mlir::Value rawInput)
-      : addr(addr), rawInput(rawInput) {}
-  explicit AddrAndBoundsInfo(mlir::Value addr, mlir::Value rawInput,
-                             mlir::Value isPresent)
-      : addr(addr), rawInput(rawInput), isPresent(isPresent) {}
-  explicit AddrAndBoundsInfo(mlir::Value addr, mlir::Value rawInput,
-                             mlir::Value isPresent, mlir::Type boxType)
-      : addr(addr), rawInput(rawInput), isPresent(isPresent), boxType(boxType) {
-  }
-  mlir::Value addr = nullptr;
-  mlir::Value rawInput = nullptr;
-  mlir::Value isPresent = nullptr;
-  mlir::Type boxType = nullptr;
-  void dump(llvm::raw_ostream &os) {
-    os << "AddrAndBoundsInfo addr: " << addr << "\n";
-    os << "AddrAndBoundsInfo rawInput: " << rawInput << "\n";
-    os << "AddrAndBoundsInfo isPresent: " << isPresent << "\n";
-    os << "AddrAndBoundsInfo boxType: " << boxType << "\n";
-  }
-};
-
 /// Populates \p hint and \p memoryOrder with appropriate clause information
 /// if present on atomic construct.
 static inline void genOmpAtomicHintAndMemoryOrderClauses(
@@ -609,195 +581,13 @@ void createEmptyRegionBlocks(
   }
 }
 
-inline AddrAndBoundsInfo getDataOperandBaseAddr(fir::FirOpBuilder &builder,
-                                                mlir::Value symAddr,
-                                                bool isOptional,
-                                                mlir::Location loc) {
-  mlir::Value rawInput = symAddr;
-  if (auto declareOp =
-          mlir::dyn_cast_or_null<hlfir::DeclareOp>(symAddr.getDefiningOp())) {
-    symAddr = declareOp.getResults()[0];
-    rawInput = declareOp.getResults()[1];
-  }
-
-  if (!symAddr)
-    llvm::report_fatal_error("could not retrieve symbol address");
-
-  mlir::Value isPresent;
-  if (isOptional)
-    isPresent =
-        builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), rawInput);
-
-  if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(
-          fir::unwrapRefType(symAddr.getType()))) {
-    if (mlir::isa<fir::RecordType>(boxTy.getEleTy()))
-      TODO(loc, "derived type");
-
-    // In case of a box reference, load it here to get the box value.
-    // This is preferrable because then the same box value can then be used for
-    // all address/dimension retrievals. For Fortran optional though, leave
-    // the load generation for later so it can be done in the appropriate
-    // if branches.
-    if (mlir::isa<fir::ReferenceType>(symAddr.getType()) && !isOptional) {
-      mlir::Value addr = builder.create<fir::LoadOp>(loc, symAddr);
-      return AddrAndBoundsInfo(addr, rawInput, isPresent, boxTy);
-    }
-
-    return AddrAndBoundsInfo(symAddr, rawInput, isPresent, boxTy);
-  }
-  return AddrAndBoundsInfo(symAddr, rawInput, isPresent);
-}
-
-inline AddrAndBoundsInfo
+inline fir::factory::AddrAndBoundsInfo
 getDataOperandBaseAddr(Fortran::lower::AbstractConverter &converter,
                        fir::FirOpBuilder &builder,
                        Fortran::lower::SymbolRef sym, mlir::Location loc) {
-  return getDataOperandBaseAddr(builder, converter.getSymbolAddress(sym),
-                                Fortran::semantics::IsOptional(sym), loc);
-}
-
-template <typename BoundsOp, typename BoundsType>
-llvm::SmallVector<mlir::Value>
-gatherBoundsOrBoundValues(fir::FirOpBuilder &builder, mlir::Location loc,
-                          fir::ExtendedValue dataExv, mlir::Value box,
-                          bool collectValuesOnly = false) {
-  assert(box && "box must exist");
-  llvm::SmallVector<mlir::Value> values;
-  mlir::Value byteStride;
-  mlir::Type idxTy = builder.getIndexType();
-  mlir::Type boundTy = builder.getType<BoundsType>();
-  mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
-  for (unsigned dim = 0; dim < dataExv.rank(); ++dim) {
-    mlir::Value d = builder.createIntegerConstant(loc, idxTy, dim);
-    mlir::Value baseLb =
-        fir::factory::readLowerBound(builder, loc, dataExv, dim, one);
-    auto dimInfo =
-        builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, d);
-    mlir::Value lb = builder.createIntegerConstant(loc, idxTy, 0);
-    mlir::Value ub =
-        builder.create<mlir::arith::SubIOp>(loc, dimInfo.getExtent(), one);
-    if (dim == 0) // First stride is the element size.
-      byteStride = dimInfo.getByteStride();
-    if (collectValuesOnly) {
-      values.push_back(lb);
-      values.push_back(ub);
-      values.push_back(dimInfo.getExtent());
-      values.push_back(byteStride);
-      values.push_back(baseLb);
-    } else {
-      mlir::Value bound = builder.create<BoundsOp>(
-          loc, boundTy, lb, ub, dimInfo.getExtent(), byteStride, true, baseLb);
-      values.push_back(bound);
-    }
-    // Compute the stride for the next dimension.
-    byteStride = builder.create<mlir::arith::MulIOp>(loc, byteStride,
-                                                     dimInfo.getExtent());
-  }
-  return values;
-}
-
-/// Generate the bounds operation from the descriptor information.
-template <typename BoundsOp, typename BoundsType>
-llvm::SmallVector<mlir::Value>
-genBoundsOpsFromBox(fir::FirOpBuilder &builder, mlir::Location loc,
-                    fir::ExtendedValue dataExv,
-                    Fortran::lower::AddrAndBoundsInfo &info) {
-  llvm::SmallVector<mlir::Value> bounds;
-  mlir::Type idxTy = builder.getIndexType();
-  mlir::Type boundTy = builder.getType<BoundsType>();
-
-  assert(mlir::isa<fir::BaseBoxType>(info.boxType) &&
-         "expect fir.box or fir.class");
-  assert(fir::unwrapRefType(info.addr.getType()) == info.boxType &&
-         "expected box type consistency");
-
-  if (info.isPresent) {
-    llvm::SmallVector<mlir::Type> resTypes;
-    constexpr unsigned nbValuesPerBound = 5;
-    for (unsigned dim = 0; dim < dataExv.rank() * nbValuesPerBound; ++dim)
-      resTypes.push_back(idxTy);
-
-    mlir::Operation::result_range ifRes =
-        builder.genIfOp(loc, resTypes, info.isPresent, /*withElseRegion=*/true)
-            .genThen([&]() {
-              mlir::Value box =
-                  !fir::isBoxAddress(info.addr.getType())
-                      ? info.addr
-                      : builder.create<fir::LoadOp>(loc, info.addr);
-              llvm::SmallVector<mlir::Value> boundValues =
-                  gatherBoundsOrBoundValues<BoundsOp, BoundsType>(
-                      builder, loc, dataExv, box,
-                      /*collectValuesOnly=*/true);
-              builder.create<fir::ResultOp>(loc, boundValues);
-            })
-            .genElse([&] {
-              // Box is not present. Populate bound values with default values.
-              llvm::SmallVector<mlir::Value> boundValues;
-              mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
-              mlir::Value mOne = builder.createMinusOneInteger(loc, idxTy);
-              for (unsigned dim = 0; dim < dataExv.rank(); ++dim) {
-                boundValues.push_back(zero); // lb
-                boundValues.push_back(mOne); // ub
-                boundValues.push_back(zero); // extent
-                boundValues.push_back(zero); // byteStride
-                boundValues.push_back(zero); // baseLb
-              }
-              builder.create<fir::ResultOp>(loc, boundValues);
-            })
-            .getResults();
-    // Create the bound operations outside the if-then-else with the if op
-    // results.
-    for (unsigned i = 0; i < ifRes.size(); i += nbValuesPerBound) {
-      mlir::Value bound = builder.create<BoundsOp>(
-          loc, boundTy, ifRes[i], ifRes[i + 1], ifRes[i + 2], ifRes[i + 3],
-          true, ifRes[i + 4]);
-      bounds.push_back(bound);
-    }
-  } else {
-    mlir::Value box = !fir::isBoxAddress(info.addr.getType())
-                          ? info.addr
-                          : builder.create<fir::LoadOp>(loc, info.addr);
-    bounds = gatherBoundsOrBoundValues<BoundsOp, BoundsType>(builder, loc,
-                                                             dataExv, box);
-  }
-  return bounds;
-}
-
-/// Generate bounds operation for base array without any subscripts
-/// provided.
-template <typename BoundsOp, typename BoundsType>
-llvm::SmallVector<mlir::Value>
-genBaseBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
-                 fir::ExtendedValue dataExv, bool isAssumedSize) {
-  mlir::Type idxTy = builder.getIndexType();
-  mlir::Type boundTy = builder.getType<BoundsType>();
-  llvm::SmallVector<mlir::Value> bounds;
-
-  if (dataExv.rank() == 0)
-    return bounds;
-
-  mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
-  const unsigned rank = dataExv.rank();
-  for (unsigned dim = 0; dim < rank; ++dim) {
-    mlir::Value baseLb =
-        fir::factory::readLowerBound(builder, loc, dataExv, dim, one);
-    mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
-    mlir::Value ub;
-    mlir::Value lb = zero;
-    mlir::Value ext = fir::factory::readExtent(builder, loc, dataExv, dim);
-    if (isAssumedSize && dim + 1 == rank) {
-      ext = zero;
-      ub = lb;
-    } else {
-      // ub = extent - 1
-      ub = builder.create<mlir::arith::SubIOp>(loc, ext, one);
-    }
-
-    mlir::Value bound =
-        builder.create<BoundsOp>(loc, boundTy, lb, ub, ext, one, false, baseLb);
-    bounds.push_back(bound);
-  }
-  return bounds;
+  return fir::factory::getDataOperandBaseAddr(
+      builder, converter.getSymbolAddress(sym),
+      Fortran::semantics::IsOptional(sym), loc);
 }
 
 namespace detail {
@@ -878,7 +668,7 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
              Fortran::lower::StatementContext &stmtCtx,
              const std::vector<Fortran::evaluate::Subscript> &subscripts,
              std::stringstream &asFortran, fir::ExtendedValue &dataExv,
-             bool dataExvIsAssumedSize, AddrAndBoundsInfo &info,
+             bool dataExvIsAssumedSize, fir::factory::AddrAndBoundsInfo &info,
              bool treatIndexAsSection = false) {
   int dimension = 0;
   mlir::Type idxTy = builder.getIndexType();
@@ -1083,7 +873,7 @@ std::optional<Ref> getRef(Expr &&expr) {
 } // namespace detail
 
 template <typename BoundsOp, typename BoundsType>
-AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
+fir::factory::AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
     Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
     semantics::SemanticsContext &semaCtx,
     Fortran::lower::StatementContext &stmtCtx,
@@ -1093,7 +883,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
     llvm::SmallVector<mlir::Value> &bounds, bool treatIndexAsSection = false) {
   using namespace Fortran;
 
-  AddrAndBoundsInfo info;
+  fir::factory::AddrAndBoundsInfo info;
 
   if (!maybeDesignator) {
     info = getDataOperandBaseAddr(converter, builder, symbol, operandLocation);
@@ -1158,9 +948,9 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
     info.addr = fir::getBase(compExv);
     info.rawInput = info.addr;
     if (mlir::isa<fir::SequenceType>(fir::unwrapRefType(info.addr.getType())))
-      bounds = genBaseBoundsOps<BoundsOp, BoundsType>(builder, operandLocation,
-                                                      compExv,
-                                                      /*isAssumedSize=*/false);
+      bounds = fir::factory::genBaseBoundsOps<BoundsOp, BoundsType>(
+          builder, operandLocation, compExv,
+          /*isAssumedSize=*/false);
     asFortran << designator.AsFortran();
 
     if (semantics::IsOptional(compRef->GetLastSymbol())) {
@@ -1187,7 +977,7 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
       info.addr = boxAddrOp.getVal();
       info.boxType = info.addr.getType();
       info.rawInput = info.addr;
-      bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
+      bounds = fir::factory::genBoundsOpsFromBox<BoundsOp, BoundsType>(
           builder, operandLocation, compExv, info);
     }
   } else {
@@ -1205,13 +995,13 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
       if (mlir::isa<fir::BaseBoxType>(
               fir::unwrapRefType(info.addr.getType()))) {
         info.boxType = fir::unwrapRefType(info.addr.getType());
-        bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
+        bounds = fir::factory::genBoundsOpsFromBox<BoundsOp, BoundsType>(
             builder, operandLocation, dataExv, info);
       }
       bool dataExvIsAssumedSize =
           Fortran::semantics::IsAssumedSizeArray(symRef->get().GetUltimate());
       if (mlir::isa<fir::SequenceType>(fir::unwrapRefType(info.addr.getType())))
-        bounds = genBaseBoundsOps<BoundsOp, BoundsType>(
+        bounds = fir::factory::genBaseBoundsOps<BoundsOp, BoundsType>(
             builder, operandLocation, dataExv, dataExvIsAssumedSize);
       asFortran << symRef->get().name().ToString();
     } else { // Unsupported
@@ -1222,24 +1012,6 @@ AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
   return info;
 }
 
-template <typename BoundsOp, typename BoundsType>
-llvm::SmallVector<mlir::Value>
-genImplicitBoundsOps(fir::FirOpBuilder &builder, lower::AddrAndBoundsInfo &info,
-                     fir::ExtendedValue dataExv, bool dataExvIsAssumedSize,
-                     mlir::Location loc) {
-  llvm::SmallVector<mlir::Value> bounds;
-
-  mlir::Value baseOp = info.rawInput;
-  if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(baseOp.getType())))
-    bounds = lower::genBoundsOpsFromBox<BoundsOp, BoundsType>(builder, loc,
-                                                              dataExv, info);
-  if (mlir::isa<fir::SequenceType>(fir::unwrapRefType(baseOp.getType()))) {
-    bounds = lower::genBaseBoundsOps<BoundsOp, BoundsType>(
-        builder, loc, dataExv, dataExvIsAssumedSize);
-  }
-
-  return bounds;
-}
 } // namespace lower
 } // namespace Fortran
 
diff --git a/flang/include/flang/Optimizer/Builder/DirectivesCommon.h b/flang/include/flang/Optimizer/Builder/DirectivesCommon.h
new file mode 100644
index 00000000000000..443b0ee59007fa
--- /dev/null
+++ b/flang/include/flang/Optimizer/Builder/DirectivesCommon.h
@@ -0,0 +1,256 @@
+//===-- DirectivesCommon.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
+//
+//===----------------------------------------------------------------------===//
+///
+/// A location to place directive utilities shared across multiple lowering
+/// and optimizer files, e.g. utilities shared in OpenMP and OpenACC.
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_OPTIMIZER_BUILDER_DIRECTIVESCOMMON_H_
+#define FORTRAN_OPTIMIZER_BUILDER_DIRECTIVESCOMMON_H_
+
+#include "flang/Optimizer/Builder/BoxValue.h"
+#include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/HLFIR/HLFIROps.h"
+#include "mlir/Dialect/OpenACC/OpenACC.h"
+#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
+
+namespace fir::factory {
+
+/// Information gathered to generate bounds operation and data entry/exit
+/// operations.
+struct AddrAndBoundsInfo {
+  explicit AddrAndBoundsInfo() {}
+  explicit AddrAndBoundsInfo(mlir::Value addr, mlir::Value rawInput)
+      : addr(addr), rawInput(rawInput) {}
+  explicit AddrAndBoundsInfo(mlir::Value addr, mlir::Value rawInput,
+                             mlir::Value isPresent)
+      : addr(addr), rawInput(rawInput), isPresent(isPresent) {}
+  explicit AddrAndBoundsInfo(mlir::Value addr, mlir::Value rawInput,
+                             mlir::Value isPresent, mlir::Type boxType)
+      : addr(addr), rawInput(rawInput), isPresent(isPresent), boxType(boxType) {
+  }
+  mlir::Value addr = nullptr;
+  mlir::Value rawInput = nullptr;
+  mlir::Value isPresent = nullptr;
+  mlir::Type boxType = nullptr;
+  void dump(llvm::raw_ostream &os) {
+    os << "AddrAndBoundsInfo addr: " << addr << "\n";
+    os << "AddrAndBoundsInfo rawInput: " << rawInput << "\n";
+    os << "AddrAndBoundsInfo isPresent: " << isPresent << "\n";
+    os << "AddrAndBoundsInfo boxType: " << boxType << "\n";
+  }
+};
+
+inline AddrAndBoundsInfo getDataOperandBaseAddr(fir::FirOpBuilder &builder,
+                                                mlir::Value symAddr,
+                                                bool isOptional,
+                                                mlir::Location loc) {
+  mlir::Value rawInput = symAddr;
+  if (auto declareOp =
+          mlir::dyn_cast_or_null<hlfir::DeclareOp>(symAddr.getDefiningOp())) {
+    symAddr = declareOp.getResults()[0];
+    rawInput = declareOp.getResults()[1];
+  }
+
+  if (!symAddr)
+    llvm::report_fatal_error("could not retrieve symbol address");
+
+  mlir::Value isPresent;
+  if (isOptional)
+    isPresent =
+        builder.create<fir::IsPresentOp>(loc, builder.getI1Type(), rawInput);
+
+  if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(
+          fir::unwrapRefType(symAddr.getType()))) {
+    if (mlir::isa<fir::RecordType>(boxTy.getEleTy()))
+      TODO(loc, "derived type");
+
+    // In case of a box reference, load it here to get the box value.
+    // This is preferrable because then the same box value can then be used for
+    // all address/dimension retrievals. For Fortran optional though, leave
+    // the load generation for later so it can be done in the appropriate
+    // if branches.
+    if (mlir::isa<fir::ReferenceType>(symAddr.getType()) && !isOptional) {
+      mlir::Value addr = builder.create<fir::LoadOp>(loc, symAddr);
+      return AddrAndBoundsInfo(addr, rawInput, isPresent, boxTy);
+    }
+
+    return AddrAndBoundsInfo(symAddr, rawInput, isPresent, boxTy);
+  }
+  return AddrAndBoundsInfo(symAddr, rawInput, isPresent);
+}
+
+template <typename BoundsOp, typename BoundsType>
+llvm::SmallVector<mlir::Value>
+gatherBoundsOrBoundValues(fir::FirOpBuilder &builder, mlir::Location loc,
+                          fir::ExtendedValue dataExv, mlir::Value box,
+                          bool collectValuesOnly = false) {
+  assert(box && "box must exist");
+  llvm::SmallVector<mlir::Value> values;
+  mlir::Value byteStride;
+  mlir::Type idxTy = builder.getIndexType();
+  mlir::Type boundTy = builder.getType<BoundsType>();
+  mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
+  for (unsigned dim = 0; dim < dataExv.rank(); ++dim) {
+    mlir::Value d = builder.createIntegerConstant(loc, idxTy, dim);
+    mlir::Value baseLb =
+        fir::factory::readLowerBound(builder, loc, dataExv, dim, one);
+    auto dimInfo =
+        builder.create<fir::BoxDimsOp>(loc, idxTy, idxTy, idxTy, box, d);
+    mlir::Value lb = builder.createIntegerConstant(loc, idxTy, 0);
+    mlir::Value ub =
+        builder.create<mlir::arith::SubIOp>(loc, dimInfo.getExtent(), one);
+    if (dim == 0) // First stride is the element size.
+      byteStride = dimInfo.getByteStride();
+    if (collectValuesOnly) {
+      values.push_back(lb);
+      values.push_back(ub);
+      values.push_back(dimInfo.getExtent());
+      values.push_back(byteStride);
+      values.push_back(baseLb);
+    } else {
+      mlir::Value bound = builder.create<BoundsOp>(
+          loc, boundTy, lb, ub, dimInfo.getExtent(), byteStride, true, baseLb);
+      values.push_back(bound);
+    }
+    // Compute the stride for the next dimension.
+    byteStride = builder.create<mlir::arith::MulIOp>(loc, byteStride,
+                                                     dimInfo.getExtent());
+  }
+  return values;
+}
+
+/// Generate the bounds operation from the descriptor information.
+template <typename BoundsOp, typename BoundsType>
+llvm::SmallVector<mlir::Value>
+genBoundsOpsFromBox(fir::FirOpBuilder &builder, mlir::Location loc,
+                    fir::ExtendedValue dataExv, AddrAndBoundsInfo &info) {
+  llvm::SmallVector<mlir::Value> bounds;
+  mlir::Type idxTy = builder.getIndexType();
+  mlir::Type boundTy = builder.getType<BoundsType>();
+
+  assert(mlir::isa<fir::BaseBoxType>(info.boxType) &&
+         "expect fir.box or fir.class");
+  assert(fir::unwrapRefType(info.addr.getType()) == info.boxType &&
+         "expected box type consistency");
+
+  if (info.isPresent) {
+    llvm::SmallVector<mlir::Type> resTypes;
+    constexpr unsigned nbValuesPerBound = 5;
+    for (unsigned dim = 0; dim < dataExv.rank() * nbValuesPerBound; ++dim)
+      resTypes.push_back(idxTy);
+
+    mlir::Operation::result_range ifRes =
+        builder.genIfOp(loc, resTypes, info.isPresent, /*withElseRegion=*/true)
+            .genThen([&]() {
+              mlir::Value box =
+                  !fir::isBoxAddress(info.addr.getType())
+                      ? info.addr
+                      : builder.create<fir::LoadOp>(loc, info.addr);
+              llvm::SmallVector<mlir::Value> boundValues =
+                  gatherBoundsOrBoundValues<BoundsOp, BoundsType>(
+                      builder, loc, dataExv, box,
+                      /*collectValuesOnly=*/true);
+              builder.create<fir::ResultOp>(loc, boundValues);
+            })
+            .genElse([&] {
+              // Box is not present. Populate bound values with default values.
+              llvm::SmallVector<mlir::Value> boundValues;
+              mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
+              mlir::Value mOne = builder.createMinusOneInteger(loc, idxTy);
+              for (unsigned dim = 0; dim < dataExv.rank(); ++dim) {
+                boundValues.push_back(zero); // lb
+                boundValues.push_back(mOne); // ub
+                boundValues.push_back(zero); // extent
+                boundValues.push_back(zero); // byteStride
+                boundValues.push_back(zero); // baseLb
+              }
+              builder.create<fir::ResultOp>(loc, boundValues);
+            })
+            .getResults();
+    // Create the bound operations outside the if-then-else with the if op
+    // results.
+    for (unsigned i = 0; i < ifRes.size(); i += nbValuesPerBound) {
+      mlir::Value bound = builder.create<BoundsOp>(
+          loc, boundTy, ifRes[i], ifRes[i + 1], ifRes[i + 2], ifRes[i + 3],
+          true, ifRes[i + 4]);
+      bounds.push_back(bound);
+    }
+  } else {
+    mlir::Value box = !fir::isBoxAddress(info.addr.getType())
+                          ? info.addr
+                          : builder.create<fir::LoadOp>(loc, info.addr);
+    bounds = gatherBoundsOrBoundValues<BoundsOp, BoundsType>(builder, loc,
+                                                             dataExv, box);
+  }
+  return bounds;
+}
+
+/// Generate bounds operation for base array without any subscripts
+/// provided.
+template <typename BoundsOp, typename BoundsType>
+llvm::SmallVector<mlir::Value>
+genBaseBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
+                 fir::ExtendedValue dataExv, bool isAssumedSize) {
+  mlir::Type idxTy = builder.getIndexType();
+  mlir::Type boundTy = builder.getType<BoundsType>();
+  llvm::SmallVector<mlir::Value> bounds;
+
+  if (dataExv.rank() == 0)
+    return bounds;
+
+  mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
+  const unsigned rank = dataExv.rank();
+  for (unsigned dim = 0; dim < rank; ++dim) {
+    mlir::Value baseLb =
+        fir::factory::readLowerBound(builder, loc, dataExv, dim, one);
+    mlir::Value zero = builder.createIntegerConstant(loc, idxTy, 0);
+    mlir::Value ub;
+    mlir::Value lb = zero;
+    mlir::Value ext = fir::factory::readExtent(builder, loc, dataExv, dim);
+    if (isAssumedSize && dim + 1 == rank) {
+      ext = zero;
+      ub = lb;
+    } else {
+      // ub = extent - 1
+      ub = builder.create<mlir::arith::SubIOp>(loc, ext, one);
+    }
+
+    mlir::Value bound =
+        builder.create<BoundsOp>(loc, boundTy, lb, ub, ext, one, false, baseLb);
+    bounds.push_back(bound);
+  }
+  return bounds;
+}
+
+template <typename BoundsOp, typename BoundsType>
+llvm::SmallVector<mlir::Value>
+genImplicitBoundsOps(fir::FirOpBuilder &builder, AddrAndBoundsInfo &info,
+                     fir::ExtendedValue dataExv, bool dataExvIsAssumedSize,
+                     mlir::Location loc) {
+  llvm::SmallVector<mlir::Value> bounds;
+
+  mlir::Value baseOp = info.rawInput;
+  if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(baseOp.getType())))
+    bounds =
+        genBoundsOpsFromBox<BoundsOp, BoundsType>(builder, loc, dataExv, info);
+  if (mlir::isa<fir::SequenceType>(fir::unwrapRefType(baseOp.getType()))) {
+    bounds = genBaseBoundsOps<BoundsOp, BoundsType>(builder, loc, dataExv,
+                                                    dataExvIsAssumedSize);
+  }
+
+  return bounds;
+}
+
+} // namespace fir::factory
+#endif // FORTRAN_OPTIMIZER_BUILDER_DIRECTIVESCOMMON_H_
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 86d8a549331fb0..456c30264d0684 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -352,7 +352,7 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
-    Fortran::lower::AddrAndBoundsInfo info =
+    fir::factory::AddrAndBoundsInfo info =
         Fortran::lower::gatherDataOperandAddrAndBounds<
             mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
             converter, builder, semanticsContext, stmtCtx, symbol, designator,
@@ -392,7 +392,7 @@ static void genDeclareDataOperandOperations(
     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
-    Fortran::lower::AddrAndBoundsInfo info =
+    fir::factory::AddrAndBoundsInfo info =
         Fortran::lower::gatherDataOperandAddrAndBounds<
             mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
             converter, builder, semanticsContext, stmtCtx, symbol, designator,
@@ -855,7 +855,7 @@ genPrivatizations(const Fortran::parser::AccObjectList &objectList,
     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
-    Fortran::lower::AddrAndBoundsInfo info =
+    fir::factory::AddrAndBoundsInfo info =
         Fortran::lower::gatherDataOperandAddrAndBounds<
             mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
             converter, builder, semanticsContext, stmtCtx, symbol, designator,
@@ -1436,7 +1436,7 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList,
     Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
     Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
         [&](auto &&s) { return ea.Analyze(s); }, accObject.u);
-    Fortran::lower::AddrAndBoundsInfo info =
+    fir::factory::AddrAndBoundsInfo info =
         Fortran::lower::gatherDataOperandAddrAndBounds<
             mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
             converter, builder, semanticsContext, stmtCtx, symbol, designator,
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index fb8e007c7af574..299d9d438f1156 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -949,7 +949,7 @@ void ClauseProcessor::processMapObjects(
     std::stringstream asFortran;
     std::optional<omp::Object> parentObj;
 
-    lower::AddrAndBoundsInfo info =
+    fir::factory::AddrAndBoundsInfo info =
         lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
                                               mlir::omp::MapBoundsType>(
             converter, firOpBuilder, semaCtx, stmtCtx, *object.sym(),
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 39b4de919c8baf..64eb12c7432b18 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -1346,11 +1346,12 @@ static void genBodyOfTargetOp(
             firOpBuilder.createTemporary(val.getLoc(), val.getType());
         firOpBuilder.createStoreWithConvert(copyVal.getLoc(), val, copyVal);
 
-        lower::AddrAndBoundsInfo info = lower::getDataOperandBaseAddr(
-            firOpBuilder, val, /*isOptional=*/false, val.getLoc());
+        fir::factory::AddrAndBoundsInfo info =
+            fir::factory::getDataOperandBaseAddr(
+                firOpBuilder, val, /*isOptional=*/false, val.getLoc());
         llvm::SmallVector<mlir::Value> bounds =
-            Fortran::lower::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
-                                                 mlir::omp::MapBoundsType>(
+            fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
+                                               mlir::omp::MapBoundsType>(
                 firOpBuilder, info,
                 hlfir::translateToExtendedValue(val.getLoc(), firOpBuilder,
                                                 hlfir::Entity{val})
@@ -2188,11 +2189,12 @@ genTargetOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
       fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(sym);
       name << sym.name().ToString();
 
-      lower::AddrAndBoundsInfo info = getDataOperandBaseAddr(
-          converter, firOpBuilder, sym, converter.getCurrentLocation());
+      fir::factory::AddrAndBoundsInfo info =
+          Fortran::lower::getDataOperandBaseAddr(
+              converter, firOpBuilder, sym, converter.getCurrentLocation());
       llvm::SmallVector<mlir::Value> bounds =
-          lower::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
-                                      mlir::omp::MapBoundsType>(
+          fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
+                                             mlir::omp::MapBoundsType>(
               firOpBuilder, info, dataExv,
               semantics::IsAssumedSizeArray(sym.GetUltimate()),
               converter.getCurrentLocation());
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index 9971dc8e0b0014..35722fa7d1b120 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -310,8 +310,9 @@ mlir::Value createParentSymAndGenIntermediateMaps(
   };
 
   // Generate the access to the original parent base address.
-  lower::AddrAndBoundsInfo parentBaseAddr = lower::getDataOperandBaseAddr(
-      converter, firOpBuilder, *objectList[0].sym(), clauseLocation);
+  fir::factory::AddrAndBoundsInfo parentBaseAddr =
+      lower::getDataOperandBaseAddr(converter, firOpBuilder,
+                                    *objectList[0].sym(), clauseLocation);
   mlir::Value curValue = parentBaseAddr.addr;
 
   // Iterate over all objects in the objectList, this should consist of all
@@ -560,7 +561,7 @@ void insertChildMapInfoIntoParent(
       // Create parent to emplace and bind members
       llvm::SmallVector<mlir::Value> bounds;
       std::stringstream asFortran;
-      lower::AddrAndBoundsInfo info =
+      fir::factory::AddrAndBoundsInfo info =
           lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
                                                 mlir::omp::MapBoundsType>(
               converter, firOpBuilder, semaCtx, converter.getFctCtx(),
diff --git a/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp b/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp
index e6a484923c7060..94ab31de1763dd 100644
--- a/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp
+++ b/flang/lib/Optimizer/OpenACC/FIROpenACCTypeInterfaces.cpp
@@ -11,8 +11,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "flang/Optimizer/OpenACC/FIROpenACCTypeInterfaces.h"
-#include "flang/Lower/DirectivesCommon.h"
 #include "flang/Optimizer/Builder/BoxValue.h"
+#include "flang/Optimizer/Builder/DirectivesCommon.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Optimizer/Builder/HLFIRTools.h"
 #include "flang/Optimizer/Dialect/FIROps.h"
@@ -180,10 +180,10 @@ OpenACCMappableModel<fir::SequenceType>::generateAccBounds(
       }
       // TODO: Handle Fortran optional.
       const mlir::Value isPresent;
-      Fortran::lower::AddrAndBoundsInfo info(box, boxRef, isPresent,
-                                             box.getType());
-      return Fortran::lower::genBoundsOpsFromBox<mlir::acc::DataBoundsOp,
-                                                 mlir::acc::DataBoundsType>(
+      fir::factory::AddrAndBoundsInfo info(box, boxRef, isPresent,
+                                           box.getType());
+      return fir::factory::genBoundsOpsFromBox<mlir::acc::DataBoundsOp,
+                                               mlir::acc::DataBoundsType>(
           firBuilder, loc, exv, info);
     }
     assert(false && "array with unknown dimension expected to have descriptor");
@@ -200,8 +200,8 @@ OpenACCMappableModel<fir::SequenceType>::generateAccBounds(
   auto res = hlfir::translateToExtendedValue(loc, firBuilder,
                                              hlfir::Entity(valToCheck));
   fir::ExtendedValue exv = res.first;
-  return Fortran::lower::genBaseBoundsOps<mlir::acc::DataBoundsOp,
-                                          mlir::acc::DataBoundsType>(
+  return fir::factory::genBaseBoundsOps<mlir::acc::DataBoundsOp,
+                                        mlir::acc::DataBoundsType>(
       firBuilder, loc, exv,
       /*isAssumedSize=*/isAssumedSize);
 }
diff --git a/flang/lib/Optimizer/OpenMP/CMakeLists.txt b/flang/lib/Optimizer/OpenMP/CMakeLists.txt
index 9fe2d3947c26dd..c8509ccc7fea5a 100644
--- a/flang/lib/Optimizer/OpenMP/CMakeLists.txt
+++ b/flang/lib/Optimizer/OpenMP/CMakeLists.txt
@@ -22,7 +22,6 @@ add_flang_library(FlangOpenMPTransforms
   FIRDialectSupport
   FIRSupport
   FortranCommon
-  FortranEvaluate
   HLFIRDialect
 
   MLIR_LIBS
diff --git a/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp b/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp
index c63d2f4531a6f1..98e325c307d977 100644
--- a/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp
+++ b/flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp
@@ -24,7 +24,7 @@
 /// indirectly via a parent object.
 //===----------------------------------------------------------------------===//
 
-#include "flang/Lower/DirectivesCommon.h"
+#include "flang/Optimizer/Builder/DirectivesCommon.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
 #include "flang/Optimizer/Builder/HLFIRTools.h"
 #include "flang/Optimizer/Dialect/FIRType.h"
@@ -598,12 +598,12 @@ class MapInfoFinalizationPass
           auto fieldCoord = builder.create<fir::CoordinateOp>(
               op.getLoc(), builder.getRefType(memTy), op.getVarPtr(),
               fieldIdxVal);
-          Fortran::lower::AddrAndBoundsInfo info =
-              Fortran::lower::getDataOperandBaseAddr(
+          fir::factory::AddrAndBoundsInfo info =
+              fir::factory::getDataOperandBaseAddr(
                   builder, fieldCoord, /*isOptional=*/false, op.getLoc());
           llvm::SmallVector<mlir::Value> bounds =
-              Fortran::lower::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
-                                                   mlir::omp::MapBoundsType>(
+              fir::factory::genImplicitBoundsOps<mlir::omp::MapBoundsOp,
+                                                 mlir::omp::MapBoundsType>(
                   builder, info,
                   hlfir::translateToExtendedValue(op.getLoc(), builder,
                                                   hlfir::Entity{fieldCoord})



More information about the flang-commits mailing list