[flang-commits] [flang] bd5371e - [flang] Fix LBOUND() folding for constant arrays
Mike Kashkarov via flang-commits
flang-commits at lists.llvm.org
Wed Apr 20 10:04:37 PDT 2022
Author: Mike Kashkarov
Date: 2022-04-20T20:04:31+03:00
New Revision: bd5371e4fc607aae1a77f29273fd130b59e72409
URL: https://github.com/llvm/llvm-project/commit/bd5371e4fc607aae1a77f29273fd130b59e72409
DIFF: https://github.com/llvm/llvm-project/commit/bd5371e4fc607aae1a77f29273fd130b59e72409.diff
LOG: [flang] Fix LBOUND() folding for constant arrays
Previously constant folding uses 'dim' without checks which leads to ICE if we
do not have DIM= parameter. And for inputs without DIM= we need to form an
array of rank size with computed bounds instead of single value.
Add additional PackageConstant function to simplify 'if (dim)' handling since we
need to distinguish between scalar initialization in case of DIM= argument and
rank=1 array.
Also add a few more tests with 'parameter' type to verify folding for constant
arrays.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D123237
Added:
Modified:
flang/lib/Evaluate/fold-integer.cpp
flang/test/Evaluate/folding08.f90
Removed:
################################################################################
diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp
index d07af216d230a..cbecda0ecebda 100644
--- a/flang/lib/Evaluate/fold-integer.cpp
+++ b/flang/lib/Evaluate/fold-integer.cpp
@@ -12,30 +12,52 @@
namespace Fortran::evaluate {
+// Given a collection of ConstantSubscripts values, package them as a Constant.
+// Return scalar value if asScalar == true and shape-dim array otherwise.
+template <typename T>
+Expr<T> PackageConstantBounds(
+ const ConstantSubscripts &&bounds, bool asScalar = false) {
+ if (asScalar) {
+ return Expr<T>{Constant<T>{bounds.at(0)}};
+ } else {
+ // As rank-dim array
+ const int rank{GetRank(bounds)};
+ std::vector<Scalar<T>> packed(rank);
+ std::transform(bounds.begin(), bounds.end(), packed.begin(),
+ [](ConstantSubscript x) { return Scalar<T>(x); });
+ return Expr<T>{Constant<T>{std::move(packed), ConstantSubscripts{rank}}};
+ }
+}
+
// Class to retrieve the constant lower bound of an expression which is an
// array that devolves to a type of Constant<T>
class GetConstantArrayLboundHelper {
public:
- GetConstantArrayLboundHelper(ConstantSubscript dim) : dim_{dim} {}
+ GetConstantArrayLboundHelper(std::optional<ConstantSubscript> dim)
+ : dim_{dim} {}
- template <typename T> ConstantSubscript GetLbound(const T &) {
+ template <typename T> ConstantSubscripts GetLbound(const T &) {
// The method is needed for template expansion, but we should never get
// here in practice.
CHECK(false);
- return 0;
+ return {0};
}
- template <typename T> ConstantSubscript GetLbound(const Constant<T> &x) {
+ template <typename T> ConstantSubscripts GetLbound(const Constant<T> &x) {
// Return the lower bound
- return x.lbounds()[dim_];
+ if (dim_) {
+ return {x.lbounds().at(*dim_)};
+ } else {
+ return x.lbounds();
+ }
}
- template <typename T> ConstantSubscript GetLbound(const Parentheses<T> &x) {
+ template <typename T> ConstantSubscripts GetLbound(const Parentheses<T> &x) {
// Strip off the parentheses
return GetLbound(x.left());
}
- template <typename T> ConstantSubscript GetLbound(const Expr<T> &x) {
+ template <typename T> ConstantSubscripts GetLbound(const Expr<T> &x) {
// recurse through Expr<T>'a until we hit a constant
return common::visit([&](const auto &inner) { return GetLbound(inner); },
// [&](const auto &) { return 0; },
@@ -43,7 +65,7 @@ class GetConstantArrayLboundHelper {
}
private:
- ConstantSubscript dim_;
+ std::optional<ConstantSubscript> dim_;
};
template <int KIND>
@@ -89,16 +111,13 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
}
}
if (IsActuallyConstant(*array)) {
- return Expr<T>{GetConstantArrayLboundHelper{*dim}.GetLbound(*array)};
+ const ConstantSubscripts bounds{
+ GetConstantArrayLboundHelper{dim}.GetLbound(*array)};
+ return PackageConstantBounds<T>(std::move(bounds), dim.has_value());
}
if (lowerBoundsAreOne) {
- if (dim) {
- return Expr<T>{1};
- } else {
- std::vector<Scalar<T>> ones(rank, Scalar<T>{1});
- return Expr<T>{
- Constant<T>{std::move(ones), ConstantSubscripts{rank}}};
- }
+ ConstantSubscripts ones(rank, ConstantSubscript{1});
+ return PackageConstantBounds<T>(std::move(ones), dim.has_value());
}
}
}
diff --git a/flang/test/Evaluate/folding08.f90 b/flang/test/Evaluate/folding08.f90
index 7432cbd86fb08..a5b65e0246efb 100644
--- a/flang/test/Evaluate/folding08.f90
+++ b/flang/test/Evaluate/folding08.f90
@@ -77,4 +77,22 @@ subroutine test2
end block
end associate
end subroutine
+ subroutine test3_lbound_parameter
+ ! Test lbound with constant arrays
+ integer, parameter :: a1(1) = 0
+ integer, parameter :: lba1(*) = lbound(a1)
+ logical, parameter :: test_lba1 = all(lba1 == [1])
+
+ integer, parameter :: a2(0:1) = 0
+ integer, parameter :: lba2(*) = lbound(a2)
+ logical, parameter :: test_lba2 = all(lba2 == [0])
+
+ integer, parameter :: a3(-10:-5,1,4:6) = 0
+ integer, parameter :: lba3(*) = lbound(a3)
+ logical, parameter :: test_lba3 = all(lba3 == [-10, 1, 4])
+ ! Exercise with DIM=
+ logical, parameter :: test_lba3_dim = lbound(a3, 1) == -10 .and. &
+ lbound(a3, 2) == 1 .and. &
+ lbound(a3, 3) == 4
+ end subroutine
end
More information about the flang-commits
mailing list