[flang-commits] [PATCH] D128759: flang] Fix folding of LEN(f(...))

Peter Klausler via Phabricator via flang-commits flang-commits at lists.llvm.org
Tue Jun 28 14:27:47 PDT 2022


klausler created this revision.
klausler added a reviewer: jeanPerier.
klausler added a project: Flang.
Herald added a subscriber: jdoerfert.
Herald added a reviewer: sscalpone.
Herald added a project: All.
klausler requested review of this revision.

[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.


https://reviews.llvm.org/D128759

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


Index: flang/test/Evaluate/rewrite01.f90
===================================================================
--- flang/test/Evaluate/rewrite01.f90
+++ flang/test/Evaluate/rewrite01.f90
@@ -112,9 +112,21 @@
   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 @@
   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
Index: flang/lib/Evaluate/variable.cpp
===================================================================
--- flang/lib/Evaluate/variable.cpp
+++ flang/lib/Evaluate/variable.cpp
@@ -267,7 +267,10 @@
   }
   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)});
       }
Index: flang/lib/Evaluate/call.cpp
===================================================================
--- flang/lib/Evaluate/call.cpp
+++ 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 @@
     // 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 {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D128759.440769.patch
Type: text/x-patch
Size: 2813 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/flang-commits/attachments/20220628/5bc5e509/attachment.bin>


More information about the flang-commits mailing list