Skip to content

Commit

Permalink
[flang] Fold TRIM
Browse files Browse the repository at this point in the history
Accept IS_CONTIGUOUS and fold it

test folding is_contiguous

Original-commit: flang-compiler/f18@c75a079
Reviewed-on: flang-compiler/f18#911
  • Loading branch information
klausler committed Jan 8, 2020
1 parent 7ae9cf9 commit d267f20
Show file tree
Hide file tree
Showing 11 changed files with 89 additions and 26 deletions.
15 changes: 15 additions & 0 deletions flang/lib/evaluate/call.cc
Expand Up @@ -191,6 +191,21 @@ std::optional<Expr<SubscriptInteger>> ProcedureRef::LEN() const {
return proc_.LEN();
}

int ProcedureRef::Rank() const {
if (IsElemental()) {
for (const auto &arg : arguments_) {
if (arg) {
if (int rank{arg->Rank()}; rank > 0) {
return rank;
}
}
}
return 0;
} else {
return proc_.Rank();
}
}

ProcedureRef::~ProcedureRef() {}

FOR_EACH_SPECIFIC_TYPE(template class FunctionRef, )
Expand Down
2 changes: 1 addition & 1 deletion flang/lib/evaluate/call.h
Expand Up @@ -197,7 +197,7 @@ class ProcedureRef {
const ActualArguments &arguments() const { return arguments_; }

std::optional<Expr<SubscriptInteger>> LEN() const;
int Rank() const { return proc_.Rank(); }
int Rank() const;
bool IsElemental() const { return proc_.IsElemental(); }
bool operator==(const ProcedureRef &) const;
std::ostream &AsFortran(std::ostream &) const;
Expand Down
26 changes: 16 additions & 10 deletions flang/lib/evaluate/character.h
Expand Up @@ -64,22 +64,22 @@ template<int KIND> class CharacterUtils {
return str;
}

static std::int64_t INDEX(
static ConstantSubscript INDEX(
const Character &str, const Character &substr, bool back = false) {
auto pos{back ? str.rfind(substr) : str.find(substr)};
return static_cast<std::int64_t>(pos == str.npos ? 0 : pos + 1);
return static_cast<ConstantSubscript>(pos == str.npos ? 0 : pos + 1);
}

static std::int64_t SCAN(
static ConstantSubscript SCAN(
const Character &str, const Character &set, bool back = false) {
auto pos{back ? str.find_last_of(set) : str.find_first_of(set)};
return static_cast<std::int64_t>(pos == str.npos ? 0 : pos + 1);
return static_cast<ConstantSubscript>(pos == str.npos ? 0 : pos + 1);
}

static std::int64_t VERIFY(
static ConstantSubscript VERIFY(
const Character &str, const Character &set, bool back = false) {
auto pos{back ? str.find_last_not_of(set) : str.find_first_not_of(set)};
return static_cast<std::int64_t>(pos == str.npos ? 0 : pos + 1);
return static_cast<ConstantSubscript>(pos == str.npos ? 0 : pos + 1);
}

// Resize adds spaces on the right if the new size is bigger than the
Expand All @@ -93,18 +93,24 @@ template<int KIND> class CharacterUtils {
}
}

static std::int64_t LEN_TRIM(const Character &str) {
static ConstantSubscript LEN_TRIM(const Character &str) {
return VERIFY(str, Character{' '}, true);
}

static Character REPEAT(const Character &str, std::int64_t ncopies) {
static Character REPEAT(const Character &str, ConstantSubscript ncopies) {
Character result;
while (ncopies-- > 0) {
result += str;
if (!str.empty()) {
while (ncopies-- > 0) {
result += str;
}
}
return result;
}

static Character TRIM(const Character &str) {
return str.substr(0, LEN_TRIM(str));
}

private:
// Following helpers assume that character encodings contain ASCII
static constexpr CharT Space() { return 0x20; }
Expand Down
18 changes: 8 additions & 10 deletions flang/lib/evaluate/check-expression.cc
Expand Up @@ -261,7 +261,8 @@ class IsSimplyContiguousHelper
using Base::operator();

Result operator()(const semantics::Symbol &symbol) const {
if (symbol.attrs().test(semantics::Attr::CONTIGUOUS)) {
if (symbol.attrs().test(semantics::Attr::CONTIGUOUS) ||
symbol.Rank() == 0) {
return true;
} else if (semantics::IsPointer(symbol)) {
return false;
Expand All @@ -276,11 +277,8 @@ class IsSimplyContiguousHelper
}

Result operator()(const ArrayRef &x) const {
if (x.base().Rank() > 0 || !CheckSubscripts(x.subscript())) {
return false;
} else {
return (*this)(x.base());
}
return (x.base().IsSymbol() || x.base().Rank() == 0) &&
CheckSubscripts(x.subscript()) && (*this)(x.base());
}
Result operator()(const CoarrayRef &x) const {
return CheckSubscripts(x.subscript());
Expand Down Expand Up @@ -330,11 +328,11 @@ class IsSimplyContiguousHelper
template<typename A>
bool IsSimplyContiguous(const A &x, const IntrinsicProcTable &table) {
if (IsVariable(x)) {
if (auto known{IsSimplyContiguousHelper{table}(x)}) {
return *known;
}
auto known{IsSimplyContiguousHelper{table}(x)};
return known && *known;
} else {
return true; // not a variable
}
return false;
}

template bool IsSimplyContiguous(
Expand Down
8 changes: 7 additions & 1 deletion flang/lib/evaluate/fold-character.cc
Expand Up @@ -45,9 +45,15 @@ Expr<Type<TypeCategory::Character, KIND>> FoldIntrinsicFunction(
CharacterUtils<KIND>::REPEAT(std::get<Scalar<T>>(*scalars),
std::get<Scalar<SubscriptInteger>>(*scalars).ToInt64())}};
}
} else if (name == "trim") { // not elemental
if (auto scalar{
GetScalarConstantArguments<T>(context, funcRef.arguments())}) {
return Expr<T>{Constant<T>{
CharacterUtils<KIND>::TRIM(std::get<Scalar<T>>(*scalar))}};
}
}
// TODO: cshift, eoshift, maxval, minval, pack, reduce,
// spread, transfer, transpose, trim, unpack
// spread, transfer, transpose, unpack
return Expr<T>{std::move(funcRef)};
}

Expand Down
12 changes: 11 additions & 1 deletion flang/lib/evaluate/fold-logical.cc
Expand Up @@ -6,6 +6,7 @@
//
//----------------------------------------------------------------------------//

#include "check-expression.h"
#include "fold-implementation.h"

namespace Fortran::evaluate {
Expand Down Expand Up @@ -76,12 +77,21 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
[&fptr](const Scalar<LargestInt> &i, const Scalar<LargestInt> &j) {
return Scalar<T>{std::invoke(fptr, i, j)};
}));
} else if (name == "is_contiguous") {
if (args.at(0)) {
if (auto *expr{args[0]->UnwrapExpr()}) {
if (IsSimplyContiguous(*expr, context.intrinsics())) {
return Expr<T>{true};
}
}
}
} else if (name == "merge") {
return FoldMerge<T>(context, std::move(funcRef));
}
// TODO: btest, cshift, dot_product, eoshift, is_iostat_end,
// is_iostat_eor, lge, lgt, lle, llt, logical, matmul, out_of_range,
// pack, parity, reduce, spread, transfer, transpose, unpack
// pack, parity, reduce, spread, transfer, transpose, unpack,
// extends_type_of, same_type_as
return Expr<T>{std::move(funcRef)};
}

Expand Down
4 changes: 2 additions & 2 deletions flang/lib/evaluate/intrinsics.cc
Expand Up @@ -457,6 +457,8 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{{"i", SameInt}, {"shift", AnyInt},
{"size", AnyInt, Rank::elemental, Optionality::optional}},
SameInt},
{"is_contiguous", {{"array", Addressable, Rank::anyOrAssumedRank}},
DefaultLogical},
{"is_iostat_end", {{"i", AnyInt}}, DefaultLogical},
{"is_iostat_eor", {{"i", AnyInt}}, DefaultLogical},
{"kind", {{"x", AnyIntrinsic}}, DefaultInt},
Expand Down Expand Up @@ -704,8 +706,6 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
// LCOBOUND, UCOBOUND, FAILED_IMAGES, GET_TEAM, IMAGE_INDEX,
// NUM_IMAGES, STOPPED_IMAGES, TEAM_NUMBER, THIS_IMAGE,
// COSHAPE
// TODO: Object characteristic inquiry functions
// IS_CONTIGUOUS
// TODO: Non-standard intrinsic functions
// AND, OR, XOR, LSHIFT, RSHIFT, SHIFT, ZEXT, IZEXT,
// COMPL, EQV, NEQV, INT8, JINT, JNINT, KNINT,
Expand Down
1 change: 1 addition & 0 deletions flang/test/evaluate/CMakeLists.txt
Expand Up @@ -142,6 +142,7 @@ set(FOLDING_TESTS
folding06.f90
folding07.f90
folding08.f90
folding09.f90
)

add_test(Expression expression-test)
Expand Down
Binary file modified flang/test/evaluate/folding05.f90
Binary file not shown.
27 changes: 27 additions & 0 deletions flang/test/evaluate/folding09.f90
@@ -0,0 +1,27 @@
! Test folding of IS_CONTIGUOUS on simply contiguous items (9.5.4)
! When IS_CONTIGUOUS() is constant, it's .TRUE.

module m
real, target :: hosted(2)
contains
function f()
real, pointer, contiguous :: f(:)
f => hosted
end function
subroutine test(arr1, arr2, arr3, mat)
real, intent(in) :: arr1(:), arr2(10), mat(10, 10)
real, intent(in), contiguous :: arr3(:)
real :: scalar
logical, parameter :: isc01 = is_contiguous(0)
logical, parameter :: isc02 = is_contiguous(scalar)
logical, parameter :: isc03 = is_contiguous(scalar + scalar)
logical, parameter :: isc04 = is_contiguous([0, 1, 2])
logical, parameter :: isc05 = is_contiguous(arr1 + 1.0)
logical, parameter :: isc06 = is_contiguous(arr2)
logical, parameter :: isc07 = is_contiguous(mat)
logical, parameter :: isc08 = is_contiguous(mat(1:10,1))
logical, parameter :: isc09 = is_contiguous(arr2(1:10:1))
logical, parameter :: isc10 = is_contiguous(arr3)
logical, parameter :: isc11 = is_contiguous(f())
end subroutine
end module
2 changes: 1 addition & 1 deletion flang/test/semantics/modfile32.f90
Expand Up @@ -216,7 +216,7 @@ subroutine s3(x, y)
! end
! subroutine s3(x, y)
! real(4) :: x(1_8:10_8, 1_8:10_8)
! real(4) :: y(1_8:int(ubound(f_elem(x),1_4),kind=8))
! real(4) :: y(1_8:10_8)
! end
!end

Expand Down

0 comments on commit d267f20

Please sign in to comment.