[flang-commits] [flang] d8b4ea4 - [flang] Fix UBOUND() folding for constant arrays

Mike Kashkarov via flang-commits flang-commits at lists.llvm.org
Wed Apr 27 09:17:56 PDT 2022


Author: Mike Kashkarov
Date: 2022-04-28T01:17:47+09:00
New Revision: d8b4ea486a5c152ba1ceb656a3d6638defe40fe1

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

LOG: [flang] Fix UBOUND() folding for constant arrays

Similarly to LBOUND in https://reviews.llvm.org/D123237, fix UBOUND() folding
for constant arrays (for both w/ and w/o DIM=): convert
GetConstantArrayLboundHelper into common helper class for both lower/upper
bounds.

Reviewed By: jeanPerier

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

Added: 
    

Modified: 
    flang/include/flang/Evaluate/constant.h
    flang/lib/Evaluate/constant.cpp
    flang/lib/Evaluate/fold-integer.cpp
    flang/test/Evaluate/folding08.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Evaluate/constant.h b/flang/include/flang/Evaluate/constant.h
index 97445649b8c4..6784adf9c492 100644
--- a/flang/include/flang/Evaluate/constant.h
+++ b/flang/include/flang/Evaluate/constant.h
@@ -64,6 +64,7 @@ class ConstantBounds {
   ~ConstantBounds();
   const ConstantSubscripts &shape() const { return shape_; }
   const ConstantSubscripts &lbounds() const { return lbounds_; }
+  ConstantSubscripts ComputeUbounds(std::optional<int> dim) const;
   void set_lbounds(ConstantSubscripts &&);
   void SetLowerBoundsToOne();
   int Rank() const { return GetRank(shape_); }

diff  --git a/flang/lib/Evaluate/constant.cpp b/flang/lib/Evaluate/constant.cpp
index 19c3c2aa913a..1a4d30cf9d14 100644
--- a/flang/lib/Evaluate/constant.cpp
+++ b/flang/lib/Evaluate/constant.cpp
@@ -32,6 +32,20 @@ void ConstantBounds::set_lbounds(ConstantSubscripts &&lb) {
   }
 }
 
+ConstantSubscripts ConstantBounds::ComputeUbounds(
+    std::optional<int> dim) const {
+  if (dim) {
+    CHECK(*dim < Rank());
+    return {lbounds_[*dim] + shape_[*dim] - 1};
+  } else {
+    ConstantSubscripts ubounds(Rank());
+    for (int i{0}; i < Rank(); ++i) {
+      ubounds[i] = lbounds_[i] + shape_[i] - 1;
+    }
+    return ubounds;
+  }
+}
+
 void ConstantBounds::SetLowerBoundsToOne() {
   for (auto &n : lbounds_) {
     n = 1;

diff  --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp
index a65200027433..3ca1d45fb4bf 100644
--- a/flang/lib/Evaluate/fold-integer.cpp
+++ b/flang/lib/Evaluate/fold-integer.cpp
@@ -29,44 +29,66 @@ Expr<T> PackageConstantBounds(
   }
 }
 
-// Class to retrieve the constant lower bound of an expression which is an
+// Class to retrieve the constant bound of an expression which is an
 // array that devolves to a type of Constant<T>
-class GetConstantArrayLboundHelper {
+class GetConstantArrayBoundHelper {
 public:
-  GetConstantArrayLboundHelper(std::optional<ConstantSubscript> dim)
-      : dim_{dim} {}
+  template <typename T>
+  static Expr<T> GetLbound(
+      const Expr<SomeType> &array, std::optional<int> dim) {
+    return PackageConstantBounds<T>(
+        GetConstantArrayBoundHelper(dim, /*getLbound=*/true).Get(array),
+        dim.has_value());
+  }
+
+  template <typename T>
+  static Expr<T> GetUbound(
+      const Expr<SomeType> &array, std::optional<int> dim) {
+    return PackageConstantBounds<T>(
+        GetConstantArrayBoundHelper(dim, /*getLbound=*/false).Get(array),
+        dim.has_value());
+  }
+
+private:
+  GetConstantArrayBoundHelper(
+      std::optional<ConstantSubscript> dim, bool getLbound)
+      : dim_{dim}, getLbound_{getLbound} {}
 
-  template <typename T> ConstantSubscripts GetLbound(const T &) {
+  template <typename T> ConstantSubscripts Get(const T &) {
     // The method is needed for template expansion, but we should never get
     // here in practice.
     CHECK(false);
     return {0};
   }
 
-  template <typename T> ConstantSubscripts GetLbound(const Constant<T> &x) {
-    // Return the lower bound
-    if (dim_) {
-      return {x.lbounds().at(*dim_)};
+  template <typename T> ConstantSubscripts Get(const Constant<T> &x) {
+    if (getLbound_) {
+      // Return the lower bound
+      if (dim_) {
+        return {x.lbounds().at(*dim_)};
+      } else {
+        return x.lbounds();
+      }
     } else {
-      return x.lbounds();
+      return x.ComputeUbounds(dim_);
     }
   }
 
-  template <typename T> ConstantSubscripts GetLbound(const Parentheses<T> &x) {
+  template <typename T> ConstantSubscripts Get(const Parentheses<T> &x) {
     // LBOUND for (x) is [1, ..., 1] cause of temp variable inside
     // parentheses (lower bound is omitted, the default value is 1).
     return ConstantSubscripts(x.Rank(), ConstantSubscript{1});
   }
 
-  template <typename T> ConstantSubscripts GetLbound(const Expr<T> &x) {
+  template <typename T> ConstantSubscripts Get(const Expr<T> &x) {
     // recurse through Expr<T>'a until we hit a constant
-    return common::visit([&](const auto &inner) { return GetLbound(inner); },
+    return common::visit([&](const auto &inner) { return Get(inner); },
         //      [&](const auto &) { return 0; },
         x.u);
   }
 
-private:
-  std::optional<ConstantSubscript> dim_;
+  const std::optional<ConstantSubscript> dim_;
+  const bool getLbound_;
 };
 
 template <int KIND>
@@ -112,9 +134,7 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
         }
       }
       if (IsActuallyConstant(*array)) {
-        const ConstantSubscripts bounds{
-            GetConstantArrayLboundHelper{dim}.GetLbound(*array)};
-        return PackageConstantBounds<T>(std::move(bounds), dim.has_value());
+        return GetConstantArrayBoundHelper::GetLbound<T>(*array, dim);
       }
       if (lowerBoundsAreOne) {
         ConstantSubscripts ones(rank, ConstantSubscript{1});
@@ -178,6 +198,9 @@ Expr<Type<TypeCategory::Integer, KIND>> UBOUND(FoldingContext &context,
           takeBoundsFromShape = symbol.Rank() == 0; // UBOUND(array%component)
         }
       }
+      if (IsActuallyConstant(*array)) {
+        return GetConstantArrayBoundHelper::GetUbound<T>(*array, dim);
+      }
       if (takeBoundsFromShape) {
         if (auto shape{GetContextFreeShape(context, *array)}) {
           if (dim) {

diff  --git a/flang/test/Evaluate/folding08.f90 b/flang/test/Evaluate/folding08.f90
index 3c56229d6eeb..9c9ba66473eb 100644
--- a/flang/test/Evaluate/folding08.f90
+++ b/flang/test/Evaluate/folding08.f90
@@ -77,23 +77,33 @@ subroutine test2
       end block
     end associate
   end subroutine
-  subroutine test3_lbound_parameter
-    ! Test lbound with constant arrays
+  subroutine test3_bound_parameter
+    ! Test [ul]bound with parameter arrays
     integer, parameter :: a1(1) = 0
     integer, parameter :: lba1(*) = lbound(a1)
     logical, parameter :: test_lba1 = all(lba1 == [1])
+    integer, parameter :: uba1(*) = ubound(a1)
+    logical, parameter :: test_uba1 = all(lba1 == [1])
 
     integer, parameter :: a2(0:1) = 0
     integer, parameter :: lba2(*) = lbound(a2)
     logical, parameter :: test_lba2 = all(lba2 == [0])
+    integer, parameter :: uba2(*) = ubound(a2)
+    logical, parameter :: test_uba2 = all(uba2 == [1])
 
     integer, parameter :: a3(-10:-5,1,4:6) = 0
     integer, parameter :: lba3(*) = lbound(a3)
     logical, parameter :: test_lba3 = all(lba3 == [-10, 1, 4])
+    integer, parameter :: uba3(*) = ubound(a3)
+    logical, parameter :: test_uba3 = all(uba3 == [-5, 1, 6])
+
     ! Exercise with DIM=
     logical, parameter :: test_lba3_dim = lbound(a3, 1) == -10 .and. &
          lbound(a3, 2) == 1 .and. &
          lbound(a3, 3) == 4
+    logical, parameter :: test_uba3_dim = ubound(a3, 1) == -5 .and. &
+         ubound(a3, 2) == 1 .and. &
+         ubound(a3, 3) == 6
   end subroutine
   subroutine test4_lbound_parentheses
     ! Test lbound with (x) expressions


        


More information about the flang-commits mailing list