[flang] Simplify RaggedArrayHeader and make it plain C struct
authorValentin Clement <clementval@gmail.com>
Thu, 9 Dec 2021 21:27:49 +0000 (22:27 +0100)
committerValentin Clement <clementval@gmail.com>
Thu, 9 Dec 2021 21:28:06 +0000 (22:28 +0100)
- Join indirection and rank into a single value `flags`
- Make the struct a plain C struct.

Reviewed By: schweitz

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

flang/include/flang/Runtime/ragged.h
flang/lib/Optimizer/Builder/FIRBuilder.cpp
flang/lib/Optimizer/Builder/Runtime/Ragged.cpp
flang/runtime/ragged.cpp
flang/unittests/Runtime/Ragged.cpp

index ddd0622..e4b5838 100644 (file)
@@ -16,21 +16,17 @@ 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 boolean value to indicate if the header points to
+// 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 in an integer value. The rank is the length of the extents
-// vector accessed through `extentPointer`. The `bufferPointer` is overloaded
+// 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; }
+  std::uint64_t flags;
+  void *bufferPointer;
+  std::int64_t *extentPointer;
 };
 
 RaggedArrayHeader *RaggedArrayAllocate(
index 1a4f6c1..28a3816 100644 (file)
@@ -597,12 +597,10 @@ fir::factory::createExtents(fir::FirOpBuilder &builder, mlir::Location loc,
 
 mlir::TupleType
 fir::factory::getRaggedArrayHeaderType(fir::FirOpBuilder &builder) {
-  mlir::IntegerType i1Ty = builder.getIntegerType(1);
-  mlir::IntegerType i8Ty = builder.getIntegerType(8);
   mlir::IntegerType i64Ty = builder.getIntegerType(64);
   auto arrTy = fir::SequenceType::get(builder.getIntegerType(8), 1);
   auto buffTy = fir::HeapType::get(arrTy);
   auto extTy = fir::SequenceType::get(i64Ty, 1);
   auto shTy = fir::HeapType::get(extTy);
-  return mlir::TupleType::get(builder.getContext(), {i1Ty, i8Ty, buffTy, shTy});
+  return mlir::TupleType::get(builder.getContext(), {i64Ty, buffTy, shTy});
 }
index 5df8382..bdbbb78 100644 (file)
@@ -30,10 +30,10 @@ void fir::runtime::genRaggedArrayAllocate(mlir::Location loc,
   auto extentTy = fir::SequenceType::get(shape, i64Ty);
   auto refTy = fir::ReferenceType::get(i64Ty);
   // Position of the bufferPointer in the header struct.
-  auto two = builder.createIntegerConstant(loc, i32Ty, 2);
+  auto one = builder.createIntegerConstant(loc, i32Ty, 1);
   auto eleTy = fir::unwrapSequenceType(fir::unwrapRefType(header.getType()));
   auto ptrTy = builder.getRefType(eleTy.cast<mlir::TupleType>().getType(1));
-  auto ptr = builder.create<fir::CoordinateOp>(loc, ptrTy, header, two);
+  auto ptr = builder.create<fir::CoordinateOp>(loc, ptrTy, header, one);
   auto heap = builder.create<fir::LoadOp>(loc, ptr);
   auto cmp = builder.genIsNull(loc, heap);
   builder.genIfThen(loc, cmp)
index 7923359..855aa02 100644 (file)
 
 namespace Fortran::runtime {
 
+inline bool isIndirection(const RaggedArrayHeader *const header) {
+  return header->flags & 1;
+}
+
+inline std::size_t rank(const RaggedArrayHeader *const header) {
+  return header->flags >> 1;
+}
+
 RaggedArrayHeader *RaggedArrayAllocate(RaggedArrayHeader *header, bool isHeader,
     std::int64_t rank, std::int64_t elementSize, std::int64_t *extentVector) {
   if (header && rank) {
@@ -21,11 +29,10 @@ RaggedArrayHeader *RaggedArrayAllocate(RaggedArrayHeader *header, bool isHeader,
         return nullptr;
       }
     }
-    header->indirection = isHeader;
-    header->rank = rank;
+    header->flags = (rank << 1) | isHeader;
     header->extentPointer = extentVector;
     if (isHeader) {
-      header->bufferPointer = std::malloc(sizeof(RaggedArrayHeader) * size);
+      header->bufferPointer = std::calloc(sizeof(RaggedArrayHeader), size);
     } else {
       header->bufferPointer =
           static_cast<void *>(std::calloc(elementSize, size));
@@ -39,8 +46,8 @@ RaggedArrayHeader *RaggedArrayAllocate(RaggedArrayHeader *header, bool isHeader,
 // Deallocate a ragged array from the heap.
 void RaggedArrayDeallocate(RaggedArrayHeader *raggedArrayHeader) {
   if (raggedArrayHeader) {
-    if (std::size_t end{raggedArrayHeader->getRank()}) {
-      if (raggedArrayHeader->isIndirection()) {
+    if (std::size_t end{rank(raggedArrayHeader)}) {
+      if (isIndirection(raggedArrayHeader)) {
         std::size_t linearExtent{1u};
         for (std::size_t counter{0u}; counter < end && linearExtent > 0;
              ++counter) {
@@ -53,8 +60,7 @@ void RaggedArrayDeallocate(RaggedArrayHeader *raggedArrayHeader) {
       }
       std::free(raggedArrayHeader->bufferPointer);
       std::free(raggedArrayHeader->extentPointer);
-      raggedArrayHeader->indirection = false;
-      raggedArrayHeader->rank = 0u;
+      raggedArrayHeader->flags = 0u;
     }
   }
 }
index 002dba1..4b261b1 100644 (file)
@@ -24,10 +24,9 @@ TEST(Ragged, RaggedArrayAllocateDeallocateTest) {
   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());
+  EXPECT_EQ(rank, ret->flags >> 1);
+  EXPECT_FALSE(ret->flags & 1);
 
   _FortranARaggedArrayDeallocate(ret);
-  EXPECT_EQ(0u, ret->getRank());
-  EXPECT_FALSE(ret->isIndirection());
+  EXPECT_EQ(0u, ret->flags);
 }