aboutsummaryrefslogtreecommitdiff
path: root/flang/unittests
diff options
context:
space:
mode:
authorjeanPerier <jperier@nvidia.com>2024-05-27 10:32:33 +0200
committerGitHub <noreply@github.com>2024-05-27 10:32:33 +0200
commit2b78c641525b7cea9dec8125b7f5cd06d7ce8fff (patch)
tree936a6c6a5dff62f508816a086973d38f9f132261 /flang/unittests
parent7429950d840b8fec3d9a48d00e612a3240c2be83 (diff)
downloadllvm-2b78c641525b7cea9dec8125b7f5cd06d7ce8fff.zip
llvm-2b78c641525b7cea9dec8125b7f5cd06d7ce8fff.tar.gz
llvm-2b78c641525b7cea9dec8125b7f5cd06d7ce8fff.tar.bz2
[flang] add API to copy and update descriptors for assumed ranks (#93305)
When passing assumed-rank around, the lower bounds, dynamic type and attribute must sometimes be updated to match the dummy attributes. See https://github.com/llvm/llvm-project/blob/main/flang/docs/AssumedRank.md#annex-1---descriptor-temporary-for-the-dummy-arguments for more details. Doing it inline would require generating many instructions and block CFG at the LLVM IR dialect level in codegen. Go for a simple runtime API instead. A matching fir.rebox_assumed_rank operation will be created and will allow for easier future optimizations when inlining is done in FIR.
Diffstat (limited to 'flang/unittests')
-rw-r--r--flang/unittests/Runtime/CMakeLists.txt1
-rw-r--r--flang/unittests/Runtime/Support.cpp58
2 files changed, 59 insertions, 0 deletions
diff --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt
index f7caaca..ed047b08 100644
--- a/flang/unittests/Runtime/CMakeLists.txt
+++ b/flang/unittests/Runtime/CMakeLists.txt
@@ -25,6 +25,7 @@ add_flang_unittest(FlangRuntimeTests
Reduction.cpp
RuntimeCrashTest.cpp
Stop.cpp
+ Support.cpp
Time.cpp
TemporaryStack.cpp
Transformational.cpp
diff --git a/flang/unittests/Runtime/Support.cpp b/flang/unittests/Runtime/Support.cpp
new file mode 100644
index 0000000..fa2a233
--- /dev/null
+++ b/flang/unittests/Runtime/Support.cpp
@@ -0,0 +1,58 @@
+//===-- flang/unittests/Runtime/Support.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/support.h"
+#include "gtest/gtest.h"
+#include "tools.h"
+#include "flang/Runtime/descriptor.h"
+
+using namespace Fortran::runtime;
+using Fortran::common::TypeCategory;
+TEST(CopyAndUpdateDescriptor, Basic) {
+ auto x{MakeArray<TypeCategory::Integer, 4>(
+ std::vector<int>{2, 3}, std::vector<std::int32_t>{0, 1, 2, 3, 4, 5})};
+ x->GetDimension(0).SetLowerBound(11);
+ x->GetDimension(1).SetLowerBound(12);
+
+ StaticDescriptor<2, false> statDesc;
+ Descriptor &result{statDesc.descriptor()};
+
+ RTNAME(CopyAndUpdateDescriptor)
+ (result, *x, nullptr, CFI_attribute_pointer, LowerBoundModifier::Preserve);
+ ASSERT_EQ(result.rank(), 2);
+ EXPECT_EQ(result.raw().base_addr, x->raw().base_addr);
+ EXPECT_TRUE(result.IsPointer());
+ EXPECT_EQ(result.GetDimension(0).Extent(), x->GetDimension(0).Extent());
+ EXPECT_EQ(
+ result.GetDimension(0).LowerBound(), x->GetDimension(0).LowerBound());
+ EXPECT_EQ(result.GetDimension(1).Extent(), x->GetDimension(1).Extent());
+ EXPECT_EQ(
+ result.GetDimension(1).LowerBound(), x->GetDimension(1).LowerBound());
+
+ RTNAME(CopyAndUpdateDescriptor)
+ (result, *x, nullptr, CFI_attribute_allocatable,
+ LowerBoundModifier::SetToZeroes);
+ ASSERT_EQ(result.rank(), 2);
+ EXPECT_EQ(result.raw().base_addr, x->raw().base_addr);
+ EXPECT_TRUE(result.IsAllocatable());
+ EXPECT_EQ(result.GetDimension(0).Extent(), x->GetDimension(0).Extent());
+ EXPECT_EQ(result.GetDimension(0).LowerBound(), 0);
+ EXPECT_EQ(result.GetDimension(1).Extent(), x->GetDimension(1).Extent());
+ EXPECT_EQ(result.GetDimension(1).LowerBound(), 0);
+
+ RTNAME(CopyAndUpdateDescriptor)
+ (result, *x, nullptr, CFI_attribute_other, LowerBoundModifier::SetToOnes);
+ ASSERT_EQ(result.rank(), 2);
+ EXPECT_EQ(result.raw().base_addr, x->raw().base_addr);
+ EXPECT_FALSE(result.IsAllocatable());
+ EXPECT_FALSE(result.IsPointer());
+ EXPECT_EQ(result.GetDimension(0).Extent(), x->GetDimension(0).Extent());
+ EXPECT_EQ(result.GetDimension(0).LowerBound(), 1);
+ EXPECT_EQ(result.GetDimension(1).Extent(), x->GetDimension(1).Extent());
+ EXPECT_EQ(result.GetDimension(1).LowerBound(), 1);
+}