-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[flang] implement split
for fortran 2023
#161484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -570,6 +570,35 @@ static RT_API_ATTRS void MaxMin(Descriptor &accumulator, const Descriptor &x, | |
} | ||
} | ||
|
||
template <typename CHAR> | ||
inline RT_API_ATTRS std::size_t Split(const CHAR *x, std::size_t xLen, | ||
const CHAR *set, std::size_t setLen, std::size_t pos, bool back, | ||
const char *sourceFile, int sourceLine) { | ||
Terminator terminator{sourceFile, sourceLine}; | ||
|
||
if (!back) { | ||
RUNTIME_CHECK(terminator, pos <= xLen); | ||
for (std::size_t i{pos + 1}; i <= xLen; ++i) { | ||
for (std::size_t j{0}; j < setLen; ++j) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are O(n^2) implementations. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it has the same time complexity as the fallback implementations for scan/verify. |
||
if (x[i - 1] == set[j]) { | ||
return i; | ||
} | ||
} | ||
} | ||
return xLen + 1; | ||
} else { | ||
RUNTIME_CHECK(terminator, pos >= 1 && pos <= xLen + 1); | ||
for (std::size_t i{pos - 1}; i != 0; --i) { | ||
for (std::size_t j{0}; j < setLen; ++j) { | ||
if (x[i - 1] == set[j]) { | ||
return i; | ||
} | ||
} | ||
} | ||
return 0; | ||
} | ||
} | ||
|
||
extern "C" { | ||
RT_EXT_API_GROUP_BEGIN | ||
|
||
|
@@ -917,6 +946,24 @@ void RTDEF(CharacterMin)(Descriptor &accumulator, const Descriptor &x, | |
MaxMin<true>(accumulator, x, sourceFile, sourceLine); | ||
} | ||
|
||
std::size_t RTDEF(Split1)(const char *x, std::size_t xLen, const char *set, | ||
std::size_t setLen, std::size_t pos, bool back, const char *sourceFile, | ||
int sourceLine) { | ||
return Split<char>(x, xLen, set, setLen, pos, back, sourceFile, sourceLine); | ||
} | ||
std::size_t RTDEF(Split2)(const char16_t *x, std::size_t xLen, | ||
const char16_t *set, std::size_t setLen, std::size_t pos, bool back, | ||
const char *sourceFile, int sourceLine) { | ||
return Split<char16_t>( | ||
x, xLen, set, setLen, pos, back, sourceFile, sourceLine); | ||
} | ||
std::size_t RTDEF(Split4)(const char32_t *x, std::size_t xLen, | ||
const char32_t *set, std::size_t setLen, std::size_t pos, bool back, | ||
const char *sourceFile, int sourceLine) { | ||
return Split<char32_t>( | ||
x, xLen, set, setLen, pos, back, sourceFile, sourceLine); | ||
} | ||
|
||
RT_EXT_API_GROUP_END | ||
} | ||
} // namespace Fortran::runtime |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s | ||
tblah marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
! CHECK-LABEL: func @_QPsplit_test1( | ||
! CHECK-SAME: %[[s1:[^:]+]]: !fir.boxchar<1>{{.*}}, %[[s2:[^:]+]]: !fir.boxchar<1>{{.*}}, %[[p:[^:]+]]: !fir.ref<i32>{{.*}}) | ||
subroutine split_test1(s1, s2, p) | ||
character(*) :: s1, s2 | ||
integer :: p | ||
! CHECK: %[[c1:.*]]:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) | ||
! CHECK: %[[c2:.*]]:2 = fir.unboxchar %arg1 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) | ||
! CHECK: %[[pos:.*]] = fir.load %arg2 : !fir.ref<i32> | ||
! CHECK: %false = arith.constant false | ||
! CHECK: %[[c1base:.*]] = fir.convert %[[c1]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> | ||
! CHECK: %[[c1len:.*]] = fir.convert %[[c1]]#1 : (index) -> i64 | ||
! CHECK: %[[c2base:.*]] = fir.convert %[[c2]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> | ||
! CHECK: %[[c2len:.*]] = fir.convert %[[c2]]#1 : (index) -> i64 | ||
! CHECK: %[[pos1:.*]] = fir.convert %[[pos]] : (i32) -> i64 | ||
! CHECK: %[[pos2:.*]] = fir.call @_FortranASplit1(%[[c1base]], %[[c1len]], %[[c2base]], %[[c2len]], %[[pos1]], %false, {{.*}}) {{.*}}: (!fir.ref<i8>, i64, !fir.ref<i8>, i64, i64, i1, !fir.ref<i8>, i32) -> i64 | ||
! CHECK: %[[pos3:.*]] = fir.convert %[[pos2]] : (i64) -> i32 | ||
! CHECK: fir.store %[[pos3]] to %[[p]] : !fir.ref<i32> | ||
! CHECK: return | ||
call split(s1, s2, p) | ||
end subroutine split_test1 | ||
|
||
! CHECK-LABEL: func @_QPsplit_test2( | ||
! CHECK-SAME: %[[s1:[^:]+]]: !fir.boxchar<1>{{.*}}, %[[s2:[^:]+]]: !fir.boxchar<1>{{.*}}, %[[p:[^:]+]]: !fir.ref<i32>{{.*}}) | ||
subroutine split_test2(s1, s2, p) | ||
character(*) :: s1, s2 | ||
integer :: p | ||
! CHECK: %[[c1:.*]]:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) | ||
! CHECK: %[[c2:.*]]:2 = fir.unboxchar %arg1 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) | ||
! CHECK: %true = arith.constant true | ||
! CHECK: %[[pos:.*]] = fir.load %arg2 : !fir.ref<i32> | ||
! CHECK: %[[c1base:.*]] = fir.convert %[[c1]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> | ||
! CHECK: %[[c1len:.*]] = fir.convert %[[c1]]#1 : (index) -> i64 | ||
! CHECK: %[[c2base:.*]] = fir.convert %[[c2]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> | ||
! CHECK: %[[c2len:.*]] = fir.convert %[[c2]]#1 : (index) -> i64 | ||
! CHECK: %[[pos1:.*]] = fir.convert %[[pos]] : (i32) -> i64 | ||
! CHECK: %[[pos2:.*]] = fir.call @_FortranASplit1(%[[c1base]], %[[c1len]], %[[c2base]], %[[c2len]], %[[pos1]], %true, {{.*}}) {{.*}}: (!fir.ref<i8>, i64, !fir.ref<i8>, i64, i64, i1, !fir.ref<i8>, i32) -> i64 | ||
! CHECK: %[[pos3:.*]] = fir.convert %[[pos2]] : (i64) -> i32 | ||
! CHECK: fir.store %[[pos3]] to %[[p]] : !fir.ref<i32> | ||
! CHECK: return | ||
call split(s1, s2, p, .true.) | ||
end subroutine split_test2 | ||
|
||
! CHECK-LABEL: func @_QPsplit_test3( | ||
! CHECK-SAME: %[[s1:[^:]+]]: !fir.boxchar<1>{{.*}}, %[[s2:[^:]+]]: !fir.boxchar<1>{{.*}}, %[[p:[^:]+]]: !fir.ref<i32>{{.*}}, %[[back:[^:]+]]: !fir.ref<!fir.logical<4>>{{.*}}) | ||
subroutine split_test3(s1, s2, p, back) | ||
character(*) :: s1, s2 | ||
integer :: p | ||
logical, optional :: back | ||
! CHECK: %[[c1:.*]]:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) | ||
! CHECK: %[[c2:.*]]:2 = fir.unboxchar %arg1 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) | ||
! CHECK: %[[is_present:.*]] = fir.is_present %arg3 : (!fir.ref<!fir.logical<4>>) -> i1 | ||
! CHECK: %[[back_unwrap:.*]] = fir.if %[[is_present]] -> (!fir.logical<4>) { | ||
! CHECK: {{.*}} = fir.load %arg3 : !fir.ref<!fir.logical<4>> | ||
! CHECK: fir.result {{.*}} : !fir.logical<4> | ||
! CHECK: } else { | ||
! CHECK: %false = arith.constant false | ||
! CHECK: {{.*}} = fir.convert %false : (i1) -> !fir.logical<4> | ||
! CHECK: fir.result {{.*}} : !fir.logical<4> | ||
! CHECK: } | ||
! CHECK: %[[pos:.*]] = fir.load %arg2 : !fir.ref<i32> | ||
! CHECK: %[[c1base:.*]] = fir.convert %[[c1]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> | ||
! CHECK: %[[c1len:.*]] = fir.convert %[[c1]]#1 : (index) -> i64 | ||
! CHECK: %[[c2base:.*]] = fir.convert %[[c2]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<i8> | ||
! CHECK: %[[c2len:.*]] = fir.convert %[[c2]]#1 : (index) -> i64 | ||
! CHECK: %[[pos1:.*]] = fir.convert %[[pos]] : (i32) -> i64 | ||
! CHECK: %[[back_convert:.*]] = fir.convert %[[back_unwrap]] : (!fir.logical<4>) -> i1 | ||
! CHECK: %[[pos2:.*]] = fir.call @_FortranASplit1(%[[c1base]], %[[c1len]], %[[c2base]], %[[c2len]], %[[pos1]], %[[back_convert]], {{.*}}) {{.*}}: (!fir.ref<i8>, i64, !fir.ref<i8>, i64, i64, i1, !fir.ref<i8>, i32) -> i64 | ||
! CHECK: %[[pos3:.*]] = fir.convert %[[pos2]] : (i64) -> i32 | ||
! CHECK: fir.store %[[pos3]] to %[[p]] : !fir.ref<i32> | ||
! CHECK: return | ||
call split(s1, s2, p, back) | ||
end subroutine split_test3 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::int64_t
is the correct type to use for FortranINTEGER
argument values.