diff --git a/flang/include/flang/Runtime/ragged.h b/flang/include/flang/Runtime/ragged.h --- a/flang/include/flang/Runtime/ragged.h +++ b/flang/include/flang/Runtime/ragged.h @@ -16,21 +16,17 @@ // 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( diff --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp --- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp +++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp @@ -597,12 +597,10 @@ 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}); } diff --git a/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp b/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp --- a/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Ragged.cpp @@ -30,10 +30,10 @@ 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().getType(1)); - auto ptr = builder.create(loc, ptrTy, header, two); + auto ptr = builder.create(loc, ptrTy, header, one); auto heap = builder.create(loc, ptr); auto cmp = builder.genIsNull(loc, heap); builder.genIfThen(loc, cmp) diff --git a/flang/runtime/ragged.cpp b/flang/runtime/ragged.cpp --- a/flang/runtime/ragged.cpp +++ b/flang/runtime/ragged.cpp @@ -11,6 +11,14 @@ 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 @@ 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(std::calloc(elementSize, size)); @@ -39,8 +46,8 @@ // 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 @@ } std::free(raggedArrayHeader->bufferPointer); std::free(raggedArrayHeader->extentPointer); - raggedArrayHeader->indirection = false; - raggedArrayHeader->rank = 0u; + raggedArrayHeader->flags = 0u; } } } diff --git a/flang/unittests/Runtime/Ragged.cpp b/flang/unittests/Runtime/Ragged.cpp --- a/flang/unittests/Runtime/Ragged.cpp +++ b/flang/unittests/Runtime/Ragged.cpp @@ -24,10 +24,9 @@ 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); }