Skip to content

Commit 7898e7c

Browse files
committed
[flang] Implement the runtime portion of the CSHIFT intrinsic
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
1 parent 8e6b31c commit 7898e7c

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

flang/runtime/transformational.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ static inline std::size_t AllocateResult(Descriptor &result,
130130

131131
extern "C" {
132132

133-
// CSHIFT of rank > 1
133+
// CSHIFT where rank of ARRAY argument > 1
134134
void RTNAME(Cshift)(Descriptor &result, const Descriptor &source,
135135
const Descriptor &shift, int dim, const char *sourceFile, int line) {
136136
Terminator terminator{sourceFile, line};
@@ -172,7 +172,7 @@ void RTNAME(Cshift)(Descriptor &result, const Descriptor &source,
172172
}
173173
}
174174

175-
// CSHIFT of vector
175+
// CSHIFT where rank of ARRAY argument == 1
176176
void RTNAME(CshiftVector)(Descriptor &result, const Descriptor &source,
177177
std::int64_t shift, const char *sourceFile, int line) {
178178
Terminator terminator{sourceFile, line};
@@ -184,6 +184,9 @@ void RTNAME(CshiftVector)(Descriptor &result, const Descriptor &source,
184184
for (SubscriptValue j{0}; j < extent; ++j) {
185185
SubscriptValue resultAt{1 + j};
186186
SubscriptValue sourceAt{lb + (j + shift) % extent};
187+
if (sourceAt < 0) {
188+
sourceAt += extent;
189+
}
187190
CopyElement(result, &resultAt, source, &sourceAt, terminator);
188191
}
189192
}

flang/unittests/RuntimeGTest/Transformational.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,39 @@ TEST(Transformational, Shifts) {
6060
}
6161
result.Destroy();
6262

63+
// VECTOR 1 3 5 2 4 6
64+
auto vector{MakeArray<TypeCategory::Integer, 4>(
65+
std::vector<int>{6}, std::vector<std::int32_t>{1, 2, 3, 4, 5, 6})};
66+
vector->GetDimension(0).SetLowerBound(0);
67+
StaticDescriptor<1, true> vectorDesc;
68+
Descriptor &vectorResult{vectorDesc.descriptor()};
69+
70+
RTNAME(CshiftVector)(vectorResult, *vector, 2, __FILE__, __LINE__);
71+
EXPECT_EQ(vectorResult.type(), array->type());
72+
EXPECT_EQ(vectorResult.rank(), 1);
73+
EXPECT_EQ(vectorResult.GetDimension(0).LowerBound(), 1);
74+
EXPECT_EQ(vectorResult.GetDimension(0).Extent(), 6);
75+
EXPECT_EQ(vectorResult.type(), (TypeCode{TypeCategory::Integer, 4}));
76+
static std::int32_t cshiftExpect3[6]{3, 4, 5, 6, 1, 2};
77+
for (int j{0}; j < 6; ++j) {
78+
EXPECT_EQ(*vectorResult.ZeroBasedIndexedElement<std::int32_t>(j),
79+
cshiftExpect3[j]);
80+
}
81+
vectorResult.Destroy();
82+
83+
RTNAME(CshiftVector)(vectorResult, *vector, -2, __FILE__, __LINE__);
84+
EXPECT_EQ(vectorResult.type(), array->type());
85+
EXPECT_EQ(vectorResult.rank(), 1);
86+
EXPECT_EQ(vectorResult.GetDimension(0).LowerBound(), 1);
87+
EXPECT_EQ(vectorResult.GetDimension(0).Extent(), 6);
88+
EXPECT_EQ(vectorResult.type(), (TypeCode{TypeCategory::Integer, 4}));
89+
static std::int32_t cshiftExpect4[6]{5, 6, 1, 2, 3, 4};
90+
for (int j{0}; j < 6; ++j) {
91+
EXPECT_EQ(*vectorResult.ZeroBasedIndexedElement<std::int32_t>(j),
92+
cshiftExpect4[j]);
93+
}
94+
vectorResult.Destroy();
95+
6396
auto boundary{MakeArray<TypeCategory::Integer, 4>(
6497
std::vector<int>{3}, std::vector<std::int32_t>{-1, -2, -3})};
6598
boundary->GetDimension(0).SetLowerBound(9); // shouldn't matter

0 commit comments

Comments
 (0)