[flang] Fix calls to LBOUND() intrinsic for arrays with lower bounds not 1

Constant folding for calls to LBOUND() was not working when the lower bound of
a constant array was not 1.

I fixed this and re-enabled the test in Evaluate/folding16.f90 that previously
was silently failing.  I slightly changed the test to parenthesize the first
argument to exercise all of the new code.

Differential Revision: https://reviews.llvm.org/D95894
This commit is contained in:
Peter Steinfeld 2021-02-02 14:15:50 -08:00
parent 15f26c5f51
commit 2018dafce5
2 changed files with 40 additions and 4 deletions

View File

@ -7,9 +7,44 @@
//===----------------------------------------------------------------------===//
#include "fold-implementation.h"
#include "flang/Evaluate/check-expression.h"
namespace Fortran::evaluate {
// 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} {}
template <typename T> ConstantSubscript GetLbound(const T &) {
// The method is needed for template expansion, but we should never get
// here in practice.
CHECK(false);
return 0;
}
template <typename T> ConstantSubscript GetLbound(const Constant<T> &x) {
// Return the lower bound
return x.lbounds()[dim_];
}
template <typename T> ConstantSubscript GetLbound(const Parentheses<T> &x) {
// Strip off the parentheses
return GetLbound(x.left());
}
template <typename T> ConstantSubscript GetLbound(const Expr<T> &x) {
// recurse through Expr<T>'a until we hit a constant
return std::visit([&](const auto &inner) { return GetLbound(inner); },
// [&](const auto &) { return 0; },
x.u);
}
private:
ConstantSubscript dim_;
};
template <int KIND>
Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
FunctionRef<Type<TypeCategory::Integer, KIND>> &&funcRef) {
@ -51,6 +86,9 @@ Expr<Type<TypeCategory::Integer, KIND>> LBOUND(FoldingContext &context,
lowerBoundsAreOne = symbol.Rank() == 0; // LBOUND(array%component)
}
}
if (IsActuallyConstant(*array)) {
return Expr<T>{GetConstantArrayLboundHelper{*dim}.GetLbound(*array)};
}
if (lowerBoundsAreOne) {
if (dim) {
return Expr<T>{1};

View File

@ -7,10 +7,8 @@ module m
integer, parameter :: c(-1:1) = [33, 22, 11]
integer, parameter :: d(1:3) = [33, 22, 11]
integer, parameter :: e(-2:0) = ([33, 22, 11])
! The following test is commented out because constant folding for "lbound"
! is currently broken
!logical, parameter :: test_1 = lbound(a,1)==-1 .and. lbound(b,1)==-1 .and. &
! lbound(log(a),1)==1 .and. all(b==0)
logical, parameter :: test_1 = lbound((a),1)==-1 .and. lbound(b,1)==-1 .and. &
lbound(log(a),1)==1 .and. all(b==0)
logical, parameter :: test_2 = all(c .eq. d)
logical, parameter :: test_3 = all(c .eq. e)
logical, parameter :: test_4 = all(d .eq. e)