[flang-commits] [flang] [flang] Better IS_CONTIGUOUS folding for substrings (PR #115970)

via flang-commits flang-commits at lists.llvm.org
Thu Nov 14 01:36:05 PST 2024


================
@@ -908,7 +908,54 @@ class IsContiguousHelper
   Result operator()(const ComplexPart &x) const {
     return x.complex().Rank() == 0;
   }
-  Result operator()(const Substring &) const { return std::nullopt; }
+  Result operator()(const Substring &x) const {
+    if (x.Rank() == 0) {
+      return true; // scalar substring always contiguous
+    }
+    // Substrings with rank must have DataRefs as their parents
+    const DataRef &parentDataRef{DEREF(x.GetParentIf<DataRef>())};
+    std::optional<std::int64_t> len;
+    if (auto lenExpr{parentDataRef.LEN()}) {
+      len = ToInt64(Fold(context_, std::move(*lenExpr)));
+      if (len) {
+        if (*len <= 0) {
+          return true; // empty substrings
+        } else if (*len == 1) {
+          // Substrings can't be incomplete; is base array contiguous?
+          return (*this)(parentDataRef);
+        }
+      }
+    }
+    auto upperExpr{x.upper()};
+    std::optional<std::int64_t> upper;
+    bool upperIsLen{false};
+    if (upperExpr) {
+      upper = ToInt64(Fold(context_, std::move(*upperExpr)));
+      if (upper) {
+        if (*upper < 1) {
+          return true; // substring(n:0) empty
+        }
+        upperIsLen = len && *upper >= *len;
+      }
+    } else {
+      upperIsLen = true; // substring(n:)
----------------
jeanPerier wrote:

It seems that some previous folding step may already have expended the absent upper into the length, blurring the information here for cases where the length is not a compile time constant:

```
subroutine test(charr)
  character(*) :: charr(5)
  print *, is_contiguous(charr(:)(1:))
end subroutine
```
Folds to `is_contiguous(charr(::1_8)(1_8:int(charr%len,kind=8)))` while it could be folded to true.

However, folding this may not be required by the standard, so this may be fine.

I do not find the standard very clear regarding the appearance of IS_CONTIGUOUS in constant expressions. As I understand it, it falls into the 10.1.12 (6) case since IS_CONTIGUOUS is an inquiry function. I am not sure how to read _"a variable whose properties inquired about are not assumed, deferred, or defined by an expression that is not a constant expression"_ when the "property" is the contiguity.

https://github.com/llvm/llvm-project/pull/115970


More information about the flang-commits mailing list