[flang-commits] [flang] 8411549 - [flang][Lower] Convert OMP Map and related functions to evaluate::Expr (#81626)

via flang-commits flang-commits at lists.llvm.org
Wed Mar 20 13:00:33 PDT 2024


Author: Krzysztof Parzyszek
Date: 2024-03-20T15:00:29-05:00
New Revision: 84115494d6475e1aea3cdd1163d3a88243b75f36

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

LOG: [flang][Lower] Convert OMP Map and related functions to evaluate::Expr (#81626)

The related functions are `gatherDataOperandAddrAndBounds` and
`genBoundsOps`. The former is used in OpenACC as well, and it was
updated to pass evaluate::Expr instead of parser objects.

The difference in the test case comes from unfolded conversions of index
expressions, which are explicitly of type integer(kind=8).

Delete now unused `findRepeatableClause2` and `findClause2`.

Add `AsGenericExpr` that takes std::optional. It already returns
optional Expr. Making it accept an optional Expr as input would reduce
the number of necessary checks when handling frequent optional values in
evaluator.

[Clause representation 4/6]

Added: 
    

Modified: 
    flang/include/flang/Evaluate/tools.h
    flang/lib/Lower/DirectivesCommon.h
    flang/lib/Lower/OpenACC.cpp
    flang/lib/Lower/OpenMP/ClauseProcessor.cpp
    flang/lib/Lower/OpenMP/ClauseProcessor.h
    flang/lib/Lower/OpenMP/OpenMP.cpp
    flang/test/Lower/OpenACC/acc-bounds.f90
    flang/test/Lower/OpenACC/acc-enter-data.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index 9a32062440abc0..8c872a0579c8ed 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -148,6 +148,14 @@ inline Expr<SomeType> AsGenericExpr(Expr<SomeType> &&x) { return std::move(x); }
 std::optional<Expr<SomeType>> AsGenericExpr(DataRef &&);
 std::optional<Expr<SomeType>> AsGenericExpr(const Symbol &);
 
+// Propagate std::optional from input to output.
+template <typename A>
+std::optional<Expr<SomeType>> AsGenericExpr(std::optional<A> &&x) {
+  if (!x)
+    return std::nullopt;
+  return AsGenericExpr(std::move(*x));
+}
+
 template <typename A>
 common::IfNoLvalue<Expr<SomeKind<ResultType<A>::category>>, A> AsCategoryExpr(
     A &&x) {

diff  --git a/flang/lib/Lower/DirectivesCommon.h b/flang/lib/Lower/DirectivesCommon.h
index 8d560db34e05bf..6daa72b84d90d4 100644
--- a/flang/lib/Lower/DirectivesCommon.h
+++ b/flang/lib/Lower/DirectivesCommon.h
@@ -808,6 +808,75 @@ genBaseBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
   return bounds;
 }
 
+namespace detail {
+template <typename T> //
+static T &&AsRvalueRef(T &&t) {
+  return std::move(t);
+}
+template <typename T> //
+static T AsRvalueRef(T &t) {
+  return t;
+}
+template <typename T> //
+static T AsRvalueRef(const T &t) {
+  return t;
+}
+
+// Helper class for stripping enclosing parentheses and a conversion that
+// preserves type category. This is used for triplet elements, which are
+// always of type integer(kind=8). The lower/upper bounds are converted to
+// an "index" type, which is 64-bit, so the explicit conversion to kind=8
+// (if present) is not needed. When it's present, though, it causes generated
+// names to contain "int(..., kind=8)".
+struct PeelConvert {
+  template <Fortran::common::TypeCategory Category, int Kind>
+  static Fortran::semantics::MaybeExpr visit_with_category(
+      const Fortran::evaluate::Expr<Fortran::evaluate::Type<Category, Kind>>
+          &expr) {
+    return std::visit(
+        [](auto &&s) { return visit_with_category<Category, Kind>(s); },
+        expr.u);
+  }
+  template <Fortran::common::TypeCategory Category, int Kind>
+  static Fortran::semantics::MaybeExpr visit_with_category(
+      const Fortran::evaluate::Convert<Fortran::evaluate::Type<Category, Kind>,
+                                       Category> &expr) {
+    return AsGenericExpr(AsRvalueRef(expr.left()));
+  }
+  template <Fortran::common::TypeCategory Category, int Kind, typename T>
+  static Fortran::semantics::MaybeExpr visit_with_category(const T &) {
+    return std::nullopt; //
+  }
+  template <Fortran::common::TypeCategory Category, typename T>
+  static Fortran::semantics::MaybeExpr visit_with_category(const T &) {
+    return std::nullopt; //
+  }
+
+  template <Fortran::common::TypeCategory Category>
+  static Fortran::semantics::MaybeExpr
+  visit(const Fortran::evaluate::Expr<Fortran::evaluate::SomeKind<Category>>
+            &expr) {
+    return std::visit([](auto &&s) { return visit_with_category<Category>(s); },
+                      expr.u);
+  }
+  static Fortran::semantics::MaybeExpr
+  visit(const Fortran::evaluate::Expr<Fortran::evaluate::SomeType> &expr) {
+    return std::visit([](auto &&s) { return visit(s); }, expr.u);
+  }
+  template <typename T> //
+  static Fortran::semantics::MaybeExpr visit(const T &) {
+    return std::nullopt;
+  }
+};
+
+static Fortran::semantics::SomeExpr
+peelOuterConvert(Fortran::semantics::SomeExpr &expr) {
+  if (auto peeled = PeelConvert::visit(expr))
+    return *peeled;
+  return expr;
+}
+} // namespace detail
+
 /// Generate bounds operations for an array section when subscripts are
 /// provided.
 template <typename BoundsOp, typename BoundsType>
@@ -815,7 +884,7 @@ llvm::SmallVector<mlir::Value>
 genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
              Fortran::lower::AbstractConverter &converter,
              Fortran::lower::StatementContext &stmtCtx,
-             const std::list<Fortran::parser::SectionSubscript> &subscripts,
+             const std::vector<Fortran::evaluate::Subscript> &subscripts,
              std::stringstream &asFortran, fir::ExtendedValue &dataExv,
              bool dataExvIsAssumedSize, AddrAndBoundsInfo &info,
              bool treatIndexAsSection = false) {
@@ -828,8 +897,7 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
   mlir::Value one = builder.createIntegerConstant(loc, idxTy, 1);
   const int dataExvRank = static_cast<int>(dataExv.rank());
   for (const auto &subscript : subscripts) {
-    const auto *triplet{
-        std::get_if<Fortran::parser::SubscriptTriplet>(&subscript.u)};
+    const auto *triplet{std::get_if<Fortran::evaluate::Triplet>(&subscript.u)};
     if (triplet || treatIndexAsSection) {
       if (dimension != 0)
         asFortran << ',';
@@ -868,13 +936,17 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
         strideInBytes = true;
       }
 
-      const Fortran::lower::SomeExpr *lower{nullptr};
+      Fortran::semantics::MaybeExpr lower;
       if (triplet) {
-        if (const auto &tripletLb{std::get<0>(triplet->t)})
-          lower = Fortran::semantics::GetExpr(*tripletLb);
+        lower = Fortran::evaluate::AsGenericExpr(triplet->lower());
       } else {
-        const auto &index{std::get<Fortran::parser::IntExpr>(subscript.u)};
-        lower = Fortran::semantics::GetExpr(index);
+        // Case of IndirectSubscriptIntegerExpr
+        using IndirectSubscriptIntegerExpr =
+            Fortran::evaluate::IndirectSubscriptIntegerExpr;
+        using SubscriptInteger = Fortran::evaluate::SubscriptInteger;
+        Fortran::evaluate::Expr<SubscriptInteger> oneInt =
+            std::get<IndirectSubscriptIntegerExpr>(subscript.u).value();
+        lower = Fortran::evaluate::AsGenericExpr(std::move(oneInt));
         if (lower->Rank() > 0) {
           mlir::emitError(
               loc, "vector subscript cannot be used for an array section");
@@ -896,7 +968,7 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
               fir::getBase(converter.genExprValue(loc, *lower, stmtCtx));
           lb = builder.createConvert(loc, baseLb.getType(), lb);
           lbound = builder.create<mlir::arith::SubIOp>(loc, lb, baseLb);
-          asFortran << lower->AsFortran();
+          asFortran << detail::peelOuterConvert(*lower).AsFortran();
         }
       } else {
         // If the lower bound is not specified, then the section
@@ -912,10 +984,11 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
         extent = one;
       } else {
         asFortran << ':';
-        const auto &upper{std::get<1>(triplet->t)};
+        Fortran::semantics::MaybeExpr upper =
+            Fortran::evaluate::AsGenericExpr(triplet->upper());
 
         if (upper) {
-          uval = Fortran::semantics::GetIntValue(upper);
+          uval = Fortran::evaluate::ToInt64(*upper);
           if (uval) {
             if (defaultLb) {
               ubound = builder.createIntegerConstant(loc, idxTy, *uval - 1);
@@ -925,22 +998,21 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
             }
             asFortran << *uval;
           } else {
-            const Fortran::lower::SomeExpr *uexpr =
-                Fortran::semantics::GetExpr(*upper);
             mlir::Value ub =
-                fir::getBase(converter.genExprValue(loc, *uexpr, stmtCtx));
+                fir::getBase(converter.genExprValue(loc, *upper, stmtCtx));
             ub = builder.createConvert(loc, baseLb.getType(), ub);
             ubound = builder.create<mlir::arith::SubIOp>(loc, ub, baseLb);
-            asFortran << uexpr->AsFortran();
+            asFortran << detail::peelOuterConvert(*upper).AsFortran();
           }
         }
         if (lower && upper) {
           if (lval && uval && *uval < *lval) {
             mlir::emitError(loc, "zero sized array section");
             break;
-          } else if (std::get<2>(triplet->t)) {
-            const auto &strideExpr{std::get<2>(triplet->t)};
-            if (strideExpr) {
+          } else {
+            // Stride is mandatory in evaluate::Triplet. Make sure it's 1.
+            auto val = Fortran::evaluate::ToInt64(triplet->GetStride());
+            if (!val || *val != 1) {
               mlir::emitError(loc, "stride cannot be specified on "
                                    "an array section");
               break;
@@ -993,150 +1065,157 @@ genBoundsOps(fir::FirOpBuilder &builder, mlir::Location loc,
   return bounds;
 }
 
-template <typename ObjectType, typename BoundsOp, typename BoundsType>
+namespace detail {
+template <typename Ref, typename Expr> //
+std::optional<Ref> getRef(Expr &&expr) {
+  if constexpr (std::is_same_v<llvm::remove_cvref_t<Expr>,
+                               Fortran::evaluate::DataRef>) {
+    if (auto *ref = std::get_if<Ref>(&expr.u))
+      return *ref;
+    return std::nullopt;
+  } else {
+    auto maybeRef = Fortran::evaluate::ExtractDataRef(expr);
+    if (!maybeRef || !std::holds_alternative<Ref>(maybeRef->u))
+      return std::nullopt;
+    return std::get<Ref>(maybeRef->u);
+  }
+}
+} // namespace detail
+
+template <typename BoundsOp, typename BoundsType>
 AddrAndBoundsInfo gatherDataOperandAddrAndBounds(
     Fortran::lower::AbstractConverter &converter, fir::FirOpBuilder &builder,
-    Fortran::semantics::SemanticsContext &semanticsContext,
-    Fortran::lower::StatementContext &stmtCtx, const ObjectType &object,
+    semantics::SemanticsContext &semaCtx,
+    Fortran::lower::StatementContext &stmtCtx,
+    Fortran::semantics::SymbolRef symbol,
+    const Fortran::semantics::MaybeExpr &maybeDesignator,
     mlir::Location operandLocation, std::stringstream &asFortran,
     llvm::SmallVector<mlir::Value> &bounds, bool treatIndexAsSection = false) {
+  using namespace Fortran;
+
   AddrAndBoundsInfo info;
-  std::visit(
-      Fortran::common::visitors{
-          [&](const Fortran::parser::Designator &designator) {
-            if (auto expr{Fortran::semantics::AnalyzeExpr(semanticsContext,
-                                                          designator)}) {
-              if (((*expr).Rank() > 0 || treatIndexAsSection) &&
-                  Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
-                      designator)) {
-                const auto *arrayElement =
-                    Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
-                        designator);
-                const auto *dataRef =
-                    std::get_if<Fortran::parser::DataRef>(&designator.u);
-                fir::ExtendedValue dataExv;
-                bool dataExvIsAssumedSize = false;
-                if (Fortran::parser::Unwrap<
-                        Fortran::parser::StructureComponent>(
-                        arrayElement->base)) {
-                  auto exprBase = Fortran::semantics::AnalyzeExpr(
-                      semanticsContext, arrayElement->base);
-                  dataExv = converter.genExprAddr(operandLocation, *exprBase,
-                                                  stmtCtx);
-                  info.addr = fir::getBase(dataExv);
-                  info.rawInput = info.addr;
-                  asFortran << (*exprBase).AsFortran();
-                } else {
-                  const Fortran::parser::Name &name =
-                      Fortran::parser::GetLastName(*dataRef);
-                  dataExvIsAssumedSize = Fortran::semantics::IsAssumedSizeArray(
-                      name.symbol->GetUltimate());
-                  info = getDataOperandBaseAddr(converter, builder,
-                                                *name.symbol, operandLocation);
-                  dataExv = converter.getSymbolExtendedValue(*name.symbol);
-                  asFortran << name.ToString();
-                }
-
-                if (!arrayElement->subscripts.empty()) {
-                  asFortran << '(';
-                  bounds = genBoundsOps<BoundsOp, BoundsType>(
-                      builder, operandLocation, converter, stmtCtx,
-                      arrayElement->subscripts, asFortran, dataExv,
-                      dataExvIsAssumedSize, info, treatIndexAsSection);
-                }
-                asFortran << ')';
-              } else if (auto structComp = Fortran::parser::Unwrap<
-                             Fortran::parser::StructureComponent>(designator)) {
-                fir::ExtendedValue compExv =
-                    converter.genExprAddr(operandLocation, *expr, stmtCtx);
-                info.addr = fir::getBase(compExv);
-                info.rawInput = info.addr;
-                if (fir::unwrapRefType(info.addr.getType())
-                        .isa<fir::SequenceType>())
-                  bounds = genBaseBoundsOps<BoundsOp, BoundsType>(
-                      builder, operandLocation, converter, compExv,
-                      /*isAssumedSize=*/false);
-                asFortran << (*expr).AsFortran();
-
-                bool isOptional = Fortran::semantics::IsOptional(
-                    *Fortran::parser::GetLastName(*structComp).symbol);
-                if (isOptional)
-                  info.isPresent = builder.create<fir::IsPresentOp>(
-                      operandLocation, builder.getI1Type(), info.rawInput);
-
-                if (auto loadOp = mlir::dyn_cast_or_null<fir::LoadOp>(
-                        info.addr.getDefiningOp())) {
-                  if (fir::isAllocatableType(loadOp.getType()) ||
-                      fir::isPointerType(loadOp.getType()))
-                    info.addr = builder.create<fir::BoxAddrOp>(operandLocation,
-                                                               info.addr);
-                  info.rawInput = info.addr;
-                }
-
-                // If the component is an allocatable or pointer the result of
-                // genExprAddr will be the result of a fir.box_addr operation or
-                // a fir.box_addr has been inserted just before.
-                // Retrieve the box so we handle it like other descriptor.
-                if (auto boxAddrOp = mlir::dyn_cast_or_null<fir::BoxAddrOp>(
-                        info.addr.getDefiningOp())) {
-                  info.addr = boxAddrOp.getVal();
-                  info.rawInput = info.addr;
-                  bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
-                      builder, operandLocation, converter, compExv, info);
-                }
-              } else {
-                if (Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
-                        designator)) {
-                  // Single array element.
-                  const auto *arrayElement =
-                      Fortran::parser::Unwrap<Fortran::parser::ArrayElement>(
-                          designator);
-                  (void)arrayElement;
-                  fir::ExtendedValue compExv =
-                      converter.genExprAddr(operandLocation, *expr, stmtCtx);
-                  info.addr = fir::getBase(compExv);
-                  info.rawInput = info.addr;
-                  asFortran << (*expr).AsFortran();
-                } else if (const auto *dataRef{
-                               std::get_if<Fortran::parser::DataRef>(
-                                   &designator.u)}) {
-                  // Scalar or full array.
-                  const Fortran::parser::Name &name =
-                      Fortran::parser::GetLastName(*dataRef);
-                  fir::ExtendedValue dataExv =
-                      converter.getSymbolExtendedValue(*name.symbol);
-                  info = getDataOperandBaseAddr(converter, builder,
-                                                *name.symbol, operandLocation);
-                  if (fir::unwrapRefType(info.addr.getType())
-                          .isa<fir::BaseBoxType>()) {
-                    bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
-                        builder, operandLocation, converter, dataExv, info);
-                  }
-                  bool dataExvIsAssumedSize =
-                      Fortran::semantics::IsAssumedSizeArray(
-                          name.symbol->GetUltimate());
-                  if (fir::unwrapRefType(info.addr.getType())
-                          .isa<fir::SequenceType>())
-                    bounds = genBaseBoundsOps<BoundsOp, BoundsType>(
-                        builder, operandLocation, converter, dataExv,
-                        dataExvIsAssumedSize);
-                  asFortran << name.ToString();
-                } else { // Unsupported
-                  llvm::report_fatal_error(
-                      "Unsupported type of OpenACC operand");
-                }
-              }
-            }
-          },
-          [&](const Fortran::parser::Name &name) {
-            info = getDataOperandBaseAddr(converter, builder, *name.symbol,
-                                          operandLocation);
-            asFortran << name.ToString();
-          }},
-      object.u);
+
+  if (!maybeDesignator) {
+    info = getDataOperandBaseAddr(converter, builder, symbol, operandLocation);
+    asFortran << symbol->name().ToString();
+    return info;
+  }
+
+  semantics::SomeExpr designator = *maybeDesignator;
+
+  if ((designator.Rank() > 0 || treatIndexAsSection) &&
+      IsArrayElement(designator)) {
+    auto arrayRef = detail::getRef<evaluate::ArrayRef>(designator);
+    // This shouldn't fail after IsArrayElement(designator).
+    assert(arrayRef && "Expecting ArrayRef");
+
+    fir::ExtendedValue dataExv;
+    bool dataExvIsAssumedSize = false;
+
+    auto toMaybeExpr = [&](auto &&base) {
+      using BaseType = llvm::remove_cvref_t<decltype(base)>;
+      evaluate::ExpressionAnalyzer ea{semaCtx};
+
+      if constexpr (std::is_same_v<evaluate::NamedEntity, BaseType>) {
+        if (auto *ref = base.UnwrapSymbolRef())
+          return ea.Designate(evaluate::DataRef{*ref});
+        if (auto *ref = base.UnwrapComponent())
+          return ea.Designate(evaluate::DataRef{*ref});
+        llvm_unreachable("Unexpected NamedEntity");
+      } else {
+        static_assert(std::is_same_v<semantics::SymbolRef, BaseType>);
+        return ea.Designate(evaluate::DataRef{base});
+      }
+    };
+
+    auto arrayBase = toMaybeExpr(arrayRef->base());
+    assert(arrayBase);
+
+    if (detail::getRef<evaluate::Component>(*arrayBase)) {
+      dataExv = converter.genExprAddr(operandLocation, *arrayBase, stmtCtx);
+      info.addr = fir::getBase(dataExv);
+      info.rawInput = info.addr;
+      asFortran << arrayBase->AsFortran();
+    } else {
+      const semantics::Symbol &sym = arrayRef->GetLastSymbol();
+      dataExvIsAssumedSize =
+          Fortran::semantics::IsAssumedSizeArray(sym.GetUltimate());
+      info = getDataOperandBaseAddr(converter, builder, sym, operandLocation);
+      dataExv = converter.getSymbolExtendedValue(sym);
+      asFortran << sym.name().ToString();
+    }
+
+    if (!arrayRef->subscript().empty()) {
+      asFortran << '(';
+      bounds = genBoundsOps<BoundsOp, BoundsType>(
+          builder, operandLocation, converter, stmtCtx, arrayRef->subscript(),
+          asFortran, dataExv, dataExvIsAssumedSize, info, treatIndexAsSection);
+    }
+    asFortran << ')';
+  } else if (auto compRef = detail::getRef<evaluate::Component>(designator)) {
+    fir::ExtendedValue compExv =
+        converter.genExprAddr(operandLocation, designator, stmtCtx);
+    info.addr = fir::getBase(compExv);
+    info.rawInput = info.addr;
+    if (fir::unwrapRefType(info.addr.getType()).isa<fir::SequenceType>())
+      bounds = genBaseBoundsOps<BoundsOp, BoundsType>(builder, operandLocation,
+                                                      converter, compExv,
+                                                      /*isAssumedSize=*/false);
+    asFortran << designator.AsFortran();
+
+    if (semantics::IsOptional(compRef->GetLastSymbol())) {
+      info.isPresent = builder.create<fir::IsPresentOp>(
+          operandLocation, builder.getI1Type(), info.rawInput);
+    }
+
+    if (auto loadOp =
+            mlir::dyn_cast_or_null<fir::LoadOp>(info.addr.getDefiningOp())) {
+      if (fir::isAllocatableType(loadOp.getType()) ||
+          fir::isPointerType(loadOp.getType()))
+        info.addr = builder.create<fir::BoxAddrOp>(operandLocation, info.addr);
+      info.rawInput = info.addr;
+    }
+
+    // If the component is an allocatable or pointer the result of
+    // genExprAddr will be the result of a fir.box_addr operation or
+    // a fir.box_addr has been inserted just before.
+    // Retrieve the box so we handle it like other descriptor.
+    if (auto boxAddrOp =
+            mlir::dyn_cast_or_null<fir::BoxAddrOp>(info.addr.getDefiningOp())) {
+      info.addr = boxAddrOp.getVal();
+      info.rawInput = info.addr;
+      bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
+          builder, operandLocation, converter, compExv, info);
+    }
+  } else {
+    if (detail::getRef<evaluate::ArrayRef>(designator)) {
+      fir::ExtendedValue compExv =
+          converter.genExprAddr(operandLocation, designator, stmtCtx);
+      info.addr = fir::getBase(compExv);
+      info.rawInput = info.addr;
+      asFortran << designator.AsFortran();
+    } else if (auto symRef = detail::getRef<semantics::SymbolRef>(designator)) {
+      // Scalar or full array.
+      fir::ExtendedValue dataExv = converter.getSymbolExtendedValue(*symRef);
+      info =
+          getDataOperandBaseAddr(converter, builder, *symRef, operandLocation);
+      if (fir::unwrapRefType(info.addr.getType()).isa<fir::BaseBoxType>()) {
+        bounds = genBoundsOpsFromBox<BoundsOp, BoundsType>(
+            builder, operandLocation, converter, dataExv, info);
+      }
+      bool dataExvIsAssumedSize =
+          Fortran::semantics::IsAssumedSizeArray(symRef->get().GetUltimate());
+      if (fir::unwrapRefType(info.addr.getType()).isa<fir::SequenceType>())
+        bounds = genBaseBoundsOps<BoundsOp, BoundsType>(
+            builder, operandLocation, converter, dataExv, dataExvIsAssumedSize);
+      asFortran << symRef->get().name().ToString();
+    } else { // Unsupported
+      llvm::report_fatal_error("Unsupported type of OpenACC operand");
+    }
+  }
+
   return info;
 }
-
 } // namespace lower
 } // namespace Fortran
 

diff  --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 6539de4d88304c..7b7e4a875cd8e8 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -269,6 +269,11 @@ getSymbolFromAccObject(const Fortran::parser::AccObject &accObject) {
           Fortran::parser::GetLastName(arrayElement->base);
       return *name.symbol;
     }
+    if (const auto *component =
+            Fortran::parser::Unwrap<Fortran::parser::StructureComponent>(
+                *designator)) {
+      return *component->component.symbol;
+    }
   } else if (const auto *name =
                  std::get_if<Fortran::parser::Name>(&accObject.u)) {
     return *name->symbol;
@@ -286,17 +291,20 @@ genDataOperandOperations(const Fortran::parser::AccObjectList &objectList,
                          mlir::acc::DataClause dataClause, bool structured,
                          bool implicit, bool setDeclareAttr = false) {
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
   for (const auto &accObject : objectList.v) {
     llvm::SmallVector<mlir::Value> bounds;
     std::stringstream asFortran;
     mlir::Location operandLocation = genOperandLocation(converter, accObject);
+    Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
+    Fortran::semantics::MaybeExpr designator =
+        std::visit([&](auto &&s) { return ea.Analyze(s); }, accObject.u);
     Fortran::lower::AddrAndBoundsInfo info =
         Fortran::lower::gatherDataOperandAddrAndBounds<
-            Fortran::parser::AccObject, mlir::acc::DataBoundsOp,
-            mlir::acc::DataBoundsType>(converter, builder, semanticsContext,
-                                       stmtCtx, accObject, operandLocation,
-                                       asFortran, bounds,
-                                       /*treatIndexAsSection=*/true);
+            mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
+            converter, builder, semanticsContext, stmtCtx, symbol, designator,
+            operandLocation, asFortran, bounds,
+            /*treatIndexAsSection=*/true);
 
     // If the input value is optional and is not a descriptor, we use the
     // rawInput directly.
@@ -321,16 +329,19 @@ static void genDeclareDataOperandOperations(
     llvm::SmallVectorImpl<mlir::Value> &dataOperands,
     mlir::acc::DataClause dataClause, bool structured, bool implicit) {
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
   for (const auto &accObject : objectList.v) {
     llvm::SmallVector<mlir::Value> bounds;
     std::stringstream asFortran;
     mlir::Location operandLocation = genOperandLocation(converter, accObject);
+    Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
+    Fortran::semantics::MaybeExpr designator =
+        std::visit([&](auto &&s) { return ea.Analyze(s); }, accObject.u);
     Fortran::lower::AddrAndBoundsInfo info =
         Fortran::lower::gatherDataOperandAddrAndBounds<
-            Fortran::parser::AccObject, mlir::acc::DataBoundsOp,
-            mlir::acc::DataBoundsType>(converter, builder, semanticsContext,
-                                       stmtCtx, accObject, operandLocation,
-                                       asFortran, bounds);
+            mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
+            converter, builder, semanticsContext, stmtCtx, symbol, designator,
+            operandLocation, asFortran, bounds);
     EntryOp op = createDataEntryOp<EntryOp>(
         builder, operandLocation, info.addr, asFortran, bounds, structured,
         implicit, dataClause, info.addr.getType());
@@ -339,8 +350,7 @@ static void genDeclareDataOperandOperations(
     if (mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(info.addr.getType()))) {
       mlir::OpBuilder modBuilder(builder.getModule().getBodyRegion());
       modBuilder.setInsertionPointAfter(builder.getFunction());
-      std::string prefix =
-          converter.mangleName(getSymbolFromAccObject(accObject));
+      std::string prefix = converter.mangleName(symbol);
       createDeclareAllocFuncWithArg<EntryOp>(
           modBuilder, builder, operandLocation, info.addr.getType(), prefix,
           asFortran, dataClause);
@@ -770,16 +780,19 @@ genPrivatizations(const Fortran::parser::AccObjectList &objectList,
                   llvm::SmallVectorImpl<mlir::Value> &dataOperands,
                   llvm::SmallVector<mlir::Attribute> &privatizations) {
   fir::FirOpBuilder &builder = converter.getFirOpBuilder();
+  Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
   for (const auto &accObject : objectList.v) {
     llvm::SmallVector<mlir::Value> bounds;
     std::stringstream asFortran;
     mlir::Location operandLocation = genOperandLocation(converter, accObject);
+    Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
+    Fortran::semantics::MaybeExpr designator =
+        std::visit([&](auto &&s) { return ea.Analyze(s); }, accObject.u);
     Fortran::lower::AddrAndBoundsInfo info =
         Fortran::lower::gatherDataOperandAddrAndBounds<
-            Fortran::parser::AccObject, mlir::acc::DataBoundsOp,
-            mlir::acc::DataBoundsType>(converter, builder, semanticsContext,
-                                       stmtCtx, accObject, operandLocation,
-                                       asFortran, bounds);
+            mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
+            converter, builder, semanticsContext, stmtCtx, symbol, designator,
+            operandLocation, asFortran, bounds);
     RecipeOp recipe;
     mlir::Type retTy = getTypeFromBounds(bounds, info.addr.getType());
     if constexpr (std::is_same_v<RecipeOp, mlir::acc::PrivateRecipeOp>) {
@@ -1340,16 +1353,19 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList,
   const auto &op =
       std::get<Fortran::parser::AccReductionOperator>(objectList.t);
   mlir::acc::ReductionOperator mlirOp = getReductionOperator(op);
+  Fortran::evaluate::ExpressionAnalyzer ea{semanticsContext};
   for (const auto &accObject : objects.v) {
     llvm::SmallVector<mlir::Value> bounds;
     std::stringstream asFortran;
     mlir::Location operandLocation = genOperandLocation(converter, accObject);
+    Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
+    Fortran::semantics::MaybeExpr designator =
+        std::visit([&](auto &&s) { return ea.Analyze(s); }, accObject.u);
     Fortran::lower::AddrAndBoundsInfo info =
         Fortran::lower::gatherDataOperandAddrAndBounds<
-            Fortran::parser::AccObject, mlir::acc::DataBoundsOp,
-            mlir::acc::DataBoundsType>(converter, builder, semanticsContext,
-                                       stmtCtx, accObject, operandLocation,
-                                       asFortran, bounds);
+            mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
+            converter, builder, semanticsContext, stmtCtx, symbol, designator,
+            operandLocation, asFortran, bounds);
 
     mlir::Type reductionTy = fir::unwrapRefType(info.addr.getType());
     if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(reductionTy))

diff  --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index ae798b5c0a58fa..95faa0767e3656 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -818,65 +818,61 @@ bool ClauseProcessor::processMap(
     llvm::SmallVectorImpl<const Fortran::semantics::Symbol *> *mapSymbols)
     const {
   fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
-  return findRepeatableClause2<ClauseTy::Map>(
-      [&](const ClauseTy::Map *mapClause,
+  return findRepeatableClause<omp::clause::Map>(
+      [&](const omp::clause::Map &clause,
           const Fortran::parser::CharBlock &source) {
+        using Map = omp::clause::Map;
         mlir::Location clauseLocation = converter.genLocation(source);
-        const auto &oMapType =
-            std::get<std::optional<Fortran::parser::OmpMapType>>(
-                mapClause->v.t);
+        const auto &oMapType = std::get<std::optional<Map::MapType>>(clause.t);
         llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
             llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
         // If the map type is specified, then process it else Tofrom is the
         // default.
         if (oMapType) {
-          const Fortran::parser::OmpMapType::Type &mapType =
-              std::get<Fortran::parser::OmpMapType::Type>(oMapType->t);
+          const Map::MapType::Type &mapType =
+              std::get<Map::MapType::Type>(oMapType->t);
           switch (mapType) {
-          case Fortran::parser::OmpMapType::Type::To:
+          case Map::MapType::Type::To:
             mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO;
             break;
-          case Fortran::parser::OmpMapType::Type::From:
+          case Map::MapType::Type::From:
             mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
             break;
-          case Fortran::parser::OmpMapType::Type::Tofrom:
+          case Map::MapType::Type::Tofrom:
             mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
                            llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
             break;
-          case Fortran::parser::OmpMapType::Type::Alloc:
-          case Fortran::parser::OmpMapType::Type::Release:
+          case Map::MapType::Type::Alloc:
+          case Map::MapType::Type::Release:
             // alloc and release is the default map_type for the Target Data
             // Ops, i.e. if no bits for map_type is supplied then alloc/release
             // is implicitly assumed based on the target directive. Default
             // value for Target Data and Enter Data is alloc and for Exit Data
             // it is release.
             break;
-          case Fortran::parser::OmpMapType::Type::Delete:
+          case Map::MapType::Type::Delete:
             mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
           }
 
-          if (std::get<std::optional<Fortran::parser::OmpMapType::Always>>(
-                  oMapType->t))
+          if (std::get<std::optional<Map::MapType::Always>>(oMapType->t))
             mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
         } else {
           mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
                          llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
         }
 
-        for (const Fortran::parser::OmpObject &ompObject :
-             std::get<Fortran::parser::OmpObjectList>(mapClause->v.t).v) {
+        for (const omp::Object &object : std::get<omp::ObjectList>(clause.t)) {
           llvm::SmallVector<mlir::Value> bounds;
           std::stringstream asFortran;
 
           Fortran::lower::AddrAndBoundsInfo info =
               Fortran::lower::gatherDataOperandAddrAndBounds<
-                  Fortran::parser::OmpObject, mlir::omp::MapBoundsOp,
-                  mlir::omp::MapBoundsType>(
-                  converter, firOpBuilder, semaCtx, stmtCtx, ompObject,
-                  clauseLocation, asFortran, bounds, treatIndexAsSection);
+                  mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>(
+                  converter, firOpBuilder, semaCtx, stmtCtx, *object.id(),
+                  object.ref(), clauseLocation, asFortran, bounds,
+                  treatIndexAsSection);
 
-          auto origSymbol =
-              converter.getSymbolAddress(*getOmpObjectSymbol(ompObject));
+          auto origSymbol = converter.getSymbolAddress(*object.id());
           mlir::Value symAddr = info.addr;
           if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
             symAddr = origSymbol;
@@ -899,7 +895,7 @@ bool ClauseProcessor::processMap(
             mapSymLocs->push_back(symAddr.getLoc());
 
           if (mapSymbols)
-            mapSymbols->push_back(getOmpObjectSymbol(ompObject));
+            mapSymbols->push_back(object.id());
         }
       });
 }

diff  --git a/flang/lib/Lower/OpenMP/ClauseProcessor.h b/flang/lib/Lower/OpenMP/ClauseProcessor.h
index c2db0cfc3cb7bd..ffa8a5e0559385 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.h
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.h
@@ -162,9 +162,6 @@ class ClauseProcessor {
   /// Utility to find a clause within a range in the clause list.
   template <typename T>
   static ClauseIterator findClause(ClauseIterator begin, ClauseIterator end);
-  template <typename T>
-  static ClauseIterator2 findClause2(ClauseIterator2 begin,
-                                     ClauseIterator2 end);
 
   /// Return the first instance of the given clause found in the clause list or
   /// `nullptr` if not present. If more than one instance is expected, use
@@ -179,10 +176,6 @@ class ClauseProcessor {
   bool findRepeatableClause(
       std::function<void(const T &, const Fortran::parser::CharBlock &source)>
           callbackFn) const;
-  template <typename T>
-  bool findRepeatableClause2(
-      std::function<void(const T *, const Fortran::parser::CharBlock &source)>
-          callbackFn) const;
 
   /// Set the `result` to a new `mlir::UnitAttr` if the clause is present.
   template <typename T>
@@ -198,32 +191,31 @@ template <typename T>
 bool ClauseProcessor::processMotionClauses(
     Fortran::lower::StatementContext &stmtCtx,
     llvm::SmallVectorImpl<mlir::Value> &mapOperands) {
-  return findRepeatableClause2<T>(
-      [&](const T *motionClause, const Fortran::parser::CharBlock &source) {
+  return findRepeatableClause<T>(
+      [&](const T &clause, const Fortran::parser::CharBlock &source) {
         mlir::Location clauseLocation = converter.genLocation(source);
         fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
 
-        static_assert(std::is_same_v<T, ClauseProcessor::ClauseTy::To> ||
-                      std::is_same_v<T, ClauseProcessor::ClauseTy::From>);
+        static_assert(std::is_same_v<T, omp::clause::To> ||
+                      std::is_same_v<T, omp::clause::From>);
 
         // TODO Support motion modifiers: present, mapper, iterator.
         constexpr llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
-            std::is_same_v<T, ClauseProcessor::ClauseTy::To>
+            std::is_same_v<T, omp::clause::To>
                 ? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO
                 : llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
 
-        for (const Fortran::parser::OmpObject &ompObject : motionClause->v.v) {
+        for (const omp::Object &object : clause.v) {
           llvm::SmallVector<mlir::Value> bounds;
           std::stringstream asFortran;
           Fortran::lower::AddrAndBoundsInfo info =
               Fortran::lower::gatherDataOperandAddrAndBounds<
-                  Fortran::parser::OmpObject, mlir::omp::MapBoundsOp,
-                  mlir::omp::MapBoundsType>(
-                  converter, firOpBuilder, semaCtx, stmtCtx, ompObject,
-                  clauseLocation, asFortran, bounds, treatIndexAsSection);
+                  mlir::omp::MapBoundsOp, mlir::omp::MapBoundsType>(
+                  converter, firOpBuilder, semaCtx, stmtCtx, *object.id(),
+                  object.ref(), clauseLocation, asFortran, bounds,
+                  treatIndexAsSection);
 
-          auto origSymbol =
-              converter.getSymbolAddress(*getOmpObjectSymbol(ompObject));
+          auto origSymbol = converter.getSymbolAddress(*object.id());
           mlir::Value symAddr = info.addr;
           if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
             symAddr = origSymbol;
@@ -273,17 +265,6 @@ ClauseProcessor::findClause(ClauseIterator begin, ClauseIterator end) {
   return end;
 }
 
-template <typename T>
-ClauseProcessor::ClauseIterator2
-ClauseProcessor::findClause2(ClauseIterator2 begin, ClauseIterator2 end) {
-  for (ClauseIterator2 it = begin; it != end; ++it) {
-    if (std::get_if<T>(&it->u))
-      return it;
-  }
-
-  return end;
-}
-
 template <typename T>
 const T *ClauseProcessor::findUniqueClause(
     const Fortran::parser::CharBlock **source) const {
@@ -314,24 +295,6 @@ bool ClauseProcessor::findRepeatableClause(
   return found;
 }
 
-template <typename T>
-bool ClauseProcessor::findRepeatableClause2(
-    std::function<void(const T *, const Fortran::parser::CharBlock &source)>
-        callbackFn) const {
-  bool found = false;
-  ClauseIterator2 nextIt, endIt = clauses2.v.end();
-  for (ClauseIterator2 it = clauses2.v.begin(); it != endIt; it = nextIt) {
-    nextIt = findClause2<T>(it, endIt);
-
-    if (nextIt != endIt) {
-      callbackFn(&std::get<T>(nextIt->u), nextIt->source);
-      found = true;
-      ++nextIt;
-    }
-  }
-  return found;
-}
-
 template <typename T>
 bool ClauseProcessor::markClauseOccurrence(mlir::UnitAttr &result) const {
   if (findUniqueClause<T>()) {

diff  --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 5c4caa1de57382..d335129565b4e2 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -930,11 +930,8 @@ static OpTy genTargetEnterExitDataUpdateOp(
   cp.processNowait(nowaitAttr);
 
   if constexpr (std::is_same_v<OpTy, mlir::omp::TargetUpdateOp>) {
-    cp.processMotionClauses<Fortran::parser::OmpClause::To>(stmtCtx,
-                                                            mapOperands);
-    cp.processMotionClauses<Fortran::parser::OmpClause::From>(stmtCtx,
-                                                              mapOperands);
-
+    cp.processMotionClauses<clause::To>(stmtCtx, mapOperands);
+    cp.processMotionClauses<clause::From>(stmtCtx, mapOperands);
   } else {
     cp.processMap(currentLocation, directive, stmtCtx, mapOperands);
   }

diff  --git a/flang/test/Lower/OpenACC/acc-bounds.f90 b/flang/test/Lower/OpenACC/acc-bounds.f90
index df97cbcd187d2b..c275d4f1b1d5f2 100644
--- a/flang/test/Lower/OpenACC/acc-bounds.f90
+++ b/flang/test/Lower/OpenACC/acc-bounds.f90
@@ -184,7 +184,7 @@ subroutine acc_optional_data3(a, n)
 ! CHECK:   fir.result %c0{{.*}} : index
 ! CHECK: }
 ! CHECK: %[[BOUNDS:.*]] = acc.bounds lowerbound(%c0{{.*}} : index) upperbound(%{{.*}} : index) extent(%{{.*}} : index) stride(%[[STRIDE]] : index) startIdx(%c1 : index) {strideInBytes = true}
-! CHECK: %[[NOCREATE:.*]] = acc.nocreate varPtr(%[[DECL_A]]#1 : !fir.ref<!fir.array<?xf32>>) bounds(%14) -> !fir.ref<!fir.array<?xf32>> {name = "a(1:n)"}
+! CHECK: %[[NOCREATE:.*]] = acc.nocreate varPtr(%[[DECL_A]]#1 : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUNDS]]) -> !fir.ref<!fir.array<?xf32>> {name = "a(1:n)"}
 ! CHECK: acc.data dataOperands(%[[NOCREATE]] : !fir.ref<!fir.array<?xf32>>) {
 
 end module

diff  --git a/flang/test/Lower/OpenACC/acc-enter-data.f90 b/flang/test/Lower/OpenACC/acc-enter-data.f90
index 2cf50c1b62f190..251edbf9c2dd0a 100644
--- a/flang/test/Lower/OpenACC/acc-enter-data.f90
+++ b/flang/test/Lower/OpenACC/acc-enter-data.f90
@@ -234,11 +234,13 @@ subroutine acc_enter_data_dummy(a, b, n, m)
   !$acc enter data create(b(n:m))
 !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 !CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref<i32>
-!CHECK: %[[N_CONV:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index
-!CHECK: %[[LB:.*]] = arith.subi %[[N_CONV]], %[[N_IDX]] : index
+!CHECK: %[[N_CONV1:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64
+!CHECK: %[[N_CONV2:.*]] = fir.convert %[[N_CONV1]] : (i64) -> index
+!CHECK: %[[LB:.*]] = arith.subi %[[N_CONV2]], %[[N_IDX]] : index
 !CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref<i32>
-!CHECK: %[[M_CONV:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index
-!CHECK: %[[UB:.*]] = arith.subi %[[M_CONV]], %[[N_IDX]] : index
+!CHECK: %[[M_CONV1:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64
+!CHECK: %[[M_CONV2:.*]] = fir.convert %[[M_CONV1]] : (i64) -> index
+!CHECK: %[[UB:.*]] = arith.subi %[[M_CONV2]], %[[N_IDX]] : index
 !CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT_B]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[N_IDX]] : index) {strideInBytes = true}
 !CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
 !CHECK: %[[CREATE1:.*]] = acc.create varPtr(%[[ADDR]] : !fir.ref<!fir.array<?xf32>>) bounds(%[[BOUND1]]) -> !fir.ref<!fir.array<?xf32>> {name = "b(n:m)", structured = false}
@@ -248,8 +250,9 @@ subroutine acc_enter_data_dummy(a, b, n, m)
 !CHECK: %[[ONE:.*]] = arith.constant 1 : index
 !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %c0_8 : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 !CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref<i32>
-!CHECK: %[[CONVERT_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index
-!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT_N]], %[[N_IDX]] : index
+!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64
+!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index
+!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[N_IDX]] : index
 !CHECK: %[[UB:.*]] = arith.subi %[[EXT_B]], %c1{{.*}} : index
 !CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[EXT_B]] : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[N_IDX]] : index) {strideInBytes = true}
 !CHECK: %[[ADDR:.*]] = fir.box_addr %[[DECLB]]#0 : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
@@ -424,8 +427,9 @@ subroutine acc_enter_data_assumed(a, b, n, m)
 !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 
 !CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref<i32>
-!CHECK: %[[CONVERT_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index
-!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT_N]], %[[ONE]] : index
+!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64
+!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index
+!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[ONE]] : index
 !CHECK: %[[C0:.*]] = arith.constant 0 : index
 
 !CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[DECLA]]#1, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
@@ -444,8 +448,9 @@ subroutine acc_enter_data_assumed(a, b, n, m)
 !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 
 !CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref<i32>
-!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index
-!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[ONE]] : index
+!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64
+!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index
+!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[ONE]] : index
 !CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 !CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[BASELB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true}
 
@@ -460,12 +465,14 @@ subroutine acc_enter_data_assumed(a, b, n, m)
 !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLA]]#0, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 
 !CHECK: %[[LOAD_N:.*]] = fir.load %[[DECLN]]#0 : !fir.ref<i32>
-!CHECK: %[[CONVERT_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> index
-!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT_N]], %[[ONE]] : index
+!CHECK: %[[CONVERT1_N:.*]] = fir.convert %[[LOAD_N]] : (i32) -> i64
+!CHECK: %[[CONVERT2_N:.*]] = fir.convert %[[CONVERT1_N]] : (i64) -> index
+!CHECK: %[[LB:.*]] = arith.subi %[[CONVERT2_N]], %[[ONE]] : index
 
 !CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref<i32>
-!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index
-!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[ONE]] : index
+!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64
+!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index
+!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[ONE]] : index
 !CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLA]]#1, %{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 !CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[LB]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[ONE]] : index) {strideInBytes = true}
 
@@ -480,8 +487,9 @@ subroutine acc_enter_data_assumed(a, b, n, m)
 !CHECK: %[[DIMS0:.*]]:3 = fir.box_dims %[[DECLB]]#0, %[[C0]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 
 !CHECK: %[[LOAD_M:.*]] = fir.load %[[DECLM]]#0 : !fir.ref<i32>
-!CHECK: %[[CONVERT_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> index
-!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT_M]], %[[LB_C10_IDX]] : index
+!CHECK: %[[CONVERT1_M:.*]] = fir.convert %[[LOAD_M]] : (i32) -> i64
+!CHECK: %[[CONVERT2_M:.*]] = fir.convert %[[CONVERT1_M]] : (i64) -> index
+!CHECK: %[[UB:.*]] = arith.subi %[[CONVERT2_M]], %[[LB_C10_IDX]] : index
 !CHECK: %[[DIMS1:.*]]:3 = fir.box_dims %[[DECLB]]#1, %{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 !CHECK: %[[BOUND:.*]] = acc.bounds lowerbound(%[[ZERO]] : index) upperbound(%[[UB]] : index) extent(%[[DIMS1]]#1 : index) stride(%[[DIMS0]]#2 : index) startIdx(%[[LB_C10_IDX]] : index) {strideInBytes = true}
 


        


More information about the flang-commits mailing list