Skip to content

Commit

Permalink
[flang] Implement the runtime portion of the CSHIFT intrinsic
Browse files Browse the repository at this point in the history
This change fixes a bug in  the runtime portion of the CSHIFT intrinsic
that happens when the value of the SHIFT argument is negative.

Differential Revision: https://reviews.llvm.org/D106292
  • Loading branch information
psteinfeld committed Jul 21, 2021
1 parent 8e6b31c commit 7898e7c
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 2 deletions.
7 changes: 5 additions & 2 deletions flang/runtime/transformational.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ static inline std::size_t AllocateResult(Descriptor &result,

extern "C" {

// CSHIFT of rank > 1
// CSHIFT where rank of ARRAY argument > 1
void RTNAME(Cshift)(Descriptor &result, const Descriptor &source,
const Descriptor &shift, int dim, const char *sourceFile, int line) {
Terminator terminator{sourceFile, line};
Expand Down Expand Up @@ -172,7 +172,7 @@ void RTNAME(Cshift)(Descriptor &result, const Descriptor &source,
}
}

// CSHIFT of vector
// CSHIFT where rank of ARRAY argument == 1
void RTNAME(CshiftVector)(Descriptor &result, const Descriptor &source,
std::int64_t shift, const char *sourceFile, int line) {
Terminator terminator{sourceFile, line};
Expand All @@ -184,6 +184,9 @@ void RTNAME(CshiftVector)(Descriptor &result, const Descriptor &source,
for (SubscriptValue j{0}; j < extent; ++j) {
SubscriptValue resultAt{1 + j};
SubscriptValue sourceAt{lb + (j + shift) % extent};
if (sourceAt < 0) {
sourceAt += extent;
}
CopyElement(result, &resultAt, source, &sourceAt, terminator);
}
}
Expand Down
33 changes: 33 additions & 0 deletions flang/unittests/RuntimeGTest/Transformational.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,39 @@ TEST(Transformational, Shifts) {
}
result.Destroy();

// VECTOR 1 3 5 2 4 6
auto vector{MakeArray<TypeCategory::Integer, 4>(
std::vector<int>{6}, std::vector<std::int32_t>{1, 2, 3, 4, 5, 6})};
vector->GetDimension(0).SetLowerBound(0);
StaticDescriptor<1, true> vectorDesc;
Descriptor &vectorResult{vectorDesc.descriptor()};

RTNAME(CshiftVector)(vectorResult, *vector, 2, __FILE__, __LINE__);
EXPECT_EQ(vectorResult.type(), array->type());
EXPECT_EQ(vectorResult.rank(), 1);
EXPECT_EQ(vectorResult.GetDimension(0).LowerBound(), 1);
EXPECT_EQ(vectorResult.GetDimension(0).Extent(), 6);
EXPECT_EQ(vectorResult.type(), (TypeCode{TypeCategory::Integer, 4}));
static std::int32_t cshiftExpect3[6]{3, 4, 5, 6, 1, 2};
for (int j{0}; j < 6; ++j) {
EXPECT_EQ(*vectorResult.ZeroBasedIndexedElement<std::int32_t>(j),
cshiftExpect3[j]);
}
vectorResult.Destroy();

RTNAME(CshiftVector)(vectorResult, *vector, -2, __FILE__, __LINE__);
EXPECT_EQ(vectorResult.type(), array->type());
EXPECT_EQ(vectorResult.rank(), 1);
EXPECT_EQ(vectorResult.GetDimension(0).LowerBound(), 1);
EXPECT_EQ(vectorResult.GetDimension(0).Extent(), 6);
EXPECT_EQ(vectorResult.type(), (TypeCode{TypeCategory::Integer, 4}));
static std::int32_t cshiftExpect4[6]{5, 6, 1, 2, 3, 4};
for (int j{0}; j < 6; ++j) {
EXPECT_EQ(*vectorResult.ZeroBasedIndexedElement<std::int32_t>(j),
cshiftExpect4[j]);
}
vectorResult.Destroy();

auto boundary{MakeArray<TypeCategory::Integer, 4>(
std::vector<int>{3}, std::vector<std::int32_t>{-1, -2, -3})};
boundary->GetDimension(0).SetLowerBound(9); // shouldn't matter
Expand Down

0 comments on commit 7898e7c

Please sign in to comment.