Skip to content

Commit bd5371e

Browse files
committed
[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
1 parent c8f822a commit bd5371e

File tree

2 files changed

+53
-16
lines changed

2 files changed

+53
-16
lines changed

flang/lib/Evaluate/fold-integer.cpp

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,60 @@
1212

1313
namespace Fortran::evaluate {
1414

15+
// Given a collection of ConstantSubscripts values, package them as a Constant.
16+
// Return scalar value if asScalar == true and shape-dim array otherwise.
17+
template <typename T>
18+
Expr<T> PackageConstantBounds(
19+
const ConstantSubscripts &&bounds, bool asScalar = false) {
20+
if (asScalar) {
21+
return Expr<T>{Constant<T>{bounds.at(0)}};
22+
} else {
23+
// As rank-dim array
24+
const int rank{GetRank(bounds)};
25+
std::vector<Scalar<T>> packed(rank);
26+
std::transform(bounds.begin(), bounds.end(), packed.begin(),
27+
[](ConstantSubscript x) { return Scalar<T>(x); });
28+
return Expr<T>{Constant<T>{std::move(packed), ConstantSubscripts{rank}}};
29+
}
30+
}
31+
1532
// Class to retrieve the constant lower bound of an expression which is an
1633
// array that devolves to a type of Constant<T>
1734
class GetConstantArrayLboundHelper {
1835
public:
19-
GetConstantArrayLboundHelper(ConstantSubscript dim) : dim_{dim} {}
36+
GetConstantArrayLboundHelper(std::optional<ConstantSubscript> dim)
37+
: dim_{dim} {}
2038

21-
template <typename T> ConstantSubscript GetLbound(const T &) {
39+
template <typename T> ConstantSubscripts GetLbound(const T &) {
2240
// The method is needed for template expansion, but we should never get
2341
// here in practice.
2442
CHECK(false);
25-
return 0;
43+
return {0};
2644
}
2745

28-
template <typename T> ConstantSubscript GetLbound(const Constant<T> &x) {
46+
template <typename T> ConstantSubscripts GetLbound(const Constant<T> &x) {
2947
// Return the lower bound
30-
return x.lbounds()[dim_];
48+
if (dim_) {
49+
return {x.lbounds().at(*dim_)};
50+
} else {
51+
return x.lbounds();
52+
}
3153
}
3254

33-
template <typename T> ConstantSubscript GetLbound(const Parentheses<T> &x) {
55+
template <typename T> ConstantSubscripts GetLbound(const Parentheses<T> &x) {
3456
// Strip off the parentheses
3557
return GetLbound(x.left());
3658
}
3759

38-
template <typename T> ConstantSubscript GetLbound(const Expr<T> &x) {
60+
template <typename T> ConstantSubscripts GetLbound(const Expr<T> &x) {
3961
// recurse through Expr<T>'a until we hit a constant
4062
return common::visit([&](const auto &inner) { return GetLbound(inner); },
4163
// [&](const auto &) { return 0; },
4264
x.u);
4365
}
4466

4567
private:
46-
ConstantSubscript dim_;
68+
std::optional<ConstantSubscript> dim_;
4769
};
4870

4971
template <int KIND>
@@ -89,16 +111,13 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
89111
}
90112
}
91113
if (IsActuallyConstant(*array)) {
92-
return Expr<T>{GetConstantArrayLboundHelper{*dim}.GetLbound(*array)};
114+
const ConstantSubscripts bounds{
115+
GetConstantArrayLboundHelper{dim}.GetLbound(*array)};
116+
return PackageConstantBounds<T>(std::move(bounds), dim.has_value());
93117
}
94118
if (lowerBoundsAreOne) {
95-
if (dim) {
96-
return Expr<T>{1};
97-
} else {
98-
std::vector<Scalar<T>> ones(rank, Scalar<T>{1});
99-
return Expr<T>{
100-
Constant<T>{std::move(ones), ConstantSubscripts{rank}}};
101-
}
119+
ConstantSubscripts ones(rank, ConstantSubscript{1});
120+
return PackageConstantBounds<T>(std::move(ones), dim.has_value());
102121
}
103122
}
104123
}

flang/test/Evaluate/folding08.f90

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,22 @@ subroutine test2
7777
end block
7878
end associate
7979
end subroutine
80+
subroutine test3_lbound_parameter
81+
! Test lbound with constant arrays
82+
integer, parameter :: a1(1) = 0
83+
integer, parameter :: lba1(*) = lbound(a1)
84+
logical, parameter :: test_lba1 = all(lba1 == [1])
85+
86+
integer, parameter :: a2(0:1) = 0
87+
integer, parameter :: lba2(*) = lbound(a2)
88+
logical, parameter :: test_lba2 = all(lba2 == [0])
89+
90+
integer, parameter :: a3(-10:-5,1,4:6) = 0
91+
integer, parameter :: lba3(*) = lbound(a3)
92+
logical, parameter :: test_lba3 = all(lba3 == [-10, 1, 4])
93+
! Exercise with DIM=
94+
logical, parameter :: test_lba3_dim = lbound(a3, 1) == -10 .and. &
95+
lbound(a3, 2) == 1 .and. &
96+
lbound(a3, 3) == 4
97+
end subroutine
8098
end

0 commit comments

Comments
 (0)