[flang-commits] [flang] 6116ff2 - [flang][runtime] Add ragged array runtime functions

Valentin Clement via flang-commits flang-commits at lists.llvm.org
Tue Dec 7 12:22:43 PST 2021


Author: Valentin Clement
Date: 2021-12-07T21:22:34+01:00
New Revision: 6116ff297f52c32fbe617c5dcea33c54c2c274ee

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

LOG: [flang][runtime] Add ragged array runtime functions

This patch adds the runtime function to allocate and
deallocate ragged arrays.

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: klausler

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

Co-authored-by: Eric Schweitz <eschweitz at nvidia.com>

Added: 
    flang/include/flang/Runtime/ragged.h
    flang/runtime/ragged.cpp
    flang/unittests/Runtime/Ragged.cpp

Modified: 
    flang/runtime/CMakeLists.txt
    flang/unittests/Runtime/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Runtime/ragged.h b/flang/include/flang/Runtime/ragged.h
new file mode 100644
index 0000000000000..03980f9a7ad09
--- /dev/null
+++ b/flang/include/flang/Runtime/ragged.h
@@ -0,0 +1,69 @@
+//===-- Runtime/ragged.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FORTRAN_RUNTIME_RAGGED_H_
+#define FORTRAN_RUNTIME_RAGGED_H_
+
+#include "flang/Runtime/entry-names.h"
+#include <cstdint>
+
+namespace Fortran::runtime {
+
+// A ragged array header block.
+// The header block is used to create the "array of arrays" ragged data
+// structure. It contains a pair in `flags` to indicate if the header points to
+// an array of headers (isIndirection) or data elements and the rank of the
+// pointed-to array. The rank is the length of the extents vector accessed
+// through `extentPointer`. The `bufferPointer` is overloaded and is null,
+// points to an array of headers (isIndirection), or data.
+// By default, a header is set to zero, which is its unused state.
+// The layout of a ragged buffer header is mirrored in the compiler.
+struct RaggedArrayHeader {
+  bool indirection{false};
+  std::uint8_t rank;
+  void *bufferPointer{nullptr};
+  std::int64_t *extentPointer{nullptr};
+
+  bool isIndirection() { return indirection; }
+  std::uint8_t getRank() { return rank; }
+};
+
+RaggedArrayHeader *RaggedArrayAllocate(
+    RaggedArrayHeader *, bool, std::int64_t, std::int64_t, std::int64_t *);
+
+void RaggedArrayDeallocate(RaggedArrayHeader *);
+
+extern "C" {
+
+// For more on ragged arrays see https://en.wikipedia.org/wiki/Jagged_array. The
+// Flang compiler allocates ragged arrays as a generalization for
+// non-rectangular array temporaries. Ragged arrays can be allocated recursively
+// and on demand. Structurally, each leaf is an optional rectangular array of
+// elements. The shape of each leaf is independent and may be computed on
+// demand. Each branch node is an optional, possibly sparse rectangular array of
+// headers. The shape of each branch is independent and may be computed on
+// demand. Ragged arrays preserve a correspondence between a multidimensional
+// iteration space and array access vectors, which is helpful for dependence
+// analysis.
+
+// Runtime helper for allocation of ragged array buffers.
+// A pointer to the header block to be allocated is given as header. The flag
+// isHeader indicates if a block of headers or data is to be allocated. A
+// non-negative rank indicates the length of the extentVector, which is a list
+// of non-negative extents. elementSize is the size of a data element in the
+// rectangular space defined by the extentVector.
+void *RTNAME(RaggedArrayAllocate)(void *header, bool isHeader,
+    std::int64_t rank, std::int64_t elementSize, std::int64_t *extentVector);
+
+// Runtime helper for deallocation of ragged array buffers. The root header of
+// the ragged array structure is passed to deallocate the entire ragged array.
+void RTNAME(RaggedArrayDeallocate)(void *raggedArrayHeader);
+
+} // extern "C"
+} // namespace Fortran::runtime
+#endif // FORTRAN_RUNTIME_RAGGED_H_

diff  --git a/flang/runtime/CMakeLists.txt b/flang/runtime/CMakeLists.txt
index 8b3a7a96cae13..2c0a1b4ed4c29 100644
--- a/flang/runtime/CMakeLists.txt
+++ b/flang/runtime/CMakeLists.txt
@@ -63,6 +63,7 @@ add_flang_library(FortranRuntime
   misc-intrinsic.cpp
   namelist.cpp
   numeric.cpp
+  ragged.cpp
   random.cpp
   reduction.cpp
   pointer.cpp

diff  --git a/flang/runtime/ragged.cpp b/flang/runtime/ragged.cpp
new file mode 100644
index 0000000000000..79233595f8daf
--- /dev/null
+++ b/flang/runtime/ragged.cpp
@@ -0,0 +1,74 @@
+//===-- runtime/ragged.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Runtime/ragged.h"
+#include <cstdlib>
+
+namespace Fortran::runtime {
+
+RaggedArrayHeader *RaggedArrayAllocate(RaggedArrayHeader *header, bool isHeader,
+    std::int64_t rank, std::int64_t elementSize, std::int64_t *extentVector) {
+  if (header && rank) {
+    std::int64_t size{1};
+    for (std::int64_t counter{0}; counter < rank; ++counter) {
+      size *= extentVector[counter];
+      if (size <= 0) {
+        return nullptr;
+      }
+    }
+    header->indirection = isHeader;
+    header->rank = rank;
+    header->extentPointer = extentVector;
+    if (isHeader) {
+      header->bufferPointer = std::malloc(sizeof(RaggedArrayHeader) * size);
+    } else {
+      header->bufferPointer =
+          static_cast<void *>(std::calloc(elementSize, size));
+    }
+    return header;
+  } else {
+    return nullptr;
+  }
+}
+
+// Deallocate a ragged array from the heap.
+void RaggedArrayDeallocate(RaggedArrayHeader *raggedArrayHeader) {
+  if (raggedArrayHeader) {
+    if (std::size_t end{raggedArrayHeader->getRank()}) {
+      if (raggedArrayHeader->isIndirection()) {
+        std::size_t linearExtent{1u};
+        for (std::size_t counter{0u}; counter < end && linearExtent > 0;
+             ++counter) {
+          linearExtent *= raggedArrayHeader->extentPointer[counter];
+        }
+        for (std::size_t counter{0u}; counter < linearExtent; ++counter) {
+          RaggedArrayDeallocate(&static_cast<RaggedArrayHeader *>(
+              raggedArrayHeader->bufferPointer)[counter]);
+        }
+      }
+      std::free(raggedArrayHeader->bufferPointer);
+      std::free(raggedArrayHeader->extentPointer);
+      raggedArrayHeader->indirection = false;
+      raggedArrayHeader->rank = 0u;
+    }
+  }
+}
+
+extern "C" {
+void *RTNAME(RaggedArrayAllocate)(void *header, bool isHeader,
+    std::int64_t rank, std::int64_t elementSize, std::int64_t *extentVector) {
+  auto *result = RaggedArrayAllocate(static_cast<RaggedArrayHeader *>(header),
+      isHeader, rank, elementSize, extentVector);
+  return static_cast<void *>(result);
+}
+
+void RTNAME(RaggedArrayDeallocate)(void *raggedArrayHeader) {
+  RaggedArrayDeallocate(static_cast<RaggedArrayHeader *>(raggedArrayHeader));
+}
+} // extern "C"
+} // namespace Fortran::runtime

diff  --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt
index 1067348ec31dc..5985adf391850 100644
--- a/flang/unittests/Runtime/CMakeLists.txt
+++ b/flang/unittests/Runtime/CMakeLists.txt
@@ -11,6 +11,7 @@ add_flang_unittest(FlangRuntimeTests
   Namelist.cpp
   Numeric.cpp
   NumericalFormatTest.cpp
+  Ragged.cpp
   Random.cpp
   Reduction.cpp
   RuntimeCrashTest.cpp

diff  --git a/flang/unittests/Runtime/Ragged.cpp b/flang/unittests/Runtime/Ragged.cpp
new file mode 100644
index 0000000000000..002dba1a6cf5e
--- /dev/null
+++ b/flang/unittests/Runtime/Ragged.cpp
@@ -0,0 +1,33 @@
+//===-- flang/unittests/Runtime/Ragged.cpp ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Runtime/ragged.h"
+#include "gtest/gtest.h"
+
+using namespace Fortran::runtime;
+
+TEST(Ragged, RaggedArrayAllocateDeallocateTest) {
+  struct RaggedArrayHeader header;
+  unsigned rank = 2;
+  int64_t *extents = new int64_t[2];
+  extents[0] = 10;
+  extents[1] = 100;
+  RaggedArrayHeader *ret = (RaggedArrayHeader *)_FortranARaggedArrayAllocate(
+      &header, false, rank, 32, extents);
+  EXPECT_TRUE(ret != nullptr);
+  EXPECT_TRUE(ret->bufferPointer != nullptr);
+  EXPECT_EQ(extents, ret->extentPointer);
+  EXPECT_EQ(10, ret->extentPointer[0]);
+  EXPECT_EQ(100, ret->extentPointer[1]);
+  EXPECT_EQ(rank, ret->getRank());
+  EXPECT_FALSE(ret->isIndirection());
+
+  _FortranARaggedArrayDeallocate(ret);
+  EXPECT_EQ(0u, ret->getRank());
+  EXPECT_FALSE(ret->isIndirection());
+}


        


More information about the flang-commits mailing list