[flang-commits] [flang] b70f507 - [flang] Fix folding of LEN(f(...))

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Wed Jun 29 10:25:17 PDT 2022


Author: Peter Klausler
Date: 2022-06-29T10:25:07-07:00
New Revision: b70f507c75ac327eba895a970b507467a325f03b

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

LOG: [flang] Fix folding of LEN(f(...))

LEN(f(...)), where "f" is a non-intrinsic function, should not be folded
to anything else unless the result is a known constant value.  While there
are conceivable cases in which we could do better (e.g., an internal function
whose length is a host-associated INTENT(IN) dummy argument), there are
other cases that we're getting wrong.

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

Added: 
    

Modified: 
    flang/lib/Evaluate/call.cpp
    flang/lib/Evaluate/variable.cpp
    flang/test/Evaluate/rewrite01.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Evaluate/call.cpp b/flang/lib/Evaluate/call.cpp
index 75bc3939c00ee..39ca949b066f0 100644
--- a/flang/lib/Evaluate/call.cpp
+++ b/flang/lib/Evaluate/call.cpp
@@ -10,6 +10,7 @@
 #include "flang/Common/Fortran.h"
 #include "flang/Common/idioms.h"
 #include "flang/Evaluate/characteristics.h"
+#include "flang/Evaluate/check-expression.h"
 #include "flang/Evaluate/expression.h"
 #include "flang/Evaluate/tools.h"
 #include "flang/Semantics/symbol.h"
@@ -199,7 +200,15 @@ std::optional<Expr<SubscriptInteger>> ProcedureRef::LEN() const {
     // ProcedureDesignator::LEN() because they're independent of the
     // lengths of the actual arguments.
   }
-  return proc_.LEN();
+  if (auto len{proc_.LEN()}) {
+    if (IsActuallyConstant(*len)) {
+      return len;
+    }
+    // TODO: Handle cases where the length of a function result is a
+    // safe expression in terms of actual argument values, after substituting
+    // actual argument expressions for INTENT(IN)/VALUE dummy arguments.
+  }
+  return std::nullopt;
 }
 
 int ProcedureRef::Rank() const {

diff  --git a/flang/lib/Evaluate/variable.cpp b/flang/lib/Evaluate/variable.cpp
index b19effa980233..2de0de668d856 100644
--- a/flang/lib/Evaluate/variable.cpp
+++ b/flang/lib/Evaluate/variable.cpp
@@ -267,7 +267,10 @@ static std::optional<Expr<SubscriptInteger>> SymbolLEN(const Symbol &symbol) {
   }
   if (auto dyType{DynamicType::From(ultimate)}) {
     if (auto len{dyType->GetCharLength()}) {
-      if (ultimate.owner().IsDerivedType() || IsScopeInvariantExpr(*len)) {
+      if (auto constLen{ToInt64(*len)}) {
+        return Expr<SubscriptInteger>{std::max<std::int64_t>(*constLen, 0)};
+      } else if (ultimate.owner().IsDerivedType() ||
+          IsScopeInvariantExpr(*len)) {
         return AsExpr(Extremum<SubscriptInteger>{
             Ordering::Greater, Expr<SubscriptInteger>{0}, std::move(*len)});
       }

diff  --git a/flang/test/Evaluate/rewrite01.f90 b/flang/test/Evaluate/rewrite01.f90
index 94c43d95ab27a..0d781094b3d56 100644
--- a/flang/test/Evaluate/rewrite01.f90
+++ b/flang/test/Evaluate/rewrite01.f90
@@ -112,9 +112,21 @@ subroutine len_test(a,b, c, d, e, n, m)
   external d
   integer, intent(in) :: n, m
   character(n), intent(in) :: e
+  interface
+     function fun1(L)
+       character(L) :: fun1
+       integer :: L
+     end function fun1
+  end interface
+  interface
+     function mofun(L)
+       character(L) :: mofun
+       integer, intent(in) :: L
+     end function mofun
+  end interface
 
-  !CHECK: PRINT *, int(a%len,kind=8)
-  print *, len(a, kind=8)
+  !CHECK: PRINT *, int(int(a%len,kind=8),kind=4)
+  print *, len(a)
   !CHECK: PRINT *, 5_4
   print *, len(a(1:5))
   !CHECK: PRINT *, len(b(a))
@@ -139,6 +151,10 @@ subroutine len_test(a,b, c, d, e, n, m)
   print *, len(b(a(n:m)))
   !CHECK: PRINT *, int(max(0_8,max(0_8,int(n,kind=8))-4_8+1_8),kind=4)
   print *, len(e(4:))
+  !CHECK: PRINT *, len(fun1(n-m))
+  print *, len(fun1(n-m))
+  !CHECK: PRINT *, len(mofun(m+1_4))
+  print *, len(mofun(m+1))
 end subroutine len_test
 
 end module


        


More information about the flang-commits mailing list