Skip to content

[WIP] Unrolled Select Optimization #166

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions include/ctll/list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ template <typename Front, typename List> struct list_pop_pair {
constexpr list_pop_pair() = default;
};

template <typename A, typename B, typename C> struct list_pop_triple {
A front{};
B tail{};
C other{};
constexpr list_pop_triple() = default;
};

template <typename Head, typename... As, typename T = _nothing> constexpr auto pop_and_get_front(list<Head, As...>, T = T()) noexcept -> list_pop_pair<Head, list<As...>> { return {}; }
template <typename T = _nothing> constexpr auto pop_and_get_front(empty_list, T = T()) noexcept -> list_pop_pair<T, empty_list> { return {}; }

Expand Down
82 changes: 62 additions & 20 deletions include/ctre/evaluation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "return_type.hpp"
#include "find_captures.hpp"
#include "first.hpp"
#include "pattern_length.hpp"
#include <iterator>

// remove me when MSVC fix the constexpr bug
Expand Down Expand Up @@ -286,6 +287,37 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
return evaluate(begin, current, end, f, captures, ctll::list<Tail...>());
}

//check if unrollable
template<typename Iterator, typename R, typename... Content, typename... Tail>
constexpr auto may_unroll(ctll::list<sequence<Content...>, Tail...>, R) {
return may_unroll<Iterator>(ctll::list<Content..., Tail...>{}, R{});
}

template<typename Iterator, typename R, typename A, typename... Content, typename... Tail>
constexpr auto may_unroll(ctll::list<select<A, Content...>, Tail...>, R) {
constexpr auto length = ctre::pattern_length<Iterator>(sequence<select<Content...>, Tail...>{}, R{});
if constexpr (atomic_pattern_length(length) && !collides(calculate_first(sequence<A,Tail...>{}), calculate_first(sequence<select<Content...>, Tail...>{}))) {
if constexpr (sizeof...(Content) == 1) {
if constexpr (sizeof...(Tail))
return ctll::list_pop_triple<star<sequence<A,Tail...>>, sequence<Content..., Tail...>, ::std::true_type>{};
else
return ctll::list_pop_triple<star<A>, sequence<Content...>, ::std::true_type>{};
} else {
if constexpr (sizeof...(Tail))
return ctll::list_pop_triple<star<sequence<A,Tail...>>, sequence<select<Content...>, Tail...>, ::std::true_type>{};
else
return ctll::list_pop_triple<star<A>, select<Content...>, ::std::true_type>{};
}
} else {
return ctll::list_pop_triple<ctll::_nothing, ctll::_nothing, ::std::false_type>{};
}
}

template<typename Iterator, typename R, typename T>
constexpr auto may_unroll(T, R) {
return ctll::list_pop_triple<ctll::_nothing, ctll::_nothing, ::std::false_type>{};
}

// lazy repeat
template <typename R, typename Iterator, typename EndIterator, size_t A, size_t B, typename... Content, typename... Tail>
constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, const EndIterator end, [[maybe_unused]] const flags & f, R captures, ctll::list<lazy_repeat<A,B,Content...>, Tail...>) noexcept {
Expand Down Expand Up @@ -409,30 +441,40 @@ constexpr CTRE_FORCE_INLINE R evaluate(const Iterator begin, Iterator current, c
}

#ifndef CTRE_DISABLE_GREEDY_OPT
if constexpr (!collides(calculate_first(Content{}...), calculate_first(Tail{}...))) {
using unroll_t = decltype(may_unroll<Iterator>(ctll::list<Content...>{}, R{}));
if constexpr (B == 0 && unroll_t{}.other) {
if constexpr (A > 0) {
return evaluate(begin, current, end, f, captures, ctll::list<repeat<A,A,Content...>,star<decltype(unroll_t{}.front)>, star<decltype(unroll_t{}.tail), star<decltype(unroll_t{}.front)>>, Tail...>{});
} else {
return evaluate(begin, current, end, f, captures, ctll::list<star<decltype(unroll_t{}.front)>, star<decltype(unroll_t{}.tail), star<decltype(unroll_t{}.front)>>, Tail...>{});
}
} else if constexpr (!collides(calculate_first(Content{}...), calculate_first(Tail{}...))) {
return evaluate(begin, current, end, f, captures, ctll::list<possessive_repeat<A,B,Content...>, Tail...>());
}
} else {
#endif
// A..B
size_t i{0};
while (less_than<A>(i)) {
auto inner_result = evaluate(begin, current, end, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());
if (!inner_result) return not_matched;
captures = inner_result.unmatch();
current = inner_result.get_end_position();
++i;
}

// A..B
size_t i{ 0 };
while (less_than<A>(i)) {
auto inner_result = evaluate(begin, current, end, not_empty_match(f), captures, ctll::list<Content..., end_cycle_mark>());

if (!inner_result) return not_matched;

captures = inner_result.unmatch();
current = inner_result.get_end_position();

++i;
}

#ifdef CTRE_MSVC_GREEDY_WORKAROUND
R result;
evaluate_recursive(result, i, begin, current, end, f, captures, stack);
return result;
R result;
evaluate_recursive(result, i, begin, current, end, f, captures, stack);
return result;
#else
return evaluate_recursive(i, begin, current, end, f, captures, stack);
return evaluate_recursive(i, begin, current, end, f, captures, stack);
#endif
#ifndef CTRE_DISABLE_GREEDY_OPT
}
#endif

}
Expand Down
30 changes: 18 additions & 12 deletions include/ctre/first.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,18 +382,6 @@ template <size_t Capacity> class point_set {
};
point points[Capacity+1]{};
size_t used{0};
constexpr point * begin() {
return points;
}
constexpr point * begin() const {
return points;
}
constexpr point * end() {
return points + used;
}
constexpr point * end() const {
return points + used;
}
constexpr point * lower_bound(point obj) {
auto first = begin();
auto last = end();
Expand Down Expand Up @@ -444,6 +432,24 @@ template <size_t Capacity> class point_set {
insert_point(low, high);
//insert_point(high, low);
}
constexpr point* begin() {
return points;
}
constexpr point* begin() const {
return points;
}
constexpr point* end() {
return points + used;
}
constexpr point* end() const {
return points + used;
}
constexpr size_t size() {
return used;
}
constexpr size_t size() const {
return used;
}
constexpr bool check(int64_t low, int64_t high) {
for (auto r: *this) {
if (r.low <= low && low <= r.high) {
Expand Down
Loading